diff --git a/pjcloud-supermarket/pjcloud-supermarket-api/src/main/java/com/bsd/pjcloud/supermarket/dto/inventoryrecords/InventoryRecordEditItemDTO.java b/pjcloud-supermarket/pjcloud-supermarket-api/src/main/java/com/bsd/pjcloud/supermarket/dto/inventoryrecords/InventoryRecordEditItemDTO.java index 8d0845edf..9e5a1575a 100644 --- a/pjcloud-supermarket/pjcloud-supermarket-api/src/main/java/com/bsd/pjcloud/supermarket/dto/inventoryrecords/InventoryRecordEditItemDTO.java +++ b/pjcloud-supermarket/pjcloud-supermarket-api/src/main/java/com/bsd/pjcloud/supermarket/dto/inventoryrecords/InventoryRecordEditItemDTO.java @@ -96,6 +96,12 @@ public class InventoryRecordEditItemDTO { @Schema(description="包装单位id") private Long unitId; + @Schema(description="实际进价") + private Integer realPrice; + + @Schema(description="零售价") + private Integer retailPrice; + // 注意:packageNum 不需要前端传递,由后端根据 unitId 自动查询并设置 } \ No newline at end of file diff --git a/pjcloud-supermarket/pjcloud-supermarket-api/src/main/java/com/bsd/pjcloud/supermarket/dto/inventoryrecords/InventoryRecordSaveItemDTO.java b/pjcloud-supermarket/pjcloud-supermarket-api/src/main/java/com/bsd/pjcloud/supermarket/dto/inventoryrecords/InventoryRecordSaveItemDTO.java index e4dd6f994..692ae323a 100644 --- a/pjcloud-supermarket/pjcloud-supermarket-api/src/main/java/com/bsd/pjcloud/supermarket/dto/inventoryrecords/InventoryRecordSaveItemDTO.java +++ b/pjcloud-supermarket/pjcloud-supermarket-api/src/main/java/com/bsd/pjcloud/supermarket/dto/inventoryrecords/InventoryRecordSaveItemDTO.java @@ -55,6 +55,9 @@ public class InventoryRecordSaveItemDTO { @Schema(description="实际进价") private Integer realPrice; + @Schema(description="零售价") + private Integer retailPrice; + // 注意:packageNum 不需要前端传递,由后端根据 unitId 自动查询并设置 } \ No newline at end of file diff --git a/pjcloud-supermarket/pjcloud-supermarket-biz/src/main/java/com/bsd/pjcloud/supermarket/controller/SmErpCategoryController.java b/pjcloud-supermarket/pjcloud-supermarket-biz/src/main/java/com/bsd/pjcloud/supermarket/controller/SmErpCategoryController.java index de011e7ec..291bbb8aa 100644 --- a/pjcloud-supermarket/pjcloud-supermarket-biz/src/main/java/com/bsd/pjcloud/supermarket/controller/SmErpCategoryController.java +++ b/pjcloud-supermarket/pjcloud-supermarket-biz/src/main/java/com/bsd/pjcloud/supermarket/controller/SmErpCategoryController.java @@ -119,7 +119,10 @@ public class SmErpCategoryController { @GetMapping("/export") @PreAuthorize("@pms.hasPermission('supermarket_supermarketCategory_export')" ) public List export(SmErpCategoryEntity supermarketCategory, Long[] ids) { - return smErpCategoryService.list(Wrappers.lambdaQuery(supermarketCategory).in(ArrayUtil.isNotEmpty(ids), SmErpCategoryEntity::getId, ids)); + LambdaQueryWrapper wrapper = Wrappers.lambdaQuery(supermarketCategory) + .in(ArrayUtil.isNotEmpty(ids), SmErpCategoryEntity::getId, ids); + smErpCategoryService.applyDefaultSort(wrapper); + return smErpCategoryService.list(wrapper); } @@ -145,8 +148,10 @@ public class SmErpCategoryController { @Operation(summary = "APP分类查询",description = "通过商户id获取该商户下的分类") @GetMapping("/app/simpleAll") public R> getAppSimpleAll(@RequestParam("merchantId")Long merchantId) { - List list = smErpCategoryService. - list(new LambdaQueryWrapper().eq(SmErpCategoryEntity::getMerchantId, merchantId)); + LambdaQueryWrapper wrapper = new LambdaQueryWrapper() + .eq(SmErpCategoryEntity::getMerchantId, merchantId); + smErpCategoryService.applyDefaultSort(wrapper); + List list = smErpCategoryService.list(wrapper); List bean = BeanUtils.toBean(list, SmErpCategorySimpleVo.class); return R.ok(bean); } diff --git a/pjcloud-supermarket/pjcloud-supermarket-biz/src/main/java/com/bsd/pjcloud/supermarket/controller/SmErpSupplierController.java b/pjcloud-supermarket/pjcloud-supermarket-biz/src/main/java/com/bsd/pjcloud/supermarket/controller/SmErpSupplierController.java index e9bebd24f..d31651f68 100644 --- a/pjcloud-supermarket/pjcloud-supermarket-biz/src/main/java/com/bsd/pjcloud/supermarket/controller/SmErpSupplierController.java +++ b/pjcloud-supermarket/pjcloud-supermarket-biz/src/main/java/com/bsd/pjcloud/supermarket/controller/SmErpSupplierController.java @@ -131,10 +131,9 @@ public class SmErpSupplierController { } /** - * 货商下拉 - * @return R + * 货商下拉(带数据权限 scope,仅返回当前账号可见范围) */ - @Operation(summary = "通过id查询" , description = "通过id查询" ) + @Operation(summary = "货商下拉" , description = "货商下拉,支持名称/拼音/联系人/电话模糊搜索" ) @GetMapping("/selectSimpleAll" ) public R selectSimpleAll(@RequestParam(value = "name",required = false)String name, @RequestParam(value = "supplierId",required = false)Long supplierId) { diff --git a/pjcloud-supermarket/pjcloud-supermarket-biz/src/main/java/com/bsd/pjcloud/supermarket/controller/SmSpuController.java b/pjcloud-supermarket/pjcloud-supermarket-biz/src/main/java/com/bsd/pjcloud/supermarket/controller/SmSpuController.java index f59e9be36..c0f215b58 100644 --- a/pjcloud-supermarket/pjcloud-supermarket-biz/src/main/java/com/bsd/pjcloud/supermarket/controller/SmSpuController.java +++ b/pjcloud-supermarket/pjcloud-supermarket-biz/src/main/java/com/bsd/pjcloud/supermarket/controller/SmSpuController.java @@ -203,6 +203,7 @@ public class SmSpuController { LambdaQueryWrapper smErpCategoryEntityLambdaQueryWrapper = new LambdaQueryWrapper<>(); smErpCategoryEntityLambdaQueryWrapper.in(SmErpCategoryEntity::getId, categoryIds); + smErpCategoryService.applyDefaultSort(smErpCategoryEntityLambdaQueryWrapper); List categoryEntities = smErpCategoryService.list(smErpCategoryEntityLambdaQueryWrapper); List bean = BeanUtils.toBean(categoryEntities, SmErpCategorySimpleVo.class); return R.ok(bean); diff --git a/pjcloud-supermarket/pjcloud-supermarket-biz/src/main/java/com/bsd/pjcloud/supermarket/service/SmErpCategoryService.java b/pjcloud-supermarket/pjcloud-supermarket-biz/src/main/java/com/bsd/pjcloud/supermarket/service/SmErpCategoryService.java index c557ff49b..6372bbaf4 100644 --- a/pjcloud-supermarket/pjcloud-supermarket-biz/src/main/java/com/bsd/pjcloud/supermarket/service/SmErpCategoryService.java +++ b/pjcloud-supermarket/pjcloud-supermarket-biz/src/main/java/com/bsd/pjcloud/supermarket/service/SmErpCategoryService.java @@ -23,4 +23,9 @@ public interface SmErpCategoryService extends IService { * @return */ Object pageScope(Page page, LambdaQueryWrapper wrapper); + + /** + * 分类默认排序:sort 升序,id 降序 + */ + void applyDefaultSort(LambdaQueryWrapper wrapper); } \ No newline at end of file diff --git a/pjcloud-supermarket/pjcloud-supermarket-biz/src/main/java/com/bsd/pjcloud/supermarket/service/impl/SmErpCategoryServiceImpl.java b/pjcloud-supermarket/pjcloud-supermarket-biz/src/main/java/com/bsd/pjcloud/supermarket/service/impl/SmErpCategoryServiceImpl.java index 8ae3ac816..3a85f4f14 100644 --- a/pjcloud-supermarket/pjcloud-supermarket-biz/src/main/java/com/bsd/pjcloud/supermarket/service/impl/SmErpCategoryServiceImpl.java +++ b/pjcloud-supermarket/pjcloud-supermarket-biz/src/main/java/com/bsd/pjcloud/supermarket/service/impl/SmErpCategoryServiceImpl.java @@ -19,13 +19,23 @@ import java.util.List; */ @Service public class SmErpCategoryServiceImpl extends ServiceImpl implements SmErpCategoryService { + + @Override + public void applyDefaultSort(LambdaQueryWrapper wrapper) { + wrapper.orderByAsc(SmErpCategoryEntity::getSort) + .orderByDesc(SmErpCategoryEntity::getId); + } + @Override public List listScope() { - return baseMapper.selectListByScope(new LambdaQueryWrapper(), DataScope.of()); + LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); + applyDefaultSort(wrapper); + return baseMapper.selectListByScope(wrapper, DataScope.of()); } @Override public Object pageScope(Page page, LambdaQueryWrapper wrapper) { + applyDefaultSort(wrapper); return baseMapper.selectPageByScope(page, wrapper, DataScope.of()); } } \ No newline at end of file diff --git a/pjcloud-supermarket/pjcloud-supermarket-biz/src/main/java/com/bsd/pjcloud/supermarket/service/impl/SmErpInventoryRecordsServiceImpl.java b/pjcloud-supermarket/pjcloud-supermarket-biz/src/main/java/com/bsd/pjcloud/supermarket/service/impl/SmErpInventoryRecordsServiceImpl.java index 037c9ae79..845e78b0d 100644 --- a/pjcloud-supermarket/pjcloud-supermarket-biz/src/main/java/com/bsd/pjcloud/supermarket/service/impl/SmErpInventoryRecordsServiceImpl.java +++ b/pjcloud-supermarket/pjcloud-supermarket-biz/src/main/java/com/bsd/pjcloud/supermarket/service/impl/SmErpInventoryRecordsServiceImpl.java @@ -172,6 +172,7 @@ public class SmErpInventoryRecordsServiceImpl extends ServiceImpl> itemsBySpuId = cgPlanItemEntities.stream() .collect(Collectors.groupingBy(SmErpInventoryRecordsItemEntity::getErpSpuId)); + Map retailPriceByUnitId = buildRetailPriceMap(items); itemsBySpuId.forEach((erpSpuId, spuItems) -> { // 获取剩余库存数量(入库前的库存) @@ -207,61 +208,188 @@ public class SmErpInventoryRecordsServiceImpl extends ServiceImpl 0) { - double totalAmount = remainingPurchasePrice * remainingQuantity + newInTotalAmount; - newCostPrice = totalAmount / totalQuantity; - - // 调试日志:打印成本价计算过程 -// System.out.println("========== 成本价计算详情 =========="); -// System.out.println("商品ID: " + erpSpuId); -// System.out.println("剩余数量: " + remainingQuantity); -// System.out.println("剩余商品进货价(基础单位采购价): " + remainingPurchasePrice + " 分/个"); -// System.out.println("剩余总金额: " + (remainingPurchasePrice * remainingQuantity) + " 分"); -// System.out.println("新进数量: " + newInTotalQuantity); -// System.out.println("新进商品进货价(realPrice): " + (newInTotalQuantity > 0 ? (newInTotalAmount / newInTotalQuantity) : 0) + " 分/个"); -// System.out.println("新进总金额: " + newInTotalAmount + " 分"); -// System.out.println("总数量: " + totalQuantity); -// System.out.println("总金额: " + totalAmount + " 分"); -// System.out.println("新成本价: " + newCostPrice + " 分/个"); -// System.out.println("新成本价(保留2位): " + String.format("%.2f", newCostPrice) + " 分/个"); -// System.out.println("===================================="); - } else { - // 如果总数量为0,使用新进商品的平均价格 - if (newInTotalQuantity > 0) { - newCostPrice = newInTotalAmount / newInTotalQuantity; - } - } + syncUnitPurchaseAndRetailPrice(spuItems, retailPriceByUnitId); + syncSpuAndBaseUnitPurchasePrice(erpSpuId, spuItems); + + double newCostPrice = calcWeightedCostPrice(remainingQuantity, remainingPurchasePrice, newInTotalAmount, newInTotalQuantity); - // 更新商品成本价(double类型会自动保留精度) SmErpSpuEntity updateSpu = new SmErpSpuEntity(); updateSpu.setId(erpSpuId); updateSpu.setCostPrice(newCostPrice); smErpSpuMapper.updateById(updateSpu); }); + } else if (InventoryTypeEnum.CKTH.getType().equals(inventoryRecordSaveDTO.getInventoryType())) { + syncUnitPriceAndRetailPrice(cgPlanItemEntities, buildRetailPriceMap(items)); } return insert; } + /** 采购入库/退货:同步实际进价、零售价到包装单位主数据 */ + private void syncUnitPriceAndRetailPrice(List itemEntities, Map retailPriceByUnitId) { + if (CollectionUtils.isEmpty(itemEntities)) { + return; + } + for (SmErpInventoryRecordsItemEntity item : itemEntities) { + if (item.getUnitId() == null) { + continue; + } + Integer retailPrice = retailPriceByUnitId != null ? retailPriceByUnitId.get(item.getUnitId()) : null; + if (item.getRealPrice() == null && retailPrice == null) { + continue; + } + SmErpUnitEntity smErpUnitEntity = new SmErpUnitEntity(); + smErpUnitEntity.setId(item.getUnitId()); + if (item.getRealPrice() != null) { + smErpUnitEntity.setPurchasePrice(item.getRealPrice()); + } + if (retailPrice != null) { + smErpUnitEntity.setRetailPrice(retailPrice); + } + smErpUnitMapper.updateById(smErpUnitEntity); + } + } + + private Map buildRetailPriceMap(List items) { + if (CollectionUtils.isEmpty(items)) { + return Collections.emptyMap(); + } + return items.stream() + .filter(item -> item.getUnitId() != null && item.getRetailPrice() != null) + .collect(Collectors.toMap(InventoryRecordSaveItemDTO::getUnitId, InventoryRecordSaveItemDTO::getRetailPrice, (a, b) -> b)); + } + + private Map buildRetailPriceMapFromEditItems(List items) { + if (CollectionUtils.isEmpty(items)) { + return Collections.emptyMap(); + } + return items.stream() + .filter(item -> item.getUnitId() != null && item.getRetailPrice() != null) + .collect(Collectors.toMap(InventoryRecordEditItemDTO::getUnitId, InventoryRecordEditItemDTO::getRetailPrice, (a, b) -> b)); + } + + /** 明细行基准数量(包装数×内装数×行数量) */ + private double calcItemBaseQuantity(SmErpInventoryRecordsItemEntity item) { + Integer pkgNum = item.getPackageNum(); + if (pkgNum == null && item.getUnitId() != null) { + SmErpUnitEntity unit = smErpUnitMapper.selectById(item.getUnitId()); + pkgNum = unit != null ? unit.getPackageNum() : 1; + } + if (pkgNum == null) { + pkgNum = 1; + } + return pkgNum * (item.getQuantity() != null ? item.getQuantity() : 0D); + } + + private double calcItemsBaseQuantity(List items) { + return items.stream().mapToDouble(this::calcItemBaseQuantity).sum(); + } + + /** 明细行金额(realPrice 为包装单位进价/分,金额=进价×包装数量,与前端一致) */ + private double calcItemBaseAmount(SmErpInventoryRecordsItemEntity item) { + if (item.getTotalAmount() != null) { + return item.getTotalAmount(); + } + if (item.getRealPrice() != null && item.getQuantity() != null) { + return item.getRealPrice() * item.getQuantity(); + } + return 0D; + } + + /** 将入库明细的实际进价换算为基础单位进价(分) */ + private Integer calcBaseUnitPurchasePrice(SmErpInventoryRecordsItemEntity item, SmErpUnitEntity inboundUnit, SmErpUnitEntity baseUnit) { + if (item.getRealPrice() == null) { + return null; + } + if (baseUnit != null && item.getUnitId() != null && item.getUnitId().equals(baseUnit.getId())) { + return item.getRealPrice(); + } + Integer packageNum = inboundUnit != null ? inboundUnit.getPackageNum() : item.getPackageNum(); + if (packageNum == null || packageNum <= 0) { + return item.getRealPrice(); + } + return (int) Math.round((double) item.getRealPrice() / packageNum); + } + + /** 同步 SPU、基础包装单位的进价(取本批入库最后一条明细) */ + private void syncSpuAndBaseUnitPurchasePrice(Long erpSpuId, List spuItems) { + if (CollectionUtils.isEmpty(spuItems)) { + return; + } + SmErpUnitEntity baseUnit = smErpUnitMapper.selectOne( + new LambdaQueryWrapper() + .eq(SmErpUnitEntity::getSpuId, erpSpuId) + .eq(SmErpUnitEntity::getIsBase, true) + .last("LIMIT 1") + ); + SmErpInventoryRecordsItemEntity latestItem = spuItems.get(spuItems.size() - 1); + if (latestItem.getRealPrice() == null) { + return; + } + SmErpUnitEntity inboundUnit = latestItem.getUnitId() != null + ? smErpUnitMapper.selectById(latestItem.getUnitId()) + : null; + Integer basePurchasePrice = calcBaseUnitPurchasePrice(latestItem, inboundUnit, baseUnit); + if (basePurchasePrice == null) { + return; + } + if (baseUnit != null && (inboundUnit == null || !latestItem.getUnitId().equals(baseUnit.getId()))) { + SmErpUnitEntity updateBaseUnit = new SmErpUnitEntity(); + updateBaseUnit.setId(baseUnit.getId()); + updateBaseUnit.setPurchasePrice(basePurchasePrice); + smErpUnitMapper.updateById(updateBaseUnit); + } + SmErpSpuEntity updateSpu = new SmErpSpuEntity(); + updateSpu.setId(erpSpuId); + updateSpu.setPurchasePrice(basePurchasePrice); + smErpSpuMapper.updateById(updateSpu); + } + + /** 计算加权平均成本价(分/基础单位) */ + private double calcWeightedCostPrice(double remainingQuantity, double remainingPurchasePrice, + double newInTotalAmount, double newInTotalQuantity) { + double totalQuantity = remainingQuantity + newInTotalQuantity; + if (totalQuantity > 0) { + return (remainingPurchasePrice * remainingQuantity + newInTotalAmount) / totalQuantity; + } + if (newInTotalQuantity > 0) { + return newInTotalAmount / newInTotalQuantity; + } + return 0D; + } + + private double calcItemsBaseAmount(List items) { + return items.stream().mapToDouble(this::calcItemBaseAmount).sum(); + } + + /** 同步明细实际进价、零售价到包装单位主数据 */ + private void syncUnitPurchaseAndRetailPrice(List itemEntities, Map retailPriceByUnitId) { + if (CollectionUtils.isEmpty(itemEntities)) { + return; + } + for (SmErpInventoryRecordsItemEntity item : itemEntities) { + if (item.getUnitId() == null) { + continue; + } + Integer retailPrice = retailPriceByUnitId != null ? retailPriceByUnitId.get(item.getUnitId()) : null; + if (item.getRealPrice() == null && retailPrice == null) { + continue; + } + SmErpUnitEntity smErpUnitEntity = new SmErpUnitEntity(); + smErpUnitEntity.setId(item.getUnitId()); + if (item.getRealPrice() != null) { + smErpUnitEntity.setPurchasePrice(item.getRealPrice()); + } + if (retailPrice != null) { + smErpUnitEntity.setRetailPrice(retailPrice); + } + smErpUnitMapper.updateById(smErpUnitEntity); + } + } + private String getProcessKey(String inventoryType) { switch (inventoryType) { case "3": @@ -585,15 +713,35 @@ public class SmErpInventoryRecordsServiceImpl extends ServiceImpl smErpInventoryRecordsItemEntity.getId() != null).collect(Collectors.toList()); // 为新增的项目设置inventoryId和deptId + final String recordInventoryType; + if (inventoryRecordEditDTO.getInventoryType() != null) { + recordInventoryType = inventoryRecordEditDTO.getInventoryType(); + } else { + SmErpInventoryRecordsEntity dbRecord = baseMapper.selectById(inventoryRecordEditDTO.getId()); + recordInventoryType = dbRecord != null ? dbRecord.getInventoryType() : null; + } insertItems.forEach(insertItem -> { insertItem.setInventoryId(inventoryRecordEditDTO.getId()); insertItem.setDeptId(deptId); + if (insertItem.getInventoryType() == null) { + insertItem.setInventoryType(recordInventoryType); + } }); //更新的话,查询之前保存了哪些item,然后去库存表删掉从新计算库存 List dataBaseSmErpInventoryRecordsItemEntityList = smErpInventoryRecordsItemMapper .selectList(new LambdaQueryWrapper().eq(SmErpInventoryRecordsItemEntity::getInventoryId, inventoryRecordEditDTO.getId())); + // 本次提交保留的明细ID(新增行无ID,不在此列) + List submittedItemIds = items.stream() + .map(InventoryRecordEditItemDTO::getId) + .filter(Objects::nonNull) + .collect(Collectors.toList()); + List toDeleteItemIds = dataBaseSmErpInventoryRecordsItemEntityList.stream() + .map(SmErpInventoryRecordsItemEntity::getId) + .filter(id -> !submittedItemIds.contains(id)) + .collect(Collectors.toList()); + //这部分是数据库原本添加的库存数据,需要全部减掉,重新添加更新的库存数据进去 dataBaseSmErpInventoryRecordsItemEntityList.forEach(item -> { // 使用保存时的内装数,而不是查询最新的内装数,这样即使内装数改变了也能正确计算 @@ -615,6 +763,11 @@ public class SmErpInventoryRecordsServiceImpl extends ServiceImpl smErpInventoryRecordsItemMapper.updateById(item)); @@ -624,27 +777,6 @@ public class SmErpInventoryRecordsServiceImpl extends ServiceImpl existingCodeIds = smErpInventoryRecordsItemMapper.selectList( - new LambdaQueryWrapper() - .eq(SmErpInventoryRecordsItemEntity::getInventoryId, smErpInventoryRecordsEntity.getId()) - ).stream().map(SmErpInventoryRecordsItemEntity::getId).collect(Collectors.toList()); - - // 收集本次提交的ID(排除新增的) - List submittedCodeIds = updateItems.stream() - .map(SmErpInventoryRecordsItemEntity::getId) - .filter(Objects::nonNull) - .collect(Collectors.toList()); - - // 计算需要删除的ID - List toDeleteCodeIds = existingCodeIds.stream() - .filter(id -> !submittedCodeIds.contains(id)) - .collect(Collectors.toList()); - - // 批量删除失效条码 - if (!toDeleteCodeIds.isEmpty()) { - smErpInventoryRecordsItemMapper.deleteByIds(toDeleteCodeIds); - } - // 重新计算主表的totalAmount List finalItems = smErpInventoryRecordsItemMapper.selectList( new LambdaQueryWrapper() @@ -666,25 +798,20 @@ public class SmErpInventoryRecordsServiceImpl extends ServiceImpl savedItems = smErpInventoryRecordsItemMapper.selectList( new LambdaQueryWrapper() .eq(SmErpInventoryRecordsItemEntity::getInventoryId, inventoryRecordEditDTO.getId()) ); - // 获取涉及的商品ID List currentSpuIds = savedItems.stream() .map(SmErpInventoryRecordsItemEntity::getErpSpuId) .distinct() .collect(Collectors.toList()); if (!CollectionUtils.isEmpty(currentSpuIds)) { - // 获取当前库存信息和商品信息 List stockList = smErpStockService.list( new LambdaQueryWrapper().in(SmErpStockEntity::getErpSpuId, currentSpuIds) ); @@ -697,113 +824,51 @@ public class SmErpInventoryRecordsServiceImpl extends ServiceImpl spuMap = spuList.stream() .collect(Collectors.toMap(SmErpSpuEntity::getId, spu -> spu)); - // 按商品分组,计算每个商品的加权平均成本价 Map> itemsBySpuId = savedItems.stream() .collect(Collectors.groupingBy(SmErpInventoryRecordsItemEntity::getErpSpuId)); + Map> oldItemsBySpuId = dataBaseSmErpInventoryRecordsItemEntityList.stream() + .collect(Collectors.groupingBy(SmErpInventoryRecordsItemEntity::getErpSpuId)); + Map retailPriceByUnitId = buildRetailPriceMapFromEditItems(items); itemsBySpuId.forEach((erpSpuId, spuItems) -> { - // 获取当前库存数量(已经更新后的库存) + List oldSpuItems = oldItemsBySpuId.getOrDefault(erpSpuId, Collections.emptyList()); + double oldBatchAmount = calcItemsBaseAmount(oldSpuItems); + double newBatchAmount = calcItemsBaseAmount(spuItems); + SmErpStockEntity stock = stockMap.get(erpSpuId); - double currentStockQuantity = 0; - - if (stock != null) { - currentStockQuantity = stock.getCurrentStock(); - } + double currentStockQuantity = stock != null && stock.getCurrentStock() != null ? stock.getCurrentStock() : 0D; - // 计算本次编辑的入库数量 - double editInQuantity = spuItems.stream() - .mapToDouble(item -> { - Integer pkgNum = item.getPackageNum(); - if (pkgNum == null) { - SmErpUnitEntity unit = smErpUnitMapper.selectById(item.getUnitId()); - pkgNum = unit != null ? unit.getPackageNum() : 1; - } - return pkgNum * item.getQuantity(); - }) - .sum(); + SmErpSpuEntity spu = spuMap.get(erpSpuId); + double currentCostPrice = spu != null && spu.getCostPrice() != null ? spu.getCostPrice() : 0D; - // 剩余数量 = 当前库存 - 本次入库数量 - double remainingQuantity = currentStockQuantity - editInQuantity; - if (remainingQuantity < 0) { - remainingQuantity = 0; - } + syncUnitPurchaseAndRetailPrice(spuItems, retailPriceByUnitId); + syncSpuAndBaseUnitPurchasePrice(erpSpuId, spuItems); - // 获取剩余商品的进货价(从基础单位的采购价获取,单位:分) - double remainingPurchasePrice = 0; - LambdaQueryWrapper baseUnitWrapper = new LambdaQueryWrapper<>(); - baseUnitWrapper.eq(SmErpUnitEntity::getSpuId, erpSpuId); - baseUnitWrapper.eq(SmErpUnitEntity::getIsBase, true); - SmErpUnitEntity baseUnit = smErpUnitMapper.selectOne(baseUnitWrapper); - if (baseUnit != null && baseUnit.getPurchasePrice() != null) { - remainingPurchasePrice = baseUnit.getPurchasePrice(); - } - - // 计算新进(编辑后)商品的总金额和总数量 - double newInTotalAmount = 0; - double newInTotalQuantity = 0; - - for (SmErpInventoryRecordsItemEntity item : spuItems) { - // 获取内装数 - Integer pkgNum = item.getPackageNum(); - if (pkgNum == null) { - SmErpUnitEntity unit = smErpUnitMapper.selectById(item.getUnitId()); - pkgNum = unit != null ? unit.getPackageNum() : 1; - } - - // 新进数量 = 包装数量 * 内装数 - double quantity = pkgNum * item.getQuantity(); - newInTotalQuantity += quantity; - - // 新进商品总金额 = 实际进价 * 数量 - if (item.getRealPrice() != null) { - newInTotalAmount += item.getRealPrice() * quantity; - } - - //更新实际进价到商品包装单位里 - if (item.getRealPrice() != null) { - SmErpUnitEntity smErpUnitEntity = new SmErpUnitEntity(); - smErpUnitEntity.setPurchasePrice(item.getRealPrice()); - smErpUnitEntity.setId(item.getUnitId()); - smErpUnitMapper.updateById(smErpUnitEntity); - } - } - - // 计算加权平均成本价 = (剩余商品进货价*剩余数量 + 新进商品进货价*新进数量) / (剩余数量 + 新进数量) - double newCostPrice = 0; - double totalQuantity = remainingQuantity + newInTotalQuantity; - - if (totalQuantity > 0) { - double totalAmount = remainingPurchasePrice * remainingQuantity + newInTotalAmount; - newCostPrice = totalAmount / totalQuantity; - - // 调试日志:打印成本价计算过程(编辑) - System.out.println("========== 成本价计算详情(编辑) =========="); - System.out.println("商品ID: " + erpSpuId); - System.out.println("剩余数量: " + remainingQuantity); - System.out.println("剩余商品进货价(基础单位采购价): " + remainingPurchasePrice + " 分/个"); - System.out.println("剩余总金额: " + (remainingPurchasePrice * remainingQuantity) + " 分"); - System.out.println("新进数量: " + newInTotalQuantity); - System.out.println("新进商品进货价(realPrice): " + (newInTotalQuantity > 0 ? (newInTotalAmount / newInTotalQuantity) : 0) + " 分/个"); - System.out.println("新进总金额: " + newInTotalAmount + " 分"); - System.out.println("总数量: " + totalQuantity); - System.out.println("总金额: " + totalAmount + " 分"); - System.out.println("新成本价: " + newCostPrice + " 分/个"); - System.out.println("新成本价(保留2位): " + String.format("%.2f", newCostPrice) + " 分/个"); - System.out.println("=========================================="); + double newCostPrice; + if (currentStockQuantity <= 0) { + double newBatchQty = calcItemsBaseQuantity(spuItems); + newCostPrice = newBatchQty > 0 ? calcItemsBaseAmount(spuItems) / newBatchQty : 0D; } else { - // 如果总数量为0,使用新进商品的平均价格 - if (newInTotalQuantity > 0) { - newCostPrice = newInTotalAmount / newInTotalQuantity; + double inventoryValue = currentCostPrice * currentStockQuantity - oldBatchAmount + newBatchAmount; + newCostPrice = inventoryValue / currentStockQuantity; + if (newCostPrice < 0) { + double newBatchQty = calcItemsBaseQuantity(spuItems); + newCostPrice = newBatchQty > 0 ? calcItemsBaseAmount(spuItems) / newBatchQty : 0D; } } - // 更新商品成本价 SmErpSpuEntity updateSpu = new SmErpSpuEntity(); updateSpu.setId(erpSpuId); updateSpu.setCostPrice(newCostPrice); smErpSpuMapper.updateById(updateSpu); }); } + } else if (InventoryTypeEnum.CKTH.getType().equals(inventoryType)) { + List savedItems = smErpInventoryRecordsItemMapper.selectList( + new LambdaQueryWrapper() + .eq(SmErpInventoryRecordsItemEntity::getInventoryId, inventoryRecordEditDTO.getId()) + ); + syncUnitPriceAndRetailPrice(savedItems, buildRetailPriceMapFromEditItems(items)); } return i; @@ -992,6 +1057,15 @@ public class SmErpInventoryRecordsServiceImpl extends ServiceImpl dataBaseSmErpInventoryRecordsItemEntityList = smErpInventoryRecordsItemMapper .selectList(new LambdaQueryWrapper().eq(SmErpInventoryRecordsItemEntity::getInventoryId, pdfUpdateDTO.getId())); + Set submittedSpuIds = items.stream() + .map(PDItemUpdateDTO::getErpSpuId) + .filter(Objects::nonNull) + .collect(Collectors.toSet()); + List toDeleteItemIds = dataBaseSmErpInventoryRecordsItemEntityList.stream() + .filter(item -> !submittedSpuIds.contains(item.getErpSpuId())) + .map(SmErpInventoryRecordsItemEntity::getId) + .collect(Collectors.toList()); + //这部分是数据库原本添加的库存数据,需要全部减掉,重新添加更新的库存数据进去 dataBaseSmErpInventoryRecordsItemEntityList.forEach(item -> { UpdateStockDTO updateStockDTO = new UpdateStockDTO(); @@ -1000,6 +1074,10 @@ public class SmErpInventoryRecordsServiceImpl extends ServiceImpl smErpInventoryRecordsItemMapper.updateById(item)); @@ -1009,27 +1087,6 @@ public class SmErpInventoryRecordsServiceImpl extends ServiceImpl existingCodeIds = smErpInventoryRecordsItemMapper.selectList( - new LambdaQueryWrapper() - .eq(SmErpInventoryRecordsItemEntity::getInventoryId, smErpInventoryRecordsEntity.getId()) - ).stream().map(SmErpInventoryRecordsItemEntity::getId).collect(Collectors.toList()); - - // 收集本次提交的ID(排除新增的) - List submittedCodeIds = updateItems.stream() - .map(SmErpInventoryRecordsItemEntity::getId) - .filter(Objects::nonNull) - .collect(Collectors.toList()); - - // 计算需要删除的ID - List toDeleteCodeIds = existingCodeIds.stream() - .filter(id -> !submittedCodeIds.contains(id)) - .collect(Collectors.toList()); - - // 批量删除失效条码 - if (!toDeleteCodeIds.isEmpty()) { - smErpInventoryRecordsItemMapper.deleteByIds(toDeleteCodeIds); - } - //todo 实际上应该审批后才会入库 //更新库存 smErpStockService.updateStock(updateStockDTOS); @@ -1161,6 +1218,8 @@ public class SmErpInventoryRecordsServiceImpl extends ServiceImpl wrapper = Wrappers.lambdaQuery(); // wrapper.eq(StringUtils.isNotBlank(supermarketSpu.getProductCode()), SmErpSpuEntity::getProductCode,supermarketSpu.getProductCode()); // wrapper.eq(StringUtils.isNotBlank(supermarketSpu.getBarCode()), SmErpSpuEntity::getBarCode,supermarketSpu.getBarCode()); @@ -712,6 +713,23 @@ public class SmErpSpuServiceImpl extends ServiceImpl selectListAllScope(@ParameterObject Page page, SupermarketSpuQueryDTO supermarketSpuQueryDTO) { diff --git a/pjcloud-supermarket/pjcloud-supermarket-biz/src/main/java/com/bsd/pjcloud/supermarket/service/impl/SmErpSupplierServiceImpl.java b/pjcloud-supermarket/pjcloud-supermarket-biz/src/main/java/com/bsd/pjcloud/supermarket/service/impl/SmErpSupplierServiceImpl.java index 74ff30028..51312d6e9 100644 --- a/pjcloud-supermarket/pjcloud-supermarket-biz/src/main/java/com/bsd/pjcloud/supermarket/service/impl/SmErpSupplierServiceImpl.java +++ b/pjcloud-supermarket/pjcloud-supermarket-biz/src/main/java/com/bsd/pjcloud/supermarket/service/impl/SmErpSupplierServiceImpl.java @@ -39,10 +39,17 @@ public class SmErpSupplierServiceImpl extends ServiceImpl selectSimpleAllScope(String name,Long supplierId) { - LambdaQueryWrapper wrapper = new LambdaQueryWrapper(); - wrapper.eq(SmErpSupplierEntity::getStatus, "0"); - wrapper.like(StringUtils.isNotBlank(name),SmErpSupplierEntity::getSupplierName,name); - wrapper.eq(supplierId!=null,SmErpSupplierEntity::getSupplierId,supplierId); + LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); + wrapper.eq(SmErpSupplierEntity::getStatus, "0"); + if (supplierId != null) { + wrapper.eq(SmErpSupplierEntity::getSupplierId, supplierId); + } else if (StringUtils.isNotBlank(name)) { + wrapper.and(w -> w.like(SmErpSupplierEntity::getSupplierName, name) + .or().like(SmErpSupplierEntity::getPinyinCod, name) + .or().like(SmErpSupplierEntity::getLinkName, name) + .or().like(SmErpSupplierEntity::getPhone, name)); + } + wrapper.orderByAsc(SmErpSupplierEntity::getSupplierName); return baseMapper.selectListByScope(wrapper, DataScope.of()); }