Commit c4be58dae28ca11c744a743376b0912a3b08bbd5

Authored by 房远帅
1 parent 9f17d57c

报价:价格表导入

... ... @@ -7,9 +7,12 @@ import com.lframework.starter.web.core.components.resp.InvokeResult;
7 7 import com.lframework.starter.web.core.components.resp.InvokeResultBuilder;
8 8 import com.lframework.starter.web.core.components.resp.PageResult;
9 9 import com.lframework.starter.web.core.controller.DefaultBaseController;
  10 +import com.lframework.starter.web.core.utils.ExcelUtil;
10 11 import com.lframework.starter.web.core.utils.PageResultUtil;
11 12 import com.lframework.xingyun.basedata.bo.price.QueryPriceBo;
12 13 import com.lframework.xingyun.basedata.entity.Price;
  14 +import com.lframework.xingyun.basedata.excel.price.PriceImportListener;
  15 +import com.lframework.xingyun.basedata.excel.price.PriceImportModel;
13 16 import com.lframework.xingyun.basedata.service.price.PriceService;
14 17 import com.lframework.xingyun.basedata.vo.price.CreatePriceVo;
15 18 import com.lframework.xingyun.basedata.vo.price.QueryPriceVo;
... ... @@ -22,8 +25,12 @@ import org.springframework.validation.annotation.Validated;
22 25 import org.springframework.web.bind.annotation.*;
23 26 import javax.validation.Valid;
24 27 import javax.validation.constraints.NotBlank;
  28 +import javax.validation.constraints.NotNull;
  29 +import javax.servlet.http.HttpServletResponse;
  30 +import java.io.IOException;
25 31 import java.util.List;
26 32 import java.util.stream.Collectors;
  33 +import org.springframework.web.multipart.MultipartFile;
27 34
28 35 /**
29 36 * 价格表 Controller
... ... @@ -116,4 +123,30 @@ public class PriceController extends DefaultBaseController {
116 123
117 124 return InvokeResultBuilder.success();
118 125 }
  126 +
  127 + /**
  128 + * 下载导入模板
  129 + */
  130 + @ApiOperation("下载导入模板")
  131 + @HasPermission({"base-data:price-table:import"})
  132 + @GetMapping("/import/template")
  133 + public void downloadImportTemplate(HttpServletResponse response) throws IOException {
  134 + ExcelUtil.exportXls("价格表导入模板", PriceImportModel.class);
  135 + }
  136 +
  137 + /**
  138 + * 导入
  139 + */
  140 + @ApiOperation("导入")
  141 + @HasPermission({"base-data:price-table:import"})
  142 + @PostMapping("/import")
  143 + public InvokeResult<Void> importExcel(@NotBlank(message = "ID不能为空") String id,
  144 + @NotNull(message = "请上传文件") MultipartFile file) {
  145 +
  146 + PriceImportListener listener = new PriceImportListener();
  147 + listener.setTaskId(id);
  148 + ExcelUtil.read(file, PriceImportModel.class, listener).sheet().doRead();
  149 +
  150 + return InvokeResultBuilder.success();
  151 + }
