库存商品上传修改,库存单位类型修改

This commit is contained in:
zjf committed 2025-02-28 22:05:44 +08:00
1 parent 593701cd83
commit 2b8591efab
5 files changed
+263 -29

No files matched your search

@@ -1,6 +1,10 @@
package com.bsd.pjcloud.supermarket.dto.erpspu;
import com.alibaba.excel.annotation.ExcelProperty;
import com.bsd.pjcloud.common.core.util.MoneyDeserializer;
import com.bsd.pjcloud.common.core.util.MoneySerializer;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import lombok.Data;
@Data
@@ -24,7 +28,7 @@ public class SmErpSpuImportDto {
private String spec; // 规格
@ExcelProperty("库存")
private Integer stock; // 库存
private Double stock; // 库存
@ExcelProperty("品牌")
private String brand; // 品牌
@@ -36,21 +40,29 @@ public class SmErpSpuImportDto {
private Integer packageNum; // 装数
@ExcelProperty("进价")
@JsonSerialize(using = MoneySerializer.class) // 分 -> 元
@JsonDeserialize(using = MoneyDeserializer.class) // 元 -> 分
private Integer purchasePrice; // 进价
@ExcelProperty("零售价")
@JsonSerialize(using = MoneySerializer.class) // 分 -> 元
@JsonDeserialize(using = MoneyDeserializer.class) // 元 -> 分
private Integer retailPrice; // 零售价
@ExcelProperty("货商")
private String supplier; // 货商
@ExcelProperty("促销价")
private Double promotionPrice; // 促销价
@JsonSerialize(using = MoneySerializer.class) // 分 -> 元
@JsonDeserialize(using = MoneyDeserializer.class) // 元 -> 分
private Integer promotionPrice; // 促销价
@ExcelProperty("商品性质")
private String commodityNature; // 商品性质
@ExcelProperty("成本单价")
@JsonSerialize(using = MoneySerializer.class) // 分 -> 元
@JsonDeserialize(using = MoneyDeserializer.class) // 元 -> 分
private Integer costPrice; // 成本单价
@ExcelProperty("库存上限")
@@ -116,7 +116,7 @@ public class SmErpSpuEntity extends Model<SmErpSpuEntity> {
*/
@Schema(description="库存")
@TableField(exist = false)
private Integer stock;
private Double stock;
/**
* 赠送积分
@@ -33,7 +33,7 @@ public class SmErpStockEntity extends Model<SmErpStockEntity> {
* 基础库存数量
*/
@Schema(description="基础库存数量")
private Integer baseStock;
private Double baseStock;
/**
* 乐观锁版本号
@@ -90,7 +90,7 @@ public class SmErpStockEntity extends Model<SmErpStockEntity> {
private Long tenantId;
@Schema(description="当前库存")
private Integer currentStock;
private Double currentStock;
/**
* 库存上限
@@ -35,7 +35,7 @@ public class SupermarketAppSpuDetailsVo {
* 库存
*/
@Schema(description="剩余库存")
private Integer stock;
private Double stock;
/**
@@ -124,14 +124,14 @@ public class SmErpSpuServiceImpl extends ServiceImpl<SmErpSpuMapper, SmErpSpuEnt
public R updateSpuById(SmErpSpuEntity supermarketSpu) {
baseMapper.updateById(supermarketSpu);
Integer stock = supermarketSpu.getStock();
Double stock = supermarketSpu.getStock();
//如果更新商品的期初库存,就需要计算后期商品出入库单据进行了多少数据
LambdaQueryWrapper<SmErpStockEntity> selectWStockWrapper = new LambdaQueryWrapper<>();
selectWStockWrapper.eq(SmErpStockEntity::getErpSpuId, supermarketSpu.getId());
SmErpStockEntity queryStock = smErpStockMapper.selectOne(selectWStockWrapper);
//得到单据进出的库存数量
int inventoryStockNum = queryStock.getCurrentStock() - queryStock.getBaseStock();
Double inventoryStockNum = queryStock.getCurrentStock() - queryStock.getBaseStock();
LambdaQueryWrapper<SmErpStockEntity> smErpStockEntityLambdaQueryWrapper = new LambdaQueryWrapper<>();
smErpStockEntityLambdaQueryWrapper.eq(SmErpStockEntity::getErpSpuId, supermarketSpu.getId());
@@ -668,27 +668,27 @@ public class SmErpSpuServiceImpl extends ServiceImpl<SmErpSpuMapper, SmErpSpuEnt
}
*/
private R buildImportResult(int total, int successCount, List<Map<String, Object>> errorList) {
Map<String, Object> result = new LinkedHashMap<>();
result.put("total", total);
result.put("successCount", successCount);
result.put("errorCount", errorList.size());
if (!errorList.isEmpty()) {
result.put("errors", errorList);
return R.failed(result,"部分数据导入失败");
}
return R.ok( result,"成功导入所有" + successCount + "条数据");
}
// 错误信息构建方法
private Map<String, Object> createErrorInfo(int row, String name, List<String> reasons) {
return new HashMap<String, Object>() {{
put("row", row);
put("supplierName", name);
put("reasons", reasons);
}};
}
@Override
// private R buildImportResult(int total, int successCount, List<Map<String, Object>> errorList) {
// Map<String, Object> result = new LinkedHashMap<>();
// result.put("total", total);
// result.put("successCount", successCount);
// result.put("errorCount", errorList.size());
//
// if (!errorList.isEmpty()) {
// result.put("errors", errorList);
// return R.failed(result,"部分数据导入失败");
// }
// return R.ok( result,"成功导入所有" + successCount + "条数据");
// }
// // 错误信息构建方法
// private Map<String, Object> createErrorInfo(int row, String name, List<String> reasons) {
// return new HashMap<String, Object>() {{
// put("row", row);
// put("supplierName", name);
// put("reasons", reasons);
// }};
// }
/* @Override
@Transactional(rollbackFor = Exception.class)
public R importErpSpu(List<SmErpSpuImportDto> smErpSpuImportDtos, BindingResult bindingResult) {
if (CollectionUtils.isEmpty(smErpSpuImportDtos)) {
@@ -869,9 +869,231 @@ public class SmErpSpuServiceImpl extends ServiceImpl<SmErpSpuMapper, SmErpSpuEnt
}
*/
@Override
@Transactional(rollbackFor = Exception.class)
public R importErpSpu(List<SmErpSpuImportDto> smErpSpuImportDtos, BindingResult bindingResult) {
if (CollectionUtils.isEmpty(smErpSpuImportDtos)) {
return R.failed("导入数据不能为空");
}
List<Map<String, Object>> errorList = new ArrayList<>();
List<SmErpSpuEntity> spuBatch = new ArrayList<>();
Map<String, SmErpSpuEntity> productCodeToSpuMap = new HashMap<>();
// 第一阶段:处理商品主数据
for (int i = 0; i < smErpSpuImportDtos.size(); i++) {
int rowNumber = i + 1;
SmErpSpuImportDto dto = smErpSpuImportDtos.get(i);
List<String> errorReasons = new ArrayList<>();
String productCode = dto.getProductCode();
try {
// 数据校验
List<String> validationErrors = ErpSpuValidator.validate(dto, rowNumber);
if (!validationErrors.isEmpty()) {
errorList.add(createErrorInfo(rowNumber, productCode, validationErrors));
continue;
}
// 处理分类(带完整错误处理)
Long categoryId = resolveCategory(
dto.getClassification(),
errorReasons,
rowNumber,
productCode
);
if (categoryId == null) {
errorList.add(createErrorInfo(rowNumber, productCode, errorReasons));
continue;
}
//todo 处理货商
// 构建商品实体
SmErpSpuEntity spu = new SmErpSpuEntity();
org.springframework.beans.BeanUtils.copyProperties(dto, spu);
spu.setProductNature("电子称称重商品".equals(dto.getCommodityNature()) ? "2" : "1");
spu.setCategoryId(categoryId);
spuBatch.add(spu);
productCodeToSpuMap.put(productCode, spu);
} catch (Exception e) {
errorReasons.add("系统异常: " + e.getMessage());
errorList.add(createErrorInfo(rowNumber, productCode, errorReasons));
}
}
// 批量保存商品(生成ID)
try {
if (!spuBatch.isEmpty()) {
this.saveBatch(spuBatch); // MyBatis-Plus批量插入
}
} catch (Exception e) {
throw new RuntimeException("商品批量保存失败", e);
}
// 第二阶段:处理关联数据
List<SmErpUnitEntity> unitBatch = new ArrayList<>();
List<SmErpStockEntity> stockBatch = new ArrayList<>();
List<SmErpAuxiliaryCodeEntity> codeBatch = new ArrayList<>();
for (int i = 0; i < smErpSpuImportDtos.size(); i++) {
int rowNumber = i + 1;
SmErpSpuImportDto dto = smErpSpuImportDtos.get(i);
String productCode = dto.getProductCode();
List<String> errorReasons = new ArrayList<>();
try {
// 跳过已记录错误的数据
if (errorList.stream().anyMatch(e ->
e.get("productCode").equals(productCode) &&
(int)e.get("row") == rowNumber)) {
continue;
}
// 获取已插入的商品
SmErpSpuEntity spu = productCodeToSpuMap.get(productCode);
if (spu == null || spu.getId() == null) {
errorReasons.add("商品数据不存在或ID未生成");
errorList.add(createErrorInfo(rowNumber, productCode, errorReasons));
continue;
}
// 处理单位数据
SmErpUnitEntity unit = new SmErpUnitEntity();
org.springframework.beans.BeanUtils.copyProperties(dto, unit);
unit.setSpuId(spu.getId());
unit.setIsBase(true);
unitBatch.add(unit);
// 处理库存数据
SmErpStockEntity stock = new SmErpStockEntity();
org.springframework.beans.BeanUtils.copyProperties(dto, stock);
stock.setErpSpuId(spu.getId());
stock.setCurrentStock(dto.getStock());
stock.setBaseStock(dto.getStock());
stockBatch.add(stock);
} catch (Exception e) {
errorReasons.add("关联数据处理失败: " + e.getMessage());
errorList.add(createErrorInfo(rowNumber, productCode, errorReasons));
}
}
// 第三阶段:批量保存单位(生成单位ID)
try {
if (!unitBatch.isEmpty()) {
smErpUnitService.saveBatch(unitBatch);
}
} catch (Exception e) {
throw new RuntimeException("单位批量保存失败", e);
}
// 第四阶段:处理条码(需要单位ID)
for (int i = 0; i < unitBatch.size(); i++) {
SmErpUnitEntity unit = unitBatch.get(i);
SmErpSpuImportDto dto = smErpSpuImportDtos.get(i);
List<String> errorReasons = new ArrayList<>();
try {
if (unit.getId() == null) {
errorReasons.add("单位ID未生成");
errorList.add(createErrorInfo(i + 1, dto.getProductCode(), errorReasons));
continue;
}
SmErpAuxiliaryCodeEntity code = new SmErpAuxiliaryCodeEntity();
code.setBarCode(dto.getBarCode());
code.setSpuId(unit.getSpuId());
code.setUnitId(unit.getId());
codeBatch.add(code);
} catch (Exception e) {
errorReasons.add("条码处理失败: " + e.getMessage());
errorList.add(createErrorInfo(i + 1, dto.getProductCode(), errorReasons));
}
}
// 最终批量保存
try {
if (!stockBatch.isEmpty()) {
smErpStockService.saveBatch(stockBatch);
}
if (!codeBatch.isEmpty()) {
smErpAuxiliaryCodeService.saveBatch(codeBatch);
}
} catch (Exception e) {
throw new RuntimeException("最终数据保存失败", e);
}
return buildImportResult(smErpSpuImportDtos.size(), productCodeToSpuMap.size(), errorList);
}
// 分类处理(完整实现)
private Long resolveCategory(String categoryName,
List<String> errorReasons,
int rowNumber,
String productCode) {
try {
// 查询现有分类
SmErpCategoryEntity existCategory = smErpCategoryMapper.selectOne(
new LambdaQueryWrapper<SmErpCategoryEntity>()
.eq(SmErpCategoryEntity::getName, categoryName)
);
if (existCategory != null) {
return existCategory.getId();
}
// 创建新分类
SmErpCategoryEntity newCategory = new SmErpCategoryEntity();
newCategory.setName(categoryName);
newCategory.setStatus("0");
int insertResult = smErpCategoryMapper.insert(newCategory);
if (insertResult > 0) {
return newCategory.getId();
}
errorReasons.add("分类创建失败");
return null;
} catch (DuplicateKeyException e) {
// 处理并发创建冲突
SmErpCategoryEntity conflictCategory = smErpCategoryMapper.selectOne(
new LambdaQueryWrapper<SmErpCategoryEntity>()
.eq(SmErpCategoryEntity::getName, categoryName)
);
return conflictCategory != null ? conflictCategory.getId() : null;
} catch (Exception e) {
errorReasons.add("分类处理异常: " + e.getMessage());
return null;
}
}
// 错误信息构建(完整实现)
private Map<String, Object> createErrorInfo(int row, String productCode, List<String> reasons) {
Map<String, Object> errorInfo = new LinkedHashMap<>();
errorInfo.put("row", row);
errorInfo.put("productCode", productCode);
errorInfo.put("reasons", new ArrayList<>(reasons)); // 防止列表被修改
return errorInfo;
}
// 结果构建(完整实现)
private R buildImportResult(int total, int successCount, List<Map<String, Object>> errorList) {
Map<String, Object> result = new LinkedHashMap<>();
result.put("total", total);
result.put("successCount", successCount);
result.put("errorCount", errorList.size());
if (!errorList.isEmpty()) {
result.put("errors", errorList);
return R.failed(result, "部分数据导入失败");
}
return R.ok(result, "成功导入" + successCount + "条数据");
}
public void asyncExecuteImport(String taskId, List<SmErpSpuImportDto> dtos) {