pd导入,excel模版
This commit is contained in:
1 parent
0776aa415f
commit
fa2734ca89
5 files changed
+161
-57
No files matched your search
+55
@@ -44,6 +44,8 @@ import org.springframework.validation.BindingResult;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.math.RoundingMode;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.stream.Collectors;
|
||||
@@ -73,6 +75,8 @@ public class SmErpSpuController {
|
||||
|
||||
private final SmErpInventoryRecordsService smErpInventoryRecordsService;
|
||||
|
||||
private final SmErpTasteStockService smErpTasteStockService;
|
||||
|
||||
|
||||
/**
|
||||
* 分页查询
|
||||
@@ -419,4 +423,55 @@ public class SmErpSpuController {
|
||||
return R.ok();
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新迁移脚本
|
||||
* @return
|
||||
*/
|
||||
@GetMapping("/123456789")
|
||||
@Transactional
|
||||
public R qy() {
|
||||
|
||||
List<SmErpUnitEntity> list = smErpUnitService.list();
|
||||
List<SmErpUnitEntity> erpUnitEntities = list.stream().filter(supermarketUnitEntity -> supermarketUnitEntity.getTasteId() == null).collect(Collectors.toList());
|
||||
|
||||
for (SmErpUnitEntity item:erpUnitEntities
|
||||
) {
|
||||
String tasteName = item.getTasteName();
|
||||
if (StringUtils.isNotBlank(tasteName)){
|
||||
//需要查询当前item下面有多少口味商品,然后在查询商品的当前库存/口味数量,平均赋予口味库存数量
|
||||
LambdaQueryWrapper<SmErpUnitEntity> smErpUnitEntityLambdaQueryWrapper = new LambdaQueryWrapper<>();
|
||||
smErpUnitEntityLambdaQueryWrapper.eq(SmErpUnitEntity::getSpuId,item.getSpuId());
|
||||
List<SmErpUnitEntity> list1 = smErpUnitService.list(smErpUnitEntityLambdaQueryWrapper);
|
||||
int tasteCount = list1.size();
|
||||
LambdaQueryWrapper<SmErpStockEntity> smErpStockEntityLambdaQueryWrapper = new LambdaQueryWrapper<>();
|
||||
smErpStockEntityLambdaQueryWrapper.eq(SmErpStockEntity::getErpSpuId,item.getSpuId());
|
||||
SmErpStockEntity one = smErpStockService.getOne(smErpStockEntityLambdaQueryWrapper);
|
||||
double tasteStock = one.getCurrentStock()/tasteCount;
|
||||
tasteStock = BigDecimal.valueOf(tasteStock).setScale(2, RoundingMode.HALF_EVEN).doubleValue();
|
||||
|
||||
SmErpTasteStockEntity smErpTasteEntity = new SmErpTasteStockEntity();
|
||||
smErpTasteEntity.setStock(tasteStock);
|
||||
smErpTasteEntity.setTasteName(tasteName);
|
||||
//查询口味是否存在,存在就用存在的id,不存在就创建
|
||||
LambdaQueryWrapper<SmErpTasteStockEntity> smErpTasteEntityLambdaQueryWrapper = new LambdaQueryWrapper<>();
|
||||
smErpTasteEntityLambdaQueryWrapper.eq(SmErpTasteStockEntity::getTasteName, tasteName);
|
||||
smErpTasteEntityLambdaQueryWrapper.eq(SmErpTasteStockEntity::getSpuId, item.getSpuId());
|
||||
SmErpTasteStockEntity smErpTasteStockEntity = smErpTasteStockService.getOne(smErpTasteEntityLambdaQueryWrapper);
|
||||
if (smErpTasteStockEntity == null) {
|
||||
smErpTasteEntity.setSpuId(item.getSpuId());
|
||||
smErpTasteStockService.save(smErpTasteEntity);
|
||||
//不存在使用创建的id
|
||||
item.setTasteId(smErpTasteEntity.getId());
|
||||
smErpUnitService.updateById(item);
|
||||
} else {
|
||||
//存在,就更新item的tasteId
|
||||
item.setTasteId(smErpTasteStockEntity.getId());
|
||||
smErpUnitService.updateById(item);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
return R.ok();
|
||||
}
|
||||
|
||||
}
|
||||
+1
@@ -92,3 +92,4 @@ public class SmErpSpuImportPDNewDto {
|
||||
// @ExcelProperty("品牌")
|
||||
// private String brand; // 品牌
|
||||
}
|
||||
|
||||
+105
-57
@@ -119,6 +119,32 @@ public class SmErpSpuServiceImpl extends ServiceImpl<SmErpSpuMapper, SmErpSpuEnt
|
||||
@Autowired
|
||||
private TaskStoreService taskStoreService;
|
||||
|
||||
// 兼容多种日期格式: yyyy-MM-dd, yyyy/M/d, yyyy.M.d
|
||||
private static LocalDate parseFlexibleLocalDate(String text) {
|
||||
if (text == null) return null;
|
||||
String t = text.trim();
|
||||
java.time.format.DateTimeFormatter[] formats = new java.time.format.DateTimeFormatter[] {
|
||||
java.time.format.DateTimeFormatter.ofPattern("yyyy-MM-dd"),
|
||||
java.time.format.DateTimeFormatter.ofPattern("yyyy/M/d"),
|
||||
java.time.format.DateTimeFormatter.ofPattern("yyyy/M/dd"),
|
||||
java.time.format.DateTimeFormatter.ofPattern("yyyy/MM/d"),
|
||||
java.time.format.DateTimeFormatter.ofPattern("yyyy/MM/dd"),
|
||||
java.time.format.DateTimeFormatter.ofPattern("yyyy.M.d"),
|
||||
java.time.format.DateTimeFormatter.ofPattern("yyyy.MM.dd")
|
||||
};
|
||||
for (java.time.format.DateTimeFormatter f : formats) {
|
||||
try {
|
||||
return LocalDate.parse(t, f);
|
||||
} catch (Exception ignored) {}
|
||||
}
|
||||
// fallback: 尝试替换非数字分隔符为'-'
|
||||
try {
|
||||
String norm = t.replace('/', '-').replace('.', '-');
|
||||
return LocalDate.parse(norm);
|
||||
} catch (Exception ignored) {}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public R saveSpu(SmErpSpuEntity supermarketSpu) {
|
||||
@@ -2162,50 +2188,32 @@ public class SmErpSpuServiceImpl extends ServiceImpl<SmErpSpuMapper, SmErpSpuEnt
|
||||
Map<String, List<SmErpSpuImportPDNewDto>> spuGroupMap = smErpSpuImportPDNewDtos.stream()
|
||||
.collect(Collectors.groupingBy(SmErpSpuImportPDNewDto::getProductCode));
|
||||
|
||||
// 计算从盘点日期到当前的零售销量,用于计算实际剩余库存
|
||||
Map<Long, Double> spuSalesMap = new HashMap<>();
|
||||
// 计算从最早盘点日期到当前的所有零售出库记录,供逐条过滤(包含今天)
|
||||
LocalDate currentDate = LocalDate.now();
|
||||
|
||||
// 收集所有盘点日期,用于计算销量
|
||||
Set<String> allPdDates = smErpSpuImportPDNewDtos.stream()
|
||||
LocalDate minPdDate = smErpSpuImportPDNewDtos.stream()
|
||||
.map(SmErpSpuImportPDNewDto::getPdDate)
|
||||
.filter(StringUtils::isNotBlank)
|
||||
.collect(Collectors.toSet());
|
||||
|
||||
for (String pdDateStr : allPdDates) {
|
||||
try {
|
||||
LocalDate pdDate = LocalDate.parse(pdDateStr);
|
||||
|
||||
// 查询从盘点日期到当前日期的零售出库记录
|
||||
LambdaQueryWrapper<SmErpInventoryRecordsEntity> retailWrapper = new LambdaQueryWrapper<>();
|
||||
retailWrapper.eq(SmErpInventoryRecordsEntity::getInventoryType, "5"); // LSCK 零售出库
|
||||
retailWrapper.ge(SmErpInventoryRecordsEntity::getInventoryDate, pdDate);
|
||||
retailWrapper.le(SmErpInventoryRecordsEntity::getInventoryDate, currentDate);
|
||||
|
||||
List<SmErpInventoryRecordsEntity> retailRecords = smErpInventoryRecordsService.list(retailWrapper);
|
||||
|
||||
// 收集所有零售记录的ID
|
||||
List<Long> retailRecordIds = retailRecords.stream()
|
||||
.map(SmErpInventoryRecordsEntity::getId)
|
||||
.collect(Collectors.toList());
|
||||
|
||||
// 查询零售出库明细
|
||||
if (!retailRecordIds.isEmpty()) {
|
||||
LambdaQueryWrapper<SmErpInventoryRecordsItemEntity> itemWrapper = new LambdaQueryWrapper<>();
|
||||
itemWrapper.in(SmErpInventoryRecordsItemEntity::getInventoryId, retailRecordIds);
|
||||
List<SmErpInventoryRecordsItemEntity> retailItems = smErpInventoryRecordsItemService.list(itemWrapper);
|
||||
|
||||
// 按商品ID汇总销量
|
||||
for (SmErpInventoryRecordsItemEntity item : retailItems) {
|
||||
Long spuId = item.getErpSpuId();
|
||||
Double quantity = item.getQuantity();
|
||||
spuSalesMap.merge(spuId, quantity, Double::sum);
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
// 日期解析失败,跳过该条记录
|
||||
continue;
|
||||
}
|
||||
.map(SmErpSpuServiceImpl::parseFlexibleLocalDate)
|
||||
.filter(Objects::nonNull)
|
||||
.min(LocalDate::compareTo)
|
||||
.orElse(currentDate);
|
||||
|
||||
LambdaQueryWrapper<SmErpInventoryRecordsEntity> retailWrapperAll = new LambdaQueryWrapper<>();
|
||||
retailWrapperAll.eq(SmErpInventoryRecordsEntity::getInventoryType, "5");
|
||||
retailWrapperAll.ge(SmErpInventoryRecordsEntity::getInventoryDate, minPdDate);
|
||||
retailWrapperAll.le(SmErpInventoryRecordsEntity::getInventoryDate, currentDate);
|
||||
List<SmErpInventoryRecordsEntity> allRetailRecords = smErpInventoryRecordsService.list(retailWrapperAll);
|
||||
|
||||
Map<Long, LocalDate> recordIdToDate = allRetailRecords.stream()
|
||||
.collect(Collectors.toMap(SmErpInventoryRecordsEntity::getId, SmErpInventoryRecordsEntity::getInventoryDate));
|
||||
|
||||
Map<Long, List<SmErpInventoryRecordsItemEntity>> spuToItemsMap = new HashMap<>();
|
||||
if (!allRetailRecords.isEmpty()) {
|
||||
List<Long> allRetailRecordIds = allRetailRecords.stream().map(SmErpInventoryRecordsEntity::getId).collect(Collectors.toList());
|
||||
LambdaQueryWrapper<SmErpInventoryRecordsItemEntity> allItemsWrapper = new LambdaQueryWrapper<>();
|
||||
allItemsWrapper.in(SmErpInventoryRecordsItemEntity::getInventoryId, allRetailRecordIds);
|
||||
List<SmErpInventoryRecordsItemEntity> allRetailItems = smErpInventoryRecordsItemService.list(allItemsWrapper);
|
||||
spuToItemsMap = allRetailItems.stream().collect(Collectors.groupingBy(SmErpInventoryRecordsItemEntity::getErpSpuId));
|
||||
}
|
||||
|
||||
// 按商品分组处理
|
||||
@@ -2217,7 +2225,8 @@ public class SmErpSpuServiceImpl extends ServiceImpl<SmErpSpuMapper, SmErpSpuEnt
|
||||
SmErpSpuEntity spu = null;
|
||||
List<SmErpUnitEntity> units = new ArrayList<>();
|
||||
Map<String, Double> tasteStockMap = new HashMap<>(); // 口味库存映射
|
||||
Double totalSpuStock = 0.0; // 商品总库存
|
||||
Double totalSpuAccount = 0.0; // 账面合计
|
||||
Double totalSpuReal = 0.0; // 真实合计(扣销量)
|
||||
|
||||
// 第一轮:处理商品主数据和包装单位
|
||||
for (SmErpSpuImportPDNewDto dto : spuDtos) {
|
||||
@@ -2428,17 +2437,56 @@ public class SmErpSpuServiceImpl extends ServiceImpl<SmErpSpuMapper, SmErpSpuEnt
|
||||
}
|
||||
}
|
||||
|
||||
// 6. 计算包装单位的实际库存(盘点库存 × 内装数)
|
||||
Double unitActualStock = dto.getPdStock() * dto.getPackageNum();
|
||||
|
||||
// 7. 更新口味库存(如果有口味)
|
||||
if (tasteId != null) {
|
||||
// 累加同一口味的库存
|
||||
tasteStockMap.merge(dto.getTaste(), unitActualStock, Double::sum);
|
||||
// 6. 账面数量(盘点 × 内装)
|
||||
Double accountNumber = (dto.getPdStock() == null ? 0.0 : dto.getPdStock()) *
|
||||
(dto.getPackageNum() == null ? 1.0 : dto.getPackageNum());
|
||||
|
||||
// 7. 计算从pdDate到今天(含)的销量(按SPU)
|
||||
Double salesQuantity = 0.0;
|
||||
if (StringUtils.isNotBlank(dto.getPdDate())) {
|
||||
try {
|
||||
LocalDate pdDate = parseFlexibleLocalDate(dto.getPdDate());
|
||||
if (pdDate == null) { throw new IllegalArgumentException("bad date"); }
|
||||
List<SmErpInventoryRecordsItemEntity> spuItems = spuToItemsMap.getOrDefault(spu.getId(), Collections.emptyList());
|
||||
for (SmErpInventoryRecordsItemEntity it : spuItems) {
|
||||
LocalDate d = recordIdToDate.get(it.getInventoryId());
|
||||
if (d != null && (d.isEqual(pdDate) || d.isAfter(pdDate))) {
|
||||
salesQuantity += (it.getQuantity() == null ? 0.0 : it.getQuantity());
|
||||
}
|
||||
}
|
||||
} catch (Exception ignore) {}
|
||||
}
|
||||
|
||||
// 8. 累加到商品总库存
|
||||
totalSpuStock += unitActualStock;
|
||||
|
||||
// 8. 真实库存 = 账面 - 销量
|
||||
Double realRemainingStock = accountNumber - salesQuantity;
|
||||
|
||||
// 9. 累计
|
||||
if (tasteId != null) {
|
||||
tasteStockMap.merge(dto.getTaste(), realRemainingStock, Double::sum);
|
||||
}
|
||||
totalSpuAccount += accountNumber;
|
||||
totalSpuReal += realRemainingStock;
|
||||
|
||||
// 10. 盘点明细
|
||||
PDItemSaveDTO item = new PDItemSaveDTO();
|
||||
item.setErpSpuId(spu.getId());
|
||||
item.setUnitId(unit.getId());
|
||||
item.setAccountNumber(accountNumber);
|
||||
item.setRealNumber(realRemainingStock);
|
||||
Double purchasePrice = dto.getPurchasePrice() != null ? dto.getPurchasePrice() : 0.0;
|
||||
Double retailPrice = dto.getRetailPrice() != null ? dto.getRetailPrice() : purchasePrice;
|
||||
item.setUnitPrice((int) Math.round(purchasePrice * 100));
|
||||
item.setRealPrice((int) Math.round(retailPrice * 100));
|
||||
Double diff = realRemainingStock - accountNumber;
|
||||
if (diff > 0) { item.setProfit(diff); item.setLoss(0.0); item.setOrderType(OrderTypeEnum.RK.getType()); }
|
||||
else if (diff < 0) { item.setProfit(0.0); item.setLoss(Math.abs(diff)); item.setOrderType(OrderTypeEnum.CK.getType()); }
|
||||
else { item.setProfit(0.0); item.setLoss(0.0); item.setOrderType(OrderTypeEnum.No.getType()); }
|
||||
item.setQuantity(Math.abs(diff));
|
||||
// 备注:盘点日期与销量扣减说明
|
||||
String remark = "盘点日期:" + (dto.getPdDate() == null ? "" : dto.getPdDate()) +
|
||||
", 销量合计:" + BigDecimal.valueOf(salesQuantity).setScale(2, RoundingMode.HALF_UP);
|
||||
item.setRemark(remark);
|
||||
pdItemList.add(item);
|
||||
|
||||
} catch (Exception e) {
|
||||
errorList.add(createErrorInfo(spuDtos.indexOf(dto) + 1, dto.getProductCode(),
|
||||
@@ -2466,7 +2514,7 @@ public class SmErpSpuServiceImpl extends ServiceImpl<SmErpSpuMapper, SmErpSpuEnt
|
||||
}
|
||||
}
|
||||
|
||||
// 更新商品总库存
|
||||
// 更新商品总库存:期初=账面合计,当前=真实合计(已扣销量)
|
||||
LambdaQueryWrapper<SmErpStockEntity> existingStockWrapper = new LambdaQueryWrapper<>();
|
||||
existingStockWrapper.eq(SmErpStockEntity::getErpSpuId, spu.getId());
|
||||
SmErpStockEntity existingStock = smErpStockService.getOne(existingStockWrapper);
|
||||
@@ -2474,16 +2522,16 @@ public class SmErpSpuServiceImpl extends ServiceImpl<SmErpSpuMapper, SmErpSpuEnt
|
||||
if (existingStock != null) {
|
||||
existingStock.setInventoryUpperLimit(1000); // 默认值
|
||||
existingStock.setInventoryLowerLimit(10); // 默认值
|
||||
existingStock.setBaseStock(totalSpuStock);
|
||||
existingStock.setCurrentStock(totalSpuStock);
|
||||
existingStock.setBaseStock(totalSpuAccount);
|
||||
existingStock.setCurrentStock(totalSpuReal);
|
||||
smErpStockService.updateById(existingStock);
|
||||
} else {
|
||||
SmErpStockEntity stock = new SmErpStockEntity();
|
||||
stock.setErpSpuId(spu.getId());
|
||||
stock.setInventoryUpperLimit(1000);
|
||||
stock.setInventoryLowerLimit(10);
|
||||
stock.setBaseStock(totalSpuStock);
|
||||
stock.setCurrentStock(totalSpuStock);
|
||||
stock.setBaseStock(totalSpuAccount);
|
||||
stock.setCurrentStock(totalSpuReal);
|
||||
smErpStockService.save(stock);
|
||||
}
|
||||
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Reference in new issue
Block a user