Merge branch 'master' of http://gitea.zianxin.com/zianxin-tec/biz-api-cloud
This commit is contained in:
commit
254f074c52
15 files changed
+1182
-15
No files matched your search
+71
@@ -0,0 +1,71 @@
|
||||
package com.bsd.pjcloud.supermarket.dto.erpspu;
|
||||
|
||||
import com.alibaba.excel.annotation.ExcelProperty;
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
public class SmErpSpuImportDto {
|
||||
@ExcelProperty("货号")
|
||||
private String productCode; // 货号
|
||||
|
||||
@ExcelProperty("自编码/条码")
|
||||
private String barCode; // 自编码/条码
|
||||
|
||||
@ExcelProperty("商品名称")
|
||||
private String productName; // 商品名称
|
||||
|
||||
@ExcelProperty("单位")
|
||||
private String unit; // 单位
|
||||
|
||||
@ExcelProperty("产地")
|
||||
private String origin; // 产地
|
||||
|
||||
@ExcelProperty("规格")
|
||||
private String spec; // 规格
|
||||
|
||||
@ExcelProperty("库存")
|
||||
private Integer stock; // 库存
|
||||
|
||||
@ExcelProperty("品牌")
|
||||
private String brand; // 品牌
|
||||
|
||||
@ExcelProperty("分类")
|
||||
private String classification; // 分类
|
||||
|
||||
@ExcelProperty("装数")
|
||||
private Integer packageNum; // 装数
|
||||
|
||||
@ExcelProperty("进价")
|
||||
private Integer purchasePrice; // 进价
|
||||
|
||||
@ExcelProperty("零售价")
|
||||
private Integer retailPrice; // 零售价
|
||||
|
||||
@ExcelProperty("货商")
|
||||
private String supplier; // 货商
|
||||
|
||||
@ExcelProperty("促销价")
|
||||
private Double promotionPrice; // 促销价
|
||||
|
||||
@ExcelProperty("商品性质")
|
||||
private String commodityNature; // 商品性质
|
||||
|
||||
@ExcelProperty("成本单价")
|
||||
private Integer costPrice; // 成本单价
|
||||
|
||||
@ExcelProperty("库存上限")
|
||||
private int inventoryUpperLimit; // 库存上限
|
||||
|
||||
@ExcelProperty("库存下限")
|
||||
private int inventoryLowerLimit; // 库存下限
|
||||
|
||||
@ExcelProperty("毛利率%")
|
||||
private Double grossProfitRate; // 毛利率%
|
||||
|
||||
@ExcelProperty("辅助条码")
|
||||
private String auxiliaryBarcode; // 辅助条码
|
||||
|
||||
@ExcelProperty("停销")
|
||||
private Boolean discontinued; // 停销
|
||||
|
||||
}
|
||||
+3
-3
@@ -33,7 +33,7 @@ public class SmErpSupplierImportDto {
|
||||
@ExcelProperty("开户行及帐号")
|
||||
private String bankAccount;
|
||||
|
||||
@ExcelProperty("货商类别")
|
||||
@ExcelProperty("货商类")
|
||||
private String supplierCategory;
|
||||
|
||||
@ExcelProperty("货商地区")
|
||||
@@ -42,8 +42,8 @@ public class SmErpSupplierImportDto {
|
||||
@ExcelProperty("建档人")
|
||||
private String creator;
|
||||
|
||||
@ExcelProperty("状态")
|
||||
private String status;
|
||||
// @ExcelProperty("状态")
|
||||
// private String status;
|
||||
|
||||
@ExcelProperty("期初应付款")
|
||||
private Double initialPayable;
|
||||
|
||||
+1
@@ -3,6 +3,7 @@ package com.bsd.pjcloud.supermarket.entity;
|
||||
import com.baomidou.mybatisplus.annotation.*;
|
||||
import com.baomidou.mybatisplus.extension.activerecord.Model;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import com.bsd.pjcloud.common.core.util.TenantTable;
|
||||
|
||||
+1
-1
@@ -81,7 +81,7 @@ public class SmErpSupplierEntity extends Model<SmErpSupplierEntity> {
|
||||
* 货商类别
|
||||
*/
|
||||
@Schema(description="货商类别")
|
||||
private String supplierType;
|
||||
private Long supplierType;
|
||||
|
||||
/**
|
||||
* 货商地区
|
||||
|
||||
+21
@@ -0,0 +1,21 @@
|
||||
package com.bsd.pjcloud.supermarket.task;
|
||||
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
|
||||
|
||||
import java.util.concurrent.Executor;
|
||||
|
||||
@Configuration
|
||||
public class AsyncConfig {
|
||||
@Bean("importExecutor")
|
||||
public Executor asyncExecutor() {
|
||||
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
|
||||
executor.setCorePoolSize(4);
|
||||
executor.setMaxPoolSize(8);
|
||||
executor.setQueueCapacity(100);
|
||||
executor.setThreadNamePrefix("import-");
|
||||
executor.initialize();
|
||||
return executor;
|
||||
}
|
||||
}
|
||||
+20
@@ -0,0 +1,20 @@
|
||||
package com.bsd.pjcloud.supermarket.task;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@Data
|
||||
public class ImportTask {
|
||||
private String taskId;
|
||||
private String status; // PENDING, PROCESSING, COMPLETED, FAILED
|
||||
private LocalDateTime createTime;
|
||||
private LocalDateTime finishTime;
|
||||
private int total;
|
||||
private int success;
|
||||
private int error;
|
||||
private List<Map<String, Object>> errors = new ArrayList<>();
|
||||
}
|
||||
+36
@@ -0,0 +1,36 @@
|
||||
package com.bsd.pjcloud.supermarket.task;
|
||||
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
@Service
|
||||
public class TaskStoreService {
|
||||
private final Map<String, ImportTask> tasks = new ConcurrentHashMap<>();
|
||||
|
||||
public String createTask(int total) {
|
||||
String taskId = "TASK-" + UUID.randomUUID().toString().substring(0, 8);
|
||||
ImportTask task = new ImportTask();
|
||||
task.setTaskId(taskId);
|
||||
task.setStatus("PENDING");
|
||||
task.setCreateTime(LocalDateTime.now());
|
||||
task.setTotal(total);
|
||||
tasks.put(taskId, task);
|
||||
return taskId;
|
||||
}
|
||||
|
||||
public void updateTask(String taskId, Consumer<ImportTask> updater) {
|
||||
ImportTask task = tasks.get(taskId);
|
||||
if (task != null) {
|
||||
updater.accept(task);
|
||||
}
|
||||
}
|
||||
|
||||
public ImportTask getTask(String taskId) {
|
||||
return tasks.get(taskId);
|
||||
}
|
||||
}
|
||||
+45
@@ -0,0 +1,45 @@
|
||||
package com.bsd.pjcloud.supermarket.validarot;
|
||||
|
||||
|
||||
import com.alibaba.excel.util.StringUtils;
|
||||
import com.bsd.pjcloud.supermarket.dto.erpspu.SmErpSpuImportDto;
|
||||
import com.bsd.pjcloud.supermarket.dto.supplier.SmErpSupplierImportDto;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class ErpSpuValidator {
|
||||
public static List<String> validate(SmErpSpuImportDto entity, int rowIndex) {
|
||||
List<String> errors = new ArrayList<>();
|
||||
|
||||
if (StringUtils.isEmpty(entity.getProductCode())) {
|
||||
errors.add("第" + (rowIndex + 1) + "行: 货号不能为空");
|
||||
}
|
||||
if (StringUtils.isEmpty(entity.getProductName())) {
|
||||
errors.add("第" + (rowIndex + 1) + "行: 商品名称不能为空");
|
||||
}
|
||||
if (StringUtils.isEmpty(entity.getUnit())) {
|
||||
errors.add("第" + (rowIndex + 1) + "行: 单位不能为空");
|
||||
}
|
||||
if (StringUtils.isEmpty(entity.getSpec())) {
|
||||
errors.add("第" + (rowIndex + 1) + "行: 规格不能为空");
|
||||
}
|
||||
if (StringUtils.isEmpty(entity.getClassification())) {
|
||||
errors.add("第" + (rowIndex + 1) + "行: 分类不能为空");
|
||||
}
|
||||
if (StringUtils.isEmpty(entity.getCommodityNature())) {
|
||||
errors.add("第" + (rowIndex + 1) + "行: 商品性质不能为空");
|
||||
}
|
||||
if (StringUtils.isEmpty(entity.getSupplier())) {
|
||||
errors.add("第" + (rowIndex + 1) + "行: 货商不能为空");
|
||||
}
|
||||
if (null==entity.getPurchasePrice()) {
|
||||
errors.add("第" + (rowIndex + 1) + "行: 进价不能为空");
|
||||
}
|
||||
if (null==entity.getRetailPrice()) {
|
||||
errors.add("第" + (rowIndex + 1) + "行: 零售价不能为空");
|
||||
}
|
||||
|
||||
return errors;
|
||||
}
|
||||
}
|
||||
+22
@@ -0,0 +1,22 @@
|
||||
package com.bsd.pjcloud.supermarket.validarot;
|
||||
|
||||
|
||||
import com.bsd.pjcloud.supermarket.dto.supplier.SmErpSupplierImportDto;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class SupplierValidator {
|
||||
public static List<String> validate(SmErpSupplierImportDto entity, int rowIndex) {
|
||||
List<String> errors = new ArrayList<>();
|
||||
|
||||
if (entity.getSupplierName() == null || entity.getSupplierName().isEmpty()) {
|
||||
errors.add("第" + (rowIndex + 1) + "行: 货商名称不能为空");
|
||||
}
|
||||
// if (entity.getPhone()== null || entity.getPhone().isEmpty()) {
|
||||
// errors.add("第" + (rowIndex + 1) + "行: 电话不能为空");
|
||||
// }
|
||||
return errors;
|
||||
}
|
||||
}
|
||||
+37
-6
@@ -1,31 +1,30 @@
|
||||
package com.bsd.pjcloud.supermarket.controller;
|
||||
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.hutool.core.util.ArrayUtil;
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.bsd.pjcloud.common.core.util.BeanUtils;
|
||||
import com.bsd.pjcloud.common.core.util.R;
|
||||
import com.bsd.pjcloud.common.excel.annotation.RequestExcel;
|
||||
import com.bsd.pjcloud.common.log.annotation.SysLog;
|
||||
import com.bsd.pjcloud.common.security.util.SecurityUtils;
|
||||
import com.bsd.pjcloud.supermarket.dto.SupermarketSpuAppQueryDTO;
|
||||
import com.bsd.pjcloud.supermarket.dto.SupermarketSpuQueryDTO;
|
||||
import com.bsd.pjcloud.supermarket.dto.SupermarketSpuUpdateStockReqDTO;
|
||||
import com.bsd.pjcloud.supermarket.dto.erpspu.SmErpSpuImportDto;
|
||||
import com.bsd.pjcloud.supermarket.entity.SmErpAuxiliaryCodeEntity;
|
||||
import com.bsd.pjcloud.supermarket.entity.SmErpSpuEntity;
|
||||
import com.bsd.pjcloud.supermarket.entity.SmErpStockEntity;
|
||||
import com.bsd.pjcloud.supermarket.entity.SmErpUnitEntity;
|
||||
import com.bsd.pjcloud.supermarket.service.*;
|
||||
import com.bsd.pjcloud.supermarket.vo.app.SupermarketAppSpuVo;
|
||||
import com.bsd.pjcloud.supermarket.task.TaskStoreService;
|
||||
import com.bsd.pjcloud.supermarket.vo.erpspu.SmErpSpuSimpleVo;
|
||||
import com.bsd.pjcloud.supermarket.vo.stockwarn.StockWarnVO;
|
||||
import com.github.yulichang.toolkit.JoinWrappers;
|
||||
import com.github.yulichang.wrapper.MPJLambdaWrapper;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.beans.factory.annotation.Qualifier;
|
||||
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import com.bsd.pjcloud.common.excel.annotation.ResponseExcel;
|
||||
import io.swagger.v3.oas.annotations.security.SecurityRequirement;
|
||||
@@ -35,9 +34,14 @@ import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import org.springframework.validation.BindingResult;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* 商品spu
|
||||
@@ -62,6 +66,12 @@ public class SmErpSpuController {
|
||||
|
||||
private final SmErpStockService smErpStockService;
|
||||
|
||||
|
||||
private final TaskStoreService taskStoreService;
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 分页查询
|
||||
* @param page 分页对象
|
||||
@@ -211,6 +221,27 @@ public class SmErpSpuController {
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 导入
|
||||
*
|
||||
* @param
|
||||
* @param bindingResult 错误信息列表
|
||||
* @return R
|
||||
*/
|
||||
@PostMapping("/import")
|
||||
@PreAuthorize("@pms.hasPermission('supermarket_supermarketSpu_export')" )
|
||||
public R importErpSpu(@RequestExcel List<SmErpSpuImportDto> dtos, BindingResult bindingResult) {
|
||||
List<SmErpSpuImportDto> collect = dtos.stream().filter(smErpSpuImportDto -> smErpSpuImportDto.getProductCode() == null).collect(Collectors.toList());
|
||||
// String taskId = taskStoreService.createTask(dtos.size());
|
||||
// smErpSpuService.asyncExecuteImport(taskId, collect);
|
||||
// return R.ok(Collections.singletonMap("taskId", taskId));
|
||||
System.out.println(collect);
|
||||
List<SmErpSpuImportDto> collect1 = dtos.stream().filter(smErpSpuImportDto -> StringUtils.isBlank(smErpSpuImportDto.getClassification())).collect(Collectors.toList());
|
||||
System.out.println(collect1);
|
||||
return smErpSpuService.importErpSpu(dtos, bindingResult);
|
||||
}
|
||||
|
||||
|
||||
// --------APP-----------------
|
||||
|
||||
|
||||
|
||||
+18
@@ -6,10 +6,14 @@ import cn.hutool.core.collection.CollUtil;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.bsd.pjcloud.admin.api.vo.UserExcelVO;
|
||||
import com.bsd.pjcloud.common.core.util.BeanUtils;
|
||||
import com.bsd.pjcloud.common.core.util.R;
|
||||
import com.bsd.pjcloud.common.excel.annotation.RequestExcel;
|
||||
import com.bsd.pjcloud.common.log.annotation.SysLog;
|
||||
import com.bsd.pjcloud.common.security.annotation.HasPermission;
|
||||
import com.bsd.pjcloud.common.security.util.SecurityUtils;
|
||||
import com.bsd.pjcloud.supermarket.dto.supplier.SmErpSupplierImportDto;
|
||||
import com.bsd.pjcloud.supermarket.entity.SmErpSupplierEntity;
|
||||
import com.bsd.pjcloud.supermarket.service.SmErpSupplierService;
|
||||
import com.bsd.pjcloud.supermarket.vo.erp.SmErpSupplierSimpleVo;
|
||||
@@ -21,6 +25,7 @@ import org.springframework.http.HttpHeaders;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.validation.BindingResult;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.List;
|
||||
@@ -135,4 +140,17 @@ public class SmErpSupplierController {
|
||||
List<SmErpSupplierSimpleVo> bean = BeanUtils.toBean(list, SmErpSupplierSimpleVo.class);
|
||||
return R.ok(bean);
|
||||
}
|
||||
|
||||
/**
|
||||
* 导入
|
||||
*
|
||||
* @param smErpSupplierImportDtos 用户列表
|
||||
* @param bindingResult 错误信息列表
|
||||
* @return R
|
||||
*/
|
||||
@PostMapping("/import")
|
||||
// @PreAuthorize("@pms.hasPermission('supermarketerp_smErpSupplier_import')" )
|
||||
public R importUser(@RequestExcel List<SmErpSupplierImportDto> smErpSupplierImportDtos, BindingResult bindingResult) {
|
||||
return smErpSupplierService.importSupplier(smErpSupplierImportDtos, bindingResult);
|
||||
}
|
||||
}
|
||||
+17
@@ -7,9 +7,11 @@ import com.bsd.pjcloud.common.core.util.R;
|
||||
import com.bsd.pjcloud.supermarket.dto.SupermarketSpuQueryDTO;
|
||||
import com.bsd.pjcloud.supermarket.dto.SupermarketSpuUpdateStockReqDTO;
|
||||
import com.bsd.pjcloud.supermarket.dto.cgplan.ErpCgPlanDTO;
|
||||
import com.bsd.pjcloud.supermarket.dto.erpspu.SmErpSpuImportDto;
|
||||
import com.bsd.pjcloud.supermarket.entity.SmErpSpuEntity;
|
||||
import com.bsd.pjcloud.supermarket.vo.cgplan.ErpSpuWithUnitPageVo;
|
||||
import com.bsd.pjcloud.supermarket.vo.sm.smspu.SmErpPageScopeVo;
|
||||
import org.springframework.validation.BindingResult;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
@@ -85,4 +87,19 @@ public interface SmErpSpuService extends IService<SmErpSpuEntity> {
|
||||
* @return
|
||||
*/
|
||||
List<SmErpSpuEntity> ListScope(LambdaQueryWrapper<SmErpSpuEntity> wrapper);
|
||||
|
||||
|
||||
/**
|
||||
* 导入
|
||||
* @param smErpSupplierImportDtos
|
||||
* @param bindingResult
|
||||
* @return
|
||||
*/
|
||||
R importErpSpu(List<SmErpSpuImportDto> smErpSupplierImportDtos, BindingResult bindingResult);
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void asyncExecuteImport(String taskId, List<SmErpSpuImportDto> dtos);
|
||||
}
|
||||
+12
@@ -3,7 +3,10 @@ package com.bsd.pjcloud.supermarket.service;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
import com.bsd.pjcloud.common.core.util.R;
|
||||
import com.bsd.pjcloud.supermarket.dto.supplier.SmErpSupplierImportDto;
|
||||
import com.bsd.pjcloud.supermarket.entity.SmErpSupplierEntity;
|
||||
import org.springframework.validation.BindingResult;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@@ -24,4 +27,13 @@ public interface SmErpSupplierService extends IService<SmErpSupplierEntity> {
|
||||
* @return
|
||||
*/
|
||||
Object pageScope(Page page, LambdaQueryWrapper<SmErpSupplierEntity> wrapper);
|
||||
|
||||
|
||||
/**
|
||||
* 导入
|
||||
* @param smErpSupplierImportDtos
|
||||
* @param bindingResult
|
||||
* @return
|
||||
*/
|
||||
R importSupplier(List<SmErpSupplierImportDto> smErpSupplierImportDtos, BindingResult bindingResult);
|
||||
}
|
||||
+667
-4
@@ -13,15 +13,18 @@ import com.bsd.pjcloud.supermarket.constant.OrderTypeEnum;
|
||||
import com.bsd.pjcloud.supermarket.dto.SupermarketSpuQueryDTO;
|
||||
import com.bsd.pjcloud.supermarket.dto.SupermarketSpuUpdateStockReqDTO;
|
||||
import com.bsd.pjcloud.supermarket.dto.cgplan.ErpCgPlanDTO;
|
||||
import com.bsd.pjcloud.supermarket.dto.erpspu.SmErpSpuImportDto;
|
||||
import com.bsd.pjcloud.supermarket.dto.inventoryrecords.UpdateStockDTO;
|
||||
import com.bsd.pjcloud.supermarket.dto.supplier.SmErpSupplierImportDto;
|
||||
import com.bsd.pjcloud.supermarket.entity.*;
|
||||
import com.bsd.pjcloud.supermarket.mapper.SmErpCategoryMapper;
|
||||
import com.bsd.pjcloud.supermarket.mapper.SmErpSpuMapper;
|
||||
import com.bsd.pjcloud.supermarket.mapper.SmErpStockMapper;
|
||||
import com.bsd.pjcloud.supermarket.mapper.SmSpuMapper;
|
||||
import com.bsd.pjcloud.supermarket.service.SmErpAuxiliaryCodeService;
|
||||
import com.bsd.pjcloud.supermarket.service.SmErpSpuService;
|
||||
import com.bsd.pjcloud.supermarket.service.SmErpStockService;
|
||||
import com.bsd.pjcloud.supermarket.service.SmErpUnitService;
|
||||
import com.bsd.pjcloud.supermarket.service.*;
|
||||
import com.bsd.pjcloud.supermarket.task.TaskStoreService;
|
||||
import com.bsd.pjcloud.supermarket.validarot.ErpSpuValidator;
|
||||
import com.bsd.pjcloud.supermarket.validarot.SupplierValidator;
|
||||
import com.bsd.pjcloud.supermarket.vo.app.SupermarketAppSpuDetailsVo;
|
||||
import com.bsd.pjcloud.supermarket.vo.app.SupermarketAppUnitVo;
|
||||
import com.bsd.pjcloud.supermarket.vo.erp.SmErpAuxiliaryCodeVo;
|
||||
@@ -34,11 +37,17 @@ import lombok.AllArgsConstructor;
|
||||
import org.apache.commons.collections4.CollectionUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Qualifier;
|
||||
import org.springframework.dao.DuplicateKeyException;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import org.springframework.validation.BindingResult;
|
||||
|
||||
import java.time.LocalDate;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.Executor;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
@@ -61,9 +70,21 @@ public class SmErpSpuServiceImpl extends ServiceImpl<SmErpSpuMapper, SmErpSpuEnt
|
||||
|
||||
private final SmErpStockService smErpStockService;
|
||||
|
||||
private final SmErpCategoryMapper smErpCategoryMapper;
|
||||
|
||||
private final SmErpCategoryService smCategoryService;
|
||||
|
||||
|
||||
@Autowired
|
||||
private Sequence sequence;
|
||||
|
||||
@Autowired
|
||||
@Qualifier("importExecutor")
|
||||
private Executor executor;
|
||||
|
||||
@Autowired
|
||||
private TaskStoreService taskStoreService;
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public R saveSpu(SmErpSpuEntity supermarketSpu) {
|
||||
@@ -333,4 +354,646 @@ public class SmErpSpuServiceImpl extends ServiceImpl<SmErpSpuMapper, SmErpSpuEnt
|
||||
List<SmErpSpuEntity> smErpSpuEntities = baseMapper.selectListByScope(wrapper, DataScope.of());
|
||||
return smErpSpuEntities;
|
||||
}
|
||||
|
||||
/* @Override
|
||||
@Transactional
|
||||
public R importErpSpu(List<SmErpSpuImportDto> smErpSpuImportDtos, BindingResult bindingResult) {
|
||||
if (CollectionUtils.isEmpty(smErpSpuImportDtos)) {
|
||||
return R.failed("导入数据不能为空");
|
||||
}
|
||||
List<Map<String, Object>> errorList = new ArrayList<>();
|
||||
List<SmErpSupplierEntity> successList = new ArrayList<>();
|
||||
for (int i = 0; i < smErpSpuImportDtos.size(); i++) {
|
||||
int rowNumber = i + 1;
|
||||
SmErpSpuImportDto dto = smErpSpuImportDtos.get(i);
|
||||
List<String> errorReasons = new ArrayList<>();
|
||||
// 数据校验阶段
|
||||
List<String> validationErrors = ErpSpuValidator.validate(dto, rowNumber);
|
||||
String productCode = dto.getProductCode();
|
||||
if (!validationErrors.isEmpty()) {
|
||||
errorList.add(createErrorInfo(rowNumber, productCode, validationErrors));
|
||||
continue;
|
||||
}
|
||||
//新增商品
|
||||
//1.先查询当前货号是否存在,存在即更新,不存在即新增
|
||||
List<SmErpSpuEntity> smErpSpuEntities = baseMapper.selectListByScope(new LambdaQueryWrapper<SmErpSpuEntity>().
|
||||
eq(SmErpSpuEntity::getProductCode, productCode), DataScope.of());
|
||||
if (CollectionUtils.isEmpty(smErpSpuEntities)) {
|
||||
//新增
|
||||
SmErpSpuEntity smErpSpuEntity = BeanUtils.toBean(dto, SmErpSpuEntity.class);
|
||||
if (dto.getCommodityNature().equals("电子称称重商品")){
|
||||
smErpSpuEntity.setProductNature("2");
|
||||
}else {
|
||||
smErpSpuEntity.setProductNature("1");
|
||||
}
|
||||
//先查询分类是否有,没有自动新增
|
||||
SmErpCategoryEntity smErpCategoryEntity = smErpCategoryMapper.selectOne
|
||||
(new LambdaQueryWrapper<SmErpCategoryEntity>().eq(SmErpCategoryEntity::getName, dto.getClassification()));
|
||||
if (smErpCategoryEntity == null) {
|
||||
//新增分类
|
||||
SmErpCategoryEntity smErpCategoryEntity1 = new SmErpCategoryEntity();
|
||||
smErpCategoryEntity1.setName(dto.getClassification());
|
||||
smErpCategoryEntity1.setStatus("0");
|
||||
smErpCategoryMapper.insert(smErpCategoryEntity1);
|
||||
smErpSpuEntity.setCategoryId(smErpCategoryEntity1.getId());
|
||||
}else {
|
||||
smErpSpuEntity.setCategoryId(smErpCategoryEntity.getId());
|
||||
}
|
||||
baseMapper.insert(smErpSpuEntity);
|
||||
//新增包装单位
|
||||
SmErpUnitEntity smErpUnitEntity = BeanUtils.toBean(dto, SmErpUnitEntity.class);
|
||||
smErpUnitEntity.setIsBase(true);
|
||||
smErpUnitEntity.setSpuId(smErpSpuEntity.getId());
|
||||
smErpUnitService.save(smErpUnitEntity);
|
||||
//新增库存
|
||||
SmErpStockEntity smErpStockEntity = new SmErpStockEntity();
|
||||
smErpStockEntity.setCurrentStock(dto.getStock());
|
||||
smErpStockEntity.setBaseStock(dto.getStock());
|
||||
smErpStockEntity.setInventoryLowerLimit(dto.getInventoryLowerLimit());
|
||||
smErpStockEntity.setInventoryUpperLimit(dto.getInventoryUpperLimit());
|
||||
smErpStockEntity.setErpSpuId(smErpSpuEntity.getId());
|
||||
smErpStockMapper.insert(smErpStockEntity);
|
||||
//新增辅助条码
|
||||
SmErpAuxiliaryCodeEntity smErpAuxiliaryCodeEntity = new SmErpAuxiliaryCodeEntity();
|
||||
smErpAuxiliaryCodeEntity.setBarCode(dto.getBarCode());
|
||||
smErpAuxiliaryCodeEntity.setSpuId(smErpSpuEntity.getId());
|
||||
smErpAuxiliaryCodeEntity.setUnitId(smErpUnitEntity.getId());
|
||||
smErpAuxiliaryCodeService.save(smErpAuxiliaryCodeEntity);
|
||||
}else {
|
||||
//查到相同的货号,更新
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
return null;
|
||||
}*/
|
||||
/*
|
||||
@Override
|
||||
@Transactional
|
||||
public R importErpSpu(List<SmErpSpuImportDto> smErpSpuImportDtos, BindingResult bindingResult) {
|
||||
if (CollectionUtils.isEmpty(smErpSpuImportDtos)) {
|
||||
return R.failed("导入数据不能为空");
|
||||
}
|
||||
|
||||
List<Map<String, Object>> errorList = new ArrayList<>();
|
||||
List<SmErpSpuEntity> successList = new ArrayList<>();
|
||||
|
||||
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);
|
||||
if (categoryId == null) {
|
||||
errorList.add(createErrorInfo(rowNumber, productCode, errorReasons));
|
||||
continue;
|
||||
}
|
||||
|
||||
// 查询现有商品
|
||||
SmErpSpuEntity existingSpu = baseMapper.selectOne(new LambdaQueryWrapper<SmErpSpuEntity>()
|
||||
.eq(SmErpSpuEntity::getProductCode, productCode));
|
||||
|
||||
if (existingSpu == null) {
|
||||
// 新增逻辑
|
||||
handleNewSpu(dto, categoryId, errorReasons, rowNumber, productCode, errorList);
|
||||
} else {
|
||||
// 更新逻辑
|
||||
handleExistingSpu(existingSpu, dto, categoryId, errorReasons, rowNumber, productCode, errorList);
|
||||
}
|
||||
|
||||
// 记录成功数据
|
||||
if (errorReasons.isEmpty()) {
|
||||
successList.add(baseMapper.selectById(existingSpu != null ? existingSpu.getId() : null));
|
||||
}
|
||||
} catch (Exception e) {
|
||||
errorReasons.add("系统异常: " + e.getMessage());
|
||||
errorList.add(createErrorInfo(rowNumber, productCode, errorReasons));
|
||||
}
|
||||
}
|
||||
|
||||
return buildImportResult(smErpSpuImportDtos.size(), successList.size(), errorList);
|
||||
}
|
||||
|
||||
|
||||
|
||||
// 处理分类(公共方法)
|
||||
private Long resolveCategory(String categoryName, List<String> errorReasons) {
|
||||
try {
|
||||
SmErpCategoryEntity category = smErpCategoryMapper.selectOne(
|
||||
new LambdaQueryWrapper<SmErpCategoryEntity>()
|
||||
.eq(SmErpCategoryEntity::getName, categoryName)
|
||||
);
|
||||
|
||||
if (category != null) return category.getId();
|
||||
|
||||
// 新建分类
|
||||
SmErpCategoryEntity newCategory = new SmErpCategoryEntity();
|
||||
newCategory.setName(categoryName);
|
||||
newCategory.setStatus("0"); // 假设0为启用状态
|
||||
if (smErpCategoryMapper.insert(newCategory) > 0) {
|
||||
return newCategory.getId();
|
||||
}
|
||||
errorReasons.add("分类创建失败");
|
||||
} catch (DuplicateKeyException e) {
|
||||
// 处理并发创建场景
|
||||
return smErpCategoryMapper.selectOne(
|
||||
new LambdaQueryWrapper<SmErpCategoryEntity>()
|
||||
.eq(SmErpCategoryEntity::getName, categoryName)
|
||||
).getId();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
// 处理新增商品
|
||||
private void handleNewSpu(SmErpSpuImportDto dto, Long categoryId, List<String> errorReasons,
|
||||
int rowNumber, String productCode, List<Map<String, Object>> errorList) {
|
||||
try {
|
||||
SmErpSpuEntity newSpu = BeanUtils.toBean(dto, SmErpSpuEntity.class);
|
||||
newSpu.setProductNature(dto.getCommodityNature().equals("电子称称重商品") ? "2" : "1");
|
||||
newSpu.setCategoryId(categoryId);
|
||||
|
||||
if (baseMapper.insert(newSpu) <= 0) {
|
||||
errorReasons.add("商品创建失败");
|
||||
errorList.add(createErrorInfo(rowNumber, productCode, errorReasons));
|
||||
return;
|
||||
}
|
||||
|
||||
// 处理关联数据
|
||||
handleRelatedData(newSpu, dto, errorReasons, rowNumber, productCode, errorList);
|
||||
} catch (DuplicateKeyException e) {
|
||||
errorReasons.add("货号已存在");
|
||||
errorList.add(createErrorInfo(rowNumber, productCode, errorReasons));
|
||||
}
|
||||
}
|
||||
|
||||
// 处理更新商品
|
||||
private void handleExistingSpu(SmErpSpuEntity existingSpu, SmErpSpuImportDto dto, Long categoryId,
|
||||
List<String> errorReasons, int rowNumber, String productCode,
|
||||
List<Map<String, Object>> errorList) {
|
||||
try {
|
||||
// 更新主数据
|
||||
org.springframework.beans.BeanUtils.copyProperties(dto, existingSpu);
|
||||
existingSpu.setProductNature(dto.getCommodityNature().equals("电子称称重商品") ? "2" : "1");
|
||||
existingSpu.setCategoryId(categoryId);
|
||||
|
||||
if (baseMapper.updateById(existingSpu) <= 0) {
|
||||
errorReasons.add("商品更新失败");
|
||||
errorList.add(createErrorInfo(rowNumber, productCode, errorReasons));
|
||||
return;
|
||||
}
|
||||
|
||||
// 处理关联数据
|
||||
handleRelatedData(existingSpu, dto, errorReasons, rowNumber, productCode, errorList);
|
||||
} catch (Exception e) {
|
||||
errorReasons.add("更新异常: " + e.getMessage());
|
||||
errorList.add(createErrorInfo(rowNumber, productCode, errorReasons));
|
||||
}
|
||||
}
|
||||
|
||||
// 处理关联数据(单位、库存、条码)
|
||||
private void handleRelatedData(SmErpSpuEntity spu, SmErpSpuImportDto dto, List<String> errorReasons,
|
||||
int rowNumber, String productCode, List<Map<String, Object>> errorList) {
|
||||
// 处理包装单位
|
||||
SmErpUnitEntity unit = smErpUnitService.getOne(
|
||||
new LambdaQueryWrapper<SmErpUnitEntity>()
|
||||
.eq(SmErpUnitEntity::getSpuId, spu.getId())
|
||||
);
|
||||
|
||||
try {
|
||||
if (unit != null) {
|
||||
// 更新单位
|
||||
org.springframework.beans.BeanUtils.copyProperties(dto, unit);
|
||||
smErpUnitService.updateById(unit);
|
||||
} else {
|
||||
// 新增单位
|
||||
unit = BeanUtils.toBean(dto, SmErpUnitEntity.class);
|
||||
unit.setSpuId(spu.getId());
|
||||
unit.setIsBase(true);
|
||||
smErpUnitService.save(unit);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
errorReasons.add("包装单位处理失败: " + e.getMessage());
|
||||
}
|
||||
|
||||
// 处理库存
|
||||
SmErpStockEntity stock = smErpStockMapper.selectOne(
|
||||
new LambdaQueryWrapper<SmErpStockEntity>()
|
||||
.eq(SmErpStockEntity::getErpSpuId, spu.getId())
|
||||
);
|
||||
|
||||
try {
|
||||
if (stock != null) {
|
||||
// 更新库存
|
||||
stock.setCurrentStock(dto.getStock());
|
||||
stock.setBaseStock(dto.getStock());
|
||||
stock.setInventoryLowerLimit(dto.getInventoryLowerLimit());
|
||||
stock.setInventoryUpperLimit(dto.getInventoryUpperLimit());
|
||||
smErpStockMapper.updateById(stock);
|
||||
} else {
|
||||
// 新增库存
|
||||
stock = BeanUtils.toBean(dto, SmErpStockEntity.class);
|
||||
stock.setErpSpuId(spu.getId());
|
||||
smErpStockMapper.insert(stock);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
errorReasons.add("库存处理失败: " + e.getMessage());
|
||||
}
|
||||
|
||||
// 处理辅助条码
|
||||
SmErpAuxiliaryCodeEntity code = smErpAuxiliaryCodeService.getOne(
|
||||
new LambdaQueryWrapper<SmErpAuxiliaryCodeEntity>()
|
||||
.eq(SmErpAuxiliaryCodeEntity::getSpuId, spu.getId())
|
||||
);
|
||||
|
||||
try {
|
||||
if (code != null) {
|
||||
// 更新条码
|
||||
code.setBarCode(dto.getBarCode());
|
||||
code.setUnitId(unit.getId());
|
||||
smErpAuxiliaryCodeService.updateById(code);
|
||||
} else {
|
||||
// 新增条码
|
||||
code = new SmErpAuxiliaryCodeEntity();
|
||||
code.setBarCode(dto.getBarCode());
|
||||
code.setSpuId(spu.getId());
|
||||
code.setUnitId(unit.getId());
|
||||
smErpAuxiliaryCodeService.save(code);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
errorReasons.add("条码处理失败: " + e.getMessage());
|
||||
}
|
||||
|
||||
// 记录错误
|
||||
if (!errorReasons.isEmpty()) {
|
||||
errorList.add(createErrorInfo(rowNumber, productCode, errorReasons));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// 构建返回结果(与供应商导入保持一致)
|
||||
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);
|
||||
}};
|
||||
}
|
||||
*/
|
||||
|
||||
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)) {
|
||||
return R.failed("导入数据不能为空");
|
||||
}
|
||||
|
||||
List<Map<String, Object>> errorList = new ArrayList<>();
|
||||
List<SmErpSpuEntity> successList = new ArrayList<>();
|
||||
|
||||
// 批量处理分类
|
||||
Map<String, Long> categoryMap = resolveCategories(smErpSpuImportDtos, errorList);
|
||||
|
||||
// 批量处理商品
|
||||
List<SmErpSpuEntity> spuBatch = new ArrayList<>();
|
||||
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);
|
||||
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;
|
||||
}
|
||||
|
||||
// 获取分类ID
|
||||
Long categoryId = categoryMap.get(dto.getClassification());
|
||||
if (categoryId == null) {
|
||||
errorReasons.add("分类不存在且创建失败");
|
||||
errorList.add(createErrorInfo(rowNumber, productCode, errorReasons));
|
||||
continue;
|
||||
}
|
||||
|
||||
// 构造商品实体
|
||||
SmErpSpuEntity spu = BeanUtils.toBean(dto, SmErpSpuEntity.class);
|
||||
spu.setProductNature("电子称称重商品".equals(dto.getCommodityNature()) ? "2" : "1");
|
||||
spu.setCategoryId(categoryId);
|
||||
spuBatch.add(spu);
|
||||
|
||||
// 构造关联数据
|
||||
buildRelatedData(dto, spu, unitBatch, stockBatch, codeBatch);
|
||||
|
||||
successList.add(spu);
|
||||
} catch (Exception e) {
|
||||
errorReasons.add("系统异常: " + e.getMessage());
|
||||
errorList.add(createErrorInfo(rowNumber, productCode, errorReasons));
|
||||
}
|
||||
}
|
||||
|
||||
// 批量数据库操作
|
||||
try {
|
||||
// 批量插入/更新商品
|
||||
if (!spuBatch.isEmpty()) {
|
||||
saveOrUpdateBatchSpu(spuBatch);
|
||||
}
|
||||
|
||||
// 批量处理关联数据
|
||||
if (!unitBatch.isEmpty()) {
|
||||
smErpUnitService.saveOrUpdateBatch(unitBatch);
|
||||
}
|
||||
if (!stockBatch.isEmpty()) {
|
||||
smErpStockService.saveOrUpdateBatch(stockBatch);
|
||||
}
|
||||
if (!codeBatch.isEmpty()) {
|
||||
smErpAuxiliaryCodeService.saveOrUpdateBatch(codeBatch);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException("批量操作失败", e);
|
||||
}
|
||||
|
||||
return buildImportResult(smErpSpuImportDtos.size(), successList.size(), errorList);
|
||||
}
|
||||
|
||||
// 批量处理分类
|
||||
private Map<String, Long> resolveCategories(List<SmErpSpuImportDto> dtos, List<Map<String, Object>> errorList) {
|
||||
// 获取所有分类名称
|
||||
Set<String> categoryNames = dtos.stream()
|
||||
.map(SmErpSpuImportDto::getClassification)
|
||||
.collect(Collectors.toSet());
|
||||
|
||||
// 批量查询已有分类
|
||||
List<SmErpCategoryEntity> existCategories = smErpCategoryMapper.selectList(
|
||||
new LambdaQueryWrapper<SmErpCategoryEntity>()
|
||||
.in(SmErpCategoryEntity::getName, categoryNames));
|
||||
|
||||
Map<String, Long> categoryMap = existCategories.stream()
|
||||
.collect(Collectors.toMap(SmErpCategoryEntity::getName, SmErpCategoryEntity::getId));
|
||||
|
||||
// 找出需要新增的分类
|
||||
List<SmErpCategoryEntity> newCategories = categoryNames.stream()
|
||||
.filter(name -> !categoryMap.containsKey(name))
|
||||
.map(name -> {
|
||||
SmErpCategoryEntity category = new SmErpCategoryEntity();
|
||||
category.setName(name);
|
||||
category.setStatus("0");
|
||||
return category;
|
||||
})
|
||||
.collect(Collectors.toList());
|
||||
|
||||
// 批量插入新分类
|
||||
if (!newCategories.isEmpty()) {
|
||||
smCategoryService.saveBatch(newCategories);
|
||||
newCategories.forEach(cat -> categoryMap.put(cat.getName(), cat.getId()));
|
||||
}
|
||||
|
||||
return categoryMap;
|
||||
}
|
||||
|
||||
// 批量保存或更新商品
|
||||
private void saveOrUpdateBatchSpu(List<SmErpSpuEntity> spuList) {
|
||||
// 按货号分组
|
||||
Map<String, List<SmErpSpuEntity>> spuMap = spuList.stream()
|
||||
.collect(Collectors.groupingBy(SmErpSpuEntity::getProductCode));
|
||||
|
||||
// 批量查询已存在的商品
|
||||
List<SmErpSpuEntity> existSpus = baseMapper.selectList(
|
||||
new LambdaQueryWrapper<SmErpSpuEntity>()
|
||||
.in(SmErpSpuEntity::getProductCode, spuMap.keySet()));
|
||||
|
||||
// 分离新增和更新数据
|
||||
List<SmErpSpuEntity> toInsert = new ArrayList<>();
|
||||
List<SmErpSpuEntity> toUpdate = new ArrayList<>();
|
||||
|
||||
spuList.forEach(spu -> {
|
||||
Optional<SmErpSpuEntity> exist = existSpus.stream()
|
||||
.filter(e -> e.getProductCode().equals(spu.getProductCode()))
|
||||
.findFirst();
|
||||
|
||||
if (exist.isPresent()) {
|
||||
SmErpSpuEntity entity = exist.get();
|
||||
org.springframework.beans.BeanUtils.copyProperties(spu, entity);
|
||||
toUpdate.add(entity);
|
||||
} else {
|
||||
toInsert.add(spu);
|
||||
}
|
||||
});
|
||||
|
||||
// 批量操作
|
||||
if (!toInsert.isEmpty()) {
|
||||
this.saveBatch((toInsert));
|
||||
}
|
||||
if (!toUpdate.isEmpty()) {
|
||||
this.updateBatchById(toUpdate);
|
||||
}
|
||||
}
|
||||
|
||||
// 构建关联数据
|
||||
private void buildRelatedData(SmErpSpuImportDto dto, SmErpSpuEntity spu,
|
||||
List<SmErpUnitEntity> unitBatch,
|
||||
List<SmErpStockEntity> stockBatch,
|
||||
List<SmErpAuxiliaryCodeEntity> codeBatch) {
|
||||
// 包装单位
|
||||
SmErpUnitEntity unit = BeanUtils.toBean(dto, SmErpUnitEntity.class);
|
||||
unit.setSpuId(spu.getId());
|
||||
unit.setIsBase(true);
|
||||
unitBatch.add(unit);
|
||||
|
||||
// 库存
|
||||
SmErpStockEntity stock = BeanUtils.toBean(dto, SmErpStockEntity.class);
|
||||
stock.setErpSpuId(spu.getId());
|
||||
stockBatch.add(stock);
|
||||
|
||||
// 辅助条码
|
||||
SmErpAuxiliaryCodeEntity code = new SmErpAuxiliaryCodeEntity();
|
||||
code.setBarCode(dto.getBarCode());
|
||||
code.setSpuId(spu.getId());
|
||||
code.setUnitId(unit.getId());
|
||||
codeBatch.add(code);
|
||||
}
|
||||
|
||||
public void asyncExecuteImport(String taskId, List<SmErpSpuImportDto> dtos) {
|
||||
executor.execute(() -> {
|
||||
List<Map<String, Object>> errors = new ArrayList<>();
|
||||
// 使用线程安全的计数器
|
||||
AtomicInteger successCount = new AtomicInteger(0);
|
||||
|
||||
try {
|
||||
taskStoreService.updateTask(taskId, t -> t.setStatus("PROCESSING"));
|
||||
|
||||
for (int i = 0; i < dtos.size(); i++) {
|
||||
try {
|
||||
processSingleItem(dtos.get(i), i + 1);
|
||||
successCount.incrementAndGet();
|
||||
} catch (Exception e) {
|
||||
errors.add(buildErrorInfo(i + 1, dtos.get(i).getProductCode(), e));
|
||||
}
|
||||
}
|
||||
|
||||
taskStoreService.updateTask(taskId, t -> {
|
||||
t.setStatus("COMPLETED");
|
||||
t.setSuccess(successCount.get());
|
||||
t.setError(errors.size());
|
||||
t.setErrors(errors);
|
||||
t.setFinishTime(LocalDateTime.now());
|
||||
});
|
||||
} catch (Exception e) {
|
||||
taskStoreService.updateTask(taskId, t -> {
|
||||
t.setStatus("FAILED");
|
||||
t.setError(dtos.size());
|
||||
t.setErrors(Collections.singletonList(
|
||||
buildErrorInfo(0, "SYSTEM", e)
|
||||
));
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void processSingleItem(SmErpSpuImportDto dto, int row) throws Exception {
|
||||
// 数据校验
|
||||
List<String> validations = ErpSpuValidator.validate(dto, row);
|
||||
if (!validations.isEmpty()) {
|
||||
throw new RuntimeException(String.join(",", validations));
|
||||
}
|
||||
|
||||
// 处理分类
|
||||
Long categoryId = resolveCategory(dto.getClassification());
|
||||
|
||||
// 处理商品
|
||||
SmErpSpuEntity spu = resolveSpu(dto, categoryId);
|
||||
|
||||
// 处理关联数据
|
||||
handleRelatedData(spu, dto);
|
||||
}
|
||||
|
||||
private Long resolveCategory(String name) {
|
||||
SmErpCategoryEntity category = smErpCategoryMapper.selectOne(
|
||||
new LambdaQueryWrapper<SmErpCategoryEntity>()
|
||||
.eq(SmErpCategoryEntity::getName, name));
|
||||
|
||||
if (category != null) return category.getId();
|
||||
|
||||
SmErpCategoryEntity newCategory = new SmErpCategoryEntity();
|
||||
newCategory.setName(name);
|
||||
if (smErpCategoryMapper.insert(newCategory) > 0) {
|
||||
return newCategory.getId();
|
||||
}
|
||||
throw new RuntimeException("分类创建失败");
|
||||
}
|
||||
|
||||
private SmErpSpuEntity resolveSpu(SmErpSpuImportDto dto, Long categoryId) {
|
||||
SmErpSpuEntity existing = baseMapper.selectOne(
|
||||
new LambdaQueryWrapper<SmErpSpuEntity>()
|
||||
.eq(SmErpSpuEntity::getProductCode, dto.getProductCode()));
|
||||
|
||||
SmErpSpuEntity spu = BeanUtils.toBean(dto, SmErpSpuEntity.class);
|
||||
spu.setProductNature("电子称称重商品".equals(dto.getCommodityNature()) ? "2" : "1");
|
||||
spu.setCategoryId(categoryId);
|
||||
|
||||
if (existing != null) {
|
||||
spu.setId(existing.getId());
|
||||
if (baseMapper.updateById(spu) <= 0) {
|
||||
throw new RuntimeException("商品更新失败");
|
||||
}
|
||||
} else {
|
||||
if (baseMapper.insert(spu) <= 0) {
|
||||
throw new RuntimeException("商品创建失败");
|
||||
}
|
||||
}
|
||||
return spu;
|
||||
}
|
||||
|
||||
private void handleRelatedData(SmErpSpuEntity spu, SmErpSpuImportDto dto) {
|
||||
// 处理单位
|
||||
SmErpUnitEntity unit = Optional.ofNullable(smErpUnitService.getOne(
|
||||
new LambdaQueryWrapper<SmErpUnitEntity>()
|
||||
.eq(SmErpUnitEntity::getSpuId, spu.getId())))
|
||||
.orElseGet(() -> new SmErpUnitEntity());
|
||||
|
||||
org.springframework.beans.BeanUtils.copyProperties(dto, unit);
|
||||
unit.setSpuId(spu.getId());
|
||||
unit.setIsBase(true);
|
||||
smErpUnitService.saveOrUpdate(unit);
|
||||
|
||||
// 处理库存
|
||||
SmErpStockEntity stock = Optional.ofNullable(smErpStockMapper.selectOne(
|
||||
new LambdaQueryWrapper<SmErpStockEntity>()
|
||||
.eq(SmErpStockEntity::getErpSpuId, spu.getId())))
|
||||
.orElseGet(() -> new SmErpStockEntity());
|
||||
|
||||
org.springframework.beans.BeanUtils.copyProperties(dto, stock);
|
||||
stock.setErpSpuId(spu.getId());
|
||||
smErpStockMapper.insertOrUpdate(stock);
|
||||
|
||||
// 处理条码
|
||||
SmErpAuxiliaryCodeEntity code = Optional.ofNullable(smErpAuxiliaryCodeService.getOne(
|
||||
new LambdaQueryWrapper<SmErpAuxiliaryCodeEntity>()
|
||||
.eq(SmErpAuxiliaryCodeEntity::getSpuId, spu.getId())))
|
||||
.orElseGet(() -> new SmErpAuxiliaryCodeEntity());
|
||||
|
||||
code.setBarCode(dto.getBarCode());
|
||||
code.setSpuId(spu.getId());
|
||||
code.setUnitId(unit.getId());
|
||||
smErpAuxiliaryCodeService.saveOrUpdate(code);
|
||||
}
|
||||
|
||||
private Map<String, Object> buildErrorInfo(int row, String code, Exception e) {
|
||||
return new HashMap<String, Object>() {{
|
||||
put("row", row);
|
||||
put("productCode", code);
|
||||
put("reason", e.getMessage());
|
||||
}};
|
||||
}
|
||||
|
||||
}
|
||||
+211
-1
@@ -1,15 +1,29 @@
|
||||
package com.bsd.pjcloud.supermarket.service.impl;
|
||||
|
||||
import cn.hutool.core.lang.Assert;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import com.bsd.pjcloud.common.core.util.BeanUtils;
|
||||
import com.bsd.pjcloud.common.core.util.R;
|
||||
import com.bsd.pjcloud.common.data.datascope.DataScope;
|
||||
import com.bsd.pjcloud.common.security.util.SecurityUtils;
|
||||
import com.bsd.pjcloud.supermarket.dto.supplier.SmErpSupplierImportDto;
|
||||
import com.bsd.pjcloud.supermarket.entity.SmErpSupplierEntity;
|
||||
import com.bsd.pjcloud.supermarket.entity.SmErpSupplierTypeEntity;
|
||||
import com.bsd.pjcloud.supermarket.mapper.SmErpSupplierMapper;
|
||||
import com.bsd.pjcloud.supermarket.mapper.SmErpSupplierTypeMapper;
|
||||
import com.bsd.pjcloud.supermarket.service.SmErpSupplierService;
|
||||
import com.bsd.pjcloud.supermarket.validarot.SupplierValidator;
|
||||
import lombok.AllArgsConstructor;
|
||||
import org.springframework.dao.DuplicateKeyException;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Propagation;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
import org.springframework.validation.BindingResult;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* 货商管理
|
||||
@@ -18,7 +32,10 @@ import java.util.List;
|
||||
* @date 2024-12-20 12:07:42
|
||||
*/
|
||||
@Service
|
||||
@AllArgsConstructor
|
||||
public class SmErpSupplierServiceImpl extends ServiceImpl<SmErpSupplierMapper, SmErpSupplierEntity> implements SmErpSupplierService {
|
||||
|
||||
private final SmErpSupplierTypeMapper supplierTypeMapper;
|
||||
@Override
|
||||
public List<SmErpSupplierEntity> selectSimpleAllScope() {
|
||||
return baseMapper.selectListByScope(new LambdaQueryWrapper<SmErpSupplierEntity>().eq(SmErpSupplierEntity::getStatus, "0"), DataScope.of());
|
||||
@@ -28,4 +45,197 @@ public class SmErpSupplierServiceImpl extends ServiceImpl<SmErpSupplierMapper, S
|
||||
public Object pageScope(Page page, LambdaQueryWrapper<SmErpSupplierEntity> wrapper) {
|
||||
return baseMapper.selectPageByScope(page, wrapper, DataScope.of());
|
||||
}
|
||||
|
||||
/* @Override
|
||||
@Transactional
|
||||
public R importSupplier(List<SmErpSupplierImportDto> smErpSupplierImportDtos, BindingResult bindingResult) {
|
||||
if (smErpSupplierImportDtos.isEmpty()) {
|
||||
return R.failed("导入内容为空");
|
||||
}
|
||||
|
||||
List<R> result = new ArrayList<>();
|
||||
for (int i = 0; i < smErpSupplierImportDtos.size(); i++) {
|
||||
SmErpSupplierImportDto entity = smErpSupplierImportDtos.get(i);
|
||||
List<String> errors = SupplierValidator.validate(entity, i);
|
||||
|
||||
if (!errors.isEmpty()) {
|
||||
for (String error : errors) {
|
||||
bindingResult.rejectValue("", "", error);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
SmErpSupplierEntity supplier = BeanUtils.toBean(entity, SmErpSupplierEntity.class);
|
||||
//查询货商
|
||||
List<SmErpSupplierEntity> smErpSupplierEntities = baseMapper.selectListByScope(new LambdaQueryWrapper<>(SmErpSupplierEntity.class)
|
||||
.eq(SmErpSupplierEntity::getSupplierName, supplier.getSupplierName()), DataScope.of());
|
||||
//查询货商类型
|
||||
String supplierCategory = entity.getSupplierCategory();
|
||||
List<SmErpSupplierTypeEntity> smErpSupplierTypeEntities = supplierTypeMapper.selectListByScope(new LambdaQueryWrapper<>(SmErpSupplierTypeEntity.class)
|
||||
.eq(SmErpSupplierTypeEntity::getTypeName, supplierCategory), DataScope.of());
|
||||
Long supplierTypeId = determineSupplierTypeId(supplierCategory, smErpSupplierTypeEntities);
|
||||
supplier.setSupplierId(supplierTypeId);
|
||||
|
||||
//如果有当前名称,则更新
|
||||
if (CollectionUtils.isEmpty(smErpSupplierEntities)) {
|
||||
boolean b = updateById(supplier);
|
||||
if (b) {
|
||||
result.add(R.ok("更新成功"));
|
||||
} else {
|
||||
result.add(R.failed("更新失败"));
|
||||
}
|
||||
} else {
|
||||
boolean save = save(supplier);
|
||||
if (save) {
|
||||
result.add(R.ok("新增成功"));
|
||||
} else {
|
||||
result.add(R.ok("新增失败"));
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
return R.ok(result);
|
||||
}
|
||||
// 新增的公共方法
|
||||
private Long determineSupplierTypeId(String category, List<SmErpSupplierTypeEntity> typeEntities) {
|
||||
if (CollectionUtils.isEmpty(typeEntities)) {
|
||||
SmErpSupplierTypeEntity newType = new SmErpSupplierTypeEntity();
|
||||
newType.setTypeName(category);
|
||||
supplierTypeMapper.insert(newType);
|
||||
return newType.getId();
|
||||
}
|
||||
// 显式断言确保集合非空
|
||||
Assert.notEmpty(typeEntities, "供应商类型查询结果不应为空");
|
||||
return typeEntities.get(0).getId();
|
||||
}
|
||||
*/
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public R importSupplier(List<SmErpSupplierImportDto> smErpSupplierImportDtos, BindingResult bindingResult) {
|
||||
if (CollectionUtils.isEmpty(smErpSupplierImportDtos)) {
|
||||
return R.failed("导入数据不能为空");
|
||||
}
|
||||
|
||||
List<Map<String, Object>> errorList = new ArrayList<>();
|
||||
List<SmErpSupplierEntity> successList = new ArrayList<>();
|
||||
|
||||
for (int i = 0; i < smErpSupplierImportDtos.size(); i++) {
|
||||
int rowNumber = i + 1;
|
||||
SmErpSupplierImportDto dto = smErpSupplierImportDtos.get(i);
|
||||
List<String> errorReasons = new ArrayList<>();
|
||||
|
||||
// 数据校验阶段
|
||||
List<String> validationErrors = SupplierValidator.validate(dto, rowNumber);
|
||||
if (!validationErrors.isEmpty()) {
|
||||
errorList.add(createErrorInfo(rowNumber, dto.getSupplierName(), validationErrors));
|
||||
continue;
|
||||
}
|
||||
|
||||
try {
|
||||
// 处理供应商类型
|
||||
SmErpSupplierTypeEntity typeEntity = resolveSupplierType(dto.getSupplierCategory());
|
||||
if (typeEntity == null) {
|
||||
errorReasons.add("供应商类型不存在且创建失败");
|
||||
errorList.add(createErrorInfo(rowNumber, dto.getSupplierName(), errorReasons));
|
||||
continue;
|
||||
}
|
||||
|
||||
// 转换实体
|
||||
SmErpSupplierEntity supplier = BeanUtils.toBean(dto, SmErpSupplierEntity.class);
|
||||
supplier.setDeptId(SecurityUtils.getUser().getDeptId());
|
||||
supplier.setSupplierType(typeEntity.getId());
|
||||
|
||||
// 根据名称检查存在性(需确保supplier_name有唯一约束)
|
||||
SmErpSupplierEntity existing = getExistingSupplier(supplier.getSupplierName());
|
||||
|
||||
boolean operationResult;
|
||||
if (existing != null) {
|
||||
// 更新逻辑:保持原有ID
|
||||
supplier.setSupplierId(existing.getSupplierId());
|
||||
operationResult = updateById(supplier);
|
||||
} else {
|
||||
// 新增逻辑
|
||||
operationResult = save(supplier);
|
||||
}
|
||||
|
||||
if (operationResult) {
|
||||
successList.add(supplier);
|
||||
} else {
|
||||
errorReasons.add(existing != null ? "更新失败" : "新增失败");
|
||||
errorList.add(createErrorInfo(rowNumber, dto.getSupplierName(), errorReasons));
|
||||
}
|
||||
} catch (DuplicateKeyException e) {
|
||||
errorReasons.add("供应商名称已存在");
|
||||
errorList.add(createErrorInfo(rowNumber, dto.getSupplierName(), errorReasons));
|
||||
} catch (Exception e) {
|
||||
errorReasons.add("系统异常: " + e.getMessage());
|
||||
errorList.add(createErrorInfo(rowNumber, dto.getSupplierName(), errorReasons));
|
||||
}
|
||||
}
|
||||
|
||||
return buildFinalResult(smErpSupplierImportDtos.size(), successList.size(), errorList);
|
||||
}
|
||||
|
||||
// 辅助方法:获取已存在的供应商
|
||||
private SmErpSupplierEntity getExistingSupplier(String supplierName) {
|
||||
List<SmErpSupplierEntity> list = baseMapper.selectListByScope(
|
||||
new LambdaQueryWrapper<SmErpSupplierEntity>()
|
||||
.eq(SmErpSupplierEntity::getSupplierName, supplierName)
|
||||
.last("LIMIT 1"),
|
||||
DataScope.of()
|
||||
);
|
||||
return CollectionUtils.isEmpty(list) ? null : list.get(0);
|
||||
}
|
||||
|
||||
// 构建最终返回结果
|
||||
private R buildFinalResult(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 + "条数据");
|
||||
}
|
||||
|
||||
// 类型解析方法(带事务传播调整)
|
||||
@Transactional(propagation = Propagation.REQUIRES_NEW) // 新事务避免主事务回滚影响
|
||||
public SmErpSupplierTypeEntity resolveSupplierType(String typeName) {
|
||||
// 先尝试查询
|
||||
SmErpSupplierTypeEntity type = supplierTypeMapper.selectOne(
|
||||
new LambdaQueryWrapper<SmErpSupplierTypeEntity>()
|
||||
.eq(SmErpSupplierTypeEntity::getTypeName, typeName)
|
||||
);
|
||||
|
||||
if (type != null) return type;
|
||||
|
||||
// 不存在则尝试插入
|
||||
try {
|
||||
SmErpSupplierTypeEntity newType = new SmErpSupplierTypeEntity();
|
||||
newType.setTypeName(typeName);
|
||||
if (supplierTypeMapper.insert(newType) > 0) {
|
||||
return newType;
|
||||
}
|
||||
} catch (DuplicateKeyException e) {
|
||||
// 并发情况下其他事务已创建
|
||||
return supplierTypeMapper.selectOne(
|
||||
new LambdaQueryWrapper<SmErpSupplierTypeEntity>()
|
||||
.eq(SmErpSupplierTypeEntity::getTypeName, typeName)
|
||||
);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
// 错误信息构建方法
|
||||
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);
|
||||
}};
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user