diff --git a/pjcloud-supermarket/pjcloud-supermarket-api/src/main/java/com/bsd/pjcloud/supermarket/dto/erpspu/SmErpSpuImportDto.java b/pjcloud-supermarket/pjcloud-supermarket-api/src/main/java/com/bsd/pjcloud/supermarket/dto/erpspu/SmErpSpuImportDto.java index 27cdccbd9..c569c3b76 100644 --- a/pjcloud-supermarket/pjcloud-supermarket-api/src/main/java/com/bsd/pjcloud/supermarket/dto/erpspu/SmErpSpuImportDto.java +++ b/pjcloud-supermarket/pjcloud-supermarket-api/src/main/java/com/bsd/pjcloud/supermarket/dto/erpspu/SmErpSpuImportDto.java @@ -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("库存上限") diff --git a/pjcloud-supermarket/pjcloud-supermarket-api/src/main/java/com/bsd/pjcloud/supermarket/entity/SmErpSpuEntity.java b/pjcloud-supermarket/pjcloud-supermarket-api/src/main/java/com/bsd/pjcloud/supermarket/entity/SmErpSpuEntity.java index 2d2f288e5..909738c1b 100644 --- a/pjcloud-supermarket/pjcloud-supermarket-api/src/main/java/com/bsd/pjcloud/supermarket/entity/SmErpSpuEntity.java +++ b/pjcloud-supermarket/pjcloud-supermarket-api/src/main/java/com/bsd/pjcloud/supermarket/entity/SmErpSpuEntity.java @@ -116,7 +116,7 @@ public class SmErpSpuEntity extends Model { */ @Schema(description="库存") @TableField(exist = false) - private Integer stock; + private Double stock; /** * 赠送积分 diff --git a/pjcloud-supermarket/pjcloud-supermarket-api/src/main/java/com/bsd/pjcloud/supermarket/entity/SmErpStockEntity.java b/pjcloud-supermarket/pjcloud-supermarket-api/src/main/java/com/bsd/pjcloud/supermarket/entity/SmErpStockEntity.java index 58c36c36a..fccb9ec46 100644 --- a/pjcloud-supermarket/pjcloud-supermarket-api/src/main/java/com/bsd/pjcloud/supermarket/entity/SmErpStockEntity.java +++ b/pjcloud-supermarket/pjcloud-supermarket-api/src/main/java/com/bsd/pjcloud/supermarket/entity/SmErpStockEntity.java @@ -33,7 +33,7 @@ public class SmErpStockEntity extends Model { * 基础库存数量 */ @Schema(description="基础库存数量") - private Integer baseStock; + private Double baseStock; /** * 乐观锁版本号 @@ -90,7 +90,7 @@ public class SmErpStockEntity extends Model { private Long tenantId; @Schema(description="当前库存") - private Integer currentStock; + private Double currentStock; /** * 库存上限 diff --git a/pjcloud-supermarket/pjcloud-supermarket-api/src/main/java/com/bsd/pjcloud/supermarket/vo/app/SupermarketAppSpuDetailsVo.java b/pjcloud-supermarket/pjcloud-supermarket-api/src/main/java/com/bsd/pjcloud/supermarket/vo/app/SupermarketAppSpuDetailsVo.java index 4ff20f5f3..0faac082a 100644 --- a/pjcloud-supermarket/pjcloud-supermarket-api/src/main/java/com/bsd/pjcloud/supermarket/vo/app/SupermarketAppSpuDetailsVo.java +++ b/pjcloud-supermarket/pjcloud-supermarket-api/src/main/java/com/bsd/pjcloud/supermarket/vo/app/SupermarketAppSpuDetailsVo.java @@ -35,7 +35,7 @@ public class SupermarketAppSpuDetailsVo { * 库存 */ @Schema(description="剩余库存") - private Integer stock; + private Double stock; /** diff --git a/pjcloud-supermarket/pjcloud-supermarket-biz/src/main/java/com/bsd/pjcloud/supermarket/service/impl/SmErpSpuServiceImpl.java b/pjcloud-supermarket/pjcloud-supermarket-biz/src/main/java/com/bsd/pjcloud/supermarket/service/impl/SmErpSpuServiceImpl.java index 78ec4f74e..6b4511037 100644 --- a/pjcloud-supermarket/pjcloud-supermarket-biz/src/main/java/com/bsd/pjcloud/supermarket/service/impl/SmErpSpuServiceImpl.java +++ b/pjcloud-supermarket/pjcloud-supermarket-biz/src/main/java/com/bsd/pjcloud/supermarket/service/impl/SmErpSpuServiceImpl.java @@ -124,14 +124,14 @@ public class SmErpSpuServiceImpl extends ServiceImpl 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 smErpStockEntityLambdaQueryWrapper = new LambdaQueryWrapper<>(); smErpStockEntityLambdaQueryWrapper.eq(SmErpStockEntity::getErpSpuId, supermarketSpu.getId()); @@ -668,27 +668,27 @@ public class SmErpSpuServiceImpl extends ServiceImpl> errorList) { - Map 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 createErrorInfo(int row, String name, List reasons) { - return new HashMap() {{ - put("row", row); - put("supplierName", name); - put("reasons", reasons); - }}; - } - @Override +// private R buildImportResult(int total, int successCount, List> errorList) { +// Map 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 createErrorInfo(int row, String name, List reasons) { +// return new HashMap() {{ +// put("row", row); +// put("supplierName", name); +// put("reasons", reasons); +// }}; +// } + /* @Override @Transactional(rollbackFor = Exception.class) public R importErpSpu(List smErpSpuImportDtos, BindingResult bindingResult) { if (CollectionUtils.isEmpty(smErpSpuImportDtos)) { @@ -869,9 +869,231 @@ public class SmErpSpuServiceImpl extends ServiceImpl smErpSpuImportDtos, BindingResult bindingResult) { + if (CollectionUtils.isEmpty(smErpSpuImportDtos)) { + return R.failed("导入数据不能为空"); + } + List> errorList = new ArrayList<>(); + List spuBatch = new ArrayList<>(); + Map productCodeToSpuMap = new HashMap<>(); + + // 第一阶段:处理商品主数据 + for (int i = 0; i < smErpSpuImportDtos.size(); i++) { + int rowNumber = i + 1; + SmErpSpuImportDto dto = smErpSpuImportDtos.get(i); + List errorReasons = new ArrayList<>(); + String productCode = dto.getProductCode(); + + try { + // 数据校验 + List 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 unitBatch = new ArrayList<>(); + List stockBatch = new ArrayList<>(); + List 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 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 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 errorReasons, + int rowNumber, + String productCode) { + try { + // 查询现有分类 + SmErpCategoryEntity existCategory = smErpCategoryMapper.selectOne( + new LambdaQueryWrapper() + .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() + .eq(SmErpCategoryEntity::getName, categoryName) + ); + return conflictCategory != null ? conflictCategory.getId() : null; + + } catch (Exception e) { + errorReasons.add("分类处理异常: " + e.getMessage()); + return null; + } + } + + // 错误信息构建(完整实现) + private Map createErrorInfo(int row, String productCode, List reasons) { + Map 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> errorList) { + Map 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 dtos) {