119 152 }
... ...
  1 +package com.lframework.xingyun.basedata.excel.price;
  2 +
  3 +import com.alibaba.excel.context.AnalysisContext;
  4 +import com.baomidou.mybatisplus.core.toolkit.Wrappers;
  5 +import com.lframework.starter.common.exceptions.impl.DefaultClientException;
  6 +import com.lframework.starter.common.utils.StringUtil;
  7 +import com.lframework.starter.web.core.components.excel.ExcelImportListener;
  8 +import com.lframework.starter.web.core.utils.ApplicationUtil;
  9 +import com.lframework.starter.web.core.utils.IdUtil;
  10 +import com.lframework.xingyun.basedata.entity.BreedRelationship;
  11 +import com.lframework.xingyun.basedata.entity.Price;
  12 +import com.lframework.xingyun.basedata.service.breed.BreedRelationshipService;
  13 +import com.lframework.xingyun.basedata.service.price.PriceService;
  14 +import com.lframework.xingyun.basedata.vo.price.CreatePriceSubTableVo;
  15 +import com.lframework.xingyun.basedata.vo.price.CreatePriceVo;
  16 +import java.math.BigDecimal;
  17 +import java.util.ArrayList;
  18 +import java.util.List;
  19 +import lombok.extern.slf4j.Slf4j;
  20 +
  21 +/**
  22 + * 价格表导入监听器
  23 + */
  24 +@Slf4j
  25 +public class PriceImportListener extends ExcelImportListener<PriceImportModel> {
  26 +
  27 + /**
  28 + * 导入文件中的价格表编号
  29 + */
  30 + private String importCode;
  31 +
  32 + /**
  33 + * 编号所在行号
  34 + */
  35 + private Integer codeRowIndex;
  36 +
  37 + /**
  38 + * 导入文件中的品名校验列表
  39 + */
  40 + private final List<String> checkProductNameList = new ArrayList<>();
  41 +
  42 + @Override
  43 + protected void doInvoke(PriceImportModel data, AnalysisContext context) {
  44 + int rowIndex = context.readRowHolder().getRowIndex();
  45 + PriceService priceService = ApplicationUtil.getBean(PriceService.class);
  46 + BreedRelationshipService breedRelationshipService = ApplicationUtil.getBean(BreedRelationshipService.class);
  47 +
  48 + if (StringUtil.isNotBlank(data.getCode())) {
  49 + data.setCode(data.getCode().trim());
  50 + }
  51 + if (StringUtil.isNotBlank(data.getProductName())) {
  52 + data.setProductName(data.getProductName().trim());
  53 + }
  54 +
  55 + validateCode(data.getCode(), rowIndex, priceService);
  56 +
  57 + if (StringUtil.isBlank(data.getProductName())) {
  58 + throw new DefaultClientException("第" + rowIndex + "行“品名”不能为空");
  59 + }
  60 +
  61 + BreedRelationship breedRelationship = breedRelationshipService.getOne(
  62 + Wrappers.lambdaQuery(BreedRelationship.class)
  63 + .eq(BreedRelationship::getProductName, data.getProductName())
  64 + .last("LIMIT 1"));
  65 + if (breedRelationship == null) {
  66 + throw new DefaultClientException("第" + rowIndex + "行“品名”不存在于品种关系中");
  67 + }
  68 + data.setProductId(breedRelationship.getId());
  69 +
  70 + if (checkProductNameList.contains(data.getProductName())) {
  71 + throw new DefaultClientException(
  72 + "第" + rowIndex + "行“品名”与第" + (checkProductNameList.indexOf(data.getProductName()) + 1) + "行重复");
  73 + }
  74 + checkProductNameList.add(data.getProductName());
  75 +
  76 + data.setPriceValue(parsePrice(data.getPrice(), rowIndex));
  77 + }
  78 +
  79 + @Override
  80 + protected void afterAllAnalysed(AnalysisContext context) {
  81 + PriceService priceService = ApplicationUtil.getBean(PriceService.class);
  82 +
  83 + List<PriceImportModel> datas = this.getDatas();
  84 + if (datas.isEmpty()) {
  85 + return;
  86 + }
  87 +
  88 + CreatePriceVo vo = new CreatePriceVo();
  89 + vo.setCode(importCode);
  90 +
  91 + List<CreatePriceSubTableVo> priceSubTableList = new ArrayList<>(datas.size());
  92 + for (PriceImportModel data : datas) {
  93 + CreatePriceSubTableVo subTableVo = new CreatePriceSubTableVo();
  94 + subTableVo.setProductId(data.getProductId());
  95 + subTableVo.setPrice(data.getPriceValue());
  96 + subTableVo.setItemId(IdUtil.getId());
  97 + priceSubTableList.add(subTableVo);
  98 + }
  99 + vo.setPriceSubTableList(priceSubTableList);
  100 +
  101 + priceService.create(vo);
  102 + for (int i = 0; i < datas.size(); i++) {
  103 + this.setSuccessProcess(i);
  104 + }
  105 + }
  106 +
  107 + @Override
  108 + protected void doComplete() {
  109 +
  110 + }
  111 +
  112 + /**
  113 + * 校验导入编号
  114 + */
  115 + private void validateCode(String code, int rowIndex, PriceService priceService) {
  116 + if (importCode == null) {
  117 + if (StringUtil.isBlank(code)) {
  118 + throw new DefaultClientException("第" + rowIndex + "行“编号”不能为空");
  119 + }
  120 +
  121 + Price existsPrice = priceService.getOne(Wrappers.lambdaQuery(Price.class)
  122 + .eq(Price::getCode, code)
  123 + .last("LIMIT 1"));
  124 + if (existsPrice != null) {
  125 + throw new DefaultClientException("第" + rowIndex + "行“编号”已存在");
  126 + }
  127 +
  128 + importCode = code;
  129 + codeRowIndex = rowIndex;
  130 + return;
  131 + }
  132 +
  133 + if (StringUtil.isNotBlank(code)) {
  134 + throw new DefaultClientException(
  135 + "第" + rowIndex + "行“编号”重复填写,请仅在第" + codeRowIndex + "行填写一次");
  136 + }
  137 + }
  138 +
  139 + /**
  140 + * 解析采购价,并按统一口径返回行级错误
  141 + */
  142 + private BigDecimal parsePrice(String value, int rowIndex) {
  143 + if (StringUtil.isBlank(value)) {
  144 + throw new DefaultClientException("第" + rowIndex + "行“采购价”不能为空");
  145 + }
  146 +
  147 + BigDecimal decimalValue;
  148 + try {
  149 + decimalValue = new BigDecimal(value.trim());
  150 + } catch (NumberFormatException e) {
  151 + throw new DefaultClientException("第" + rowIndex + "行“采购价”格式有误");
  152 + }
  153 +
  154 + BigDecimal normalizedValue = decimalValue.stripTrailingZeros();
  155 + int scale = Math.max(normalizedValue.scale(), 0);
  156 + if (scale > 10) {
  157 + throw new DefaultClientException("第" + rowIndex + "行“采购价”最多允许10位小数");
  158 + }
  159 +
  160 + return decimalValue;
  161 + }
  162 +}
