|
@@ -10,9 +10,11 @@ import com.fjhx.common.entity.InOutBo;
|
|
|
import com.fjhx.common.enums.InOutType;
|
|
|
import com.fjhx.item.entity.product.po.ProductClassify;
|
|
|
import com.fjhx.item.entity.product.po.ProductInfo;
|
|
|
+import com.fjhx.item.entity.product.po.ProductStockInfo;
|
|
|
import com.fjhx.item.enums.ProductAvailableRecordType;
|
|
|
import com.fjhx.item.service.product.ProductClassifyService;
|
|
|
import com.fjhx.item.service.product.ProductInfoService;
|
|
|
+import com.fjhx.item.service.product.ProductStockInfoService;
|
|
|
import com.fjhx.wms.entity.stock.dto.StockDto;
|
|
|
import com.fjhx.wms.entity.stock.dto.StockJournalDetailsDto;
|
|
|
import com.fjhx.wms.entity.stock.dto.StockSelectDto;
|
|
@@ -29,6 +31,7 @@ import com.fjhx.wms.service.stock.StockService;
|
|
|
import com.fjhx.wms.service.warehouse.WarehouseService;
|
|
|
import com.fjhx.wms.utils.CodeEnum;
|
|
|
import com.ruoyi.common.core.domain.BaseIdPo;
|
|
|
+import com.ruoyi.common.core.domain.BasePo;
|
|
|
import com.ruoyi.common.exception.ServiceException;
|
|
|
import com.ruoyi.common.utils.SecurityUtils;
|
|
|
import com.ruoyi.common.utils.wrapper.IWrapper;
|
|
@@ -36,10 +39,8 @@ import org.springframework.beans.factory.annotation.Autowired;
|
|
|
import org.springframework.stereotype.Service;
|
|
|
|
|
|
import java.math.BigDecimal;
|
|
|
-import java.util.ArrayList;
|
|
|
-import java.util.List;
|
|
|
-import java.util.Map;
|
|
|
-import java.util.Objects;
|
|
|
+import java.math.RoundingMode;
|
|
|
+import java.util.*;
|
|
|
import java.util.function.Function;
|
|
|
import java.util.stream.Collectors;
|
|
|
|
|
@@ -55,15 +56,17 @@ import java.util.stream.Collectors;
|
|
|
@Service
|
|
|
public class StockServiceImpl extends ServiceImpl<StockMapper, Stock> implements StockService {
|
|
|
@Autowired
|
|
|
- StockJournalService stockJournalService;
|
|
|
+ private StockJournalService stockJournalService;
|
|
|
@Autowired
|
|
|
- StockJournalDetailsService stockJournalDetailsService;
|
|
|
+ private StockJournalDetailsService stockJournalDetailsService;
|
|
|
@Autowired
|
|
|
- ProductInfoService productInfoService;
|
|
|
+ private ProductInfoService productInfoService;
|
|
|
@Autowired
|
|
|
- ProductClassifyService productClassifyService;
|
|
|
+ private ProductClassifyService productClassifyService;
|
|
|
@Autowired
|
|
|
- WarehouseService warehouseService;
|
|
|
+ private WarehouseService warehouseService;
|
|
|
+ @Autowired
|
|
|
+ private ProductStockInfoService productStockInfoService;
|
|
|
|
|
|
@Override
|
|
|
public Page<StockVo> getPage(StockSelectDto dto) {
|
|
@@ -245,4 +248,131 @@ public class StockServiceImpl extends ServiceImpl<StockMapper, Stock> implements
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+ /**
|
|
|
+ * 计算结存单价(在操作库存之前计算)
|
|
|
+ */
|
|
|
+ @Override
|
|
|
+ public synchronized StockJournalDetails calculateUnitPrice(InOutType inOutType, Long productId, Long warehouseId, BigDecimal inOutQuantity, Integer purchaseArrival, BigDecimal price) {
|
|
|
+ Warehouse warehouse = warehouseService.getById(warehouseId);
|
|
|
+ if (ObjectUtil.isEmpty(warehouse)) {
|
|
|
+ throw new ServiceException("查询不到仓库信息");
|
|
|
+ }
|
|
|
+ Long companyId = warehouse.getCompanyId();
|
|
|
+
|
|
|
+ StockJournalDetails stockJournalDetails = new StockJournalDetails();
|
|
|
+ stockJournalDetails.setProductId(productId);
|
|
|
+ stockJournalDetails.setQuantity(inOutQuantity);
|
|
|
+
|
|
|
+ //计算结存单价(在操作库存之前计算)
|
|
|
+ ProductStockInfo productStockInfo = productStockInfoService.getOne(q -> q
|
|
|
+ .eq(ProductStockInfo::getProductId, productId)
|
|
|
+ .eq(ProductStockInfo::getCompanyId, companyId)
|
|
|
+ );
|
|
|
+ if (ObjectUtil.isEmpty(productStockInfo)) {
|
|
|
+ throw new ServiceException("查询不到产品信息");
|
|
|
+ }
|
|
|
+ //在库结存单价(实时在库单价)
|
|
|
+ BigDecimal unitPrice = productStockInfo.getUnitPrice();
|
|
|
+ unitPrice = ObjectUtil.isEmpty(unitPrice) ? BigDecimal.ZERO : unitPrice;
|
|
|
+ //不在库结存单价(实时不在库单价)
|
|
|
+ BigDecimal outUnitPrice = productStockInfo.getOutUnitPrice();
|
|
|
+ outUnitPrice = ObjectUtil.isEmpty(outUnitPrice) ? BigDecimal.ZERO : outUnitPrice;
|
|
|
+ List<Stock> stockList = this.list(q -> q.eq(Stock::getProductId, productId).eq(Stock::getCompanyId, companyId));
|
|
|
+ //在库总库存(所有仓库)
|
|
|
+ BigDecimal stockQuantity = stockList.stream().map(Stock::getQuantity).reduce(BigDecimal.ZERO, BigDecimal::add);
|
|
|
+ //不在库总库存(所有仓库)
|
|
|
+ BigDecimal stockOutQuantity = stockList.stream().map(Stock::getOutQuantity).reduce(BigDecimal.ZERO, BigDecimal::add);
|
|
|
+ //获取产品当前仓库信息
|
|
|
+ Stock stock = this.getOne(q -> q.eq(Stock::getWarehouseId, warehouseId).eq(Stock::getProductId, productId).eq(Stock::getCompanyId, companyId));
|
|
|
+ //库存不存在创建0库存记录
|
|
|
+ if (ObjectUtil.isEmpty(stock)) {
|
|
|
+ stock = new Stock();
|
|
|
+ stock.setWarehouseId(warehouseId);
|
|
|
+ stock.setProductId(productId);
|
|
|
+ stock.setQuantity(BigDecimal.ZERO);
|
|
|
+ stock.setCompanyId(companyId);
|
|
|
+ this.save(stock);
|
|
|
+ }
|
|
|
+ Stock finalStock = stock;
|
|
|
+ if (inOutType.equals(InOutType.IN)) {
|
|
|
+ //入库
|
|
|
+ //有单价【采购入库等】按单价算,没有按【其他入库】当前价值=实时不在库单价
|
|
|
+ if (price == null) {
|
|
|
+ price = outUnitPrice;
|
|
|
+ }
|
|
|
+
|
|
|
+ //【入库】实时在库单价=(库存*实时在库单价 + 当前入库数量*当前价值) / (库存+当前入库数量)
|
|
|
+ BigDecimal multiply0 = stockQuantity.multiply(unitPrice);//库存*实时在库单价
|
|
|
+ BigDecimal multiply1 = inOutQuantity.multiply(price);//当前入库数量*当前价值
|
|
|
+ BigDecimal add0 = multiply0.add(multiply1);//(库存*实时在库单价 + 当前入库数量*当前价值)
|
|
|
+ BigDecimal add1 = stockQuantity.add(inOutQuantity);//(库存+当前入库数量)
|
|
|
+ BigDecimal newUnitPrice = add0.divide(add1, 4, RoundingMode.HALF_UP);
|
|
|
+
|
|
|
+ //【其他入库】已出库(为负数时取0) = 已出库 - 当前入库数量
|
|
|
+ if (purchaseArrival != 1) {
|
|
|
+ String format = String.format("out_quantity = IF((out_quantity - %s)<0,0,(out_quantity - %s))", inOutQuantity, inOutQuantity);
|
|
|
+ this.update(q -> q
|
|
|
+ .eq(Stock::getId, finalStock.getId())
|
|
|
+ .eq(Stock::getCompanyId, companyId)
|
|
|
+ .setSql(format)
|
|
|
+ .set(BasePo::getUpdateTime, new Date())
|
|
|
+ .set(BasePo::getUpdateUser, SecurityUtils.getUserId())
|
|
|
+ );
|
|
|
+ }
|
|
|
+ //修改产品中的库存单价
|
|
|
+ productStockInfoService.update(q -> q
|
|
|
+ .eq(ProductStockInfo::getProductId, productId)
|
|
|
+ .eq(ProductStockInfo::getCompanyId, companyId)
|
|
|
+ .set(ProductStockInfo::getUnitPrice, newUnitPrice)
|
|
|
+ .set(BasePo::getUpdateTime, new Date())
|
|
|
+ .set(BasePo::getUpdateUser, SecurityUtils.getUserId())
|
|
|
+ );
|
|
|
+
|
|
|
+ //赋值流水信息
|
|
|
+ stockJournalDetails.setPrice(price);
|
|
|
+ stockJournalDetails.setStockPrice(newUnitPrice);
|
|
|
+ //【入库】实时不在库单价=A物料最新流水的实时不在库单价(不用动直接获取产品的不在库单价)
|
|
|
+ stockJournalDetails.setOutStockPrice(outUnitPrice);
|
|
|
+ } else {
|
|
|
+ //出库
|
|
|
+
|
|
|
+ //有单价按单价算,没有按【出库】当前价值=实时在库单价
|
|
|
+ if (price == null) {
|
|
|
+ price = unitPrice;
|
|
|
+ }
|
|
|
+
|
|
|
+ //【出库】实时不在库单价=(不在库数量*实时不在库单价 + 当前出库数量*当前价值) / (不在库数量+当前出库数量)
|
|
|
+ BigDecimal multiply0 = stockOutQuantity.multiply(outUnitPrice);//不在库数量*实时不在库单价
|
|
|
+ BigDecimal multiply1 = inOutQuantity.multiply(price);//当前出库数量*当前价值
|
|
|
+ BigDecimal add0 = multiply0.add(multiply1);//(不在库数量*实时不在库单价 + 当前出库数量*当前价值)
|
|
|
+ BigDecimal add1 = stockOutQuantity.add(inOutQuantity);//(不在库数量+当前出库数量)
|
|
|
+ BigDecimal newOutUnitPrice = add0.divide(add1, 4, RoundingMode.HALF_UP);
|
|
|
+
|
|
|
+ //计算已出库库存-【出库】已出库 = 已出库+当前出库数量
|
|
|
+ this.update(q -> q
|
|
|
+ .eq(Stock::getId, finalStock.getId())
|
|
|
+ .eq(Stock::getCompanyId, companyId)
|
|
|
+ .setSql("out_quantity = out_quantity + " + inOutQuantity)
|
|
|
+ .set(BasePo::getUpdateTime, new Date())
|
|
|
+ .set(BasePo::getUpdateUser, SecurityUtils.getUserId())
|
|
|
+ );
|
|
|
+ //修改产品中的已出库单价
|
|
|
+ productStockInfoService.update(q -> q
|
|
|
+ .eq(ProductStockInfo::getProductId, productId)
|
|
|
+ .eq(ProductStockInfo::getCompanyId, companyId)
|
|
|
+ .set(ProductStockInfo::getOutUnitPrice, newOutUnitPrice)
|
|
|
+ .set(BasePo::getUpdateTime, new Date())
|
|
|
+ .set(BasePo::getUpdateUser, SecurityUtils.getUserId())
|
|
|
+ );
|
|
|
+
|
|
|
+ //赋值流水信息
|
|
|
+ stockJournalDetails.setPrice(price);
|
|
|
+ //【出库】实时在库单价=A物料最新流水的实时在库单价(不用动直接获取产品的在库单价)
|
|
|
+ stockJournalDetails.setStockPrice(unitPrice);
|
|
|
+ stockJournalDetails.setOutStockPrice(newOutUnitPrice);
|
|
|
+ }
|
|
|
+
|
|
|
+ return stockJournalDetails;
|
|
|
+ }
|
|
|
+
|
|
|
}
|