// 退货
  @Test
  public void testStockOut() throws BusinessException, SQLException {
    Supplier supplier;
    List<Supplier> suppliers = SupplierDao.getSuppliers(mStaff, null, null);
    if (suppliers.isEmpty()) {
      throw new BusinessException(SupplierError.SUPPLIER_NOT_ADD);
    } else {
      supplier = suppliers.get(0);
    }
    Department deptOut;
    List<Department> depts = DepartmentDao.getDepartments4Inventory(mStaff);
    if (depts.isEmpty()) {
      throw new BusinessException(DeptError.DEPT_NOT_EXIST);
    } else {
      deptOut = depts.get(2);
    }

    //		Map<Object, Object> params = new HashMap<Object, Object>();
    //		params.put(SQLUtil.SQL_PARAMS_EXTRA, " AND M.restaurant_id = " + mStaff.getRestaurantId());
    List<Material> materials = MaterialDao.getByCond(mStaff, null);
    if (materials.isEmpty()) {
      throw new BusinessException(MaterialError.SELECT_NOT_ADD);
    }

    InsertBuilder builder =
        StockAction.InsertBuilder.newStockOut(
                mStaff.getRestaurantId(), DateUtil.parseDate("2013-09-28 12:12:12"), 300)
            .setOriStockId("asd12000")
            .setOperatorId((int) mStaff.getId())
            .setOperator(mStaff.getName())
            .setComment("good...")
            .setDeptOut(deptOut.getId())
            .setCateType(MaterialCate.Type.GOOD)
            .setSupplierId(supplier.getSupplierId())
            .addDetail(new StockActionDetail(materials.get(0).getId(), 1.5f, 12))
            .addDetail(new StockActionDetail(materials.get(2).getId(), 1.5f, 12));

    testInsert(builder);
  }
  private void testInsert(InsertBuilder builder) throws SQLException, BusinessException {

    // 添加一张入库存单

    final int stockActionId = StockActionDao.insertStockAction(mStaff, builder);

    StockAction expected = builder.build();
    // 根据不同类型获取供应商或部门
    if (builder.getSubType() == SubType.STOCK_IN) {
      Department deptIn = DepartmentDao.getById(mStaff, builder.getDeptIn().getId());
      Supplier supplier =
          SupplierDao.getSupplierById(mStaff, builder.getSupplier().getSupplierId());
      expected.setDeptIn(deptIn);
      expected.setSupplier(supplier);
    } else if (builder.getSubType() == SubType.STOCK_OUT) {
      Department deptOut = DepartmentDao.getById(mStaff, builder.getDeptOut().getId());
      Supplier supplier =
          SupplierDao.getSupplierById(mStaff, builder.getSupplier().getSupplierId());
      expected.setDeptOut(deptOut);
      expected.setSupplier(supplier);
    } else if (builder.getSubType() == SubType.STOCK_IN_TRANSFER
        || builder.getSubType() == SubType.STOCK_OUT_TRANSFER) {
      Department deptIn = DepartmentDao.getById(mStaff, builder.getDeptIn().getId());
      Department deptOut = DepartmentDao.getById(mStaff, builder.getDeptOut().getId());
      expected.setDeptIn(deptIn);
      expected.setDeptOut(deptOut);
    } else {
      Department deptIn = DepartmentDao.getById(mStaff, builder.getDeptIn().getId());
      expected.setDeptIn(deptIn);
    }
    expected.setId(stockActionId);

    StockAction actual = StockActionDao.getStockAndDetailById(mStaff, stockActionId);
    compare(expected, actual, true);

    // TODO 要修改的话解注释
    /*		InsertBuilder updatebuilder = StockAction.InsertBuilder.newStockIn(mTerminal.restaurantID, DateUtil.parseDate("2013-09-29 12:12:12"))
    		   .setOriStockId("aaa12000")
    		   .setOperatorId((int) mTerminal.pin).setOperator(mTerminal.owner)
    		   .setComment("good hting")
    		   .setDeptIn(actual.getDeptIn().getId())
    		   .setCateType(CateType.GOOD)
    		   .setSupplierId(actual.getSupplier().getSupplierId())
    		   .addDetail(new StockActionDetail(2, 30f, 90))
    			.addDetail(new StockActionDetail(4, 30f, 30));
    StockActionDao.updateStockAction(mTerminal, actual.getId(), updatebuilder);*/

    // 在审核时先获取之前的数据以作对比
    //		Map<Object, Object> param = new HashMap<Object, Object>();
    //		param.put(SQLUtil.SQL_PARAMS_EXTRA, " AND M.restaurant_id = " + mStaff.getRestaurantId());
    List<Material> beforeMaterials = MaterialDao.getByCond(mStaff, null);

    List<MaterialDept> beforeMaterialDepts =
        MaterialDeptDao.getMaterialDepts(
            mStaff, " AND restaurant_id = " + mStaff.getRestaurantId(), null);
    // 审核库存
    expected = actual;
    AuditBuilder uBuilder =
        StockAction.AuditBuilder.newStockActionAudit(expected.getId())
            .setApprover("兰戈")
            .setApproverId(12);
    // 做对比数据之用
    expected.setApprover("兰戈");
    expected.setApproverId(12);
    expected.setStatus(Status.AUDIT);
    /*		expected.setOriStockId("aaa12000");
    expected.setComment("good hting");
    expected.setOriStockIdDate(DateUtil.parseDate("2013-09-29 12:12:12"));*/

    // 审核
    StockActionDao.auditStockAction(mStaff, uBuilder);

    actual = StockActionDao.getStockAndDetailById(mStaff, uBuilder.getId());
    // 对比审核后期望与真实值
    compare(expected, actual, false);

    // 审核完成,与部门库存,商品原料库存对接
    for (StockActionDetail actualStockActionDetail : actual.getStockDetails()) {

      // 获取变化数量
      float deltaStock = actualStockActionDetail.getAmount();
      int index;
      if (actual.getSubType() == SubType.STOCK_IN) {
        MaterialDept afterMaterialDept =
            MaterialDeptDao.getMaterialDepts(
                    mStaff,
                    " AND material_id = "
                        + actualStockActionDetail.getMaterialId()
                        + " AND dept_id = "
                        + actual.getDeptIn().getId(),
                    null)
                .get(0);
        index = beforeMaterialDepts.indexOf(afterMaterialDept);
        if (index >= 0) {
          float deltaMaterialDeptStock =
              Math.abs(afterMaterialDept.getStock() - beforeMaterialDepts.get(index).getStock());
          Assert.assertEquals("deltaMaterialDeptStock", deltaStock, deltaMaterialDeptStock, 0.0001);
        } else {
          float deltaMaterialDeptStock = afterMaterialDept.getStock();
          Assert.assertEquals("deltaMaterialDeptStock", deltaStock, deltaMaterialDeptStock, 0.0001);
        }
        // 对比原料表的变化
        Material afterMaterial =
            MaterialDao.getById(mStaff, actualStockActionDetail.getMaterialId());
        index = beforeMaterials.indexOf(afterMaterial);
        if (index >= 0) {
          float deltaMaterialStock =
              afterMaterial.getStock() - beforeMaterials.get(index).getStock();
          Assert.assertEquals("deltaMaterialStock", deltaStock, deltaMaterialStock, 0.0001);
        } else {
          throw new BusinessException(MaterialError.MATERIAL_NOT_EXIST);
        }
      } else if (actual.getSubType() == SubType.SPILL
          || actual.getSubType() == SubType.DAMAGE
          || actual.getSubType() == SubType.USE_UP) {
        MaterialDept afterMaterialDept =
            MaterialDeptDao.getMaterialDepts(
                    mStaff,
                    " AND material_id = "
                        + actualStockActionDetail.getMaterialId()
                        + " AND dept_id = "
                        + actual.getDeptIn().getId(),
                    null)
                .get(0);
        index = beforeMaterialDepts.indexOf(afterMaterialDept);
        if (index >= 0) {
          float deltaMaterialDeptStock =
              Math.abs(afterMaterialDept.getStock() - beforeMaterialDepts.get(index).getStock());
          Assert.assertEquals("deltaMaterialDeptStock", deltaStock, deltaMaterialDeptStock, 0.0001);
        } else {
          throw new BusinessException(StockError.MATERIAL_DEPT_ADD);
        }
        // 对比材料表变化
        Material afterMaterial =
            MaterialDao.getById(mStaff, actualStockActionDetail.getMaterialId());
        index = beforeMaterials.indexOf(afterMaterial);
        if (index >= 0) {
          float deltaMaterialStock =
              Math.abs(afterMaterial.getStock() - beforeMaterials.get(index).getStock());
          Assert.assertEquals("deltaMaterialStock", deltaStock, deltaMaterialStock, 0.0001);
        } else {
          throw new BusinessException(MaterialError.MATERIAL_NOT_EXIST);
        }

      } else if (actual.getSubType() == SubType.STOCK_OUT) {
        MaterialDept afterMaterialDept =
            MaterialDeptDao.getMaterialDepts(
                    mStaff,
                    " AND material_id = "
                        + actualStockActionDetail.getMaterialId()
                        + " AND dept_id = "
                        + actual.getDeptOut().getId(),
                    null)
                .get(0);
        index = beforeMaterialDepts.indexOf(afterMaterialDept);
        if (index >= 0) {
          float deltaMaterialDeptStock =
              beforeMaterialDepts.get(index).getStock() - afterMaterialDept.getStock();
          Assert.assertEquals("deltaMaterialDeptStock", deltaStock, deltaMaterialDeptStock, 0.0001);
        } else {
          throw new BusinessException(StockError.MATERIAL_DEPT_ADD);
        }
        // 对比原料表的变化
        //				Map<Object, Object> afterParam = new HashMap<Object, Object>();
        //				afterParam.put(SQLUtil.SQL_PARAMS_EXTRA, " AND M.restaurant_id = " +
        // mStaff.getRestaurantId() + " AND M.material_id = " +
        // actualStockActionDetail.getMaterialId());
        Material afterMaterial =
            MaterialDao.getByCond(
                    mStaff,
                    new MaterialDao.ExtraCond().setId(actualStockActionDetail.getMaterialId()))
                .get(0);
        index = beforeMaterials.indexOf(afterMaterial);
        if (index >= 0) {
          float deltaMaterialStock =
              Math.abs(afterMaterial.getStock() - beforeMaterials.get(index).getStock());
          Assert.assertEquals("deltaMaterialStock", deltaStock, deltaMaterialStock, 0.0001);
        } else {
          throw new BusinessException(MaterialError.MATERIAL_NOT_EXIST);
        }
      } else if (actual.getSubType() == SubType.STOCK_IN_TRANSFER
          || actual.getSubType() == SubType.STOCK_OUT_TRANSFER) {
        MaterialDept afterMaterialDeptIn =
            MaterialDeptDao.getMaterialDepts(
                    mStaff,
                    " AND material_id = "
                        + actualStockActionDetail.getMaterialId()
                        + " AND dept_id = "
                        + actual.getDeptIn().getId(),
                    null)
                .get(0);
        MaterialDept afterMaterialDeptOut =
            MaterialDeptDao.getMaterialDepts(
                    mStaff,
                    " AND material_id = "
                        + actualStockActionDetail.getMaterialId()
                        + " AND dept_id = "
                        + actual.getDeptOut().getId(),
                    null)
                .get(0);
        int indexOut = beforeMaterialDepts.indexOf(afterMaterialDeptOut);
        if (indexOut >= 0) {
          float deltaMaterialDeptStock =
              Math.abs(
                  afterMaterialDeptOut.getStock() - beforeMaterialDepts.get(indexOut).getStock());
          Assert.assertEquals("deltaMaterialDeptStock", deltaStock, deltaMaterialDeptStock, 0.0001);
        } else {
          throw new BusinessException(StockError.MATERIAL_DEPT_ADD);
        }

        index = beforeMaterialDepts.indexOf(afterMaterialDeptIn);
        if (index >= 0) {
          float deltaMaterialDeptStock =
              Math.abs(afterMaterialDeptIn.getStock() - beforeMaterialDepts.get(index).getStock());
          Assert.assertEquals("deltaMaterialDeptStock", deltaStock, deltaMaterialDeptStock, 0.0001);
        } else {
          float deltaMaterialDeptStock = afterMaterialDeptIn.getStock();
          Assert.assertEquals("deltaMaterialDeptStock", deltaStock, deltaMaterialDeptStock, 0.0001);
        }
      }
    }

    /*		StockActionDao.deleteStockActionById(mTerminal, StockActionId);

    try{
    	StockActionDao.getStockActionById(mTerminal, StockActionId);
    	Assert.assertTrue("delete stock in record(id = " + StockActionId + ") failed", false);
    }catch(BusinessException e){

    }*/
  }