Merge branch 'master' of https://gitea.zianxin.com/zax/biz-api-cloud
This commit is contained in:
commit
4faa7bb759
10 files changed
+308
-193
No files matched your search
+6
@@ -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 自动查询并设置
|
||||
|
||||
}
|
||||
+3
@@ -55,6 +55,9 @@ public class InventoryRecordSaveItemDTO {
|
||||
@Schema(description="实际进价")
|
||||
private Integer realPrice;
|
||||
|
||||
@Schema(description="零售价")
|
||||
private Integer retailPrice;
|
||||
|
||||
// 注意:packageNum 不需要前端传递,由后端根据 unitId 自动查询并设置
|
||||
|
||||
}
|
||||
+8
-3
@@ -119,7 +119,10 @@ public class SmErpCategoryController {
|
||||
@GetMapping("/export")
|
||||
@PreAuthorize("@pms.hasPermission('supermarket_supermarketCategory_export')" )
|
||||
public List<SmErpCategoryEntity> export(SmErpCategoryEntity supermarketCategory, Long[] ids) {
|
||||
return smErpCategoryService.list(Wrappers.lambdaQuery(supermarketCategory).in(ArrayUtil.isNotEmpty(ids), SmErpCategoryEntity::getId, ids));
|
||||
LambdaQueryWrapper<SmErpCategoryEntity> 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<List<SmErpCategorySimpleVo>> getAppSimpleAll(@RequestParam("merchantId")Long merchantId) {
|
||||
List<SmErpCategoryEntity> list = smErpCategoryService.
|
||||
list(new LambdaQueryWrapper<SmErpCategoryEntity>().eq(SmErpCategoryEntity::getMerchantId, merchantId));
|
||||
LambdaQueryWrapper<SmErpCategoryEntity> wrapper = new LambdaQueryWrapper<SmErpCategoryEntity>()
|
||||
.eq(SmErpCategoryEntity::getMerchantId, merchantId);
|
||||
smErpCategoryService.applyDefaultSort(wrapper);
|
||||
List<SmErpCategoryEntity> list = smErpCategoryService.list(wrapper);
|
||||
List<SmErpCategorySimpleVo> bean = BeanUtils.toBean(list, SmErpCategorySimpleVo.class);
|
||||
return R.ok(bean);
|
||||
}
|
||||
|
||||
+2
-3
@@ -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) {
|
||||
|
||||
+1
@@ -203,6 +203,7 @@ public class SmSpuController {
|
||||
|
||||
LambdaQueryWrapper<SmErpCategoryEntity> smErpCategoryEntityLambdaQueryWrapper = new LambdaQueryWrapper<>();
|
||||
smErpCategoryEntityLambdaQueryWrapper.in(SmErpCategoryEntity::getId, categoryIds);
|
||||
smErpCategoryService.applyDefaultSort(smErpCategoryEntityLambdaQueryWrapper);
|
||||
List<SmErpCategoryEntity> categoryEntities = smErpCategoryService.list(smErpCategoryEntityLambdaQueryWrapper);
|
||||
List<SmErpCategorySimpleVo> bean = BeanUtils.toBean(categoryEntities, SmErpCategorySimpleVo.class);
|
||||
return R.ok(bean);
|
||||
|
||||
+5
@@ -23,4 +23,9 @@ public interface SmErpCategoryService extends IService<SmErpCategoryEntity> {
|
||||
* @return
|
||||
*/
|
||||
Object pageScope(Page page, LambdaQueryWrapper<SmErpCategoryEntity> wrapper);
|
||||
|
||||
/**
|
||||
* 分类默认排序:sort 升序,id 降序
|
||||
*/
|
||||
void applyDefaultSort(LambdaQueryWrapper<SmErpCategoryEntity> wrapper);
|
||||
}
|
||||
+11
-1
@@ -19,13 +19,23 @@ import java.util.List;
|
||||
*/
|
||||
@Service
|
||||
public class SmErpCategoryServiceImpl extends ServiceImpl<SmErpCategoryMapper, SmErpCategoryEntity> implements SmErpCategoryService {
|
||||
|
||||
@Override
|
||||
public void applyDefaultSort(LambdaQueryWrapper<SmErpCategoryEntity> wrapper) {
|
||||
wrapper.orderByAsc(SmErpCategoryEntity::getSort)
|
||||
.orderByDesc(SmErpCategoryEntity::getId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<SmErpCategoryEntity> listScope() {
|
||||
return baseMapper.selectListByScope(new LambdaQueryWrapper<SmErpCategoryEntity>(), DataScope.of());
|
||||
LambdaQueryWrapper<SmErpCategoryEntity> wrapper = new LambdaQueryWrapper<>();
|
||||
applyDefaultSort(wrapper);
|
||||
return baseMapper.selectListByScope(wrapper, DataScope.of());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object pageScope(Page page, LambdaQueryWrapper<SmErpCategoryEntity> wrapper) {
|
||||
applyDefaultSort(wrapper);
|
||||
return baseMapper.selectPageByScope(page, wrapper, DataScope.of());
|
||||
}
|
||||
}
|
||||
+243
-182
@@ -172,6 +172,7 @@ public class SmErpInventoryRecordsServiceImpl extends ServiceImpl<SmErpInventory
|
||||
// 按商品分组,计算每个商品的加权平均成本价
|
||||
Map<Long, List<SmErpInventoryRecordsItemEntity>> itemsBySpuId = cgPlanItemEntities.stream()
|
||||
.collect(Collectors.groupingBy(SmErpInventoryRecordsItemEntity::getErpSpuId));
|
||||
Map<Long, Integer> retailPriceByUnitId = buildRetailPriceMap(items);
|
||||
|
||||
itemsBySpuId.forEach((erpSpuId, spuItems) -> {
|
||||
// 获取剩余库存数量(入库前的库存)
|
||||
@@ -207,61 +208,188 @@ public class SmErpInventoryRecordsServiceImpl extends ServiceImpl<SmErpInventory
|
||||
double newInTotalQuantity = 0;
|
||||
|
||||
for (SmErpInventoryRecordsItemEntity item : spuItems) {
|
||||
// 新进数量 = 包装数量(箱数) * 内装数(个/箱)
|
||||
double quantity = item.getPackageNum() * item.getQuantity();
|
||||
newInTotalQuantity += quantity;
|
||||
|
||||
// 新进商品总金额 = 实际进价(分/个) * 数量(个)
|
||||
if (item.getRealPrice() != null) {
|
||||
newInTotalAmount += item.getRealPrice() * quantity;
|
||||
}
|
||||
|
||||
//更新实际进价到商品包装单位里
|
||||
SmErpUnitEntity smErpUnitEntity = new SmErpUnitEntity();
|
||||
smErpUnitEntity.setPurchasePrice(item.getRealPrice());
|
||||
smErpUnitEntity.setId(item.getUnitId());
|
||||
smErpUnitMapper.updateById(smErpUnitEntity);
|
||||
newInTotalQuantity += calcItemBaseQuantity(item);
|
||||
newInTotalAmount += calcItemBaseAmount(item);
|
||||
}
|
||||
|
||||
// 计算加权平均成本价 = (剩余商品进货价*剩余数量 + 新进商品进货价*新进数量) / (剩余数量 + 新进数量)
|
||||
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("====================================");
|
||||
} 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<SmErpInventoryRecordsItemEntity> itemEntities, Map<Long, Integer> 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<Long, Integer> buildRetailPriceMap(List<InventoryRecordSaveItemDTO> 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<Long, Integer> buildRetailPriceMapFromEditItems(List<InventoryRecordEditItemDTO> 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<SmErpInventoryRecordsItemEntity> 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<SmErpInventoryRecordsItemEntity> spuItems) {
|
||||
if (CollectionUtils.isEmpty(spuItems)) {
|
||||
return;
|
||||
}
|
||||
SmErpUnitEntity baseUnit = smErpUnitMapper.selectOne(
|
||||
new LambdaQueryWrapper<SmErpUnitEntity>()
|
||||
.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<SmErpInventoryRecordsItemEntity> items) {
|
||||
return items.stream().mapToDouble(this::calcItemBaseAmount).sum();
|
||||
}
|
||||
|
||||
/** 同步明细实际进价、零售价到包装单位主数据 */
|
||||
private void syncUnitPurchaseAndRetailPrice(List<SmErpInventoryRecordsItemEntity> itemEntities, Map<Long, Integer> 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<SmErpInventory
|
||||
filter(smErpInventoryRecordsItemEntity -> 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<SmErpInventoryRecordsItemEntity> dataBaseSmErpInventoryRecordsItemEntityList = smErpInventoryRecordsItemMapper
|
||||
.selectList(new LambdaQueryWrapper<SmErpInventoryRecordsItemEntity>().eq(SmErpInventoryRecordsItemEntity::getInventoryId, inventoryRecordEditDTO.getId()));
|
||||
|
||||
// 本次提交保留的明细ID(新增行无ID,不在此列)
|
||||
List<Long> submittedItemIds = items.stream()
|
||||
.map(InventoryRecordEditItemDTO::getId)
|
||||
.filter(Objects::nonNull)
|
||||
.collect(Collectors.toList());
|
||||
List<Long> 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<SmErpInventory
|
||||
});
|
||||
|
||||
|
||||
// 删除前端已移除的明细(须在 insert 之前,且不能按 insert 后再查全量ID删除,否则会误删新增行)
|
||||
if (!toDeleteItemIds.isEmpty()) {
|
||||
smErpInventoryRecordsItemMapper.deleteByIds(toDeleteItemIds);
|
||||
}
|
||||
|
||||
// 批量更新已存在的明细(包括 packageNum 字段)
|
||||
if (!CollectionUtils.isEmpty(updateItems)) {
|
||||
updateItems.forEach(item -> smErpInventoryRecordsItemMapper.updateById(item));
|
||||
@@ -624,27 +777,6 @@ public class SmErpInventoryRecordsServiceImpl extends ServiceImpl<SmErpInventory
|
||||
smErpInventoryRecordsItemMapper.insert(insertItems);
|
||||
}
|
||||
|
||||
List<Long> existingCodeIds = smErpInventoryRecordsItemMapper.selectList(
|
||||
new LambdaQueryWrapper<SmErpInventoryRecordsItemEntity>()
|
||||
.eq(SmErpInventoryRecordsItemEntity::getInventoryId, smErpInventoryRecordsEntity.getId())
|
||||
).stream().map(SmErpInventoryRecordsItemEntity::getId).collect(Collectors.toList());
|
||||
|
||||
// 收集本次提交的ID(排除新增的)
|
||||
List<Long> submittedCodeIds = updateItems.stream()
|
||||
.map(SmErpInventoryRecordsItemEntity::getId)
|
||||
.filter(Objects::nonNull)
|
||||
.collect(Collectors.toList());
|
||||
|
||||
// 计算需要删除的ID
|
||||
List<Long> toDeleteCodeIds = existingCodeIds.stream()
|
||||
.filter(id -> !submittedCodeIds.contains(id))
|
||||
.collect(Collectors.toList());
|
||||
|
||||
// 批量删除失效条码
|
||||
if (!toDeleteCodeIds.isEmpty()) {
|
||||
smErpInventoryRecordsItemMapper.deleteByIds(toDeleteCodeIds);
|
||||
}
|
||||
|
||||
// 重新计算主表的totalAmount
|
||||
List<SmErpInventoryRecordsItemEntity> finalItems = smErpInventoryRecordsItemMapper.selectList(
|
||||
new LambdaQueryWrapper<SmErpInventoryRecordsItemEntity>()
|
||||
@@ -666,25 +798,20 @@ public class SmErpInventoryRecordsServiceImpl extends ServiceImpl<SmErpInventory
|
||||
//更新库存
|
||||
smErpStockService.updateStock(updateStockDTOS);
|
||||
|
||||
//计算库存商品的成本价 = (剩余商品进货价*剩余数量+新进商品进货价*新进数量)/(剩余数量+新进数量)
|
||||
//只有采购入库类型才需要更新成本价
|
||||
if (smErpInventoryRecordsEntity.getInventoryType() != null &&
|
||||
smErpInventoryRecordsEntity.getInventoryType().equals(InventoryTypeEnum.CKRK.getType())){
|
||||
|
||||
// 获取最终保存的商品列表
|
||||
// 采购入库编辑:同步进价/零售价,并重算成本价(扣除本单旧进价后写入新进价)
|
||||
String inventoryType = recordInventoryType;
|
||||
if (InventoryTypeEnum.CKRK.getType().equals(inventoryType)) {
|
||||
List<SmErpInventoryRecordsItemEntity> savedItems = smErpInventoryRecordsItemMapper.selectList(
|
||||
new LambdaQueryWrapper<SmErpInventoryRecordsItemEntity>()
|
||||
.eq(SmErpInventoryRecordsItemEntity::getInventoryId, inventoryRecordEditDTO.getId())
|
||||
);
|
||||
|
||||
// 获取涉及的商品ID
|
||||
List<Long> currentSpuIds = savedItems.stream()
|
||||
.map(SmErpInventoryRecordsItemEntity::getErpSpuId)
|
||||
.distinct()
|
||||
.collect(Collectors.toList());
|
||||
|
||||
if (!CollectionUtils.isEmpty(currentSpuIds)) {
|
||||
// 获取当前库存信息和商品信息
|
||||
List<SmErpStockEntity> stockList = smErpStockService.list(
|
||||
new LambdaQueryWrapper<SmErpStockEntity>().in(SmErpStockEntity::getErpSpuId, currentSpuIds)
|
||||
);
|
||||
@@ -697,113 +824,51 @@ public class SmErpInventoryRecordsServiceImpl extends ServiceImpl<SmErpInventory
|
||||
Map<Long, SmErpSpuEntity> spuMap = spuList.stream()
|
||||
.collect(Collectors.toMap(SmErpSpuEntity::getId, spu -> spu));
|
||||
|
||||
// 按商品分组,计算每个商品的加权平均成本价
|
||||
Map<Long, List<SmErpInventoryRecordsItemEntity>> itemsBySpuId = savedItems.stream()
|
||||
.collect(Collectors.groupingBy(SmErpInventoryRecordsItemEntity::getErpSpuId));
|
||||
Map<Long, List<SmErpInventoryRecordsItemEntity>> oldItemsBySpuId = dataBaseSmErpInventoryRecordsItemEntityList.stream()
|
||||
.collect(Collectors.groupingBy(SmErpInventoryRecordsItemEntity::getErpSpuId));
|
||||
Map<Long, Integer> retailPriceByUnitId = buildRetailPriceMapFromEditItems(items);
|
||||
|
||||
itemsBySpuId.forEach((erpSpuId, spuItems) -> {
|
||||
// 获取当前库存数量(已经更新后的库存)
|
||||
List<SmErpInventoryRecordsItemEntity> 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<SmErpUnitEntity> 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<SmErpInventoryRecordsItemEntity> savedItems = smErpInventoryRecordsItemMapper.selectList(
|
||||
new LambdaQueryWrapper<SmErpInventoryRecordsItemEntity>()
|
||||
.eq(SmErpInventoryRecordsItemEntity::getInventoryId, inventoryRecordEditDTO.getId())
|
||||
);
|
||||
syncUnitPriceAndRetailPrice(savedItems, buildRetailPriceMapFromEditItems(items));
|
||||
}
|
||||
|
||||
return i;
|
||||
@@ -992,6 +1057,15 @@ public class SmErpInventoryRecordsServiceImpl extends ServiceImpl<SmErpInventory
|
||||
List<SmErpInventoryRecordsItemEntity> dataBaseSmErpInventoryRecordsItemEntityList = smErpInventoryRecordsItemMapper
|
||||
.selectList(new LambdaQueryWrapper<SmErpInventoryRecordsItemEntity>().eq(SmErpInventoryRecordsItemEntity::getInventoryId, pdfUpdateDTO.getId()));
|
||||
|
||||
Set<Long> submittedSpuIds = items.stream()
|
||||
.map(PDItemUpdateDTO::getErpSpuId)
|
||||
.filter(Objects::nonNull)
|
||||
.collect(Collectors.toSet());
|
||||
List<Long> 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<SmErpInventory
|
||||
updateStockDTOS.add(updateStockDTO);
|
||||
});
|
||||
|
||||
if (!toDeleteItemIds.isEmpty()) {
|
||||
smErpInventoryRecordsItemMapper.deleteByIds(toDeleteItemIds);
|
||||
}
|
||||
|
||||
// 批量更新已存在的明细
|
||||
if (!CollectionUtils.isEmpty(updateItems)) {
|
||||
updateItems.forEach(item -> smErpInventoryRecordsItemMapper.updateById(item));
|
||||
@@ -1009,27 +1087,6 @@ public class SmErpInventoryRecordsServiceImpl extends ServiceImpl<SmErpInventory
|
||||
smErpInventoryRecordsItemMapper.insert(insertItems);
|
||||
}
|
||||
|
||||
List<Long> existingCodeIds = smErpInventoryRecordsItemMapper.selectList(
|
||||
new LambdaQueryWrapper<SmErpInventoryRecordsItemEntity>()
|
||||
.eq(SmErpInventoryRecordsItemEntity::getInventoryId, smErpInventoryRecordsEntity.getId())
|
||||
).stream().map(SmErpInventoryRecordsItemEntity::getId).collect(Collectors.toList());
|
||||
|
||||
// 收集本次提交的ID(排除新增的)
|
||||
List<Long> submittedCodeIds = updateItems.stream()
|
||||
.map(SmErpInventoryRecordsItemEntity::getId)
|
||||
.filter(Objects::nonNull)
|
||||
.collect(Collectors.toList());
|
||||
|
||||
// 计算需要删除的ID
|
||||
List<Long> 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<SmErpInventory
|
||||
SmErpInventoryRecordsEntity::getInventoryType, smErpInventoryRecords.getInventoryType());
|
||||
wrapper.eq(StringUtils.isNotBlank(smErpInventoryRecords.getOrderType()),
|
||||
SmErpInventoryRecordsEntity::getOrderType, smErpInventoryRecords.getOrderType());
|
||||
wrapper.eq(smErpInventoryRecords.getSupplierId() != null,
|
||||
SmErpInventoryRecordsEntity::getSupplierId, smErpInventoryRecords.getSupplierId());
|
||||
}
|
||||
}
|
||||
wrapper.orderByDesc(SmErpInventoryRecordsEntity::getCreateTime);
|
||||
@@ -1345,6 +1404,8 @@ public class SmErpInventoryRecordsServiceImpl extends ServiceImpl<SmErpInventory
|
||||
SmErpInventoryRecordsEntity::getInventoryType, smErpInventoryRecords.getInventoryType());
|
||||
wrapper.eq(StringUtils.isNotBlank(smErpInventoryRecords.getOrderType()),
|
||||
SmErpInventoryRecordsEntity::getOrderType, smErpInventoryRecords.getOrderType());
|
||||
wrapper.eq(smErpInventoryRecords.getSupplierId() != null,
|
||||
SmErpInventoryRecordsEntity::getSupplierId, smErpInventoryRecords.getSupplierId());
|
||||
}
|
||||
}
|
||||
wrapper.orderByDesc(SmErpInventoryRecordsEntity::getCreateTime);
|
||||
|
||||
+18
@@ -677,6 +677,7 @@ public class SmErpSpuServiceImpl extends ServiceImpl<SmErpSpuMapper, SmErpSpuEnt
|
||||
|
||||
@Override
|
||||
public Object pageScope(Page page, SmErpSpuPageDto smErpSpuPageDto) {
|
||||
normalizeSpuPageQuery(smErpSpuPageDto);
|
||||
// LambdaQueryWrapper<SmErpSpuEntity> 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<SmErpSpuMapper, SmErpSpuEnt
|
||||
return pageData;
|
||||
}
|
||||
|
||||
private void normalizeSpuPageQuery(SmErpSpuPageDto dto) {
|
||||
if (dto == null) {
|
||||
return;
|
||||
}
|
||||
dto.setProductCode(trimToNull(dto.getProductCode()));
|
||||
dto.setBarCode(trimToNull(dto.getBarCode()));
|
||||
dto.setProductName(trimToNull(dto.getProductName()));
|
||||
}
|
||||
|
||||
private String trimToNull(String value) {
|
||||
if (value == null) {
|
||||
return null;
|
||||
}
|
||||
String trimmed = value.trim();
|
||||
return StringUtils.isBlank(trimmed) ? null : trimmed;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Page<SpuVo> selectListAllScope(@ParameterObject Page page, SupermarketSpuQueryDTO supermarketSpuQueryDTO) {
|
||||
|
||||
|
||||
+11
-4
@@ -39,10 +39,17 @@ public class SmErpSupplierServiceImpl extends ServiceImpl<SmErpSupplierMapper, S
|
||||
private final SmErpSupplierTypeMapper supplierTypeMapper;
|
||||
@Override
|
||||
public List<SmErpSupplierEntity> selectSimpleAllScope(String name,Long supplierId) {
|
||||
LambdaQueryWrapper<SmErpSupplierEntity> wrapper = new LambdaQueryWrapper<SmErpSupplierEntity>();
|
||||
wrapper.eq(SmErpSupplierEntity::getStatus, "0");
|
||||
wrapper.like(StringUtils.isNotBlank(name),SmErpSupplierEntity::getSupplierName,name);
|
||||
wrapper.eq(supplierId!=null,SmErpSupplierEntity::getSupplierId,supplierId);
|
||||
LambdaQueryWrapper<SmErpSupplierEntity> 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());
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user