... ...
  1 +package com.lframework.xingyun.basedata.excel.price;
  2 +
  3 +import com.alibaba.excel.annotation.ExcelIgnore;
  4 +import com.alibaba.excel.annotation.ExcelProperty;
  5 +import com.lframework.starter.web.core.components.excel.ExcelModel;
  6 +import io.swagger.annotations.ApiModelProperty;
  7 +import lombok.Data;
  8 +
  9 +/**
  10 + * 价格表导入模型
  11 + */
  12 +@Data
  13 +public class PriceImportModel implements ExcelModel {
  14 +
  15 + /**
  16 + * 编号
  17 + */
  18 + @ApiModelProperty("编号")
  19 + @ExcelProperty("编号")
  20 + private String code;
  21 +
  22 + /**
  23 + * 品名
  24 + */
  25 + @ApiModelProperty("品名")
  26 + @ExcelProperty("品名")
  27 + private String productName;
  28 +
  29 + /**
  30 + * 采购价
  31 + */
  32 + @ApiModelProperty("采购价")
  33 + @ExcelProperty("采购价")
  34 + private String price;
  35 +
  36 + /**
  37 + * 导入时解析出的品种ID
  38 + */
  39 + @ExcelIgnore
  40 + private String productId;
  41 +
  42 + /**
  43 + * 导入时解析出的采购价
  44 + */
  45 + @ExcelIgnore
  46 + private java.math.BigDecimal priceValue;
  47 +}
... ...