From d85e3524575dd6a9ebfa8e66c5ce3152243a79e7 Mon Sep 17 00:00:00 2001 From: dengjun Date: Thu, 7 Dec 2023 10:05:24 +0800 Subject: [PATCH] =?UTF-8?q?=E6=89=B9=E9=87=8F=E4=BF=AE=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../haitonggauto/rtosc/dto/CargoStatusVo.java | 6 +- .../rtosc/dto/CheckVinRepeatVo.java | 26 + .../haitonggauto/rtosc/dto/ExportInVo.java | 27 +- .../rtosc/dto/ExportInspectCargoVo.java | 4 + .../rtosc/dto/UpdateVoyageVo.java | 42 ++ .../rtosc/excel/ExportInPlanExcel.java | 12 +- .../rtosc/excel/InspectExportExcel.java | 90 +++ .../haitonggauto/rtosc/query/CargoQuery.java | 3 + .../rtosc/query/DepartureQuery.java | 4 + .../rtosc/query/ExportInCheckQuery.java | 20 + .../rtosc/query/ExportInQuery.java | 14 + .../rtosc/query/ExportInspectCheckQuery.java | 8 + .../rtosc/query/ExportInspectQuery.java | 9 + .../rtosc/query/ExportLoadCheckQuery.java | 5 + .../rtosc/query/ExportLoadQuery.java | 10 +- .../rtosc/query/FreeTradeQuery.java | 5 + .../rtosc/common/db/query/BaseQuery.java | 1 - .../haitonggauto/rtosc/api/NuzarOpenApi.java | 13 +- .../rtosc/api/dto/TransitPartRequest.java | 21 + .../rtosc/api/dto/TransitPartResp.java | 16 + .../rtosc/handler/DepartureHandler.java | 53 +- .../rtosc/handler/ExportInHandler.java | 543 +++++++++++++++--- .../rtosc/handler/ExportInspectHandler.java | 147 ++++- .../rtosc/handler/ExportLoadHandler.java | 252 ++++++-- .../rtosc/handler/FreeTradeHandler.java | 14 +- .../rtosc/handler/ImportInspectHandler.java | 148 ++++- .../rtosc/handler/ImportTakeHandler.java | 2 +- .../rtosc/handler/ImportUnloadHandler.java | 2 +- .../rtosc/handler/mapper/PoMapper.java | 7 +- .../service/impl/CustomerServiceImpl.java | 2 + .../src/main/resources/templates/in_temp.xlsx | Bin 0 -> 12850 bytes .../repository/entity/CustomerExportIn.java | 21 + .../entity/CustomerExportInspectCargo.java | 5 + .../mapper/CustomerExportLoadMapper.xml | 2 + 34 files changed, 1357 insertions(+), 177 deletions(-) create mode 100644 nuzar-customer-client/src/main/java/com/haitonggauto/rtosc/dto/CheckVinRepeatVo.java create mode 100644 nuzar-customer-client/src/main/java/com/haitonggauto/rtosc/dto/UpdateVoyageVo.java create mode 100644 nuzar-customer-client/src/main/java/com/haitonggauto/rtosc/excel/InspectExportExcel.java create mode 100644 nuzar-customer-controller/src/main/java/com/haitonggauto/rtosc/api/dto/TransitPartRequest.java create mode 100644 nuzar-customer-controller/src/main/java/com/haitonggauto/rtosc/api/dto/TransitPartResp.java create mode 100644 nuzar-customer-controller/src/main/resources/templates/in_temp.xlsx diff --git a/nuzar-customer-client/src/main/java/com/haitonggauto/rtosc/dto/CargoStatusVo.java b/nuzar-customer-client/src/main/java/com/haitonggauto/rtosc/dto/CargoStatusVo.java index ed78e59..d3bf5c9 100644 --- a/nuzar-customer-client/src/main/java/com/haitonggauto/rtosc/dto/CargoStatusVo.java +++ b/nuzar-customer-client/src/main/java/com/haitonggauto/rtosc/dto/CargoStatusVo.java @@ -47,9 +47,9 @@ public class CargoStatusVo implements Serializable { @ApiModelProperty(value = "单票体积") private BigDecimal eachVolume; - @Valid - @NotNull(groups = {ValidationGroup.update.class}, message = "车架号必填!" ) - @Size(min = 1 , message = "车架号必填要有一个") +// @Valid +// @NotNull(groups = {ValidationGroup.update.class}, message = "车架号必填!" ) +// @Size(min = 1 , message = "车架号必填要有一个") private List vins; } diff --git a/nuzar-customer-client/src/main/java/com/haitonggauto/rtosc/dto/CheckVinRepeatVo.java b/nuzar-customer-client/src/main/java/com/haitonggauto/rtosc/dto/CheckVinRepeatVo.java new file mode 100644 index 0000000..177bc3e --- /dev/null +++ b/nuzar-customer-client/src/main/java/com/haitonggauto/rtosc/dto/CheckVinRepeatVo.java @@ -0,0 +1,26 @@ +package com.haitonggauto.rtosc.dto; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +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.util.List; + +@Data +@ApiModel(value = "验证车架号是否已经申请",description = "") +public class CheckVinRepeatVo implements Serializable { + @NotBlank(message = "航次ID为空") + @ApiModelProperty(value = "航次ID") + private String voyageId; + + + @Valid + @NotNull(message = "车架号必填!" ) + @Size(min = 1 , message = "车架号必填要有一个") + private List vins; +} 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 50bcb99..18f187a 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,5 +1,6 @@ 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.MoreThan; @@ -313,6 +314,24 @@ public class ExportInVo implements Serializable { @ApiModelProperty(value = "提单号", required = true) private String billNum; + /** + * 使用机械ID + */ + @ApiModelProperty(value = "使用机械ID") + private String machineId; + + /** + * 使用机械名称 + */ + @ApiModelProperty(value = "使用机械名称") + private String machineName; + + /** + * 是否是二手车 + */ + @ApiModelProperty(value = "是否是二手车,1是二手车,0不是二手车") + private Integer secondHand; + /** * 备注 */ @@ -322,11 +341,11 @@ public class ExportInVo implements Serializable { /** * 源类型 */ - @NotNull(groups = {ValidationGroup.insert.class, ValidationGroup.update.class}, message = "源类型不能为空") +// @NotNull(groups = {ValidationGroup.insert.class, ValidationGroup.update.class}, message = "源类型不能为空") @ApiModelProperty(value = "源类型", required = true) private String energyType; - @NotNull(groups = {ValidationGroup.insert.class, ValidationGroup.update.class}, message = "源类型名称不能为空") +// @NotNull(groups = {ValidationGroup.insert.class, ValidationGroup.update.class}, message = "源类型名称不能为空") @ApiModelProperty(value = "源类型名称", required = true) private String energyTypeName; @@ -358,8 +377,8 @@ public class ExportInVo implements Serializable { private List cargos; @Valid - @NotNull(groups = {ValidationGroup.insert.class, ValidationGroup.update.class}, message = "出口进场时间必须填!") - @Size(groups = {ValidationGroup.insert.class, ValidationGroup.update.class}, min = 1, message = "出口进场时间至少要有一个") +// @NotNull(groups = {ValidationGroup.insert.class, ValidationGroup.update.class}, message = "出口进场时间必须填!") +// @Size(groups = {ValidationGroup.insert.class, ValidationGroup.update.class}, min = 1, message = "出口进场时间至少要有一个") private List times; @Valid diff --git a/nuzar-customer-client/src/main/java/com/haitonggauto/rtosc/dto/ExportInspectCargoVo.java b/nuzar-customer-client/src/main/java/com/haitonggauto/rtosc/dto/ExportInspectCargoVo.java index 2fd495e..ae06434 100644 --- a/nuzar-customer-client/src/main/java/com/haitonggauto/rtosc/dto/ExportInspectCargoVo.java +++ b/nuzar-customer-client/src/main/java/com/haitonggauto/rtosc/dto/ExportInspectCargoVo.java @@ -1,5 +1,6 @@ package com.haitonggauto.rtosc.dto; +import com.baomidou.mybatisplus.annotation.TableField; import com.haitonggauto.rtosc.common.utils.ValidationGroup; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; @@ -38,6 +39,9 @@ public class ExportInspectCargoVo implements Serializable { // @NotBlank(groups = {ValidationGroup.insert.class, ValidationGroup.update.class}, message = "车型不能为空") private String cartType; + @ApiModelProperty(value = "型号") + private String models; + /** * 车架号 */ diff --git a/nuzar-customer-client/src/main/java/com/haitonggauto/rtosc/dto/UpdateVoyageVo.java b/nuzar-customer-client/src/main/java/com/haitonggauto/rtosc/dto/UpdateVoyageVo.java new file mode 100644 index 0000000..611747d --- /dev/null +++ b/nuzar-customer-client/src/main/java/com/haitonggauto/rtosc/dto/UpdateVoyageVo.java @@ -0,0 +1,42 @@ +package com.haitonggauto.rtosc.dto; + +import com.haitonggauto.rtosc.common.utils.ValidationGroup; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +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.util.List; + +@Data +@ApiModel(value = "批量修改船名、航次") +public class UpdateVoyageVo implements Serializable { + + /** + * 船名 + */ + @Valid + @ApiModelProperty(value = "计划ID") + @Size(groups = {ValidationGroup.insert.class, ValidationGroup.update.class}, min = 1, message = "计划ID不能为空") + @NotNull(groups = {ValidationGroup.insert.class, ValidationGroup.update.class}, message = "计划ID不能为空") + private List ids; + + /** + * 航次ID + */ + @ApiModelProperty(value = "航次ID") + @NotBlank(groups = {ValidationGroup.insert.class, ValidationGroup.update.class}, message = "航次ID不能为空") + private String voyageId; + + /** + * 航次 + */ + @ApiModelProperty(value = "航次", required = true) + @NotBlank(groups = {ValidationGroup.insert.class, ValidationGroup.update.class}, message = "航次不能为空") + private String voyage; + +} 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 7b83803..f9a34f3 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 @@ -98,14 +98,14 @@ public class ExportInPlanExcel { * 进场时间 */ // @DateTimeFormat("yyyy-MM-dd HH:mm") - @ExcelProperty("*进场时间") + @ExcelProperty("进场时间") @NotNull(message = "进场时间不能为空") private String enterTime; /** * 进场数量 */ - @ExcelProperty("*进场数量") + @ExcelProperty("进场数量") @NotNull(message = "进场数量不能为空") private Integer enterQuantity; @@ -234,7 +234,11 @@ public class ExportInPlanExcel { /** * 源类型 */ - @ExcelProperty("*源类型") - @NotBlank(message = "源类型不能为空") + @ExcelProperty("*能源类型") + @NotBlank(message = "*能源类型不能为空") private String energyTypeName; + + @ExcelProperty("*是否二手车") + @NotBlank(message = "是否是二手车不能为空") + private String secondHand; } \ No newline at end of file diff --git a/nuzar-customer-client/src/main/java/com/haitonggauto/rtosc/excel/InspectExportExcel.java b/nuzar-customer-client/src/main/java/com/haitonggauto/rtosc/excel/InspectExportExcel.java new file mode 100644 index 0000000..f7403a5 --- /dev/null +++ b/nuzar-customer-client/src/main/java/com/haitonggauto/rtosc/excel/InspectExportExcel.java @@ -0,0 +1,90 @@ +package com.haitonggauto.rtosc.excel; + +import com.alibaba.excel.annotation.ExcelProperty; +import lombok.Data; + +import java.math.BigDecimal; +import java.util.Date; + +/** + * 出口进场基本表 + * @TableName customer_export_in + */ +@Data +public class InspectExportExcel { + + /** + * 受理号 + */ + @ExcelProperty("受理号") + private String batchNo; + + /** + * 中文船名 + */ + @ExcelProperty("船名") + private String shipName; + + /** + * 航次 + */ + @ExcelProperty("航次") + private String voyage; + + /** + * 提单号 + */ + @ExcelProperty("提单号") + private String billNo; + + /** + * 查验日期 + */ + @ExcelProperty("查验日期") + private Date inspectTime; + + /** + * 查验车辆数 + */ + @ExcelProperty("计划车辆数") + private Integer plannedCargoQuantity; + + /** + * 查验备件数 + */ + @ExcelProperty("计划备件数") + private Integer plannedSpareQuantity; + + /** + * 公司名 + */ + @ExcelProperty("公司名称") + private String company; + + /** + * 申请对象(从基础数据库获取客户类型为进口货代的数据) + */ + @ExcelProperty("申请对象") + private String applyObj; + + /** + * 联系人 + */ + @ExcelProperty("联系人") + private String contact; + + /** + * 联系电话 + */ + @ExcelProperty(value = "联系电话") + private String contactPhone; + + + @ExcelProperty(value = "查验状态") + private String apiInspectStatus; + + + @ExcelProperty(value = "申请时间") + private Date applyTime; + +} \ No newline at end of file diff --git a/nuzar-customer-client/src/main/java/com/haitonggauto/rtosc/query/CargoQuery.java b/nuzar-customer-client/src/main/java/com/haitonggauto/rtosc/query/CargoQuery.java index 83a677c..887fd1c 100644 --- a/nuzar-customer-client/src/main/java/com/haitonggauto/rtosc/query/CargoQuery.java +++ b/nuzar-customer-client/src/main/java/com/haitonggauto/rtosc/query/CargoQuery.java @@ -11,4 +11,7 @@ import lombok.Data; public class CargoQuery extends BaseQuery { @ApiModelProperty(value = "货物类型, 0代表车辆,1代表备件") private Integer cargoType; + + @ApiModelProperty(value = "车架号") + private String vin; } diff --git a/nuzar-customer-client/src/main/java/com/haitonggauto/rtosc/query/DepartureQuery.java b/nuzar-customer-client/src/main/java/com/haitonggauto/rtosc/query/DepartureQuery.java index 34e2e22..a8c4419 100644 --- a/nuzar-customer-client/src/main/java/com/haitonggauto/rtosc/query/DepartureQuery.java +++ b/nuzar-customer-client/src/main/java/com/haitonggauto/rtosc/query/DepartureQuery.java @@ -49,6 +49,10 @@ public class DepartureQuery extends BaseQuery { @ApiModelProperty(value = "港区ID") private String portAreaId; + @ApiModelProperty(value = "港区ID集合") + @DbQuery(field = "portAreaId", symbol = SqlSymbol.IN) + private List pamIds; + @ApiModelProperty(hidden = true) // 明细表查询时会用到 private Long departureId; diff --git a/nuzar-customer-client/src/main/java/com/haitonggauto/rtosc/query/ExportInCheckQuery.java b/nuzar-customer-client/src/main/java/com/haitonggauto/rtosc/query/ExportInCheckQuery.java index d8e9d3a..bbaaaac 100644 --- a/nuzar-customer-client/src/main/java/com/haitonggauto/rtosc/query/ExportInCheckQuery.java +++ b/nuzar-customer-client/src/main/java/com/haitonggauto/rtosc/query/ExportInCheckQuery.java @@ -26,12 +26,20 @@ public class ExportInCheckQuery extends BaseQuery { @ApiModelProperty(value = "航次ID") private String voyageId; + @ApiModelProperty(value = "批量航次ID") + @DbQuery(field = "voyageId", symbol = SqlSymbol.IN) + private List voyageIds; + @ApiModelProperty(value = "航次") private String voyage; @ApiModelProperty(value = "港区ID") private String portAreaId; + @ApiModelProperty(value = "港区ID集合") + @DbQuery(field = "portAreaId", symbol = SqlSymbol.IN) + private List pamIds; + @JsonFormat(pattern = "yyyy-MM-dd") @ApiModelProperty(value = "开始进场时间") @DbQuery(field = "applyTime", symbol = SqlSymbol.GTE) @@ -75,6 +83,18 @@ public class ExportInCheckQuery extends BaseQuery { @ApiModelProperty(value = "型号") private String models; + @ApiModelProperty(value = "货代ID") + private String freightId; + + @ApiModelProperty(value = "车架号") + private String vin; + + @ApiModelProperty(value = "国家Id") + private String countryId; + + @ApiModelProperty(value = "港口ID") + private String portId; + @ApiModelProperty(hidden = true) @DbQuery(field = "vin", symbol = SqlSymbol.IN) private List vins; diff --git a/nuzar-customer-client/src/main/java/com/haitonggauto/rtosc/query/ExportInQuery.java b/nuzar-customer-client/src/main/java/com/haitonggauto/rtosc/query/ExportInQuery.java index c8e08a5..ecfdb2c 100644 --- a/nuzar-customer-client/src/main/java/com/haitonggauto/rtosc/query/ExportInQuery.java +++ b/nuzar-customer-client/src/main/java/com/haitonggauto/rtosc/query/ExportInQuery.java @@ -16,10 +16,18 @@ import java.util.List; @ApiModel(value = "出口进场查询") public class ExportInQuery extends BaseQuery { + @ApiModelProperty(value = "船ID") + private String shipId; + + @ApiModelProperty(value = "航次ID") + private String voyageId; + @ApiModelProperty(value = "船名") + @DbQuery(symbol = SqlSymbol.LIKE) private String shipName; @ApiModelProperty(value = "航次") + @DbQuery(symbol = SqlSymbol.LIKE) private String voyage; @ApiModelProperty(value = "港区ID") @@ -62,6 +70,12 @@ public class ExportInQuery extends BaseQuery { @ApiModelProperty(value = "型号") private String models; + @ApiModelProperty(value = "国家Id") + private String countryId; + + @ApiModelProperty(value = "港口ID") + private String portId; + @ApiModelProperty(hidden = true) @DbQuery(field = "vin", symbol = SqlSymbol.IN) private List vins; diff --git a/nuzar-customer-client/src/main/java/com/haitonggauto/rtosc/query/ExportInspectCheckQuery.java b/nuzar-customer-client/src/main/java/com/haitonggauto/rtosc/query/ExportInspectCheckQuery.java index 0f96a71..9c68441 100644 --- a/nuzar-customer-client/src/main/java/com/haitonggauto/rtosc/query/ExportInspectCheckQuery.java +++ b/nuzar-customer-client/src/main/java/com/haitonggauto/rtosc/query/ExportInspectCheckQuery.java @@ -18,6 +18,9 @@ public class ExportInspectCheckQuery extends BaseQuery { @DbQuery(field = "shipId") private String shipName; + @ApiModelProperty(value = "船ID") + private String shipId; + @ApiModelProperty(value = "航次ID") private String voyageId; @@ -27,6 +30,10 @@ public class ExportInspectCheckQuery extends BaseQuery { @ApiModelProperty(value = "港区ID") private String portAreaId; + @ApiModelProperty(value = "港区ID集合") + @DbQuery(field = "portAreaId", symbol = SqlSymbol.IN) + private List pamIds; + @ApiModelProperty(value = "审核状态") private AuditEnum checkStatus; @@ -35,6 +42,7 @@ public class ExportInspectCheckQuery extends BaseQuery { private List checkStatusList; @ApiModelProperty(value = "受理号") + @DbQuery(symbol = SqlSymbol.LIKE) private String batchNo; @ApiModelProperty(hidden = true) diff --git a/nuzar-customer-client/src/main/java/com/haitonggauto/rtosc/query/ExportInspectQuery.java b/nuzar-customer-client/src/main/java/com/haitonggauto/rtosc/query/ExportInspectQuery.java index 2e77c19..add28f9 100644 --- a/nuzar-customer-client/src/main/java/com/haitonggauto/rtosc/query/ExportInspectQuery.java +++ b/nuzar-customer-client/src/main/java/com/haitonggauto/rtosc/query/ExportInspectQuery.java @@ -14,10 +14,18 @@ import java.util.List; @ApiModel(value = "海关查验查询") public class ExportInspectQuery extends BaseQuery { + @ApiModelProperty(value = "船ID") + private String shipId; + + @ApiModelProperty(value = "航次ID") + private String voyageId; + @ApiModelProperty(value = "船名") + @DbQuery(symbol = SqlSymbol.LIKE) private String shipName; @ApiModelProperty(value = "航次") + @DbQuery(symbol = SqlSymbol.LIKE) private String voyage; @ApiModelProperty(value = "港区ID") @@ -31,6 +39,7 @@ public class ExportInspectQuery extends BaseQuery { private List checkStatusList; @ApiModelProperty(value = "受理号") + @DbQuery(symbol = SqlSymbol.LIKE) private String batchNo; @ApiModelProperty(hidden = true) diff --git a/nuzar-customer-client/src/main/java/com/haitonggauto/rtosc/query/ExportLoadCheckQuery.java b/nuzar-customer-client/src/main/java/com/haitonggauto/rtosc/query/ExportLoadCheckQuery.java index 0e18fd6..ef8f0cf 100644 --- a/nuzar-customer-client/src/main/java/com/haitonggauto/rtosc/query/ExportLoadCheckQuery.java +++ b/nuzar-customer-client/src/main/java/com/haitonggauto/rtosc/query/ExportLoadCheckQuery.java @@ -14,6 +14,7 @@ import java.util.List; @ApiModel(value = "出口装船查询") public class ExportLoadCheckQuery extends BaseQuery { @ApiModelProperty(value = "受理号") + @DbQuery(symbol = SqlSymbol.LIKE) private String batchNo; @ApiModelProperty(value = "船ID") @@ -39,6 +40,10 @@ public class ExportLoadCheckQuery extends BaseQuery { @ApiModelProperty(value = "港区ID") private String portAreaId; + @ApiModelProperty(value = "港区ID集合") + @DbQuery(field = "portAreaId", symbol = SqlSymbol.IN) + private List pamIds; + @ApiModelProperty(value = "审核状态") private AuditEnum checkStatus; diff --git a/nuzar-customer-client/src/main/java/com/haitonggauto/rtosc/query/ExportLoadQuery.java b/nuzar-customer-client/src/main/java/com/haitonggauto/rtosc/query/ExportLoadQuery.java index 0c02669..e15f78d 100644 --- a/nuzar-customer-client/src/main/java/com/haitonggauto/rtosc/query/ExportLoadQuery.java +++ b/nuzar-customer-client/src/main/java/com/haitonggauto/rtosc/query/ExportLoadQuery.java @@ -14,15 +14,21 @@ import java.util.List; @ApiModel(value = "出口装船查询") public class ExportLoadQuery extends BaseQuery { @ApiModelProperty(value = "受理号") + @DbQuery(symbol = SqlSymbol.LIKE) private String batchNo; - @ApiModelProperty(value = "船名") - private String shipName; + @ApiModelProperty(value = "船ID") + private String shipId; @ApiModelProperty(value = "航次ID") private String voyageId; + @ApiModelProperty(value = "船名") + @DbQuery(symbol = SqlSymbol.LIKE) + private String shipName; + @ApiModelProperty(value = "航次") + @DbQuery(symbol = SqlSymbol.LIKE) private String voyage; @ApiModelProperty(value = "贸易类型") diff --git a/nuzar-customer-client/src/main/java/com/haitonggauto/rtosc/query/FreeTradeQuery.java b/nuzar-customer-client/src/main/java/com/haitonggauto/rtosc/query/FreeTradeQuery.java index c71787e..414c4b0 100644 --- a/nuzar-customer-client/src/main/java/com/haitonggauto/rtosc/query/FreeTradeQuery.java +++ b/nuzar-customer-client/src/main/java/com/haitonggauto/rtosc/query/FreeTradeQuery.java @@ -17,6 +17,7 @@ import java.util.List; @ApiModel(value = "特保区查询") public class FreeTradeQuery extends BaseQuery { @ApiModelProperty(value = "批次号") + @DbQuery(symbol = SqlSymbol.LIKE) private String batchNo; @ApiModelProperty(value = "企业编码") @@ -42,6 +43,10 @@ public class FreeTradeQuery extends BaseQuery { @ApiModelProperty(value = "港区ID") private String portAreaId; + @ApiModelProperty(value = "港区ID集合") + @DbQuery(field = "portAreaId", symbol = SqlSymbol.IN) + private List pamIds; + @ApiModelProperty(value = "审核状态", hidden = true) @DbQuery(field = "checkStatus", symbol = SqlSymbol.IN) private List checkStatusList; diff --git a/nuzar-customer-common/src/main/java/com/haitonggauto/rtosc/common/db/query/BaseQuery.java b/nuzar-customer-common/src/main/java/com/haitonggauto/rtosc/common/db/query/BaseQuery.java index 46484e5..1321672 100644 --- a/nuzar-customer-common/src/main/java/com/haitonggauto/rtosc/common/db/query/BaseQuery.java +++ b/nuzar-customer-common/src/main/java/com/haitonggauto/rtosc/common/db/query/BaseQuery.java @@ -14,7 +14,6 @@ public class BaseQuery extends Perm { private Long id; // 批量查询 - @ApiModelProperty(hidden = true) @DbQuery(field = "id", symbol = SqlSymbol.IN) private List ids; diff --git a/nuzar-customer-controller/src/main/java/com/haitonggauto/rtosc/api/NuzarOpenApi.java b/nuzar-customer-controller/src/main/java/com/haitonggauto/rtosc/api/NuzarOpenApi.java index 3f8ac3b..2402d90 100644 --- a/nuzar-customer-controller/src/main/java/com/haitonggauto/rtosc/api/NuzarOpenApi.java +++ b/nuzar-customer-controller/src/main/java/com/haitonggauto/rtosc/api/NuzarOpenApi.java @@ -11,10 +11,11 @@ import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestParam; import java.util.List; +import java.util.Map; -//@FeignClient(name = "https://rtops4.haitongauto.com/tos/api") -@FeignClient(name = "rtos-openapi") +@FeignClient(name = "https://rtops4.haitongauto.com/tos/api") +//@FeignClient(name = "rtos-openapi") public interface NuzarOpenApi { // 根据港区ID获取国家 @@ -108,4 +109,12 @@ public interface NuzarOpenApi { // 查验状态 @PostMapping("/customer/exportInspectApply/applyId/status") List getInspectStatusStatus(@RequestBody List req); + + // 判断是否生成船期计划 + @GetMapping("/customer/shipment/shipLoad/getShipPlan") + Boolean haveShipPlan(@RequestParam("vvyId") String vvyId); + + // 装船审核获取国际中转备件 + @PostMapping("/customer/shipment/shipLoad/transitPart") + Map> getTransitPart(@RequestBody TransitPartRequest request); } diff --git a/nuzar-customer-controller/src/main/java/com/haitonggauto/rtosc/api/dto/TransitPartRequest.java b/nuzar-customer-controller/src/main/java/com/haitonggauto/rtosc/api/dto/TransitPartRequest.java new file mode 100644 index 0000000..0ccdb1b --- /dev/null +++ b/nuzar-customer-controller/src/main/java/com/haitonggauto/rtosc/api/dto/TransitPartRequest.java @@ -0,0 +1,21 @@ +package com.haitonggauto.rtosc.api.dto; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.io.Serializable; +import java.util.List; + +@Data +@ApiModel("国际中转备件") +public class TransitPartRequest implements Serializable { + @ApiModelProperty("提单号") + private String mnfBl; + + @ApiModelProperty("备件数") + private Integer partAmount; + + @ApiModelProperty("航次ID") + private List vvyIds; +} diff --git a/nuzar-customer-controller/src/main/java/com/haitonggauto/rtosc/api/dto/TransitPartResp.java b/nuzar-customer-controller/src/main/java/com/haitonggauto/rtosc/api/dto/TransitPartResp.java new file mode 100644 index 0000000..f19b719 --- /dev/null +++ b/nuzar-customer-controller/src/main/java/com/haitonggauto/rtosc/api/dto/TransitPartResp.java @@ -0,0 +1,16 @@ +package com.haitonggauto.rtosc.api.dto; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.io.Serializable; +import java.util.List; + +@Data +@ApiModel("国际中转备件返回") +public class TransitPartResp implements Serializable { + private String workStatus; + + private String vinCode; +} diff --git a/nuzar-customer-controller/src/main/java/com/haitonggauto/rtosc/handler/DepartureHandler.java b/nuzar-customer-controller/src/main/java/com/haitonggauto/rtosc/handler/DepartureHandler.java index 0c80af5..db1ced0 100644 --- a/nuzar-customer-controller/src/main/java/com/haitonggauto/rtosc/handler/DepartureHandler.java +++ b/nuzar-customer-controller/src/main/java/com/haitonggauto/rtosc/handler/DepartureHandler.java @@ -11,6 +11,7 @@ import com.alibaba.excel.write.metadata.fill.FillWrapper; import com.baomidou.mybatisplus.core.conditions.Wrapper; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.conditions.query.QueryChainWrapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.haitonggauto.rtosc.api.NuzarOpenApi; import com.haitonggauto.rtosc.api.dto.*; @@ -19,10 +20,8 @@ import com.haitonggauto.rtosc.common.context.UserContext; import com.haitonggauto.rtosc.common.dto.Result; import com.haitonggauto.rtosc.common.enums.ErrorType; import com.haitonggauto.rtosc.common.handler.BaseHandler; -import com.haitonggauto.rtosc.common.utils.DateUtils; -import com.haitonggauto.rtosc.common.utils.ResultUtil; -import com.haitonggauto.rtosc.common.utils.ValidationGroup; -import com.haitonggauto.rtosc.common.utils.WrapperKit; +import com.haitonggauto.rtosc.common.utils.*; +import com.haitonggauto.rtosc.dto.CheckVinRepeatVo; import com.haitonggauto.rtosc.dto.DepartureCargoVo; import com.haitonggauto.rtosc.dto.DepartureCheckVo; import com.haitonggauto.rtosc.dto.DepartureVo; @@ -172,6 +171,15 @@ public class DepartureHandler implements BaseHandler { return ResultUtil.failure(ErrorType.PARAMS_ERROR.id(), StringUtils.join(repeat, ",") + "车架号重复"); } } + + // 验证是否重复申请 + List vins = form.getCargos().stream().map(item -> item.getVin()).collect(Collectors.toList()); + List exists = departureCargoService.lambdaQuery().in(CustomerDepartureCargo::getVin, vins).list(); + List repeat = exists.stream().map(item -> item.getVin()).collect(Collectors.toList());; + if (CollectionUtils.isNotEmpty(exists)) { + return ResultUtil.failure(ErrorType.PARAMS_ERROR.id(), StringUtils.join(repeat, ",") + "车架号不能重复申请"); + } + String batchNo = customerService.getSequenceNo("departure_batch_no", "提离港区", "EP"); // 表单验证以及格式转换 CustomerDeparture departure = PoMapper.instance.departureVo2Entity(form); @@ -204,6 +212,24 @@ public class DepartureHandler implements BaseHandler { return ResultUtil.success(String.valueOf(id)); } + + @ApiOperation("批量验证车架号是否已经存在") + @PostMapping("/check/vin/repeat") + public Result>> checkVinRepeat(@RequestBody @NotNull(message = "验证列表不能为空") @Size(min = 1, message = "验证列表不能为空") ValidList form) { + Map> rst = new HashMap<>(); + for(CheckVinRepeatVo vo : form) { + List cargos = departureCargoService.query() + .select("count(*) as quantity, vin") + .in("vin", vo.getVins()) + .exists("select id from customer_departure where customer_departure.id=customer_departure_cargo.departure_id and customer_departure.voyage_id={0}", vo.getVoyageId()) + .groupBy("vin") + .having("count(quantity) > 1") + .list(); + rst.put(vo.getVoyageId(), cargos.stream().map(item -> item.getVin()).collect(Collectors.toList())); + } + return ResultUtil.success(rst); + } + @ApiOperation("提交审核") @PostMapping("/submit-check") public Result submitCheck(@RequestBody @@ -214,6 +240,16 @@ public class DepartureHandler implements BaseHandler { return ResultUtil.success("success"); } + @ApiOperation("撤销提交审核") + @PostMapping("/submit-check/reverse") + public Result submitCheckReverse(@RequestBody + @NotNull(message = "请传入要审核的提离港区ID") + @Size(min = 1, message = "ID列表不能为空") List ids) { + departureService.lambdaUpdate().set(CustomerDeparture::getCheckStatus, AuditEnum.SUBMIT) + .set(CustomerDeparture::getCheckResult, null).in(CustomerDeparture::getId, ids).update(); + return ResultUtil.success("success"); + } + /** * 删除 * @param id @@ -255,6 +291,15 @@ public class DepartureHandler implements BaseHandler { if (dep.getCheckStatus() == AuditEnum.AUDIT_PASS) { return ResultUtil.failure(ErrorType.PARAMS_ERROR.id(), "审核通过之后不能进行编辑"); } + + // 验证是否重复申请 + List vins = form.getCargos().stream().map(item -> item.getVin()).collect(Collectors.toList()); + List exists = departureCargoService.lambdaQuery().in(CustomerDepartureCargo::getVin, vins).ne(CustomerDepartureCargo::getDepartureId, form.getId()).list(); + List repeat = exists.stream().map(item -> item.getVin()).collect(Collectors.toList());; + if (CollectionUtils.isNotEmpty(exists)) { + return ResultUtil.failure(ErrorType.PARAMS_ERROR.id(), StringUtils.join(repeat, ",") + "车架号不能重复申请"); + } + String batchNo = dep.getBatchNo(); // 表单验证以及格式转换 CustomerDeparture departure = PoMapper.instance.departureVo2Entity(form); 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 406206d..043d9b1 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 @@ -47,7 +47,10 @@ import io.swagger.annotations.ApiOperation; import io.swagger.annotations.ApiParam; import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.collections4.MapUtils; +import org.apache.commons.io.IOUtils; import org.apache.commons.lang3.StringUtils; +import org.apache.poi.xssf.usermodel.*; +import org.springframework.core.io.ClassPathResource; import org.springframework.transaction.annotation.Transactional; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; @@ -64,6 +67,7 @@ import javax.validation.constraints.NotNull; import javax.validation.constraints.Size; import java.io.*; import java.math.BigDecimal; +import java.math.RoundingMode; import java.net.URLEncoder; import java.util.*; import java.util.concurrent.atomic.AtomicInteger; @@ -135,6 +139,66 @@ public class ExportInHandler implements BaseHandler { return ResultUtil.success(rst, String.valueOf(page.getTotal())); } + @ApiOperation("船名模糊匹配") + @PostMapping("/ship/list") + public Result> getShipList( + @RequestParam(required = false, defaultValue = "1") Integer current, + @RequestParam(required = false, defaultValue = "10") Integer size, + @RequestParam(required = false) String q) { + QueryWrapper query = new QueryWrapper<>(); + query.select("distinct ship_id, ship_name, ship_en_name"); + query.eq("create_by", UserContext.getUser().getUserId()); + if (StringUtils.isNotEmpty(q)) { + query.and((wrapper) -> { + wrapper.like("ship_name", q); + wrapper.or().like("ship_en_name", q); + }); + } + + Page page = customerExportInService.page(new Page<>(current, size), query); + List list = page.getRecords(); + + List rst = list.stream().map(tmp -> { + DictDTO vo = new DictDTO(); + vo.setId(tmp.getShipId()); + vo.setText(tmp.getShipName()); + vo.setExtra1(tmp.getShipEnName()); + return vo; + }).collect(Collectors.toList()); + + return ResultUtil.success(rst, String.valueOf(page.getTotal())); + } + + @ApiOperation("航次模糊匹配") + @PostMapping("/voyage/list") + public Result> getVoyageList( + @RequestParam(required = false, defaultValue = "1") Integer current, + @RequestParam(required = false, defaultValue = "10") Integer size, + @RequestParam(required = false) String shipId, + @RequestParam(required = false) String q) { + QueryWrapper query = new QueryWrapper<>(); + query.select("distinct voyage_id, voyage"); + query.eq("create_by", UserContext.getUser().getUserId()); + query.eq(StringUtils.isNotEmpty(shipId), "ship_id", shipId); + if (StringUtils.isNotEmpty(q)) { + query.and((wrapper) -> { + wrapper.like("voyage", q); + }); + } + + Page page = customerExportInService.page(new Page<>(current, size), query); + List list = page.getRecords(); + + List rst = list.stream().map(tmp -> { + DictDTO vo = new DictDTO(); + vo.setId(tmp.getVoyageId()); + vo.setText(tmp.getVoyage()); + return vo; + }).collect(Collectors.toList()); + + return ResultUtil.success(rst, String.valueOf(page.getTotal())); + } + @ApiOperation("提单号模糊匹配") @PostMapping("/billNo/query") public Result> getExportInBillNoList( @@ -216,7 +280,7 @@ public class ExportInHandler implements BaseHandler { query.setEndEnterTime(DateUtils.getDayEnd(query.getEndEnterTime())); } if (query.getCheckStatus() == null) { - query.setCheckStatusList(Arrays.asList(AuditEnum.AUDIT, AuditEnum.AUDIT_PASS, AuditEnum.AUDIT_REJECT)); + query.setCheckStatusList(Arrays.asList(AuditEnum.SUBMIT, AuditEnum.AUDIT, AuditEnum.AUDIT_PASS, AuditEnum.AUDIT_REJECT)); } Wrapper queryWrapper = new WrapperKit() { }.changeBaseQueryToWrapper(CustomerExportIn.class, query); @@ -225,6 +289,58 @@ public class ExportInHandler implements BaseHandler { return ResultUtil.success(page); } + @ApiOperation("出口进港货物跟踪查询") + @PostMapping("/cargo/tracking") + public Result> cargoTracking(@RequestBody ExportInCheckQuery query) { + if (query.getEndEnterTime() != null) { + query.setEndEnterTime(DateUtils.getDayEnd(query.getEndEnterTime())); + } + if (query.getCheckStatus() == null) { + query.setCheckStatusList(Arrays.asList(AuditEnum.AUDIT, AuditEnum.AUDIT_PASS, AuditEnum.AUDIT_REJECT)); + } + String vin = query.getVin(); + if (StringUtils.isNotEmpty(vin)) { + query.setVin(null); + } + + QueryWrapper queryWrapper = (QueryWrapper) new WrapperKit() { + }.changeBaseQueryToWrapper(CustomerExportIn.class, query); + + queryWrapper.select("sum(quantity) as quantity, port_area_id, ship_id, voyage_id, max(update_date) as update_date"); + queryWrapper.groupBy("port_area_id, ship_id, voyage_id"); + + if (StringUtils.isNotEmpty(vin)) { + queryWrapper.exists("select id from customer_export_in_cargo where customer_export_in_cargo.export_in_id=customer_export_in.id and customer_export_in_cargo.vin={0}", vin); + } + + + Page page = customerExportInService.page(new Page<>(query.getPage(), query.getRows()), queryWrapper); + customerService.wrapperEntity(page.getRecords()); + return ResultUtil.success(page); + } + + @ApiOperation("审核端统计查询") + @PostMapping("/check/query-list/count") + public Result> checkCountQuery(@RequestBody ExportInCheckQuery query) { + if (query.getEndEnterTime() != null) { + query.setEndEnterTime(DateUtils.getDayEnd(query.getEndEnterTime())); + } + if (query.getCheckStatus() == null) { + query.setCheckStatusList(Arrays.asList(AuditEnum.SUBMIT, AuditEnum.AUDIT, AuditEnum.AUDIT_PASS, AuditEnum.AUDIT_REJECT)); + } + + query.setSorts(null); + + QueryWrapper queryWrapper = (QueryWrapper) new WrapperKit() { + }.changeBaseQueryToWrapper(CustomerExportIn.class, query); + + queryWrapper.select("sum(quantity) as quantity, sum(volume) as volume, sum(weight) as weight, sum(length) as length, sum(width) as width, sum(height) as height"); + + Map map = customerExportInService.getMap(queryWrapper); + + return ResultUtil.success(map); + } + @ApiOperation("根据航次ID查询审核通过进港记录") @PostMapping("/query-list/voyage") public Result> checkQuery(@RequestParam(required = false) @NotBlank(message = "航次ID不能为空") String voyageId, @@ -298,10 +414,18 @@ public class ExportInHandler implements BaseHandler { @ApiOperation("货物明细分页列表") @PostMapping("/cargos/page") public Result> cargoList(@RequestBody @Validated(ValidationGroup.update.class) CargoQuery query) { - CustomerExportIn exportIn = customerExportInService.getById(query.getId()); + List ids = new ArrayList<>(); + if (query.getId() != null) { + ids.add(query.getId()); + } else if (CollectionUtils.isNotEmpty(query.getIds())) { + ids.addAll(query.getIds()); + } + List exportInList = customerExportInService.lambdaQuery().in(CustomerExportIn::getId, ids).list(); + Map eMap = exportInList.stream().collect(Collectors.toMap(CustomerExportIn::getId, item->item)); LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper(); queryWrapper.eq(query.getId() != null, CustomerExportInCargo::getExportInId, query.getId()); + queryWrapper.in(CollectionUtils.isNotEmpty(query.getIds()), CustomerExportInCargo::getExportInId, query.getIds()); if (query.getCargoType() != null) { queryWrapper.eq(CustomerExportInCargo::getCargoType, query.getCargoType()); } @@ -310,6 +434,7 @@ public class ExportInHandler implements BaseHandler { customerService.wrapperEntity(page.getRecords()); page.getRecords().forEach(item -> { + CustomerExportIn exportIn = eMap.get(item.getExportInId()); item.setBrandId(exportIn.getBrandId()); item.setBrand(exportIn.getBrand()); item.setCartTypeId(exportIn.getCartTypeId()); @@ -321,25 +446,33 @@ public class ExportInHandler implements BaseHandler { item.setModels(exportIn.getModels()); }); - // 获取作业状态 - Map collect = null; - List vins = page.getRecords().stream().map(item -> item.getVin()).collect(Collectors.toList()); - if (CollectionUtils.isNotEmpty(vins)) { - VinStatusRequest req = new VinStatusRequest(); - req.setBusinessType("IN_PORT"); - req.setImportExportType("E"); - req.setVinCodeList(vins); - if (!StringUtils.equalsAnyIgnoreCase(exportIn.getVoyageId(), "HT6", "HTLG", "HTTC")) { - req.setVvyId(exportIn.getVoyageId()); + Map> collect1 = page.getRecords().stream().collect(Collectors.groupingBy(CustomerExportInCargo::getExportInId)); + + collect1.entrySet().stream().forEach(m->{ + // 获取作业状态 + Map collect = null; + List vins = m.getValue().stream().map(item -> item.getVin()).collect(Collectors.toList()); + if (CollectionUtils.isNotEmpty(vins)) { + CustomerExportIn exportIn = eMap.get(m.getKey()); + + VinStatusRequest req = new VinStatusRequest(); + req.setBusinessType("IN_PORT"); + req.setImportExportType("E"); + req.setVinCodeList(vins); + if (!StringUtils.equalsAnyIgnoreCase(exportIn.getVoyageId(), "HT6", "HTLG", "HTTC")) { + req.setVvyId(exportIn.getVoyageId()); + } + List status = openApi.getVinStatus(req); + collect = status.stream().collect(Collectors.toMap(WorkStatusDTO::getVinCode, WorkStatusDTO::getWorkStatus)); } - List status = openApi.getVinStatus(req); - collect = status.stream().collect(Collectors.toMap(WorkStatusDTO::getVinCode, WorkStatusDTO::getWorkStatus)); - } - if (MapUtils.isNotEmpty(collect)) { - for (CustomerExportInCargo cargo : page.getRecords()) { - cargo.setWorkStatus(collect.get(cargo.getVin())); + + if (MapUtils.isNotEmpty(collect)) { + for (CustomerExportInCargo cargo : page.getRecords()) { + cargo.setWorkStatus(collect.get(cargo.getVin())); + } } - } + }); + return ResultUtil.success(page); } @@ -398,7 +531,7 @@ public class ExportInHandler implements BaseHandler { return entity; }).collect(Collectors.toList()); - if (CollectionUtils.isNotEmpty(cargos)) { + if (CollectionUtils.isNotEmpty(cargos) && !StringUtils.equalsAnyIgnoreCase(exportIn.getCartType(), "备件", "BJ")) { if (exportIn.getQuantity() != cargos.size()) { return ResultUtil.failure(ErrorType.PROGRAM_ERROR.id(), "车辆数不等于明细数量"); } @@ -452,7 +585,7 @@ public class ExportInHandler implements BaseHandler { return ResultUtil.failure(ErrorType.PROGRAM_ERROR.id(), "进场货物的进场时间,要小于表头进场时间"); } // 进场时间的数量加起来要和数量进行匹配,如果超过无法进行输入,自动获取进场时间加起来的数量 - int num = times.stream().mapToInt(CustomerExportInTimes::getEnterQuantity).sum(); + int num = exportIn.getEnterQuantity(); if (num != exportIn.getQuantity()) { return ResultUtil.failure(ErrorType.PROGRAM_ERROR.id(), "进场货物的数量,要等于进场货物的所有数量"); } @@ -527,11 +660,11 @@ public class ExportInHandler implements BaseHandler { return ResultUtil.success("success"); } - @ApiOperation("取消提交审核") + @ApiOperation("撤销提交审核") @PostMapping("/submit-check/reverse") public Result submitCheckReverse(@RequestBody - @NotNull(message = "请传入要审核的出口进场ID") - @Size(min = 1, message = "ID列表不能为空") List ids) { + @NotNull(message = "请传入要审核的出口进场ID") + @Size(min = 1, message = "ID列表不能为空") List ids) { customerExportInService.lambdaUpdate().set(CustomerExportIn::getCheckStatus, AuditEnum.SUBMIT) .set(CustomerExportIn::getCheckResult, null) .in(CustomerExportIn::getId, ids).update(); @@ -545,45 +678,47 @@ public class ExportInHandler implements BaseHandler { if (form.getEachQuantity() == null || form.getEachVolume() == null || form.getEachWeight() == null) { return ResultUtil.failure(ErrorType.PARAMS_ERROR.id(), "单票体积,单票件数,单票重量不能为空"); } - // 查询出货物列表 - List list = customerExportInCargoService.lambdaQuery() - .exists("select id from customer_export_in where customer_export_in.id = customer_export_in_cargo.export_in_id and check_status={0} and ship_id={1} and voyage_id={2} and bill_num={3}", AuditEnum.AUDIT_PASS, form.getShipId(), form.getVoyageId(), form.getBillNo()) - .list(); - // 转成MAP - Map collect = list.stream().collect(Collectors.toMap(CustomerExportInCargo::getVin, item -> item)); - // 找出状态不一致的,(有些情况下可能会出现本来是正常的,传进来的也是正常) - Map> listMap = form.getVins().stream().filter(item -> collect.containsKey(item.getVin())).filter(item -> item.getStatus() != collect.get(item.getVin()).getVinStatus()) - .collect(Collectors.groupingBy(CargoStatus::getStatus)); + if (CollectionUtils.isNotEmpty(form.getVins())) { + // 查询出货物列表 + List list = customerExportInCargoService.lambdaQuery() + .exists("select id from customer_export_in where customer_export_in.id = customer_export_in_cargo.export_in_id and check_status={0} and ship_id={1} and voyage_id={2} and bill_num={3}", AuditEnum.AUDIT_PASS, form.getShipId(), form.getVoyageId(), form.getBillNo()) + .list(); + // 转成MAP + Map collect = list.stream().collect(Collectors.toMap(CustomerExportInCargo::getVin, item -> item)); + // 找出状态不一致的,(有些情况下可能会出现本来是正常的,传进来的也是正常) + Map> listMap = form.getVins().stream().filter(item -> collect.containsKey(item.getVin())).filter(item -> item.getStatus() != collect.get(item.getVin()).getVinStatus()) + .collect(Collectors.groupingBy(CargoStatus::getStatus)); - if (listMap.containsKey(0)) { // 代表取消 - listMap.get(0).stream().map(item -> collect.get(item.getVin())) // 找到数据库中的明细 - .collect(Collectors.groupingBy(CustomerExportInCargo::getExportInId)) // 按主表ID进行分组 - .entrySet().stream().forEach(entry -> { - // 修改进场数量,和数量 - customerExportInService.update().setSql("enter_quantity=enter_quantity-" + entry.getValue().size() + ",quantity=quantity-" + entry.getValue().size()) - .eq("id", entry.getKey()).update(); - }); - } else if (listMap.containsKey(1)) { // 代表恢复 - listMap.get(1).stream().map(item -> collect.get(item.getVin())) // 找到数据库中的明细 - .collect(Collectors.groupingBy(CustomerExportInCargo::getExportInId)) // 按主表ID进行分组 - .entrySet().stream().forEach(entry -> { - // 修改进场数量,和数量 - customerExportInService.update().setSql("enter_quantity=enter_quantity+" + entry.getValue().size() + ",quantity=quantity+" + entry.getValue().size()) - .eq("id", entry.getKey()).update(); - }); + if (listMap.containsKey(0)) { // 代表取消 + listMap.get(0).stream().map(item -> collect.get(item.getVin())) // 找到数据库中的明细 + .collect(Collectors.groupingBy(CustomerExportInCargo::getExportInId)) // 按主表ID进行分组 + .entrySet().stream().forEach(entry -> { + // 修改进场数量,和数量 + customerExportInService.update().setSql("enter_quantity=enter_quantity-" + entry.getValue().size() + ",quantity=quantity-" + entry.getValue().size()) + .eq("id", entry.getKey()).update(); + }); + } else if (listMap.containsKey(1)) { // 代表恢复 + listMap.get(1).stream().map(item -> collect.get(item.getVin())) // 找到数据库中的明细 + .collect(Collectors.groupingBy(CustomerExportInCargo::getExportInId)) // 按主表ID进行分组 + .entrySet().stream().forEach(entry -> { + // 修改进场数量,和数量 + customerExportInService.update().setSql("enter_quantity=enter_quantity+" + entry.getValue().size() + ",quantity=quantity+" + entry.getValue().size()) + .eq("id", entry.getKey()).update(); + }); + } + + // 批量修改车辆的状态 + List update = new ArrayList<>(); + listMap.entrySet().stream().forEach(item -> { + update.addAll(item.getValue().stream().map(p -> { + CustomerExportInCargo cargo = collect.get(p.getVin()); + cargo.setVinStatus(item.getKey()); + return cargo; + }).collect(Collectors.toList())); + }); + customerExportInCargoService.updateBatchById(update); } - // 批量修改车辆的状态 - List update = new ArrayList<>(); - listMap.entrySet().stream().forEach(item -> { - update.addAll(item.getValue().stream().map(p -> { - CustomerExportInCargo cargo = collect.get(p.getVin()); - cargo.setVinStatus(item.getKey()); - return cargo; - }).collect(Collectors.toList())); - }); - customerExportInCargoService.updateBatchById(update); - // 修改提单号的信息 customerExportInService.lambdaUpdate() .set(CustomerExportIn::getEachQuantity, form.getEachQuantity()) @@ -693,7 +828,7 @@ public class ExportInHandler implements BaseHandler { return entity; }).collect(Collectors.toList()); - if (CollectionUtils.isNotEmpty(cargos)) { + if (CollectionUtils.isNotEmpty(cargos) && !StringUtils.equalsAnyIgnoreCase(exportIn.getCartType(), "备件", "BJ")) { if (exportIn.getQuantity() != cargos.size()) { return ResultUtil.failure(ErrorType.PROGRAM_ERROR.id(), "车辆数不等于明细数量"); } @@ -754,7 +889,7 @@ public class ExportInHandler implements BaseHandler { return ResultUtil.failure(ErrorType.PROGRAM_ERROR.id(), "进场货物的进场时间,要小于表头进场时间"); } // 进场时间的数量加起来要和数量进行匹配,如果超过无法进行输入,自动获取进场时间加起来的数量 - int num = times.stream().mapToInt(CustomerExportInTimes::getEnterQuantity).sum(); + int num = exportIn.getEnterQuantity(); if (num != exportIn.getQuantity()) { return ResultUtil.failure(ErrorType.PROGRAM_ERROR.id(), "进场货物的数量,要等于进场货物的所有数量"); } @@ -856,6 +991,26 @@ public class ExportInHandler implements BaseHandler { item.setCartType(exportIn.getCartType()); }); + // 获取作业状态 + Map statCollect = null; + List vins = collect.stream().map(item -> item.getVin()).collect(Collectors.toList()); + if (CollectionUtils.isNotEmpty(vins)) { + VinStatusRequest req = new VinStatusRequest(); + req.setBusinessType("IN_PORT"); + req.setImportExportType("E"); + req.setVinCodeList(vins); + if (!StringUtils.equalsAnyIgnoreCase(exportIn.getVoyageId(), "HT6", "HTLG", "HTTC")) { + req.setVvyId(exportIn.getVoyageId()); + } + List status = openApi.getVinStatus(req); + statCollect = status.stream().collect(Collectors.toMap(WorkStatusDTO::getVinCode, WorkStatusDTO::getWorkStatus)); + } + + if (MapUtils.isNotEmpty(statCollect)) { + for (CustomerExportInCargo cargo : collect) { + cargo.setWorkStatus(statCollect.get(cargo.getVin())); + } + } customerService.wrapperEntity(collect); List cargos = collect.stream().filter(item -> item.getCargoType() == 0).collect(Collectors.toList()); @@ -948,9 +1103,61 @@ public class ExportInHandler implements BaseHandler { return ResultUtil.failure(ErrorType.PARAMS_ERROR.id(), "修改失败,ID不存在"); } + @ApiOperation("批量修改船名航次") + @Transactional(rollbackFor = {Exception.class}) @PostMapping("/batch-update/shipVoyage") public Result shipVoyageUpdate(@RequestBody @Validated(ValidationGroup.insert.class) BatchUpdateShipVo form) { + Boolean havePlan = openApi.haveShipPlan(form.getVoyageId()); + if (havePlan) { + return ResultUtil.failure(ErrorType.PARAMS_ERROR.id(), "已生成装船计划,不支持批量修改航次"); + } + + // 船名,航次必须相同才能修改 + long count = customerExportInService.query() + .select("distinct(voyage_id)") + .eq("ship_id", form.getShipId()) + .eq("check_status", AuditEnum.AUDIT) + .count(); + + if (count > 0) { + return ResultUtil.failure(ErrorType.PARAMS_ERROR.id(), "所选船名航次不同,不支持批量修改航次"); + } + + // 判断是不是备件,如果是备件,则需要重新生成 + List exportInList = customerExportInService.lambdaQuery() + .eq(CustomerExportIn::getShipId, form.getShipId()) + .eq(CustomerExportIn::getCheckStatus, AuditEnum.AUDIT).list(); + + exportInList.stream().filter(item -> StringUtils.equals("备件", item.getCartType()) && StringUtils.equalsAnyIgnoreCase(item.getVoyage(), "HT6", "HTTC", "HTLG")) + .forEach(item -> { + String vvyId = item.getVoyageId(); + TransitPartRequest request = new TransitPartRequest(); + request.setVvyIds(Arrays.asList(vvyId)); + request.setPartAmount(item.getQuantity()); + request.setMnfBl(item.getBillNum()); + Map> rst = openApi.getTransitPart(request); + + List vins = new ArrayList<>(item.getQuantity()); + if (MapUtils.isNotEmpty(rst) && CollectionUtils.isNotEmpty(rst.get(vvyId))) { // 需要自动生成 + vins.addAll(rst.get(vvyId).stream().map(t -> t.getVinCode()).collect(Collectors.toList())); + + List spares = vins.stream().map(p -> { + CustomerExportInCargo entity = new CustomerExportInCargo(); + entity.setCargoType(1); + entity.setVinStatus(1); + entity.setVin(p); + entity.setTermcd(item.getPortAreaId()); + return entity; + }).collect(Collectors.toList()); + + // 先删除 + customerExportInCargoService.lambdaUpdate().eq(CustomerExportInCargo::getExportInId, item.getId()).remove(); + // 后保存 + customerExportInCargoService.saveBatch(spares); + } + }); + customerExportInService.lambdaUpdate() .set(CustomerExportIn::getVoyageId, form.getVoyageId()) .set(CustomerExportIn::getVoyage, form.getVoyage()) @@ -963,9 +1170,103 @@ public class ExportInHandler implements BaseHandler { return ResultUtil.success("success"); } + @ApiOperation("批量修改船名航次(新)") + @Transactional(rollbackFor = {Exception.class}) + @PostMapping("/update/shipVoyage/new") + public Result shipVoyageUpdate(@RequestBody @Validated(ValidationGroup.insert.class) UpdateVoyageVo form) { + List exportIns = customerExportInService.query() + .select("distinct voyage_id, ship_id") + .in("id", form.getIds()) + .list(); + + if (exportIns.size() > 1) { + return ResultUtil.failure(ErrorType.PARAMS_ERROR.id(), "所选船名航次不同,不支持批量修改航次"); + } + + Boolean havePlan = openApi.haveShipPlan(exportIns.get(0).getVoyageId()); + if (havePlan) { + return ResultUtil.failure(ErrorType.PARAMS_ERROR.id(), "已生成装船计划,不支持批量修改航次"); + } + + // 判断是不是备件,如果是备件,则需要重新生成 + List exportInList = customerExportInService.lambdaQuery() + .in(CustomerExportIn::getId, form.getIds()).list(); + + exportInList.stream().filter(item -> StringUtils.equals("备件", item.getCartType()) && StringUtils.equalsAnyIgnoreCase(item.getVoyage(), "HT6", "HTTC", "HTLG")) + .forEach(item -> { + String vvyId = item.getVoyageId(); + TransitPartRequest request = new TransitPartRequest(); + request.setVvyIds(Arrays.asList(vvyId)); + request.setPartAmount(item.getQuantity()); + request.setMnfBl(item.getBillNum()); + Map> rst = openApi.getTransitPart(request); + + List vins = new ArrayList<>(item.getQuantity()); + if (MapUtils.isNotEmpty(rst) && CollectionUtils.isNotEmpty(rst.get(vvyId))) { // 需要自动生成 + vins.addAll(rst.get(vvyId).stream().map(t -> t.getVinCode()).collect(Collectors.toList())); + + List spares = vins.stream().map(p -> { + CustomerExportInCargo entity = new CustomerExportInCargo(); + entity.setCargoType(1); + entity.setVinStatus(1); + entity.setVin(p); + entity.setTermcd(item.getPortAreaId()); + return entity; + }).collect(Collectors.toList()); + + // 先删除 + customerExportInCargoService.lambdaUpdate().eq(CustomerExportInCargo::getExportInId, item.getId()).remove(); + // 后保存 + customerExportInCargoService.saveBatch(spares); + } + }); + + customerExportInService.lambdaUpdate() + .set(CustomerExportIn::getVoyageId, form.getVoyageId()) + .set(CustomerExportIn::getVoyage, form.getVoyage()) + .in(CustomerExportIn::getId, form.getIds()) + .update(); + + return ResultUtil.success("success"); + } + @ApiOperation("单个修改船名航次") + @Transactional(rollbackFor = {Exception.class}) @PostMapping("/update/shipVoyage") public Result shipVoyageUpdate(@RequestBody @Validated(ValidationGroup.insert.class) UpdateShipVo form) { + // 判断是不是备件,如果是备件,则需要重新生成 + List exportInList = customerExportInService.lambdaQuery() + .eq(CustomerExportIn::getId, form.getId()).list(); + + exportInList.stream().filter(item -> StringUtils.equals("备件", item.getCartType()) && StringUtils.equalsAnyIgnoreCase(item.getVoyage(), "HT6", "HTTC", "HTLG")) + .forEach(item -> { + String vvyId = item.getVoyageId(); + TransitPartRequest request = new TransitPartRequest(); + request.setVvyIds(Arrays.asList(vvyId)); + request.setPartAmount(item.getQuantity()); + request.setMnfBl(item.getBillNum()); + Map> rst = openApi.getTransitPart(request); + + List vins = new ArrayList<>(item.getQuantity()); + if (MapUtils.isNotEmpty(rst) && CollectionUtils.isNotEmpty(rst.get(vvyId))) { // 需要自动生成 + vins.addAll(rst.get(vvyId).stream().map(t -> t.getVinCode()).collect(Collectors.toList())); + + List spares = vins.stream().map(p -> { + CustomerExportInCargo entity = new CustomerExportInCargo(); + entity.setCargoType(1); + entity.setVinStatus(1); + entity.setVin(p); + entity.setTermcd(item.getPortAreaId()); + return entity; + }).collect(Collectors.toList()); + + // 先删除 + customerExportInCargoService.lambdaUpdate().eq(CustomerExportInCargo::getExportInId, item.getId()).remove(); + // 后保存 + customerExportInCargoService.saveBatch(spares); + } + }); + customerExportInService.lambdaUpdate() .set(CustomerExportIn::getVoyageId, form.getVoyageId()) .set(CustomerExportIn::getVoyage, form.getVoyage()) @@ -1195,6 +1496,13 @@ public class ExportInHandler implements BaseHandler { @ApiOperation("车架号导入(文件形式)") @PostMapping("/import-vin") public Result> importVin(@RequestParam(required = false) @NotNull(message = "出口进场ID不能为空") Long id, MultipartFile file) throws IOException { + CustomerExportIn exportIn = customerExportInService.getById(id); + Boolean havePlan = openApi.haveShipPlan(exportIn.getVoyageId()); + if (havePlan) { + return ResultUtil.failure(ErrorType.PARAMS_ERROR.id(), "已生成装船计划,不能导入"); + } + + // 有错误的数据 List errorDataList = new ArrayList<>(); @@ -1574,7 +1882,7 @@ public class ExportInHandler implements BaseHandler { Map> collect = list.stream().collect(Collectors.groupingBy(CustomerExportInCargo::getExportInId)); if (customerExportInCargoService.removeByIds(ids)) { collect.entrySet().stream().forEach(item -> { - customerExportInService.update().setSql("quantity=quantity-"+item.getValue().size()+",enter_quantity=enter_quantity-"+item.getValue().size()).eq("id", item.getKey()).update(); + customerExportInService.update().setSql("quantity=quantity-" + item.getValue().size() + ",enter_quantity=enter_quantity-" + item.getValue().size()).eq("id", item.getKey()).update(); }); } return ResultUtil.success("success"); @@ -1582,11 +1890,15 @@ public class ExportInHandler implements BaseHandler { @ApiOperation("出口进场导出") @GetMapping("/exportExecl") - public void exportExecl(ExportInQuery query, HttpServletResponse response) { + public void exportExecl( + @ApiParam(name = "操作方式, 0为前端,1为审核端") @RequestParam(required = false, defaultValue = "0") String type, + ExportInQuery query, HttpServletResponse response) { if (query.getEndEnterTime() != null) { query.setEndEnterTime(DateUtils.getDayEnd(query.getEndEnterTime())); } - query.setCreateBy(UserContext.getUser().getUserId()); + if (StringUtils.equals(type, "0")) { + query.setCreateBy(UserContext.getUser().getUserId()); + } query.setPage(1); query.setRows(500); Wrapper queryWrapper = new WrapperKit() { @@ -1744,11 +2056,52 @@ public class ExportInHandler implements BaseHandler { @ApiOperation("出口进场计划导入模板下载") @GetMapping("/temp/down/plan") - public void tmpDownPlan(HttpServletResponse response) throws Exception { - ExcelWriter excelWriter = null; - OutputStream out = null; - try { - out = response.getOutputStream(); + public void newTmpDownPlan(HttpServletResponse response) throws Exception { + + // 车型基础数据 + List carTypeList = dictHandler.getCartTypeList(null).getData(); + + // 加载模板 + ClassPathResource classPathResource = new ClassPathResource("templates/in_temp.xlsx"); + InputStream inputStream = classPathResource.getInputStream(); + + XSSFWorkbook workbook = new XSSFWorkbook(inputStream); + + XSSFSheet sheet = workbook.getSheetAt(1); + + // 车型 + XSSFRow row = sheet.getRow(0); + if (row == null) { + row = sheet.createRow(0); + } + for (int i = 0; i < carTypeList.size(); i++) { + XSSFCell cell = row.getCell(i); + if (cell == null) { +// XSSFCellStyle cellStyle = row.getCell(i).getCellStyle(); + cell = row.createCell(i); +// cell.setCellStyle(cellStyle); + } + cell.setCellValue(carTypeList.get(i).getText()); + + // 车型明细 + List data = dictHandler.getCartTypeDetailList(carTypeList.get(i).getId(), null).getData(); + for (int j = 0; j < data.size(); j++) { + XSSFRow r = sheet.getRow(j + 1); + if (r == null) { + r = sheet.createRow(j + 1); + } + XSSFCell c = r.getCell(i); + if (c == null) { +// XSSFCellStyle cellStyle = r.getCell(i).getCellStyle(); + c = r.createCell(i); +// c.setCellStyle(cellStyle); + } + c.setCellValue(data.get(j).getText()); + } + } + + OutputStream out = response.getOutputStream(); + try (ByteArrayOutputStream bos = new ByteArrayOutputStream()) { // 这里注意 有同学反应使用swagger 会导致各种问题,请直接用浏览器或者用postman response.setContentType("application/vnd.ms-excel"); @@ -1757,20 +2110,13 @@ public class ExportInHandler implements BaseHandler { 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(ExportInPlanExcel.class).build(); - - // 查询数据 - List rows = new ArrayList<>(); - - excelWriter.write(rows, writeSheet); + workbook.write(bos); + byte[] bArray = bos.toByteArray(); + InputStream is = new ByteArrayInputStream(bArray); + IOUtils.copy(is, out); } catch (Exception e) { e.printStackTrace(); } finally { - if (excelWriter != null) { - excelWriter.finish(); - } if (out != null) { try { out.close(); @@ -1850,6 +2196,12 @@ public class ExportInHandler implements BaseHandler { // 港区、船名、港口、品牌、车型 validData.stream().forEach(item -> { + if (item.getEnterQuantity() != item.getQuantity()) { + JSONObject o = JSONObject.from(item); + o.put("status", "数量和进场数量不一致"); + errorDataList.add(o); + return; + } if (portList.stream().filter(p -> StringUtils.equalsIgnoreCase(p.getText(), item.getPortName())).count() == 0) { JSONObject o = JSONObject.from(item); o.put("status", "港口不存在"); @@ -1994,6 +2346,7 @@ public class ExportInHandler implements BaseHandler { in.setFreightId(companyMap.get(item.getFreight())); in.setApplicantId(UserContext.getUser().getUserId()); in.setTermcd(in.getPortAreaId()); + in.setVolume(in.getLength().multiply(in.getWeight()).multiply(in.getHeight()).setScale(4, RoundingMode.HALF_UP)); // 计算体积 if (StringUtils.equals("1", type)) { in.setCheckStatus(AuditEnum.AUDIT); @@ -2065,15 +2418,27 @@ public class ExportInHandler implements BaseHandler { // 如果是备件自动生成条码 // 过滤出是备件的 item.getValue().stream().filter(ss -> StringUtils.equals(ss.getCartType(), "备件")).forEach(ss -> { - // 出口进场计划备件条码生成的规则要变一下,BJ+年月日时分+5随机数,一共要17位 - String prefix = StringUtils.join("BJ", DateUtil.format(new Date(), "yyMMddHHmm")); + // 判断是否是国际中转航次ID + String vvyId = ss.getVoyageId(); + TransitPartRequest request = new TransitPartRequest(); + request.setVvyIds(Arrays.asList(vvyId)); + request.setPartAmount(ss.getQuantity()); + request.setMnfBl(ss.getBillNum()); + Map> rst = openApi.getTransitPart(request); + List vins = new ArrayList<>(ss.getQuantity()); - do { - String vin = prefix + RandomUtil.randomNumbers(5); - if (!vins.contains(vin)) { - vins.add(vin); - } - } while (vins.size() < ss.getQuantity()); + if (MapUtils.isNotEmpty(rst) && CollectionUtils.isNotEmpty(rst.get(vvyId))) { // 需要自动生成 + vins.addAll(rst.get(vvyId).stream().map(t -> t.getVinCode()).collect(Collectors.toList())); + } else { + // 出口进场计划备件条码生成的规则要变一下,BJ+年月日时分+5随机数,一共要17位 + String prefix = StringUtils.join("BJ", DateUtil.format(new Date(), "yyMMddHHmm")); + do { + String vin = prefix + RandomUtil.randomNumbers(5); + if (!vins.contains(vin)) { + vins.add(vin); + } + } while (vins.size() < ss.getQuantity()); + } List spares = vins.stream().map(p -> { CustomerExportInCargo entity = new CustomerExportInCargo(); entity.setCargoType(1); diff --git a/nuzar-customer-controller/src/main/java/com/haitonggauto/rtosc/handler/ExportInspectHandler.java b/nuzar-customer-controller/src/main/java/com/haitonggauto/rtosc/handler/ExportInspectHandler.java index a070b1f..0baaea4 100644 --- a/nuzar-customer-controller/src/main/java/com/haitonggauto/rtosc/handler/ExportInspectHandler.java +++ b/nuzar-customer-controller/src/main/java/com/haitonggauto/rtosc/handler/ExportInspectHandler.java @@ -1,5 +1,10 @@ package com.haitonggauto.rtosc.handler; +import cn.hutool.core.date.DatePattern; +import cn.hutool.core.date.DateUtil; +import com.alibaba.excel.EasyExcel; +import com.alibaba.excel.ExcelWriter; +import com.alibaba.excel.write.metadata.WriteSheet; import com.baomidou.mybatisplus.core.conditions.Wrapper; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; @@ -9,13 +14,17 @@ import com.haitonggauto.rtosc.api.NuzarOpenApi; import com.haitonggauto.rtosc.api.NuzarYardApi; import com.haitonggauto.rtosc.api.dto.*; import com.haitonggauto.rtosc.common.context.UserContext; +import com.haitonggauto.rtosc.common.dto.DictDTO; import com.haitonggauto.rtosc.common.dto.Result; import com.haitonggauto.rtosc.common.enums.ErrorType; import com.haitonggauto.rtosc.common.handler.BaseHandler; +import com.haitonggauto.rtosc.common.utils.DateUtils; import com.haitonggauto.rtosc.common.utils.ResultUtil; import com.haitonggauto.rtosc.common.utils.ValidationGroup; import com.haitonggauto.rtosc.common.utils.WrapperKit; import com.haitonggauto.rtosc.dto.*; +import com.haitonggauto.rtosc.excel.ExportInExcel; +import com.haitonggauto.rtosc.excel.InspectExportExcel; import com.haitonggauto.rtosc.query.CargoQuery; import com.haitonggauto.rtosc.query.ExportInspectCheckQuery; import com.haitonggauto.rtosc.query.ExportInspectQuery; @@ -38,9 +47,12 @@ import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; import javax.annotation.Resource; +import javax.servlet.http.HttpServletResponse; import javax.validation.constraints.NotBlank; import javax.validation.constraints.NotNull; import javax.validation.constraints.Size; +import java.io.*; +import java.net.URLEncoder; import java.util.*; import java.util.stream.Collectors; @@ -99,6 +111,68 @@ public class ExportInspectHandler implements BaseHandler { return ResultUtil.success(rst, String.valueOf(page.getTotal())); } + @ApiOperation("船名模糊匹配") + @PostMapping("/ship/list") + public Result> getShipList( + @RequestParam(required = false, defaultValue = "1") Integer current, + @RequestParam(required = false, defaultValue = "10") Integer size, + @RequestParam(required = false) String q) { + QueryWrapper query = new QueryWrapper<>(); + query.select("distinct ship_id, ship_name, ship_en_name"); + query.eq("create_by", UserContext.getUser().getUserId()); + query.eq("trad_type", "E"); + if (StringUtils.isNotEmpty(q)) { + query.and((wrapper) -> { + wrapper.like("ship_name", q); + wrapper.or().like("ship_en_name", q); + }); + } + + Page page = customerExportInspectService.page(new Page<>(current, size), query); + List list = page.getRecords(); + + List rst = list.stream().map(tmp -> { + DictDTO vo = new DictDTO(); + vo.setId(tmp.getShipId()); + vo.setText(tmp.getShipName()); + vo.setExtra1(tmp.getShipEnName()); + return vo; + }).collect(Collectors.toList()); + + return ResultUtil.success(rst, String.valueOf(page.getTotal())); + } + + @ApiOperation("航次模糊匹配") + @PostMapping("/voyage/list") + public Result> getVoyageList( + @RequestParam(required = false, defaultValue = "1") Integer current, + @RequestParam(required = false, defaultValue = "10") Integer size, + @RequestParam(required = false) String shipId, + @RequestParam(required = false) String q) { + QueryWrapper query = new QueryWrapper<>(); + query.select("distinct voyage_id, voyage"); + query.eq("create_by", UserContext.getUser().getUserId()); + query.eq("trad_type", "E"); + query.eq(StringUtils.isNotEmpty(shipId), "ship_id", shipId); + if (StringUtils.isNotEmpty(q)) { + query.and((wrapper) -> { + wrapper.like("voyage", q); + }); + } + + Page page = customerExportInspectService.page(new Page<>(current, size), query); + List list = page.getRecords(); + + List rst = list.stream().map(tmp -> { + DictDTO vo = new DictDTO(); + vo.setId(tmp.getVoyageId()); + vo.setText(tmp.getVoyage()); + return vo; + }).collect(Collectors.toList()); + + return ResultUtil.success(rst, String.valueOf(page.getTotal())); + } + @ApiOperation("提单号模糊匹配") @PostMapping("/billNo/query") public Result> getExportInBillNoList( @@ -198,7 +272,7 @@ public class ExportInspectHandler implements BaseHandler { public Result> checkQuery(@RequestBody ExportInspectCheckQuery query) { query.setTradType("E"); if (query.getCheckStatus() == null) { - query.setCheckStatusList(Arrays.asList(AuditEnum.AUDIT, AuditEnum.AUDIT_PASS, AuditEnum.AUDIT_REJECT)); + query.setCheckStatusList(Arrays.asList(AuditEnum.SUBMIT, AuditEnum.AUDIT, AuditEnum.AUDIT_PASS, AuditEnum.AUDIT_REJECT)); } Wrapper queryWrapper = new WrapperKit() { }.changeBaseQueryToWrapper(CustomerExportInspect.class, query); @@ -274,6 +348,15 @@ public class ExportInspectHandler implements BaseHandler { return ResultUtil.success("success"); } + @ApiOperation("撤销提交审核") + @PostMapping("/submit-check/reverse") + public Result submitCheckReverse(@RequestBody + @NotNull(message = "请传入要审核的海关查验ID") + @Size(min = 1, message = "ID列表不能为空") List ids) { + customerExportInspectService.lambdaUpdate().set(CustomerExportInspect::getCheckStatus, AuditEnum.SUBMIT).in(CustomerExportInspect::getId, ids).update(); + return ResultUtil.success("success"); + } + /** * 删除 * @@ -505,4 +588,66 @@ public class ExportInspectHandler implements BaseHandler { } return ResultUtil.failure(ErrorType.PARAMS_ERROR.id(), "修改失败,ID不存在"); } + + /** + * + * 导出excel + * @param response + */ + @ApiOperation("导出excel") + @GetMapping("/export-execl") + public void exportExcel(HttpServletResponse response, + @RequestParam + @NotBlank(message = "请传入ID列表") String strIds) throws Exception { + List ids = Arrays.stream(StringUtils.split(strIds, "-")).map(item -> Long.valueOf(item)).collect(Collectors.toList()); + 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(DateUtil.format(new Date(), DatePattern.PURE_DATE_PATTERN) + "出口查验计划清单", "UTF-8"); + response.setHeader("Content-disposition", "attachment;filename=" + fileName + ".xlsx"); + + excelWriter = EasyExcel.write(out).build(); + + WriteSheet writeSheet = EasyExcel.writerSheet(0, "出口查验计划清单").head(ExportInExcel.class).build(); + + // 查询数据 + List list = customerExportInspectService.lambdaQuery().in(CustomerExportInspect::getId, ids).list(); + customerService.wrapperEntity(list); + // 获取查验状态 + List sids = list.stream().map(item -> item.getId() + "").collect(Collectors.toList()); + if (CollectionUtils.isNotEmpty(ids)) { + List inspectStatusStatus = openApi.getInspectStatusStatus(sids); + Map collect = inspectStatusStatus.stream().collect(Collectors.toMap(InspectStatusResp::getApplyId, InspectStatusResp::getInspectionStatusNm)); + list.forEach(item -> { + if (collect.containsKey(item.getId()+"")) { + item.setApiInspectStatus(collect.get(item.getId()+"")); + } + }); + } + + + List rows = list.stream().map(item -> PoMapper.instance.inspectEntity2ExportExcel(item)).collect(Collectors.toList()); + + 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(); + } + } + } + } } 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 2129304..7a83dfe 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 @@ -19,12 +19,14 @@ import com.haitonggauto.rtosc.common.dto.DictDTO; import com.haitonggauto.rtosc.common.dto.Result; import com.haitonggauto.rtosc.common.enums.ErrorType; import com.haitonggauto.rtosc.common.handler.BaseHandler; +import com.haitonggauto.rtosc.common.utils.DateUtils; import com.haitonggauto.rtosc.common.utils.ResultUtil; 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.query.CargoQuery; +import com.haitonggauto.rtosc.query.ExportInCheckQuery; import com.haitonggauto.rtosc.query.ExportLoadCheckQuery; import com.haitonggauto.rtosc.query.ExportLoadQuery; import com.haitonggauto.rtosc.repository.entity.*; @@ -132,6 +134,66 @@ public class ExportLoadHandler implements BaseHandler { return ResultUtil.success(rst, String.valueOf(page.getTotal())); } + @ApiOperation("船名模糊匹配") + @PostMapping("/ship/list") + public Result> getShipList( + @RequestParam(required = false, defaultValue = "1") Integer current, + @RequestParam(required = false, defaultValue = "10") Integer size, + @RequestParam(required = false) String q) { + QueryWrapper query = new QueryWrapper<>(); + query.select("distinct ship_id, ship_name, ship_en_name"); + query.eq("create_by", UserContext.getUser().getUserId()); + if (StringUtils.isNotEmpty(q)) { + query.and((wrapper) -> { + wrapper.like("ship_name", q); + wrapper.or().like("ship_en_name", q); + }); + } + + Page page = customerExportLoadService.page(new Page<>(current, size), query); + List list = page.getRecords(); + + List rst = list.stream().map(tmp -> { + DictDTO vo = new DictDTO(); + vo.setId(tmp.getShipId()); + vo.setText(tmp.getShipName()); + vo.setExtra1(tmp.getShipEnName()); + return vo; + }).collect(Collectors.toList()); + + return ResultUtil.success(rst, String.valueOf(page.getTotal())); + } + + @ApiOperation("航次模糊匹配") + @PostMapping("/voyage/list") + public Result> getVoyageList( + @RequestParam(required = false, defaultValue = "1") Integer current, + @RequestParam(required = false, defaultValue = "10") Integer size, + @RequestParam(required = false) String shipId, + @RequestParam(required = false) String q) { + QueryWrapper query = new QueryWrapper<>(); + query.select("distinct voyage_id, voyage"); + query.eq("create_by", UserContext.getUser().getUserId()); + query.eq(StringUtils.isNotEmpty(shipId), "ship_id", shipId); + if (StringUtils.isNotEmpty(q)) { + query.and((wrapper) -> { + wrapper.like("voyage", q); + }); + } + + Page page = customerExportLoadService.page(new Page<>(current, size), query); + List list = page.getRecords(); + + List rst = list.stream().map(tmp -> { + DictDTO vo = new DictDTO(); + vo.setId(tmp.getVoyageId()); + vo.setText(tmp.getVoyage()); + return vo; + }).collect(Collectors.toList()); + + return ResultUtil.success(rst, String.valueOf(page.getTotal())); + } + @ApiOperation("审核端所有待审核船名列表") @PostMapping("/check/ship/list") public Result> getCheckShipList( @@ -231,7 +293,7 @@ public class ExportLoadHandler implements BaseHandler { @PostMapping("/check/query-list") public Result> checkQuery(@RequestBody ExportLoadCheckQuery query) { if (query.getCheckStatus() == null) { - query.setCheckStatusList(Arrays.asList(AuditEnum.AUDIT, AuditEnum.AUDIT_PASS, AuditEnum.AUDIT_REJECT)); + query.setCheckStatusList(Arrays.asList(AuditEnum.SUBMIT, AuditEnum.AUDIT, AuditEnum.AUDIT_PASS, AuditEnum.AUDIT_REJECT)); } Wrapper queryWrapper = new WrapperKit() { }.changeBaseQueryToWrapper(CustomerExportLoad.class, query); @@ -240,6 +302,25 @@ public class ExportLoadHandler implements BaseHandler { return ResultUtil.success(page); } + @ApiOperation("审核端统计查询") + @PostMapping("/check/query-list/count") + public Result> checkCountQuery(@RequestBody ExportLoadCheckQuery query) { + if (query.getCheckStatus() == null) { + query.setCheckStatusList(Arrays.asList(AuditEnum.SUBMIT, AuditEnum.AUDIT, AuditEnum.AUDIT_PASS, AuditEnum.AUDIT_REJECT)); + } + + query.setSorts(null); + + QueryWrapper queryWrapper = (QueryWrapper) new WrapperKit() { + }.changeBaseQueryToWrapper(CustomerExportLoad.class, query); + + queryWrapper.select("sum(quantity) as quantity, sum(spare_quantity) as spare_quantity"); + + Map map = customerExportLoadService.getMap(queryWrapper); + + return ResultUtil.success(map); + } + @ApiOperation("根据航次ID查询审核通过出口装船记录") @PostMapping("/query-list/voyage") public Result> checkQuery(@RequestParam(required = false) @NotBlank(message = "航次ID不能为空") String voyageId, @@ -328,6 +409,16 @@ public class ExportLoadHandler implements BaseHandler { return ResultUtil.success("success"); } + @ApiOperation("撤销提交审核") + @PostMapping("/submit-check/reverse") + public Result submitCheckReverse(@RequestBody + @NotNull(message = "请传入要审核的出口装船ID") + @Size(min = 1, message = "ID列表不能为空") List ids) { + customerExportLoadService.lambdaUpdate().set(CustomerExportLoad::getCheckStatus, AuditEnum.SUBMIT) + .set(CustomerExportLoad::getCheckResult, null).in(CustomerExportLoad::getId, ids).update(); + return ResultUtil.success("success"); + } + /** * 删除 * @@ -362,67 +453,69 @@ public class ExportLoadHandler implements BaseHandler { exportInHandler.recoverVin(form); } - // 修改 装船的数据 - // 查询出货物列表 - List list = customerExportLoadCargoService.lambdaQuery() - .exists("select id from customer_export_load where customer_export_load.id = customer_export_load_cargo.export_load_id and check_status={0} and ship_id={1} and voyage_id={2} and bill_no={3}", AuditEnum.AUDIT_PASS, form.getShipId(), form.getVoyageId(), form.getBillNo()) - .list(); - // 转成MAP - Map collect = - list.stream() - .collect(Collectors.collectingAndThen( - Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(CustomerExportLoadCargo::getVin))), - ArrayList::new - )) // 先去重 - .stream().collect(Collectors.toMap(CustomerExportLoadCargo::getVin, item->item)); - // 找出状态不一致的,(有些情况下可能会出现本来是正常的,传进来的也是正常) - Map> listMap = form.getVins().stream().filter(item -> collect.containsKey(item.getVin())).filter(item -> item.getStatus() != collect.get(item.getVin()).getVinStatus()) - .collect(Collectors.groupingBy(CargoStatus::getStatus)); + if (CollectionUtils.isNotEmpty(form.getVins())) { + // 修改 装船的数据 + // 查询出货物列表 + List list = customerExportLoadCargoService.lambdaQuery() + .exists("select id from customer_export_load where customer_export_load.id = customer_export_load_cargo.export_load_id and check_status={0} and ship_id={1} and voyage_id={2} and bill_no={3}", AuditEnum.AUDIT_PASS, form.getShipId(), form.getVoyageId(), form.getBillNo()) + .list(); + // 转成MAP + Map collect = + list.stream() + .collect(Collectors.collectingAndThen( + Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(CustomerExportLoadCargo::getVin))), + ArrayList::new + )) // 先去重 + .stream().collect(Collectors.toMap(CustomerExportLoadCargo::getVin, item -> item)); + // 找出状态不一致的,(有些情况下可能会出现本来是正常的,传进来的也是正常) + Map> listMap = form.getVins().stream().filter(item -> collect.containsKey(item.getVin())).filter(item -> item.getStatus() != collect.get(item.getVin()).getVinStatus()) + .collect(Collectors.groupingBy(CargoStatus::getStatus)); - // 这里需要区分备件 - if (listMap.containsKey(0)) { // 代表取消 - listMap.get(0).stream().filter(item -> collect.containsKey(item.getVin())).map(item -> collect.get(item.getVin())) // 找到数据库中的明细 - .collect(Collectors.groupingBy(CustomerExportLoadCargo::getExportLoadId)) // 按主表ID进行分组 - .entrySet().stream().forEach(entry -> { - // 修改进场数量,和数量 - Map collect1 = entry.getValue().stream().map(item -> collect.get(item.getVin())).collect(Collectors.groupingBy(CustomerExportLoadCargo::getCargoType, Collectors.counting())); - if (collect1.containsKey(0)) { // 车辆 - customerExportLoadService.update().setSql("quantity=quantity-" + collect1.get(0)) - .eq("id", entry.getKey()).update(); - } - if (collect1.containsKey(1)) { // 备件 - customerExportLoadService.update().setSql("spare_quantity=spare_quantity-" + collect1.get(1)) - .eq("id", entry.getKey()).update(); - } - }); - } else if (listMap.containsKey(1)) { // 代表恢复 - listMap.get(1).stream().filter(item -> collect.containsKey(item.getVin())).map(item -> collect.get(item.getVin())) // 找到数据库中的明细 - .collect(Collectors.groupingBy(CustomerExportLoadCargo::getExportLoadId)) // 按主表ID进行分组 - .entrySet().stream().forEach(entry -> { - // 修改进场数量,和数量 - Map collect1 = entry.getValue().stream().map(item -> collect.get(item.getVin())).collect(Collectors.groupingBy(CustomerExportLoadCargo::getCargoType, Collectors.counting())); - if (collect1.containsKey(0)) { // 车辆 - customerExportLoadService.update().setSql("quantity=quantity+" + collect1.get(0)) - .eq("id", entry.getKey()).update(); - } - if (collect1.containsKey(1)) { // 备件 - customerExportLoadService.update().setSql("spare_quantity=spare_quantity+" + collect1.get(1)) - .eq("id", entry.getKey()).update(); - } - }); + // 这里需要区分备件 + if (listMap.containsKey(0)) { // 代表取消 + listMap.get(0).stream().filter(item -> collect.containsKey(item.getVin())).map(item -> collect.get(item.getVin())) // 找到数据库中的明细 + .collect(Collectors.groupingBy(CustomerExportLoadCargo::getExportLoadId)) // 按主表ID进行分组 + .entrySet().stream().forEach(entry -> { + // 修改进场数量,和数量 + Map collect1 = entry.getValue().stream().map(item -> collect.get(item.getVin())).collect(Collectors.groupingBy(CustomerExportLoadCargo::getCargoType, Collectors.counting())); + if (collect1.containsKey(0)) { // 车辆 + customerExportLoadService.update().setSql("quantity=quantity-" + collect1.get(0)) + .eq("id", entry.getKey()).update(); + } + if (collect1.containsKey(1)) { // 备件 + customerExportLoadService.update().setSql("spare_quantity=spare_quantity-" + collect1.get(1)) + .eq("id", entry.getKey()).update(); + } + }); + } else if (listMap.containsKey(1)) { // 代表恢复 + listMap.get(1).stream().filter(item -> collect.containsKey(item.getVin())).map(item -> collect.get(item.getVin())) // 找到数据库中的明细 + .collect(Collectors.groupingBy(CustomerExportLoadCargo::getExportLoadId)) // 按主表ID进行分组 + .entrySet().stream().forEach(entry -> { + // 修改进场数量,和数量 + Map collect1 = entry.getValue().stream().map(item -> collect.get(item.getVin())).collect(Collectors.groupingBy(CustomerExportLoadCargo::getCargoType, Collectors.counting())); + if (collect1.containsKey(0)) { // 车辆 + customerExportLoadService.update().setSql("quantity=quantity+" + collect1.get(0)) + .eq("id", entry.getKey()).update(); + } + if (collect1.containsKey(1)) { // 备件 + customerExportLoadService.update().setSql("spare_quantity=spare_quantity+" + collect1.get(1)) + .eq("id", entry.getKey()).update(); + } + }); + } + + // 批量修改车辆的状态 + List update = new ArrayList<>(); + listMap.entrySet().stream().forEach(item -> { + update.addAll(item.getValue().stream().map(p -> { + CustomerExportLoadCargo cargo = collect.get(p.getVin()); + cargo.setVinStatus(item.getKey()); + return cargo; + }).collect(Collectors.toList())); + }); + customerExportLoadCargoService.updateBatchById(update); } - // 批量修改车辆的状态 - List update = new ArrayList<>(); - listMap.entrySet().stream().forEach(item -> { - update.addAll(item.getValue().stream().map(p -> { - CustomerExportLoadCargo cargo = collect.get(p.getVin()); - cargo.setVinStatus(item.getKey()); - return cargo; - }).collect(Collectors.toList())); - }); - customerExportLoadCargoService.updateBatchById(update); - return ResultUtil.success("success"); } @@ -752,9 +845,50 @@ public class ExportLoadHandler implements BaseHandler { return ResultUtil.success("success"); } + @ApiOperation("批量修改船名航次(新)") + @PostMapping("/update/shipVoyage/new") + public Result shipVoyageUpdate(@RequestBody @Validated(ValidationGroup.insert.class) UpdateVoyageVo form) { + List exportLoads = customerExportLoadService.query() + .select("distinct voyage_id, ship_id") + .in("id", form.getIds()) + .list(); + + if (exportLoads.size() > 1) { + return ResultUtil.failure(ErrorType.PARAMS_ERROR.id(), "所选船名航次不同,不支持批量修改航次"); + } + + Boolean havePlan = openApi.haveShipPlan(exportLoads.get(0).getVoyageId()); + if (havePlan) { + return ResultUtil.failure(ErrorType.PARAMS_ERROR.id(), "已生成装船计划,不支持批量修改航次"); + } + + customerExportLoadService.lambdaUpdate() + .set(CustomerExportLoad::getVoyageId, form.getVoyageId()) + .set(CustomerExportLoad::getVoyage, form.getVoyage()) + .in(CustomerExportLoad::getId, form.getIds()) + .update(); + + return ResultUtil.success("success"); + } + @ApiOperation("批量修改船名航次") @PostMapping("/batch-update/shipVoyage") public Result shipVoyageUpdate(@RequestBody @Validated(ValidationGroup.update.class) BatchUpdateShipVo form) { + Boolean havePlan = openApi.haveShipPlan(form.getVoyageId()); + if (havePlan) { + return ResultUtil.failure(ErrorType.PARAMS_ERROR.id(), "已生成装船计划,不支持批量修改航次"); + } + + // 船名,航次必须相同才能修改 + long count = customerExportInService.query() + .select("distinct(voyage_id)") + .eq("ship_id", form.getShipId()) + .eq("check_status", AuditEnum.AUDIT) + .count(); + + if (count > 0) { + return ResultUtil.failure(ErrorType.PARAMS_ERROR.id(), "所选船名航次不同,不支持批量修改航次"); + } customerExportLoadService.lambdaUpdate() .set(CustomerExportLoad::getVoyageId, form.getVoyageId()) diff --git a/nuzar-customer-controller/src/main/java/com/haitonggauto/rtosc/handler/FreeTradeHandler.java b/nuzar-customer-controller/src/main/java/com/haitonggauto/rtosc/handler/FreeTradeHandler.java index bc29eb8..4f37f9f 100644 --- a/nuzar-customer-controller/src/main/java/com/haitonggauto/rtosc/handler/FreeTradeHandler.java +++ b/nuzar-customer-controller/src/main/java/com/haitonggauto/rtosc/handler/FreeTradeHandler.java @@ -99,7 +99,7 @@ public class FreeTradeHandler implements BaseHandler { query.setEndCreateDate(DateUtils.getDayEnd(query.getEndCreateDate())); } if (query.getCheckStatus() == null) { - query.setCheckStatusList(Arrays.asList(AuditEnum.AUDIT, AuditEnum.AUDIT_PASS, AuditEnum.AUDIT_REJECT)); + query.setCheckStatusList(Arrays.asList(AuditEnum.SUBMIT, AuditEnum.AUDIT, AuditEnum.AUDIT_PASS, AuditEnum.AUDIT_REJECT)); } Wrapper queryWrapper = new WrapperKit() { }.changeBaseQueryToWrapper(CustomerFreeTrade.class, query); @@ -236,6 +236,18 @@ public class FreeTradeHandler implements BaseHandler { return ResultUtil.success("success"); } + @ApiOperation("撤销提交审核") + @PostMapping("/submit-check/reverse") + public Result submitCheckReverse(@RequestBody List ids) { + if (CollectionUtils.isEmpty(ids)) { + } else { + customerFreeTradeService.lambdaUpdate().set(CustomerFreeTrade::getCheckStatus, AuditEnum.SUBMIT) + .set(CustomerFreeTrade::getCheckResult, null) + .in(CustomerFreeTrade::getId, ids).update(); + } + return ResultUtil.success("success"); + } + /** * 验证车架号状态是否激活 * @param vins diff --git a/nuzar-customer-controller/src/main/java/com/haitonggauto/rtosc/handler/ImportInspectHandler.java b/nuzar-customer-controller/src/main/java/com/haitonggauto/rtosc/handler/ImportInspectHandler.java index a3d6e6c..8ad9597 100644 --- a/nuzar-customer-controller/src/main/java/com/haitonggauto/rtosc/handler/ImportInspectHandler.java +++ b/nuzar-customer-controller/src/main/java/com/haitonggauto/rtosc/handler/ImportInspectHandler.java @@ -1,5 +1,10 @@ package com.haitonggauto.rtosc.handler; +import cn.hutool.core.date.DatePattern; +import cn.hutool.core.date.DateUtil; +import com.alibaba.excel.EasyExcel; +import com.alibaba.excel.ExcelWriter; +import com.alibaba.excel.write.metadata.WriteSheet; import com.baomidou.mybatisplus.core.conditions.Wrapper; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; @@ -9,6 +14,7 @@ import com.haitonggauto.rtosc.api.NuzarOpenApi; import com.haitonggauto.rtosc.api.dto.*; import com.haitonggauto.rtosc.api.dto.log.ImportInspectLog; import com.haitonggauto.rtosc.common.context.UserContext; +import com.haitonggauto.rtosc.common.dto.DictDTO; import com.haitonggauto.rtosc.common.dto.Result; import com.haitonggauto.rtosc.common.enums.ErrorType; import com.haitonggauto.rtosc.common.handler.BaseHandler; @@ -16,6 +22,8 @@ import com.haitonggauto.rtosc.common.utils.ResultUtil; import com.haitonggauto.rtosc.common.utils.ValidationGroup; import com.haitonggauto.rtosc.common.utils.WrapperKit; import com.haitonggauto.rtosc.dto.*; +import com.haitonggauto.rtosc.excel.ExportInExcel; +import com.haitonggauto.rtosc.excel.InspectExportExcel; import com.haitonggauto.rtosc.handler.mapper.PoMapper; import com.haitonggauto.rtosc.query.CargoQuery; import com.haitonggauto.rtosc.query.ExportInspectCheckQuery; @@ -39,9 +47,13 @@ import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; import javax.annotation.Resource; +import javax.servlet.http.HttpServletResponse; import javax.validation.constraints.NotBlank; import javax.validation.constraints.NotNull; import javax.validation.constraints.Size; +import java.io.IOException; +import java.io.OutputStream; +import java.net.URLEncoder; import java.util.*; import java.util.stream.Collectors; @@ -97,6 +109,68 @@ public class ImportInspectHandler implements BaseHandler { return ResultUtil.success(rst, String.valueOf(page.getTotal())); } + @ApiOperation("船名模糊匹配") + @PostMapping("/ship/list") + public Result> getShipList( + @RequestParam(required = false, defaultValue = "1") Integer current, + @RequestParam(required = false, defaultValue = "10") Integer size, + @RequestParam(required = false) String q) { + QueryWrapper query = new QueryWrapper<>(); + query.select("distinct ship_id, ship_name, ship_en_name"); + query.eq("create_by", UserContext.getUser().getUserId()); + query.eq("trad_type", "I"); + if (StringUtils.isNotEmpty(q)) { + query.and((wrapper) -> { + wrapper.like("ship_name", q); + wrapper.or().like("ship_en_name", q); + }); + } + + Page page = customerExportInspectService.page(new Page<>(current, size), query); + List list = page.getRecords(); + + List rst = list.stream().map(tmp -> { + DictDTO vo = new DictDTO(); + vo.setId(tmp.getShipId()); + vo.setText(tmp.getShipName()); + vo.setExtra1(tmp.getShipEnName()); + return vo; + }).collect(Collectors.toList()); + + return ResultUtil.success(rst, String.valueOf(page.getTotal())); + } + + @ApiOperation("航次模糊匹配") + @PostMapping("/voyage/list") + public Result> getVoyageList( + @RequestParam(required = false, defaultValue = "1") Integer current, + @RequestParam(required = false, defaultValue = "10") Integer size, + @RequestParam(required = false) String shipId, + @RequestParam(required = false) String q) { + QueryWrapper query = new QueryWrapper<>(); + query.select("distinct voyage_id, voyage"); + query.eq("create_by", UserContext.getUser().getUserId()); + query.eq("trad_type", "I"); + query.eq(StringUtils.isNotEmpty(shipId), "ship_id", shipId); + if (StringUtils.isNotEmpty(q)) { + query.and((wrapper) -> { + wrapper.like("voyage", q); + }); + } + + Page page = customerExportInspectService.page(new Page<>(current, size), query); + List list = page.getRecords(); + + List rst = list.stream().map(tmp -> { + DictDTO vo = new DictDTO(); + vo.setId(tmp.getVoyageId()); + vo.setText(tmp.getVoyage()); + return vo; + }).collect(Collectors.toList()); + + return ResultUtil.success(rst, String.valueOf(page.getTotal())); + } + @ApiOperation("提单号模糊匹配") @PostMapping("/billNo/query") public Result> getExportInBillNoList( @@ -183,7 +257,7 @@ public class ImportInspectHandler implements BaseHandler { public Result> checkQuery(@RequestBody ExportInspectCheckQuery query) { query.setTradType("I"); if (query.getCheckStatus() == null) { - query.setCheckStatusList(Arrays.asList(AuditEnum.AUDIT, AuditEnum.AUDIT_PASS, AuditEnum.AUDIT_REJECT)); + query.setCheckStatusList(Arrays.asList(AuditEnum.SUBMIT, AuditEnum.AUDIT, AuditEnum.AUDIT_PASS, AuditEnum.AUDIT_REJECT)); } Wrapper queryWrapper = new WrapperKit() { }.changeBaseQueryToWrapper(CustomerExportInspect.class, query); @@ -255,6 +329,16 @@ public class ImportInspectHandler implements BaseHandler { return ResultUtil.success("success"); } + @ApiOperation("撤销提交审核") + @PostMapping("/submit-check/reverse") + public Result submitCheckReverse(@RequestBody + @NotNull(message = "请传入要审核的海关查验ID") + @Size(min = 1, message = "ID列表不能为空") List ids) { + customerExportInspectService.lambdaUpdate().set(CustomerExportInspect::getCheckStatus, AuditEnum.SUBMIT) + .set(CustomerExportInspect::getCheckReason, null).in(CustomerExportInspect::getId, ids).update(); + return ResultUtil.success("success"); + } + /** * 删除 * @@ -470,4 +554,66 @@ public class ImportInspectHandler implements BaseHandler { } return ResultUtil.failure(ErrorType.PARAMS_ERROR.id(), "修改失败,ID不存在"); } + + /** + * + * 导出excel + * @param response + */ + @ApiOperation("导出excel") + @GetMapping("/export-execl") + public void exportExcel(HttpServletResponse response, + @RequestParam + @NotBlank(message = "请传入ID列表") String strIds) throws Exception { + List ids = Arrays.stream(StringUtils.split(strIds, "-")).map(item -> Long.valueOf(item)).collect(Collectors.toList()); + 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(DateUtil.format(new Date(), DatePattern.PURE_DATE_PATTERN) + "进口查验计划清单", "UTF-8"); + response.setHeader("Content-disposition", "attachment;filename=" + fileName + ".xlsx"); + + excelWriter = EasyExcel.write(out).build(); + + WriteSheet writeSheet = EasyExcel.writerSheet(0, "进口查验计划清单").head(ExportInExcel.class).build(); + + // 查询数据 + List list = customerExportInspectService.lambdaQuery().in(CustomerExportInspect::getId, ids).list(); + customerService.wrapperEntity(list); + // 获取查验状态 + List sids = list.stream().map(item -> item.getId() + "").collect(Collectors.toList()); + if (CollectionUtils.isNotEmpty(ids)) { + List inspectStatusStatus = openApi.getInspectStatusStatus(sids); + Map collect = inspectStatusStatus.stream().collect(Collectors.toMap(InspectStatusResp::getApplyId, InspectStatusResp::getInspectionStatusNm)); + list.forEach(item -> { + if (collect.containsKey(item.getId()+"")) { + item.setApiInspectStatus(collect.get(item.getId()+"")); + } + }); + } + + + List rows = list.stream().map(item -> PoMapper.instance.inspectEntity2ExportExcel(item)).collect(Collectors.toList()); + + 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(); + } + } + } + } } diff --git a/nuzar-customer-controller/src/main/java/com/haitonggauto/rtosc/handler/ImportTakeHandler.java b/nuzar-customer-controller/src/main/java/com/haitonggauto/rtosc/handler/ImportTakeHandler.java index d5c7874..0b52848 100644 --- a/nuzar-customer-controller/src/main/java/com/haitonggauto/rtosc/handler/ImportTakeHandler.java +++ b/nuzar-customer-controller/src/main/java/com/haitonggauto/rtosc/handler/ImportTakeHandler.java @@ -153,7 +153,7 @@ public class ImportTakeHandler implements BaseHandler { @PostMapping("/check/list") public Result> checkList(@RequestBody ImportTakeQuery query) { if (query.getCheckStatus() == null) { - query.setCheckStatusList(Arrays.asList(AuditEnum.AUDIT, AuditEnum.AUDIT_PASS, AuditEnum.AUDIT_REJECT)); + query.setCheckStatusList(Arrays.asList(AuditEnum.SUBMIT, AuditEnum.AUDIT, AuditEnum.AUDIT_PASS, AuditEnum.AUDIT_REJECT)); } IPage page = importTakeCargoService.getImportTakeCargoPage(new Page<>(query.getPage(), query.getRows()), query); customerService.wrapperEntity(page.getRecords()); diff --git a/nuzar-customer-controller/src/main/java/com/haitonggauto/rtosc/handler/ImportUnloadHandler.java b/nuzar-customer-controller/src/main/java/com/haitonggauto/rtosc/handler/ImportUnloadHandler.java index 91b8bf7..c0b1141 100644 --- a/nuzar-customer-controller/src/main/java/com/haitonggauto/rtosc/handler/ImportUnloadHandler.java +++ b/nuzar-customer-controller/src/main/java/com/haitonggauto/rtosc/handler/ImportUnloadHandler.java @@ -159,7 +159,7 @@ public class ImportUnloadHandler implements BaseHandler { @PostMapping("/audit/query-list") public Result> auditQuery(@RequestBody ImportUnloadQuery query) { if (query.getCheckStatus() == null) { - query.setCheckStatusList(Arrays.asList(AuditEnum.AUDIT, AuditEnum.AUDIT_PASS, AuditEnum.AUDIT_REJECT)); + query.setCheckStatusList(Arrays.asList(AuditEnum.SUBMIT, AuditEnum.AUDIT, AuditEnum.AUDIT_PASS, AuditEnum.AUDIT_REJECT)); } Wrapper queryWrapper = new WrapperKit() { }.changeBaseQueryToWrapper(CustomerImportUnload.class, query); diff --git a/nuzar-customer-controller/src/main/java/com/haitonggauto/rtosc/handler/mapper/PoMapper.java b/nuzar-customer-controller/src/main/java/com/haitonggauto/rtosc/handler/mapper/PoMapper.java index f746ca4..67c3bcf 100644 --- a/nuzar-customer-controller/src/main/java/com/haitonggauto/rtosc/handler/mapper/PoMapper.java +++ b/nuzar-customer-controller/src/main/java/com/haitonggauto/rtosc/handler/mapper/PoMapper.java @@ -1,10 +1,7 @@ package com.haitonggauto.rtosc.handler.mapper; import com.haitonggauto.rtosc.api.dto.log.ImportInspectLog; -import com.haitonggauto.rtosc.excel.ExportInExcel; -import com.haitonggauto.rtosc.excel.ExportInPlanExcel; -import com.haitonggauto.rtosc.excel.FreeTradeExcel; -import com.haitonggauto.rtosc.excel.FreeTradeExportExcel; +import com.haitonggauto.rtosc.excel.*; import com.haitonggauto.rtosc.repository.entity.*; import com.haitonggauto.rtosc.dto.*; import org.mapstruct.Mapper; @@ -78,4 +75,6 @@ public interface PoMapper { CustomerLinkman linkmanVo2Entity(LinkmanVo vo); ImportInspectLog exportInspect2Import(CustomerExportInspect inspect); + + InspectExportExcel inspectEntity2ExportExcel(CustomerExportInspect inspect); } diff --git a/nuzar-customer-controller/src/main/java/com/haitonggauto/rtosc/service/impl/CustomerServiceImpl.java b/nuzar-customer-controller/src/main/java/com/haitonggauto/rtosc/service/impl/CustomerServiceImpl.java index 210641e..7ea0c09 100644 --- a/nuzar-customer-controller/src/main/java/com/haitonggauto/rtosc/service/impl/CustomerServiceImpl.java +++ b/nuzar-customer-controller/src/main/java/com/haitonggauto/rtosc/service/impl/CustomerServiceImpl.java @@ -307,6 +307,8 @@ public class CustomerServiceImpl implements CustomerService { } exportInTimesService.saveBatch(insert); + } else { + exportInTimesService.lambdaUpdate().eq(CustomerExportInTimes::getExportInId, exportIn.getId()).remove(); } } diff --git a/nuzar-customer-controller/src/main/resources/templates/in_temp.xlsx b/nuzar-customer-controller/src/main/resources/templates/in_temp.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..a24744598618b59eae49630b235f664b384985ab GIT binary patch literal 12850 zcmeHt1y@|#vUTGw!8N$MOK^90_u!2~kl^kRoZ#*f+}+*XL$Kg(ALrcrUe3uq-!FJ~ z_gJfYjJ;=#-fPsXsiMOAcPQGyYS z;wvy64?>L3L&lU(UKEfeB~pUWdA3Gm8BMot+bLUaHnP=zA+7*VRWTOao{r)c2&aQ3ZO8E3z9vsPXyaeocv1BXy5-d>^0_ z!gVHC={l0{3Zp}ixh;`~@?)t*MxYwp+k)x&{BO=4ljRL8U`*N_e-Sa5wtdZwGJz=Khci~`B z42m8EEo2B5Q&xPTrJ22!@#y1?D3+1*5-7NQX}X2V1^L<=`(qtsV&YOd)-(zaZ>Arh z_i+1h%6L37Bx_wM53!B2Q~pF4&&iu&3Mx-7%FZ4ArhM5f$v1$I9ART@+4-OY-vTyW z*TsB40@S&rLC5Ig#`>{bCYWnN*!k*>h_A0;0ENHN6jiU?6!eXz8*eOxd!wnogQ>M6 z1N|TKf9d&un3I2b^|ClwX)q?_pi{qBqS3YwE7Zi()(oOQWKEtym{Oh%I8tKrnxAjQ z1f8<$-@B(*x@LSzxi+iGb<0Kea6w5Fh4D)_n`u$&mVRz*gnAe6AQpKn(d|oYU2;@< z%@Rqym%Vt+7gn~N6F^V)>VxGhuGZ(r+oWT`sgdA-rFA8RR6?ecu!kSCfuk_S+BYr% z{lO6|hwrZSzLlLrw$ft69XOOvLK9OUG9IIO7qcXEc*&NdmYq-9RrPuJAY}NF*cj|R zh1PTCk5j8DB_%Pkz*MlW-|vq(A-=Wdi8`WsucnB3?lZPBBNb}cG7RP1GF9^$kE>5` zpp38AJiM*Ke^N%k0e;mB3;?)-0sxTSo^Z2fa0NP883BP-e`K{hRbAi;JDL|k)oT{Y zCvyM|3i^s<;9%em(ro9lS@}vU7A00_RHH;;(GH!c4w9T z4jaF5QrzC+Ijl*sfih{OliSa>eZ7;ljDk>SseB_pC}?2QU=9!3yPW|Lch=*TmO-V| zvk+3h8NgS?K--4)CnF&7?occ;1qQ$lJxk+g)D;iCpOwr~+T@GBDXobVEA3u&F0-U$ zo{^MuDrd$K``0gwQBvUgdJw`91GIU%@4i#*HG{{p65;$PO*SnNlI|((%ooYnO~DUi z1q&fbWb{(=A*Mli?qb4>!z0_gLE|VZ4$wz^Sq$tdl>?nwR-}TAT04!5UR^CVJ zLhU3V%Pbh%vE?FLK9RCIB;!CR9F{t>HAIK`CBhe zzYPAkv+a9O*>9+_WE80`;0uIZP12b(4WKQkaL5hUKA+QAB(n!|_N=u88z^TIzkB_u4MsZS>mEjH~ z4<5+Bm3?&{U%1jX?&4jzQu}!F9HhH(-F(yDuvYKNvufV(s8`t$o$1R`a}eye%bgM4 zCjeE1IIO|4Mm96-r_29w3L>)b=Tptt^R&WJ26nKlw&&;%5#7OI+VTUUo!DgX!T$H0 z&h^ddX#K(%2Ut#@M#_6g_SW%-ql^tAa9hk!hX)wpCSh}Jhl-GrY=Y3m#!>QfK)~v@ zZO?Pe&G`$dM=mJ1s0!nLN%7Z*J%;*G_K z?vq)p(%37oy!@`%1ex-j9LMrap@{s5B!y;rHr3Fi+t$x;M0-n-T#oerk*QL}1%`ic zSp1ExH~?snH>Un8zx|c3|C8%L-b&H8MEHOEYK}7-xI1Oy~pK7y@dr=tX_Mi%E zt6za)tVRizwKgv1|MZyp z`YmBd9ZT~qB6@^GRXIHa`^2J^oV-bk0C6#=l0iz3{}&Z)JXTY_Ea{~F0YOI`V;cVo zq-Igg@AqFLI@q#OEyBJkBD;Ra>HQ2pbPu%IVAYL`ZvTusd5#S?6bcug6-8I$XYr(m zp$Q7{DI;4aeye8yOjCr<9#5ULP`U|R`H5xJh`GV4J7(_P7~FsgA9p^BHUpVsEj4_! z*Wp7o4eJ>Hjf2|jA>2R3_%9UBeDrVey%Ylgze3``~j}ND^t*%ibHlvgyUsA~MeA$KS$g<-jNGBasLtRwkD)oQL(MuT7TG7lGVMx`030Kf>v}^LvJe$u0 z*aZXTznIwAaL6n7ED)xo6d`J@7AGW*ZtJ&6$rk#mu1m68WSGvVFi*w3H>@ybRMCY) zYzPCAeyfL?nq&;WPpkVOBM{F6DaZWWcp%pphc84cN^(5zA188gAFNu+s?Dx(o0!3z zVa@j0@d=$MLf`wHBy2^3V%=9lhvogJnkP+eY3vP>wlaR$po{{Xi~v--fMNY46y6o% zJra#`sj7qbqf`0&xQYq8uI!$2b_KSB{Y1ylL`iTP6t~=6W&!dtIgm&dYm|}bX}}Hr%is7W@Q0)zYVwMz9TAMiXWlhS*hZtakm{Zcc% zK>D5r)@-&~XS`s7T`2d*^(jp9{ZegkJaSV{b83#_MkO>J%Q80nHOi|IwPeQeDAf^& zHzCyl(et-rA2Ll%dCjmDGM+H{~X90HvhXa=ervbMD#|760{{Zd* z4h1d_p2I!zC>gq6yW>DKCqtVYn(iaAC-y|j8@v#yvtV4WfA~64=oZtHr!Y1UaQ`DH zA4hkss5qz)7g#bi6WMHe*F2>V*>20KN-`OlXbJC>TaME+ZO((~&tWSs-*kV4ka#J3UkHZtCZ@7st~$f`gN z0Q)2wZ1>)4BpS^7N&e;6!uG1_%cBY+zfvCs4bUv)(%CTB#9MV45QiFUg8{{trr}&0 z_Se-)0z^>#Aysg~dMUk$nV|UqeoyFEBaI6ebm=S@NA7GS8i6*gp{znzYQPmAC;!YsRVZQ89r?r?1UviP6>^%>_nr4~ z3~Rkb)N(YmBZB24E|gOR|D-G!sfHY4c$eYFB%DXto;|FC0?FXo0$Zf}TOr$6#Et5& zD5vBVrAXaO2*wn~U%oQ&!PBqjXH|qO=Lh75YP90#GAm0%>Nt|F-U$(|JP~H_9@ai=DLwaL+MlUheE<9~JR$WguF9>oRMxTDLv`QFPnH>Yt#4?V z>c>i#zzSkL+$1etJl%^b5wema8U9iq9bw5geG? zuEXgV4r%LjG@%R&!I)+T)GWvdU3H_lH$d7Y*}}^LMNZntqZT1Jd-qFi|6gCV-( zm^+Rx1aeToCSr9eYIVc=wzExm(%?iNQHNsYV{MR}NganIx>VZrQBs?TT z0EKS1M-j8v}06$-0h<*XOkItorI%ui$jm|(S*3Sw-QVNX9&#LjyQyVvEq1A~> z4t0TsT&`Da%rNu99)=e2Mjj%zMq@^~rk`>PCOb9-vLjZ0=79t@yLGX_>(ff zA3c05xkhh&J9a30JDB+Y?HrKWIwKVVy8ak53?!+q%b=!@O)iKmU6bwjh%yxNZ-q2g8 zR>d6ljaV~vJk+eF3!kW=fl)?PlAaHzeIe%@zZbTTXZO@{soA&So{n?u*mgs%af*(R zT}jeAOd*1Gf}kO?+B!GuC&^c)s3?qa_=*E$@`p-di=lG+f(w`!$)ro?d+8d|i0Hhd z2VnOkcJ;Ps5M+kp(veb*D+$eqo`TANF>#GM9rlfpnojTOmt>!OLrDrMgps~;%u028 zxpock9?Fd5p!Yn%_9Kj%l~OQkNa!RqC7>OJUDy!(d7O>m9#<<^&!d_@h{g<>2lfjY zQ%Y`wEY`7V;V#4nnGs;1$=s4@c0XSmUdTIP2*onZ?>!^m5{>iZ>4k-zB)l5T%4L{MxblS* zDh$*Uqg&L23yqK}`WOKk8TO&;=7U8l?fM#y`TR&%#vW^nD&k`^&i+gv_PKrq>E~qc zUlF#3YFt8=&R&vMa<<{Ei2t9ACKD|P+bsYuT8ZKS(0*6#Hxp^A11%)axV(s679S(l zm$9x$+c@G8{_4$+!Wr9lskqfWbW`2~+odOjhzjK5l?Wb$33n%H&-GuRF930GPVRB2 z7n)oQJYY|()Fn<|i~yoST+kf^V=9EshRC zt|7Qo+c+iVPFE)r(o4y_W8tcItI-PZh9I?mb$5&)=pyNmkvHg8p>lewvl z>A&Vb3(8|nc_6AdT8H|fE7l3VHHAwE2_D)9b_*h8vY@aXH{Nx8o|f8FY>K;}%@CDh z>heaF68D2_%W!ZdnuO0OK}w3$=jab+W;Un2#&KUHp2g9~ZjOQLueaaZmco;MlER;$ z5>d(H3hsGw36LUu$}CVMX`DJq*G7m@;XECGZg!X$b*6E2P zRHN3WNicyP(a6}xmfTwM2?wXSqs~#%-vrA_tD077YE_bAlm+{;4L+zx0B5N{aQNGF@jQdI+yO2?`LfZaWzAB( z;0hiPOk{3pN;O^PqDC_YGX^^NIlXX=dSO@&fy{ zeslHiCc@yhmE)bIWA2=m{TZamIgR7pc;JK7TpzB&s5y7KuvM@NH`g_lN#{}`W;^WJ zoC9KJHX%;IRK6y>TM0&=mLJe@3d9GJxy(FlmXibwPl&O>ZWwk`|O*8|nc(|j`6j2RxA z^L|`?yBEaPaXeMW4Z%+Il3JtjgA@tBBNO$u3)A}Tx$V}hy^Y5g!MSwseB(zo89XLe zEIITj2`RMciMtr&XqN^`=i_Es;Vv=)N~iD~@&dhhCyNP~yrlxVR3H6*zOP+#Q8x9! z9P*ERb5i~|u#=Mr1J;x*x@YOHsvWk#7X9>(u5>}`rWXWkj&)jf(x zZDbsQUeR$r!v?wUIX|-FQqU_=a$ilghH)_vbKF;8&GS==9S6aHwNGdUOsjrh)vZiT@ zMJuPnH@kQ%KEk6(Jlf)6*TkzGRU*J`#b#kbn(xs?uILZCfru}c=qFiB9s<}a%En?9QZpXXoIVfu8mz*;De#5<8W=qTtz)isv7Kf}C^}vus;!ti z@DDd(*d!z=@lmA1jRBvgXw#Y!@v?2iRA9?nQrNBB5vvn~jq1i8T|PB&0_BF14_KI4 zP6DQC$nBKOMljc-H2b9LCao(h(MeLN!lEpd6S{&gOS-maQzw@Qe*||9(=a|;Eg7zN zMO@XbozU{xhnsm7(8n?Tj9(SkI{ieT8WB%k%?v{l9es7|77-1*dYF2wZTBHGKJ2&z zZc(=NmR&Cuew2mbpp`c+ik6O?LV8M&q-Y`05(L(M9vYI7x@UkCtWtVS#t5UUPPr%m z;n6sLDd1={&DmQ+ZS$sQ*-Or_5Ya@aM3&YV7w5a;dr(?7|F&4~Vn{Py8VKvWR|u*^ zbt0@6cB;;(3acRl0U=c<7sI|)4=e#ase6fc)tI+P3el0h^pLkl3J_ioD&3L6#n2CM zIujOFY2vo_qW3!Jdk_Xl8~MhLFNk#phHXL*KVh2a zzcz4vv`GFIB&l>V4Gjak9~%Zi^g$s}<_cf9EG|Wo{l%XTiie>iF0Yv;YV=wJwpu~(MMJ^id2_$h<6M<8Lz#8N-l z0jR}@F%k|%i@CpKd<}y1`dY>(T!@C%PlX@$;4~l9x!06&JeJd&j?;BK9dAEz8}DPd zSnD1;@fHN-@uuc9^QOWx_cMJD)I2xEI9-Dj2Xb6sR$MP?bh2lH^RRXmZQ@rYg5NR>atn&v5IYWtTpw+4 ziQza?M>-YHmP_JQ^;eS&tOgY~9~B(dAWhAUx~mi)jySP;MSONaLHXW|Z?K4l(HrH} ze)){QGgQlLJP#HNfzBhc9vM#CZ5*r64m))lKKP!vR3Vun8AeX%8ySQ<`}0GoWOjYT zY9)*!hQJxIh*kbY^$yy3s!3zxJFcxWa&+b%*dT{Jv?fwcs;hzsuJ$9uba>?`>HvF; zOwc&Pd-wR2>OqIHA92hj^^kCynmnJYw}rOJz)JEL2C7xv!49*T5G!>LFPQ+ zCp$(*)RibvN)P#GGSY&Xzn-dT%k)+{qo(EdO`+SFnt4R2Q*p`N%%kT*D*U#$}t&Cq_Q#sDkpqb#~v5-qp)R( zBlli+cSYEh{o5li%3`hodxQVWi8WueSjFl3%W6}FXP0T;YK4Gt>r117U4Cp`E!+L0 z3%$r!LD3DoJ%N@HuU(|oec%0M#fj_V7XZ@9Ru<->;^zIOptlRAh+wdX-By0TGf!pn zdy9)Mjj0I6;WQmK?89-PID@+YRJnMV!nS6)x3=;>G|C#?HiWO@Vec~Imwq#_Zh1n z{mfuh6oE)mI!6^nJ0~f;Ll1=L7Ji9u`Ksx5p)WBJ)mc(UO72`dE2YUO2XfdC5oE|$mg6*!xt3N?Hz2nU7z)5G^y z8i_W1207iINOF!1b?_sMMey#7Mcnk#&YJTS?g++!dbw)6-##yqR@O)sTZ*O|O!=Hv@f zvNHG5r4gG9o!0oaC-#jQy;z0{3B|^=YvsXdk-DFnD;d71VQpXIH=<==sGjc{hoKzhWrmK~@l#N@wEK3tR4m!V z*kK^p7w$<4dXQkLDM718;GWU@7{lo~EdpcHj3P=(6{;UXEJx;i5%nC`&ze2O9KrCt z7hi*|PE>X!*i0*m^n~t}N=tOEOAbe@(jUdo#hqd;4_S_=+=rLfq_p4`H>8v%7T2Y6 z>ucH)#Jq}%4|f>9sAWWN8I~R|eioN?g?U`j>eyIqP`yz*<=@>FI+$b55n~BkUioG@ z(@#zogc5j&{j=5u3GxzuD|XRR$NqhA`CPabwCL>^zF?Xjyt&7g_S!Pkt(`@9_su|T zvA*$RS-^PW^90&5Q>~YwHML*XUG)J8dTLO;{P0fBnruK&<%ujS&in#|(xE5t@ndvx zi|yk>=WKPub30B)h9&hqFM3JG%6EseQ_S^0!~*{*Cy?t%HB@+OJes{7g}r-gQknpb z6&!$ejts^?2h%_5tT!Fbe|wW}OXnGZ_*~eg`Q!&O)cL zW==Wz9xpX136qNh8%WEu)bDeRqJt)}Y`ThOzSB0u=;8?$_EtzbAumL#jt1wJR~bIV ztNJJlRaAjafM3G9b}qt;IEldW5suBz^9tC(vr$g28>T8e?OYoqJUV8ni^-8auLsBt zG#b}$LfPA$rsGA}tdO7NMZddHeyaEM{8`$s5D!y;rWFB)xCrI(#m1 zP_MzVpJcdY1+#6d4?C%PRXxY`QVwChu_XZcE>LADyGQcV*H!*9j3ODBul>8+azkO0 z)~RLzt*-K!W3E(4n1@)K`bONL7C2e>_Ut1+=0e;+zj*z;%vAjRkI7o{wNhu~%?BPCl)S6&|v5kB@$`^mu=(lionkl8rPv% zq~=Vi=epc7r_lJAvRPGmZ-F?xqlb5Dko-x3Do@)CKP0vH^VTZ|>s;%$!(q&(Z zyv;n@^~Hnd`QG!%-qX!a8dOs80BY3>DE5z4M%C#l$)yt;SHzQm%>*$$Xy@&yQH@g; zq*5~LFcVf&jOnU|>$rJPF6hgK8dz+ZlvIJ{!%yZa^4}ZpF~7CUgf{G);b`G>-SYda zzq$E;#^Db>MbI>FcM#v=@S9-yFLBt}(FthtUk>~a0|0=$*a_(#Myx*+fx?4rW6|X{ z+{;mQO9DKUoURNO&FHCltOrgZuPxZz!B7nDPj33}Gm;pz+e_Z#?U{ebb(9c-_nqx# z{kpz?_NfI13w(aAx!5Du6j6S<+tl78o;S)YCif^0;(fLaBGNblTtFG8gzC!Vz%oTS zw(7|f*Uwms6*&pp-n=}Q5Fn_W3wXb@@osFwY z8ub#O+1E zgoH5qiHIV^I+n7INWy>RdJs^$x82V_%i@16>A!ycgGgRM`tJt*F4+C6fx@@Q{TKP} z@4(+>i@%`DZ!L-6M2x?K|E{F^1qA>CVE+XFe{@y9+xcBr^UG2@{Qv%m|4`ZdZsqsR z;V&!1Z~M%D(CYlzNBrH&@7 + +