diff --git a/nuzar-customer-client/src/main/java/com/haitonggauto/rtosc/dto/ExportInVo.java b/nuzar-customer-client/src/main/java/com/haitonggauto/rtosc/dto/ExportInVo.java index f196a90..ed9edba 100644 --- a/nuzar-customer-client/src/main/java/com/haitonggauto/rtosc/dto/ExportInVo.java +++ b/nuzar-customer-client/src/main/java/com/haitonggauto/rtosc/dto/ExportInVo.java @@ -1,8 +1,8 @@ package com.haitonggauto.rtosc.dto; -import com.baomidou.mybatisplus.annotation.TableField; import com.fasterxml.jackson.annotation.JsonFormat; import com.haitonggauto.rtosc.common.utils.ValidationGroup; +import com.haitonggauto.rtosc.common.validate.DependsOn; import com.haitonggauto.rtosc.common.validate.MoreThan; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; @@ -11,7 +11,6 @@ import lombok.Data; import javax.validation.Valid; import javax.validation.constraints.NotBlank; import javax.validation.constraints.NotNull; -import javax.validation.constraints.Size; import java.io.Serializable; import java.math.BigDecimal; import java.util.Date; @@ -25,6 +24,7 @@ import java.util.List; @Data @ApiModel(value = "出口进场基本表", description = "") @MoreThan(groups = {ValidationGroup.insert.class, ValidationGroup.update.class}, field1 = "quantity", field2 = "eachQuantity", message = "数量不得超过单票件数") +@DependsOn(groups = {ValidationGroup.insert.class, ValidationGroup.update.class}, field1 = "natureFlagName", fields = {"transferShipId", "transferShipName", "transferVoyageId", "transferVoyage"}, message = "货物性质为“正常”时,中转船ID,中转船名,中转航次ID,中转航次为空, 否则必填") public class ExportInVo implements Serializable { @ApiModelProperty(value = "是否直接提交审核") @@ -70,6 +70,27 @@ public class ExportInVo implements Serializable { @ApiModelProperty(value = "航次", required = true) private String voyage; + + @NotBlank(groups = {ValidationGroup.insert.class, ValidationGroup.update.class}, message = "货物性质ID不能为空") + @ApiModelProperty(value = "货物性质ID", required = true) + private String natureFlag; + + @NotBlank(groups = {ValidationGroup.insert.class, ValidationGroup.update.class}, message = "货物性质名称不能为空") + @ApiModelProperty(value = "货物性质名称", required = true) + private String natureFlagName; + + @ApiModelProperty(value = "中转船ID") + private String transferShipId; + + @ApiModelProperty(value = "中转船名") + private String transferShipName; + + @ApiModelProperty(value = "中转航次ID") + private String transferVoyageId; + + @ApiModelProperty(value = "中转航次名") + private String transferVoyage; + /** * 港区ID */ @@ -160,16 +181,14 @@ public class ExportInVo implements Serializable { @ApiModelProperty(value = "运输方式", required = true) private String transportWay; - @NotNull(groups = {ValidationGroup.insert.class, ValidationGroup.update.class}, message = "进场开始时间不能为空") - @ApiModelProperty(value = "进场开始时间", required = true) + @ApiModelProperty(value = "进场开始时间") @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") private Date beginEnterTime; /** * 进场开始时间 */ - @NotNull(groups = {ValidationGroup.insert.class, ValidationGroup.update.class}, message = "进场结束时间不能为空") - @ApiModelProperty(value = "进场结束时间", required = true) + @ApiModelProperty(value = "进场结束时间") @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") private Date endEnterTime; diff --git a/nuzar-customer-client/src/main/java/com/haitonggauto/rtosc/excel/ExportInBillSpareExcel.java b/nuzar-customer-client/src/main/java/com/haitonggauto/rtosc/excel/ExportInBillSpareExcel.java new file mode 100644 index 0000000..fb68600 --- /dev/null +++ b/nuzar-customer-client/src/main/java/com/haitonggauto/rtosc/excel/ExportInBillSpareExcel.java @@ -0,0 +1,32 @@ +package com.haitonggauto.rtosc.excel; + +import com.alibaba.excel.annotation.ExcelProperty; +import lombok.Data; + +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.Size; + +@Data +public class ExportInBillSpareExcel { + + @ExcelProperty("*船名") + @NotBlank(message = "船名不能为空") + private String shipName; + + @ExcelProperty("*航次") + @NotBlank(message = "航次不能为空") + private String voyage; + + @ExcelProperty("*提单号") + @NotBlank(message = "提单号不能为空") + private String billNo; + + @ExcelProperty("*品牌") + @NotBlank(message = "品牌不能为空") + private String brand; + + @ExcelProperty("*备件号") + @NotBlank(message = "备件号不能为空") + @Size(min = 17, max = 17, message = "备件号长度为17位") + private String vin; +} diff --git a/nuzar-customer-client/src/main/java/com/haitonggauto/rtosc/excel/ExportInPlanExcel.java b/nuzar-customer-client/src/main/java/com/haitonggauto/rtosc/excel/ExportInPlanExcel.java index 38527d6..334d3a8 100644 --- a/nuzar-customer-client/src/main/java/com/haitonggauto/rtosc/excel/ExportInPlanExcel.java +++ b/nuzar-customer-client/src/main/java/com/haitonggauto/rtosc/excel/ExportInPlanExcel.java @@ -3,6 +3,9 @@ package com.haitonggauto.rtosc.excel; import com.alibaba.excel.annotation.ExcelProperty; import com.alibaba.excel.annotation.format.DateTimeFormat; import com.alibaba.excel.annotation.format.NumberFormat; +import com.baomidou.mybatisplus.annotation.TableField; +import com.haitonggauto.rtosc.common.utils.ValidationGroup; +import com.haitonggauto.rtosc.common.validate.DependsOn; import io.swagger.annotations.ApiModelProperty; import lombok.Data; @@ -34,6 +37,7 @@ import java.util.Date; * 19.源类型必须是是新能源、不是新能源,否则的导入不成功 */ @Data +@DependsOn(field1 = "natureFlagName", fields = {"transferShipName", "transferVoyage"}, message = "货物性质为“正常”时,中转船ID,中转船名,中转航次ID,中转航次为空, 否则必填") public class ExportInPlanExcel { /** @@ -57,6 +61,16 @@ public class ExportInPlanExcel { @NotBlank(message = "航次不能为空") private String voyage; + @ExcelProperty("*货物性质") + @NotBlank(message = "货物性质不能为空") + private String natureFlagName; + + @ExcelProperty("中转进口船名") + private String transferShipName; + + @ExcelProperty("中转进口航次") + private String transferVoyage; + /** * 货代 diff --git a/nuzar-customer-client/src/main/java/com/haitonggauto/rtosc/excel/ExportInSpareExcel.java b/nuzar-customer-client/src/main/java/com/haitonggauto/rtosc/excel/ExportInSpareExcel.java new file mode 100644 index 0000000..52ab629 --- /dev/null +++ b/nuzar-customer-client/src/main/java/com/haitonggauto/rtosc/excel/ExportInSpareExcel.java @@ -0,0 +1,28 @@ +package com.haitonggauto.rtosc.excel; + +import com.alibaba.excel.annotation.ExcelProperty; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.Size; + + +/** + * 出口进场基本表 + * @TableName customer_export_in + */ +@Data +@ApiModel +public class ExportInSpareExcel { + /** + * 船名 + */ + @NotBlank(message = "备件号不能为空") + @Size(min = 17, max = 17, message = "备件号长度为17位") + @ApiModelProperty(value = "备件号") + @ExcelProperty("*备件号") + private String vin; + +} \ No newline at end of file diff --git a/nuzar-customer-client/src/main/java/com/haitonggauto/rtosc/excel/ExportLoadInsideExcel.java b/nuzar-customer-client/src/main/java/com/haitonggauto/rtosc/excel/ExportLoadInsideExcel.java index 8235ecd..ca2e1e6 100644 --- a/nuzar-customer-client/src/main/java/com/haitonggauto/rtosc/excel/ExportLoadInsideExcel.java +++ b/nuzar-customer-client/src/main/java/com/haitonggauto/rtosc/excel/ExportLoadInsideExcel.java @@ -1,6 +1,7 @@ package com.haitonggauto.rtosc.excel; import com.alibaba.excel.annotation.ExcelProperty; +import com.haitonggauto.rtosc.common.validate.DependsOn; import io.swagger.annotations.ApiModelProperty; import lombok.Data; @@ -8,6 +9,7 @@ import javax.validation.constraints.NotBlank; import javax.validation.constraints.Size; @Data +@DependsOn(field1 = "natureFlagName", fields = {"transferShipName", "transferVoyage"}, message = "货物性质为“正常”时,中转船ID,中转船名,中转航次ID,中转航次为空, 否则必填") public class ExportLoadInsideExcel { @ExcelProperty("*船名") @@ -18,6 +20,16 @@ public class ExportLoadInsideExcel { @NotBlank(message = "航次不能为空") private String voyage; + @ExcelProperty("*货物性质") + @NotBlank(message = "货物性质不能为空") + private String natureFlagName; + + @ExcelProperty("中转进口船名") + private String transferShipName; + + @ExcelProperty("中转进口航次") + private String transferVoyage; + @ExcelProperty("*港区") @NotBlank(message = "港区不能为空") private String portArea; @@ -30,7 +42,7 @@ public class ExportLoadInsideExcel { @NotBlank(message = "品牌不能为空") private String brand; - @ExcelProperty("*目的港") + @ExcelProperty("目的港") private String destPort; @ExcelProperty("*车架号") diff --git a/nuzar-customer-common/src/main/java/com/haitonggauto/rtosc/common/validate/DependsOn.java b/nuzar-customer-common/src/main/java/com/haitonggauto/rtosc/common/validate/DependsOn.java new file mode 100644 index 0000000..ff16e1b --- /dev/null +++ b/nuzar-customer-common/src/main/java/com/haitonggauto/rtosc/common/validate/DependsOn.java @@ -0,0 +1,32 @@ +package com.haitonggauto.rtosc.common.validate; + +import javax.validation.Constraint; +import javax.validation.Payload; +import java.lang.annotation.*; + +/** + * 一个字段依赖于另一个字段 + */ +@Target({ElementType.TYPE, ElementType.ANNOTATION_TYPE}) +@Retention(RetentionPolicy.RUNTIME) +@Documented +@Constraint(validatedBy = DependsOnValidator.class) +public @interface DependsOn { + + /** + * 违反校验时的错误信息 + */ + String message() default "{DependsOn.message}"; + + /** + * 用于指定校验的条件 + */ + Class[] groups() default {}; + + Class[] payload() default {}; + + // 比较字段一 + String field1(); + // 比较字段二 + String[] fields(); +} diff --git a/nuzar-customer-common/src/main/java/com/haitonggauto/rtosc/common/validate/DependsOnValidator.java b/nuzar-customer-common/src/main/java/com/haitonggauto/rtosc/common/validate/DependsOnValidator.java new file mode 100644 index 0000000..0b45f8b --- /dev/null +++ b/nuzar-customer-common/src/main/java/com/haitonggauto/rtosc/common/validate/DependsOnValidator.java @@ -0,0 +1,62 @@ +package com.haitonggauto.rtosc.common.validate; + +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.BeanWrapperImpl; + +import javax.validation.ConstraintValidator; +import javax.validation.ConstraintValidatorContext; + +public class DependsOnValidator implements ConstraintValidator { + // 字段一 + private String field1; + // 字段二 + private String[] fields; + + @Override + public void initialize(final DependsOn constraintAnnotation) { + field1 = constraintAnnotation.field1(); + fields = constraintAnnotation.fields(); + } + + @Override + public boolean isValid(final Object src, ConstraintValidatorContext context) { + BeanWrapperImpl wrapper = new BeanWrapperImpl(src); + + if (StringUtils.isAnyEmpty(field1, field1)) { + return false; + } + + Object value1 = wrapper.getPropertyValue(field1); + + if (value1 == null) { + for (String field : fields) { + String v = (String) wrapper.getPropertyValue(field); + if (StringUtils.isNotEmpty(v)) { + return false; + } + } + return true; + } + + if (value1 != null) { + if (StringUtils.equals("正常", (String)value1)) { + for (String field : fields) { + String v = (String) wrapper.getPropertyValue(field); + if (StringUtils.isNotEmpty(v)) { + return false; + } + } + } else { + for (String field : fields) { + String v = (String) wrapper.getPropertyValue(field); + if (StringUtils.isEmpty(v)) { + return false; + } + } + } + return true; + } + + return false; + } +} diff --git a/nuzar-customer-controller/src/main/java/com/haitonggauto/rtosc/api/NuzarPubApi.java b/nuzar-customer-controller/src/main/java/com/haitonggauto/rtosc/api/NuzarPubApi.java index e405b61..e4ac356 100644 --- a/nuzar-customer-controller/src/main/java/com/haitonggauto/rtosc/api/NuzarPubApi.java +++ b/nuzar-customer-controller/src/main/java/com/haitonggauto/rtosc/api/NuzarPubApi.java @@ -24,6 +24,10 @@ public interface NuzarPubApi { @GetMapping(value = "/typeRef/domain/TRADE_TYPE") List getTradType(); + // 获取获物性质 + @GetMapping(value = "/typeRef/domain/GOODS_NATURE") + List getGoodsNatureList(); + // 所有船舶 @GetMapping(value = "/shipManage/queryAllShipManage") List getAllShip(); @@ -63,4 +67,9 @@ public interface NuzarPubApi { // 根据客户名称查询客户信息 @GetMapping(value = "/customerManage/query/name") CompanyDTO getCompanyByName(@RequestParam("cueCnname") String cueCnname); + + // 船舶管理下拉框模糊查询 + @GetMapping(value = "/shipManage/queryLikeShipManage") + List getShipList(@RequestParam("key") String key, @RequestParam("query") String query, @RequestParam("spmId") String spmId + , @RequestParam("valid") String valid, @RequestParam("vslCd") String vslCd, @RequestParam("vslCnname") String vslCnname, @RequestParam("vslEnnameList") List vslEnnameList); } diff --git a/nuzar-customer-controller/src/main/java/com/haitonggauto/rtosc/api/NuzarShpApi.java b/nuzar-customer-controller/src/main/java/com/haitonggauto/rtosc/api/NuzarShpApi.java index c64d3f5..22c33f2 100644 --- a/nuzar-customer-controller/src/main/java/com/haitonggauto/rtosc/api/NuzarShpApi.java +++ b/nuzar-customer-controller/src/main/java/com/haitonggauto/rtosc/api/NuzarShpApi.java @@ -12,8 +12,8 @@ import org.springframework.web.bind.annotation.RequestParam; import java.util.List; -//@FeignClient(name = "https://rtops4.haitongauto.com/tos/shp") -@FeignClient(name = "shipment-service") +@FeignClient(name = "https://rtops4.haitongauto.com/tos/shp") +//@FeignClient(name = "shipment-service") public interface NuzarShpApi { @GetMapping("/vesselVoyages/queryVvyName") @@ -24,4 +24,9 @@ public interface NuzarShpApi { @PostMapping("/vesselVoyages/queryVvyListByVvNameAndSpmName") List queryVvyListByVvNameAndSpmName(@RequestBody List req); + + // 获取航次 + @GetMapping("/vesselVoyages/queryByKey") + List queryVoyageByKey(@RequestParam("ieType") String ieType, @RequestParam("key") String key, @RequestParam("pamId") String pamId, @RequestParam("spmId") String spmId + , @RequestParam("tradeType") String tradeType); } diff --git a/nuzar-customer-controller/src/main/java/com/haitonggauto/rtosc/handler/DictHandler.java b/nuzar-customer-controller/src/main/java/com/haitonggauto/rtosc/handler/DictHandler.java index c83b1e9..975e7ec 100644 --- a/nuzar-customer-controller/src/main/java/com/haitonggauto/rtosc/handler/DictHandler.java +++ b/nuzar-customer-controller/src/main/java/com/haitonggauto/rtosc/handler/DictHandler.java @@ -3,6 +3,7 @@ package com.haitonggauto.rtosc.handler; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.haitonggauto.rtosc.api.NuzarOpenApi; import com.haitonggauto.rtosc.api.NuzarPubApi; +import com.haitonggauto.rtosc.api.NuzarShpApi; import com.haitonggauto.rtosc.api.dto.*; import com.haitonggauto.rtosc.common.context.UserContext; import com.haitonggauto.rtosc.common.dto.DictDTO; @@ -41,15 +42,15 @@ import java.util.stream.Collectors; @Validated public class DictHandler implements BaseHandler { - @Resource - private LoginHandler loginHandler; - @Resource private NuzarPubApi nuzarPubApi; @Resource private NuzarOpenApi nuzarOpenApi; + @Resource + private NuzarShpApi nuzarShpApi; + @Resource private CustomerLinkmanService customerLinkmanService; @@ -446,4 +447,49 @@ public class DictHandler implements BaseHandler { } } + + @ApiOperation("货物性质") + @GetMapping("/goodsNature") + public Result> getGoodsNature() { + + List list = nuzarPubApi.getGoodsNatureList(); + + if (CollectionUtils.isEmpty(list)) { + return ResultUtil.success(Collections.emptyList()); + } else { + + } + + return ResultUtil.success(list); + } + + @ApiOperation("获取船名") + @GetMapping(value = "/shipManage/queryLikeShipManage") + public Result> getShipList(@RequestParam(value = "key", required = false) String key, @RequestParam(value = "query", required = false) String query, @RequestParam(value = "spmId", required = false) String spmId + , @RequestParam(value = "valid", required = false) String valid, @RequestParam(value = "vslCd", required = false) String vslCd, @RequestParam(value = "vslCnname", required = false) String vslCnname, @RequestParam(value = "vslEnnameList", required = false) List vslEnnameList) { + List list = nuzarPubApi.getShipList(key, query, spmId, valid, vslCd, vslCnname, vslEnnameList); + + if (CollectionUtils.isEmpty(list)) { + return ResultUtil.success(Collections.emptyList()); + } else { + + } + + return ResultUtil.success(list); + } + + @ApiOperation("获取航次") + @GetMapping("/vesselVoyages/queryByKey") + public Result> queryVoyageByKey(@RequestParam(value = "ieType", required = false) String ieType, @RequestParam(value = "key", required = false) String key, @RequestParam(value = "pamId", required = false) String pamId, @RequestParam(value = "spmId", required = false) String spmId + , @RequestParam(value = "tradeType", required = false) String tradeType) { + List list = nuzarShpApi.queryVoyageByKey(ieType, key, pamId, spmId, tradeType); + + if (CollectionUtils.isEmpty(list)) { + return ResultUtil.success(Collections.emptyList()); + } else { + + } + + return ResultUtil.success(list); + } } diff --git a/nuzar-customer-controller/src/main/java/com/haitonggauto/rtosc/handler/ExportInHandler.java b/nuzar-customer-controller/src/main/java/com/haitonggauto/rtosc/handler/ExportInHandler.java index 773f066..d8b3e2b 100644 --- a/nuzar-customer-controller/src/main/java/com/haitonggauto/rtosc/handler/ExportInHandler.java +++ b/nuzar-customer-controller/src/main/java/com/haitonggauto/rtosc/handler/ExportInHandler.java @@ -683,7 +683,7 @@ public class ExportInHandler implements BaseHandler { entity.setVinStatus(1); return entity; }).collect(Collectors.toList()); - if (CollectionUtils.isEmpty(spares) && StringUtils.equalsAnyIgnoreCase(exportIn.getCartType(), "备件", "BJ")) { + if (CollectionUtils.isEmpty(spares) && StringUtils.equalsAnyIgnoreCase(exportIn.getCartType(), "备件", "BJ") && StringUtils.equals("正常", exportIn.getNatureFlagName())) { // 出口进场计划备件条码生成的规则要变一下,BJ+年月日时分+5随机数,一共要17位 String prefix = StringUtils.join("BJ", DateUtil.format(new Date(), "yyMMddHHmm")); List vins = new ArrayList<>(exportIn.getQuantity()); @@ -931,6 +931,7 @@ public class ExportInHandler implements BaseHandler { */ @ApiOperation("编辑") @PostMapping("/edit") + @Transactional(rollbackFor = {Exception.class}) // 使用LambdaUpdateWrapper只在特定需求下做处理(推荐) 将字段修改为空值的处理方法 public Result edit(@RequestParam(required = false, defaultValue = "false") Boolean flag, @RequestBody @Validated(ValidationGroup.update.class) ExportInVo form) { @@ -954,6 +955,7 @@ public class ExportInHandler implements BaseHandler { if (in.getCheckStatus() == AuditEnum.AUDIT_PASS) { return ResultUtil.failure(ErrorType.PARAMS_ERROR.id(), "审核通过之后不能进行编辑"); } + String batchNo = in.getBatchNo(); // 表单验证以及格式转换 CustomerExportIn exportIn = PoMapper.instance.exportInVo2Entity(form); @@ -965,6 +967,9 @@ public class ExportInHandler implements BaseHandler { exportIn.setCheckStatus(AuditEnum.AUDIT); } + // 判断货物性质是否发生变化 + boolean f = StringUtils.equals(in.getNatureFlagName(), exportIn.getNatureFlagName()); + List cargos = form.getCargos().stream().map(item -> { CustomerExportInCargo entity = PoMapper.instance.exportInCargoVo2Entity(item); entity.setBrand(exportIn.getBrand()); @@ -997,7 +1002,7 @@ public class ExportInHandler implements BaseHandler { return entity; }).collect(Collectors.toList()); - if (CollectionUtils.isNotEmpty(spares)) { + if (CollectionUtils.isNotEmpty(spares) || (!f && StringUtils.equalsAnyIgnoreCase(exportIn.getCartType(), "备件", "BJ") && StringUtils.equalsAnyIgnoreCase(exportIn.getNatureFlagName(), "正常"))) { // 验证数量 if (exportIn.getQuantity() < spares.size()) { return ResultUtil.failure(ErrorType.PROGRAM_ERROR.id(), "备件列表不能大于备件总数"); @@ -1103,6 +1108,11 @@ public class ExportInHandler implements BaseHandler { } } + // 货物性质发生变化时,需要清空表 + if (!f && StringUtils.equalsAnyIgnoreCase(exportIn.getCartType(), "备件", "BJ")) { + customerExportInCargoService.lambdaUpdate().eq(CustomerExportInCargo::getExportInId, in.getId()).remove(); + } + customerService.updateExportIn(false, exportIn, cargos, times, spares); return ResultUtil.success(String.valueOf(exportIn.getId())); @@ -1840,7 +1850,7 @@ public class ExportInHandler implements BaseHandler { List existData = item.getValue().stream().filter(p -> existVins.contains(p.getVin())).collect(Collectors.toList()); if (CollectionUtils.isNotEmpty(existData)) { - errorDataList.addAll(item.getValue().stream().map(p -> { + errorDataList.addAll(existData.stream().map(p -> { JSONObject o = JSONObject.from(p); o.put("status", "数据已存在"); return o; @@ -1871,6 +1881,192 @@ public class ExportInHandler implements BaseHandler { return ResultUtil.success(errorDataList); } + @ApiOperation("备件号导入模板下载") + @GetMapping("/temp/down/spare") + public void tmpDownSpare(HttpServletResponse response) throws Exception { + ExcelWriter excelWriter = null; + OutputStream out = null; + try { + out = response.getOutputStream(); + + // 这里注意 有同学反应使用swagger 会导致各种问题,请直接用浏览器或者用postman + response.setContentType("application/vnd.ms-excel"); + response.setCharacterEncoding("utf-8"); + // 这里URLEncoder.encode可以防止中文乱码 当然和easyexcel没有关系 + String fileName = URLEncoder.encode("备件号导入模板", "UTF-8"); + response.setHeader("Content-disposition", "attachment;filename=" + fileName + ".xlsx"); + + excelWriter = EasyExcel.write(out).build(); + + WriteSheet writeSheet = EasyExcel.writerSheet(0, "备件号").head(ExportInSpareExcel.class).build(); + + // 查询数据 + List rows = new ArrayList<>(); + + excelWriter.write(rows, writeSheet); + } catch (Exception e) { + e.printStackTrace(); + } finally { + if (excelWriter != null) { + excelWriter.finish(); + } + if (out != null) { + try { + out.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + } + } + + @ApiOperation("备件号导入") + @PostMapping("/import-spare") + public Result> importSpare(@RequestParam(required = false) @NotNull(message = "出口进场ID不能为空") Long id, MultipartFile file) throws IOException { + CustomerExportIn exportIn = customerExportInService.getById(id); + + List havePlans = openApi.haveShipPlan(exportIn.getVoyageId()); + if (exportIn != null && CollectionUtils.isNotEmpty(havePlans)) { + Boolean c = havePlans.contains(exportIn.getId()); + if (c) { + return ResultUtil.failure(ErrorType.PARAMS_ERROR.id(), "已生成装船计划,不能导入"); + } + } + + // 所有读取的数据 + List dataList = new ArrayList<>(); + + // 有错误的数据 + List errorDataList = new ArrayList<>(); + + // 验证成功的数据 + List successDataList = new ArrayList<>(); + + // 要存储的数据 + List saveCargos = new ArrayList<>(); + + EasyExcel.read(file.getInputStream(), ExportInSpareExcel.class, new ReadExcelListener() { + @Override + protected void saveData(List list) { // 缓存数据 + dataList.addAll(list); + } + }).sheet().doRead(); + + ValidatorFactory vf = Validation.buildDefaultValidatorFactory(); + Validator validator = vf.getValidator(); + + List validData = new ArrayList<>(); + + // 数据验证 + dataList.stream().forEach(item -> { + Set> set = validator.validate(item); + if (CollectionUtils.isEmpty(set)) { // 验证通过的 + validData.add(item); + } else { // 验证失败的 + JSONObject o = JSONObject.from(item); + o.put("status", set.stream().map(p -> p.getMessage()).collect(Collectors.joining(","))); + errorDataList.add(o); + } + }); + + if (CollectionUtils.isEmpty(validData)) { + return ResultUtil.failure(ErrorType.PARAMS_ERROR.id(), "导入失败", errorDataList); + } + + // 是否有重复的车架号 + List repeat = validData.stream().collect(Collectors.groupingBy(ExportInSpareExcel::getVin, Collectors.counting())) + .entrySet().stream().filter(entry -> entry.getValue() > 1).map(entry -> entry.getKey()).collect(Collectors.toList()); + if (CollectionUtils.isNotEmpty(repeat)) { + errorDataList.addAll(validData.stream().filter(p -> repeat.contains(p.getVin())).map(p -> { + JSONObject o = JSONObject.from(p); + o.put("status", "车架号重复"); + return o; + }).collect(Collectors.toList())); + return ResultUtil.failure(ErrorType.PARAMS_ERROR.id(), "导入失败", errorDataList); + } + + if (exportIn.getQuantity() != validData.size()) { + errorDataList.addAll(validData.stream().map(p -> { + JSONObject o = JSONObject.from(p); + o.put("status", "数量不一致"); + return o; + }).collect(Collectors.toList())); + return ResultUtil.failure(ErrorType.PARAMS_ERROR.id(), "导入失败", errorDataList); + } + + List cargos = validData.stream().map(p -> { + CustomerExportInCargo cargo = new CustomerExportInCargo(); + cargo.setExportInId(exportIn.getId()); + cargo.setBrand(exportIn.getBrand()); + cargo.setBrandId(exportIn.getBrandId()); + cargo.setCargoType(0); + cargo.setVin(p.getVin()); + cargo.setTermcd(exportIn.getPortAreaId()); + cargo.setVinStatus(1); + return cargo; + }).collect(Collectors.toList()); + + List vins = cargos.stream().map(p -> p.getVin()).collect(Collectors.toList()); + + // 验证哪些车架号已经存在了 + List existCargos = customerExportInCargoService.list(new LambdaQueryWrapper().in(CustomerExportInCargo::getVin, vins).ne(CustomerExportInCargo::getExportInId, exportIn.getId())); + List existVins = existCargos.stream().map(p -> p.getVin()).collect(Collectors.toList()); + + if (CollectionUtils.isNotEmpty(existCargos)) { + // 查询出对应的港区 + List sList = customerExportInService.lambdaQuery().in(CustomerExportIn::getId, existCargos.stream().map(ss -> ss.getExportInId()).collect(Collectors.toList())).list(); + Map portAreaMap = sList.stream().collect(Collectors.toMap(CustomerExportIn::getId, CustomerExportIn::getPortAreaId)); + // 通过接口再次验证 + List req = existCargos.stream().map(ss -> { + CheckVinReq v = new CheckVinReq(); + v.setIsRepetition(true); + v.setPamId(portAreaMap.get(ss.getExportInId())); + v.setVinCode(ss.getVin()); + return v; + }).collect(Collectors.toList()); + List rst = shpApi.checkVinRepeat(req); + existVins.clear(); + if (CollectionUtils.isNotEmpty(rst)) { + // 再次过滤出重复的 + List sCollect = rst.stream().filter(ss -> ss.getIsRepetition()).collect(Collectors.toList()); + if (CollectionUtils.isNotEmpty(sCollect)) { + existVins.addAll(sCollect.stream().map(ss -> ss.getVinCode()).collect(Collectors.toList())); + } + } + } + + List existData = validData.stream().filter(p -> existVins.contains(p.getVin())).collect(Collectors.toList()); + if (CollectionUtils.isNotEmpty(existData)) { + errorDataList.addAll(existData.stream().map(p -> { + JSONObject o = JSONObject.from(p); + o.put("status", "数据已存在"); + return o; + }).collect(Collectors.toList())); + } + + successDataList.addAll(validData.stream().filter(p -> !existVins.contains(p.getVin())) + .map(p -> { + JSONObject o = JSONObject.from(p); + o.put("status", "数据验证成功"); + return o; + }).collect(Collectors.toList())); + + saveCargos.addAll(cargos.stream().filter(p -> !existVins.contains(p.getVin())).collect(Collectors.toList())); + + if (CollectionUtils.isNotEmpty(errorDataList)) { + errorDataList.addAll(successDataList); + return ResultUtil.failure(ErrorType.PARAMS_ERROR.id(), "导入失败", errorDataList); + } + + if (CollectionUtils.isNotEmpty(saveCargos)) { + // 删除原有的车架号 + customerExportInCargoService.lambdaUpdate().eq(CustomerExportInCargo::getExportInId, exportIn.getId()).remove(); + customerExportInCargoService.saveBatch(saveCargos); + } + + return ResultUtil.success(errorDataList); + } + @ApiOperation("整船清单导入模板下载") @GetMapping("/temp/down/ship") public void tmpDownShip(HttpServletResponse response) throws Exception { @@ -2095,7 +2291,268 @@ public class ExportInHandler implements BaseHandler { List existData = item.getValue().stream().filter(p -> existVins.contains(p.getVin())).collect(Collectors.toList()); if (CollectionUtils.isNotEmpty(existData)) { - errorDataList.addAll(item.getValue().stream().filter(p -> existVins.contains(p.getVin())).map(p -> { + errorDataList.addAll(existData.stream().map(p -> { + JSONObject o = JSONObject.from(p); + o.put("status", "数据已存在, 未导入"); + return o; + }).collect(Collectors.toList())); + successDataList.addAll(item.getValue().stream().filter(p -> !existVins.contains(p.getVin())) + .map(p -> { + JSONObject o = JSONObject.from(p); + o.put("status", "数据验证成功"); + return o; + }).collect(Collectors.toList())); + return; + } else { + successDataList.addAll(item.getValue().stream().filter(p -> !existVins.contains(p.getVin())) + .map(p -> { + JSONObject o = JSONObject.from(p); + o.put("status", "数据验证成功"); + return o; + }).collect(Collectors.toList())); + } + + saveCargos.addAll(cargos.stream().filter(p -> !existVins.contains(p.getVin())).collect(Collectors.toList())); + + }); + + if (CollectionUtils.isNotEmpty(errorDataList)) { + errorDataList.addAll(successDataList); + return ResultUtil.failure(ErrorType.PARAMS_ERROR.id(), "导入失败", errorDataList); + } + + if (CollectionUtils.isNotEmpty(saveCargos)) { + // 删除原有的车架号 + customerExportInCargoService.lambdaUpdate().in(CustomerExportInCargo::getExportInId, ids).remove(); + customerExportInCargoService.saveBatch(saveCargos); + } + + return ResultUtil.success(errorDataList); + } + + @ApiOperation("整票备件号导入模板下载") + @GetMapping("/temp/spare/down/ship") + public void tmpDownShipSpare(HttpServletResponse response) throws Exception { + ExcelWriter excelWriter = null; + OutputStream out = null; + try { + out = response.getOutputStream(); + + // 这里注意 有同学反应使用swagger 会导致各种问题,请直接用浏览器或者用postman + response.setContentType("application/vnd.ms-excel"); + response.setCharacterEncoding("utf-8"); + // 这里URLEncoder.encode可以防止中文乱码 当然和easyexcel没有关系 + String fileName = URLEncoder.encode("整票备件号导入模板", "UTF-8"); + response.setHeader("Content-disposition", "attachment;filename=" + fileName + ".xlsx"); + + excelWriter = EasyExcel.write(out).build(); + + WriteSheet writeSheet = EasyExcel.writerSheet(0, "整票备件号").head(ExportInBillSpareExcel.class).build(); + + // 查询数据 + List rows = new ArrayList<>(); + + excelWriter.write(rows, writeSheet); + } catch (Exception e) { + e.printStackTrace(); + } finally { + if (excelWriter != null) { + excelWriter.finish(); + } + if (out != null) { + try { + out.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + } + } + + @ApiOperation("整票备件号导入") + @PostMapping("/import-to-add/spare") + public Result> uploadSpare( + @ApiParam(name = "操作方式, 0为前端,1为审核端") @RequestParam(required = false, defaultValue = "0") String type, + MultipartFile file) throws IOException { + // 所有读取的数据 + List dataList = new ArrayList<>(); + + // 有错误的数据 + List errorDataList = new ArrayList<>(); + + // 验证成功的数据 + List successDataList = new ArrayList<>(); + + // 需要清空的 + List ids = new ArrayList<>(); + + // 要保存到数据库的数据 + List saveCargos = new ArrayList<>(); + + EasyExcel.read(file.getInputStream(), ExportLoadExcel.class, new ReadExcelListener() { + @Override + protected void saveData(List list) { // 保存数据 + dataList.addAll(list); + } + }).sheet().doRead(); + + ValidatorFactory vf = Validation.buildDefaultValidatorFactory(); + Validator validator = vf.getValidator(); + + List validData = new ArrayList<>(); + + // 数据验证 + dataList.stream().forEach(item -> { + Set> set = validator.validate(item); + if (CollectionUtils.isEmpty(set)) { // 验证通过的 + validData.add(item); + } else { // 验证失败的 + JSONObject o = JSONObject.from(item); + o.put("status", set.stream().map(p -> p.getMessage()).collect(Collectors.joining(","))); + errorDataList.add(o); + } + }); + + // 所有数据验证都不通过 + if (CollectionUtils.isEmpty(validData)) { + return ResultUtil.failure(ErrorType.PARAMS_ERROR.id(), "导入失败", errorDataList); + } + + // 首先按对船名,般次,提单进行分组 + Map> collect = validData.stream() + .collect(Collectors.groupingBy(item -> StringUtils.joinWith("#$#", item.getShipName(), item.getVoyage(), item.getBillNo(), item.getBrand()), Collectors.toList())); + + collect.entrySet().forEach(item -> { + String[] keys = StringUtils.split(item.getKey(), "#$#"); + String shipName = keys[0]; // 船名 + String voyage = keys[1]; // 航次 + String billNo = keys[2]; // 提单号 + String brand = keys[3]; // 品牌 + // 找到是否存在船名,航次,提单号的表头 + + LambdaQueryWrapper cQuery = new LambdaQueryWrapper<>(); + cQuery.eq(CustomerExportIn::getShipName, shipName) + .eq(CustomerExportIn::getVoyage, voyage) + .eq(CustomerExportIn::getBillNum, billNo) + .eq(CustomerExportIn::getBrand, brand) + .eq(CustomerExportIn::getCartType, "备件"); // 备件的不允许整船导入 + if (StringUtils.equals(type, "0")) { + cQuery.and((wrapper) -> { + wrapper.eq(CustomerExportIn::getCheckStatus, AuditEnum.SUBMIT) + .or() + .eq(CustomerExportIn::getCheckStatus, AuditEnum.AUDIT_REJECT); + }); + } else { + cQuery.and((wrapper) -> { + wrapper.eq(CustomerExportIn::getCheckStatus, AuditEnum.AUDIT) + .or() + .eq(CustomerExportIn::getCheckStatus, AuditEnum.AUDIT_REJECT); + }); + } + + List exportInList = customerExportInService.list(cQuery); + + if (CollectionUtils.isEmpty(exportInList)) { // 船名,航次等不存在 + errorDataList.addAll(item.getValue().stream().map(p -> { + JSONObject o = JSONObject.from(p); + o.put("status", "船名、航次、提单号、品牌不存在"); + return o; + }).collect(Collectors.toList())); + return; + } + + // 找到和本次数量一致的 + Optional first = exportInList.stream().filter(p -> p.getQuantity() == item.getValue().size()).findFirst(); + + CustomerExportIn exportIn = first.isPresent() ? first.get() : null; + + if (exportIn == null) { + errorDataList.addAll(item.getValue().stream().map(p -> { + JSONObject o = JSONObject.from(p); + o.put("status", "数量不一致不允许导入"); + return o; + }).collect(Collectors.toList())); + return; + } + + ids.add(exportIn.getId()); + + // 已生成装船计划,不能导入 + List havePlans = openApi.haveShipPlan(exportIn.getVoyageId()); + if (exportIn != null && CollectionUtils.isNotEmpty(havePlans)) { + Boolean c = havePlans.contains(exportIn.getId()); + if (c) { + errorDataList.addAll(item.getValue().stream().map(p -> { + JSONObject o = JSONObject.from(p); + o.put("status", "已生成装船计划,不能导入"); + return o; + }).collect(Collectors.toList())); + return; + } + } + + if (exportIn.getCheckStatus() == AuditEnum.AUDIT_PASS) { // 审核 + errorDataList.addAll(item.getValue().stream().map(p -> { + JSONObject o = JSONObject.from(p); + o.put("status", "审核通过状态的不可导入"); + return o; + }).collect(Collectors.toList())); + return; + } + + if (exportIn.getEnterQuantity() != item.getValue().size()) { + errorDataList.addAll(item.getValue().stream().map(p -> { + JSONObject o = JSONObject.from(p); + o.put("status", "车架号数量和实际货物数量不符合,无法导入"); + return o; + }).collect(Collectors.toList())); + return; + } + + List cargos = item.getValue().stream().map(p -> { + CustomerExportInCargo cargo = new CustomerExportInCargo(); + cargo.setBrandId(exportIn.getBrandId()); + cargo.setBrand(exportIn.getBrand()); + cargo.setExportInId(exportIn.getId()); + cargo.setCargoType(1); + cargo.setVin(p.getVin()); + cargo.setTermcd(exportIn.getPortAreaId()); + cargo.setVinStatus(1); + return cargo; + }).collect(Collectors.toList()); + + List vins = cargos.stream().map(p -> p.getVin()).collect(Collectors.toList()); + + // 验证哪些车架号已经存在了 + List existCargos = customerExportInCargoService.list(new LambdaQueryWrapper().in(CustomerExportInCargo::getVin, vins).ne(CustomerExportInCargo::getExportInId, exportIn.getId())); + List existVins = existCargos.stream().map(p -> p.getVin()).collect(Collectors.toList()); + + if (CollectionUtils.isNotEmpty(existCargos)) { + // 查询出对应的港区 + List sList = customerExportInService.lambdaQuery().in(CustomerExportIn::getId, existCargos.stream().map(ss -> ss.getExportInId()).collect(Collectors.toList())).list(); + Map portAreaMap = sList.stream().collect(Collectors.toMap(CustomerExportIn::getId, CustomerExportIn::getPortAreaId)); + // 通过接口再次验证 + List req = existCargos.stream().map(ss -> { + CheckVinReq v = new CheckVinReq(); + v.setIsRepetition(true); + v.setPamId(portAreaMap.get(ss.getExportInId())); + v.setVinCode(ss.getVin()); + return v; + }).collect(Collectors.toList()); + List rst = shpApi.checkVinRepeat(req); + existVins.clear(); // 先清空 + if (CollectionUtils.isNotEmpty(rst)) { + // 再次过滤出重复的 + List sCollect = rst.stream().filter(ss -> ss.getIsRepetition()).collect(Collectors.toList()); + if (CollectionUtils.isNotEmpty(sCollect)) { + existVins.addAll(sCollect.stream().map(ss -> ss.getVinCode()).collect(Collectors.toList())); + } + } + } + + List existData = item.getValue().stream().filter(p -> existVins.contains(p.getVin())).collect(Collectors.toList()); + if (CollectionUtils.isNotEmpty(existData)) { + errorDataList.addAll(existData.stream().map(p -> { JSONObject o = JSONObject.from(p); o.put("status", "数据已存在, 未导入"); return o; @@ -2481,9 +2938,12 @@ public class ExportInHandler implements BaseHandler { Map portCountryList = new HashMap<>(); // 货代列表 Map companyMap = new HashMap<>(); - + // 货物性质 + List goodsNature = dictHandler.getGoodsNature().getData(); // 车型明细缓存 Map> carDetailTypeList = new HashMap<>(); + // 航次缴存 + Map> voyageMap = new HashMap<>(); EasyExcel.read(file.getInputStream(), ExportInPlanExcel.class, new ReadExcelListener() { @Override @@ -2606,6 +3066,30 @@ public class ExportInHandler implements BaseHandler { errorDataList.add(o); return; } + if (goodsNature.stream().filter(p -> StringUtils.equalsIgnoreCase(p.getPtrDesc(), item.getNatureFlagName())).count() == 0) { + JSONObject o = JSONObject.from(item); + o.put("status", "货物性质不存在"); + errorDataList.add(o); + return; + } + if (!StringUtils.equals(item.getNatureFlagName(), "正常")) { + if (shipList.stream().filter(p -> StringUtils.equalsIgnoreCase(p.getText(), item.getTransferShipName())).count() == 0) { + JSONObject o = JSONObject.from(item); + o.put("status", "中转进口船名不存在"); + errorDataList.add(o); + return; + } + if (!voyageMap.containsKey(item.getTransferShipName())) { + List data = dictHandler.queryVoyageByKey(null, null, null, shipList.stream().filter(p -> StringUtils.equalsIgnoreCase(p.getText(), item.getTransferShipName())).findFirst().get().getId(), null).getData(); + voyageMap.put(item.getTransferShipName(), data); + } + if (voyageMap.get(item.getTransferShipName()).stream().filter(p -> StringUtils.equalsIgnoreCase(p.getVvyName(), item.getTransferVoyage())).count() == 0) { + JSONObject o = JSONObject.from(item); + o.put("status", "中转进口航次不存在"); + errorDataList.add(o); + return; + } + } Date bDate = DateUtils.parseDate(StringUtils.trim(item.getBeginEnterTime()), "yyyy/MM/dd"); if (bDate == null) { JSONObject o = JSONObject.from(item); @@ -2683,6 +3167,11 @@ public class ExportInHandler implements BaseHandler { in.setApplicantId(UserContext.getUser().getUserId()); in.setTermcd(in.getPortAreaId()); in.setVolume(in.getLength().multiply(in.getWidth()).multiply(in.getHeight()).setScale(4, RoundingMode.HALF_UP)); // 计算体积 + in.setNatureFlag(goodsNature.stream().filter(p -> StringUtils.equalsIgnoreCase(p.getPtrDesc(), item.getNatureFlagName())).findFirst().get().getPtrCode()); + if (!StringUtils.equals(item.getNatureFlagName(), "正常")) { + in.setTransferShipId(shipList.stream().filter(p -> StringUtils.equalsIgnoreCase(p.getText(), item.getTransferShipName())).findFirst().get().getId()); + in.setTransferVoyageId(voyageMap.get(in.getTransferShipName()).stream().filter(p -> StringUtils.equalsIgnoreCase(p.getVvyName(), item.getTransferVoyage())).findFirst().get().getVvyId()); + } if (in.getEnterQuantity() == null) { in.setEnterQuantity(in.getQuantity()); } @@ -2756,7 +3245,7 @@ public class ExportInHandler implements BaseHandler { // 如果是备件自动生成条码 // 过滤出是备件的 - item.getValue().stream().filter(ss -> StringUtils.equals(ss.getCartType(), "备件")).forEach(ss -> { + item.getValue().stream().filter(ss -> StringUtils.equals(ss.getCartType(), "备件") && StringUtils.equals(ss.getNatureFlagName(), "正常")).forEach(ss -> { // 判断是否是国际中转航次ID String vvyId = ss.getVoyageId(); TransitPartRequest request = new TransitPartRequest(); diff --git a/nuzar-customer-controller/src/main/java/com/haitonggauto/rtosc/handler/ExportLoadHandler.java b/nuzar-customer-controller/src/main/java/com/haitonggauto/rtosc/handler/ExportLoadHandler.java index e4dd2cf..2f7b55a 100644 --- a/nuzar-customer-controller/src/main/java/com/haitonggauto/rtosc/handler/ExportLoadHandler.java +++ b/nuzar-customer-controller/src/main/java/com/haitonggauto/rtosc/handler/ExportLoadHandler.java @@ -26,6 +26,7 @@ import com.haitonggauto.rtosc.common.utils.ValidationGroup; import com.haitonggauto.rtosc.common.utils.WrapperKit; import com.haitonggauto.rtosc.dto.*; import com.haitonggauto.rtosc.excel.*; +import com.haitonggauto.rtosc.handler.excel.CustomCellWriteHandler; import com.haitonggauto.rtosc.query.CargoQuery; import com.haitonggauto.rtosc.query.ExportInCheckQuery; import com.haitonggauto.rtosc.query.ExportLoadCheckQuery; @@ -1406,7 +1407,20 @@ public class ExportLoadHandler implements BaseHandler { String fileName = URLEncoder.encode("内贸整船车辆导入模板", "UTF-8"); response.setHeader("Content-disposition", "attachment;filename=" + fileName + ".xlsx"); - excelWriter = EasyExcel.write(out).build(); + //普通下拉数据 + Map map = new HashMap<>(); + String[] isZgArray = {"是", "否"}; + map.put(3, isZgArray); + //检查类型-子类 + Map> inspNameMap = new HashMap<>(); + //检查类型-父类 + String[] proInspNameMap = new String[0]; + //问题属性 + Map> probPropsNameMap = new HashMap<>(); + + excelWriter = EasyExcel.write(out) + .registerWriteHandler(new CustomCellWriteHandler(map, proInspNameMap, inspNameMap, probPropsNameMap)) + .build(); WriteSheet writeSheet = EasyExcel.writerSheet(0, "内贸整船车辆导入模板").head(ExportLoadInsideExcel.class).build(); @@ -1457,9 +1471,14 @@ public class ExportLoadHandler implements BaseHandler { List shipList = dictHandler.getAllShip(null).getData(); // 港区基础数据 List portAreaList = dictHandler.getPortAreaList(null).getData(); + // 货物性质 + List goodsNature = dictHandler.getGoodsNature().getData(); // 缓存航次信息 Map voyageMap = new HashMap<>(); + // 缓存中转航次信息 + Map> transferVoyageMap = new HashMap<>(); + EasyExcel.read(file.getInputStream(), ExportLoadInsideExcel.class, new ReadExcelListener() { @Override protected void saveData(List list) { // 保存数据 @@ -1541,6 +1560,31 @@ public class ExportLoadHandler implements BaseHandler { errorDataList.add(o); return; } + if (goodsNature.stream().filter(p -> StringUtils.equalsIgnoreCase(p.getPtrDesc(), item.getNatureFlagName())).count() == 0) { + JSONObject o = JSONObject.from(item); + o.put("status", "货物性质不存在"); + errorDataList.add(o); + return; + } + if (!StringUtils.equals(item.getNatureFlagName(), "正常")) { + if (shipList.stream().filter(p -> StringUtils.equalsIgnoreCase(p.getText(), item.getTransferShipName())).count() == 0) { + JSONObject o = JSONObject.from(item); + o.put("status", "中转进口船名不存在"); + errorDataList.add(o); + return; + } + if (!transferVoyageMap.containsKey(item.getTransferShipName())) { + List data = dictHandler.queryVoyageByKey(null, null, null, shipList.stream().filter(p -> StringUtils.equalsIgnoreCase(p.getText(), item.getTransferShipName())).findFirst().get().getId(), null).getData(); + transferVoyageMap.put(item.getTransferShipName(), data); + } + if (transferVoyageMap.get(item.getTransferShipName()).stream().filter(p -> StringUtils.equalsIgnoreCase(p.getVvyName(), item.getTransferVoyage())).count() == 0) { + JSONObject o = JSONObject.from(item); + o.put("status", "中转进口航次不存在"); + errorDataList.add(o); + return; + } + } + if (CollectionUtils.containsAny(list, item.getSettleCompName())) { JSONObject o = JSONObject.from(item); o.put("status", "相同提单号需保持结费单位相同"); @@ -1684,6 +1728,11 @@ public class ExportLoadHandler implements BaseHandler { exportLoad.setPortArea(item.getValue().get(0).getPortArea()); exportLoad.setContact(item.getValue().get(0).getContact()); exportLoad.setContactPhone(item.getValue().get(0).getContactPhone()); + exportLoad.setNatureFlag(goodsNature.stream().filter(p -> StringUtils.equalsIgnoreCase(p.getPtrDesc(), item.getValue().get(0).getNatureFlagName())).findFirst().get().getPtrCode()); + if (!StringUtils.equals(item.getValue().get(0).getNatureFlagName(), "正常")) { + exportLoad.setTransferShipId(shipList.stream().filter(p -> StringUtils.equalsIgnoreCase(p.getText(), item.getValue().get(0).getTransferShipName())).findFirst().get().getId()); + exportLoad.setTransferVoyageId(transferVoyageMap.get(exportLoad.getTransferShipName()).stream().filter(p -> StringUtils.equalsIgnoreCase(p.getVvyName(), item.getValue().get(0).getTransferVoyage())).findFirst().get().getVvyId()); + } if (StringUtils.isNotEmpty(item.getValue().get(0).getDestPort())) { // 内贸目的港可以为空 exportLoad.setDestPort(item.getValue().get(0).getDestPort()); exportLoad.setDestPortId(portList.stream().filter(s -> StringUtils.equals(s.getText(), item.getValue().get(0).getDestPort())).findFirst().get().getId()); diff --git a/nuzar-customer-controller/src/main/java/com/haitonggauto/rtosc/handler/excel/CustomCellWriteHandler.java b/nuzar-customer-controller/src/main/java/com/haitonggauto/rtosc/handler/excel/CustomCellWriteHandler.java new file mode 100644 index 0000000..fd1f708 --- /dev/null +++ b/nuzar-customer-controller/src/main/java/com/haitonggauto/rtosc/handler/excel/CustomCellWriteHandler.java @@ -0,0 +1,214 @@ +package com.haitonggauto.rtosc.handler.excel; + +import com.alibaba.excel.write.handler.SheetWriteHandler; +import com.alibaba.excel.write.metadata.holder.WriteSheetHolder; +import com.alibaba.excel.write.metadata.holder.WriteWorkbookHolder; +import org.apache.poi.ss.usermodel.*; +import org.apache.poi.ss.util.CellRangeAddressList; + +import java.util.Iterator; +import java.util.List; +import java.util.Map; + +public class CustomCellWriteHandler implements SheetWriteHandler { + /** + * 普通下拉数据 + */ + private Map map; + + /** + * 检查类型-父类 + */ + private String[] proInspNameArray; + + /** + * 检查类型-子类 + */ + private Map> inspNameArray; + + /** + * 问题属性 + */ + private Map> probPropsNameArray; + + public CustomCellWriteHandler(Map map, String[] proInspNameArray, Map> inspNameArray, Map> probPropsNameArray) { + this.map = map; + this.proInspNameArray = proInspNameArray; + this.inspNameArray = inspNameArray; + this.probPropsNameArray = probPropsNameArray; + } + + @Override + public void beforeSheetCreate(WriteWorkbookHolder writeWorkbookHolder, WriteSheetHolder writeSheetHolder) { + + } + + @Override + public void afterSheetCreate(WriteWorkbookHolder writeWorkbookHolder, WriteSheetHolder writeSheetHolder) { + // 获取第一个sheet页 + Sheet sheet = writeSheetHolder.getCachedSheet(); + // 获取sheet页的数据校验对象 + DataValidationHelper helper = sheet.getDataValidationHelper(); + // 获取工作簿对象,用于创建存放下拉数据的字典sheet数据页 + Workbook workbook = writeWorkbookHolder.getWorkbook(); + + // 普通数据,迭代索引,用于存放下拉数据的字典sheet数据页命名 + int index = 1; + for (Map.Entry entry : map.entrySet()) { + + // 设置存放下拉数据的字典sheet,并把这些sheet隐藏掉,这样用户交互更友好 + String dictSheetName = "dict_hide_sheet" + index; + Sheet dictSheet = workbook.createSheet(dictSheetName); + // 隐藏字典sheet页 + workbook.setSheetHidden(index++, true); + + // 设置下拉列表覆盖的行数,从第一行开始到最后一行,这里注意,Excel行的 + // 索引是从0开始的,我这边第0行是标题行,第1行开始时数据化,可根据实 + // 际业务设置真正的数据开始行,如果要设置到最后一行,那么一定注意, + // 最后一行的行索引是1048575,千万别写成1048576,不然会导致下拉列表 + // 失效,出不来 + CellRangeAddressList infoList = new CellRangeAddressList(1, 1048575, entry.getKey(), entry.getKey()); + int rowLen = entry.getValue().length; + for (int i = 0; i < rowLen; i++) { + // 向字典sheet写数据,从第一行开始写,此处可根据自己业务需要,自定 + // 义从第几行还是写,写的时候注意一下行索引是从0开始的即可 + dictSheet.createRow(i).createCell(0).setCellValue(entry.getValue()[i]); + } + + // 设置关联数据公式,这个格式跟Excel设置有效性数据的表达式是一样的 + String refers = dictSheetName + "!$A$1:$A$" + entry.getValue().length; + Name name = workbook.createName(); + name.setNameName(dictSheetName); + // 将关联公式和sheet页做关联 + name.setRefersToFormula(refers); + + // 将上面设置好的下拉列表字典sheet页和目标sheet关联起来 + DataValidationConstraint constraint = helper.createFormulaListConstraint(dictSheetName); + setValidation(sheet, helper, constraint, infoList); + } + + + //检查类型-父类 + Sheet hideSheet = workbook.createSheet("site"); + workbook.setSheetHidden(workbook.getSheetIndex(hideSheet), false); + // 将具体的数据写入到每一行中,行开头为父级区域,后面是子区域。 + int rowId = 0; + Row proviRow = hideSheet.createRow(rowId++); + proviRow.createCell(0).setCellValue("大类列表"); + for (int i = 0; i < proInspNameArray.length; i++) { + Cell proviCell = proviRow.createCell(i + 1); + proviCell.setCellValue(proInspNameArray[i]); + } + //检查类型-子类 + Iterator keyIterator = inspNameArray.keySet().iterator(); + while (keyIterator.hasNext()) { + String key = keyIterator.next(); + List son = inspNameArray.get(key); + + Row row = hideSheet.createRow(rowId++); + row.createCell(0).setCellValue(key); + for (int i = 0; i < son.size(); i++) { + Cell cell = row.createCell(i + 1); + cell.setCellValue(son.get(i)); + } + // 添加名称管理器 + String range = getRange(1, rowId, son.size()); + Name name = workbook.createName(); + name.setNameName(key); + String formula = "site!" + range; + name.setRefersToFormula(formula); + } + + //问题属性 + Iterator probPropsNameIterator = probPropsNameArray.keySet().iterator(); + while (probPropsNameIterator.hasNext()) { + String key = probPropsNameIterator.next(); + List son = probPropsNameArray.get(key); + + Row row = hideSheet.createRow(rowId++); + row.createCell(0).setCellValue(key); + for (int i = 0; i < son.size(); i++) { + Cell cell = row.createCell(i + 1); + cell.setCellValue(son.get(i)); + } + // 添加名称管理器 + String range = getRange(1, rowId, son.size()); + Name name = workbook.createName(); + name.setNameName(key); + String formula = "site!" + range; + name.setRefersToFormula(formula); + } + + ///开始设置(大类小类)下拉框 + DataValidationHelper dvHelper = sheet.getDataValidationHelper(); + // 大类规则 + DataValidationConstraint expConstraint = dvHelper.createExplicitListConstraint(proInspNameArray); + CellRangeAddressList expRangeAddressList = new CellRangeAddressList(1, 1048575, 3, 3); + setValidation(sheet, dvHelper, expConstraint, expRangeAddressList); + + //检查类型-子类 + // 小类规则(各单元格按个设置) + // "INDIRECT($A$" + 2 + ")" 表示规则数据会从名称管理器中获取key与单元格 A2 值相同的数据,如果A2是浙江省,那么此处就是浙江省下面的市 + // 为了让每个单元格的公式能动态适应,使用循环挨个给公式。 + // 循环几次,就有几个单元格生效,次数要和上面的大类影响行数一一对应,要不然最后几个没对上的单元格实现不了级联 + for (int i = 2; i < inspNameArray.size() + 10; i++) { + CellRangeAddressList rangeAddressList = new CellRangeAddressList(i-1 , i-1, 4, 4); + DataValidationConstraint formula = dvHelper.createFormulaListConstraint("INDIRECT($D$" + i + ")"); + setValidation(sheet, dvHelper, formula, rangeAddressList); + } + + //问题属性 + for (int i = 2; i < probPropsNameArray.size() + 10; i++) { + CellRangeAddressList rangeAddressList = new CellRangeAddressList(i-1 , i-1, 5, 5); + DataValidationConstraint formula = dvHelper.createFormulaListConstraint("INDIRECT($E$" + i + ")"); + setValidation(sheet, dvHelper, formula, rangeAddressList); + } + } + + /** + * 设置验证规则 + * @param sheet sheet对象 + * @param helper 验证助手 + * @param constraint createExplicitListConstraint + * @param addressList 验证位置对象 + */ + private void setValidation(Sheet sheet, DataValidationHelper helper, DataValidationConstraint constraint, CellRangeAddressList addressList) { + DataValidation dataValidation = helper.createValidation(constraint, addressList); + dataValidation.createErrorBox("错误提示", "您输入的内容,不符合限制条件"); + sheet.addValidationData(dataValidation); + } + + /** + * @param offset 偏移量,如果给0,表示从A列开始,1,就是从B列 + * @param rowId 第几行 + * @param colCount 一共多少列 + * @return 如果给入参 1,1,10. 表示从B1-K1。最终返回 $B$1:$K$1 + * @author denggonghai 2016年8月31日 下午5:17:49 + */ + public String getRange(int offset, int rowId, int colCount) { + char start = (char) ('A' + offset); + if (colCount <= 25) { + char end = (char) (start + colCount - 1); + return "$" + start + "$" + rowId + ":$" + end + "$" + rowId; + } else { + char endPrefix = 'A'; + char endSuffix = 'A'; + if ((colCount - 25) / 26 == 0 || colCount == 51) {// 26-51之间,包括边界(仅两次字母表计算) + if ((colCount - 25) % 26 == 0) {// 边界值 + endSuffix = (char) ('A' + 25); + } else { + endSuffix = (char) ('A' + (colCount - 25) % 26 - 1); + } + } else {// 51以上 + if ((colCount - 25) % 26 == 0) { + endSuffix = (char) ('A' + 25); + endPrefix = (char) (endPrefix + (colCount - 25) / 26 - 1); + } else { + endSuffix = (char) ('A' + (colCount - 25) % 26 - 1); + endPrefix = (char) (endPrefix + (colCount - 25) / 26); + } + } + return "$" + start + "$" + rowId + ":$" + endPrefix + endSuffix + "$" + rowId; + } + } +} diff --git a/nuzar-customer-controller/src/main/resources/templates/in_temp.xlsx b/nuzar-customer-controller/src/main/resources/templates/in_temp.xlsx index 084feb7..7612fdb 100644 Binary files a/nuzar-customer-controller/src/main/resources/templates/in_temp.xlsx and b/nuzar-customer-controller/src/main/resources/templates/in_temp.xlsx differ diff --git a/nuzar-customer-repository/src/main/java/com/haitonggauto/rtosc/repository/entity/CustomerExportIn.java b/nuzar-customer-repository/src/main/java/com/haitonggauto/rtosc/repository/entity/CustomerExportIn.java index badbc03..b397f83 100644 --- a/nuzar-customer-repository/src/main/java/com/haitonggauto/rtosc/repository/entity/CustomerExportIn.java +++ b/nuzar-customer-repository/src/main/java/com/haitonggauto/rtosc/repository/entity/CustomerExportIn.java @@ -70,6 +70,30 @@ public class CustomerExportIn extends BaseEntity implements Serializable { @EsLogMean(name = "航次", title = true) private String voyage; + @TableField(value = "nature_flag") + @ApiModelProperty(value = "货物性质ID") + private String natureFlag; + + @TableField(value = "nature_flag_name") + @ApiModelProperty(value = "货物性质名称") + private String natureFlagName; + + @TableField(value = "transfer_ship_id") + @ApiModelProperty(value = "中转船ID") + private String transferShipId; + + @TableField(value = "transfer_ship_name") + @ApiModelProperty(value = "中转船名") + private String transferShipName; + + @TableField(value = "transfer_voyage_id") + @ApiModelProperty(value = "中转航次ID") + private String transferVoyageId; + + @TableField(value = "transfer_voyage") + @ApiModelProperty(value = "中转航次名") + private String transferVoyage; + /** * 港区ID */ diff --git a/nuzar-customer-repository/src/main/java/com/haitonggauto/rtosc/repository/entity/CustomerExportLoad.java b/nuzar-customer-repository/src/main/java/com/haitonggauto/rtosc/repository/entity/CustomerExportLoad.java index d58b551..7851bc6 100644 --- a/nuzar-customer-repository/src/main/java/com/haitonggauto/rtosc/repository/entity/CustomerExportLoad.java +++ b/nuzar-customer-repository/src/main/java/com/haitonggauto/rtosc/repository/entity/CustomerExportLoad.java @@ -76,6 +76,30 @@ public class CustomerExportLoad extends BaseEntity implements Serializable { @EsLogMean(name = "航次", title = true) private String voyage; + @TableField(value = "nature_flag") + @ApiModelProperty(value = "货物性质ID") + private String natureFlag; + + @TableField(value = "nature_flag_name") + @ApiModelProperty(value = "货物性质名称") + private String natureFlagName; + + @TableField(value = "transfer_ship_id") + @ApiModelProperty(value = "中转船ID") + private String transferShipId; + + @TableField(value = "transfer_ship_name") + @ApiModelProperty(value = "中转船名") + private String transferShipName; + + @TableField(value = "transfer_voyage_id") + @ApiModelProperty(value = "中转航次ID") + private String transferVoyageId; + + @TableField(value = "transfer_voyage") + @ApiModelProperty(value = "中转航次名") + private String transferVoyage; + /** * 港区ID */