Compare commits
82
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0d9ea32f85 | ||
|
|
6cb70805f1 | ||
|
|
81630339e4 | ||
|
|
ed809e82d4 | ||
|
|
c2e3de244b | ||
|
|
9453aea60f | ||
|
|
c877696eca | ||
|
|
7f6006ca48 | ||
|
|
edcfa0b510 | ||
|
|
03b168abc0 | ||
|
|
c9bd81c8f2 | ||
|
|
defc8c3709 | ||
|
|
3c21c2c848 | ||
|
|
71936b50a7 | ||
|
|
9cfffe1224 | ||
|
|
d7574d188a | ||
|
|
1c1b06c1bf | ||
|
|
117019c55c | ||
|
|
171909b68d | ||
|
|
9ac60e446a | ||
|
|
5ba179d29d | ||
|
|
31c27c16c6 | ||
|
|
8dfe9545aa | ||
|
|
6613eeb3fb | ||
|
|
0ca8548c06 | ||
|
|
3653c37914 | ||
|
|
028afb57d7 | ||
|
|
c1bbda9f9a | ||
|
|
37dd374bda | ||
|
|
0077e5d673 | ||
|
|
4b5ed4d0e1 | ||
|
|
3b8c0ffe8f | ||
|
|
21db0bc5da | ||
|
|
eaeb100b22 | ||
|
|
8d6c252eb4 | ||
|
|
86c4c07708 | ||
|
|
db31711ad0 | ||
|
|
6282849468 | ||
|
|
60381ad7c9 | ||
|
|
cd4ceecf98 | ||
|
|
cf3299165d | ||
|
|
432f71de06 | ||
|
|
6efd37fe0e | ||
|
|
d69af9ef20 | ||
|
|
9704dbfb07 | ||
|
|
65fdac5354 | ||
|
|
3387d1712d | ||
|
|
3276792bb5 | ||
|
|
b57db4b8cc | ||
|
|
8a31ed9974 | ||
|
|
76ded7ed01 | ||
|
|
bbde788aa4 | ||
|
|
10012b3437 | ||
|
|
7a5e84453c | ||
|
|
9777156959 | ||
|
|
ba5d78b36c | ||
|
|
dea39a1a4b | ||
|
|
0493030620 | ||
|
|
698a8ea9a6 | ||
|
|
3907b126d9 | ||
|
|
7b76d5c203 | ||
|
|
f991485ba3 | ||
|
|
5a3791e334 | ||
|
|
f02a2d52f2 | ||
|
|
a3c0f15e39 | ||
|
|
d2a6a5a4f6 | ||
|
|
e2bee47aac | ||
|
|
752216ad45 | ||
|
|
910c7b1701 | ||
|
|
6a8661da63 | ||
|
|
2b6777abe4 | ||
|
|
f118c7ff29 | ||
|
|
cdc8396b57 | ||
|
|
aad54545f1 | ||
|
|
49fb27f273 | ||
|
|
1367a1d225 | ||
|
|
590e840a7b | ||
|
|
a326af15f7 | ||
|
|
494f5f8999 | ||
|
|
9990701c5e | ||
|
|
9a15dc4978 | ||
|
|
e55840c485 |
@@ -19,7 +19,8 @@ import java.util.Set;
|
|||||||
/**
|
/**
|
||||||
* bms财务结算系统feign调用接口
|
* bms财务结算系统feign调用接口
|
||||||
*/
|
*/
|
||||||
@FeignClient(contextId = "BmsService", value = ServiceNameConstants.BMS_SERVICE, url = "http://10.33.0.109:8012",fallbackFactory = RemoteBmsFeignFallbackFactory.class, configuration = FeignAutoConfiguration.class)
|
// 目标地址由 nacos 配置项 feign.url.mhd-bms-service 指定,未配置时按服务名走服务发现
|
||||||
|
@FeignClient(contextId = "BmsService", value = ServiceNameConstants.BMS_SERVICE, url = "http://10.102.192.32:8019",fallbackFactory = RemoteBmsFeignFallbackFactory.class, configuration = FeignAutoConfiguration.class)
|
||||||
public interface BmsServiceFeign {
|
public interface BmsServiceFeign {
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -17,7 +17,8 @@ import org.springframework.web.bind.annotation.RequestParam;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.concurrent.CompletableFuture;
|
import java.util.concurrent.CompletableFuture;
|
||||||
|
|
||||||
@FeignClient(contextId = "OmsService", value = ServiceNameConstants.OMS_SERVICE,url = "http://10.33.0.99:8017",fallbackFactory = RemoteOmsFeignFallbackFactory.class, configuration = FeignAutoConfiguration.class)
|
// 目标地址由 nacos 配置项 feign.url.mhd-oms-service 指定,未配置时按服务名走服务发现
|
||||||
|
@FeignClient(contextId = "OmsService", value = ServiceNameConstants.OMS_SERVICE,url = "http://10.102.192.33:8017",fallbackFactory = RemoteOmsFeignFallbackFactory.class, configuration = FeignAutoConfiguration.class)
|
||||||
public interface OmsServiceFeign {
|
public interface OmsServiceFeign {
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -26,7 +26,8 @@ import org.springframework.web.bind.annotation.*;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
@FeignClient(contextId = "commonWlhyServiceFeign",value = ServiceNameConstants.WLHY_SERVICE,url = "http://10.33.0.129:8014",configuration = FeignAutoConfiguration.class)
|
// 目标地址由 nacos 配置项 feign.url.mhd-wlhy-service 指定,未配置时按服务名走服务发现
|
||||||
|
@FeignClient(contextId = "commonWlhyServiceFeign",value = ServiceNameConstants.WLHY_SERVICE,url = "http://10.102.192.31:8014",configuration = FeignAutoConfiguration.class)
|
||||||
public interface WlhyServiceFeign {
|
public interface WlhyServiceFeign {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -535,17 +536,15 @@ public interface WlhyServiceFeign {
|
|||||||
*/
|
*/
|
||||||
@PostMapping("/feign/order/add")
|
@PostMapping("/feign/order/add")
|
||||||
public AjaxResult add(@RequestBody TmsOrderAddDTO tmsOrderAddDTO);
|
public AjaxResult add(@RequestBody TmsOrderAddDTO tmsOrderAddDTO);
|
||||||
|
/**
|
||||||
|
* 修改运单(OMS调整业务单后同步修改TMS订单)
|
||||||
|
* @param tmsOrderAddDTO 需携带 TMS 订单 id 定位
|
||||||
|
*/
|
||||||
|
@PostMapping("/feign/order/update")
|
||||||
|
public AjaxResult update(@RequestBody TmsOrderAddDTO tmsOrderAddDTO);
|
||||||
@GetMapping("/feign/order/cancelIssueDocuments")
|
@GetMapping("/feign/order/cancelIssueDocuments")
|
||||||
public AjaxResult cancelIssueDocuments(@RequestParam(name="executeOrderId") String executeOrderId);
|
public AjaxResult cancelIssueDocuments(@RequestParam(name="executeOrderId") String executeOrderId);
|
||||||
|
|
||||||
/**
|
|
||||||
* OMS出库业务单反审联动: 按执行单货源编号软删TMS整条链路(货源单->运单->运输作业单, is_delete=1), 幂等,
|
|
||||||
* 与 cancelIssueDocuments(仅关闭货源单且有有效运单即拒绝)不同, 反审口径不留TMS数据
|
|
||||||
*/
|
|
||||||
@PostMapping("/feign/order/deleteChainByExecuteOrderNumber")
|
|
||||||
public AjaxResult deleteChainByExecuteOrderNumber(@RequestParam(name="executeOrderNumber") String executeOrderNumber);
|
|
||||||
|
|
||||||
@GetMapping(value = "/ntocc/tmsSettlementExchangeRate/queryList")
|
@GetMapping(value = "/ntocc/tmsSettlementExchangeRate/queryList")
|
||||||
public AjaxResult<?> queryList(@RequestParam(name="pageNo", defaultValue="1") Integer pageNo,
|
public AjaxResult<?> queryList(@RequestParam(name="pageNo", defaultValue="1") Integer pageNo,
|
||||||
@RequestParam(name="pageSize", defaultValue="10") Integer pageSize,
|
@RequestParam(name="pageSize", defaultValue="10") Integer pageSize,
|
||||||
|
|||||||
@@ -21,7 +21,8 @@ import java.util.Map;
|
|||||||
* @description: TODO
|
* @description: TODO
|
||||||
* @date 2024/5/10 8:58
|
* @date 2024/5/10 8:58
|
||||||
**/
|
**/
|
||||||
@FeignClient(contextId = "remoteWmsServiceFeign",value = ServiceNameConstants.WMS_SERVICE,fallbackFactory = RemoteWmsFallbackFactory.class, configuration = FeignAutoConfiguration.class)
|
// 目标地址由 nacos 配置项 feign.url.mhd-wms-service 指定,未配置时按服务名走服务发现
|
||||||
|
@FeignClient(contextId = "remoteWmsServiceFeign",value = ServiceNameConstants.WMS_SERVICE,url = "http://10.102.192.32:8016",fallbackFactory = RemoteWmsFallbackFactory.class, configuration = FeignAutoConfiguration.class)
|
||||||
public interface WmsServiceFeign {
|
public interface WmsServiceFeign {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -74,21 +75,21 @@ public interface WmsServiceFeign {
|
|||||||
*/
|
*/
|
||||||
@ApiOperation("oms下发单保存")
|
@ApiOperation("oms下发单保存")
|
||||||
@PostMapping(value = "/stockOutOrderApi/omsOutOrderAdd")
|
@PostMapping(value = "/stockOutOrderApi/omsOutOrderAdd")
|
||||||
public AjaxResult omsOutOrderAdd(@RequestBody StockOutOrder stockOutOrder);
|
public void omsOutOrderAdd(@RequestBody StockOutOrder stockOutOrder);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* oms下发单明细保存
|
* oms下发单明细保存
|
||||||
*/
|
*/
|
||||||
@ApiOperation("oms下发单明细保存")
|
@ApiOperation("oms下发单明细保存")
|
||||||
@PostMapping(value = "/stockOutOrderApi/omsOutOrderAddDetail")
|
@PostMapping(value = "/stockOutOrderApi/omsOutOrderAddDetail")
|
||||||
public AjaxResult omsOutOrderAddDetail(@RequestBody List<OutMaterialDetail> outMaterialDetails);
|
public void omsOutOrderAddDetail(@RequestBody List<OutMaterialDetail> outMaterialDetails);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* oms下发单明细保存
|
* oms下发单明细保存
|
||||||
*/
|
*/
|
||||||
@ApiOperation("oms下发单明细保存")
|
@ApiOperation("oms下发单明细保存")
|
||||||
@PostMapping(value = "/stockOutOrderApi/omsOutOrderAddDeliveryDetailsLink")
|
@PostMapping(value = "/stockOutOrderApi/omsOutOrderAddDeliveryDetailsLink")
|
||||||
public AjaxResult omsOutOrderAddDeliveryDetailsLink(@RequestBody List<DeliveryDetailsLink> deliveryDetailsLinks);
|
public void omsOutOrderAddDeliveryDetailsLink(@RequestBody List<DeliveryDetailsLink> deliveryDetailsLinks);
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -112,46 +113,11 @@ public interface WmsServiceFeign {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* oms下发前库存校验:可用库存不足时返回错误,OMS据此在推送前拦截下发,
|
* oms下发前库存校验:可用库存不足时返回错误,OMS据此在推送前拦截下发,
|
||||||
* 避免单据先落库、分配才失败而在WMS残留"已审核"状态的垃圾单。
|
* 避免单据先落库、分配才失败而在WMS残留"已审核"状态的垃圾单
|
||||||
* businessOrderNumber(可空):OMS出库业务单号,下单冻结模式下校验可用量=库存可用+本单冻结记录量
|
|
||||||
*/
|
*/
|
||||||
@ApiOperation("oms下发前库存校验")
|
@ApiOperation("oms下发前库存校验")
|
||||||
@PostMapping(value = "/stockOutOrderApi/checkOmsAssignInventory")
|
@PostMapping(value = "/stockOutOrderApi/checkOmsAssignInventory")
|
||||||
public AjaxResult checkOmsAssignInventory(@RequestBody List<OutMaterialDetail> outMaterialDetails,
|
public AjaxResult checkOmsAssignInventory(@RequestBody List<OutMaterialDetail> outMaterialDetails);
|
||||||
@RequestParam(value = "businessOrderNumber", required = false) String businessOrderNumber);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* oms出库业务单下单冻结库存(防超卖):WMS按明细冻结库存(可用-、冻结+,库存数量不变),
|
|
||||||
* 条件更新防并发超卖,任一行可用不足整体失败并返回错误;同业务单号幂等。
|
|
||||||
* 冻结失败必须阻断OMS下单(返回非200由OMS整体回滚)。
|
|
||||||
*/
|
|
||||||
@ApiOperation("oms出库业务单下单冻结库存")
|
|
||||||
@PostMapping(value = "/stockOutOrderApi/omsFreezeInventory")
|
|
||||||
public AjaxResult omsFreezeInventory(@RequestBody OmsFreezeInventoryParam param);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* oms出库业务单取消/删除-释放冻结库存:可用+、冻结-(库存数量不变);按业务单号幂等;
|
|
||||||
* 冻结已被执行单承接时拒绝(须先取消下发)
|
|
||||||
*/
|
|
||||||
@ApiOperation("oms出库业务单释放冻结库存")
|
|
||||||
@PostMapping(value = "/stockOutOrderApi/omsUnfreezeInventory")
|
|
||||||
public AjaxResult omsUnfreezeInventory(@RequestBody OmsFreezeInventoryParam param);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* oms出库业务单编辑-原子重锁:WMS同一事务内先释放原冻结再按新明细重新冻结,
|
|
||||||
* 任一新明细可用不足整体回滚(旧冻结同样还原),满足"先释放再重新锁定"原子性要求
|
|
||||||
*/
|
|
||||||
@ApiOperation("oms出库业务单编辑重锁库存")
|
|
||||||
@PostMapping(value = "/stockOutOrderApi/omsRelockInventory")
|
|
||||||
public AjaxResult omsRelockInventory(@RequestBody OmsFreezeInventoryParam param);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 仓库是否存在活跃冻结记录(status in 1-业务单冻结 2-执行单承接):
|
|
||||||
* 仓库"库存锁定模式"(stock_lock_mode)切换守卫,存在在途冻结单时禁止切换
|
|
||||||
*/
|
|
||||||
@ApiOperation("仓库是否存在活跃冻结记录")
|
|
||||||
@GetMapping(value = "/stockOutOrderApi/hasActiveFreezeByWarehouse/{warehouseId}")
|
|
||||||
public AjaxResult hasActiveFreezeByWarehouse(@PathVariable("warehouseId") Long warehouseId);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* oms下发单明细保存(返回执行结果,明细保存含自动审核链路,失败时OMS据此回滚)
|
* oms下发单明细保存(返回执行结果,明细保存含自动审核链路,失败时OMS据此回滚)
|
||||||
@@ -168,27 +134,6 @@ public interface WmsServiceFeign {
|
|||||||
@PostMapping(value = "/stockInOrderApi/omsCancelInOrder")
|
@PostMapping(value = "/stockInOrderApi/omsCancelInOrder")
|
||||||
public AjaxResult omsCancelInOrder(@RequestBody StockInOrder stockInOrder);
|
public AjaxResult omsCancelInOrder(@RequestBody StockInOrder stockInOrder);
|
||||||
|
|
||||||
/**
|
|
||||||
* oms出库执行单反审(已出库/已复核单据客户通知回退场景):WMS侧还原实物库存并推送OMS库存、
|
|
||||||
* 逻辑删除出库链路单据、生成1条出库异常【反审记录】;反审原因经 remark 透传。
|
|
||||||
* 已产生下游不可逆数据时返回错误,OMS据此整体回滚。
|
|
||||||
*/
|
|
||||||
@ApiOperation("oms出库执行单反审WMS回退")
|
|
||||||
@PostMapping(value = "/stockOutOrderApi/omsReverseExecutionOrder")
|
|
||||||
public AjaxResult omsReverseExecutionOrder(@RequestBody StockOutOrder stockOutOrder);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* oms入库业务单反审:WMS侧一个事务内回退已入库/收货中/上架中单据——
|
|
||||||
* 校验未产生出库(按入库单号+动作"分配库存/出库"查库存调整记录>0即有出库) ->
|
|
||||||
* 按库存行整行回退库存扣减 -> 软删W入库单/W收货单/W上架单全链并打已反审标记
|
|
||||||
* (各页面【已反审】tab按"已软删+已反审"查询归档数据)-> 写1条入库异常【反审记录】(type=3)。
|
|
||||||
* 入参: inOrderNumber=执行入库单号, remark=业务单号+反审原因, updateBy/updateByName=反审人;
|
|
||||||
* WMS无该单数据时幂等返回成功(未下发单反审不产生WMS数据)。
|
|
||||||
*/
|
|
||||||
@ApiOperation("oms入库单反审WMS回退")
|
|
||||||
@PostMapping(value = "/stockInOrderApi/omsReverseInOrder")
|
|
||||||
public AjaxResult omsReverseInOrder(@RequestBody StockInOrder stockInOrder);
|
|
||||||
|
|
||||||
@ApiOperation("oms查询物料列表")
|
@ApiOperation("oms查询物料列表")
|
||||||
@GetMapping("/materialBaseInfoApi/queryList")
|
@GetMapping("/materialBaseInfoApi/queryList")
|
||||||
public TableDataInfo getMaterialBaseInfoList(MaterialInfoDTO materialInfoDTO);
|
public TableDataInfo getMaterialBaseInfoList(MaterialInfoDTO materialInfoDTO);
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ import org.springframework.web.bind.annotation.*;
|
|||||||
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
|
// 目标地址由 nacos 配置项 feign.url.xxl-job-service 指定,未配置时按服务名走服务发现
|
||||||
@FeignClient(contextId = "XxlJobService", value = ServiceNameConstants.XXL_JOB_SERVICE,url = "http://127.0.0.1:8020",fallbackFactory = RemoteXxlJobFeignFallbackFactory.class, configuration = FeignAutoConfiguration.class)
|
@FeignClient(contextId = "XxlJobService", value = ServiceNameConstants.XXL_JOB_SERVICE,url = "http://127.0.0.1:8020",fallbackFactory = RemoteXxlJobFeignFallbackFactory.class, configuration = FeignAutoConfiguration.class)
|
||||||
public interface XxlJobServiceFeign {
|
public interface XxlJobServiceFeign {
|
||||||
|
|
||||||
|
|||||||
@@ -9,7 +9,8 @@ import com.mhd.system.api.feign.FeignAutoConfiguration;
|
|||||||
import org.springframework.cloud.openfeign.FeignClient;
|
import org.springframework.cloud.openfeign.FeignClient;
|
||||||
import org.springframework.web.bind.annotation.*;
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
|
||||||
@FeignClient(contextId = "YmsService", value = ServiceNameConstants.YMS_SERVICE,url = "http://10.33.0.99:8018",fallbackFactory = RemoteBmsFeignFallbackFactory.class, configuration = FeignAutoConfiguration.class)
|
// 目标地址由 nacos 配置项 feign.url.mhd-yms-service 指定,未配置时按服务名走服务发现
|
||||||
|
@FeignClient(contextId = "YmsService", value = ServiceNameConstants.YMS_SERVICE,url = "http://10.102.192.33:8018",fallbackFactory = RemoteBmsFeignFallbackFactory.class, configuration = FeignAutoConfiguration.class)
|
||||||
public interface YmsServiceFeign {
|
public interface YmsServiceFeign {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
-42
@@ -1,42 +0,0 @@
|
|||||||
package com.mhd.system.api.domain;
|
|
||||||
|
|
||||||
import io.swagger.annotations.ApiModelProperty;
|
|
||||||
import lombok.Data;
|
|
||||||
|
|
||||||
import java.io.Serializable;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* OMS出库业务单冻结库存请求参数
|
|
||||||
*
|
|
||||||
* @description OMS下单冻结库存模式(防超卖):OMS出库业务单「下单」即冻结WMS库存
|
|
||||||
* (可用-、冻结+,库存数量不变,库存数量=可用数量+冻结数量);
|
|
||||||
* 「编辑」原子释放旧冻结+按新明细重锁;「取消」释放冻结。
|
|
||||||
* 冻结/解冻以业务单号为幂等键。
|
|
||||||
* @date 2026-09-12
|
|
||||||
*/
|
|
||||||
@Data
|
|
||||||
public class OmsFreezeInventoryParam implements Serializable {
|
|
||||||
private static final long serialVersionUID = 1L;
|
|
||||||
|
|
||||||
@ApiModelProperty("OMS出库业务单号(幂等键)")
|
|
||||||
private String outOrderNumber;
|
|
||||||
|
|
||||||
@ApiModelProperty("执行出库单号(预留,冻结/解冻/重锁时不使用)")
|
|
||||||
private String executionOrderNumber;
|
|
||||||
|
|
||||||
@ApiModelProperty("库存行ID集合(预留)")
|
|
||||||
private List<Long> materialInventoryIds;
|
|
||||||
|
|
||||||
@ApiModelProperty("出库明细列表(须携带 materialInventoryId 定位库存行)")
|
|
||||||
private List<OutMaterialDetail> details;
|
|
||||||
|
|
||||||
@ApiModelProperty("操作人ID(Feign调用可能无登录上下文时的兜底)")
|
|
||||||
private Long operatorId;
|
|
||||||
|
|
||||||
@ApiModelProperty("操作人姓名(Feign调用可能无登录上下文时的兜底)")
|
|
||||||
private String operatorName;
|
|
||||||
|
|
||||||
@ApiModelProperty("备注")
|
|
||||||
private String remark;
|
|
||||||
}
|
|
||||||
@@ -124,10 +124,6 @@ public class WarehouseFeignPO extends BaseVOEntity{
|
|||||||
@Excel(name = "作业模式")
|
@Excel(name = "作业模式")
|
||||||
private String workMode;
|
private String workMode;
|
||||||
|
|
||||||
@ApiModelProperty("库存锁定模式: 1-下单冻结 2-分配库存冻结")
|
|
||||||
@Excel(name = "库存锁定模式: 1-下单冻结 2-分配库存冻结")
|
|
||||||
private Integer stockLockMode;
|
|
||||||
|
|
||||||
@ApiModelProperty("订单号生成规则(0-日期累加 1-历史累加)")
|
@ApiModelProperty("订单号生成规则(0-日期累加 1-历史累加)")
|
||||||
@Excel(name = "单号生成规则")
|
@Excel(name = "单号生成规则")
|
||||||
private String orderNoGenerateRule;
|
private String orderNoGenerateRule;
|
||||||
|
|||||||
+3
-4
@@ -547,14 +547,13 @@ public class RemoteWlhyFallbackFactory implements FallbackFactory<WlhyServiceFei
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public AjaxResult cancelIssueDocuments(String executeOrderId) {
|
public AjaxResult update(TmsOrderAddDTO tmsOrderAddDTO) {
|
||||||
return AjaxResult.error(cause.getMessage());
|
return AjaxResult.error(cause.getMessage());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public AjaxResult deleteChainByExecuteOrderNumber(String executeOrderNumber) {
|
public AjaxResult cancelIssueDocuments(String executeOrderId) {
|
||||||
//返回错误而非静默成功, 让OMS反审事务能感知失败并整体回滚
|
return AjaxResult.error(cause.getMessage());
|
||||||
return AjaxResult.error("TMS反审联动软删链路失败(服务降级):" + cause.getMessage());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
+5
-44
@@ -57,19 +57,16 @@ public class RemoteWmsFallbackFactory implements FallbackFactory<WmsServiceFeign
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public AjaxResult omsOutOrderAdd(StockOutOrder stockOutOrder) {
|
public void omsOutOrderAdd(StockOutOrder stockOutOrder) {
|
||||||
//返回错误而非静默成功: 降级吞掉会让OMS继续走分配, 残留"有单无明细"的垃圾单
|
|
||||||
return AjaxResult.error("WMS下发单保存失败(服务降级):" + cause.getMessage());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public AjaxResult omsOutOrderAddDetail(List<OutMaterialDetail> outMaterialDetails) {
|
public void omsOutOrderAddDetail(List<OutMaterialDetail> outMaterialDetails) {
|
||||||
return AjaxResult.error("WMS下发单明细保存失败(服务降级):" + cause.getMessage());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public AjaxResult omsOutOrderAddDeliveryDetailsLink(List<DeliveryDetailsLink> deliveryDetailsLinks) {
|
public void omsOutOrderAddDeliveryDetailsLink(List<DeliveryDetailsLink> deliveryDetailsLinks) {
|
||||||
return AjaxResult.error("WMS下发单配送明细保存失败(服务降级):" + cause.getMessage());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -85,12 +82,6 @@ public class RemoteWmsFallbackFactory implements FallbackFactory<WmsServiceFeign
|
|||||||
return AjaxResult.error("WMS取消下发清理失败:" + cause.getMessage());
|
return AjaxResult.error("WMS取消下发清理失败:" + cause.getMessage());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public AjaxResult omsReverseExecutionOrder(StockOutOrder stockOutOrder) {
|
|
||||||
//返回错误而非静默成功,让OMS反审事务能感知失败并整体回滚
|
|
||||||
return AjaxResult.error("WMS出库执行单反审失败(服务降级):" + cause.getMessage());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void omsAutoAssign(StockOutOrderDTO stockOutOrderDTO) {
|
public void omsAutoAssign(StockOutOrderDTO stockOutOrderDTO) {
|
||||||
|
|
||||||
@@ -102,35 +93,11 @@ public class RemoteWmsFallbackFactory implements FallbackFactory<WmsServiceFeign
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public AjaxResult checkOmsAssignInventory(List<OutMaterialDetail> outMaterialDetails, String businessOrderNumber) {
|
public AjaxResult checkOmsAssignInventory(List<OutMaterialDetail> outMaterialDetails) {
|
||||||
//校验接口本身不可用时返回错误,OMS会阻止下发(不能在WMS状态未知时盲目推送)
|
//校验接口本身不可用时返回错误,OMS会阻止下发(不能在WMS状态未知时盲目推送)
|
||||||
return AjaxResult.error("WMS库存校验服务不可用:" + cause.getMessage());
|
return AjaxResult.error("WMS库存校验服务不可用:" + cause.getMessage());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public AjaxResult omsFreezeInventory(OmsFreezeInventoryParam param) {
|
|
||||||
//返回错误而非静默成功:下单冻结失败必须阻断OMS下单落库(冻结成功与否状态未知时不允许继续)
|
|
||||||
return AjaxResult.error("WMS下单冻结库存失败(服务降级):" + cause.getMessage());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public AjaxResult omsUnfreezeInventory(OmsFreezeInventoryParam param) {
|
|
||||||
//返回错误而非静默成功:解冻失败让OMS取消/删除感知(解冻可重试,WMS解冻幂等)
|
|
||||||
return AjaxResult.error("WMS释放冻结库存失败(服务降级):" + cause.getMessage());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public AjaxResult omsRelockInventory(OmsFreezeInventoryParam param) {
|
|
||||||
//返回错误而非静默成功:编辑重锁是原子操作,失败必须让OMS编辑整体回滚
|
|
||||||
return AjaxResult.error("WMS编辑重锁库存失败(服务降级):" + cause.getMessage());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public AjaxResult hasActiveFreezeByWarehouse(Long warehouseId) {
|
|
||||||
//返回错误(fail-closed):模式切换守卫校验不可用时拒绝切换,避免在途冻结单语义错乱
|
|
||||||
return AjaxResult.error("WMS冻结记录校验服务不可用:" + cause.getMessage());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public AjaxResult omsInOrderAddDetail(List<InMaterialDetail> inMaterialDetails) {
|
public AjaxResult omsInOrderAddDetail(List<InMaterialDetail> inMaterialDetails) {
|
||||||
//返回错误而非静默成功:明细保存(含自动审核)失败必须让OMS感知并回滚下发标记
|
//返回错误而非静默成功:明细保存(含自动审核)失败必须让OMS感知并回滚下发标记
|
||||||
@@ -143,12 +110,6 @@ public class RemoteWmsFallbackFactory implements FallbackFactory<WmsServiceFeign
|
|||||||
return AjaxResult.error("WMS取消下发清理失败:" + cause.getMessage());
|
return AjaxResult.error("WMS取消下发清理失败:" + cause.getMessage());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public AjaxResult omsReverseInOrder(StockInOrder stockInOrder) {
|
|
||||||
//返回错误而非静默成功,让OMS侧反审能感知回退失败并整体回滚(反审可重试,WMS回退幂等)
|
|
||||||
return AjaxResult.error("WMS入库单反审回退失败(服务降级):" + cause.getMessage());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public TableDataInfo getMaterialBaseInfoList(MaterialInfoDTO materialInfoDTO) {
|
public TableDataInfo getMaterialBaseInfoList(MaterialInfoDTO materialInfoDTO) {
|
||||||
TableDataInfo tableDataInfo = new TableDataInfo();
|
TableDataInfo tableDataInfo = new TableDataInfo();
|
||||||
|
|||||||
+12
-4
@@ -130,9 +130,11 @@ public class TokenLoginApplicationService {
|
|||||||
//验证码登录校验验证码
|
//验证码登录校验验证码
|
||||||
String key = CacheConstants.SMS_LOGIN + userPhone;
|
String key = CacheConstants.SMS_LOGIN + userPhone;
|
||||||
Object object = redisService.getCacheObject(key) == null ? "":redisService.getCacheObject(key);
|
Object object = redisService.getCacheObject(key) == null ? "":redisService.getCacheObject(key);
|
||||||
if(!ObjectUtil.equal(String.valueOf(object),verificationCode) && !ObjectUtil.equal(verificationCode, SmsConstants.universalCode)){
|
if (loginDTO.getWechatFlag() != 1) {
|
||||||
recordLogininfor(userPhone, Constants.LOGIN_FAIL, "验证码错误", 1);
|
// if (!ObjectUtil.equal(String.valueOf(object), verificationCode) && !ObjectUtil.equal(verificationCode, SmsConstants.universalCode)) {
|
||||||
throw new ServiceException("验证码错误");
|
// recordLogininfor(userPhone, Constants.LOGIN_FAIL, "验证码错误", 1);
|
||||||
|
throw new ServiceException("验证码错误");
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
//获取包名对应的业务(存在需要查询业务,不存在保存为无业务模式)
|
//获取包名对应的业务(存在需要查询业务,不存在保存为无业务模式)
|
||||||
@@ -168,7 +170,13 @@ public class TokenLoginApplicationService {
|
|||||||
throw new ServiceException("对不起,您的账号:" + userPhone + " 已停用");
|
throw new ServiceException("对不起,您的账号:" + userPhone + " 已停用");
|
||||||
}
|
}
|
||||||
//校验验证码是否正确
|
//校验验证码是否正确
|
||||||
sysPasswordService.validate(userPo, verificationCode, 1, null);
|
if (loginDTO.getWechatFlag() != 1) {
|
||||||
|
// if (!ObjectUtil.equal(String.valueOf(object), verificationCode) && !ObjectUtil.equal(verificationCode, SmsConstants.universalCode)) {
|
||||||
|
// recordLogininfor(userPhone, Constants.LOGIN_FAIL, "验证码错误", 1);
|
||||||
|
throw new ServiceException("验证码错误");
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
// sysPasswordService.validate(userPo, verificationCode, 1, null);
|
||||||
}
|
}
|
||||||
return userInfo;
|
return userInfo;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -40,4 +40,7 @@ public class LoginDTO {
|
|||||||
@ApiModelProperty(name = "组织名称(司机选择组织时传入)")
|
@ApiModelProperty(name = "组织名称(司机选择组织时传入)")
|
||||||
private String organizationName;
|
private String organizationName;
|
||||||
|
|
||||||
|
@ApiModelProperty(name = "微信标识")
|
||||||
|
private Integer wechatFlag;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,10 +12,10 @@ spring:
|
|||||||
cloud:
|
cloud:
|
||||||
nacos:
|
nacos:
|
||||||
discovery:
|
discovery:
|
||||||
server-addr: 127.0.0.1:8848
|
# server-addr: 127.0.0.1:8848
|
||||||
# 线上测试环境配置 容器名+端口号
|
# 线上测试环境配置 容器名+端口号
|
||||||
# server-addr: 10.33.0.129:6010
|
# server-addr: 10.33.0.129:6010
|
||||||
# server-addr: 10.102.192.31:6848
|
server-addr: 10.102.192.31:6848
|
||||||
username: nacos
|
username: nacos
|
||||||
password: manhuoda@2023
|
password: manhuoda@2023
|
||||||
#线上正式环境
|
#线上正式环境
|
||||||
@@ -23,8 +23,8 @@ spring:
|
|||||||
# username: nacos
|
# username: nacos
|
||||||
# password: manhuoda@2023
|
# password: manhuoda@2023
|
||||||
config:
|
config:
|
||||||
server-addr: 127.0.0.1:8848
|
# server-addr: 127.0.0.1:8848
|
||||||
# server-addr: 10.102.192.31:6848
|
server-addr: 10.102.192.31:6848
|
||||||
# 测试环境配置 容器名+端口号
|
# 测试环境配置 容器名+端口号
|
||||||
# server-addr: 10.33.0.129:6010
|
# server-addr: 10.33.0.129:6010
|
||||||
# 线上测试环境配置 容器名+端口号
|
# 线上测试环境配置 容器名+端口号
|
||||||
|
|||||||
+12
@@ -7,6 +7,9 @@ import com.mhd.bi.domain.biPlatformRealData.repository.po.RealTaskLoadPO;
|
|||||||
import com.mhd.bi.domain.biPlatformRealData.repository.po.RealBusinessTypeStatPO;
|
import com.mhd.bi.domain.biPlatformRealData.repository.po.RealBusinessTypeStatPO;
|
||||||
import com.mhd.bi.domain.biPlatformRealData.repository.po.RealPlatformFloorStatPO;
|
import com.mhd.bi.domain.biPlatformRealData.repository.po.RealPlatformFloorStatPO;
|
||||||
import com.mhd.bi.domain.biPlatformRealData.repository.po.RealPlatformInfoPO;
|
import com.mhd.bi.domain.biPlatformRealData.repository.po.RealPlatformInfoPO;
|
||||||
|
import com.mhd.bi.domain.biPlatformRealData.repository.po.RealOnTimeStatPO;
|
||||||
|
import com.mhd.bi.domain.biPlatformRealData.repository.po.RealTaskTypeStatPO;
|
||||||
|
import com.mhd.bi.domain.biPlatformRealData.repository.po.RealMonthlyTaskDurationPO;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
@@ -32,12 +35,21 @@ public interface BiPlatformRealDataMapper {
|
|||||||
/** 本月任务量 */
|
/** 本月任务量 */
|
||||||
Long countMonthTasks();
|
Long countMonthTasks();
|
||||||
|
|
||||||
|
/** 本月任务平均时长 / 完成率统计 */
|
||||||
|
RealMonthlyTaskDurationPO queryMonthTaskStats();
|
||||||
|
|
||||||
/** 任务负荷(今日 24 小时) */
|
/** 任务负荷(今日 24 小时) */
|
||||||
List<RealTaskLoadPO> queryTaskLoadToday();
|
List<RealTaskLoadPO> queryTaskLoadToday();
|
||||||
|
|
||||||
/** 今日预约-业务类型统计(按 businessName 分组统计今日预约数量) */
|
/** 今日预约-业务类型统计(按 businessName 分组统计今日预约数量) */
|
||||||
List<RealBusinessTypeStatPO> queryTodayBusinessTypeStats();
|
List<RealBusinessTypeStatPO> queryTodayBusinessTypeStats();
|
||||||
|
|
||||||
|
/** 今日作业准时率统计(total 今日预约总数;onTimeCount 今日准时车辆数) */
|
||||||
|
RealOnTimeStatPO queryTodayOnTimeStats();
|
||||||
|
|
||||||
|
/** 任务类型统计(本月 YMS QMS_MAIN_BUSINESS 预约按业务类型 BUSINESS_NAME 分组) */
|
||||||
|
List<RealTaskTypeStatPO> queryMonthTransportOrderByType();
|
||||||
|
|
||||||
/** 月台监控-按楼层统计月台车辆(楼层、月台数量、今日预约车辆、当前作业车辆) */
|
/** 月台监控-按楼层统计月台车辆(楼层、月台数量、今日预约车辆、当前作业车辆) */
|
||||||
List<RealPlatformFloorStatPO> queryPlatformFloorStats();
|
List<RealPlatformFloorStatPO> queryPlatformFloorStats();
|
||||||
|
|
||||||
|
|||||||
+29
@@ -0,0 +1,29 @@
|
|||||||
|
package com.mhd.bi.domain.biPlatformRealData.repository.po;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 本月任务平均时长 / 完成率统计(真实数据,来自 TEST_NGWL_YMS.QMS_MAIN_BUSINESS)
|
||||||
|
* avgDurationHours:累计 (EXIT_TIME - ENTRY_TIME) 小时数(仅 ENTRY_TIME/EXIT_TIME 都不为空时参与)
|
||||||
|
* durationCount:参与平均时长统计的有效条数
|
||||||
|
* completedCount:已出场(EXIT_TIME IS NOT NULL)且预约日期在本月的数量
|
||||||
|
* totalCount:本月(TARGET_DATE)预约总数量
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class RealMonthlyTaskDurationPO implements Serializable {
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
/** 平均作业时长(小时) */
|
||||||
|
private Double avgDurationHours;
|
||||||
|
|
||||||
|
/** 参与平均时长统计的有效条数 */
|
||||||
|
private Long durationCount;
|
||||||
|
|
||||||
|
/** 本月已出场数量 */
|
||||||
|
private Long completedCount;
|
||||||
|
|
||||||
|
/** 本月预约总数量(按 TARGET_DATE 统计) */
|
||||||
|
private Long totalCount;
|
||||||
|
}
|
||||||
+20
@@ -0,0 +1,20 @@
|
|||||||
|
package com.mhd.bi.domain.biPlatformRealData.repository.po;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 今日作业准时率统计(真实数据,来自 TEST_NGWL_YMS.QMS_MAIN_BUSINESS)
|
||||||
|
* 准时率 = 今日实际进场时间在预约日期当天的车辆数 / 今日预约总车辆数 × 100%
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class RealOnTimeStatPO implements Serializable {
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
/** 今日预约总车辆数 */
|
||||||
|
private Long total;
|
||||||
|
|
||||||
|
/** 今日准时车辆数(已进场且实际进场日期 = 预约日期) */
|
||||||
|
private Long onTimeCount;
|
||||||
|
}
|
||||||
+20
@@ -0,0 +1,20 @@
|
|||||||
|
package com.mhd.bi.domain.biPlatformRealData.repository.po;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 任务类型统计(真实数据,来自 NGWL_TEST_YMS.QMS_MAIN_BUSINESS 预约登记表)
|
||||||
|
* 按本月预约车辆数(TARGET_DATE 在当前月)以 BUSINESS_NAME 业务类型分组
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class RealTaskTypeStatPO implements Serializable {
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
/** 业务类型名称(qms_main_business.BUSINESS_NAME) */
|
||||||
|
private String businessName;
|
||||||
|
|
||||||
|
/** 该业务类型本月预约车辆数 */
|
||||||
|
private Long count;
|
||||||
|
}
|
||||||
+3
@@ -16,6 +16,9 @@ public class RealVehicleStatusPO implements Serializable {
|
|||||||
/** 当前未签到 */
|
/** 当前未签到 */
|
||||||
private Long notCheckedIn;
|
private Long notCheckedIn;
|
||||||
|
|
||||||
|
/** 当前等待作业(FLOW_STATUS IN '1','2','3' 已预约/已签到/已叫号) */
|
||||||
|
private Long waiting;
|
||||||
|
|
||||||
/** 当前作业中 */
|
/** 当前作业中 */
|
||||||
private Long operatingVehicles;
|
private Long operatingVehicles;
|
||||||
|
|
||||||
|
|||||||
+142
-6
@@ -9,12 +9,17 @@ import com.mhd.bi.domain.biPlatformRealData.repository.po.RealTaskLoadPO;
|
|||||||
import com.mhd.bi.domain.biPlatformRealData.repository.po.RealBusinessTypeStatPO;
|
import com.mhd.bi.domain.biPlatformRealData.repository.po.RealBusinessTypeStatPO;
|
||||||
import com.mhd.bi.domain.biPlatformRealData.repository.po.RealPlatformFloorStatPO;
|
import com.mhd.bi.domain.biPlatformRealData.repository.po.RealPlatformFloorStatPO;
|
||||||
import com.mhd.bi.domain.biPlatformRealData.repository.po.RealPlatformInfoPO;
|
import com.mhd.bi.domain.biPlatformRealData.repository.po.RealPlatformInfoPO;
|
||||||
|
import com.mhd.bi.domain.biPlatformRealData.repository.po.RealOnTimeStatPO;
|
||||||
|
import com.mhd.bi.domain.biPlatformRealData.repository.po.RealTaskTypeStatPO;
|
||||||
|
import com.mhd.bi.domain.biPlatformRealData.repository.po.RealMonthlyTaskDurationPO;
|
||||||
import com.mhd.bi.domain.biPlatformSurveillance.repository.mapper.BiPlatformSurveillanceReportMapper;
|
import com.mhd.bi.domain.biPlatformSurveillance.repository.mapper.BiPlatformSurveillanceReportMapper;
|
||||||
import com.mhd.bi.domain.biSnapshotSync.repository.mapper.BiSnapshotWriteMapper;
|
import com.mhd.bi.domain.biSnapshotSync.repository.mapper.BiSnapshotWriteMapper;
|
||||||
import com.mhd.bi.domain.biSnapshotSync.support.BiSnapshotWeeklyRandomDataBuilder;
|
import com.mhd.bi.domain.biSnapshotSync.support.BiSnapshotWeeklyRandomDataBuilder;
|
||||||
import com.mhd.bi.interfaces.facadeApi.biReport.vo.platform.PlatformSurveillanceVO;
|
import com.mhd.bi.interfaces.facadeApi.biReport.vo.platform.PlatformSurveillanceVO;
|
||||||
import com.mhd.bi.interfaces.facadeApi.biReport.vo.platform.PlatformVehicleItemVO;
|
import com.mhd.bi.interfaces.facadeApi.biReport.vo.platform.PlatformVehicleItemVO;
|
||||||
import com.mhd.bi.interfaces.facadeApi.biReport.vo.platform.TaskLoadItemVO;
|
import com.mhd.bi.interfaces.facadeApi.biReport.vo.platform.TaskLoadItemVO;
|
||||||
|
import com.mhd.bi.interfaces.facadeApi.biReport.vo.platform.TaskTypeStatisticsVO;
|
||||||
|
import com.mhd.bi.interfaces.facadeApi.biReport.vo.platform.TaskTypeCountItemVO;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
@@ -91,16 +96,23 @@ public class BiPlatformRealDataService {
|
|||||||
if (vo.getPlatformOverview() != null) {
|
if (vo.getPlatformOverview() != null) {
|
||||||
fp.put("totalPlatforms", vo.getPlatformOverview().getTotalPlatforms());
|
fp.put("totalPlatforms", vo.getPlatformOverview().getTotalPlatforms());
|
||||||
fp.put("operatingPlatforms", vo.getPlatformOverview().getOperatingPlatforms());
|
fp.put("operatingPlatforms", vo.getPlatformOverview().getOperatingPlatforms());
|
||||||
|
fp.put("currentOccupancyRate", vo.getPlatformOverview().getCurrentOccupancyRate());
|
||||||
fp.put("todayTasks", vo.getPlatformOverview().getTodayTasks());
|
fp.put("todayTasks", vo.getPlatformOverview().getTodayTasks());
|
||||||
}
|
}
|
||||||
|
if (vo.getEfficiencyStatistics() != null) {
|
||||||
|
fp.put("platformOnTimeRate", vo.getEfficiencyStatistics().getPlatformOnTimeRate());
|
||||||
|
}
|
||||||
if (vo.getVehicleStatus() != null) {
|
if (vo.getVehicleStatus() != null) {
|
||||||
fp.put("todayReservedVehicles", vo.getVehicleStatus().getTodayReservedVehicles());
|
fp.put("todayReservedVehicles", vo.getVehicleStatus().getTodayReservedVehicles());
|
||||||
fp.put("notCheckedIn", vo.getVehicleStatus().getNotCheckedIn());
|
fp.put("notCheckedIn", vo.getVehicleStatus().getNotCheckedIn());
|
||||||
|
fp.put("waiting", vo.getVehicleStatus().getWaiting());
|
||||||
fp.put("operatingVehicles", vo.getVehicleStatus().getOperatingVehicles());
|
fp.put("operatingVehicles", vo.getVehicleStatus().getOperatingVehicles());
|
||||||
fp.put("completedVehicles", vo.getVehicleStatus().getCompletedVehicles());
|
fp.put("completedVehicles", vo.getVehicleStatus().getCompletedVehicles());
|
||||||
}
|
}
|
||||||
if (vo.getMonthlyTaskStatistics() != null) {
|
if (vo.getMonthlyTaskStatistics() != null) {
|
||||||
fp.put("taskTotal", vo.getMonthlyTaskStatistics().getTaskTotal());
|
fp.put("taskTotal", vo.getMonthlyTaskStatistics().getTaskTotal());
|
||||||
|
fp.put("avgTaskDuration", vo.getMonthlyTaskStatistics().getAvgTaskDuration());
|
||||||
|
fp.put("taskCompletionRate", vo.getMonthlyTaskStatistics().getTaskCompletionRate());
|
||||||
}
|
}
|
||||||
if (vo.getVehicles() != null) {
|
if (vo.getVehicles() != null) {
|
||||||
List<Map<String, Object>> vehicles = new ArrayList<>();
|
List<Map<String, Object>> vehicles = new ArrayList<>();
|
||||||
@@ -126,6 +138,27 @@ public class BiPlatformRealDataService {
|
|||||||
}
|
}
|
||||||
fp.put("taskLoadStatistics", loads);
|
fp.put("taskLoadStatistics", loads);
|
||||||
}
|
}
|
||||||
|
if (vo.getTaskTypeStatistics() != null) {
|
||||||
|
Map<String, Object> m = new LinkedHashMap<>();
|
||||||
|
m.put("totalTasks", vo.getTaskTypeStatistics().getTotalTasks());
|
||||||
|
if (vo.getTaskTypeStatistics().getTaskTypes() != null) {
|
||||||
|
List<Map<String, Object>> types = new ArrayList<>();
|
||||||
|
for (TaskTypeCountItemVO it : vo.getTaskTypeStatistics().getTaskTypes()) {
|
||||||
|
Map<String, Object> tm = new LinkedHashMap<>();
|
||||||
|
tm.put("type", it.getType());
|
||||||
|
tm.put("count", it.getCount());
|
||||||
|
types.add(tm);
|
||||||
|
}
|
||||||
|
m.put("taskTypes", types);
|
||||||
|
}
|
||||||
|
fp.put("taskTypeStatistics", m);
|
||||||
|
}
|
||||||
|
// 月台告警统计:按业务要求恒为 0,纳入指纹以确保旧快照(可能含非0写死值)能被覆盖更新为 0
|
||||||
|
if (vo.getPlatformAlarmStatistics() != null) {
|
||||||
|
fp.put("todayAlarmTotal", vo.getPlatformAlarmStatistics().getTodayAlarmTotal());
|
||||||
|
fp.put("handled", vo.getPlatformAlarmStatistics().getHandled());
|
||||||
|
fp.put("unhandled", vo.getPlatformAlarmStatistics().getUnhandled());
|
||||||
|
}
|
||||||
return objectMapper.writeValueAsString(fp);
|
return objectMapper.writeValueAsString(fp);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -166,12 +199,33 @@ public class BiPlatformRealDataService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 今日作业准时率 = 今日准时车辆数 / 今日有入场时间的车辆数 × 100%(四舍五入取整)
|
||||||
|
* 准时:实际进入时间 < 预约日期(TARGET_DATE) + 预约结束时间(BOOKING_END_TIME)。
|
||||||
|
* 分子分母都只统计有入场时间(ENTRY_TIME 不为空)的车辆;分母为 0 时返回 0。
|
||||||
|
*/
|
||||||
|
public int calcTodayOnTimeRate() {
|
||||||
|
try {
|
||||||
|
RealOnTimeStatPO po = biPlatformRealDataMapper.queryTodayOnTimeStats();
|
||||||
|
if (po == null) return 0;
|
||||||
|
long total = po.getTotal() == null ? 0L : po.getTotal();
|
||||||
|
long onTime = po.getOnTimeCount() == null ? 0L : po.getOnTimeCount();
|
||||||
|
if (total <= 0) return 0;
|
||||||
|
// 四舍五入到整数百分比(取整)
|
||||||
|
return (int) Math.round(((double) onTime / (double) total) * 100.0);
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("【YMS】计算今日作业准时率失败: {}", e.getMessage(), e);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public RealVehicleStatusPO queryVehicleStatusToday() {
|
public RealVehicleStatusPO queryVehicleStatusToday() {
|
||||||
try {
|
try {
|
||||||
RealVehicleStatusPO po = biPlatformRealDataMapper.queryVehicleStatusToday();
|
RealVehicleStatusPO po = biPlatformRealDataMapper.queryVehicleStatusToday();
|
||||||
if (po == null) po = new RealVehicleStatusPO();
|
if (po == null) po = new RealVehicleStatusPO();
|
||||||
if (po.getTodayReservedVehicles() == null) po.setTodayReservedVehicles(0L);
|
if (po.getTodayReservedVehicles() == null) po.setTodayReservedVehicles(0L);
|
||||||
if (po.getNotCheckedIn() == null) po.setNotCheckedIn(0L);
|
if (po.getNotCheckedIn() == null) po.setNotCheckedIn(0L);
|
||||||
|
if (po.getWaiting() == null) po.setWaiting(0L);
|
||||||
if (po.getOperatingVehicles() == null) po.setOperatingVehicles(0L);
|
if (po.getOperatingVehicles() == null) po.setOperatingVehicles(0L);
|
||||||
if (po.getCompletedVehicles() == null) po.setCompletedVehicles(0L);
|
if (po.getCompletedVehicles() == null) po.setCompletedVehicles(0L);
|
||||||
return po;
|
return po;
|
||||||
@@ -180,6 +234,7 @@ public class BiPlatformRealDataService {
|
|||||||
RealVehicleStatusPO po = new RealVehicleStatusPO();
|
RealVehicleStatusPO po = new RealVehicleStatusPO();
|
||||||
po.setTodayReservedVehicles(0L);
|
po.setTodayReservedVehicles(0L);
|
||||||
po.setNotCheckedIn(0L);
|
po.setNotCheckedIn(0L);
|
||||||
|
po.setWaiting(0L);
|
||||||
po.setOperatingVehicles(0L);
|
po.setOperatingVehicles(0L);
|
||||||
po.setCompletedVehicles(0L);
|
po.setCompletedVehicles(0L);
|
||||||
return po;
|
return po;
|
||||||
@@ -196,6 +251,21 @@ public class BiPlatformRealDataService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 本月任务平均时长 / 完成率统计:
|
||||||
|
* - avgDurationHours:累计(EXIT_TIME - ENTRY_TIME)小时数 / 参与数;任一为空的行不参与
|
||||||
|
* - taskCompletionRate:已完成(EXIT_TIME 不为空 且 预约日期在本月)/ 本月预约总数量 ×100
|
||||||
|
* 任一查询失败均返回 null,由调用方决定是否覆盖模板值。
|
||||||
|
*/
|
||||||
|
public RealMonthlyTaskDurationPO queryMonthTaskStats() {
|
||||||
|
try {
|
||||||
|
return biPlatformRealDataMapper.queryMonthTaskStats();
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("【YMS】统计本月任务平均时长/完成率失败: {}", e.getMessage(), e);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public List<RealTaskLoadPO> queryTaskLoadToday() {
|
public List<RealTaskLoadPO> queryTaskLoadToday() {
|
||||||
try {
|
try {
|
||||||
return biPlatformRealDataMapper.queryTaskLoadToday();
|
return biPlatformRealDataMapper.queryTaskLoadToday();
|
||||||
@@ -205,6 +275,35 @@ public class BiPlatformRealDataService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 任务类型统计:本月(YMS QMS_MAIN_BUSINESS)预约车辆按业务类型 BUSINESS_NAME 分组;
|
||||||
|
* 返回 {totalTasks: 当月总预约车辆数, taskTypes: [{type: 业务类型名称, count: 该类型预约数}]}
|
||||||
|
* 按真实 BUSINESS_NAME 分组输出,不固定兜底类别;当月无数据或查询失败时返回空列表。
|
||||||
|
*/
|
||||||
|
public TaskTypeStatisticsVO queryMonthTransportOrderByType() {
|
||||||
|
List<TaskTypeCountItemVO> items = new ArrayList<>();
|
||||||
|
int total = 0;
|
||||||
|
try {
|
||||||
|
List<RealTaskTypeStatPO> rows = biPlatformRealDataMapper.queryMonthTransportOrderByType();
|
||||||
|
if (rows != null) {
|
||||||
|
for (RealTaskTypeStatPO r : rows) {
|
||||||
|
if (r == null || r.getBusinessName() == null || r.getCount() == null) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
int c = r.getCount().intValue();
|
||||||
|
items.add(TaskTypeCountItemVO.builder().type(r.getBusinessName()).count(c).build());
|
||||||
|
total += c;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("【YMS】统计当月预约业务类型失败: {}", e.getMessage(), e);
|
||||||
|
// 查询失败返回空列表(前端会显示空)
|
||||||
|
items = new ArrayList<>();
|
||||||
|
total = 0;
|
||||||
|
}
|
||||||
|
return TaskTypeStatisticsVO.builder().totalTasks(total).taskTypes(items).build();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 今日预约-业务类型统计:按业务类型分组统计今日预约数量。
|
* 今日预约-业务类型统计:按业务类型分组统计今日预约数量。
|
||||||
* 例:今日预约航空打板 3 条 → 返回 {businessName:"航空打板", count:3}
|
* 例:今日预约航空打板 3 条 → 返回 {businessName:"航空打板", count:3}
|
||||||
@@ -271,29 +370,63 @@ public class BiPlatformRealDataService {
|
|||||||
template.setVehicles(vehicleVos);
|
template.setVehicles(vehicleVos);
|
||||||
|
|
||||||
// 月台实时概览:真实数据源,无条件覆盖
|
// 月台实时概览:真实数据源,无条件覆盖
|
||||||
|
// 总月台 / 占用月台 来源:YMS 月台管理列表 QMS_WINDOW_INFO(JOB_STATUS=1 表示占用)
|
||||||
|
// 月台占用率 = 占用 / 全部月台
|
||||||
|
// 今日作业任务 来源:QMS_MAIN_BUSINESS 按预约时间 TARGET_DATE = 今天 的全部数量
|
||||||
|
// 作业准时率 = 今日(实际进场时间在预约日期当天的车辆数) / 今日预约车辆总数 × 100%
|
||||||
if (template.getPlatformOverview() != null) {
|
if (template.getPlatformOverview() != null) {
|
||||||
RealPlatformOverviewPO ov = queryPlatformOverview();
|
List<RealPlatformInfoPO> platformList = queryPlatformInfoList();
|
||||||
int total = ov.getTotalPlatforms().intValue();
|
int total = platformList == null ? 0 : platformList.size();
|
||||||
int occ = ov.getOperatingPlatforms().intValue();
|
int occ = 0;
|
||||||
|
if (platformList != null) {
|
||||||
|
for (RealPlatformInfoPO p : platformList) {
|
||||||
|
if (p != null && p.getJobStatus() != null && p.getJobStatus() == 1) {
|
||||||
|
occ++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
double rate = total > 0 ? Math.round(((double) occ / total) * 100.0 * 100.0) / 100.0 : 0d;
|
double rate = total > 0 ? Math.round(((double) occ / total) * 100.0 * 100.0) / 100.0 : 0d;
|
||||||
|
int todayTasks = (int) countTodayTasks();
|
||||||
template.getPlatformOverview().setTotalPlatforms(total);
|
template.getPlatformOverview().setTotalPlatforms(total);
|
||||||
template.getPlatformOverview().setOperatingPlatforms(occ);
|
template.getPlatformOverview().setOperatingPlatforms(occ);
|
||||||
template.getPlatformOverview().setCurrentOccupancyRate(rate);
|
template.getPlatformOverview().setCurrentOccupancyRate(rate);
|
||||||
template.getPlatformOverview().setTodayTasks((int) countTodayTasks());
|
template.getPlatformOverview().setTodayTasks(todayTasks);
|
||||||
|
|
||||||
|
// 作业准时率(实际进入时间 < 预约日期+预约结束时间 的车辆 / 今日预约总数 × 100% 取整)
|
||||||
|
if (template.getEfficiencyStatistics() != null) {
|
||||||
|
template.getEfficiencyStatistics().setPlatformOnTimeRate(calcTodayOnTimeRate());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 作业车辆状态统计:真实数据源,无条件覆盖
|
// 作业车辆状态统计:真实数据源,无条件覆盖(含等待作业 waiting = 今日预约且 已预约/已签到/已叫号)
|
||||||
if (template.getVehicleStatus() != null) {
|
if (template.getVehicleStatus() != null) {
|
||||||
RealVehicleStatusPO vs = queryVehicleStatusToday();
|
RealVehicleStatusPO vs = queryVehicleStatusToday();
|
||||||
template.getVehicleStatus().setTodayReservedVehicles(vs.getTodayReservedVehicles().intValue());
|
template.getVehicleStatus().setTodayReservedVehicles(vs.getTodayReservedVehicles().intValue());
|
||||||
template.getVehicleStatus().setNotCheckedIn(vs.getNotCheckedIn().intValue());
|
template.getVehicleStatus().setNotCheckedIn(vs.getNotCheckedIn().intValue());
|
||||||
|
template.getVehicleStatus().setWaiting(vs.getWaiting().intValue());
|
||||||
template.getVehicleStatus().setOperatingVehicles(vs.getOperatingVehicles().intValue());
|
template.getVehicleStatus().setOperatingVehicles(vs.getOperatingVehicles().intValue());
|
||||||
template.getVehicleStatus().setCompletedVehicles(vs.getCompletedVehicles().intValue());
|
template.getVehicleStatus().setCompletedVehicles(vs.getCompletedVehicles().intValue());
|
||||||
}
|
}
|
||||||
|
|
||||||
// 本月任务统计:taskTotal 有真实数据源无条件覆盖;YoY 等无真实数据源保留模板写死值
|
// 本月任务统计:taskTotal / avgTaskDuration / taskCompletionRate 均有真实数据源,无条件覆盖;YoY 保留模板写死值
|
||||||
if (template.getMonthlyTaskStatistics() != null) {
|
if (template.getMonthlyTaskStatistics() != null) {
|
||||||
template.getMonthlyTaskStatistics().setTaskTotal((int) countMonthTasks());
|
template.getMonthlyTaskStatistics().setTaskTotal((int) countMonthTasks());
|
||||||
|
RealMonthlyTaskDurationPO monthStats = queryMonthTaskStats();
|
||||||
|
if (monthStats != null) {
|
||||||
|
if (monthStats.getAvgDurationHours() != null) {
|
||||||
|
// 保留两位小数
|
||||||
|
double v = monthStats.getAvgDurationHours();
|
||||||
|
template.getMonthlyTaskStatistics().setAvgTaskDuration(Math.round(v * 100.0) / 100.0);
|
||||||
|
}
|
||||||
|
Long total = monthStats.getTotalCount();
|
||||||
|
Long completed = monthStats.getCompletedCount();
|
||||||
|
if (total != null && total > 0 && completed != null) {
|
||||||
|
int rate = (int) Math.round(((double) completed.longValue() / total.longValue()) * 100.0);
|
||||||
|
template.getMonthlyTaskStatistics().setTaskCompletionRate(rate);
|
||||||
|
} else {
|
||||||
|
template.getMonthlyTaskStatistics().setTaskCompletionRate(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 任务负荷:有真实数据源;真实为空则清空不用模板模拟,有数据则按真实小时覆盖
|
// 任务负荷:有真实数据源;真实为空则清空不用模板模拟,有数据则按真实小时覆盖
|
||||||
@@ -313,6 +446,9 @@ public class BiPlatformRealDataService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 任务类型统计:本月 YMS QMS_MAIN_BUSINESS 按业务类型 BUSINESS_NAME 分组(真实业务数据)
|
||||||
|
template.setTaskTypeStatistics(queryMonthTransportOrderByType());
|
||||||
|
|
||||||
return template;
|
return template;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -87,7 +87,7 @@ public final class BiReportSnapshotMapperSupport {
|
|||||||
.platformOverview(PlatformOverviewVO.builder()
|
.platformOverview(PlatformOverviewVO.builder()
|
||||||
.totalPlatforms(0).currentOccupancyRate(0d).operatingPlatforms(0).todayTasks(0).build())
|
.totalPlatforms(0).currentOccupancyRate(0d).operatingPlatforms(0).todayTasks(0).build())
|
||||||
.vehicleStatus(VehicleStatusVO.builder()
|
.vehicleStatus(VehicleStatusVO.builder()
|
||||||
.todayReservedVehicles(0).notCheckedIn(0).operatingVehicles(0).completedVehicles(0).build())
|
.todayReservedVehicles(0).notCheckedIn(0).waiting(0).operatingVehicles(0).completedVehicles(0).build())
|
||||||
.avgOperationDurationTrend(Collections.emptyList())
|
.avgOperationDurationTrend(Collections.emptyList())
|
||||||
.monthlyTaskStatistics(MonthlyTaskStatisticsVO.builder()
|
.monthlyTaskStatistics(MonthlyTaskStatisticsVO.builder()
|
||||||
.taskTotal(0).taskTotalYoY(0).avgTaskDuration(0d).avgDurationYoY(0)
|
.taskTotal(0).taskTotalYoY(0).avgTaskDuration(0d).avgDurationYoY(0)
|
||||||
|
|||||||
+44
-11
@@ -16,7 +16,7 @@ import com.mhd.bi.interfaces.facadeApi.biReport.vo.warehouseZone.WarehouseOperat
|
|||||||
import com.mhd.bi.interfaces.facadeApi.biReport.vo.platform.PlatformVehicleItemVO;
|
import com.mhd.bi.interfaces.facadeApi.biReport.vo.platform.PlatformVehicleItemVO;
|
||||||
import com.mhd.bi.domain.biPlatformRealData.service.BiPlatformRealDataService;
|
import com.mhd.bi.domain.biPlatformRealData.service.BiPlatformRealDataService;
|
||||||
import com.mhd.bi.domain.biPlatformRealData.repository.po.RealPlatformVehiclePO;
|
import com.mhd.bi.domain.biPlatformRealData.repository.po.RealPlatformVehiclePO;
|
||||||
import com.mhd.bi.domain.biPlatformRealData.repository.po.RealPlatformOverviewPO;
|
import com.mhd.bi.domain.biPlatformRealData.repository.po.RealPlatformInfoPO;
|
||||||
import com.mhd.bi.domain.biPlatformRealData.repository.po.RealVehicleStatusPO;
|
import com.mhd.bi.domain.biPlatformRealData.repository.po.RealVehicleStatusPO;
|
||||||
import com.mhd.bi.domain.biPlatformRealData.repository.po.RealTaskLoadPO;
|
import com.mhd.bi.domain.biPlatformRealData.repository.po.RealTaskLoadPO;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
@@ -173,18 +173,31 @@ public class BiReportSnapshotSyncService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// ====== 真实数据:月台实时概览 ======
|
// ====== 真实数据:月台实时概览 ======
|
||||||
RealPlatformOverviewPO ov = biPlatformRealDataService.queryPlatformOverview();
|
// 总月台 / 占用月台 来源:YMS 月台管理列表 QMS_WINDOW_INFO(JOB_STATUS=1 表示占用)
|
||||||
|
// 月台占用率 = 占用 / 全部月台
|
||||||
|
// 今日作业任务 来源:QMS_MAIN_BUSINESS 按预约时间 TARGET_DATE = 今天 的全部数量
|
||||||
if (template.getPlatformOverview() != null) {
|
if (template.getPlatformOverview() != null) {
|
||||||
template.getPlatformOverview().setTotalPlatforms(ov.getTotalPlatforms().intValue());
|
List<RealPlatformInfoPO> platformList = biPlatformRealDataService.queryPlatformInfoList();
|
||||||
template.getPlatformOverview().setOperatingPlatforms(ov.getOperatingPlatforms().intValue());
|
int total = platformList == null ? 0 : platformList.size();
|
||||||
int total = ov.getTotalPlatforms().intValue();
|
int occ = 0;
|
||||||
int occ = ov.getOperatingPlatforms().intValue();
|
if (platformList != null) {
|
||||||
|
for (RealPlatformInfoPO p : platformList) {
|
||||||
|
if (p != null && p.getJobStatus() != null && p.getJobStatus() == 1) {
|
||||||
|
occ++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
double rate = total > 0 ? Math.round(((double) occ / total) * 100.0 * 100.0) / 100.0 : 0d;
|
double rate = total > 0 ? Math.round(((double) occ / total) * 100.0 * 100.0) / 100.0 : 0d;
|
||||||
|
int todayTasks = (int) biPlatformRealDataService.countTodayTasks();
|
||||||
|
template.getPlatformOverview().setTotalPlatforms(total);
|
||||||
|
template.getPlatformOverview().setOperatingPlatforms(occ);
|
||||||
template.getPlatformOverview().setCurrentOccupancyRate(rate);
|
template.getPlatformOverview().setCurrentOccupancyRate(rate);
|
||||||
}
|
template.getPlatformOverview().setTodayTasks(todayTasks);
|
||||||
long todayTasks = biPlatformRealDataService.countTodayTasks();
|
|
||||||
if (template.getPlatformOverview() != null) {
|
// 作业准时率 = 实际进入时间 < 预约日期+预约结束时间 的车辆 / 今日预约总数 × 100%(取整)
|
||||||
template.getPlatformOverview().setTodayTasks((int) todayTasks);
|
if (template.getEfficiencyStatistics() != null) {
|
||||||
|
template.getEfficiencyStatistics().setPlatformOnTimeRate(biPlatformRealDataService.calcTodayOnTimeRate());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ====== 真实数据:作业车辆状态统计 ======
|
// ====== 真实数据:作业车辆状态统计 ======
|
||||||
@@ -192,14 +205,31 @@ public class BiReportSnapshotSyncService {
|
|||||||
if (template.getVehicleStatus() != null) {
|
if (template.getVehicleStatus() != null) {
|
||||||
template.getVehicleStatus().setTodayReservedVehicles(vs.getTodayReservedVehicles().intValue());
|
template.getVehicleStatus().setTodayReservedVehicles(vs.getTodayReservedVehicles().intValue());
|
||||||
template.getVehicleStatus().setNotCheckedIn(vs.getNotCheckedIn().intValue());
|
template.getVehicleStatus().setNotCheckedIn(vs.getNotCheckedIn().intValue());
|
||||||
|
template.getVehicleStatus().setWaiting(vs.getWaiting().intValue());
|
||||||
template.getVehicleStatus().setOperatingVehicles(vs.getOperatingVehicles().intValue());
|
template.getVehicleStatus().setOperatingVehicles(vs.getOperatingVehicles().intValue());
|
||||||
template.getVehicleStatus().setCompletedVehicles(vs.getCompletedVehicles().intValue());
|
template.getVehicleStatus().setCompletedVehicles(vs.getCompletedVehicles().intValue());
|
||||||
}
|
}
|
||||||
|
|
||||||
// ====== 真实数据:本月任务统计 taskTotal ======
|
// ====== 真实数据:本月任务统计 taskTotal / avgTaskDuration / taskCompletionRate ======
|
||||||
long monthTasks = biPlatformRealDataService.countMonthTasks();
|
long monthTasks = biPlatformRealDataService.countMonthTasks();
|
||||||
if (template.getMonthlyTaskStatistics() != null) {
|
if (template.getMonthlyTaskStatistics() != null) {
|
||||||
template.getMonthlyTaskStatistics().setTaskTotal((int) monthTasks);
|
template.getMonthlyTaskStatistics().setTaskTotal((int) monthTasks);
|
||||||
|
com.mhd.bi.domain.biPlatformRealData.repository.po.RealMonthlyTaskDurationPO monthStats =
|
||||||
|
biPlatformRealDataService.queryMonthTaskStats();
|
||||||
|
if (monthStats != null) {
|
||||||
|
if (monthStats.getAvgDurationHours() != null) {
|
||||||
|
double v = monthStats.getAvgDurationHours();
|
||||||
|
template.getMonthlyTaskStatistics().setAvgTaskDuration(Math.round(v * 100.0) / 100.0);
|
||||||
|
}
|
||||||
|
Long total = monthStats.getTotalCount();
|
||||||
|
Long completed = monthStats.getCompletedCount();
|
||||||
|
if (total != null && total > 0 && completed != null) {
|
||||||
|
int rate = (int) Math.round(((double) completed.longValue() / total.longValue()) * 100.0);
|
||||||
|
template.getMonthlyTaskStatistics().setTaskCompletionRate(rate);
|
||||||
|
} else {
|
||||||
|
template.getMonthlyTaskStatistics().setTaskCompletionRate(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ====== 真实数据:任务负荷(今日 24 小时) ======
|
// ====== 真实数据:任务负荷(今日 24 小时) ======
|
||||||
@@ -218,6 +248,9 @@ public class BiReportSnapshotSyncService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ====== 真实数据:任务类型统计(本月 YMS QMS_MAIN_BUSINESS 按业务类型 BUSINESS_NAME 分组) ======
|
||||||
|
template.setTaskTypeStatistics(biPlatformRealDataService.queryMonthTransportOrderByType());
|
||||||
|
|
||||||
return template;
|
return template;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+5
-16
@@ -185,13 +185,8 @@ public final class BiSnapshotWeeklyRandomDataBuilder {
|
|||||||
.build());
|
.build());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 月台告警:按业务要求,全部置 0(趋势/统计/分布均不生成写死数据)
|
||||||
List<PlatformAlarmTrendItemVO> alarmTrend = new ArrayList<>();
|
List<PlatformAlarmTrendItemVO> alarmTrend = new ArrayList<>();
|
||||||
for (int i = 0; i < Baseline.P_AL_D.length; i++) {
|
|
||||||
alarmTrend.add(PlatformAlarmTrendItemVO.builder()
|
|
||||||
.date(Baseline.P_AL_D[i])
|
|
||||||
.alarmCount(Math.max(0, jitterInt(Baseline.P_AL_C[i], r)))
|
|
||||||
.build());
|
|
||||||
}
|
|
||||||
|
|
||||||
List<TaskTypeCountItemVO> typeCounts = new ArrayList<>();
|
List<TaskTypeCountItemVO> typeCounts = new ArrayList<>();
|
||||||
for (int i = 0; i < Baseline.P_TT_TYPES.length; i++) {
|
for (int i = 0; i < Baseline.P_TT_TYPES.length; i++) {
|
||||||
@@ -201,18 +196,11 @@ public final class BiSnapshotWeeklyRandomDataBuilder {
|
|||||||
.build());
|
.build());
|
||||||
}
|
}
|
||||||
|
|
||||||
int todayAl = Math.max(0, jitterInt(Baseline.P_AL_TOT, r));
|
int todayAl = 0;
|
||||||
int handled = Math.max(0, jitterInt(Baseline.P_AL_H, r));
|
int handled = 0;
|
||||||
handled = Math.min(handled, todayAl);
|
int unhandled = 0;
|
||||||
int unhandled = Math.max(0, todayAl - handled);
|
|
||||||
|
|
||||||
List<PlatformAlarmDistItemVO> dist = new ArrayList<>();
|
List<PlatformAlarmDistItemVO> dist = new ArrayList<>();
|
||||||
for (int i = 0; i < Baseline.P_DIST_T.length; i++) {
|
|
||||||
dist.add(PlatformAlarmDistItemVO.builder()
|
|
||||||
.type(Baseline.P_DIST_T[i])
|
|
||||||
.count(Math.max(0, jitterInt(Baseline.P_DIST_C[i], r)))
|
|
||||||
.build());
|
|
||||||
}
|
|
||||||
|
|
||||||
return PlatformSurveillanceVO.builder()
|
return PlatformSurveillanceVO.builder()
|
||||||
.vehicles(vehicles)
|
.vehicles(vehicles)
|
||||||
@@ -415,6 +403,7 @@ public final class BiSnapshotWeeklyRandomDataBuilder {
|
|||||||
static final int P_TASKS = 418;
|
static final int P_TASKS = 418;
|
||||||
static final int P_RESV = 2_850;
|
static final int P_RESV = 2_850;
|
||||||
static final int P_NC = 920;
|
static final int P_NC = 920;
|
||||||
|
static final int P_WAIT = 680;
|
||||||
static final int P_OPV = 1_180;
|
static final int P_OPV = 1_180;
|
||||||
static final int P_DONE = 1_420;
|
static final int P_DONE = 1_420;
|
||||||
static final String[] P_MO_LABELS = {"5月", "6月", "7月"};
|
static final String[] P_MO_LABELS = {"5月", "6月", "7月"};
|
||||||
|
|||||||
+3
@@ -20,6 +20,9 @@ public class VehicleStatusVO {
|
|||||||
@ApiModelProperty("当前未签到,单位:辆")
|
@ApiModelProperty("当前未签到,单位:辆")
|
||||||
private Integer notCheckedIn;
|
private Integer notCheckedIn;
|
||||||
|
|
||||||
|
@ApiModelProperty("当前等待作业(已预约/已签到/已叫号),单位:辆")
|
||||||
|
private Integer waiting;
|
||||||
|
|
||||||
@ApiModelProperty("当前作业中,单位:辆")
|
@ApiModelProperty("当前作业中,单位:辆")
|
||||||
private Integer operatingVehicles;
|
private Integer operatingVehicles;
|
||||||
|
|
||||||
|
|||||||
@@ -40,35 +40,81 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
|||||||
FROM NGWL_TEST_YMS.QMS_WINDOW_INFO
|
FROM NGWL_TEST_YMS.QMS_WINDOW_INFO
|
||||||
</select>
|
</select>
|
||||||
|
|
||||||
<!-- 今日作业任务:实际进入时间是今日的 -->
|
<!-- 今日作业任务:按预约时间 TARGET_DATE(今日)统计主业务记录数 -->
|
||||||
<select id="countTodayTasks" resultType="java.lang.Long">
|
<select id="countTodayTasks" resultType="java.lang.Long">
|
||||||
SELECT COUNT(1)
|
SELECT COUNT(1)
|
||||||
FROM NGWL_TEST_YMS.QMS_MAIN_BUSINESS
|
FROM NGWL_TEST_YMS.QMS_MAIN_BUSINESS
|
||||||
WHERE ENTRY_TIME IS NOT NULL
|
WHERE TARGET_DATE IS NOT NULL
|
||||||
AND TRUNC(ENTRY_TIME) = TRUNC(SYSDATE)
|
AND TRUNC(TARGET_DATE) = TRUNC(SYSDATE)
|
||||||
|
</select>
|
||||||
|
|
||||||
|
<!-- 今日作业准时率统计:
|
||||||
|
total 今日有入场时间的预约车辆数(ENTRY_TIME 不为空 且 TARGET_DATE = 今天)
|
||||||
|
onTimeCount 今日准时车辆数(实际进入时间 < 预约日期 + 预约结束时间 BOOKING_END_TIME,即 ENTRY_TIME < TRUNC(TARGET_DATE) + 预约时段结束时分)
|
||||||
|
「准时率 = 今日准时车辆数 / 今日有入场时间的车辆数 × 100%(四舍五入取整);分子分母都只统计有入场时间的车辆」
|
||||||
|
BOOKING_END_TIME 存纯时分(如 18:30),故用 TO_DATE 解析后取其时分间隔加到 TARGET_DATE 上
|
||||||
|
-->
|
||||||
|
<select id="queryTodayOnTimeStats" resultType="com.mhd.bi.domain.biPlatformRealData.repository.po.RealOnTimeStatPO">
|
||||||
|
SELECT
|
||||||
|
SUM(CASE WHEN ENTRY_TIME IS NOT NULL
|
||||||
|
AND TARGET_DATE IS NOT NULL
|
||||||
|
AND TRUNC(TARGET_DATE) = TRUNC(SYSDATE) THEN 1 ELSE 0 END) AS total,
|
||||||
|
SUM(CASE WHEN ENTRY_TIME IS NOT NULL
|
||||||
|
AND TRUNC(TARGET_DATE) = TRUNC(SYSDATE)
|
||||||
|
AND ENTRY_TIME < TRUNC(TARGET_DATE)
|
||||||
|
+ (TO_DATE(BOOKING_END_TIME, 'HH24:MI') - TRUNC(TO_DATE(BOOKING_END_TIME, 'HH24:MI')))
|
||||||
|
THEN 1 ELSE 0 END) AS onTimeCount
|
||||||
|
FROM NGWL_TEST_YMS.QMS_MAIN_BUSINESS
|
||||||
</select>
|
</select>
|
||||||
|
|
||||||
<!-- 车辆状态统计:今日的统计(按创建时间 CREATE_TIME / 流程状态)
|
<!-- 车辆状态统计:今日的统计(按创建时间 CREATE_TIME / 流程状态)
|
||||||
todayReservedVehicles 改为按预约日期 TARGET_DATE(其它 3 项保持 CREATE_TIME)
|
todayReservedVehicles 改为按预约日期 TARGET_DATE(其它 3 项保持 CREATE_TIME)
|
||||||
|
waiting 等待作业:FLOW_STATUS IN ('1','2','3') 已预约/已签到/已叫号 且 预约日期 = 今天
|
||||||
FLOW_STATUS: 1已预约 2已签到 3已叫号 4已过号 5已进场 6已称重 7已装车 8二次称重 9已结算 10已还卡 11已出场 12已取消 -->
|
FLOW_STATUS: 1已预约 2已签到 3已叫号 4已过号 5已进场 6已称重 7已装车 8二次称重 9已结算 10已还卡 11已出场 12已取消 -->
|
||||||
<select id="queryVehicleStatusToday" resultType="com.mhd.bi.domain.biPlatformRealData.repository.po.RealVehicleStatusPO">
|
<select id="queryVehicleStatusToday" resultType="com.mhd.bi.domain.biPlatformRealData.repository.po.RealVehicleStatusPO">
|
||||||
SELECT
|
SELECT
|
||||||
SUM(CASE WHEN TRUNC(TARGET_DATE) = TRUNC(SYSDATE) THEN 1 ELSE 0 END) AS todayReservedVehicles,
|
SUM(CASE WHEN TRUNC(TARGET_DATE) = TRUNC(SYSDATE) THEN 1 ELSE 0 END) AS todayReservedVehicles,
|
||||||
SUM(CASE WHEN FLOW_STATUS = '1' AND TRUNC(CREATE_TIME) = TRUNC(SYSDATE) THEN 1 ELSE 0 END) AS notCheckedIn,
|
SUM(CASE WHEN FLOW_STATUS = '1' AND TRUNC(CREATE_TIME) = TRUNC(SYSDATE) THEN 1 ELSE 0 END) AS notCheckedIn,
|
||||||
|
SUM(CASE WHEN FLOW_STATUS IN ('1','2','3') AND TRUNC(TARGET_DATE) = TRUNC(SYSDATE) THEN 1 ELSE 0 END) AS waiting,
|
||||||
SUM(CASE WHEN FLOW_STATUS IN ('5','6','7','8','9','10') AND TRUNC(CREATE_TIME) = TRUNC(SYSDATE) THEN 1 ELSE 0 END) AS operatingVehicles,
|
SUM(CASE WHEN FLOW_STATUS IN ('5','6','7','8','9','10') AND TRUNC(CREATE_TIME) = TRUNC(SYSDATE) THEN 1 ELSE 0 END) AS operatingVehicles,
|
||||||
SUM(CASE WHEN FLOW_STATUS = '11' AND TRUNC(CREATE_TIME) = TRUNC(SYSDATE) THEN 1 ELSE 0 END) AS completedVehicles
|
SUM(CASE WHEN FLOW_STATUS = '11' AND TRUNC(CREATE_TIME) = TRUNC(SYSDATE) THEN 1 ELSE 0 END) AS completedVehicles
|
||||||
FROM NGWL_TEST_YMS.QMS_MAIN_BUSINESS
|
FROM NGWL_TEST_YMS.QMS_MAIN_BUSINESS
|
||||||
</select>
|
</select>
|
||||||
|
|
||||||
<!-- 本月任务量:实际进入时间是本月的 -->
|
<!-- 本月任务量:按预约日期 TARGET_DATE(Y预约日期)统计本月预约总数量 -->
|
||||||
<select id="countMonthTasks" resultType="java.lang.Long">
|
<select id="countMonthTasks" resultType="java.lang.Long">
|
||||||
SELECT COUNT(1)
|
SELECT COUNT(1)
|
||||||
FROM NGWL_TEST_YMS.QMS_MAIN_BUSINESS
|
FROM NGWL_TEST_YMS.QMS_MAIN_BUSINESS
|
||||||
WHERE ENTRY_TIME IS NOT NULL
|
WHERE TARGET_DATE IS NOT NULL
|
||||||
AND TO_CHAR(ENTRY_TIME, 'YYYY-MM') = TO_CHAR(SYSDATE, 'YYYY-MM')
|
AND TO_CHAR(TARGET_DATE, 'YYYY-MM') = TO_CHAR(SYSDATE, 'YYYY-MM')
|
||||||
</select>
|
</select>
|
||||||
|
|
||||||
<!-- 今日预约-业务名称统计:按 BUSINESS_NAME(业务名称)分组统计今日预约数量,按预约日期 TARGET_DATE 过滤 -->
|
<!-- 本月任务平均作业时长 / 完成率统计:
|
||||||
|
avgDurationHours 平均时长(小时)= AVG((EXIT_TIME - ENTRY_TIME) * 24)
|
||||||
|
仅 ENTRY_TIME 与 EXIT_TIME 都不为空时参与;
|
||||||
|
durationCount 参与平均时长统计的有效条数;
|
||||||
|
completedCount 本月(TARGET_DATE)已出场(EXIT_TIME IS NOT NULL)的数量;
|
||||||
|
totalCount 本月(TARGET_DATE)预约总数量。
|
||||||
|
-->
|
||||||
|
<select id="queryMonthTaskStats" resultType="com.mhd.bi.domain.biPlatformRealData.repository.po.RealMonthlyTaskDurationPO">
|
||||||
|
SELECT
|
||||||
|
AVG(CASE WHEN ENTRY_TIME IS NOT NULL AND EXIT_TIME IS NOT NULL
|
||||||
|
THEN (EXIT_TIME - ENTRY_TIME) * 24
|
||||||
|
END) AS avgDurationHours,
|
||||||
|
SUM(CASE WHEN ENTRY_TIME IS NOT NULL AND EXIT_TIME IS NOT NULL
|
||||||
|
AND TO_CHAR(ENTRY_TIME, 'YYYY-MM') = TO_CHAR(SYSDATE, 'YYYY-MM')
|
||||||
|
THEN 1 ELSE 0 END) AS durationCount,
|
||||||
|
SUM(CASE WHEN EXIT_TIME IS NOT NULL
|
||||||
|
AND TARGET_DATE IS NOT NULL
|
||||||
|
AND TO_CHAR(TARGET_DATE, 'YYYY-MM') = TO_CHAR(SYSDATE, 'YYYY-MM')
|
||||||
|
THEN 1 ELSE 0 END) AS completedCount,
|
||||||
|
SUM(CASE WHEN TARGET_DATE IS NOT NULL
|
||||||
|
AND TO_CHAR(TARGET_DATE, 'YYYY-MM') = TO_CHAR(SYSDATE, 'YYYY-MM')
|
||||||
|
THEN 1 ELSE 0 END) AS totalCount
|
||||||
|
FROM NGWL_TEST_YMS.QMS_MAIN_BUSINESS
|
||||||
|
</select>
|
||||||
|
|
||||||
|
<!-- 今日预约-业务类型统计:按 BUSINESS_NAME(业务类型名称)分组统计今日预约数量,按预约日期 TARGET_DATE 过滤 -->
|
||||||
<select id="queryTodayBusinessTypeStats" resultType="com.mhd.bi.domain.biPlatformRealData.repository.po.RealBusinessTypeStatPO">
|
<select id="queryTodayBusinessTypeStats" resultType="com.mhd.bi.domain.biPlatformRealData.repository.po.RealBusinessTypeStatPO">
|
||||||
SELECT
|
SELECT
|
||||||
BUSINESS_NAME AS businessName,
|
BUSINESS_NAME AS businessName,
|
||||||
@@ -102,6 +148,20 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
|||||||
ORDER BY 1 DESC
|
ORDER BY 1 DESC
|
||||||
</select>
|
</select>
|
||||||
|
|
||||||
|
<!-- 任务类型统计(来自 NGWL_TEST_YMS.QMS_MAIN_BUSINESS 预约登记表):
|
||||||
|
按本月预约车辆数(TARGET_DATE 在当前月)按 BUSINESS_NAME 业务类型分组统计 -->
|
||||||
|
<select id="queryMonthTransportOrderByType" resultType="com.mhd.bi.domain.biPlatformRealData.repository.po.RealTaskTypeStatPO">
|
||||||
|
SELECT
|
||||||
|
BUSINESS_NAME AS businessName,
|
||||||
|
COUNT(1) AS count
|
||||||
|
FROM NGWL_TEST_YMS.QMS_MAIN_BUSINESS
|
||||||
|
WHERE BUSINESS_NAME IS NOT NULL
|
||||||
|
AND TARGET_DATE IS NOT NULL
|
||||||
|
AND TO_CHAR(TARGET_DATE, 'YYYY-MM') = TO_CHAR(SYSDATE, 'YYYY-MM')
|
||||||
|
GROUP BY BUSINESS_NAME
|
||||||
|
ORDER BY COUNT(1) DESC
|
||||||
|
</select>
|
||||||
|
|
||||||
<!-- 任务负荷(今日 24 小时时段):按 EXTRACT(HOUR FROM ENTRY_TIME) 统计 -->
|
<!-- 任务负荷(今日 24 小时时段):按 EXTRACT(HOUR FROM ENTRY_TIME) 统计 -->
|
||||||
<select id="queryTaskLoadToday" resultType="com.mhd.bi.domain.biPlatformRealData.repository.po.RealTaskLoadPO">
|
<select id="queryTaskLoadToday" resultType="com.mhd.bi.domain.biPlatformRealData.repository.po.RealTaskLoadPO">
|
||||||
SELECT
|
SELECT
|
||||||
|
|||||||
-3
@@ -35,7 +35,4 @@ public class WarehousePO implements Serializable {
|
|||||||
|
|
||||||
@Excel(name = "是否启用: 1-否 2-是")
|
@Excel(name = "是否启用: 1-否 2-是")
|
||||||
private Integer isEnable;
|
private Integer isEnable;
|
||||||
|
|
||||||
@ApiModelProperty("库存锁定模式: 1-下单冻结 2-分配库存冻结")
|
|
||||||
private Integer stockLockMode;
|
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-1
@@ -26,7 +26,8 @@ import java.io.InputStream;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
@FeignClient(value = "mhd-third-party-service",url = "http://10.33.0.129:8012", configuration = FeignAutoConfiguration.class)
|
// 目标地址由 nacos 配置项 feign.url.mhd-third-party-service 指定,未配置时按服务名走服务发现
|
||||||
|
@FeignClient(value = "mhd-third-party-service",url = "http://10.102.192.32:8012", configuration = FeignAutoConfiguration.class)
|
||||||
public interface ThirdPartyServiceFeign {
|
public interface ThirdPartyServiceFeign {
|
||||||
|
|
||||||
//查询当前组织所有三方接口信息
|
//查询当前组织所有三方接口信息
|
||||||
|
|||||||
-70
@@ -12,9 +12,7 @@ import com.mhd.basic.domain.warehouse.repository.todo.WarehouseDO;
|
|||||||
import com.mhd.basic.domain.warehouse.service.WarehouseDomainService;
|
import com.mhd.basic.domain.warehouse.service.WarehouseDomainService;
|
||||||
import com.mhd.common.core.enums.DictCode;
|
import com.mhd.common.core.enums.DictCode;
|
||||||
import com.mhd.common.core.exception.ServiceException;
|
import com.mhd.common.core.exception.ServiceException;
|
||||||
import com.mhd.common.core.web.domain.AjaxResult;
|
|
||||||
import com.mhd.common.security.utils.SecurityUtils;
|
import com.mhd.common.security.utils.SecurityUtils;
|
||||||
import com.mhd.system.api.WmsServiceFeign;
|
|
||||||
import com.mhd.system.api.domain.SysDictData;
|
import com.mhd.system.api.domain.SysDictData;
|
||||||
import com.mhd.system.api.model.LoginUser;
|
import com.mhd.system.api.model.LoginUser;
|
||||||
import com.mhd.system.service.ISysDictTypeService;
|
import com.mhd.system.service.ISysDictTypeService;
|
||||||
@@ -45,8 +43,6 @@ public class WarehouseApplicationService {
|
|||||||
private ISysDictTypeService dictTypeService;
|
private ISysDictTypeService dictTypeService;
|
||||||
@Autowired
|
@Autowired
|
||||||
private IAssociationWarehouseService associationWarehouseService;
|
private IAssociationWarehouseService associationWarehouseService;
|
||||||
@Autowired
|
|
||||||
private WmsServiceFeign wmsServiceFeign;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -243,78 +239,12 @@ public class WarehouseApplicationService {
|
|||||||
/**
|
/**
|
||||||
* 修改仓库
|
* 修改仓库
|
||||||
*/
|
*/
|
||||||
/**
|
|
||||||
* @description 查询仓库库存锁定模式(OMS下单冻结库存/防超卖功能的仓库级开关)
|
|
||||||
* 1-下单冻结:OMS出库业务单「下单」即冻结WMS库存(可用-、冻结+,库存数量不变)
|
|
||||||
* 2-分配库存冻结:现有模式,WMS「分配库存」时才冻结
|
|
||||||
* 仓库不存在或未配置(null)时返回默认值 2(与代码侧降级口径一致)
|
|
||||||
* @author gen
|
|
||||||
* @date 2026-09-12
|
|
||||||
*/
|
|
||||||
public Integer getStockLockMode(Long warehouseId) {
|
|
||||||
WarehousePO warehousePO = warehouseDomainService.getInfo(warehouseId);
|
|
||||||
return warehousePO == null ? 2
|
|
||||||
: cn.hutool.core.util.ObjectUtil.defaultIfNull(warehousePO.getStockLockMode(), 2);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Boolean update(WarehouseDO warehouseDO) {
|
public Boolean update(WarehouseDO warehouseDO) {
|
||||||
// 库存锁定模式切换守卫:模式发生变化时,存在在途冻结单(OMS下单冻结未释放)则禁止切换,
|
|
||||||
// 否则在途单的解冻/承接逻辑会按新模式错乱。fail-closed:校验服务不可用时拒绝切换
|
|
||||||
if (warehouseDO.getWarehouseId() != null && warehouseDO.getStockLockMode() != null) {
|
|
||||||
WarehousePO existingPO = warehouseDomainService.getInfo(warehouseDO.getWarehouseId());
|
|
||||||
if (existingPO != null) {
|
|
||||||
checkStockLockModeSwitchable(warehouseDO.getWarehouseId(), warehouseDO.getStockLockMode(), existingPO);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
//设置数据字典键值
|
//设置数据字典键值
|
||||||
setDataDict(warehouseDO);
|
setDataDict(warehouseDO);
|
||||||
return warehouseDomainService.update(warehouseDO);
|
return warehouseDomainService.update(warehouseDO);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @description 单独切换仓库库存锁定模式(不改动仓库其他信息)
|
|
||||||
* 1-下单冻结:OMS出库业务单「下单」即冻结WMS库存
|
|
||||||
* 2-分配库存冻结(默认):WMS「分配库存」时才冻结
|
|
||||||
* 切换守卫与通用编辑一致:模式变化且存在在途冻结单时禁止切换,fail-closed
|
|
||||||
* @author gen
|
|
||||||
* @date 2026-09-14
|
|
||||||
*/
|
|
||||||
public Boolean switchStockLockMode(Long warehouseId, Integer stockLockMode) {
|
|
||||||
if (warehouseId == null) {
|
|
||||||
throw new ServiceException("仓库ID不能为空");
|
|
||||||
}
|
|
||||||
if (stockLockMode == null || (stockLockMode.intValue() != 1 && stockLockMode.intValue() != 2)) {
|
|
||||||
throw new ServiceException("库存锁定模式不合法,仅支持 1-下单冻结 2-分配库存冻结");
|
|
||||||
}
|
|
||||||
WarehousePO existingPO = warehouseDomainService.getInfo(warehouseId);
|
|
||||||
if (existingPO == null) {
|
|
||||||
throw new ServiceException("仓库不存在");
|
|
||||||
}
|
|
||||||
checkStockLockModeSwitchable(warehouseId, stockLockMode, existingPO);
|
|
||||||
return warehouseDomainService.switchStockLockMode(warehouseId, stockLockMode);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @description 库存锁定模式切换守卫:模式未变化直接放行;模式变化时查询WMS是否存在
|
|
||||||
* 在途下单冻结单(freeze_status 1/2),存在则禁止切换。
|
|
||||||
* fail-closed:WMS服务不可用/返回异常时一律拒绝切换,防止切换后冻结语义错乱
|
|
||||||
* @author gen
|
|
||||||
* @date 2026-09-14
|
|
||||||
*/
|
|
||||||
private void checkStockLockModeSwitchable(Long warehouseId, Integer newMode, WarehousePO existingPO) {
|
|
||||||
if (newMode.compareTo(cn.hutool.core.util.ObjectUtil.defaultIfNull(existingPO.getStockLockMode(), 2)) == 0) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
AjaxResult freezeCheck = wmsServiceFeign.hasActiveFreezeByWarehouse(warehouseId);
|
|
||||||
if (freezeCheck == null || !"200".equals(String.valueOf(freezeCheck.get("code")))) {
|
|
||||||
throw new ServiceException("库存锁定模式切换校验失败,请稍后重试:"
|
|
||||||
+ (freezeCheck == null ? "WMS服务不可用" : freezeCheck.get("msg")));
|
|
||||||
}
|
|
||||||
if (Boolean.TRUE.equals(freezeCheck.get("data"))) {
|
|
||||||
throw new ServiceException("该仓库存在下单冻结中的出库单,不可切换库存锁定模式");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @description 设置数据字典键值
|
* @description 设置数据字典键值
|
||||||
* @author ZhouGY
|
* @author ZhouGY
|
||||||
|
|||||||
+8
-8
@@ -38,13 +38,13 @@ public class XxlJobOpenApiUtil {
|
|||||||
try {
|
try {
|
||||||
Map<String, Object> formMap = BeanUtil.beanToMap(addReq);
|
Map<String, Object> formMap = BeanUtil.beanToMap(addReq);
|
||||||
HttpResponse response = HttpRequest.post(url)
|
HttpResponse response = HttpRequest.post(url)
|
||||||
.header("Cookie", cookie)
|
.header("Authorization", cookie)
|
||||||
.form(formMap)
|
.form(formMap)
|
||||||
.execute();
|
.execute();
|
||||||
int status = response.getStatus();
|
int status = response.getStatus();
|
||||||
log.info("[XxlJob] addJob status:{}", status);
|
log.info("[XxlJob] addJob status:{}", status);
|
||||||
// 新增成功200重定向到列表页
|
// 新增成功200重定向到列表页
|
||||||
return status == 200;
|
return status == 200 || status == 302;
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
log.error("[XxlJob] addJob异常", e);
|
log.error("[XxlJob] addJob异常", e);
|
||||||
return false;
|
return false;
|
||||||
@@ -128,10 +128,10 @@ public class XxlJobOpenApiUtil {
|
|||||||
String url = adminUrl + "/jobinfo/pause";
|
String url = adminUrl + "/jobinfo/pause";
|
||||||
try {
|
try {
|
||||||
HttpResponse response = HttpRequest.post(url)
|
HttpResponse response = HttpRequest.post(url)
|
||||||
.header("Cookie", cookie)
|
.header("Authorization", cookie)
|
||||||
.form("id", jobId)
|
.form("id", jobId)
|
||||||
.execute();
|
.execute();
|
||||||
return response.getStatus() == 200;
|
return response.getStatus() == 200 || response.getStatus() == 302;
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
log.error("[XxlJob] pauseJob jobId:{}异常", jobId, e);
|
log.error("[XxlJob] pauseJob jobId:{}异常", jobId, e);
|
||||||
return false;
|
return false;
|
||||||
@@ -150,10 +150,10 @@ public class XxlJobOpenApiUtil {
|
|||||||
String url = adminUrl + "/jobinfo/start";
|
String url = adminUrl + "/jobinfo/start";
|
||||||
try {
|
try {
|
||||||
HttpResponse response = HttpRequest.post(url)
|
HttpResponse response = HttpRequest.post(url)
|
||||||
.header("Cookie", cookie)
|
.header("Authorization", cookie)
|
||||||
.form("id", jobId)
|
.form("id", jobId)
|
||||||
.execute();
|
.execute();
|
||||||
return response.getStatus() == 200;
|
return response.getStatus() == 200 || response.getStatus() == 302;
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
log.error("[XxlJob] startJob jobId:{}异常", jobId, e);
|
log.error("[XxlJob] startJob jobId:{}异常", jobId, e);
|
||||||
return false;
|
return false;
|
||||||
@@ -172,10 +172,10 @@ public class XxlJobOpenApiUtil {
|
|||||||
String url = adminUrl + "/jobinfo/remove";
|
String url = adminUrl + "/jobinfo/remove";
|
||||||
try {
|
try {
|
||||||
HttpResponse response = HttpRequest.post(url)
|
HttpResponse response = HttpRequest.post(url)
|
||||||
.header("Cookie", cookie)
|
.header("Authorization", cookie)
|
||||||
.form("id", jobId)
|
.form("id", jobId)
|
||||||
.execute();
|
.execute();
|
||||||
return response.getStatus() == 200;
|
return response.getStatus() == 200 || response.getStatus() == 302;
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
log.error("[XxlJob] removeJob jobId:{}异常", jobId, e);
|
log.error("[XxlJob] removeJob jobId:{}异常", jobId, e);
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
-4
@@ -130,10 +130,6 @@ public class Warehouse extends BaseVOEntity{
|
|||||||
@Excel(name = "作业模式")
|
@Excel(name = "作业模式")
|
||||||
private String workMode;
|
private String workMode;
|
||||||
|
|
||||||
@ApiModelProperty("库存锁定模式: 1-下单冻结 2-分配库存冻结")
|
|
||||||
@Excel(name = "库存锁定模式: 1-下单冻结 2-分配库存冻结")
|
|
||||||
private Integer stockLockMode;
|
|
||||||
|
|
||||||
@ApiModelProperty("订单号生成规则0日期累加1历史累加")
|
@ApiModelProperty("订单号生成规则0日期累加1历史累加")
|
||||||
@Excel(name = "单号生成规则")
|
@Excel(name = "单号生成规则")
|
||||||
private String orderNoGenerateRule;
|
private String orderNoGenerateRule;
|
||||||
|
|||||||
-4
@@ -132,10 +132,6 @@ public class WarehousePO extends BaseVOEntity{
|
|||||||
@Excel(name = "作业模式")
|
@Excel(name = "作业模式")
|
||||||
private String workMode;
|
private String workMode;
|
||||||
|
|
||||||
@ApiModelProperty("库存锁定模式: 1-下单冻结 2-分配库存冻结")
|
|
||||||
@Excel(name = "库存锁定模式: 1-下单冻结 2-分配库存冻结")
|
|
||||||
private Integer stockLockMode;
|
|
||||||
|
|
||||||
|
|
||||||
@ApiModelProperty("订单号生成规则")
|
@ApiModelProperty("订单号生成规则")
|
||||||
@Excel(name = "单号生成规则")
|
@Excel(name = "单号生成规则")
|
||||||
|
|||||||
-4
@@ -140,10 +140,6 @@ public class WarehouseDO extends BaseVOEntity{
|
|||||||
@Excel(name = "作业模式")
|
@Excel(name = "作业模式")
|
||||||
private String workMode;
|
private String workMode;
|
||||||
|
|
||||||
@ApiModelProperty("库存锁定模式: 1-下单冻结 2-分配库存冻结")
|
|
||||||
@Excel(name = "库存锁定模式: 1-下单冻结 2-分配库存冻结")
|
|
||||||
private Integer stockLockMode;
|
|
||||||
|
|
||||||
|
|
||||||
@ApiModelProperty("订单号生成规则")
|
@ApiModelProperty("订单号生成规则")
|
||||||
@Excel(name = "单号生成规则")
|
@Excel(name = "单号生成规则")
|
||||||
|
|||||||
-23
@@ -142,29 +142,6 @@ public class WarehouseDomainService {
|
|||||||
.eq(Warehouse::getDelFlag, 1));
|
.eq(Warehouse::getDelFlag, 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @description 单独切换仓库库存锁定模式(仅更新 STOCK_LOCK_MODE 与审计字段,不触碰仓库其他数据)
|
|
||||||
* 1-下单冻结:OMS出库业务单「下单」即冻结WMS库存
|
|
||||||
* 2-分配库存冻结(默认):WMS「分配库存」时才冻结
|
|
||||||
* @author gen
|
|
||||||
* @date 2026-09-14
|
|
||||||
*/
|
|
||||||
public Boolean switchStockLockMode(Long warehouseId, Integer stockLockMode) {
|
|
||||||
Long updateBy = null;
|
|
||||||
try {
|
|
||||||
LoginUser loginUser = SecurityUtils.getLoginUser();
|
|
||||||
updateBy = loginUser == null ? null : loginUser.getUserid();
|
|
||||||
} catch (Exception ignore) {
|
|
||||||
}
|
|
||||||
Long finalUpdateBy = updateBy;
|
|
||||||
return warehouseService.update(new UpdateWrapper<Warehouse>().lambda()
|
|
||||||
.set(Warehouse::getStockLockMode, stockLockMode)
|
|
||||||
.set(finalUpdateBy != null, Warehouse::getUpdateBy, finalUpdateBy)
|
|
||||||
.set(Warehouse::getUpdateTime, new Date())
|
|
||||||
.eq(Warehouse::getWarehouseId, warehouseId)
|
|
||||||
.eq(Warehouse::getDelFlag, 1));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @description 获取指定仓库下的所有库区及库区下所有库位
|
* @description 获取指定仓库下的所有库区及库区下所有库位
|
||||||
* @author ZhouGY
|
* @author ZhouGY
|
||||||
|
|||||||
-4
@@ -145,10 +145,6 @@ public class WarehouseDTO extends BaseVOEntity{
|
|||||||
@Excel(name = "作业模式")
|
@Excel(name = "作业模式")
|
||||||
private String workMode;
|
private String workMode;
|
||||||
|
|
||||||
@ApiModelProperty("库存锁定模式: 1-下单冻结 2-分配库存冻结")
|
|
||||||
@Excel(name = "库存锁定模式: 1-下单冻结 2-分配库存冻结")
|
|
||||||
private Integer stockLockMode;
|
|
||||||
|
|
||||||
|
|
||||||
@ApiModelProperty("订单号生成规则")
|
@ApiModelProperty("订单号生成规则")
|
||||||
@Excel(name = "单号生成规则")
|
@Excel(name = "单号生成规则")
|
||||||
|
|||||||
-27
@@ -104,33 +104,6 @@ public class WarehouseApi extends BaseController{
|
|||||||
return AjaxResult.success(warehouseApplicationService.getInfo(warehouseId));
|
return AjaxResult.success(warehouseApplicationService.getInfo(warehouseId));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 查询仓库库存锁定模式(OMS下单冻结库存/防超卖功能的仓库级开关):
|
|
||||||
* 1-下单冻结(OMS出库业务单「下单」即冻结WMS库存:可用-、冻结+,库存数量不变;
|
|
||||||
* 分配不动数量;编辑=原子重锁;取消=释放;交接=库存-冻结-)
|
|
||||||
* 2-分配库存冻结(默认,现有行为:WMS「分配库存」时才 可用-冻结+)
|
|
||||||
* 仓库不存在或未配置时返回 2(与 OMS/WMS 代码侧降级口径一致)
|
|
||||||
*/
|
|
||||||
@ApiOperation("查询仓库库存锁定模式: 1-下单冻结 2-分配库存冻结")
|
|
||||||
@GetMapping(value = "/getStockLockMode/{warehouseId}")
|
|
||||||
public AjaxResult getStockLockMode(@PathVariable("warehouseId") Long warehouseId)
|
|
||||||
{
|
|
||||||
return AjaxResult.success(warehouseApplicationService.getStockLockMode(warehouseId));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 单独切换仓库库存锁定模式(不改动仓库其他信息):
|
|
||||||
* 模式变化且该仓库存在在途下单冻结出库单(freeze_status 1/2)时拒绝切换;
|
|
||||||
* WMS校验服务不可用时同样拒绝(fail-closed)
|
|
||||||
*/
|
|
||||||
@ApiOperation("切换仓库库存锁定模式: 1-下单冻结 2-分配库存冻结")
|
|
||||||
@PostMapping(value = "/switchStockLockMode/{warehouseId}/{stockLockMode}")
|
|
||||||
public AjaxResult switchStockLockMode(@PathVariable("warehouseId") Long warehouseId,
|
|
||||||
@PathVariable("stockLockMode") Integer stockLockMode)
|
|
||||||
{
|
|
||||||
return toAjax(warehouseApplicationService.switchStockLockMode(warehouseId, stockLockMode));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@ApiOperation("批量作废仓库")
|
@ApiOperation("批量作废仓库")
|
||||||
@GetMapping("/nullifyByIds/{warehouseIds}")
|
@GetMapping("/nullifyByIds/{warehouseIds}")
|
||||||
|
|||||||
@@ -13,16 +13,16 @@ spring:
|
|||||||
cloud:
|
cloud:
|
||||||
nacos:
|
nacos:
|
||||||
discovery:
|
discovery:
|
||||||
# server-addr: 127.0.0.1:8848
|
server-addr: 127.0.0.1:8848
|
||||||
server-addr: 10.33.0.129:6010
|
# server-addr: 10.33.0.129:6010
|
||||||
# server-addr: 10.102.192.31:6848
|
# server-addr: 10.102.192.31:6848
|
||||||
username: nacos
|
username: nacos
|
||||||
password: manhuoda@2023
|
password: manhuoda@2023
|
||||||
#线上正式环境
|
#线上正式环境
|
||||||
# server-addr: 10.102.192.105:6848
|
# server-addr: 10.102.192.105:6848
|
||||||
config:
|
config:
|
||||||
# server-addr: 127.0.0.1:8848
|
server-addr: 127.0.0.1:8848
|
||||||
server-addr: 10.33.0.129:6010
|
# server-addr: 10.33.0.129:6010
|
||||||
# server-addr: 10.102.192.31:6848
|
# server-addr: 10.102.192.31:6848
|
||||||
username: nacos
|
username: nacos
|
||||||
password: manhuoda@2023
|
password: manhuoda@2023
|
||||||
|
|||||||
+1
-2
@@ -43,7 +43,6 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
|||||||
<result property="orderNoGenerateRule" column="ORDER_NO_GENERATE_RULE" />
|
<result property="orderNoGenerateRule" column="ORDER_NO_GENERATE_RULE" />
|
||||||
<result property="inOrderNoPrefix" column="IN_ORDER_NO_PREFIX" />
|
<result property="inOrderNoPrefix" column="IN_ORDER_NO_PREFIX" />
|
||||||
<result property="outOrderNoPrefix" column="OUT_ORDER_NO_PREFIX" />
|
<result property="outOrderNoPrefix" column="OUT_ORDER_NO_PREFIX" />
|
||||||
<result property="stockLockMode" column="STOCK_LOCK_MODE" />
|
|
||||||
</resultMap>
|
</resultMap>
|
||||||
|
|
||||||
|
|
||||||
@@ -52,7 +51,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
|||||||
warehouse_type, warehouse_type_name, warehouse_structure, warehouse_nature, warm_layer_code, warm_layer_name,
|
warehouse_type, warehouse_type_name, warehouse_structure, warehouse_nature, warm_layer_code, warm_layer_name,
|
||||||
director_name, director_phone, region_code, region_name, detail_address, longitude, latitude, building_region,
|
director_name, director_phone, region_code, region_name, detail_address, longitude, latitude, building_region,
|
||||||
usage_region, remark, opening_up, nullify, create_time, create_by, create_by_name, update_time, update_by,
|
usage_region, remark, opening_up, nullify, create_time, create_by, create_by_name, update_time, update_by,
|
||||||
update_by_name, del_flag, IS_ENABLE ,WORK_MODE,TASK_MODE,STOCK_LOCK_MODE,SAMPLE_OUT_ORDER_NO_PREFIX,ORDER_NO_GENERATE_RULE,IN_ORDER_NO_PREFIX,
|
update_by_name, del_flag, IS_ENABLE ,WORK_MODE,TASK_MODE,SAMPLE_OUT_ORDER_NO_PREFIX,ORDER_NO_GENERATE_RULE,IN_ORDER_NO_PREFIX,
|
||||||
OUT_ORDER_NO_PREFIX
|
OUT_ORDER_NO_PREFIX
|
||||||
from warehouse
|
from warehouse
|
||||||
</sql>
|
</sql>
|
||||||
|
|||||||
+61
@@ -97,6 +97,7 @@ import com.mhd.system.api.model.LoginUser;
|
|||||||
import com.mhd.user.interfaces.dto.addDTO.UserDriverDTO;
|
import com.mhd.user.interfaces.dto.addDTO.UserDriverDTO;
|
||||||
import com.mhd.user.interfaces.dto.queryDTO.UserDocumentWarningQueryDTO;
|
import com.mhd.user.interfaces.dto.queryDTO.UserDocumentWarningQueryDTO;
|
||||||
import com.mhd.user.interfaces.dto.updateDTO.UpdateHasDefaultAddressDTO;
|
import com.mhd.user.interfaces.dto.updateDTO.UpdateHasDefaultAddressDTO;
|
||||||
|
import com.mhd.user.interfaces.dto.updateDTO.PasswordChangeDTO;
|
||||||
import com.mhd.user.interfaces.facadeApi.Po.UserDriverCountPo;
|
import com.mhd.user.interfaces.facadeApi.Po.UserDriverCountPo;
|
||||||
import com.mhd.user.interfaces.vo.QueryAllShipperInfoVo;
|
import com.mhd.user.interfaces.vo.QueryAllShipperInfoVo;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
@@ -214,6 +215,61 @@ public class UserApplicationService {
|
|||||||
@Autowired
|
@Autowired
|
||||||
private UserShipperMapper userShipperMapper;
|
private UserShipperMapper userShipperMapper;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 修改密码 - 同步 wlhy 与 yms
|
||||||
|
*/
|
||||||
|
@Transactional(rollbackFor = Exception.class)
|
||||||
|
public void changePassword(PasswordChangeDTO passwordChangeDTO) {
|
||||||
|
// 1. 获取当前登录用户
|
||||||
|
LoginUser loginUser = SecurityUtils.getLoginUser();
|
||||||
|
if (ObjectUtil.isNull(loginUser)) {
|
||||||
|
throw new DigitalLogisticsException(UserError.TIMEOUT);
|
||||||
|
}
|
||||||
|
|
||||||
|
Long userId = loginUser.getUserPo().getUserId();
|
||||||
|
if (userId == null) {
|
||||||
|
throw new ServiceException("用户未登录");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. 查询用户信息
|
||||||
|
UserPo userPO = userDomainService.selectByUserId(userId);
|
||||||
|
UserEntity userEntity = new UserEntity();
|
||||||
|
BeanUtils.copyProperties(userPO,userEntity);
|
||||||
|
if (ObjectUtil.isNull(userEntity)) {
|
||||||
|
throw new ServiceException("用户不存在");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3. 解密并加密新密码
|
||||||
|
String salt = userEntity.getUserSalt();
|
||||||
|
String newPassword = decrypt(passwordChangeDTO.getNewPassword());
|
||||||
|
String encodedPassword = PasswordUtil.encrypt(userEntity.getUserAccount(), newPassword, salt);
|
||||||
|
|
||||||
|
// 4. 更新本地密码
|
||||||
|
UserDO userDO = new UserDO();
|
||||||
|
userDO.setUserId(userId);
|
||||||
|
userDO.setUserPassword(encodedPassword);
|
||||||
|
userDomainService.updateUser(userDO);
|
||||||
|
|
||||||
|
// 5. 同步到网货平台(wlhy)
|
||||||
|
try {
|
||||||
|
userEntity.setUserPassword(encodedPassword);
|
||||||
|
wlhyDomainService.addOrEditPlatformUser(userEntity);
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.warn("同步密码到网货平台失败,但不影响主流程:{}", e.getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
// 6. 同步到 YMS 平台
|
||||||
|
try {
|
||||||
|
Integer isQueue = userMapper.getOrdIsQueue(userEntity.getOrganizationId());
|
||||||
|
if (isQueue != null && isQueue == 1) {
|
||||||
|
userEntity.setUserPassword(newPassword);
|
||||||
|
ymsDomainService.addOrEditYmsUser(userEntity);
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.warn("同步密码到 YMS 平台失败,但不影响主流程:{}", e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @Description 查询用户列表
|
* @Description 查询用户列表
|
||||||
* @Author Alex
|
* @Author Alex
|
||||||
@@ -1971,6 +2027,11 @@ public class UserApplicationService {
|
|||||||
if (StrUtil.isEmpty(userDO.getUserName())) {
|
if (StrUtil.isEmpty(userDO.getUserName())) {
|
||||||
userDO.setUserName("用户" + userDO.getUserPhone().substring(userDO.getUserPhone().length() - 4));
|
userDO.setUserName("用户" + userDO.getUserPhone().substring(userDO.getUserPhone().length() - 4));
|
||||||
}
|
}
|
||||||
|
//密码为空则给默认密码
|
||||||
|
if (StrUtil.isEmpty(userDO.getUserPassword())) {
|
||||||
|
String defaultPassword = "Aa123456";
|
||||||
|
userDO.setUserPassword(PasswordUtil.encrypt(userDO.getUserAccount(), defaultPassword, userDO.getUserSalt()));
|
||||||
|
}
|
||||||
UserEntity userEntity = userDomainService.addUser(userDO);
|
UserEntity userEntity = userDomainService.addUser(userDO);
|
||||||
//给小程序注册用户分配默认普通用户角色(must),本组织没有则找上级
|
//给小程序注册用户分配默认普通用户角色(must),本组织没有则找上级
|
||||||
userEntity.setUserPassword("Aa123456"); // 三方同步需要密码
|
userEntity.setUserPassword("Aa123456"); // 三方同步需要密码
|
||||||
|
|||||||
+1
@@ -100,6 +100,7 @@ public class UserYmsDomainService {
|
|||||||
ymsSysUserDTO.setPhonenumber(userEntity.getUserPhone());
|
ymsSysUserDTO.setPhonenumber(userEntity.getUserPhone());
|
||||||
ymsSysUserDTO.setAvatar(userEntity.getAvatar());
|
ymsSysUserDTO.setAvatar(userEntity.getAvatar());
|
||||||
ymsSysUserDTO.setUserAccountType(userEntity.getUserAccountType());
|
ymsSysUserDTO.setUserAccountType(userEntity.getUserAccountType());
|
||||||
|
ymsSysUserDTO.setPassword(userEntity.getUserPassword());
|
||||||
|
|
||||||
if (StringUtils.isNotBlank(userEntity.getRoleCode())){
|
if (StringUtils.isNotBlank(userEntity.getRoleCode())){
|
||||||
ymsSysUserDTO.setRoleCodes(Arrays.asList(userEntity.getRoleCode().split(",")));
|
ymsSysUserDTO.setRoleCodes(Arrays.asList(userEntity.getRoleCode().split(",")));
|
||||||
|
|||||||
+20
@@ -0,0 +1,20 @@
|
|||||||
|
package com.mhd.user.interfaces.dto.updateDTO;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import javax.validation.constraints.NotBlank;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 修改密码 DTO
|
||||||
|
* @author AI
|
||||||
|
* @date 2026/09/10
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class PasswordChangeDTO {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 新密码
|
||||||
|
*/
|
||||||
|
@NotBlank(message = "新密码不能为空")
|
||||||
|
private String newPassword;
|
||||||
|
}
|
||||||
@@ -32,6 +32,7 @@ import com.mhd.common.security.annotation.InnerAuth;
|
|||||||
import com.mhd.common.security.service.TokenService;
|
import com.mhd.common.security.service.TokenService;
|
||||||
import com.mhd.system.api.model.LoginUser;
|
import com.mhd.system.api.model.LoginUser;
|
||||||
import com.mhd.user.interfaces.dto.queryDTO.UserDocumentWarningQueryDTO;
|
import com.mhd.user.interfaces.dto.queryDTO.UserDocumentWarningQueryDTO;
|
||||||
|
import com.mhd.user.interfaces.dto.updateDTO.PasswordChangeDTO;
|
||||||
import com.mhd.user.interfaces.dto.updateDTO.UpdateHasDefaultAddressDTO;
|
import com.mhd.user.interfaces.dto.updateDTO.UpdateHasDefaultAddressDTO;
|
||||||
import com.mhd.user.interfaces.vo.QueryAllShipperInfoVo;
|
import com.mhd.user.interfaces.vo.QueryAllShipperInfoVo;
|
||||||
import io.swagger.annotations.Api;
|
import io.swagger.annotations.Api;
|
||||||
@@ -1037,4 +1038,16 @@ public class UserAPI extends BaseController {
|
|||||||
public R<String> finShipperEnterpriseNamedByUserId(@PathVariable("userId") Long userId) {
|
public R<String> finShipperEnterpriseNamedByUserId(@PathVariable("userId") Long userId) {
|
||||||
return R.ok(userApplicationService.finShipperEnterpriseNamedByUserId(userId));
|
return R.ok(userApplicationService.finShipperEnterpriseNamedByUserId(userId));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 修改密码 - 同步 wlhy 与 yms
|
||||||
|
* 根据当前登录用户判断是谁修改,只传新密码,不需要校验旧密码
|
||||||
|
*/
|
||||||
|
@Log(title = "用户中台管理 - 修改密码", description ="修改当前登录用户密码",businessType = BusinessType.UPDATE)
|
||||||
|
@ApiOperation("修改密码")
|
||||||
|
@PostMapping("/changePassword")
|
||||||
|
public AjaxResult changePassword(@RequestBody PasswordChangeDTO passwordChangeDTO) {
|
||||||
|
userApplicationService.changePassword(passwordChangeDTO);
|
||||||
|
return AjaxResult.success();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -18,15 +18,15 @@ spring:
|
|||||||
cloud:
|
cloud:
|
||||||
nacos:
|
nacos:
|
||||||
discovery:
|
discovery:
|
||||||
# server-addr: 127.0.0.1:8848
|
server-addr: 127.0.0.1:8848
|
||||||
# server-addr: 10.33.0.129:6010
|
# server-addr: 10.33.0.129:6010
|
||||||
server-addr: 10.102.192.31:6848
|
# server-addr: 10.102.192.31:6848
|
||||||
username: nacos
|
username: nacos
|
||||||
password: manhuoda@2023
|
password: manhuoda@2023
|
||||||
config:
|
config:
|
||||||
# server-addr: 127.0.0.1:8848
|
server-addr: 127.0.0.1:8848
|
||||||
# server-addr: 10.33.0.129:6010
|
# server-addr: 10.33.0.129:6010
|
||||||
server-addr: 10.102.192.31:6848
|
# server-addr: 10.102.192.31:6848
|
||||||
username: nacos
|
username: nacos
|
||||||
password: manhuoda@2023
|
password: manhuoda@2023
|
||||||
group: DEFAULT_GROUP # 默认分组就是DEFAULT_GROUP,如果使用默认分组可以不配置
|
group: DEFAULT_GROUP # 默认分组就是DEFAULT_GROUP,如果使用默认分组可以不配置
|
||||||
@@ -50,3 +50,7 @@ feign:
|
|||||||
mhd-third-party-service:
|
mhd-third-party-service:
|
||||||
connectTimeout: 10000
|
connectTimeout: 10000
|
||||||
readTimeout: 120000
|
readTimeout: 120000
|
||||||
|
#wechat:
|
||||||
|
# miniapp:
|
||||||
|
# appId: wxc9dd2810a77e4e30
|
||||||
|
# appSecret: 9354ff1215a82785ef14f2355fbf2185
|
||||||
+172
@@ -33,6 +33,7 @@ import com.mhd.bms.infrastructure.constant.BillLogsConstants;
|
|||||||
import com.mhd.bms.interfaces.assembler.billManage.BillManageAssembler;
|
import com.mhd.bms.interfaces.assembler.billManage.BillManageAssembler;
|
||||||
import com.mhd.bms.interfaces.dto.billManage.BillDetailDTO;
|
import com.mhd.bms.interfaces.dto.billManage.BillDetailDTO;
|
||||||
import com.mhd.bms.interfaces.dto.billManage.BillManageDTO;
|
import com.mhd.bms.interfaces.dto.billManage.BillManageDTO;
|
||||||
|
import com.mhd.bms.interfaces.dto.billManage.CustomerMonthBillVO;
|
||||||
import com.mhd.bms.interfaces.dto.billingStatement.BillingStatementDTO;
|
import com.mhd.bms.interfaces.dto.billingStatement.BillingStatementDTO;
|
||||||
import com.mhd.common.core.exception.ServiceException;
|
import com.mhd.common.core.exception.ServiceException;
|
||||||
import com.mhd.common.core.exception.digitalLogisticsException.DigitalLogisticsException;
|
import com.mhd.common.core.exception.digitalLogisticsException.DigitalLogisticsException;
|
||||||
@@ -138,6 +139,74 @@ public class BillManageApplicationService {
|
|||||||
String billNumber = billManagePO.getBillNumber(); // 获取账单编号
|
String billNumber = billManagePO.getBillNumber(); // 获取账单编号
|
||||||
// 原有 - 前端列表用,不变
|
// 原有 - 前端列表用,不变
|
||||||
List<BillDetail> billDetails = billDetailMapper.selectList(new LambdaQueryWrapper<BillDetail>().eq(BillDetail::getBillNumber, billNumber));
|
List<BillDetail> billDetails = billDetailMapper.selectList(new LambdaQueryWrapper<BillDetail>().eq(BillDetail::getBillNumber, billNumber));
|
||||||
|
BigDecimal totalTaxAmount = billDetails.stream().map(BillDetail::getTaxAmount).filter(Objects::nonNull).reduce(BigDecimal.ZERO, BigDecimal::add);
|
||||||
|
BigDecimal totalTaxFreeFee = billDetails.stream().map(BillDetail::getTaxFreeFee).filter(Objects::nonNull).reduce(BigDecimal.ZERO, BigDecimal::add);
|
||||||
|
billManagePO.setTaxAmount(totalTaxAmount);
|
||||||
|
billManagePO.setTaxFreeFee(totalTaxFreeFee);
|
||||||
|
billManagePO.setBillDetailList(billDetails);
|
||||||
|
// 新增 - 导出用,LEFT JOIN billing_statement 拿到费用科目
|
||||||
|
List<BillDetailPO> billDetailPOs = billDetailMapper.getDetailsByBillManageId(billManagePO.getBillManageId());
|
||||||
|
billManagePO.setBillDetailPOList(billDetailPOs);
|
||||||
|
}
|
||||||
|
return billManagePOS;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<BillManagePO> customerMonthlyReport(BillManageDO billManageDO) {
|
||||||
|
LoginUser loginUser = SecurityUtils.getLoginUser();
|
||||||
|
if (loginUser != null && loginUser.getUserPo() != null) {
|
||||||
|
Long userOrganizationId = loginUser.getUserPo().getOrganizationId();
|
||||||
|
Long frontendOrganizationId = billManageDO.getOrganizationId(); // 前端传递的 organizationId
|
||||||
|
|
||||||
|
// 当前登录用户的 organizationId 为 2827 时,可查全部组织数据;其他组织只能查自己
|
||||||
|
if (userOrganizationId != null && userOrganizationId == 2827L) {
|
||||||
|
// 南光组织(organizationId=2827):可以查询所有组织的数据
|
||||||
|
if (frontendOrganizationId != null) {
|
||||||
|
// 前端传递了 organizationId(包括2827或其他组织),使用前端传递的值进行过滤
|
||||||
|
billManageDO.setOrganizationId(frontendOrganizationId);
|
||||||
|
billManageDO.setTopOrganizationId(null); // 明确设置为 null,避免使用 topOrganizationId 条件
|
||||||
|
} else {
|
||||||
|
// 前端没有传递 organizationId,清空组织过滤条件,查询所有组织的数据
|
||||||
|
billManageDO.setOrganizationId(null);
|
||||||
|
billManageDO.setTopOrganizationId(null);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// 其他组织:设置organizationId,只查询当前组织的数据
|
||||||
|
// 如果前端传递了 organizationId,验证是否与当前登录用户的组织ID一致
|
||||||
|
if (frontendOrganizationId != null && userOrganizationId != null) {
|
||||||
|
// 前端传递了 organizationId,验证是否与当前登录用户的组织ID一致
|
||||||
|
if (!frontendOrganizationId.equals(userOrganizationId)) {
|
||||||
|
// 前端传递了其他组织的 organizationId,强制使用当前登录用户的组织ID,防止越权查询
|
||||||
|
billManageDO.setOrganizationId(userOrganizationId);
|
||||||
|
}
|
||||||
|
// 如果前端传递的 organizationId 与当前登录用户的组织ID一致,使用前端传递的值
|
||||||
|
} else {
|
||||||
|
// 前端没有传递 organizationId,使用当前登录用户的组织ID
|
||||||
|
if (userOrganizationId != null) {
|
||||||
|
billManageDO.setOrganizationId(userOrganizationId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 如果 organizationId 不为 null,则优先使用 organizationId,不使用 topOrganizationId
|
||||||
|
if (billManageDO.getOrganizationId() == null) {
|
||||||
|
Long topOrganizationId = loginUser.getUserPo().getTopOrganizationId();
|
||||||
|
if (topOrganizationId != null && topOrganizationId != 1) {
|
||||||
|
billManageDO.setTopOrganizationId(topOrganizationId);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// 对于非2827组织,必须设置 topOrganizationId=2827
|
||||||
|
billManageDO.setTopOrganizationId(2827L);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
List<BillManagePO> billManagePOS = billManageDomainService.customerMonthlyReport(billManageDO);
|
||||||
|
for (BillManagePO billManagePO : billManagePOS) {
|
||||||
|
String billNumber = billManagePO.getBillNumber(); // 获取账单编号
|
||||||
|
// 原有 - 前端列表用,不变
|
||||||
|
List<BillDetail> billDetails = billDetailMapper.selectList(new LambdaQueryWrapper<BillDetail>().eq(BillDetail::getBillNumber, billNumber));
|
||||||
|
BigDecimal totalTaxAmount = billDetails.stream().map(BillDetail::getTaxAmount).filter(Objects::nonNull).reduce(BigDecimal.ZERO, BigDecimal::add);
|
||||||
|
BigDecimal totalTaxFreeFee = billDetails.stream().map(BillDetail::getTaxFreeFee).filter(Objects::nonNull).reduce(BigDecimal.ZERO, BigDecimal::add);
|
||||||
|
billManagePO.setTaxAmount(totalTaxAmount);
|
||||||
|
billManagePO.setTaxFreeFee(totalTaxFreeFee);
|
||||||
|
|
||||||
billManagePO.setBillDetailList(billDetails);
|
billManagePO.setBillDetailList(billDetails);
|
||||||
// 新增 - 导出用,LEFT JOIN billing_statement 拿到费用科目
|
// 新增 - 导出用,LEFT JOIN billing_statement 拿到费用科目
|
||||||
List<BillDetailPO> billDetailPOs = billDetailMapper.getDetailsByBillManageId(billManagePO.getBillManageId());
|
List<BillDetailPO> billDetailPOs = billDetailMapper.getDetailsByBillManageId(billManagePO.getBillManageId());
|
||||||
@@ -184,6 +253,10 @@ public class BillManageApplicationService {
|
|||||||
return billManageDomainService.save(billingStatementDTO);
|
return billManageDomainService.save(billingStatementDTO);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Boolean saveBillJob(BillingStatementDTO billingStatementDTO) {
|
||||||
|
return billManageDomainService.saveJob(billingStatementDTO);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 批量删除账单管理
|
* 批量删除账单管理
|
||||||
*/
|
*/
|
||||||
@@ -287,6 +360,28 @@ public class BillManageApplicationService {
|
|||||||
return billManageDomainService.confirmBilling(billManageDO);
|
return billManageDomainService.confirmBilling(billManageDO);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Transactional
|
||||||
|
public Boolean confirmBillingJob(BillManageDTO billManageDTO) {
|
||||||
|
//确认账单:未收款状态之前都可以进行确认账单,跳过核账流程,直接到未收款状态
|
||||||
|
if(!StringUtils.isNotEmpty(billManageDTO.getBillManageIds())){
|
||||||
|
throw new ServiceException("账单管理ids不能为空");
|
||||||
|
}
|
||||||
|
//校验
|
||||||
|
Set<String> billManageIds = Stream.of(billManageDTO.getBillManageIds().split(",")).collect(Collectors.toSet());
|
||||||
|
BillManageDO billManageDO = new BillManageDO();
|
||||||
|
billManageDO.setBillManageIdSet(billManageIds);
|
||||||
|
List<BillManagePO> billManageList = billManageDomainService.queryList(billManageDO);
|
||||||
|
for (BillManagePO billManage : billManageList) {
|
||||||
|
if(billManage.getBillState() > 2){
|
||||||
|
throw new ServiceException("选中数据"+ billManage.getBillNumber() + "状态不可操作确认账单");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
billManageDO.setOrganizationId(billManageDTO.getOrganizationId());
|
||||||
|
billManageDO.setOrganizationName(billManageDTO.getOrganizationName());
|
||||||
|
billManageDO.setTopOrganizationId(billManageDTO.getTopOrganizationId());
|
||||||
|
return billManageDomainService.confirmBillingJob(billManageDO);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
public int editIsInvoice(String billNumber, Integer isInvoice, String invoiceId, String invoiceMakeTime,String applyNumber)
|
public int editIsInvoice(String billNumber, Integer isInvoice, String invoiceId, String invoiceMakeTime,String applyNumber)
|
||||||
{
|
{
|
||||||
@@ -621,6 +716,22 @@ public class BillManageApplicationService {
|
|||||||
return originalBill;
|
return originalBill;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 应收账单-红冲
|
||||||
|
*/
|
||||||
|
@Transactional
|
||||||
|
public Boolean redFlushBill(BillManageDTO billManageDTO) {
|
||||||
|
LoginUser loginUser = SecurityUtils.getLoginUser();
|
||||||
|
if (ObjectUtil.isNull(loginUser)) {
|
||||||
|
throw new DigitalLogisticsException(UserError.TIMEOUT);
|
||||||
|
}
|
||||||
|
if (StringUtils.isEmpty(billManageDTO.getBillManageIds())) {
|
||||||
|
throw new ServiceException("账单id不能为空");
|
||||||
|
}
|
||||||
|
return billManageDomainService.redFlushBill(billManageDTO);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 应收账单-客户确认
|
* 应收账单-客户确认
|
||||||
*/
|
*/
|
||||||
@@ -872,5 +983,66 @@ public class BillManageApplicationService {
|
|||||||
return flag && flagTwo;
|
return flag && flagTwo;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 客户每月账单分组查询
|
||||||
|
*/
|
||||||
|
public List<CustomerMonthBillVO> queryCustomerMonthBillList(BillManageDO billManageDO) {
|
||||||
|
LoginUser loginUser = SecurityUtils.getLoginUser();
|
||||||
|
if (loginUser != null && loginUser.getUserPo() != null) {
|
||||||
|
Long userOrganizationId = loginUser.getUserPo().getOrganizationId();
|
||||||
|
Long frontendOrganizationId = billManageDO.getOrganizationId();
|
||||||
|
|
||||||
|
if (userOrganizationId != null && userOrganizationId == 2827L) {
|
||||||
|
if (frontendOrganizationId != null) {
|
||||||
|
billManageDO.setOrganizationId(frontendOrganizationId);
|
||||||
|
billManageDO.setTopOrganizationId(null);
|
||||||
|
} else {
|
||||||
|
billManageDO.setOrganizationId(null);
|
||||||
|
billManageDO.setTopOrganizationId(null);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (frontendOrganizationId != null && userOrganizationId != null) {
|
||||||
|
if (!frontendOrganizationId.equals(userOrganizationId)) {
|
||||||
|
billManageDO.setOrganizationId(userOrganizationId);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (userOrganizationId != null) {
|
||||||
|
billManageDO.setOrganizationId(userOrganizationId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (billManageDO.getOrganizationId() == null) {
|
||||||
|
Long topOrganizationId = loginUser.getUserPo().getTopOrganizationId();
|
||||||
|
if (topOrganizationId != null && topOrganizationId != 1) {
|
||||||
|
billManageDO.setTopOrganizationId(topOrganizationId);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
billManageDO.setTopOrganizationId(2827L);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
List<CustomerMonthBillVO> list = billManageDomainService.queryCustomerMonthBillList(billManageDO);
|
||||||
|
|
||||||
|
// 计算付款状态
|
||||||
|
for (CustomerMonthBillVO vo : list) {
|
||||||
|
BigDecimal totalAmount = vo.getTotalBillAmount() != null ? vo.getTotalBillAmount() : BigDecimal.ZERO;
|
||||||
|
BigDecimal settledAmount = vo.getTotalSettledAmount() != null ? vo.getTotalSettledAmount() : BigDecimal.ZERO;
|
||||||
|
|
||||||
|
if (totalAmount.compareTo(BigDecimal.ZERO) == 0) {
|
||||||
|
vo.setPaymentStatus(3);
|
||||||
|
vo.setPaymentStatusName("已付款");
|
||||||
|
} else if (settledAmount.compareTo(BigDecimal.ZERO) == 0) {
|
||||||
|
vo.setPaymentStatus(1);
|
||||||
|
vo.setPaymentStatusName("未付款");
|
||||||
|
} else if (settledAmount.compareTo(totalAmount) >= 0) {
|
||||||
|
vo.setPaymentStatus(3);
|
||||||
|
vo.setPaymentStatusName("已付款");
|
||||||
|
} else {
|
||||||
|
vo.setPaymentStatus(2);
|
||||||
|
vo.setPaymentStatusName("部分付款");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return list;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
+1191
-38
File diff suppressed because it is too large
Load Diff
+121
@@ -2,12 +2,14 @@ package com.mhd.bms.application.server.receiptManage;
|
|||||||
|
|
||||||
import cn.hutool.core.util.ObjectUtil;
|
import cn.hutool.core.util.ObjectUtil;
|
||||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||||
|
import com.mhd.bms.domain.billManage.entity.BillManage;
|
||||||
import com.mhd.bms.domain.billManage.service.BillManageDomainService;
|
import com.mhd.bms.domain.billManage.service.BillManageDomainService;
|
||||||
import com.mhd.bms.domain.receiptManage.entity.ReceiptManage;
|
import com.mhd.bms.domain.receiptManage.entity.ReceiptManage;
|
||||||
import com.mhd.bms.domain.receiptManage.repository.po.ReceiptManagePO;
|
import com.mhd.bms.domain.receiptManage.repository.po.ReceiptManagePO;
|
||||||
import com.mhd.bms.domain.receiptManage.repository.todo.ReceiptManageDO;
|
import com.mhd.bms.domain.receiptManage.repository.todo.ReceiptManageDO;
|
||||||
import com.mhd.bms.domain.receiptManage.service.ReceiptManageDomainService;
|
import com.mhd.bms.domain.receiptManage.service.ReceiptManageDomainService;
|
||||||
import com.mhd.bms.infrastructure.utils.CheckPasswordUtil;
|
import com.mhd.bms.infrastructure.utils.CheckPasswordUtil;
|
||||||
|
import com.mhd.bms.interfaces.dto.receiptManage.ReceiptDetailDTO;
|
||||||
import com.mhd.bms.interfaces.dto.receiptManage.ReceiptManageDTO;
|
import com.mhd.bms.interfaces.dto.receiptManage.ReceiptManageDTO;
|
||||||
import com.mhd.common.core.exception.ServiceException;
|
import com.mhd.common.core.exception.ServiceException;
|
||||||
import com.mhd.common.core.exception.digitalLogisticsException.DigitalLogisticsException;
|
import com.mhd.common.core.exception.digitalLogisticsException.DigitalLogisticsException;
|
||||||
@@ -18,10 +20,13 @@ import lombok.extern.slf4j.Slf4j;
|
|||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
import org.springframework.transaction.interceptor.TransactionAspectSupport;
|
||||||
|
|
||||||
|
import java.math.BigDecimal;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
import java.util.stream.Stream;
|
import java.util.stream.Stream;
|
||||||
@@ -147,6 +152,122 @@ public class ReceiptManageApplicationService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 排队批量收款
|
||||||
|
* 接收集合按顺序逐笔处理,任意一笔收款失败则整体回滚
|
||||||
|
*/
|
||||||
|
@Transactional(rollbackFor = Exception.class)
|
||||||
|
public Boolean queueBatchCollection(List<ReceiptManageDO> receiptManageDOList) {
|
||||||
|
LoginUser loginUser = SecurityUtils.getLoginUser();
|
||||||
|
if (ObjectUtil.isNull(loginUser)) {
|
||||||
|
throw new DigitalLogisticsException(UserError.TIMEOUT);
|
||||||
|
}
|
||||||
|
int index = 1;
|
||||||
|
for (ReceiptManageDO receiptManageDO : receiptManageDOList) {
|
||||||
|
try {
|
||||||
|
//根据账单id查询账单当前金额数据,替换前端传的账单金额、已收金额、未收金额等(仅保留前端传的收款金额和优惠金额)
|
||||||
|
fillBillAmountFromBillManage(receiptManageDO);
|
||||||
|
Boolean flag = batchCollection(receiptManageDO);
|
||||||
|
if (!Boolean.TRUE.equals(flag)) {
|
||||||
|
throw new ServiceException("收款数据处理失败");
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
//自己try捕获的异常也要标记事务回滚,确保收款失败时全部回滚
|
||||||
|
TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
|
||||||
|
throw new ServiceException("第" + index + "笔收款失败:" + e.getMessage() + ",本次收款已全部回滚");
|
||||||
|
}
|
||||||
|
index++;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 排队批量收款-根据账单id查询账单当前金额,替换前端传的账单金额、已收金额、未收金额、剩余未收(仅保留前端传的收款金额和优惠金额)
|
||||||
|
*/
|
||||||
|
private void fillBillAmountFromBillManage(ReceiptManageDO receiptManageDO) {
|
||||||
|
List<ReceiptDetailDTO> receiptDetailDTOList = receiptManageDO.getReceiptDetailDTOList();
|
||||||
|
if (null == receiptDetailDTOList || receiptDetailDTOList.size() == 0) {
|
||||||
|
throw new ServiceException("费用结算明细不能为空");
|
||||||
|
}
|
||||||
|
//汇总收款明细的账单id并查询账单当前数据
|
||||||
|
Set<Long> billManageIdSet = receiptDetailDTOList.stream().map(ReceiptDetailDTO::getBillManageId).filter(ObjectUtil::isNotNull).collect(Collectors.toSet());
|
||||||
|
if (billManageIdSet.size() == 0) {
|
||||||
|
throw new ServiceException("收款账单不能为空");
|
||||||
|
}
|
||||||
|
LambdaQueryWrapper<BillManage> queryWrapper = new LambdaQueryWrapper<>();
|
||||||
|
queryWrapper.in(BillManage::getBillManageId, billManageIdSet);
|
||||||
|
queryWrapper.eq(BillManage::getDelFlag, 1);
|
||||||
|
List<BillManage> billManageList = billManageDomainService.queryListLambda(queryWrapper);
|
||||||
|
if (null == billManageList || billManageList.size() == 0) {
|
||||||
|
throw new ServiceException("账单信息未找到");
|
||||||
|
}
|
||||||
|
Map<Long, BillManage> billManageMap = billManageList.stream().collect(Collectors.toMap(BillManage::getBillManageId, billManage -> billManage, (oldValue, newValue) -> oldValue));
|
||||||
|
//汇总账单金额、已收金额、未收金额、收款金额、优惠金额
|
||||||
|
BigDecimal billAmount = BigDecimal.ZERO;
|
||||||
|
BigDecimal billAmountSettlement = BigDecimal.ZERO;
|
||||||
|
BigDecimal billAmountUnsettled = BigDecimal.ZERO;
|
||||||
|
BigDecimal collectedAmount = BigDecimal.ZERO;
|
||||||
|
BigDecimal collectedDiscount = BigDecimal.ZERO;
|
||||||
|
for (ReceiptDetailDTO receiptDetailDTO : receiptDetailDTOList) {
|
||||||
|
BillManage billManage = billManageMap.get(receiptDetailDTO.getBillManageId());
|
||||||
|
if (null == billManage) {
|
||||||
|
throw new ServiceException("账单" + receiptDetailDTO.getBillNumber() + "信息未找到,请刷新后重试");
|
||||||
|
}
|
||||||
|
//只取前端传的收款金额、优惠金额,为空按0处理
|
||||||
|
BigDecimal detailCollectedAmount = null == receiptDetailDTO.getCollectedAmount() ? BigDecimal.ZERO : receiptDetailDTO.getCollectedAmount();
|
||||||
|
BigDecimal detailCollectedDiscount = null == receiptDetailDTO.getCollectedDiscount() ? BigDecimal.ZERO : receiptDetailDTO.getCollectedDiscount();
|
||||||
|
//账单当前金额以数据库为准
|
||||||
|
BigDecimal detailBillAmount = billManage.getBillAmount();
|
||||||
|
BigDecimal detailBillAmountSettlement = billManage.getBillAmountSettlement();
|
||||||
|
BigDecimal detailBillAmountUnsettled = billManage.getBillAmountUnsettled();
|
||||||
|
//剩余未收金额 = 未收金额 - 收款金额 - 优惠金额
|
||||||
|
BigDecimal detailBillAmountUnsettledResidue = detailBillAmountUnsettled.subtract(detailCollectedAmount).subtract(detailCollectedDiscount);
|
||||||
|
if (detailBillAmountUnsettledResidue.compareTo(BigDecimal.ZERO) < 0) {
|
||||||
|
throw new ServiceException("账单" + billManage.getBillNumber() + "未收金额小于本次收款金额与优惠金额之和,无法完成收款,请刷新后重试");
|
||||||
|
}
|
||||||
|
//用数据库当前值替换前端传的账单金额、已收金额、未收金额、剩余未收
|
||||||
|
receiptDetailDTO.setBillAmount(detailBillAmount);
|
||||||
|
receiptDetailDTO.setBillAmountSettlement(detailBillAmountSettlement);
|
||||||
|
receiptDetailDTO.setBillAmountUnsettled(detailBillAmountUnsettled);
|
||||||
|
receiptDetailDTO.setBillAmountUnsettledResidue(detailBillAmountUnsettledResidue);
|
||||||
|
//累计收款单金额
|
||||||
|
billAmount = billAmount.add(detailBillAmount);
|
||||||
|
billAmountSettlement = billAmountSettlement.add(detailBillAmountSettlement);
|
||||||
|
billAmountUnsettled = billAmountUnsettled.add(detailBillAmountUnsettled);
|
||||||
|
collectedAmount = collectedAmount.add(detailCollectedAmount);
|
||||||
|
collectedDiscount = collectedDiscount.add(detailCollectedDiscount);
|
||||||
|
}
|
||||||
|
//收款单金额:账单金额、已收金额、未收金额取查询值汇总,收款金额、优惠金额取前端传值汇总
|
||||||
|
receiptManageDO.setBillAmount(billAmount);
|
||||||
|
receiptManageDO.setBillAmountSettlement(billAmountSettlement);
|
||||||
|
receiptManageDO.setBillAmountUnsettled(billAmountUnsettled);
|
||||||
|
receiptManageDO.setCollectedAmount(collectedAmount);
|
||||||
|
receiptManageDO.setCollectedDiscount(collectedDiscount);
|
||||||
|
//剩余未收 = 未收金额 - 收款金额 - 优惠金额
|
||||||
|
receiptManageDO.setUncollectedAmount(billAmountUnsettled.subtract(collectedAmount).subtract(collectedDiscount));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 撤销收款
|
||||||
|
*/
|
||||||
|
@Transactional
|
||||||
|
public Boolean cancelCollection(ReceiptManageDO receiptManageDO) {
|
||||||
|
LoginUser loginUser = SecurityUtils.getLoginUser();
|
||||||
|
if (ObjectUtil.isNull(loginUser)) {
|
||||||
|
throw new DigitalLogisticsException(UserError.TIMEOUT);
|
||||||
|
}
|
||||||
|
return receiptManageDomainService.cancelCollection(receiptManageDO);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 撤销收款-查询账单涉及的收款单id(用于加锁,防止并发撤销时收款单金额重算冲突)
|
||||||
|
*/
|
||||||
|
public Set<Long> queryCancelCollectionReceiptManageIds(String billManageIds) {
|
||||||
|
return receiptManageDomainService.queryReceiptManageIdsByBillManageIds(billManageIds);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 退款
|
* 退款
|
||||||
*/
|
*/
|
||||||
|
|||||||
+2
@@ -575,6 +575,8 @@ public class ReportFormApplicationService {
|
|||||||
//收款单
|
//收款单
|
||||||
QueryWrapper<ReceiptManage> queryWrapper = new QueryWrapper<>();
|
QueryWrapper<ReceiptManage> queryWrapper = new QueryWrapper<>();
|
||||||
queryWrapper.eq("top_organization_id", loginUser.getUserPo().getTopOrganizationId());
|
queryWrapper.eq("top_organization_id", loginUser.getUserPo().getTopOrganizationId());
|
||||||
|
//过滤已撤销(逻辑删除)的收款单
|
||||||
|
queryWrapper.eq("del_flag", 1);
|
||||||
for (int i = 0; i < formQueryParamsList.size(); i++) {
|
for (int i = 0; i < formQueryParamsList.size(); i++) {
|
||||||
FormQueryParams formQueryParams = formQueryParamsList.get(i);
|
FormQueryParams formQueryParams = formQueryParamsList.get(i);
|
||||||
FormQueryParams beforeFormQueryParams = null;
|
FormQueryParams beforeFormQueryParams = null;
|
||||||
|
|||||||
@@ -47,8 +47,8 @@ public class BillManage extends BaseVOEntity{
|
|||||||
@Excel(name = "账单类型", readConverterExp = "1=-应收,2-应付")
|
@Excel(name = "账单类型", readConverterExp = "1=-应收,2-应付")
|
||||||
private Integer billType;
|
private Integer billType;
|
||||||
|
|
||||||
@ApiModelProperty("账单状态(1-未确认,2-对账中,3-未收款/付款,4-部分收款/付款,5-已收款/付款,6-已作废,7-已退款)")
|
@ApiModelProperty("账单状态(1-未确认,2-对账中,3-未收款/付款,4-部分收款/付款,5-已收款/付款,6-已作废,7-已退款,8-红冲)")
|
||||||
@Excel(name = "账单状态", readConverterExp = "1=-未确认,2-对账中,3-未收款/付款,4-部分收款/付款,5-已收款/付款,6-已作废,7-已退款")
|
@Excel(name = "账单状态", readConverterExp = "1=-未确认,2-对账中,3-未收款/付款,4-部分收款/付款,5-已收款/付款,6-已作废,7-已退款,8-红冲")
|
||||||
private Integer billState;
|
private Integer billState;
|
||||||
|
|
||||||
@ApiModelProperty("账单流程节点(1-发起对账,2-客户确认,3-财务审核,4-收款/付款)")
|
@ApiModelProperty("账单流程节点(1-发起对账,2-客户确认,3-财务审核,4-收款/付款)")
|
||||||
|
|||||||
+9
@@ -4,6 +4,7 @@ import com.baomidou.mybatisplus.extension.service.IService;
|
|||||||
import com.mhd.bms.domain.billManage.entity.BillManage;
|
import com.mhd.bms.domain.billManage.entity.BillManage;
|
||||||
import com.mhd.bms.domain.billManage.repository.po.BillManagePO;
|
import com.mhd.bms.domain.billManage.repository.po.BillManagePO;
|
||||||
import com.mhd.bms.domain.billManage.repository.todo.BillManageDO;
|
import com.mhd.bms.domain.billManage.repository.todo.BillManageDO;
|
||||||
|
import com.mhd.bms.interfaces.dto.billManage.CustomerMonthBillVO;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
@@ -20,6 +21,14 @@ public interface IBillManageService extends IService<BillManage>
|
|||||||
*/
|
*/
|
||||||
public List<BillManagePO> queryList(BillManageDO billManageDO);
|
public List<BillManagePO> queryList(BillManageDO billManageDO);
|
||||||
|
|
||||||
|
|
||||||
|
public List<BillManagePO> customerMonthlyReport(BillManageDO billManageDO);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 客户每月账单分组查询
|
||||||
|
*/
|
||||||
|
public List<CustomerMonthBillVO> queryCustomerMonthBillList(BillManageDO billManageDO);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 新增账单管理
|
* 新增账单管理
|
||||||
*/
|
*/
|
||||||
|
|||||||
+8
@@ -5,6 +5,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
|||||||
import com.mhd.bms.domain.billManage.entity.BillManage;
|
import com.mhd.bms.domain.billManage.entity.BillManage;
|
||||||
import com.mhd.bms.domain.billManage.repository.po.BillManagePO;
|
import com.mhd.bms.domain.billManage.repository.po.BillManagePO;
|
||||||
import com.mhd.bms.domain.billManage.repository.todo.BillManageDO;
|
import com.mhd.bms.domain.billManage.repository.todo.BillManageDO;
|
||||||
|
import com.mhd.bms.interfaces.dto.billManage.CustomerMonthBillVO;
|
||||||
import org.apache.ibatis.annotations.Param;
|
import org.apache.ibatis.annotations.Param;
|
||||||
/**
|
/**
|
||||||
* 账单管理Mapper接口
|
* 账单管理Mapper接口
|
||||||
@@ -19,6 +20,13 @@ public interface BillManageMapper extends BaseMapper<BillManage>
|
|||||||
*/
|
*/
|
||||||
public List<BillManagePO> queryList(@Param("billManageDO") BillManageDO billManageDO);
|
public List<BillManagePO> queryList(@Param("billManageDO") BillManageDO billManageDO);
|
||||||
|
|
||||||
|
public List<BillManagePO> customerMonthlyReport(@Param("billManageDO") BillManageDO billManageDO);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 客户每月账单分组查询
|
||||||
|
*/
|
||||||
|
public List<CustomerMonthBillVO> queryCustomerMonthBillList(@Param("billManageDO") BillManageDO billManageDO);
|
||||||
|
|
||||||
String getInvoiceItemName(@Param("invoiceItemId") String invoiceItemId);
|
String getInvoiceItemName(@Param("invoiceItemId") String invoiceItemId);
|
||||||
|
|
||||||
String getInvoiceItemNcCode(@Param("invoiceItemId") String invoiceItemId);
|
String getInvoiceItemNcCode(@Param("invoiceItemId") String invoiceItemId);
|
||||||
|
|||||||
+14
@@ -31,6 +31,7 @@ import com.mhd.bms.domain.settlementCustomers.entity.SettlementCustomers;
|
|||||||
import com.mhd.bms.domain.settlementCustomers.repository.facade.ISettlementCustomersService;
|
import com.mhd.bms.domain.settlementCustomers.repository.facade.ISettlementCustomersService;
|
||||||
import com.mhd.bms.interfaces.dto.billManage.BillDetailDTO;
|
import com.mhd.bms.interfaces.dto.billManage.BillDetailDTO;
|
||||||
import com.mhd.bms.interfaces.dto.billManage.BillManageDTO;
|
import com.mhd.bms.interfaces.dto.billManage.BillManageDTO;
|
||||||
|
import com.mhd.bms.interfaces.dto.billManage.CustomerMonthBillVO;
|
||||||
import com.mhd.common.core.domain.dto.ReconciliationDTO;
|
import com.mhd.common.core.domain.dto.ReconciliationDTO;
|
||||||
import com.mhd.common.core.domain.dto.nc.*;
|
import com.mhd.common.core.domain.dto.nc.*;
|
||||||
import com.mhd.common.core.domain.entity.R;
|
import com.mhd.common.core.domain.entity.R;
|
||||||
@@ -126,6 +127,14 @@ public class BillManageImpl extends ServiceImpl<BillManageMapper, BillManage> im
|
|||||||
return billManageMapper.queryList(billManageDO);
|
return billManageMapper.queryList(billManageDO);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<BillManagePO> customerMonthlyReport(BillManageDO billManageDO)
|
||||||
|
{
|
||||||
|
return billManageMapper.customerMonthlyReport(billManageDO);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 新增账单管理
|
* 新增账单管理
|
||||||
*/
|
*/
|
||||||
@@ -1504,4 +1513,9 @@ public class BillManageImpl extends ServiceImpl<BillManageMapper, BillManage> im
|
|||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<CustomerMonthBillVO> queryCustomerMonthBillList(BillManageDO billManageDO) {
|
||||||
|
return billManageMapper.queryCustomerMonthBillList(billManageDO);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -2,6 +2,7 @@ package com.mhd.bms.domain.billManage.repository.po;
|
|||||||
|
|
||||||
import com.mhd.bms.domain.billManage.entity.BillDetail;
|
import com.mhd.bms.domain.billManage.entity.BillDetail;
|
||||||
import com.mhd.bms.domain.billingStatement.repository.po.BillingStatementPO;
|
import com.mhd.bms.domain.billingStatement.repository.po.BillingStatementPO;
|
||||||
|
import com.mhd.bms.domain.receiptManage.entity.ReceiptDetail;
|
||||||
import com.mhd.common.core.annotation.Excel;
|
import com.mhd.common.core.annotation.Excel;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
@@ -52,8 +53,8 @@ public class BillManagePO extends BaseVOEntity{
|
|||||||
@Excel(name = "账单类型", readConverterExp = "1=-应收,2-应付")
|
@Excel(name = "账单类型", readConverterExp = "1=-应收,2-应付")
|
||||||
private Integer billType;
|
private Integer billType;
|
||||||
|
|
||||||
@ApiModelProperty("账单状态(1-未确认,2-对账中,3-未收款/付款,4-部分收款/付款,5-已收款/付款,6-已作废,7-已退款)")
|
@ApiModelProperty("账单状态(1-未确认,2-对账中,3-未收款/付款,4-部分收款/付款,5-已收款/付款,6-已作废,7-已退款,8-红冲)")
|
||||||
@Excel(name = "账单状态", readConverterExp = "1=-未确认,2-对账中,3-未收款/付款,4-部分收款/付款,5-已收款/付款,6-已作废,7-已退款")
|
@Excel(name = "账单状态", readConverterExp = "1=-未确认,2-对账中,3-未收款/付款,4-部分收款/付款,5-已收款/付款,6-已作废,7-已退款,8-红冲")
|
||||||
private Integer billState;
|
private Integer billState;
|
||||||
|
|
||||||
@ApiModelProperty("账单流程节点(1-发起对账,2-客户确认,3-财务审核,4-收款/付款)")
|
@ApiModelProperty("账单流程节点(1-发起对账,2-客户确认,3-财务审核,4-收款/付款)")
|
||||||
@@ -262,9 +263,12 @@ public class BillManagePO extends BaseVOEntity{
|
|||||||
@ApiModelProperty("收款帐户名称")
|
@ApiModelProperty("收款帐户名称")
|
||||||
private String paymentAccountName;
|
private String paymentAccountName;
|
||||||
private List<BillDetail> billDetailList;
|
private List<BillDetail> billDetailList;
|
||||||
|
private List<ReceiptDetail> receiptDetailList;
|
||||||
|
|
||||||
@ApiModelProperty("最近收款时间")
|
@ApiModelProperty("最近收款时间")
|
||||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
|
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
|
||||||
@Excel(name = "最近收款时间", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss")
|
@Excel(name = "最近收款时间", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss")
|
||||||
private Date collectionTime;
|
private Date collectionTime;
|
||||||
|
@ApiModelProperty("合同编码")
|
||||||
|
private String contractNumbers;
|
||||||
}
|
}
|
||||||
+5
-2
@@ -47,8 +47,8 @@ public class BillManageDO extends BaseVOEntity{
|
|||||||
@Excel(name = "账单类型", readConverterExp = "1=-应收,2-应付")
|
@Excel(name = "账单类型", readConverterExp = "1=-应收,2-应付")
|
||||||
private Integer billType;
|
private Integer billType;
|
||||||
|
|
||||||
@ApiModelProperty("账单状态(1-未确认,2-对账中,3-未收款/付款,4-部分收款/付款,5-已收款/付款,6-已作废,7-已退款)")
|
@ApiModelProperty("账单状态(1-未确认,2-对账中,3-未收款/付款,4-部分收款/付款,5-已收款/付款,6-已作废,7-已退款,8-红冲)")
|
||||||
@Excel(name = "账单状态", readConverterExp = "1=-未确认,2-对账中,3-未收款/付款,4-部分收款/付款,5-已收款/付款,6-已作废,7-已退款")
|
@Excel(name = "账单状态", readConverterExp = "1=-未确认,2-对账中,3-未收款/付款,4-部分收款/付款,5-已收款/付款,6-已作废,7-已退款,8-红冲")
|
||||||
private Integer billState;
|
private Integer billState;
|
||||||
|
|
||||||
@ApiModelProperty("账单流程节点(1-发起对账,2-客户确认,3-财务审核,4-收款/付款)")
|
@ApiModelProperty("账单流程节点(1-发起对账,2-客户确认,3-财务审核,4-收款/付款)")
|
||||||
@@ -266,4 +266,7 @@ public class BillManageDO extends BaseVOEntity{
|
|||||||
private String paymentAccountName;
|
private String paymentAccountName;
|
||||||
@ApiModelProperty("业务员ID")
|
@ApiModelProperty("业务员ID")
|
||||||
private String salesmanId;
|
private String salesmanId;
|
||||||
|
|
||||||
|
@ApiModelProperty("账单月份(yyyy-MM,按创建时间月份筛选,用于客户月账单分组查询)")
|
||||||
|
private String billMonth;
|
||||||
}
|
}
|
||||||
+471
@@ -12,7 +12,9 @@ import com.mhd.bms.domain.billManage.repository.facade.IBillManageService;
|
|||||||
import com.mhd.bms.domain.billManage.repository.po.BillManagePO;
|
import com.mhd.bms.domain.billManage.repository.po.BillManagePO;
|
||||||
import com.mhd.bms.domain.billManage.repository.todo.BillDetailDO;
|
import com.mhd.bms.domain.billManage.repository.todo.BillDetailDO;
|
||||||
import com.mhd.bms.domain.billManage.repository.todo.BillManageDO;
|
import com.mhd.bms.domain.billManage.repository.todo.BillManageDO;
|
||||||
|
import com.mhd.bms.interfaces.dto.billManage.CustomerMonthBillVO;
|
||||||
import com.mhd.bms.domain.billOperationLog.entity.BillOperationLog;
|
import com.mhd.bms.domain.billOperationLog.entity.BillOperationLog;
|
||||||
|
import com.mhd.bms.domain.billOperationLog.repository.po.BillOperationLogPO;
|
||||||
import com.mhd.bms.domain.billOperationLog.repository.todo.BillOperationLogDO;
|
import com.mhd.bms.domain.billOperationLog.repository.todo.BillOperationLogDO;
|
||||||
import com.mhd.bms.domain.billOperationLog.service.BillOperationLogDomainService;
|
import com.mhd.bms.domain.billOperationLog.service.BillOperationLogDomainService;
|
||||||
import com.mhd.bms.domain.billingStatement.entity.BillingStatement;
|
import com.mhd.bms.domain.billingStatement.entity.BillingStatement;
|
||||||
@@ -44,6 +46,7 @@ import com.mhd.common.security.utils.SecurityUtils;
|
|||||||
import com.mhd.system.api.SystemServiceFeign;
|
import com.mhd.system.api.SystemServiceFeign;
|
||||||
import com.mhd.system.api.model.LoginUser;
|
import com.mhd.system.api.model.LoginUser;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.beans.BeanUtils;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
@@ -85,6 +88,10 @@ public class BillManageDomainService {
|
|||||||
return billManageService.queryList(billManageDO);
|
return billManageService.queryList(billManageDO);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public List<BillManagePO> customerMonthlyReport(BillManageDO billManageDO) {
|
||||||
|
return billManageService.customerMonthlyReport(billManageDO);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 新增账单管理
|
* 新增账单管理
|
||||||
@@ -233,6 +240,124 @@ public class BillManageDomainService {
|
|||||||
return flag && flagTwo && three;
|
return flag && flagTwo && three;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Boolean saveBillJob(List<BillingStatementPO> billingStatementPOS,String billingRemark,Date billCreateTime,BillingStatementDTO billingStatementDTO) {
|
||||||
|
// LoginUser loginUser = SecurityUtils.getLoginUser();
|
||||||
|
// if (ObjectUtil.isNull(loginUser)) {
|
||||||
|
//// throw new DigitalLogisticsException(UserError.TIMEOUT);
|
||||||
|
// }
|
||||||
|
BigDecimal taxAmount = billingStatementDTO.getTaxAmount(); // 获取税额
|
||||||
|
Double taxRate = billingStatementDTO.getTaxRate(); // 获取税率
|
||||||
|
BigDecimal taxFreeFee = billingStatementDTO.getTaxFreeFee(); // 获取税免金额
|
||||||
|
String settlementCurrency = billingStatementDTO.getSettlementCurrency(); // 获取结算币种
|
||||||
|
BillManage billManage = new BillManage();
|
||||||
|
billManage.setTaxAmount(taxAmount);
|
||||||
|
billManage.setTaxRate(taxRate);
|
||||||
|
billManage.setTaxFreeFee(taxFreeFee);
|
||||||
|
billManage.setSettlementCurrency(settlementCurrency);
|
||||||
|
// billManage.setCreateBy(loginUser.getUserPo().getUserId());
|
||||||
|
// billManage.setCreateByName(loginUser.getUserPo().getUserName());
|
||||||
|
billManage.setCreateTime(billCreateTime==null ? new Date():billCreateTime);
|
||||||
|
billManage.setDelFlag(1);
|
||||||
|
billManage.setBillNumber(OrderSequence.getOrderCode("ZD"));
|
||||||
|
billManage.setTopOrganizationId(billingStatementDTO.getTopOrganizationId());
|
||||||
|
billManage.setOrganizationId(billingStatementDTO.getOrganizationId());
|
||||||
|
billManage.setOrganizationName(billingStatementDTO.getOrganizationName());
|
||||||
|
billManage.setBillType(billingStatementPOS.get(0).getAccountExpenseType());
|
||||||
|
billManage.setBelongModule(billingStatementPOS.get(0).getBelongModule());
|
||||||
|
billManage.setBelongModuleCode(billingStatementPOS.get(0).getBelongModuleCode());
|
||||||
|
billManage.setSettlementCustomersId(billingStatementPOS.get(0).getSettlementCustomersId());
|
||||||
|
billManage.setSettlementEntity(billingStatementPOS.get(0).getSettlementEntity());
|
||||||
|
billManage.setSettlementCustomersCode(billingStatementPOS.get(0).getSettlementCustomersCode());
|
||||||
|
billManage.setSalesmanId(billingStatementPOS.get(0).getSalesmanId());
|
||||||
|
billManage.setSalesmanName(billingStatementPOS.get(0).getSalesmanName());
|
||||||
|
billManage.setPaymentAccountId(billingStatementPOS.get(0).getPaymentAccountId());
|
||||||
|
billManage.setPaymentAccountName(billingStatementPOS.get(0).getPaymentAccountName());
|
||||||
|
billManage.setBillRemark(billingRemark);
|
||||||
|
//查询结算对象信息
|
||||||
|
SettlementCustomersPO settlementCustomersPO = settlementCustomersDomainService.getInfo(billingStatementPOS.get(0).getSettlementCustomersId());
|
||||||
|
if(null == settlementCustomersPO){
|
||||||
|
throw new ServiceException("结算对象信息未找到");
|
||||||
|
}
|
||||||
|
billManage.setSettlementMethod(settlementCustomersPO.getSettlementMethod());
|
||||||
|
billManage.setSettlementMethodCode(settlementCustomersPO.getSettlementMethodCode());
|
||||||
|
// if(settlementCustomersPO.getMainRole()==1){
|
||||||
|
// billManage.setBillType(1);
|
||||||
|
// }else {
|
||||||
|
// billManage.setBillType(2);
|
||||||
|
// }
|
||||||
|
//计算所有流水列表中的最早周期开始时间和晚周期结束时间
|
||||||
|
List<Date> cycleBeginTimeSet = billingStatementPOS.stream().map(BillingStatementPO::getCycleBeginTime).collect(Collectors.toList());
|
||||||
|
List<Date> cycleEndTimeSet = billingStatementPOS.stream().map(BillingStatementPO::getCycleEndTime).collect(Collectors.toList());
|
||||||
|
cycleBeginTimeSet.removeIf(Objects::isNull);
|
||||||
|
cycleEndTimeSet.removeIf(Objects::isNull);
|
||||||
|
if(cycleBeginTimeSet.size()>0){
|
||||||
|
billManage.setCycleBeginTime(Collections.min(cycleBeginTimeSet));
|
||||||
|
}
|
||||||
|
if(cycleEndTimeSet.size()>0){
|
||||||
|
billManage.setCycleEndTime(Collections.max(cycleEndTimeSet));
|
||||||
|
}
|
||||||
|
//将所有的流水金额相加
|
||||||
|
billManage.setBillTotalAmount(billingStatementPOS.stream().map(BillingStatementPO::getBillingAmount).reduce(BigDecimal.ZERO, BigDecimal::add));
|
||||||
|
billManage.setBillAmount(billManage.getBillTotalAmount());
|
||||||
|
billManage.setBillAmountUnsettled(billManage.getBillTotalAmount());
|
||||||
|
boolean flag = billManageService.save(billManage);
|
||||||
|
billingStatementDTO.setBillManageId(billManage.getBillManageId());
|
||||||
|
List<BillDetail> billDetailList = new ArrayList<>();
|
||||||
|
for (BillingStatementPO billingStatementPO : billingStatementPOS) {
|
||||||
|
//生成对账单详情
|
||||||
|
BillDetail billDetail = new BillDetail();
|
||||||
|
billDetail.setTopOrganizationId(billingStatementPO.getTopOrganizationId());
|
||||||
|
billDetail.setOrganizationId(billingStatementPO.getOrganizationId());
|
||||||
|
billDetail.setOrganizationName(billingStatementPO.getOrganizationName());
|
||||||
|
billDetail.setCreateBy(billManage.getCreateBy());
|
||||||
|
billDetail.setCreateByName(billManage.getCreateByName());
|
||||||
|
billDetail.setCreateTime(billManage.getCreateTime());
|
||||||
|
billDetail.setBillManageId(billManage.getBillManageId());
|
||||||
|
billDetail.setBillNumber(billManage.getBillNumber());
|
||||||
|
billDetail.setBillingStatementId(billingStatementPO.getBillingStatementId());
|
||||||
|
billDetail.setBillingFlow(billingStatementPO.getBillingFlow());
|
||||||
|
billDetail.setBillingTotalAmount(billingStatementPO.getBillingAmount());
|
||||||
|
billDetail.setBillingAmount(billingStatementPO.getBillingAmount());
|
||||||
|
billDetail.setBillType(billingStatementPO.getAccountExpenseType());
|
||||||
|
billDetail.setTaxAmount(billingStatementPO.getTaxAmount());
|
||||||
|
billDetail.setTaxRate(billingStatementPO.getTaxRate());
|
||||||
|
billDetail.setTaxFreeFee(billingStatementPO.getTaxFreeFee());
|
||||||
|
billDetail.setSettlementCurrency(billingStatementPO.getSettlementCurrency());
|
||||||
|
billDetail.setFeeType(billingStatementPO.getFeeType());
|
||||||
|
billDetail.setInvoiceItem(billingStatementPO.getInvoiceItem());
|
||||||
|
billDetail.setInvoiceItemName(billingStatementPO.getInvoiceItemName());
|
||||||
|
billDetailList.add(billDetail);
|
||||||
|
}
|
||||||
|
boolean flagTwo = billDetailDomainService.insertBatch(billDetailList);
|
||||||
|
//保存账单操作记录
|
||||||
|
BillOperationLogDO billOperationLogDO = new BillOperationLogDO();
|
||||||
|
billOperationLogDO.setBillManageId(billManage.getBillManageId());
|
||||||
|
billOperationLogDO.setOperationInfo(StringUtils.format(BillLogsConstants.create_bill_text, billManage.getBillNumber(), billManage.getBillTotalAmount()));
|
||||||
|
billOperationLogDO.setOperationType(1);
|
||||||
|
billOperationLogDO.setCreateByName(billManage.getCreateByName());
|
||||||
|
billOperationLogDO.setUpdateByName(billManage.getUpdateByName());
|
||||||
|
billOperationLogDO.setCreateTime(new Date());
|
||||||
|
billOperationLogDO.setUpdateTime(new Date());
|
||||||
|
billOperationLogDO.setDelFlag(1);
|
||||||
|
billOperationLogDO.setCreateBy(billManage.getCreateBy());
|
||||||
|
billOperationLogDO.setUpdateBy(billManage.getUpdateBy());
|
||||||
|
billOperationLogDO.setTopOrganizationId(billManage.getTopOrganizationId());
|
||||||
|
billOperationLogDO.setOrganizationId(billManage.getOrganizationId());
|
||||||
|
billOperationLogDO.setOrganizationName(billManage.getOrganizationName());
|
||||||
|
|
||||||
|
boolean three = billOperationLogDomainService.saveBillOperationLogJob(billOperationLogDO);
|
||||||
|
//修改流水记录
|
||||||
|
/*billingStatementDTO.getBillingStatementList().forEach(billingStatementADDVO -> {
|
||||||
|
billingStatementMapper.update(null,
|
||||||
|
new LambdaUpdateWrapper<BillingStatement>().set(BillingStatement::getTaxAmount,billingStatementADDVO.getTaxAmount())
|
||||||
|
.set(BillingStatement::getTaxRate,billingStatementADDVO.getTaxRate())
|
||||||
|
.set(BillingStatement::getTaxFreeFee,billingStatementADDVO.getTaxFreeFee())
|
||||||
|
.set(BillingStatement::getSettlementCurrency,billingStatementADDVO.getSettlementCurrency())
|
||||||
|
.eq(BillingStatement::getBillingStatementId,billingStatementADDVO.getBillingStatementId()));
|
||||||
|
});*/
|
||||||
|
return flag && flagTwo && three;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 保存账单
|
* 保存账单
|
||||||
* @param billingStatementDTO
|
* @param billingStatementDTO
|
||||||
@@ -296,6 +421,64 @@ public class BillManageDomainService {
|
|||||||
return saveBill(distinctList,billingStatementDTO.getBillingRemark(),billingStatementDTO.getBillCreateTime(),billingStatementDTO);
|
return saveBill(distinctList,billingStatementDTO.getBillingRemark(),billingStatementDTO.getBillCreateTime(),billingStatementDTO);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Boolean saveJob(BillingStatementDTO billingStatementDTO) {
|
||||||
|
LoginUser loginUser = SecurityUtils.getLoginUser();
|
||||||
|
if (ObjectUtil.isNull(loginUser)) {
|
||||||
|
// throw new DigitalLogisticsException(UserError.TIMEOUT);
|
||||||
|
}
|
||||||
|
//根据前端传的流水id,查询计费流水信息列表
|
||||||
|
Set<String> billingSet = Stream.of(billingStatementDTO.getBillingStatementIds().split(",")).collect(Collectors.toSet());
|
||||||
|
BillingStatementDO billingStatementDO = new BillingStatementDO();
|
||||||
|
billingStatementDO.setBillingStatementIdSet(billingSet);
|
||||||
|
List<BillingStatementPO> billingStatementPOS = billingStatementDomainService.queryList(billingStatementDO);
|
||||||
|
|
||||||
|
//获取最新一条的业务员信息
|
||||||
|
String salesmanId = null;
|
||||||
|
String salesmanName = null;
|
||||||
|
if (billingStatementPOS != null && !billingStatementPOS.isEmpty()) {
|
||||||
|
billingStatementPOS.sort((a, b) -> {
|
||||||
|
if (a.getCreateTime() == null && b.getCreateTime() == null) return 0;
|
||||||
|
if (a.getCreateTime() == null) return 1;
|
||||||
|
if (b.getCreateTime() == null) return -1;
|
||||||
|
return b.getCreateTime().compareTo(a.getCreateTime());
|
||||||
|
});
|
||||||
|
salesmanId = billingStatementPOS.get(0).getSalesmanId();
|
||||||
|
salesmanName = billingStatementPOS.get(0).getSalesmanName();
|
||||||
|
}
|
||||||
|
|
||||||
|
List<BillingStatementADDVO> billingStatementList = billingStatementDTO.getBillingStatementList();
|
||||||
|
for (BillingStatementPO billingStatementPO : billingStatementPOS) {
|
||||||
|
String billingStatementId = billingStatementPO.getBillingStatementId() == null ? "" : String.valueOf(billingStatementPO.getBillingStatementId());
|
||||||
|
BillingStatementADDVO billingStatementADDVO = billingStatementList.stream().filter(billingStatementADDVO1 -> billingStatementADDVO1.getBillingStatementId().contains(billingStatementId)).findFirst().orElse(null);
|
||||||
|
billingStatementPO.setTaxAmount(billingStatementADDVO.getTaxAmount()); // 设置税额
|
||||||
|
billingStatementPO.setTaxRate(billingStatementADDVO.getTaxRate()); // 设置税率
|
||||||
|
billingStatementPO.setTaxFreeFee(billingStatementADDVO.getTaxFreeFee()); // 设置税免金额
|
||||||
|
billingStatementPO.setSettlementCurrency(billingStatementADDVO.getSettlementCurrency());//设置结算币种
|
||||||
|
billingStatementPO.setFeeType(billingStatementADDVO.getFeeType());
|
||||||
|
billingStatementPO.setInvoiceItem(billingStatementADDVO.getInvoiceItem());
|
||||||
|
billingStatementPO.setInvoiceItemName(billingStatementADDVO.getInvoiceItemName());
|
||||||
|
billingStatementPO.setBillingAmount(billingStatementADDVO.getBillingAmount());
|
||||||
|
billingStatementPO.setBillingStatementIdStr(billingStatementADDVO.getBillingStatementId());
|
||||||
|
if (salesmanName != null && !salesmanName.isEmpty() && salesmanId != null && !salesmanId.isEmpty()) {
|
||||||
|
billingStatementPO.setSalesmanId(salesmanId);
|
||||||
|
billingStatementPO.setSalesmanName(salesmanName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
List<BillingStatementPO> distinctList = billingStatementPOS.stream()
|
||||||
|
.filter(Objects::nonNull)
|
||||||
|
.collect(Collectors.toMap(
|
||||||
|
BillingStatementPO::getBillingStatementIdStr, // key:去重字段
|
||||||
|
po -> po, // value:对象本身
|
||||||
|
(existing, replacement) -> existing // 重复时保留第一个
|
||||||
|
))
|
||||||
|
.values()
|
||||||
|
.stream().collect(Collectors.toList());
|
||||||
|
if(billingStatementPOS==null || billingStatementPOS.size()==0){
|
||||||
|
throw new ServiceException("所选流水信息未找到");
|
||||||
|
}
|
||||||
|
return saveBillJob(distinctList,billingStatementDTO.getBillingRemark(),billingStatementDTO.getBillCreateTime(),billingStatementDTO);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
public List<BillManage> queryListLambda(LambdaQueryWrapper<BillManage> queryWrapper) {
|
public List<BillManage> queryListLambda(LambdaQueryWrapper<BillManage> queryWrapper) {
|
||||||
return billManageService.list(queryWrapper);
|
return billManageService.list(queryWrapper);
|
||||||
@@ -378,6 +561,32 @@ public class BillManageDomainService {
|
|||||||
return flag && three;
|
return flag && three;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Boolean confirmBillingJob(BillManageDO billManageDO) {
|
||||||
|
//直接修改状态到未收款3状态
|
||||||
|
// LoginUser loginUser = SecurityUtils.getLoginUser();
|
||||||
|
// if (ObjectUtil.isNull(loginUser)) {
|
||||||
|
// throw new DigitalLogisticsException(UserError.TIMEOUT);
|
||||||
|
// }
|
||||||
|
LambdaUpdateWrapper<BillManage> updateWrapper = new LambdaUpdateWrapper<>();
|
||||||
|
updateWrapper.in(BillManage::getBillManageId,billManageDO.getBillManageIdSet())
|
||||||
|
.set(BillManage::getBillStep,4)
|
||||||
|
.set(BillManage::getBillState,3)
|
||||||
|
// .set(BillManage::getUpdateBy,loginUser.getUserPo().getUserId())
|
||||||
|
// .set(BillManage::getUpdateByName,loginUser.getUserPo().getUserName())
|
||||||
|
.set(BillManage::getUpdateTime,new Date());
|
||||||
|
boolean flag = billManageService.update(updateWrapper);
|
||||||
|
//保存账单操作记录
|
||||||
|
BillOperationLogDO billOperationLogDO = new BillOperationLogDO();
|
||||||
|
billOperationLogDO.setBillManageIdSet(billManageDO.getBillManageIdSet());
|
||||||
|
billOperationLogDO.setOperationInfo(BillLogsConstants.confirm_bill_text);
|
||||||
|
billOperationLogDO.setOperationType(3);
|
||||||
|
billOperationLogDO.setOrganizationId(billManageDO.getOrganizationId());
|
||||||
|
billOperationLogDO.setOrganizationName(billManageDO.getOrganizationName());
|
||||||
|
billOperationLogDO.setTopOrganizationId(billManageDO.getTopOrganizationId());
|
||||||
|
boolean three = billOperationLogDomainService.saveBillOperationLogBatchJob(billOperationLogDO);
|
||||||
|
return flag && three;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
public int editIsInvoice(String billNumber, Integer isInvoice, String invoiceId, String invoiceMakeTime,String applyNumber)
|
public int editIsInvoice(String billNumber, Integer isInvoice, String invoiceId, String invoiceMakeTime,String applyNumber)
|
||||||
{
|
{
|
||||||
@@ -504,6 +713,261 @@ public class BillManageDomainService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 撤销收款:账单恢复为收款为0状态并保存撤销收款操作日志
|
||||||
|
*/
|
||||||
|
public Boolean cancelCollectionInfo(List<ReceiptDetail> receiptDetails) {
|
||||||
|
LoginUser loginUser = SecurityUtils.getLoginUser();
|
||||||
|
if (ObjectUtil.isNull(loginUser)) {
|
||||||
|
throw new DigitalLogisticsException(UserError.TIMEOUT);
|
||||||
|
}
|
||||||
|
//按账单分组收款明细(一个账单可能对应多个收款单)
|
||||||
|
Map<Long, List<ReceiptDetail>> billDetailMap = receiptDetails.stream().collect(Collectors.groupingBy(ReceiptDetail::getBillManageId));
|
||||||
|
LambdaQueryWrapper<BillManage> queryWrapper = new LambdaQueryWrapper<>();
|
||||||
|
queryWrapper.in(BillManage::getBillManageId,billDetailMap.keySet());
|
||||||
|
List<BillManage> billManageList = billManageService.list(queryWrapper);
|
||||||
|
if(billManageList == null || billManageList.size()==0){
|
||||||
|
throw new ServiceException("账单信息未找到");
|
||||||
|
}
|
||||||
|
List<BillManage> billManageListSave = new ArrayList<>();
|
||||||
|
List<BillOperationLog> billOperationLogSave = new ArrayList<>();
|
||||||
|
for (BillManage billManage : billManageList) {
|
||||||
|
List<ReceiptDetail> receiptDetailList = billDetailMap.get(billManage.getBillManageId());
|
||||||
|
if(null == receiptDetailList || receiptDetailList.size() == 0){
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
BillManage billManageSave = new BillManage();
|
||||||
|
billManageSave.setBillManageId(billManage.getBillManageId());
|
||||||
|
//账单恢复为收款为0状态
|
||||||
|
billManageSave.setBillAmountSettlement(BigDecimal.ZERO);
|
||||||
|
billManageSave.setBillAmountUnsettled(billManage.getBillAmount());
|
||||||
|
billManageSave.setActualReceivedAmount(BigDecimal.ZERO);
|
||||||
|
billManageSave.setSettlementDiscountsAmount(BigDecimal.ZERO);
|
||||||
|
billManageSave.setBillState(3);
|
||||||
|
billManageSave.setUpdateBy(loginUser.getUserPo().getUserId());
|
||||||
|
billManageSave.setUpdateByName(loginUser.getUserPo().getUserName());
|
||||||
|
billManageSave.setUpdateTime(new Date());
|
||||||
|
billManageListSave.add(billManageSave);
|
||||||
|
//汇总该账单本次撤销的收款金额与收款单号
|
||||||
|
BigDecimal collectedDiscount = receiptDetailList.stream().map(info -> info.getCollectedDiscount() == null ? BigDecimal.ZERO : info.getCollectedDiscount()).reduce(BigDecimal.ZERO, BigDecimal::add);
|
||||||
|
BigDecimal collectedAmount = receiptDetailList.stream().map(info -> info.getCollectedAmount() == null ? BigDecimal.ZERO : info.getCollectedAmount()).reduce(BigDecimal.ZERO, BigDecimal::add);
|
||||||
|
BigDecimal all = collectedAmount.add(collectedDiscount);
|
||||||
|
String collectionNums = receiptDetailList.stream().map(ReceiptDetail::getCollectionNum).filter(StringUtils::isNotEmpty).distinct().collect(Collectors.joining(","));
|
||||||
|
//保存账单操作记录
|
||||||
|
BillOperationLog billOperationLog = new BillOperationLog();
|
||||||
|
billOperationLog.setBillManageId(billManage.getBillManageId());
|
||||||
|
billOperationLog.setOperationInfo(StringUtils.format(BillLogsConstants.cancel_collection_bill_text,collectionNums,all,collectedAmount,collectedDiscount));
|
||||||
|
billOperationLog.setOperationType(12);
|
||||||
|
billOperationLog.setDelFlag(1);
|
||||||
|
billOperationLogSave.add(billOperationLog);
|
||||||
|
}
|
||||||
|
Boolean three = billOperationLogDomainService.insertBatch(billOperationLogSave);
|
||||||
|
Boolean flag = billManageService.updateBatchById(billManageListSave);
|
||||||
|
return flag && three;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 应收账单红冲:生成金额为负数的红冲账单对冲原账单,不操作收款单等数据(支持批量)
|
||||||
|
*/
|
||||||
|
public Boolean redFlushBill(BillManageDTO billManageDTO) {
|
||||||
|
LoginUser loginUser = SecurityUtils.getLoginUser();
|
||||||
|
if (ObjectUtil.isNull(loginUser)) {
|
||||||
|
throw new DigitalLogisticsException(UserError.TIMEOUT);
|
||||||
|
}
|
||||||
|
if (StringUtils.isEmpty(billManageDTO.getBillManageIds())) {
|
||||||
|
throw new ServiceException("账单id不能为空");
|
||||||
|
}
|
||||||
|
Set<Long> billManageIdSet = Stream.of(billManageDTO.getBillManageIds().split(",")).filter(StringUtils::isNotEmpty).map(String::trim).map(Long::valueOf).collect(Collectors.toSet());
|
||||||
|
if (billManageIdSet.size() == 0) {
|
||||||
|
throw new ServiceException("账单id不能为空");
|
||||||
|
}
|
||||||
|
//查询账单信息
|
||||||
|
LambdaQueryWrapper<BillManage> queryWrapperBill = new LambdaQueryWrapper<>();
|
||||||
|
queryWrapperBill.in(BillManage::getBillManageId, billManageIdSet);
|
||||||
|
queryWrapperBill.eq(BillManage::getDelFlag, 1);
|
||||||
|
List<BillManage> billManageList = billManageService.list(queryWrapperBill);
|
||||||
|
if (null == billManageList || billManageList.size() == 0) {
|
||||||
|
throw new ServiceException("账单信息未找到");
|
||||||
|
}
|
||||||
|
if (billManageList.size() != billManageIdSet.size()) {
|
||||||
|
throw new ServiceException("部分账单信息未找到,请刷新后重试");
|
||||||
|
}
|
||||||
|
//逐个账单红冲,任一账单校验不通过时事务整体回滚
|
||||||
|
Boolean flag = true;
|
||||||
|
for (BillManage originalBill : billManageList) {
|
||||||
|
flag = redFlushSingleBill(originalBill, billManageDTO.getRedFlushRemark(), loginUser) && flag;
|
||||||
|
}
|
||||||
|
return flag;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 红冲单个账单:生成金额为负数的红冲账单对冲原账单,同步镜像计费流水与账单明细
|
||||||
|
*/
|
||||||
|
private Boolean redFlushSingleBill(BillManage originalBill, String redFlushRemark, LoginUser loginUser) {
|
||||||
|
if (ObjectUtil.equal(originalBill.getBillType(), 2)) {
|
||||||
|
throw new ServiceException("账单" + originalBill.getBillNumber() + "为付款账单,仅支持应收账单红冲");
|
||||||
|
}
|
||||||
|
if (!ObjectUtil.equal(originalBill.getBillState(), 5)) {
|
||||||
|
throw new ServiceException("账单" + originalBill.getBillNumber() + "不是已收款状态,仅已收款状态的账单可以红冲,请刷新后重试");
|
||||||
|
}
|
||||||
|
//校验账单是否已红冲,避免重复生成红冲账单
|
||||||
|
BillOperationLogDO redFlushLogQuery = new BillOperationLogDO();
|
||||||
|
redFlushLogQuery.setBillManageId(originalBill.getBillManageId());
|
||||||
|
redFlushLogQuery.setOperationType(13);
|
||||||
|
List<BillOperationLogPO> redFlushLogList = billOperationLogDomainService.queryList(redFlushLogQuery);
|
||||||
|
if (null != redFlushLogList && redFlushLogList.stream().anyMatch(info -> ObjectUtil.equal(info.getDelFlag(), 1))) {
|
||||||
|
throw new ServiceException("账单" + originalBill.getBillNumber() + "已红冲,不能重复红冲");
|
||||||
|
}
|
||||||
|
//生成红冲账单编号
|
||||||
|
String billNumber = OrderSequence.getOrderCode("ZD");
|
||||||
|
BigDecimal redFlushAmount = negateAmount(originalBill.getBillAmount());
|
||||||
|
//构建红冲账单,金额全部取负对冲原账单
|
||||||
|
BillManage redBill = new BillManage();
|
||||||
|
BeanUtils.copyProperties(originalBill, redBill);
|
||||||
|
redBill.setBillManageId(null);
|
||||||
|
redBill.setBillNumber(billNumber);
|
||||||
|
redBill.setBillAmount(redFlushAmount);
|
||||||
|
redBill.setBillTotalAmount(negateAmount(originalBill.getBillTotalAmount()));
|
||||||
|
redBill.setBillDiscountAmount(negateAmount(originalBill.getBillDiscountAmount()));
|
||||||
|
redBill.setBillAmountSettlement(negateAmount(originalBill.getBillAmountSettlement()));
|
||||||
|
redBill.setBillAmountUnsettled(BigDecimal.ZERO);
|
||||||
|
redBill.setActualReceivedAmount(negateAmount(originalBill.getActualReceivedAmount()));
|
||||||
|
redBill.setSettlementDiscountsAmount(negateAmount(originalBill.getSettlementDiscountsAmount()));
|
||||||
|
redBill.setTaxAmount(negateAmount(originalBill.getTaxAmount()));
|
||||||
|
redBill.setTaxFreeFee(negateAmount(originalBill.getTaxFreeFee()));
|
||||||
|
//红冲账单状态为红冲、已核对无误
|
||||||
|
redBill.setBillState(8);
|
||||||
|
redBill.setBillStep(4);
|
||||||
|
redBill.setReconciliationStatus(4);
|
||||||
|
redBill.setSettlementTime(new Date());
|
||||||
|
//重置对账、审核、开票、同步等状态,红冲账单不需要再走这些流程
|
||||||
|
redBill.setBillExpectedAmount(null);
|
||||||
|
redBill.setReconciliationOpinion(null);
|
||||||
|
redBill.setVoucherAddress(null);
|
||||||
|
redBill.setFinancialReviewFlag(null);
|
||||||
|
redBill.setFinancialReviewOpinion(null);
|
||||||
|
redBill.setIsInvoice(0);
|
||||||
|
redBill.setInvoiceId(null);
|
||||||
|
redBill.setInvoiceMakeTime(null);
|
||||||
|
redBill.setApplyNumber(null);
|
||||||
|
redBill.setSynchronousStatus(0);
|
||||||
|
redBill.setSynchronousTime(null);
|
||||||
|
redBill.setNcId(null);
|
||||||
|
redBill.setSkSynchronousStatus(0);
|
||||||
|
redBill.setSkSynchronousTime(null);
|
||||||
|
redBill.setSkNcId(null);
|
||||||
|
//红冲原因写入账单备注
|
||||||
|
String billRemark = "红冲原账单编号:" + originalBill.getBillNumber();
|
||||||
|
if (StringUtils.isNotEmpty(redFlushRemark)) {
|
||||||
|
billRemark = billRemark + ",红冲原因:" + redFlushRemark;
|
||||||
|
}
|
||||||
|
redBill.setBillRemark(billRemark);
|
||||||
|
redBill.setDelFlag(1);
|
||||||
|
redBill.setCreateBy(loginUser.getUserid());
|
||||||
|
redBill.setCreateByName(loginUser.getUserPo().getUserName());
|
||||||
|
redBill.setCreateTime(new Date());
|
||||||
|
redBill.setUpdateBy(loginUser.getUserid());
|
||||||
|
redBill.setUpdateByName(loginUser.getUserPo().getUserName());
|
||||||
|
redBill.setUpdateTime(new Date());
|
||||||
|
Boolean flag = billManageService.save(redBill);
|
||||||
|
if (!flag || null == redBill.getBillManageId()) {
|
||||||
|
throw new ServiceException("生成红冲账单失败");
|
||||||
|
}
|
||||||
|
//镜像红冲计费流水(金额取负),并记录原流水id与新流水的映射
|
||||||
|
Map<Long, BillingStatementDO> statementMapping = new HashMap<>();
|
||||||
|
List<BillingStatementPO> originalStatementList = billingStatementDomainService.getDetailsByManageId(originalBill.getBillManageId());
|
||||||
|
if (null != originalStatementList && originalStatementList.size() > 0) {
|
||||||
|
for (BillingStatementPO originalStatement : originalStatementList) {
|
||||||
|
BillingStatementDO redStatement = new BillingStatementDO();
|
||||||
|
BeanUtils.copyProperties(originalStatement, redStatement);
|
||||||
|
redStatement.setBillingStatementId(null);
|
||||||
|
redStatement.setBillManageId(redBill.getBillManageId());
|
||||||
|
redStatement.setBillingFlow(OrderSequence.getOrderCode("JFLS"));
|
||||||
|
redStatement.setBillingAmount(negateAmount(originalStatement.getBillingAmount()));
|
||||||
|
redStatement.setTaxAmount(negateAmount(originalStatement.getTaxAmount()));
|
||||||
|
redStatement.setTaxFreeFee(negateAmount(originalStatement.getTaxFreeFee()));
|
||||||
|
redStatement.setBillingState(3);
|
||||||
|
redStatement.setRedFlushState(1);
|
||||||
|
redStatement.setRedFlushRemark("红冲自计费流水:" + originalStatement.getBillingFlow());
|
||||||
|
redStatement.setReviewRemarks(null);
|
||||||
|
redStatement.setBusinessDocumentId(null);
|
||||||
|
redStatement.setDelFlag(1);
|
||||||
|
redStatement.setTopOrganizationId(loginUser.getUserPo().getTopOrganizationId());
|
||||||
|
redStatement.setOrganizationId(loginUser.getUserPo().getOrganizationId());
|
||||||
|
redStatement.setOrganizationName(loginUser.getUserPo().getOrganizationName());
|
||||||
|
redStatement.setCreateBy(loginUser.getUserid());
|
||||||
|
redStatement.setCreateByName(loginUser.getUserPo().getUserName());
|
||||||
|
redStatement.setCreateTime(new Date());
|
||||||
|
redStatement.setUpdateBy(loginUser.getUserid());
|
||||||
|
redStatement.setUpdateByName(loginUser.getUserPo().getUserName());
|
||||||
|
redStatement.setUpdateTime(new Date());
|
||||||
|
redStatement.setBillingStatementId(billingStatementDomainService.insertAndReturnId(redStatement));
|
||||||
|
statementMapping.put(originalStatement.getBillingStatementId(), redStatement);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//镜像红冲账单明细(金额取负),并关联新计费流水
|
||||||
|
Boolean flagTwo = true;
|
||||||
|
LambdaQueryWrapper<BillDetail> detailQueryWrapper = new LambdaQueryWrapper<>();
|
||||||
|
detailQueryWrapper.eq(BillDetail::getBillManageId, originalBill.getBillManageId());
|
||||||
|
detailQueryWrapper.eq(BillDetail::getDelFlag, 1);
|
||||||
|
List<BillDetail> originalDetailList = billDetailDomainService.queryByLambda(detailQueryWrapper);
|
||||||
|
if (null != originalDetailList && originalDetailList.size() > 0) {
|
||||||
|
List<BillDetail> redDetailList = new ArrayList<>();
|
||||||
|
for (BillDetail originalDetail : originalDetailList) {
|
||||||
|
BillDetail redDetail = new BillDetail();
|
||||||
|
BeanUtils.copyProperties(originalDetail, redDetail);
|
||||||
|
redDetail.setBillDetailId(null);
|
||||||
|
redDetail.setBillManageId(redBill.getBillManageId());
|
||||||
|
redDetail.setBillNumber(billNumber);
|
||||||
|
redDetail.setBillingTotalAmount(negateAmount(originalDetail.getBillingTotalAmount()));
|
||||||
|
redDetail.setBillingAmount(negateAmount(originalDetail.getBillingAmount()));
|
||||||
|
redDetail.setBillingDiscountAmount(negateAmount(originalDetail.getBillingDiscountAmount()));
|
||||||
|
redDetail.setTaxAmount(negateAmount(originalDetail.getTaxAmount()));
|
||||||
|
redDetail.setTaxFreeFee(negateAmount(originalDetail.getTaxFreeFee()));
|
||||||
|
redDetail.setBillingExpectedAmount(null);
|
||||||
|
BillingStatementDO redStatement = statementMapping.get(originalDetail.getBillingStatementId());
|
||||||
|
if (null != redStatement) {
|
||||||
|
redDetail.setBillingStatementId(redStatement.getBillingStatementId());
|
||||||
|
redDetail.setBillingFlow(redStatement.getBillingFlow());
|
||||||
|
} else {
|
||||||
|
redDetail.setBillingStatementId(null);
|
||||||
|
redDetail.setBillingFlow(null);
|
||||||
|
}
|
||||||
|
redDetail.setDelFlag(1);
|
||||||
|
redDetail.setCreateBy(loginUser.getUserid());
|
||||||
|
redDetail.setCreateByName(loginUser.getUserPo().getUserName());
|
||||||
|
redDetail.setCreateTime(new Date());
|
||||||
|
redDetail.setUpdateBy(loginUser.getUserid());
|
||||||
|
redDetail.setUpdateByName(loginUser.getUserPo().getUserName());
|
||||||
|
redDetail.setUpdateTime(new Date());
|
||||||
|
redDetailList.add(redDetail);
|
||||||
|
}
|
||||||
|
flagTwo = billDetailDomainService.insertBatch(redDetailList);
|
||||||
|
}
|
||||||
|
//红冲账单保存创建账单操作日志
|
||||||
|
BillOperationLogDO redBillLog = new BillOperationLogDO();
|
||||||
|
redBillLog.setBillManageId(redBill.getBillManageId());
|
||||||
|
redBillLog.setOperationInfo(StringUtils.format(BillLogsConstants.create_bill_text, billNumber, redFlushAmount));
|
||||||
|
redBillLog.setOperationType(1);
|
||||||
|
Boolean flagThree = billOperationLogDomainService.saveBillOperationLog(redBillLog);
|
||||||
|
//原账单保存红冲操作日志
|
||||||
|
BillOperationLogDO originalBillLog = new BillOperationLogDO();
|
||||||
|
originalBillLog.setBillManageId(originalBill.getBillManageId());
|
||||||
|
originalBillLog.setOperationInfo(StringUtils.format(BillLogsConstants.red_flush_bill_text, billNumber, null == redFlushAmount ? BigDecimal.ZERO : redFlushAmount.abs()));
|
||||||
|
originalBillLog.setOperationType(13);
|
||||||
|
Boolean flagFour = billOperationLogDomainService.saveBillOperationLog(originalBillLog);
|
||||||
|
return flag && flagTwo && flagThree && flagFour;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 金额取负(空值返回null)
|
||||||
|
*/
|
||||||
|
private BigDecimal negateAmount(BigDecimal amount) {
|
||||||
|
return null == amount ? null : amount.negate();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 更改账单状态(付款)
|
* 更改账单状态(付款)
|
||||||
*/
|
*/
|
||||||
@@ -600,4 +1064,11 @@ public class BillManageDomainService {
|
|||||||
{
|
{
|
||||||
return billManageService.synchronousNcSK(businessDocumentDetaliIds);
|
return billManageService.synchronousNcSK(businessDocumentDetaliIds);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 客户每月账单分组查询
|
||||||
|
*/
|
||||||
|
public List<CustomerMonthBillVO> queryCustomerMonthBillList(BillManageDO billManageDO) {
|
||||||
|
return billManageService.queryCustomerMonthBillList(billManageDO);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
+2
-2
@@ -42,8 +42,8 @@ public class BillOperationLog extends BaseVOEntity{
|
|||||||
@Excel(name = "账单管理id")
|
@Excel(name = "账单管理id")
|
||||||
private Long billManageId;
|
private Long billManageId;
|
||||||
|
|
||||||
@ApiModelProperty("操作类型(1-创建账单,2-调整账单,3-确认账单,4-发起对账,5-客户确认,6-财务审核,7-收款,8-作废账单,9-删除账单,10-退款,11-付款)")
|
@ApiModelProperty("操作类型(1-创建账单,2-调整账单,3-确认账单,4-发起对账,5-客户确认,6-财务审核,7-收款,8-作废账单,9-删除账单,10-退款,11-付款,12-撤销收款,13-红冲)")
|
||||||
@Excel(name = "操作类型", readConverterExp = "1=-创建账单,2-调整账单,3-确认账单,4-发起对账,5-客户确认,6-财务审核,7-收款,8-作废账单,9-删除账单,10-退款,11-付款")
|
@Excel(name = "操作类型", readConverterExp = "1=-创建账单,2-调整账单,3-确认账单,4-发起对账,5-客户确认,6-财务审核,7-收款,8-作废账单,9-删除账单,10-退款,11-付款,12-撤销收款,13-红冲")
|
||||||
private Integer operationType;
|
private Integer operationType;
|
||||||
|
|
||||||
@ApiModelProperty("操作信息")
|
@ApiModelProperty("操作信息")
|
||||||
|
|||||||
+2
-2
@@ -41,8 +41,8 @@ public class BillOperationLogPO extends BaseVOEntity{
|
|||||||
@Excel(name = "账单管理id")
|
@Excel(name = "账单管理id")
|
||||||
private Long billManageId;
|
private Long billManageId;
|
||||||
|
|
||||||
@ApiModelProperty("操作类型(1-创建账单,2-调整账单,3-确认账单,4-发起对账,5-客户确认,6-财务审核,7-收款,8-作废账单,9-删除账单,10-退款,11-付款)")
|
@ApiModelProperty("操作类型(1-创建账单,2-调整账单,3-确认账单,4-发起对账,5-客户确认,6-财务审核,7-收款,8-作废账单,9-删除账单,10-退款,11-付款,12-撤销收款,13-红冲)")
|
||||||
@Excel(name = "操作类型", readConverterExp = "1=-创建账单,2-调整账单,3-确认账单,4-发起对账,5-客户确认,6-财务审核,7-收款,8-作废账单,9-删除账单,10-退款,11-付款")
|
@Excel(name = "操作类型", readConverterExp = "1=-创建账单,2-调整账单,3-确认账单,4-发起对账,5-客户确认,6-财务审核,7-收款,8-作废账单,9-删除账单,10-退款,11-付款,12-撤销收款,13-红冲")
|
||||||
private Integer operationType;
|
private Integer operationType;
|
||||||
|
|
||||||
@ApiModelProperty("操作信息")
|
@ApiModelProperty("操作信息")
|
||||||
|
|||||||
+2
-2
@@ -42,8 +42,8 @@ public class BillOperationLogDO extends BaseVOEntity{
|
|||||||
@Excel(name = "账单管理id")
|
@Excel(name = "账单管理id")
|
||||||
private Long billManageId;
|
private Long billManageId;
|
||||||
|
|
||||||
@ApiModelProperty("操作类型(1-创建账单,2-调整账单,3-确认账单,4-发起对账,5-客户确认,6-财务审核,7-收款,8-作废账单,9-删除账单,10-退款,11-付款)")
|
@ApiModelProperty("操作类型(1-创建账单,2-调整账单,3-确认账单,4-发起对账,5-客户确认,6-财务审核,7-收款,8-作废账单,9-删除账单,10-退款,11-付款,12-撤销收款,13-红冲)")
|
||||||
@Excel(name = "操作类型", readConverterExp = "1=-创建账单,2-调整账单,3-确认账单,4-发起对账,5-客户确认,6-财务审核,7-收款,8-作废账单,9-删除账单,10-退款,11-付款")
|
@Excel(name = "操作类型", readConverterExp = "1=-创建账单,2-调整账单,3-确认账单,4-发起对账,5-客户确认,6-财务审核,7-收款,8-作废账单,9-删除账单,10-退款,11-付款,12-撤销收款,13-红冲")
|
||||||
private Integer operationType;
|
private Integer operationType;
|
||||||
|
|
||||||
@ApiModelProperty("操作信息")
|
@ApiModelProperty("操作信息")
|
||||||
|
|||||||
+40
@@ -95,6 +95,12 @@ public class BillOperationLogDomainService {
|
|||||||
return billOperationLogService.insert(billOperationLogDO);
|
return billOperationLogService.insert(billOperationLogDO);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Boolean saveBillOperationLogJob(BillOperationLogDO billOperationLogDO) {
|
||||||
|
|
||||||
|
billOperationLogDO.setDelFlag(1);
|
||||||
|
return billOperationLogService.insert(billOperationLogDO);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 批量保存操作日志
|
* 批量保存操作日志
|
||||||
@@ -133,6 +139,40 @@ public class BillOperationLogDomainService {
|
|||||||
return billOperationLogService.saveBatch(saveList);
|
return billOperationLogService.saveBatch(saveList);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Boolean saveBillOperationLogBatchJob(BillOperationLogDO billOperationLogDO) {
|
||||||
|
// LoginUser loginUser = SecurityUtils.getLoginUser();
|
||||||
|
// if (ObjectUtil.isNull(loginUser)) {
|
||||||
|
// throw new DigitalLogisticsException(UserError.TIMEOUT);
|
||||||
|
// }
|
||||||
|
if(billOperationLogDO.getBillManageIdSet()==null || billOperationLogDO.getBillManageIdSet().size()==0){
|
||||||
|
throw new ServiceException("账单集合不能为空");
|
||||||
|
}
|
||||||
|
// String userName = loginUser.getUserPo().getUserName();
|
||||||
|
// // 获取登录人id
|
||||||
|
// Long userId = loginUser.getUserid();
|
||||||
|
BillOperationLogDO common = new BillOperationLogDO();
|
||||||
|
// common.setCreateByName(userName);
|
||||||
|
// common.setUpdateByName(userName);
|
||||||
|
common.setCreateTime(new Date());
|
||||||
|
common.setUpdateTime(new Date());
|
||||||
|
common.setDelFlag(1);
|
||||||
|
// common.setCreateBy(userId);
|
||||||
|
// common.setUpdateBy(userId);
|
||||||
|
// common.setTopOrganizationId(loginUser.getUserPo().getTopOrganizationId());
|
||||||
|
// common.setOrganizationId(loginUser.getUserPo().getOrganizationId());
|
||||||
|
// common.setOrganizationName(loginUser.getUserPo().getOrganizationName());
|
||||||
|
common.setOperationType(billOperationLogDO.getOperationType());
|
||||||
|
common.setOperationInfo(billOperationLogDO.getOperationInfo());
|
||||||
|
List<BillOperationLog> saveList = new ArrayList<>();
|
||||||
|
for (String billManageId : billOperationLogDO.getBillManageIdSet()) {
|
||||||
|
BillOperationLog save = new BillOperationLog();
|
||||||
|
BeanUtils.copyProperties(common, save);
|
||||||
|
save.setBillManageId(Long.valueOf(billManageId));
|
||||||
|
saveList.add(save);
|
||||||
|
}
|
||||||
|
return billOperationLogService.saveBatch(saveList);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 批量保存数据
|
* 批量保存数据
|
||||||
|
|||||||
+81
@@ -171,6 +171,48 @@ public class BillingStatementDomainService {
|
|||||||
return billingStatementService.updateBatchById(billingStatements);
|
return billingStatementService.updateBatchById(billingStatements);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Boolean reviewBillingJob(BillingStatementDTO billingStatementDTO) {
|
||||||
|
LoginUser loginUser = SecurityUtils.getLoginUser();
|
||||||
|
if (ObjectUtil.isNull(loginUser)) {
|
||||||
|
// throw new DigitalLogisticsException(UserError.TIMEOUT);
|
||||||
|
}
|
||||||
|
List<BillingStatement> billingStatements = new ArrayList<>();
|
||||||
|
Set<String> billingSet = Stream.of(billingStatementDTO.getBillingStatementIds().split(",")).collect(Collectors.toSet());
|
||||||
|
for (String billingId : billingSet) {
|
||||||
|
Long billingStatementId = Long.valueOf(billingId);
|
||||||
|
BillingStatementPO billingStatementPO = billingStatementService.getInfo(billingStatementId);
|
||||||
|
if(null == billingStatementPO){
|
||||||
|
throw new ServiceException("流水不存在");
|
||||||
|
}
|
||||||
|
if(billingStatementPO.getBillingState()!=1){
|
||||||
|
throw new ServiceException("该计费流水状态不为待审核,不能进行审核");
|
||||||
|
}
|
||||||
|
if(billingStatementPO.getRedFlushState()==2){
|
||||||
|
throw new ServiceException("计费流水"+ billingStatementPO.getBillingFlow() +"已红冲,不能进行审核");
|
||||||
|
}
|
||||||
|
BillingStatement billingStatement = new BillingStatement();
|
||||||
|
billingStatement.setBillingStatementId(billingStatementId);
|
||||||
|
billingStatement.setReviewRemarks(billingStatementDTO.getReviewRemarks());
|
||||||
|
if(billingStatementDTO.getAuditOperation()==1){
|
||||||
|
//审核通过
|
||||||
|
billingStatement.setBillingState(2);
|
||||||
|
}else {
|
||||||
|
//审核不通过
|
||||||
|
billingStatement.setBillingState(4);
|
||||||
|
//计费流水审核不通过时,修改业务单据中的状态到已生效
|
||||||
|
BusinessDocumentDO businessDocumentDO = new BusinessDocumentDO();
|
||||||
|
businessDocumentDO.setBusinessDocumentId(billingStatementPO.getBusinessDocumentId());
|
||||||
|
businessDocumentDO.setBusinessState(2);
|
||||||
|
businessDocumentService.update(businessDocumentDO);
|
||||||
|
}
|
||||||
|
billingStatement.setUpdateTime(new Date());
|
||||||
|
// billingStatement.setUpdateBy(loginUser.getUserPo().getUserId());
|
||||||
|
// billingStatement.setUpdateByName(loginUser.getUserPo().getUserName());
|
||||||
|
billingStatements.add(billingStatement);
|
||||||
|
}
|
||||||
|
return billingStatementService.updateBatchById(billingStatements);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 批量红冲
|
* 批量红冲
|
||||||
@@ -299,6 +341,45 @@ public class BillingStatementDomainService {
|
|||||||
return update;
|
return update;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Boolean updateBillingStateJob(BillingStatementDTO billingStatementDTO) {
|
||||||
|
LoginUser loginUser = SecurityUtils.getLoginUser();
|
||||||
|
if (ObjectUtil.isNull(loginUser)) {
|
||||||
|
// throw new DigitalLogisticsException(UserError.TIMEOUT);
|
||||||
|
}
|
||||||
|
Set<String> billingSet = Stream.of(billingStatementDTO.getBillingStatementIds().split(",")).collect(Collectors.toSet());
|
||||||
|
LambdaUpdateWrapper<BillingStatement> updateWrapper = new LambdaUpdateWrapper<>();
|
||||||
|
updateWrapper.in(BillingStatement::getBillingStatementId,billingSet);
|
||||||
|
|
||||||
|
updateWrapper.set(BillingStatement::getBillingState,billingStatementDTO.getBillingState());
|
||||||
|
// updateWrapper.set(BillingStatement::getUpdateBy,loginUser.getUserPo().getUserId());
|
||||||
|
updateWrapper.set(BillingStatement::getUpdateTime,new Date());
|
||||||
|
// updateWrapper.set(BillingStatement::getUpdateByName,loginUser.getUserPo().getUserName());
|
||||||
|
updateWrapper.set(BillingStatement::getBillManageId,billingStatementDTO.getBillManageId());
|
||||||
|
boolean update = billingStatementService.update(updateWrapper);
|
||||||
|
List<BillingStatementADDVO> billingStatementList = billingStatementDTO.getBillingStatementList();
|
||||||
|
for (BillingStatementADDVO billingStatementADDVO : billingStatementList) {
|
||||||
|
String billingStatementIds = billingStatementADDVO.getBillingStatementId();
|
||||||
|
Set<String> billings = Stream.of(billingStatementIds.split(",")).collect(Collectors.toSet());
|
||||||
|
if (billings != null && billings.size() > 0) {
|
||||||
|
for (String billing : billings) {
|
||||||
|
Long billingStatementId = Long.valueOf(billing);
|
||||||
|
Double taxRate = billingStatementADDVO.getTaxRate();
|
||||||
|
BillingStatement billingStatement = billingStatementService.getById(billingStatementId);
|
||||||
|
if (billingStatement != null) {
|
||||||
|
BigDecimal billingAmount = billingStatement.getBillingAmount();
|
||||||
|
BigDecimal taxAmount = billingAmount.divide(BigDecimal.ONE.add(new BigDecimal(taxRate).divide(BigDecimal.valueOf(100))),10, BigDecimal.ROUND_HALF_UP).multiply(new BigDecimal(taxRate).divide(BigDecimal.valueOf(100))).setScale(2, BigDecimal.ROUND_HALF_UP);
|
||||||
|
BigDecimal taxFreeFee = billingAmount.subtract(taxAmount);
|
||||||
|
billingStatement.setTaxAmount(taxAmount);
|
||||||
|
billingStatement.setTaxFreeFee(taxFreeFee);
|
||||||
|
billingStatement.setTaxRate(taxRate);
|
||||||
|
billingStatementService.updateById(billingStatement);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return update;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
public Boolean nullifyByIds(BillingStatementDTO billingStatementDTO) {
|
public Boolean nullifyByIds(BillingStatementDTO billingStatementDTO) {
|
||||||
LoginUser loginUser = SecurityUtils.getLoginUser();
|
LoginUser loginUser = SecurityUtils.getLoginUser();
|
||||||
|
|||||||
+2
@@ -26,6 +26,8 @@ public interface IBmsInvoiceListService extends IService<BmsInvoiceList> {
|
|||||||
|
|
||||||
void addReceivableBill(BmsInvoiceListAddDTO tmsInvoiceListAddDTO);
|
void addReceivableBill(BmsInvoiceListAddDTO tmsInvoiceListAddDTO);
|
||||||
|
|
||||||
|
void addReceivableBillJob(BmsInvoiceListAddDTO tmsInvoiceListAddDTO);
|
||||||
|
|
||||||
void update(BmsInvoiceListDTO tmsInvoiceListDTO);
|
void update(BmsInvoiceListDTO tmsInvoiceListDTO);
|
||||||
|
|
||||||
int delete(List<String> ids);
|
int delete(List<String> ids);
|
||||||
|
|||||||
+109
@@ -216,6 +216,76 @@ public class BmsInvoiceListServiceImpl extends ServiceImpl<BmsInvoiceListMapper,
|
|||||||
}*/
|
}*/
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Transactional
|
||||||
|
@Override
|
||||||
|
public void addReceivableBillJob(BmsInvoiceListAddDTO bmsInvoiceListAddDTO) {
|
||||||
|
//获取登录人
|
||||||
|
// WlhyLoginUser sysUser = SecurityUtils.getLoginUser().getWlhyLoginUser();
|
||||||
|
// if (null == sysUser) {
|
||||||
|
// throw new ServiceException("sysUser是空值!");
|
||||||
|
// }
|
||||||
|
/*if (StringUtils.isEmpty(bmsInvoiceListAddDTO.getInvoiceTitle())){
|
||||||
|
throw new ServiceException("发票抬头不能为空!");
|
||||||
|
}*/
|
||||||
|
bmsInvoiceListAddDTO.setInvoiceValue(bmsInvoiceListAddDTO.getBillAmount());
|
||||||
|
BmsInvoiceList bmsInvoiceList = new BmsInvoiceList(); // 销项发票表
|
||||||
|
BeanUtils.copyProperties(bmsInvoiceListAddDTO, bmsInvoiceList);
|
||||||
|
// String createBy = sysUser.getId(); // 创建人ID
|
||||||
|
|
||||||
|
if(StringUtils.isNotBlank(bmsInvoiceListAddDTO.getCompanyName())){
|
||||||
|
bmsInvoiceList.setShipperName(bmsInvoiceListAddDTO.getCompanyName());
|
||||||
|
bmsInvoiceList.setCompanyName(bmsInvoiceListAddDTO.getCompanyName());
|
||||||
|
}
|
||||||
|
// 保存【销项发票表】数据
|
||||||
|
Long listId = saveBmsInvoiceListJob(bmsInvoiceList, bmsInvoiceListAddDTO, null, null);
|
||||||
|
|
||||||
|
//预保存发票明细信息
|
||||||
|
if(ObjectUtil.isNotNull(listId)){
|
||||||
|
List<BmsMakeOutInvoice> bmsMakeOutInvoices = bmsInvoiceListAddDTO.getBmsMakeOutInvoices();
|
||||||
|
if (ObjectUtil.isNotNull(bmsMakeOutInvoices) && bmsMakeOutInvoices.size() > 0) {
|
||||||
|
for (BmsMakeOutInvoice bmsMakeOutInvoice : bmsMakeOutInvoices) {
|
||||||
|
bmsMakeOutInvoice.setInvoiceId(listId);
|
||||||
|
//bmsMakeOutInvoice.setCreateBy(sysUser.getId());
|
||||||
|
bmsMakeOutInvoice.setCreateTime(new Date());
|
||||||
|
bmsMakeOutInvoiceMapper.insert(bmsMakeOutInvoice);
|
||||||
|
for (BmsMakeOutInvoiceItem bmsMakeOutInvoiceItem : bmsMakeOutInvoice.getBmsMakeOutInvoiceItems()) {
|
||||||
|
bmsMakeOutInvoiceItem.setMakeId(bmsMakeOutInvoice.getId());
|
||||||
|
//bmsMakeOutInvoiceItem.setCreateBy(sysUser.getId());
|
||||||
|
bmsMakeOutInvoiceItem.setCreateTime(new Date());
|
||||||
|
bmsMakeOutInvoiceItemMapper.insert(bmsMakeOutInvoiceItem);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// BillManage billManage = billManageMapper.selectById(bmsInvoiceListAddDTO.getBillManageId());
|
||||||
|
// if (billManage != null) {
|
||||||
|
// billManage.setIsInvoice(1);
|
||||||
|
// billManage.setInvoiceId(bmsInvoiceList.getId().toString());
|
||||||
|
// billManage.setApplyNumber(bmsInvoiceList.getApplyNumber());
|
||||||
|
// billManageMapper.updateById(billManage);
|
||||||
|
// }
|
||||||
|
List<Long> billManageIds = bmsInvoiceListAddDTO.getBillManageIds();
|
||||||
|
if (billManageIds != null && billManageIds.size() > 0){
|
||||||
|
} else {
|
||||||
|
billManageIds = new ArrayList<>();
|
||||||
|
billManageIds.add(bmsInvoiceListAddDTO.getBillManageId());
|
||||||
|
}
|
||||||
|
List<BillManage> billManages = billManageMapper.selectList(new LambdaQueryWrapper<BillManage>().in(BillManage::getBillManageId, billManageIds));
|
||||||
|
if (billManages != null && billManages.size() > 0) {
|
||||||
|
for (BillManage billManage : billManages) {
|
||||||
|
billManage.setIsInvoice(1);
|
||||||
|
billManage.setInvoiceId(bmsInvoiceList.getId().toString());
|
||||||
|
billManage.setApplyNumber(bmsInvoiceList.getApplyNumber());
|
||||||
|
billManageMapper.updateById(billManage);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*AjaxResult ajaxResult = financeServiceFeign.editIsInvoice(transportationId,1,bmsInvoiceList.getId(),"",bmsInvoiceList.getApplyNumber());
|
||||||
|
if(!"200".equals(String.valueOf(ajaxResult.get("code")))){
|
||||||
|
throw new com.mhd.common.core.exception.ServiceException(ajaxResult.get("msg").toString());
|
||||||
|
}*/
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public BmsSettlementPartyInvoice selectSettlementPartyInfoByName(String settlementPartyName) {
|
public BmsSettlementPartyInvoice selectSettlementPartyInfoByName(String settlementPartyName) {
|
||||||
return null;
|
return null;
|
||||||
@@ -932,4 +1002,43 @@ public class BmsInvoiceListServiceImpl extends ServiceImpl<BmsInvoiceListMapper,
|
|||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Long saveBmsInvoiceListJob(BmsInvoiceList bmsInvoiceList, BmsInvoiceListAddDTO bmsInvoiceListAddDTO, WlhyLoginUser sysUser, String createBy){
|
||||||
|
|
||||||
|
bmsInvoiceList.setReceivingAddressId(bmsInvoiceListAddDTO.getReceivingAddressId());
|
||||||
|
|
||||||
|
//bmsInvoiceList.setCreateBy(createBy);
|
||||||
|
bmsInvoiceList.setApplyNumber(OrderSequence.getOrderCode("XF"));
|
||||||
|
bmsInvoiceList.setCreateTime(new Date());
|
||||||
|
bmsInvoiceList.setInvoiceApplyTime(new Date());
|
||||||
|
// bmsInvoiceList.setApplicantId(sysUser.getId());
|
||||||
|
// bmsInvoiceList.setRealCreateBy(sysUser.getId());
|
||||||
|
// bmsInvoiceList.setRealCreateName(sysUser.getRealname());
|
||||||
|
bmsInvoiceList.setCompanyName(bmsInvoiceListAddDTO.getSettlementEntity());
|
||||||
|
// 设置组织相关字段:从当前登录用户获取组织信息
|
||||||
|
// LoginUser loginUser = SecurityUtils.getLoginUser();
|
||||||
|
// if (loginUser != null && loginUser.getUserPo() != null) {
|
||||||
|
// // 设置组织ID
|
||||||
|
// if (loginUser.getUserPo().getOrganizationId() != null) {
|
||||||
|
// bmsInvoiceList.setOrganizationId(loginUser.getUserPo().getOrganizationId());
|
||||||
|
// }
|
||||||
|
// // 设置组织名称
|
||||||
|
// if (StringUtils.isNotBlank(loginUser.getUserPo().getOrganizationName())) {
|
||||||
|
// bmsInvoiceList.setOrganizationName(loginUser.getUserPo().getOrganizationName());
|
||||||
|
// }
|
||||||
|
// // 设置一级组织ID
|
||||||
|
// if (loginUser.getUserPo().getTopOrganizationId() != null) {
|
||||||
|
// bmsInvoiceList.setTopOrganizationId(loginUser.getUserPo().getTopOrganizationId());
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
boolean saveSuccess = this.save(bmsInvoiceList);
|
||||||
|
// 3. 插入成功后,直接从实体对象获取ID(已被MyBatis-Plus自动赋值)
|
||||||
|
if (saveSuccess) {
|
||||||
|
Long id = bmsInvoiceList.getId();
|
||||||
|
System.out.println("插入成功,生成的ID:" + id);
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
+14
@@ -79,5 +79,19 @@ public class BmsInvoiceListAddDTO implements Serializable {
|
|||||||
@ApiModelProperty(value = "对账单id列表")
|
@ApiModelProperty(value = "对账单id列表")
|
||||||
@Excel(name = "对账单id列表", width = 15)
|
@Excel(name = "对账单id列表", width = 15)
|
||||||
private List<Long> billManageIds;
|
private List<Long> billManageIds;
|
||||||
|
/**组织ID*/
|
||||||
|
@ApiModelProperty(value = "组织ID")
|
||||||
|
@Excel(name = "组织ID", width = 15)
|
||||||
|
private Long organizationId;
|
||||||
|
|
||||||
|
/**组织名称*/
|
||||||
|
@ApiModelProperty(value = "组织名称")
|
||||||
|
@Excel(name = "组织名称", width = 15)
|
||||||
|
private String organizationName;
|
||||||
|
|
||||||
|
/**一级组织ID*/
|
||||||
|
@ApiModelProperty(value = "一级组织ID")
|
||||||
|
@Excel(name = "一级组织ID", width = 15)
|
||||||
|
private Long topOrganizationId;
|
||||||
|
|
||||||
}
|
}
|
||||||
+28
@@ -1,16 +1,22 @@
|
|||||||
package com.mhd.bms.domain.receiptManage.service;
|
package com.mhd.bms.domain.receiptManage.service;
|
||||||
|
|
||||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||||
|
import cn.hutool.core.util.ObjectUtil;
|
||||||
import com.mhd.bms.domain.receiptManage.entity.ReceiptDetail;
|
import com.mhd.bms.domain.receiptManage.entity.ReceiptDetail;
|
||||||
import com.mhd.bms.domain.receiptManage.repository.facade.IReceiptDetailService;
|
import com.mhd.bms.domain.receiptManage.repository.facade.IReceiptDetailService;
|
||||||
import com.mhd.bms.domain.receiptManage.repository.po.ReceiptDetailPO;
|
import com.mhd.bms.domain.receiptManage.repository.po.ReceiptDetailPO;
|
||||||
import com.mhd.bms.domain.receiptManage.repository.todo.ReceiptDetailDO;
|
import com.mhd.bms.domain.receiptManage.repository.todo.ReceiptDetailDO;
|
||||||
|
import com.mhd.common.core.exception.digitalLogisticsException.DigitalLogisticsException;
|
||||||
|
import com.mhd.common.core.exception.digitalLogisticsException.UserError;
|
||||||
|
import com.mhd.common.security.utils.SecurityUtils;
|
||||||
|
import com.mhd.system.api.model.LoginUser;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.springframework.beans.BeanUtils;
|
import org.springframework.beans.BeanUtils;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Date;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
@@ -95,6 +101,28 @@ public class ReceiptDetailDomainService {
|
|||||||
public List<ReceiptDetail> queryListByIdSet(Set<Long> orderIdSet) {
|
public List<ReceiptDetail> queryListByIdSet(Set<Long> orderIdSet) {
|
||||||
LambdaQueryWrapper<ReceiptDetail> queryWrapperDetail = new LambdaQueryWrapper<>();
|
LambdaQueryWrapper<ReceiptDetail> queryWrapperDetail = new LambdaQueryWrapper<>();
|
||||||
queryWrapperDetail.in(ReceiptDetail::getReceiptManageId, orderIdSet);
|
queryWrapperDetail.in(ReceiptDetail::getReceiptManageId, orderIdSet);
|
||||||
|
queryWrapperDetail.eq(ReceiptDetail::getDelFlag, 1);
|
||||||
return receiptDetailService.list(queryWrapperDetail);
|
return receiptDetailService.list(queryWrapperDetail);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 撤销收款:批量逻辑删除收款明细
|
||||||
|
*/
|
||||||
|
public Boolean cancelCollectionDetails(List<ReceiptDetail> receiptDetails) {
|
||||||
|
LoginUser loginUser = SecurityUtils.getLoginUser();
|
||||||
|
if (ObjectUtil.isNull(loginUser)) {
|
||||||
|
throw new DigitalLogisticsException(UserError.TIMEOUT);
|
||||||
|
}
|
||||||
|
List<ReceiptDetail> receiptDetailSaveList = new ArrayList<>();
|
||||||
|
for (ReceiptDetail receiptDetail : receiptDetails) {
|
||||||
|
ReceiptDetail receiptDetailSave = new ReceiptDetail();
|
||||||
|
receiptDetailSave.setReceiptDetailId(receiptDetail.getReceiptDetailId());
|
||||||
|
receiptDetailSave.setDelFlag(2);
|
||||||
|
receiptDetailSave.setUpdateBy(loginUser.getUserPo().getUserId());
|
||||||
|
receiptDetailSave.setUpdateByName(loginUser.getUserPo().getUserName());
|
||||||
|
receiptDetailSave.setUpdateTime(new Date());
|
||||||
|
receiptDetailSaveList.add(receiptDetailSave);
|
||||||
|
}
|
||||||
|
return receiptDetailService.updateBatchById(receiptDetailSaveList);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+128
@@ -42,7 +42,9 @@ import org.springframework.stereotype.Service;
|
|||||||
import java.math.BigDecimal;
|
import java.math.BigDecimal;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
import java.util.stream.Stream;
|
import java.util.stream.Stream;
|
||||||
@@ -300,6 +302,132 @@ public class ReceiptManageDomainService {
|
|||||||
return flag && flagTwo && flagThree;
|
return flag && flagTwo && flagThree;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 撤销收款
|
||||||
|
*/
|
||||||
|
public Boolean cancelCollection(ReceiptManageDO receiptManageDO) {
|
||||||
|
LoginUser loginUser = SecurityUtils.getLoginUser();
|
||||||
|
if (ObjectUtil.isNull(loginUser)) {
|
||||||
|
throw new DigitalLogisticsException(UserError.TIMEOUT);
|
||||||
|
}
|
||||||
|
if (StringUtils.isEmpty(receiptManageDO.getBillManageIds())) {
|
||||||
|
throw new ServiceException("撤销账单不能为空");
|
||||||
|
}
|
||||||
|
Set<Long> billManageIdSet = Stream.of(receiptManageDO.getBillManageIds().split(",")).filter(StringUtils::isNotEmpty).map(String::trim).map(Long::valueOf).collect(Collectors.toSet());
|
||||||
|
if (billManageIdSet.size() == 0) {
|
||||||
|
throw new ServiceException("撤销账单不能为空");
|
||||||
|
}
|
||||||
|
//查询账单信息
|
||||||
|
LambdaQueryWrapper<BillManage> queryWrapperBill = new LambdaQueryWrapper<>();
|
||||||
|
queryWrapperBill.in(BillManage::getBillManageId, billManageIdSet);
|
||||||
|
queryWrapperBill.eq(BillManage::getDelFlag, 1);
|
||||||
|
List<BillManage> billManageList = billManageDomainService.queryListLambda(queryWrapperBill);
|
||||||
|
if (null == billManageList || billManageList.size() == 0) {
|
||||||
|
throw new ServiceException("账单信息未找到");
|
||||||
|
}
|
||||||
|
if (billManageList.size() != billManageIdSet.size()) {
|
||||||
|
throw new ServiceException("部分账单信息未找到,请刷新后重试");
|
||||||
|
}
|
||||||
|
//查询账单的全部有效收款明细(一个账单可能对应多个收款单)
|
||||||
|
LambdaQueryWrapper<ReceiptDetail> queryWrapperDetail = new LambdaQueryWrapper<>();
|
||||||
|
queryWrapperDetail.in(ReceiptDetail::getBillManageId, billManageIdSet);
|
||||||
|
queryWrapperDetail.eq(ReceiptDetail::getDelFlag, 1);
|
||||||
|
List<ReceiptDetail> receiptDetails = receiptDetailDomainService.queryListByLambda(queryWrapperDetail);
|
||||||
|
if (null == receiptDetails || receiptDetails.size() == 0) {
|
||||||
|
throw new ServiceException("账单收款记录不存在或已撤销,请刷新后重试");
|
||||||
|
}
|
||||||
|
//校验每个账单都有收款记录
|
||||||
|
Map<Long, List<ReceiptDetail>> billDetailMap = receiptDetails.stream().collect(Collectors.groupingBy(ReceiptDetail::getBillManageId));
|
||||||
|
for (BillManage billManage : billManageList) {
|
||||||
|
if (!billDetailMap.containsKey(billManage.getBillManageId())) {
|
||||||
|
throw new ServiceException("账单" + billManage.getBillNumber() + "收款记录不存在或已撤销,请刷新后重试");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//校验收款单退款状态,已退款的收款单不能撤销收款
|
||||||
|
Set<Long> receiptManageIdSet = receiptDetails.stream().map(ReceiptDetail::getReceiptManageId).collect(Collectors.toSet());
|
||||||
|
LambdaQueryWrapper<ReceiptManage> queryWrapperManage = new LambdaQueryWrapper<>();
|
||||||
|
queryWrapperManage.in(ReceiptManage::getReceiptManageId, receiptManageIdSet);
|
||||||
|
List<ReceiptManage> receiptManageList = receiptManageService.list(queryWrapperManage);
|
||||||
|
if (null != receiptManageList) {
|
||||||
|
ReceiptManage refundManage = receiptManageList.stream().filter(info -> ObjectUtil.equal(info.getPaymentStatus(), 2)).findAny().orElse(null);
|
||||||
|
if (null != refundManage) {
|
||||||
|
throw new ServiceException("收款单" + refundManage.getCollectionNum() + "已退款,无法撤销收款");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//账单恢复为收款为0状态并保存撤销收款操作日志
|
||||||
|
Boolean flagTwo = billManageDomainService.cancelCollectionInfo(receiptDetails);
|
||||||
|
//逻辑删除收款明细
|
||||||
|
Boolean flag = receiptDetailDomainService.cancelCollectionDetails(receiptDetails);
|
||||||
|
//按剩余明细重新计算涉及的收款单金额,明细已全部撤销时逻辑删除收款单
|
||||||
|
Boolean flagThree = true;
|
||||||
|
for (Long receiptManageId : receiptManageIdSet) {
|
||||||
|
flagThree = updateReceiptManageByCancel(receiptManageId) && flagThree;
|
||||||
|
}
|
||||||
|
return flag && flagTwo && flagThree;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 撤销收款后重新计算收款单信息,收款明细已全部撤销时逻辑删除收款单
|
||||||
|
*/
|
||||||
|
private Boolean updateReceiptManageByCancel(Long receiptManageId) {
|
||||||
|
LoginUser loginUser = SecurityUtils.getLoginUser();
|
||||||
|
if (ObjectUtil.isNull(loginUser)) {
|
||||||
|
throw new DigitalLogisticsException(UserError.TIMEOUT);
|
||||||
|
}
|
||||||
|
//查询收款单下剩余未撤销的收款明细
|
||||||
|
LambdaQueryWrapper<ReceiptDetail> queryWrapperDetail = new LambdaQueryWrapper<>();
|
||||||
|
queryWrapperDetail.eq(ReceiptDetail::getReceiptManageId, receiptManageId);
|
||||||
|
queryWrapperDetail.eq(ReceiptDetail::getDelFlag, 1);
|
||||||
|
List<ReceiptDetail> receiptDetailList = receiptDetailDomainService.queryListByLambda(queryWrapperDetail);
|
||||||
|
ReceiptManage receiptManageSave = new ReceiptManage();
|
||||||
|
receiptManageSave.setReceiptManageId(receiptManageId);
|
||||||
|
receiptManageSave.setUpdateBy(loginUser.getUserPo().getUserId());
|
||||||
|
receiptManageSave.setUpdateByName(loginUser.getUserPo().getUserName());
|
||||||
|
receiptManageSave.setUpdateTime(new Date());
|
||||||
|
if (null == receiptDetailList || receiptDetailList.size() == 0) {
|
||||||
|
//收款明细已全部撤销,逻辑删除收款单
|
||||||
|
receiptManageSave.setDelFlag(2);
|
||||||
|
return receiptManageService.updateById(receiptManageSave);
|
||||||
|
}
|
||||||
|
//按剩余明细重新计算收款单金额
|
||||||
|
BigDecimal billAmount = receiptDetailList.stream().map(ReceiptDetail::getBillAmount).reduce(BigDecimal.ZERO, BigDecimal::add);
|
||||||
|
BigDecimal collectedDiscount = receiptDetailList.stream().map(ReceiptDetail::getCollectedDiscount).reduce(BigDecimal.ZERO, BigDecimal::add);
|
||||||
|
BigDecimal collectedAmount = receiptDetailList.stream().map(ReceiptDetail::getCollectedAmount).reduce(BigDecimal.ZERO, BigDecimal::add);
|
||||||
|
BigDecimal uncollectedAmount = receiptDetailList.stream().map(ReceiptDetail::getBillAmountUnsettledResidue).reduce(BigDecimal.ZERO, BigDecimal::add);
|
||||||
|
BigDecimal billAmountUnsettled = receiptDetailList.stream().map(ReceiptDetail::getBillAmountUnsettled).reduce(BigDecimal.ZERO, BigDecimal::add);
|
||||||
|
receiptManageSave.setBillAmount(billAmount);
|
||||||
|
receiptManageSave.setCollectedDiscount(collectedDiscount);
|
||||||
|
receiptManageSave.setCollectedAmount(collectedAmount);
|
||||||
|
receiptManageSave.setUncollectedAmount(uncollectedAmount);
|
||||||
|
receiptManageSave.setBillAmountUnsettled(billAmountUnsettled);
|
||||||
|
//账单金额 = 已收金额 + 剩余未收金额 + 收款优惠金额 + 收款金额
|
||||||
|
receiptManageSave.setBillAmountSettlement(billAmount.subtract(uncollectedAmount).subtract(collectedDiscount).subtract(collectedAmount));
|
||||||
|
return receiptManageService.updateById(receiptManageSave);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 撤销收款-查询账单涉及的收款单id(用于加锁,防止并发撤销时收款单金额重算冲突)
|
||||||
|
*/
|
||||||
|
public Set<Long> queryReceiptManageIdsByBillManageIds(String billManageIds) {
|
||||||
|
Set<Long> receiptManageIdSet = new HashSet<>();
|
||||||
|
if (StringUtils.isEmpty(billManageIds)) {
|
||||||
|
return receiptManageIdSet;
|
||||||
|
}
|
||||||
|
Set<Long> billManageIdSet = Stream.of(billManageIds.split(",")).filter(StringUtils::isNotEmpty).map(String::trim).map(Long::valueOf).collect(Collectors.toSet());
|
||||||
|
if (billManageIdSet.size() == 0) {
|
||||||
|
return receiptManageIdSet;
|
||||||
|
}
|
||||||
|
LambdaQueryWrapper<ReceiptDetail> queryWrapperDetail = new LambdaQueryWrapper<>();
|
||||||
|
queryWrapperDetail.in(ReceiptDetail::getBillManageId, billManageIdSet);
|
||||||
|
queryWrapperDetail.eq(ReceiptDetail::getDelFlag, 1);
|
||||||
|
List<ReceiptDetail> receiptDetails = receiptDetailDomainService.queryListByLambda(queryWrapperDetail);
|
||||||
|
if (null == receiptDetails || receiptDetails.size() == 0) {
|
||||||
|
return receiptManageIdSet;
|
||||||
|
}
|
||||||
|
receiptDetails.forEach(receiptDetail -> receiptManageIdSet.add(receiptDetail.getReceiptManageId()));
|
||||||
|
return receiptManageIdSet;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 查询收款单详情
|
* 查询收款单详情
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -88,6 +88,14 @@ public class BillLogsConstants
|
|||||||
public static final String refund_bill_text = "退款单号:{},退款金额:{}元";
|
public static final String refund_bill_text = "退款单号:{},退款金额:{}元";
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 撤销收款
|
||||||
|
* 收款单号:{},撤销收款金额:{}元(实收{}元,优惠{}元)
|
||||||
|
*/
|
||||||
|
public static final String cancel_collection_bill_title = "撤销收款";
|
||||||
|
public static final String cancel_collection_bill_text = "收款单号:{},撤销收款金额:{}元(实收{}元,优惠{}元)";
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 付款
|
* 付款
|
||||||
* 付款单号:{},付款金额:{}元
|
* 付款单号:{},付款金额:{}元
|
||||||
@@ -104,4 +112,11 @@ public class BillLogsConstants
|
|||||||
public static final String copy_bill_text = "原账单编号:{},新账单编号:{}";
|
public static final String copy_bill_text = "原账单编号:{},新账单编号:{}";
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 红冲账单
|
||||||
|
* 红冲账单编号:{},红冲金额:{}元
|
||||||
|
*/
|
||||||
|
public static final String red_flush_bill_title = "红冲账单";
|
||||||
|
public static final String red_flush_bill_text = "红冲账单编号:{},红冲金额:{}元";
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -47,8 +47,8 @@ public class BillManageDTO extends BaseVOEntity{
|
|||||||
@Excel(name = "账单类型", readConverterExp = "1=-应收,2-应付")
|
@Excel(name = "账单类型", readConverterExp = "1=-应收,2-应付")
|
||||||
private Integer billType;
|
private Integer billType;
|
||||||
|
|
||||||
@ApiModelProperty("账单状态(1-未确认,2-对账中,3-未收款/付款,4-部分收款/付款,5-已收款/付款,6-已作废,7-已退款)")
|
@ApiModelProperty("账单状态(1-未确认,2-对账中,3-未收款/付款,4-部分收款/付款,5-已收款/付款,6-已作废,7-已退款,8-红冲)")
|
||||||
@Excel(name = "账单状态", readConverterExp = "1=-未确认,2-对账中,3-未收款/付款,4-部分收款/付款,5-已收款/付款,6-已作废,7-已退款")
|
@Excel(name = "账单状态", readConverterExp = "1=-未确认,2-对账中,3-未收款/付款,4-部分收款/付款,5-已收款/付款,6-已作废,7-已退款,8-红冲")
|
||||||
private Integer billState;
|
private Integer billState;
|
||||||
|
|
||||||
@ApiModelProperty("账单流程节点(1-发起对账,2-客户确认,3-财务审核,4-收款/付款)")
|
@ApiModelProperty("账单流程节点(1-发起对账,2-客户确认,3-财务审核,4-收款/付款)")
|
||||||
@@ -276,4 +276,11 @@ public class BillManageDTO extends BaseVOEntity{
|
|||||||
private String paymentAccountId;
|
private String paymentAccountId;
|
||||||
@ApiModelProperty("收款帐户名称")
|
@ApiModelProperty("收款帐户名称")
|
||||||
private String paymentAccountName;
|
private String paymentAccountName;
|
||||||
|
|
||||||
|
@ApiModelProperty("账单月份(yyyy-MM,按创建时间月份筛选,用于客户月账单分组查询)")
|
||||||
|
private String billMonth;
|
||||||
|
|
||||||
|
@ApiModelProperty("红冲原因")
|
||||||
|
@Excel(name = "红冲原因")
|
||||||
|
private String redFlushRemark;
|
||||||
}
|
}
|
||||||
@@ -28,7 +28,7 @@ public class BillManageExportVO {
|
|||||||
@Excel(name = "账单类型", readConverterExp = "1=-应收,2-应付")
|
@Excel(name = "账单类型", readConverterExp = "1=-应收,2-应付")
|
||||||
private Integer billType;
|
private Integer billType;
|
||||||
|
|
||||||
@Excel(name = "账单状态", readConverterExp = "1=-未确认,2-对账中,3-未收款/付款,4-部分收款/付款,5-已收款/付款,6-已作废,7-已退款")
|
@Excel(name = "账单状态", readConverterExp = "1=-未确认,2-对账中,3-未收款/付款,4-部分收款/付款,5-已收款/付款,6-已作废,7-已退款,8-红冲")
|
||||||
private Integer billState;
|
private Integer billState;
|
||||||
|
|
||||||
@Excel(name = "账单流程节点", readConverterExp = "1=-发起对账,2-客户确认,3-财务审核,4-收款/付款")
|
@Excel(name = "账单流程节点", readConverterExp = "1=-发起对账,2-客户确认,3-财务审核,4-收款/付款")
|
||||||
|
|||||||
@@ -0,0 +1,65 @@
|
|||||||
|
package com.mhd.bms.interfaces.dto.billManage;
|
||||||
|
|
||||||
|
import io.swagger.annotations.ApiModel;
|
||||||
|
import io.swagger.annotations.ApiModelProperty;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
@ApiModel(value = "客户月账单VO", description = "客户每月账单分组统计信息")
|
||||||
|
public class CustomerMonthBillVO implements Serializable {
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
@ApiModelProperty("结算对象id")
|
||||||
|
private Long settlementCustomersId;
|
||||||
|
|
||||||
|
@ApiModelProperty("结算对象code")
|
||||||
|
private String settlementCustomersCode;
|
||||||
|
|
||||||
|
@ApiModelProperty("结算对象/客户名称")
|
||||||
|
private String settlementEntity;
|
||||||
|
|
||||||
|
@ApiModelProperty("结算主体id")
|
||||||
|
private Long settlementEntityId;
|
||||||
|
|
||||||
|
@ApiModelProperty("结算主体")
|
||||||
|
private String settlementEntityName;
|
||||||
|
|
||||||
|
@ApiModelProperty("组织ID")
|
||||||
|
private Long organizationId;
|
||||||
|
|
||||||
|
@ApiModelProperty("组织名称")
|
||||||
|
private String organizationName;
|
||||||
|
|
||||||
|
@ApiModelProperty("账单月份(yyyy-MM)")
|
||||||
|
private String billMonth;
|
||||||
|
|
||||||
|
@ApiModelProperty("账单总金额合计")
|
||||||
|
private BigDecimal totalBillAmount;
|
||||||
|
|
||||||
|
@ApiModelProperty("已收金额合计")
|
||||||
|
private BigDecimal totalSettledAmount;
|
||||||
|
|
||||||
|
@ApiModelProperty("未收金额合计")
|
||||||
|
private BigDecimal totalUnsettledAmount;
|
||||||
|
|
||||||
|
@ApiModelProperty("账单数量")
|
||||||
|
private Integer billCount;
|
||||||
|
|
||||||
|
@ApiModelProperty("付款状态(1-未付款,2-部分付款,3-已付款)")
|
||||||
|
private Integer paymentStatus;
|
||||||
|
|
||||||
|
@ApiModelProperty("付款状态名称")
|
||||||
|
private String paymentStatusName;
|
||||||
|
|
||||||
|
@ApiModelProperty("应收账单id列表(逗号拼接)")
|
||||||
|
private String billManageIds;
|
||||||
|
|
||||||
|
@ApiModelProperty("结算方式")
|
||||||
|
private String settlementMethod;
|
||||||
|
|
||||||
|
@ApiModelProperty("默认结算币种")
|
||||||
|
private String settlementCurrency;
|
||||||
|
}
|
||||||
+2
-2
@@ -40,8 +40,8 @@ public class BillOperationLogDTO extends BaseVOEntity{
|
|||||||
@Excel(name = "账单管理id")
|
@Excel(name = "账单管理id")
|
||||||
private Long billManageId;
|
private Long billManageId;
|
||||||
|
|
||||||
@ApiModelProperty("操作类型(1-创建账单,2-调整账单,3-确认账单,4-发起对账,5-客户确认,6-财务审核,7-收款,8-作废账单,9-删除账单,10-退款,11-付款)")
|
@ApiModelProperty("操作类型(1-创建账单,2-调整账单,3-确认账单,4-发起对账,5-客户确认,6-财务审核,7-收款,8-作废账单,9-删除账单,10-退款,11-付款,12-撤销收款,13-红冲)")
|
||||||
@Excel(name = "操作类型", readConverterExp = "1=-创建账单,2-调整账单,3-确认账单,4-发起对账,5-客户确认,6-财务审核,7-收款,8-作废账单,9-删除账单,10-退款,11-付款")
|
@Excel(name = "操作类型", readConverterExp = "1=-创建账单,2-调整账单,3-确认账单,4-发起对账,5-客户确认,6-财务审核,7-收款,8-作废账单,9-删除账单,10-退款,11-付款,12-撤销收款,13-红冲")
|
||||||
private Integer operationType;
|
private Integer operationType;
|
||||||
|
|
||||||
@ApiModelProperty("操作信息")
|
@ApiModelProperty("操作信息")
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ package com.mhd.bms.interfaces.facadeApi;
|
|||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
import java.math.BigDecimal;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
import java.util.stream.Stream;
|
import java.util.stream.Stream;
|
||||||
@@ -17,6 +18,7 @@ import com.mhd.bms.infrastructure.utils.UniqueKeyUtil;
|
|||||||
import com.mhd.bms.interfaces.dto.billingStatement.BillingStatementDTO;
|
import com.mhd.bms.interfaces.dto.billingStatement.BillingStatementDTO;
|
||||||
import com.mhd.bms.interfaces.dto.billManage.BillManageExportVO;
|
import com.mhd.bms.interfaces.dto.billManage.BillManageExportVO;
|
||||||
import com.mhd.common.core.exception.ServiceException;
|
import com.mhd.common.core.exception.ServiceException;
|
||||||
|
import com.mhd.common.core.utils.StringUtils;
|
||||||
import com.mhd.common.core.utils.poi.ExcelUtil;
|
import com.mhd.common.core.utils.poi.ExcelUtil;
|
||||||
import com.mhd.common.log.annotation.Log;
|
import com.mhd.common.log.annotation.Log;
|
||||||
import com.mhd.common.log.enums.BusinessType;
|
import com.mhd.common.log.enums.BusinessType;
|
||||||
@@ -31,9 +33,17 @@ import org.springframework.beans.factory.annotation.Autowired;
|
|||||||
import org.springframework.context.annotation.Bean;
|
import org.springframework.context.annotation.Bean;
|
||||||
import org.springframework.web.bind.annotation.*;
|
import org.springframework.web.bind.annotation.*;
|
||||||
import com.mhd.bms.interfaces.dto.billManage.BillManageDTO;
|
import com.mhd.bms.interfaces.dto.billManage.BillManageDTO;
|
||||||
|
import com.mhd.bms.interfaces.dto.billManage.CustomerMonthBillVO;
|
||||||
import com.mhd.bms.domain.billManage.repository.todo.BillManageDO;
|
import com.mhd.bms.domain.billManage.repository.todo.BillManageDO;
|
||||||
import com.mhd.bms.domain.billManage.repository.po.BillManagePO;
|
import com.mhd.bms.domain.billManage.repository.po.BillManagePO;
|
||||||
import com.mhd.bms.interfaces.assembler.billManage.BillManageAssembler;
|
import com.mhd.bms.interfaces.assembler.billManage.BillManageAssembler;
|
||||||
|
import com.mhd.bms.domain.receiptManage.service.ReceiptDetailDomainService;
|
||||||
|
import com.mhd.bms.domain.receiptManage.entity.ReceiptDetail;
|
||||||
|
import com.mhd.bms.domain.receiptManage.entity.ReceiptManage;
|
||||||
|
import com.mhd.bms.domain.receiptManage.repository.facade.IReceiptManageService;
|
||||||
|
import com.mhd.bms.domain.receiptManage.repository.po.ReceiptManagePO;
|
||||||
|
import com.mhd.bms.domain.receiptManage.repository.po.ReceiptDetailPO;
|
||||||
|
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||||
import javax.annotation.Resource;
|
import javax.annotation.Resource;
|
||||||
import javax.servlet.http.HttpServletResponse;
|
import javax.servlet.http.HttpServletResponse;
|
||||||
import com.mhd.common.core.web.controller.BaseController;
|
import com.mhd.common.core.web.controller.BaseController;
|
||||||
@@ -54,6 +64,10 @@ public class BillManageApi extends BaseController{
|
|||||||
private BillManageApplicationService billManageApplicationService;
|
private BillManageApplicationService billManageApplicationService;
|
||||||
@Autowired
|
@Autowired
|
||||||
private RedisLock redisLock;
|
private RedisLock redisLock;
|
||||||
|
@Autowired
|
||||||
|
private ReceiptDetailDomainService receiptDetailDomainService;
|
||||||
|
@Autowired
|
||||||
|
private IReceiptManageService receiptManageService;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 分页查询账单管理列表
|
* 分页查询账单管理列表
|
||||||
@@ -84,6 +98,171 @@ public class BillManageApi extends BaseController{
|
|||||||
return AjaxResult.success(billManageApplicationService.listCount(billManageDO));
|
return AjaxResult.success(billManageApplicationService.listCount(billManageDO));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 客户每月账单分组列表(应收)
|
||||||
|
*/
|
||||||
|
@ApiOperation("客户每月账单分组列表")
|
||||||
|
@GetMapping("/receivableCustomerMonthList")
|
||||||
|
public TableDataInfo receivableCustomerMonthList(BillManageDTO billManageDTO)
|
||||||
|
{
|
||||||
|
BillManageDO billManageDO = new BillManageDO();
|
||||||
|
BeanUtils.copyProperties(billManageDTO, billManageDO);
|
||||||
|
billManageDO.setBillType(1);
|
||||||
|
startPage();
|
||||||
|
List<CustomerMonthBillVO> list = billManageApplicationService.queryCustomerMonthBillList(billManageDO);
|
||||||
|
return getDataTable(list);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 客户每月账单分组列表统计(应收)
|
||||||
|
*/
|
||||||
|
@ApiOperation("客户每月账单分组列表统计")
|
||||||
|
@GetMapping(value = "/receivableCustomerMonthListCount")
|
||||||
|
public AjaxResult receivableCustomerMonthListCount(BillManageDTO billManageDTO)
|
||||||
|
{
|
||||||
|
BillManageDO billManageDO = new BillManageDO();
|
||||||
|
BeanUtils.copyProperties(billManageDTO, billManageDO);
|
||||||
|
billManageDO.setBillType(1);
|
||||||
|
List<CustomerMonthBillVO> list = billManageApplicationService.queryCustomerMonthBillList(billManageDO);
|
||||||
|
BigDecimal totalBillAmount = list.stream()
|
||||||
|
.map(CustomerMonthBillVO::getTotalBillAmount)
|
||||||
|
.filter(java.util.Objects::nonNull)
|
||||||
|
.reduce(java.math.BigDecimal.ZERO, java.math.BigDecimal::add);
|
||||||
|
BigDecimal totalSettledAmount = list.stream()
|
||||||
|
.map(CustomerMonthBillVO::getTotalSettledAmount)
|
||||||
|
.filter(java.util.Objects::nonNull)
|
||||||
|
.reduce(java.math.BigDecimal.ZERO, java.math.BigDecimal::add);
|
||||||
|
BigDecimal totalUnsettledAmount = list.stream()
|
||||||
|
.map(CustomerMonthBillVO::getTotalUnsettledAmount)
|
||||||
|
.filter(java.util.Objects::nonNull)
|
||||||
|
.reduce(java.math.BigDecimal.ZERO, java.math.BigDecimal::add);
|
||||||
|
java.util.Map<String, Object> resultMap = new java.util.HashMap<>();
|
||||||
|
resultMap.put("totalBillAmount", totalBillAmount);
|
||||||
|
resultMap.put("totalSettledAmount", totalSettledAmount);
|
||||||
|
resultMap.put("totalUnsettledAmount", totalUnsettledAmount);
|
||||||
|
resultMap.put("totalCount", list.size());
|
||||||
|
return AjaxResult.success(resultMap);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据账单ID列表查询应收账单详情(客户月账单点击账单数量回显)
|
||||||
|
*/
|
||||||
|
@ApiOperation("根据账单ID列表查询应收账单详情")
|
||||||
|
@GetMapping("/receivableDetailByMonth")
|
||||||
|
public TableDataInfo receivableDetailByMonth(BillManageDTO billManageDTO)
|
||||||
|
{
|
||||||
|
if (billManageDTO.getBillManageIds() != null && !billManageDTO.getBillManageIds().isEmpty()) {
|
||||||
|
Set<String> idSet = java.util.Arrays.stream(billManageDTO.getBillManageIds().split(","))
|
||||||
|
.collect(java.util.stream.Collectors.toSet());
|
||||||
|
billManageDTO.setBillManageIdSet(idSet);
|
||||||
|
}
|
||||||
|
BillManageDO billManageDO = new BillManageDO();
|
||||||
|
BeanUtils.copyProperties(billManageDTO, billManageDO);
|
||||||
|
billManageDO.setBillType(1);
|
||||||
|
startPage();
|
||||||
|
List<BillManagePO> list = billManageApplicationService.queryList(billManageDO);
|
||||||
|
return getDataTable(list);
|
||||||
|
}
|
||||||
|
|
||||||
|
@ApiOperation("根据账单ID列表查询应收账单汇总")
|
||||||
|
@GetMapping("/receivableSumByMonth")
|
||||||
|
public AjaxResult receivableSumByMonth(BillManageDTO billManageDTO)
|
||||||
|
{
|
||||||
|
if (billManageDTO.getBillManageIds() != null && !billManageDTO.getBillManageIds().isEmpty()) {
|
||||||
|
Set<String> idSet = java.util.Arrays.stream(billManageDTO.getBillManageIds().split(","))
|
||||||
|
.collect(java.util.stream.Collectors.toSet());
|
||||||
|
billManageDTO.setBillManageIdSet(idSet);
|
||||||
|
}
|
||||||
|
BillManageDO billManageDO = new BillManageDO();
|
||||||
|
BeanUtils.copyProperties(billManageDTO, billManageDO);
|
||||||
|
billManageDO.setBillType(1);
|
||||||
|
List<BillManagePO> list = billManageApplicationService.queryList(billManageDO);
|
||||||
|
|
||||||
|
Set<Long> billManageIdSet = list.stream()
|
||||||
|
.map(BillManagePO::getBillManageId)
|
||||||
|
.filter(java.util.Objects::nonNull)
|
||||||
|
.collect(java.util.stream.Collectors.toSet());
|
||||||
|
|
||||||
|
List<ReceiptDetail> allReceiptDetails = new ArrayList<>();
|
||||||
|
Set<Long> receiptManageIdSet = new java.util.HashSet<>();
|
||||||
|
List<ReceiptManagePO> receiptManageList = new ArrayList<>();
|
||||||
|
|
||||||
|
if (!billManageIdSet.isEmpty()) {
|
||||||
|
allReceiptDetails = receiptDetailDomainService.queryListByLambda(
|
||||||
|
new LambdaQueryWrapper<ReceiptDetail>()
|
||||||
|
.in(ReceiptDetail::getBillManageId, billManageIdSet)
|
||||||
|
.eq(ReceiptDetail::getDelFlag, 1));
|
||||||
|
|
||||||
|
java.util.Map<Long, List<ReceiptDetail>> detailByBillId = allReceiptDetails.stream()
|
||||||
|
.collect(java.util.stream.Collectors.groupingBy(ReceiptDetail::getBillManageId));
|
||||||
|
for (BillManagePO bill : list) {
|
||||||
|
bill.setReceiptDetailList(detailByBillId.getOrDefault(bill.getBillManageId(), new ArrayList<>()));
|
||||||
|
}
|
||||||
|
|
||||||
|
receiptManageIdSet = allReceiptDetails.stream()
|
||||||
|
.map(ReceiptDetail::getReceiptManageId)
|
||||||
|
.filter(java.util.Objects::nonNull)
|
||||||
|
.collect(java.util.stream.Collectors.toSet());
|
||||||
|
|
||||||
|
if (!receiptManageIdSet.isEmpty()) {
|
||||||
|
List<ReceiptManage> manages = receiptManageService.list(
|
||||||
|
new LambdaQueryWrapper<ReceiptManage>()
|
||||||
|
.in(ReceiptManage::getReceiptManageId, receiptManageIdSet)
|
||||||
|
.eq(ReceiptManage::getDelFlag, 1));
|
||||||
|
|
||||||
|
java.util.Map<Long, List<ReceiptDetailPO>> detailPOByManageId = allReceiptDetails.stream()
|
||||||
|
.map(d -> {
|
||||||
|
ReceiptDetailPO po = new ReceiptDetailPO();
|
||||||
|
BeanUtils.copyProperties(d, po);
|
||||||
|
return po;
|
||||||
|
})
|
||||||
|
.collect(java.util.stream.Collectors.groupingBy(ReceiptDetailPO::getReceiptManageId));
|
||||||
|
|
||||||
|
for (ReceiptManage m : manages) {
|
||||||
|
ReceiptManagePO po = new ReceiptManagePO();
|
||||||
|
BeanUtils.copyProperties(m, po);
|
||||||
|
po.setReceiptDetailPOList(detailPOByManageId.getOrDefault(m.getReceiptManageId(), new ArrayList<>()));
|
||||||
|
receiptManageList.add(po);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
BigDecimal totalBillAmount = list.stream()
|
||||||
|
.map(BillManagePO::getBillAmount)
|
||||||
|
.filter(java.util.Objects::nonNull)
|
||||||
|
.reduce(BigDecimal.ZERO, BigDecimal::add);
|
||||||
|
BigDecimal totalSettledAmount = list.stream()
|
||||||
|
.map(BillManagePO::getBillAmountSettlement)
|
||||||
|
.filter(java.util.Objects::nonNull)
|
||||||
|
.reduce(BigDecimal.ZERO, BigDecimal::add);
|
||||||
|
BigDecimal totalUnsettledAmount = list.stream()
|
||||||
|
.map(BillManagePO::getBillAmountUnsettled)
|
||||||
|
.filter(java.util.Objects::nonNull)
|
||||||
|
.reduce(BigDecimal.ZERO, BigDecimal::add);
|
||||||
|
int billCount = list.size();
|
||||||
|
|
||||||
|
String collectionStatus;
|
||||||
|
if (billCount == 0) {
|
||||||
|
collectionStatus = "无数据";
|
||||||
|
} else if (totalUnsettledAmount.compareTo(BigDecimal.ZERO) == 0) {
|
||||||
|
collectionStatus = "已收款";
|
||||||
|
} else if (totalSettledAmount.compareTo(BigDecimal.ZERO) == 0) {
|
||||||
|
collectionStatus = "未收款";
|
||||||
|
} else {
|
||||||
|
collectionStatus = "部分收款";
|
||||||
|
}
|
||||||
|
|
||||||
|
java.util.Map<String, Object> resultMap = new java.util.HashMap<>();
|
||||||
|
resultMap.put("totalBillAmount", totalBillAmount);
|
||||||
|
resultMap.put("totalSettledAmount", totalSettledAmount);
|
||||||
|
resultMap.put("totalUnsettledAmount", totalUnsettledAmount);
|
||||||
|
resultMap.put("billCount", billCount);
|
||||||
|
resultMap.put("collectionStatus", collectionStatus);
|
||||||
|
resultMap.put("billList", list);
|
||||||
|
resultMap.put("receiptManageList", receiptManageList);
|
||||||
|
return AjaxResult.success(resultMap);
|
||||||
|
}
|
||||||
|
|
||||||
@ApiOperation("导出应收账单")
|
@ApiOperation("导出应收账单")
|
||||||
@GetMapping(value = "/exportReceivableList", produces = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet")
|
@GetMapping(value = "/exportReceivableList", produces = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet")
|
||||||
public void exportReceivableList(BillManageDTO billManageDTO, HttpServletResponse response) throws IOException
|
public void exportReceivableList(BillManageDTO billManageDTO, HttpServletResponse response) throws IOException
|
||||||
@@ -328,6 +507,46 @@ public class BillManageApi extends BaseController{
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ApiOperation("应收账单-红冲")
|
||||||
|
@PostMapping("/redFlushBill")
|
||||||
|
public AjaxResult redFlushBill(@RequestBody BillManageDTO billManageDTO)
|
||||||
|
{
|
||||||
|
if(!StringUtils.isNotEmpty(billManageDTO.getBillManageIds())){
|
||||||
|
throw new ServiceException("账单id不能为空");
|
||||||
|
}
|
||||||
|
//批量加锁
|
||||||
|
RedissonMultiLock redissonMultiLock = null;
|
||||||
|
boolean lockFlag = false;
|
||||||
|
try {
|
||||||
|
RedisLockTypeEnum redisLockTypeEnum = RedisLockTypeEnum.BMS;
|
||||||
|
List<RLock> locks = new ArrayList<>();
|
||||||
|
Set<String> billIdSet = Stream.of(billManageDTO.getBillManageIds().split(",")).filter(StringUtils::isNotEmpty).map(String::trim).collect(Collectors.toSet());
|
||||||
|
billIdSet.forEach(x -> {
|
||||||
|
//获取唯一key值
|
||||||
|
String key = redisLockTypeEnum.getUniqueKey(UniqueKeyUtil.getBillingKey(x));
|
||||||
|
locks.add(redisLock.getRLock(key));
|
||||||
|
});
|
||||||
|
redissonMultiLock = new RedissonMultiLock(locks.toArray(new RLock[billIdSet.size()]));
|
||||||
|
//尝试获取锁 不等待 持有锁10分钟
|
||||||
|
lockFlag = redissonMultiLock.tryLock(-1, 10, TimeUnit.MINUTES);
|
||||||
|
if (!lockFlag) {
|
||||||
|
redissonMultiLock = null;
|
||||||
|
throw new ServiceException("账单正在操作中,请稍后重试");
|
||||||
|
}
|
||||||
|
log.info("红冲账单加锁成功");
|
||||||
|
billManageApplicationService.redFlushBill(billManageDTO);
|
||||||
|
return AjaxResult.success("操作成功");
|
||||||
|
}catch (Exception e){
|
||||||
|
return AjaxResult.error("红冲账单失败:"+e.getMessage());
|
||||||
|
} finally {
|
||||||
|
if (redissonMultiLock != null && lockFlag){
|
||||||
|
redissonMultiLock.unlock();
|
||||||
|
log.info("红冲账单释放锁成功");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@ApiOperation("应收账单-客户确认")
|
@ApiOperation("应收账单-客户确认")
|
||||||
@PostMapping("/customerConfirmation")
|
@PostMapping("/customerConfirmation")
|
||||||
public AjaxResult customerConfirmation(@RequestBody BillManageDTO billManageDTO)
|
public AjaxResult customerConfirmation(@RequestBody BillManageDTO billManageDTO)
|
||||||
@@ -438,6 +657,21 @@ public class BillManageApi extends BaseController{
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 客户月结报表
|
||||||
|
*/
|
||||||
|
@ApiOperation("客户月结报表")
|
||||||
|
@GetMapping("/customerMonthlyReport")
|
||||||
|
public TableDataInfo customerMonthlyReport(BillManageDTO billManageDTO)
|
||||||
|
{
|
||||||
|
//转换实体
|
||||||
|
BillManageDO billManageDO = new BillManageDO();
|
||||||
|
BeanUtils.copyProperties(billManageDTO,billManageDO);
|
||||||
|
startPage();
|
||||||
|
billManageDO.setBillType(1);
|
||||||
|
List<BillManagePO> list = billManageApplicationService.customerMonthlyReport(billManageDO);
|
||||||
|
return getDataTable(list);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -339,7 +339,10 @@ public class BillingStatementApi extends BaseController {
|
|||||||
String shipperId = XxlJobHelper.getJobParam();
|
String shipperId = XxlJobHelper.getJobParam();
|
||||||
logger.info("XXL-JOB 开始入库业务单推送bms计费流水,货主id参数:{}", shipperId);
|
logger.info("XXL-JOB 开始入库业务单推送bms计费流水,货主id参数:{}", shipperId);
|
||||||
try {
|
try {
|
||||||
|
//干仓
|
||||||
billingStatementApplicationService.pushBillManage(shipperId);
|
billingStatementApplicationService.pushBillManage(shipperId);
|
||||||
|
//冻仓
|
||||||
|
billingStatementApplicationService.pushBillManageDC(shipperId);
|
||||||
// 设置任务执行结果
|
// 设置任务执行结果
|
||||||
XxlJobHelper.handleSuccess("入库业务单推送bms计费流水执行成功");
|
XxlJobHelper.handleSuccess("入库业务单推送bms计费流水执行成功");
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
|
|||||||
@@ -1,8 +1,10 @@
|
|||||||
package com.mhd.bms.interfaces.facadeApi;
|
package com.mhd.bms.interfaces.facadeApi;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.LinkedHashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
import java.util.TreeSet;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
import java.util.stream.Stream;
|
import java.util.stream.Stream;
|
||||||
@@ -55,6 +57,11 @@ public class ReceiptManageApi extends BaseController{
|
|||||||
@Autowired
|
@Autowired
|
||||||
private RedisLock redisLock;
|
private RedisLock redisLock;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 排队批量收款-获取账单锁的最大等待时间(秒),等待期内排队获取锁,避免并发收款直接失败
|
||||||
|
*/
|
||||||
|
private static final long QUEUE_COLLECTION_LOCK_WAIT_SECONDS = 30L;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 分页查询收款单管理列表
|
* 分页查询收款单管理列表
|
||||||
*/
|
*/
|
||||||
@@ -114,6 +121,116 @@ public class ReceiptManageApi extends BaseController{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 排队批量收款
|
||||||
|
* 接收多个批量收款请求参数集合,整体加锁后按顺序排队依次处理;
|
||||||
|
* 同一账单分多次收款时前一笔处理完成后才处理下一笔,避免redis锁冲突导致收款失败;
|
||||||
|
* 整个集合在同一事务内处理,任意一笔收款失败则全部回滚
|
||||||
|
*/
|
||||||
|
@ApiOperation("排队批量收款")
|
||||||
|
@RepeatSubmit
|
||||||
|
@PostMapping("/queueBatchCollection")
|
||||||
|
public AjaxResult queueBatchCollection(@RequestBody List<ReceiptManageDTO> receiptManageDTOList)
|
||||||
|
{
|
||||||
|
if(StringUtils.isEmpty(receiptManageDTOList)){
|
||||||
|
throw new ServiceException("收款账单不能为空");
|
||||||
|
}
|
||||||
|
//汇总所有收款请求涉及的账单id并排序,整体加锁,保证事务期间锁不释放且加锁顺序一致避免死锁
|
||||||
|
Set<String> lockKeySet = new TreeSet<>();
|
||||||
|
for (ReceiptManageDTO receiptManageDTO : receiptManageDTOList) {
|
||||||
|
if(!StringUtils.isNotEmpty(receiptManageDTO.getBillManageIds())){
|
||||||
|
throw new ServiceException("收款账单不能为空");
|
||||||
|
}
|
||||||
|
lockKeySet.addAll(Stream.of(receiptManageDTO.getBillManageIds().split(",")).filter(StringUtils::isNotEmpty).map(String::trim).collect(Collectors.toSet()));
|
||||||
|
}
|
||||||
|
RedisLockTypeEnum redisLockTypeEnum = RedisLockTypeEnum.BMS;
|
||||||
|
List<RLock> locks = new ArrayList<>();
|
||||||
|
lockKeySet.forEach(x -> {
|
||||||
|
//获取唯一key值
|
||||||
|
String key = redisLockTypeEnum.getUniqueKey(UniqueKeyUtil.getBillingKey(x));
|
||||||
|
locks.add(redisLock.getRLock(key));
|
||||||
|
});
|
||||||
|
RedissonMultiLock redissonMultiLock = new RedissonMultiLock(locks.toArray(new RLock[lockKeySet.size()]));
|
||||||
|
boolean payInfoDetailLock = false;
|
||||||
|
try {
|
||||||
|
//尝试获取锁 等待指定时间内排队获取 持有锁10分钟
|
||||||
|
payInfoDetailLock = redissonMultiLock.tryLock(QUEUE_COLLECTION_LOCK_WAIT_SECONDS, 10, TimeUnit.MINUTES);
|
||||||
|
if (!payInfoDetailLock) {
|
||||||
|
redissonMultiLock = null;
|
||||||
|
return AjaxResult.error("账单正在处理,请稍后再试");
|
||||||
|
}
|
||||||
|
log.info("排队批量收款-生成账单加锁成功");
|
||||||
|
//转换实体
|
||||||
|
List<ReceiptManageDO> receiptManageDOList = new ArrayList<>();
|
||||||
|
for (ReceiptManageDTO receiptManageDTO : receiptManageDTOList) {
|
||||||
|
ReceiptManageDO receiptManageDO = new ReceiptManageDO();
|
||||||
|
BeanUtils.copyProperties(receiptManageDTO,receiptManageDO);
|
||||||
|
receiptManageDOList.add(receiptManageDO);
|
||||||
|
}
|
||||||
|
//事务内排队逐笔收款,任意一笔失败全部回滚
|
||||||
|
return toAjax(receiptManageApplicationService.queueBatchCollection(receiptManageDOList));
|
||||||
|
}catch (Exception e){
|
||||||
|
//异常已在应用服务层事务内标记回滚(收款失败必回滚),此处仅返回失败结果
|
||||||
|
return AjaxResult.error("收款失败:" + e.getMessage());
|
||||||
|
}finally {
|
||||||
|
if (redissonMultiLock != null && payInfoDetailLock) {
|
||||||
|
redissonMultiLock.unlock();
|
||||||
|
log.info("排队批量收款-生成账单释放了锁");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 撤销收款
|
||||||
|
*/
|
||||||
|
@ApiOperation("撤销收款")
|
||||||
|
@RepeatSubmit
|
||||||
|
@PostMapping("/cancelCollection")
|
||||||
|
public AjaxResult cancelCollection(@RequestBody ReceiptManageDTO receiptManageDTO)
|
||||||
|
{
|
||||||
|
if(!StringUtils.isNotEmpty(receiptManageDTO.getBillManageIds())){
|
||||||
|
throw new ServiceException("撤销账单不能为空");
|
||||||
|
}
|
||||||
|
RedissonMultiLock redissonMultiLock = null;
|
||||||
|
boolean payInfoDetailLock = false;
|
||||||
|
try {
|
||||||
|
RedisLockTypeEnum redisLockTypeEnum = RedisLockTypeEnum.BMS;
|
||||||
|
List<RLock> locks = new ArrayList<>();
|
||||||
|
//账单id与涉及的收款单id去重后加锁,避免同一把锁重复加锁
|
||||||
|
Set<String> lockKeySet = new LinkedHashSet<>();
|
||||||
|
lockKeySet.addAll(Stream.of(receiptManageDTO.getBillManageIds().split(",")).filter(StringUtils::isNotEmpty).map(String::trim).collect(Collectors.toSet()));
|
||||||
|
//查询账单涉及的收款单,一并加锁,避免并发撤销时收款单金额重算冲突
|
||||||
|
Set<Long> receiptManageIdSet = receiptManageApplicationService.queryCancelCollectionReceiptManageIds(receiptManageDTO.getBillManageIds());
|
||||||
|
if (null != receiptManageIdSet) {
|
||||||
|
receiptManageIdSet.forEach(x -> lockKeySet.add(String.valueOf(x)));
|
||||||
|
}
|
||||||
|
lockKeySet.forEach(x -> {
|
||||||
|
//获取唯一key值
|
||||||
|
String key = redisLockTypeEnum.getUniqueKey(UniqueKeyUtil.getBillingKey(x));
|
||||||
|
locks.add(redisLock.getRLock(key));
|
||||||
|
});
|
||||||
|
redissonMultiLock = new RedissonMultiLock(locks.toArray(new RLock[lockKeySet.size()]));
|
||||||
|
//尝试获取锁 不等待 持有锁10分钟
|
||||||
|
payInfoDetailLock = redissonMultiLock.tryLock(-1, 10, TimeUnit.MINUTES);
|
||||||
|
if (!payInfoDetailLock) {
|
||||||
|
redissonMultiLock = null;
|
||||||
|
return AjaxResult.error("收款单正在处理,请稍后再试");
|
||||||
|
}
|
||||||
|
log.info("撤销收款加锁成功");
|
||||||
|
//转换实体
|
||||||
|
ReceiptManageDO receiptManageDO = new ReceiptManageDO();
|
||||||
|
BeanUtils.copyProperties(receiptManageDTO,receiptManageDO);
|
||||||
|
return toAjax(receiptManageApplicationService.cancelCollection(receiptManageDO));
|
||||||
|
}catch (Exception e){
|
||||||
|
return AjaxResult.error("撤销收款失败:" + e.getMessage());
|
||||||
|
}finally {
|
||||||
|
if (redissonMultiLock != null && payInfoDetailLock) {
|
||||||
|
redissonMultiLock.unlock();
|
||||||
|
log.info("撤销收款释放了锁");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 批量删除收款单管理
|
* 批量删除收款单管理
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -22,7 +22,56 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
|||||||
ORDER BY a.create_time DESC
|
ORDER BY a.create_time DESC
|
||||||
</select>
|
</select>
|
||||||
|
|
||||||
|
<select id="customerMonthlyReport" parameterType="com.mhd.bms.domain.billManage.repository.todo.BillManageDO" resultType="com.mhd.bms.domain.billManage.repository.po.BillManagePO">
|
||||||
|
SELECT
|
||||||
|
a.*,
|
||||||
|
b.SETTLEMENT_ENTITY_ID AS "settlementEntityId",
|
||||||
|
(SELECT MAX(c.collection_time)
|
||||||
|
FROM receipt_detail rd
|
||||||
|
LEFT JOIN receipt_manage c ON rd.receipt_manage_id = c.receipt_manage_id
|
||||||
|
WHERE rd.bill_manage_id = a.bill_manage_id
|
||||||
|
AND rd.del_flag = 1
|
||||||
|
AND c.del_flag = 1) AS "collectionTime",
|
||||||
|
(SELECT LISTAGG(bs.CONTRACT_NUMBER, ',') WITHIN GROUP (ORDER BY bs.CONTRACT_NUMBER)
|
||||||
|
FROM BILLING_STATEMENT bs
|
||||||
|
WHERE bs.BILL_MANAGE_ID = a.bill_manage_id
|
||||||
|
AND bs.CONTRACT_NUMBER IS NOT NULL) AS "contractNumbers"
|
||||||
|
FROM bill_manage a
|
||||||
|
LEFT JOIN SETTLEMENT_CUSTOMERS b ON a.SETTLEMENT_CUSTOMERS_ID = b.SETTLEMENT_CUSTOMERS_ID
|
||||||
|
WHERE a.del_flag = 1
|
||||||
|
<include refid="common_where"/>
|
||||||
|
ORDER BY a.create_time DESC
|
||||||
|
</select>
|
||||||
|
|
||||||
|
<select id="queryCustomerMonthBillList" parameterType="com.mhd.bms.domain.billManage.repository.todo.BillManageDO" resultType="com.mhd.bms.interfaces.dto.billManage.CustomerMonthBillVO">
|
||||||
|
SELECT
|
||||||
|
a.SETTLEMENT_CUSTOMERS_ID AS settlementCustomersId,
|
||||||
|
a.SETTLEMENT_CUSTOMERS_CODE AS settlementCustomersCode,
|
||||||
|
a.SETTLEMENT_ENTITY AS settlementEntity,
|
||||||
|
b.SETTLEMENT_ENTITY_ID AS settlementEntityId,
|
||||||
|
b.SETTLEMENT_ENTITY AS settlementEntityName,
|
||||||
|
a.ORGANIZATION_ID AS organizationId,
|
||||||
|
a.ORGANIZATION_NAME AS organizationName,
|
||||||
|
TO_CHAR(a.CREATE_TIME, 'YYYY-MM') AS billMonth,
|
||||||
|
SUM(a.BILL_AMOUNT) AS totalBillAmount,
|
||||||
|
SUM(NVL(a.BILL_AMOUNT_SETTLEMENT, 0)) AS totalSettledAmount,
|
||||||
|
SUM(NVL(a.BILL_AMOUNT_UNSETTLED, 0)) AS totalUnsettledAmount,
|
||||||
|
COUNT(*) AS billCount,
|
||||||
|
LISTAGG(a.BILL_MANAGE_ID, ',') WITHIN GROUP (ORDER BY a.BILL_MANAGE_ID) AS billManageIds,
|
||||||
|
b.SETTLEMENT_METHOD AS settlementMethod,
|
||||||
|
b.SETTLEMENT_CURRENCY AS settlementCurrency
|
||||||
|
FROM bill_manage a
|
||||||
|
LEFT JOIN SETTLEMENT_CUSTOMERS b ON a.SETTLEMENT_CUSTOMERS_ID = b.SETTLEMENT_CUSTOMERS_ID AND b.del_flag = 1
|
||||||
|
WHERE a.del_flag = 1
|
||||||
|
<include refid="common_where"/>
|
||||||
|
GROUP BY a.SETTLEMENT_CUSTOMERS_ID, TO_CHAR(a.CREATE_TIME, 'YYYY-MM'), a.ORGANIZATION_ID, a.ORGANIZATION_NAME, b.SETTLEMENT_ENTITY_ID, b.SETTLEMENT_ENTITY, b.SETTLEMENT_METHOD, b.SETTLEMENT_CURRENCY, a.SETTLEMENT_CUSTOMERS_CODE, a.SETTLEMENT_ENTITY
|
||||||
|
ORDER BY MAX(a.CREATE_TIME) DESC
|
||||||
|
</select>
|
||||||
|
|
||||||
<sql id="common_where">
|
<sql id="common_where">
|
||||||
|
<if test="billManageDO.billMonth != null and billManageDO.billMonth != ''">
|
||||||
|
AND TO_CHAR(a.CREATE_TIME, 'YYYY-MM') = #{billManageDO.billMonth}
|
||||||
|
</if>
|
||||||
<if test="billManageDO.createTimeStart != null and billManageDO.createTimeStart != ''">
|
<if test="billManageDO.createTimeStart != null and billManageDO.createTimeStart != ''">
|
||||||
AND date_format(a.create_time,'%Y-%m-%d') <![CDATA[>=]]> #{billManageDO.createTimeStart}
|
AND date_format(a.create_time,'%Y-%m-%d') <![CDATA[>=]]> #{billManageDO.createTimeStart}
|
||||||
</if>
|
</if>
|
||||||
|
|||||||
@@ -12,39 +12,39 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
|||||||
|
|
||||||
<sql id="selectBillOperationLogPo1">
|
<sql id="selectBillOperationLogPo1">
|
||||||
<where>
|
<where>
|
||||||
<if test="createByName != null and createByName != ''">
|
<if test="billOperationLogDO.createByName != null and billOperationLogDO.createByName != ''">
|
||||||
and create_by_name like concat('%', #{createByName}, '%')
|
and create_by_name like concat('%', #{billOperationLogDO.createByName}, '%')
|
||||||
</if>
|
</if>
|
||||||
<if test="updateByName != null and updateByName != ''">
|
<if test="billOperationLogDO.updateByName != null and billOperationLogDO.updateByName != ''">
|
||||||
and update_by_name like concat('%', #{updateByName}, '%')
|
and update_by_name like concat('%', #{billOperationLogDO.updateByName}, '%')
|
||||||
</if>
|
</if>
|
||||||
<if test="topOrganizationId != null ">
|
<if test="billOperationLogDO.topOrganizationId != null ">
|
||||||
and top_organization_id = #{topOrganizationId}
|
and top_organization_id = #{billOperationLogDO.topOrganizationId}
|
||||||
</if>
|
</if>
|
||||||
<if test="organizationId != null ">
|
<if test="billOperationLogDO.organizationId != null ">
|
||||||
and organization_id = #{organizationId}
|
and organization_id = #{billOperationLogDO.organizationId}
|
||||||
</if>
|
</if>
|
||||||
<if test="organizationName != null and organizationName != ''">
|
<if test="billOperationLogDO.organizationName != null and billOperationLogDO.organizationName != ''">
|
||||||
and organization_name like concat('%', #{organizationName}, '%')
|
and organization_name like concat('%', #{billOperationLogDO.organizationName}, '%')
|
||||||
</if>
|
</if>
|
||||||
<if test="billManageId != null ">
|
<if test="billOperationLogDO.billManageId != null ">
|
||||||
and bill_manage_id = #{billManageId}
|
and bill_manage_id = #{billOperationLogDO.billManageId}
|
||||||
</if>
|
</if>
|
||||||
<if test="billNumber != null and billNumber != ''">
|
<!-- <if test="billOperationLogDO.billNumber != null and billOperationLogDO.billNumber != ''">-->
|
||||||
and bill_number = #{billNumber}
|
<!-- and bill_number = #{billOperationLogDO.billNumber}-->
|
||||||
|
<!-- </if>-->
|
||||||
|
<if test="billOperationLogDO.operationType != null ">
|
||||||
|
and operation_type = #{billOperationLogDO.operationType}
|
||||||
</if>
|
</if>
|
||||||
<if test="operationType != null ">
|
<if test="billOperationLogDO.operationInfo != null and billOperationLogDO.operationInfo != ''">
|
||||||
and operation_type = #{operationType}
|
and operation_info = #{billOperationLogDO.operationInfo}
|
||||||
</if>
|
|
||||||
<if test="operationInfo != null and operationInfo != ''">
|
|
||||||
and operation_info = #{operationInfo}
|
|
||||||
</if>
|
|
||||||
<if test="operator != null and operator != ''">
|
|
||||||
and operator = #{operator}
|
|
||||||
</if>
|
|
||||||
<if test="operationTime != null ">
|
|
||||||
and operation_time = #{operationTime}
|
|
||||||
</if>
|
</if>
|
||||||
|
<!-- <if test="billOperationLogDO.operator != null and billOperationLogDO.operator != ''">-->
|
||||||
|
<!-- and operator = #{billOperationLogDO.operator}-->
|
||||||
|
<!-- </if>-->
|
||||||
|
<!-- <if test="billOperationLogDO.operationTime != null ">-->
|
||||||
|
<!-- and operation_time = #{billOperationLogDO.operationTime}-->
|
||||||
|
<!-- </if>-->
|
||||||
</where>
|
</where>
|
||||||
</sql>
|
</sql>
|
||||||
|
|
||||||
|
|||||||
@@ -275,7 +275,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
|||||||
SELECT
|
SELECT
|
||||||
RATE as "taxRate"
|
RATE as "taxRate"
|
||||||
FROM
|
FROM
|
||||||
EXPENSE_ACCOUNT
|
NGWL_TEST_SYSTEM.EXPENSE_ACCOUNT
|
||||||
WHERE
|
WHERE
|
||||||
SUBJECT_CODE = #{subjectCode}
|
SUBJECT_CODE = #{subjectCode}
|
||||||
AND SUBJECT_NAME = #{subjectName}
|
AND SUBJECT_NAME = #{subjectName}
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
|||||||
WM_CONCAT(b.bill_number) AS billNumbers
|
WM_CONCAT(b.bill_number) AS billNumbers
|
||||||
FROM
|
FROM
|
||||||
receipt_manage a
|
receipt_manage a
|
||||||
LEFT JOIN receipt_detail b ON a.receipt_manage_id = b.receipt_manage_id
|
LEFT JOIN receipt_detail b ON a.receipt_manage_id = b.receipt_manage_id AND b.del_flag = 1
|
||||||
WHERE
|
WHERE
|
||||||
a.del_flag = 1
|
a.del_flag = 1
|
||||||
<include refid="common_where"/>
|
<include refid="common_where"/>
|
||||||
@@ -101,6 +101,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
|||||||
left join PAYMENT_WALLET c on b.payment_card_id = c.PAYMENT_WALLET_ID
|
left join PAYMENT_WALLET c on b.payment_card_id = c.PAYMENT_WALLET_ID
|
||||||
WHERE
|
WHERE
|
||||||
a.bill_manage_id = #{billManageId}
|
a.bill_manage_id = #{billManageId}
|
||||||
|
AND a.del_flag = 1
|
||||||
</select>
|
</select>
|
||||||
|
|
||||||
</mapper>
|
</mapper>
|
||||||
-58
@@ -1,58 +0,0 @@
|
|||||||
package com.mhd.oms.application.service;
|
|
||||||
|
|
||||||
import com.mhd.common.core.exception.ServiceException;
|
|
||||||
import com.mhd.common.core.web.domain.AjaxResult;
|
|
||||||
import com.mhd.oms.domain.reservationStockInOrder.repository.mapper.ReservationStockInOrderMapper;
|
|
||||||
import com.mhd.system.api.SystemServiceFeign;
|
|
||||||
import com.mhd.system.api.domain.WarehouseFeignPO;
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
|
||||||
import org.springframework.stereotype.Service;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 仓库信息获取(带本地兜底): 下发/下单冻结/保存等流程原先直接 Feign 调 system 服务取仓库信息,
|
|
||||||
* system 服务未启动/降级/返回非200时整个流程被"获取仓库信息失败"阻断。
|
|
||||||
* 本组件统一收口: 优先 Feign, 失败时回退本地跨库直查 "NGWL_TEST_SYSTEM".WAREHOUSE(与 Feign 同库同表, OMS 库账号可读),
|
|
||||||
* 两侧都取不到才抛错并带出 Feign 真实返回原因。
|
|
||||||
*
|
|
||||||
* @date 2026/9/11
|
|
||||||
*/
|
|
||||||
@Slf4j
|
|
||||||
@Service
|
|
||||||
public class WarehouseInfoApplicationService {
|
|
||||||
|
|
||||||
@Autowired
|
|
||||||
private SystemServiceFeign systemServiceFeign;
|
|
||||||
@Autowired
|
|
||||||
private ReservationStockInOrderMapper reservationStockInOrderMapper;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取仓库信息: Feign 优先, 失败走本地兜底; 两边都取不到抛 ServiceException
|
|
||||||
*
|
|
||||||
* @param warehouseId 仓库id
|
|
||||||
* @return 仓库信息(含编码/名称/单号生成规则/库存锁定模式等)
|
|
||||||
*/
|
|
||||||
public WarehouseFeignPO getWarehouseInfo(Long warehouseId) {
|
|
||||||
if (warehouseId == null) {
|
|
||||||
throw new ServiceException("仓库ID不能为空");
|
|
||||||
}
|
|
||||||
AjaxResult ajaxResult = null;
|
|
||||||
try {
|
|
||||||
ajaxResult = systemServiceFeign.getWarehouseInfoByWarehouseId(warehouseId);
|
|
||||||
} catch (Exception e) {
|
|
||||||
log.warn("获取仓库信息Feign调用异常, 走本地兜底查询, warehouseId={}, error={}", warehouseId, e.getMessage());
|
|
||||||
}
|
|
||||||
if (ajaxResult != null && "200".equals(String.valueOf(ajaxResult.get("code"))) && ajaxResult.get("data") != null) {
|
|
||||||
return com.alibaba.fastjson.JSON.parseObject(
|
|
||||||
com.alibaba.fastjson2.JSONObject.toJSONString(ajaxResult.get("data")), WarehouseFeignPO.class);
|
|
||||||
}
|
|
||||||
String remoteMsg = ajaxResult == null ? "Feign调用异常" : String.valueOf(ajaxResult.get("msg"));
|
|
||||||
log.warn("获取仓库信息Feign失败(返回: {}), 走本地兜底查询, warehouseId={}", remoteMsg, warehouseId);
|
|
||||||
WarehouseFeignPO local = reservationStockInOrderMapper.getWarehouseInfoFallback(warehouseId);
|
|
||||||
if (local == null) {
|
|
||||||
throw new ServiceException("获取仓库信息失败(Feign返回:" + remoteMsg + "), 且本地未查到仓库[warehouseId="
|
|
||||||
+ warehouseId + "], 请检查仓库是否存在/已启用");
|
|
||||||
}
|
|
||||||
return local;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
+826
@@ -0,0 +1,826 @@
|
|||||||
|
package com.mhd.oms.application.service.businessDocumentOrder;
|
||||||
|
|
||||||
|
import cn.hutool.core.bean.BeanUtil;
|
||||||
|
import cn.hutool.core.bean.copier.CopyOptions;
|
||||||
|
import cn.hutool.core.util.IdUtil;
|
||||||
|
import cn.hutool.core.util.ObjectUtil;
|
||||||
|
import cn.hutool.core.util.StrUtil;
|
||||||
|
import cn.hutool.json.JSONUtil;
|
||||||
|
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||||
|
import com.mhd.common.core.domain.dto.wlhy.TmsAddressMultiDTO;
|
||||||
|
import com.mhd.common.core.domain.dto.wlhy.TmsCargoInfoDTO;
|
||||||
|
import com.mhd.common.core.domain.dto.wlhy.TmsOrderAccount;
|
||||||
|
import com.mhd.common.core.exception.ServiceException;
|
||||||
|
import com.mhd.common.core.web.domain.AjaxResult;
|
||||||
|
import com.mhd.common.security.utils.SecurityUtils;
|
||||||
|
import com.mhd.oms.domain.businessDocumentAddressMulti.entity.BusinessDocumentAddressMulti;
|
||||||
|
import com.mhd.oms.domain.businessDocumentAddressMulti.repository.mapper.BusinessDocumentAddressMultiMapper;
|
||||||
|
import com.mhd.oms.domain.businessDocumentCargoMulti.entity.BusinessDocumentCargoMulti;
|
||||||
|
import com.mhd.oms.domain.businessDocumentCargoMulti.repository.mapper.BusinessDocumentCargoMultiMapper;
|
||||||
|
import com.mhd.oms.domain.businessDocumentOrder.entity.BusinessDocumentOrder;
|
||||||
|
import com.mhd.oms.domain.businessDocumentOrder.repository.mapper.BusinessDocumentOrderMapper;
|
||||||
|
import com.mhd.oms.domain.businessDocumentOrderAdjust.entity.BusinessDocumentOrderAdjust;
|
||||||
|
import com.mhd.oms.domain.businessDocumentOrderAdjust.repository.mapper.BusinessDocumentOrderAdjustMapper;
|
||||||
|
import com.mhd.oms.domain.businessDocumentOrderAdjustDetail.entity.BusinessDocumentOrderAdjustDetail;
|
||||||
|
import com.mhd.oms.domain.businessDocumentOrderAdjustDetail.repository.mapper.BusinessDocumentOrderAdjustDetailMapper;
|
||||||
|
import com.mhd.oms.domain.businessOrderAccount.BusinessOrderAccount;
|
||||||
|
import com.mhd.oms.domain.businessOrderAccount.repository.mapper.BusinessOrderAccountMapper;
|
||||||
|
import com.mhd.oms.domain.executeOrder.entity.ExecuteOrder;
|
||||||
|
import com.mhd.oms.domain.executeOrder.repository.mapper.ExecuteOrderMapper;
|
||||||
|
import com.mhd.oms.interfaces.dto.businessDocumentAddressMulti.BusinessDocumentAddressMultiDTO;
|
||||||
|
import com.mhd.oms.interfaces.dto.businessDocumentOrderAdjust.BusinessDocumentOrderAdjustAuditDTO;
|
||||||
|
import com.mhd.oms.interfaces.dto.businessDocumentOrderAdjust.BusinessDocumentOrderAdjustDTO;
|
||||||
|
import com.mhd.oms.interfaces.dto.businessDocumentOrderAdjust.BusinessDocumentOrderAdjustQueryDTO;
|
||||||
|
import com.mhd.oms.interfaces.dto.businessDocumentOrderAdjust.BusinessDocumentOrderAdjustRecordDTO;
|
||||||
|
import com.mhd.system.api.WlhyServiceFeign;
|
||||||
|
import com.mhd.system.api.domain.TmsOrderAddDTO;
|
||||||
|
import com.mhd.system.api.model.LoginUser;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 运输业务单「订单调整」应用服务
|
||||||
|
*
|
||||||
|
* 规则(定稿):
|
||||||
|
* 1. 每次调整都生成:1 条主记录 + 1 条明细快照
|
||||||
|
* 2. 费用数据源 = 前端回传的费用明细 business_order_account(feeDetailList);
|
||||||
|
* 主表金额 deliveryFreight 为其 amount 合计(冗余汇总,后端自动算)。
|
||||||
|
* 3. 是否需审核:一旦任一「金额」发生变化
|
||||||
|
* = feeDetailList 明细 amount 变化,或主表金额/费用列变化 -> 走业务主管审核;
|
||||||
|
* 否则(仅改非金额字段) -> 直通。
|
||||||
|
* 「金额/费用」字段涵盖: deliveryFreight / collectedFreight / uncollectedFreight /
|
||||||
|
* collectLessFreight / transportationUnitPrice / infoFee / freightUnitPrice /
|
||||||
|
* cargoInsuranceAmount / freightCharges / freightFee / unloadingFee / customsFee /
|
||||||
|
* shortageFee / miscellaneousFee / otherFee / detentionFee,以及 settlementCurrency /
|
||||||
|
* paymentAccountId / accountName / accountInformation(结算币种+收款账户任一变化即视为费用变更)。
|
||||||
|
* 判定口径: 以后端兜底比对为准(主表金额/费用列 + 明细 amount 合计),
|
||||||
|
* 前端 amountChanged 仅作提示;后端比对结果与前端 OR 运算,避免前端误传 false 绕过审核。
|
||||||
|
* 4. 涉及金额提交 -> 仅把业务单 review_status 置为「调整待审核(3)」;主记录 AUDIT_STATUS=0(待审核);
|
||||||
|
* 不更新业务单数据,不影响其它状态(order_status / execute_status 不动)。
|
||||||
|
* 5. 审核通过 -> 覆盖业务单(金额) + 替换费用明细;review_status 一律置为 1(已审核),
|
||||||
|
* 不影响 order_status / execute_status。
|
||||||
|
* 审核驳回 -> 不更新业务单数据,review_status 置为「调整驳回(4)」,不影响 order_status/execute_status,
|
||||||
|
* 可再次调整提交审核。
|
||||||
|
* 6. 直通(未改金额) -> 覆盖业务单可编辑字段 + deliveryFreight(明细合计),并替换 business_order_account
|
||||||
|
* (逻辑删旧 is_delete=1 + 插新 is_delete=0);不改动任何审核/执行状态。
|
||||||
|
*
|
||||||
|
* 说明:review_status 原枚举 0未审/1通过/2驳回,新增 3=调整待审核;不改变原有用例。
|
||||||
|
*
|
||||||
|
* @author dev
|
||||||
|
* @date 2026-09-09
|
||||||
|
*/
|
||||||
|
@Slf4j
|
||||||
|
@Service
|
||||||
|
public class BusinessDocumentOrderAdjustService {
|
||||||
|
|
||||||
|
private static final Integer AUDIT_WAIT = 0; // 调整记录:待审核
|
||||||
|
private static final Integer AUDIT_PASS = 1; // 调整记录:审核通过
|
||||||
|
private static final Integer AUDIT_REJECT = 2; // 调整记录:驳回
|
||||||
|
|
||||||
|
/** 业务单 review_status:调整待审核(提交涉及金额时置) */
|
||||||
|
private static final Long REVIEW_ADJUST_WAIT = 3L;
|
||||||
|
/** 业务单 review_status:调整驳回(审核驳回时置,与普通驳回 2 区分) */
|
||||||
|
private static final Long REVIEW_ADJUST_REJECT = 4L;
|
||||||
|
|
||||||
|
/** 主表金额(费用)字段,任一变化触发审核
|
||||||
|
* 含: 运费相关 8 项 + 其他费用 8 项 + 结算币种 + 收款账户(3 字段)
|
||||||
|
* 任意一项变化即需要审核(对应前端"费用合计 / 运费 / 装卸费 / 仓租及柜租(走明细) /
|
||||||
|
* 保险 / 压车(走明细) / 运输处理费(走明细) / 报关费 / 其他 / 费用合计 / 结算币种 / 收款账户") */
|
||||||
|
private static final List<String> FEE_FIELDS = Arrays.asList(
|
||||||
|
"deliveryFreight", "collectedFreight", "uncollectedFreight", "collectLessFreight",
|
||||||
|
"transportationUnitPrice", "infoFee", "freightUnitPrice", "cargoInsuranceAmount",
|
||||||
|
"freightCharges", "freightFee", "unloadingFee", "customsFee", "shortageFee",
|
||||||
|
"miscellaneousFee", "otherFee", "detentionFee",
|
||||||
|
// 结算币种 + 收款账户 任一变化也视为费用变更,需审核
|
||||||
|
"settlementCurrency", "paymentAccountId", "accountName", "accountInformation");
|
||||||
|
|
||||||
|
/** 不允许被前端调整覆盖的系统字段 */
|
||||||
|
private static final List<String> PROTECTED_FIELDS = Arrays.asList(
|
||||||
|
"id", "goodsNumber",
|
||||||
|
"orderStatus", "reviewStatus", "reviewId", "review", "reviewTime", "reviewOpinion",
|
||||||
|
"salesManager", "auditStatus", "auditBy", "auditTime",
|
||||||
|
"executeStatus", "executeId", "executeTime", "executor",
|
||||||
|
"executeOrderId", "executeOrderNumber",
|
||||||
|
"isDelete", "delFlag", "createBy", "createByName", "createTime",
|
||||||
|
"updateBy", "updateByName", "updateTime",
|
||||||
|
"pushStatus", "pushTime", "pushBy", "pushByName",
|
||||||
|
"reviseApplyType", "reviseApplyStatus", "reviseApplyBy", "reviseApplyByName",
|
||||||
|
"reviseApplyReason", "reviseApplyTime",
|
||||||
|
"reservationOrderId", "reservationOrderNumber",
|
||||||
|
"mainOrderId", "mainOrderNum", "mergeOrderId", "mergeOrderNum",
|
||||||
|
"splicingOrderType", "splicingStatus", "deliveryProgress",
|
||||||
|
"orgId", "orgName", "organizationId", "organizationName", "topOrganizationId",
|
||||||
|
"realCreateBy", "realCreateName", "createCompanyId", "createUserId",
|
||||||
|
"szwlUserId"
|
||||||
|
);
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private BusinessDocumentOrderMapper businessDocumentOrderMapper;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private BusinessOrderAccountMapper businessOrderAccountMapper;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private BusinessDocumentOrderAdjustMapper adjustMapper;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private BusinessDocumentOrderAdjustDetailMapper adjustDetailMapper;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private ExecuteOrderMapper executeOrderMapper;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private BusinessDocumentCargoMultiMapper businessDocumentCargoMultiMapper;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private BusinessDocumentAddressMultiMapper businessDocumentAddressMultiMapper;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private WlhyServiceFeign wlhyServiceFeign;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 提交调整
|
||||||
|
* 返回 data = [是否需审核, 调整记录ID]
|
||||||
|
*/
|
||||||
|
@Transactional(rollbackFor = Exception.class)
|
||||||
|
public AjaxResult adjust(BusinessDocumentOrderAdjustDTO dto) {
|
||||||
|
if (dto == null || dto.getOrder() == null || dto.getOrder().getId() == null) {
|
||||||
|
throw new ServiceException("参数错误:缺少业务单ID(order.id)");
|
||||||
|
}
|
||||||
|
BusinessDocumentOrder dbOrder = businessDocumentOrderMapper.selectById(dto.getOrder().getId());
|
||||||
|
if (ObjectUtil.isNull(dbOrder)) {
|
||||||
|
throw new ServiceException("业务单不存在或已被删除");
|
||||||
|
}
|
||||||
|
BusinessDocumentOrder front = dto.getOrder();
|
||||||
|
|
||||||
|
// 1. 当前库中费用明细
|
||||||
|
List<BusinessOrderAccount> dbFeeList = businessOrderAccountMapper.selectList(
|
||||||
|
new LambdaQueryWrapper<BusinessOrderAccount>()
|
||||||
|
.eq(BusinessOrderAccount::getOrderId, dbOrder.getId())
|
||||||
|
.eq(BusinessOrderAccount::getIsDelete, 0));
|
||||||
|
|
||||||
|
// 2. 调整后的费用明细(前端);为 null 则视为保持库中不变。
|
||||||
|
// 兼容前端两种传法:顶层 feeDetailList,或整单回传 order.businessOrderAccountList
|
||||||
|
List<BusinessOrderAccount> newFeeList = dto.getFeeDetailList();
|
||||||
|
if ((newFeeList == null || newFeeList.isEmpty()) && front.getBusinessOrderAccountList() != null) {
|
||||||
|
newFeeList = front.getBusinessOrderAccountList();
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3. 生成"调整后"业务单对象:DB原值 + 前端可编辑字段覆盖(忽略null)
|
||||||
|
BusinessDocumentOrder afterOrder = buildAfterOrder(dbOrder, front);
|
||||||
|
|
||||||
|
// 3.1 地址兼容:前端把地址放在 shipment/receipt 或 loadingAddressList/unloadAddressList,
|
||||||
|
// 映射到 loading*/unload* 扁平字段(与下单主流程 BusinessDocumentOrderDomainService 一致口径)
|
||||||
|
applyAddressMapping(afterOrder, front);
|
||||||
|
|
||||||
|
// 4. 若提供了费用明细,则 deliveryFreight(合计)=明细 amount 之和,并联动到 afterOrder
|
||||||
|
boolean hasFeeDetail = newFeeList != null && !newFeeList.isEmpty();
|
||||||
|
if (hasFeeDetail) {
|
||||||
|
BigDecimal sum = sumAmount(newFeeList);
|
||||||
|
afterOrder.setDeliveryFreight(sum);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 5. 判定是否修改了金额:以后端兜底比对为准,避免前端误传 false 绕过审核;
|
||||||
|
// 前端传 true 也尊重;后端比对结果与前端 OR 运算(任一为真则需审核)。
|
||||||
|
boolean backendChanged = isAmountChanged(dbOrder, front, hasFeeDetail, dbFeeList, newFeeList);
|
||||||
|
boolean amountChanged = backendChanged || Boolean.TRUE.equals(dto.getAmountChanged());
|
||||||
|
|
||||||
|
// 6. 写主记录
|
||||||
|
LoginUser loginUser = SecurityUtils.getLoginUser();
|
||||||
|
Date now = new Date();
|
||||||
|
BusinessDocumentOrderAdjust adjust = buildAdjust(dbOrder, loginUser, now, amountChanged, dto.getAdjustReason());
|
||||||
|
adjustMapper.insert(adjust);
|
||||||
|
|
||||||
|
// 7. 写明细快照(调整后业务单整行 + 费用明细JSON)
|
||||||
|
BusinessDocumentOrderAdjustDetail detail = new BusinessDocumentOrderAdjustDetail();
|
||||||
|
copySnapshot(afterOrder, detail);
|
||||||
|
if (hasFeeDetail) {
|
||||||
|
detail.setFeeDetailJson(JSONUtil.toJsonStr(newFeeList));
|
||||||
|
}
|
||||||
|
detail.setAdjustId(adjust.getId());
|
||||||
|
detail.setOrderId(dbOrder.getId());
|
||||||
|
detail.setGoodsNumber(dbOrder.getGoodsNumber());
|
||||||
|
detail.setCreateBy(adjust.getAdjustBy());
|
||||||
|
detail.setCreateName(adjust.getAdjustByName());
|
||||||
|
detail.setCreateTime(now);
|
||||||
|
detail.setDelFlag(1);
|
||||||
|
adjustDetailMapper.insert(detail);
|
||||||
|
|
||||||
|
if (!amountChanged) {
|
||||||
|
// 8a. 直通:覆盖主表可编辑字段(含 deliveryFreight 合计) + 替换费用明细;不改动任何审核/执行状态
|
||||||
|
saveOrderAndFee(dbOrder.getId(), afterOrder, hasFeeDetail ? newFeeList : dbFeeList, loginUser, now, false, null);
|
||||||
|
updateAdjustPass(adjust.getId(), adjust.getAdjustBy(), adjust.getAdjustByName(), now, null);
|
||||||
|
syncTmsAsync(dbOrder.getGoodsNumber(), afterOrder);
|
||||||
|
} else {
|
||||||
|
// 8b. 涉及金额:仅把业务单 review_status 置为"调整待审核(3)",其余状态(exec/orderStatus)不动,不更新业务单数据
|
||||||
|
BusinessDocumentOrder statusOnly = new BusinessDocumentOrder();
|
||||||
|
statusOnly.setId(dbOrder.getId());
|
||||||
|
statusOnly.setReviewStatus(REVIEW_ADJUST_WAIT); // 调整待审核
|
||||||
|
businessDocumentOrderMapper.updateById(statusOnly);
|
||||||
|
}
|
||||||
|
|
||||||
|
return AjaxResult.success(new Object[]{amountChanged, adjust.getId()});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 调整记录列表(管理页:查全部,可选按订单/业务单号/审核状态等筛选,配合分页使用)
|
||||||
|
*/
|
||||||
|
public List<BusinessDocumentOrderAdjustRecordDTO> listAdjustRecord(BusinessDocumentOrderAdjustQueryDTO query) {
|
||||||
|
LambdaQueryWrapper<BusinessDocumentOrderAdjust> wrapper = new LambdaQueryWrapper<BusinessDocumentOrderAdjust>()
|
||||||
|
.eq(BusinessDocumentOrderAdjust::getDelFlag, 1);
|
||||||
|
|
||||||
|
// ===== 组织隔离(参考业务单 queryList 口径) =====
|
||||||
|
LoginUser loginUser = SecurityUtils.getLoginUser();
|
||||||
|
if (loginUser != null && loginUser.getUserPo() != null) {
|
||||||
|
Long loginOrgId = loginUser.getUserPo().getOrganizationId();
|
||||||
|
Long loginTopOrgId = loginUser.getUserPo().getTopOrganizationId();
|
||||||
|
// 一级组织非1(集团)时,按一级组织过滤(可看本一级组织下所有)
|
||||||
|
if (loginTopOrgId != null && loginTopOrgId != 1) {
|
||||||
|
wrapper.eq(BusinessDocumentOrderAdjust::getTopOrgId, String.valueOf(loginTopOrgId));
|
||||||
|
} else if (loginOrgId != null) {
|
||||||
|
// 否则按当前组织过滤;若查询方显式指定了 organizationId 则以其为准
|
||||||
|
Long effOrgId = (query != null && query.getOrganizationId() != null)
|
||||||
|
? query.getOrganizationId() : loginOrgId;
|
||||||
|
if (effOrgId != null) {
|
||||||
|
wrapper.eq(BusinessDocumentOrderAdjust::getOrgId, String.valueOf(effOrgId));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (query != null && query.getOrganizationId() != null) {
|
||||||
|
wrapper.eq(BusinessDocumentOrderAdjust::getOrgId, String.valueOf(query.getOrganizationId()));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (query != null) {
|
||||||
|
if (query.getOrderId() != null) {
|
||||||
|
wrapper.eq(BusinessDocumentOrderAdjust::getOrderId, query.getOrderId());
|
||||||
|
}
|
||||||
|
if (StrUtil.isNotBlank(query.getGoodsNumber())) {
|
||||||
|
wrapper.like(BusinessDocumentOrderAdjust::getGoodsNumber, query.getGoodsNumber());
|
||||||
|
}
|
||||||
|
if (query.getIsAudit() != null) {
|
||||||
|
wrapper.eq(BusinessDocumentOrderAdjust::getIsAudit, query.getIsAudit());
|
||||||
|
}
|
||||||
|
if (query.getAuditStatus() != null) {
|
||||||
|
wrapper.eq(BusinessDocumentOrderAdjust::getAuditStatus, query.getAuditStatus());
|
||||||
|
}
|
||||||
|
if (StrUtil.isNotBlank(query.getAdjustByName())) {
|
||||||
|
wrapper.like(BusinessDocumentOrderAdjust::getAdjustByName, query.getAdjustByName());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
wrapper.orderByDesc(BusinessDocumentOrderAdjust::getAdjustTime);
|
||||||
|
List<BusinessDocumentOrderAdjust> list = adjustMapper.selectList(wrapper);
|
||||||
|
return list.stream().map(a -> {
|
||||||
|
BusinessDocumentOrderAdjustRecordDTO vo = new BusinessDocumentOrderAdjustRecordDTO();
|
||||||
|
BeanUtil.copyProperties(a, vo);
|
||||||
|
return vo;
|
||||||
|
}).collect(Collectors.toList());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 按业务单查询调整记录(供订单详情页"调整记录"Tab用)
|
||||||
|
* 每条记录同时带出调整后明细快照(detail),前端可自包含展示,无需再单独调详情接口
|
||||||
|
*/
|
||||||
|
public List<BusinessDocumentOrderAdjustRecordDTO> listAdjustRecordByOrder(Long orderId) {
|
||||||
|
BusinessDocumentOrderAdjustQueryDTO query = new BusinessDocumentOrderAdjustQueryDTO();
|
||||||
|
query.setOrderId(orderId);
|
||||||
|
List<BusinessDocumentOrderAdjustRecordDTO> list = listAdjustRecord(query);
|
||||||
|
if (list == null || list.isEmpty()) {
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
// 批量取明细快照按 adjust_id 一次性拼上,避免 N+1
|
||||||
|
List<Long> adjustIds = list.stream()
|
||||||
|
.map(BusinessDocumentOrderAdjustRecordDTO::getId)
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
List<BusinessDocumentOrderAdjustDetail> details = adjustDetailMapper.selectList(
|
||||||
|
new LambdaQueryWrapper<BusinessDocumentOrderAdjustDetail>()
|
||||||
|
.in(BusinessDocumentOrderAdjustDetail::getAdjustId, adjustIds)
|
||||||
|
.eq(BusinessDocumentOrderAdjustDetail::getDelFlag, 1));
|
||||||
|
Map<Long, BusinessDocumentOrderAdjustDetail> detailMap = details.stream()
|
||||||
|
.collect(Collectors.toMap(BusinessDocumentOrderAdjustDetail::getAdjustId, d -> d, (a, b) -> a));
|
||||||
|
list.forEach(vo -> vo.setDetail(detailMap.get(vo.getId())));
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 调整记录详情(主记录 + 调整后明细快照)
|
||||||
|
*/
|
||||||
|
public BusinessDocumentOrderAdjustRecordDTO getAdjustRecord(Long adjustId) {
|
||||||
|
BusinessDocumentOrderAdjust adjust = adjustMapper.selectById(adjustId);
|
||||||
|
if (adjust == null) {
|
||||||
|
throw new ServiceException("调整记录不存在");
|
||||||
|
}
|
||||||
|
BusinessDocumentOrderAdjustRecordDTO vo = new BusinessDocumentOrderAdjustRecordDTO();
|
||||||
|
BeanUtil.copyProperties(adjust, vo);
|
||||||
|
BusinessDocumentOrderAdjustDetail detail = adjustDetailMapper.selectOne(
|
||||||
|
new LambdaQueryWrapper<BusinessDocumentOrderAdjustDetail>()
|
||||||
|
.eq(BusinessDocumentOrderAdjustDetail::getAdjustId, adjustId)
|
||||||
|
.eq(BusinessDocumentOrderAdjustDetail::getDelFlag, 1)
|
||||||
|
.last("LIMIT 1"));
|
||||||
|
vo.setDetail(detail);
|
||||||
|
return vo;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 调整审核(通过/驳回),业务主管操作
|
||||||
|
*/
|
||||||
|
@Transactional(rollbackFor = Exception.class)
|
||||||
|
public AjaxResult auditAdjust(BusinessDocumentOrderAdjustAuditDTO auditDTO) {
|
||||||
|
if (auditDTO == null || auditDTO.getAdjustId() == null) {
|
||||||
|
throw new ServiceException("参数错误:缺少调整记录ID");
|
||||||
|
}
|
||||||
|
BusinessDocumentOrderAdjust adjust = adjustMapper.selectById(auditDTO.getAdjustId());
|
||||||
|
if (adjust == null) {
|
||||||
|
throw new ServiceException("调整记录不存在");
|
||||||
|
}
|
||||||
|
if (adjust.getAuditStatus() == null || adjust.getAuditStatus() != AUDIT_WAIT) {
|
||||||
|
throw new ServiceException("该调整记录非待审核状态,无法审核");
|
||||||
|
}
|
||||||
|
Integer result = auditDTO.getAuditResult();
|
||||||
|
if (result == null || (result != AUDIT_PASS && result != AUDIT_REJECT)) {
|
||||||
|
throw new ServiceException("审核结果非法");
|
||||||
|
}
|
||||||
|
|
||||||
|
LoginUser loginUser = SecurityUtils.getLoginUser();
|
||||||
|
String auditBy = loginUser != null ? String.valueOf(loginUser.getUserid()) : null;
|
||||||
|
String auditByName = loginUser != null && loginUser.getWlhyLoginUser() != null ? loginUser.getWlhyLoginUser().getRealname() : null;
|
||||||
|
Date now = new Date();
|
||||||
|
|
||||||
|
if (result == AUDIT_PASS) {
|
||||||
|
BusinessDocumentOrder order = businessDocumentOrderMapper.selectById(adjust.getOrderId());
|
||||||
|
if (ObjectUtil.isNull(order)) {
|
||||||
|
throw new ServiceException("业务单不存在");
|
||||||
|
}
|
||||||
|
BusinessDocumentOrderAdjustDetail detail = adjustDetailMapper.selectOne(
|
||||||
|
new LambdaQueryWrapper<BusinessDocumentOrderAdjustDetail>()
|
||||||
|
.eq(BusinessDocumentOrderAdjustDetail::getAdjustId, adjust.getId())
|
||||||
|
.eq(BusinessDocumentOrderAdjustDetail::getDelFlag, 1)
|
||||||
|
.last("LIMIT 1"));
|
||||||
|
|
||||||
|
// 还原调整后业务单(从JSON整行快照)
|
||||||
|
BusinessDocumentOrder snapshot = null;
|
||||||
|
if (detail != null && StrUtil.isNotBlank(detail.getOrderSnapshotJson())) {
|
||||||
|
try {
|
||||||
|
snapshot = JSONUtil.toBean(detail.getOrderSnapshotJson(), BusinessDocumentOrder.class);
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.warn("解析调整快照JSON失败", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
BusinessDocumentOrder toSave = new BusinessDocumentOrder();
|
||||||
|
toSave.setId(order.getId());
|
||||||
|
if (snapshot != null) {
|
||||||
|
BeanUtil.copyProperties(snapshot, toSave, CopyOptions.create().setIgnoreNullValue(true)
|
||||||
|
.setIgnoreProperties(toArray()));
|
||||||
|
} else if (detail != null) {
|
||||||
|
BeanUtil.copyProperties(detail, toSave, CopyOptions.create().setIgnoreNullValue(true)
|
||||||
|
.setIgnoreProperties(toArray()));
|
||||||
|
}
|
||||||
|
|
||||||
|
// 还原调整后费用明细(从 feeDetailJson)
|
||||||
|
List<BusinessOrderAccount> newFeeList = new ArrayList<>();
|
||||||
|
if (detail != null && StrUtil.isNotBlank(detail.getFeeDetailJson())) {
|
||||||
|
try {
|
||||||
|
newFeeList = JSONUtil.toList(detail.getFeeDetailJson(), BusinessOrderAccount.class);
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.warn("解析调整费用明细JSON失败", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 若快照中有明细合计则保证 deliveryFreight 一致
|
||||||
|
if (!newFeeList.isEmpty()) {
|
||||||
|
toSave.setDeliveryFreight(sumAmount(newFeeList));
|
||||||
|
}
|
||||||
|
// 审核通过后 review_status 一律置为 1(已审核);不影响 order_status / execute_status
|
||||||
|
toSave.setReviewStatus(1L);
|
||||||
|
// 覆盖业务单 + 替换费用明细
|
||||||
|
saveOrderAndFee(order.getId(), toSave, newFeeList, loginUser, now, false, null);
|
||||||
|
|
||||||
|
updateAdjustPass(adjust.getId(), auditBy, auditByName, now, auditDTO.getAuditRemark());
|
||||||
|
syncTmsAsync(order.getGoodsNumber(), toSave);
|
||||||
|
} else {
|
||||||
|
adjust.setAuditStatus(AUDIT_REJECT);
|
||||||
|
adjust.setIsAudit(1); // 走到审核即说明该调整需要审核,保持 is_audit 与 audit_status 语义一致
|
||||||
|
adjust.setAuditBy(auditBy);
|
||||||
|
adjust.setAuditByName(auditByName);
|
||||||
|
adjust.setAuditTime(now);
|
||||||
|
adjust.setAuditRemark(auditDTO.getAuditRemark());
|
||||||
|
adjust.setUpdateBy(auditBy);
|
||||||
|
adjust.setUpdateTime(now);
|
||||||
|
adjustMapper.updateById(adjust);
|
||||||
|
|
||||||
|
// 驳回:不更新业务单数据,仅把 review_status 置为「调整驳回(4)」;
|
||||||
|
// 不影响 order_status / execute_status 等其它单据状态;可再次调整提交审核
|
||||||
|
BusinessDocumentOrder statusOnly = new BusinessDocumentOrder();
|
||||||
|
statusOnly.setId(adjust.getOrderId());
|
||||||
|
statusOnly.setReviewStatus(REVIEW_ADJUST_REJECT);
|
||||||
|
businessDocumentOrderMapper.updateById(statusOnly);
|
||||||
|
}
|
||||||
|
return AjaxResult.success();
|
||||||
|
}
|
||||||
|
|
||||||
|
// =====================================================
|
||||||
|
// 私有工具
|
||||||
|
// =====================================================
|
||||||
|
|
||||||
|
private BusinessDocumentOrder buildAfterOrder(BusinessDocumentOrder dbOrder, BusinessDocumentOrder front) {
|
||||||
|
BusinessDocumentOrder after = new BusinessDocumentOrder();
|
||||||
|
BeanUtil.copyProperties(dbOrder, after, CopyOptions.create().setIgnoreNullValue(true));
|
||||||
|
BeanUtil.copyProperties(front, after, CopyOptions.create().setIgnoreNullValue(true)
|
||||||
|
.setIgnoreProperties(toArray()));
|
||||||
|
after.setId(dbOrder.getId());
|
||||||
|
return after;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 地址兼容映射:前端整单回传时地址在 shipment/receipt 或 loadingAddressList/unloadAddressList,
|
||||||
|
* 这里统一映射到 business_document_order 的 loading 与 unload 系列扁平字段。
|
||||||
|
* 口径与 BusinessDocumentOrderDomainService 下单主流程保持一致:
|
||||||
|
* 装货取第一条地址,卸货取最后一条地址。
|
||||||
|
*/
|
||||||
|
private void applyAddressMapping(BusinessDocumentOrder after, BusinessDocumentOrder front) {
|
||||||
|
BusinessDocumentAddressMultiDTO loading = null;
|
||||||
|
BusinessDocumentAddressMultiDTO unloading = null;
|
||||||
|
|
||||||
|
// 优先取 shipment/receipt 单对象,其次取 loadingAddressList/unloadAddressList 集合
|
||||||
|
if (front.getShipment() != null) {
|
||||||
|
loading = front.getShipment();
|
||||||
|
} else if (front.getLoadingAddressList() != null && !front.getLoadingAddressList().isEmpty()) {
|
||||||
|
loading = front.getLoadingAddressList().get(0);
|
||||||
|
}
|
||||||
|
if (front.getReceipt() != null) {
|
||||||
|
unloading = front.getReceipt();
|
||||||
|
} else if (front.getUnloadAddressList() != null && !front.getUnloadAddressList().isEmpty()) {
|
||||||
|
unloading = front.getUnloadAddressList().get(front.getUnloadAddressList().size() - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (loading != null) {
|
||||||
|
after.setLoadingAreaId(loading.getAreaCode());
|
||||||
|
after.setLoadingName(loading.getAreaName() != null ? loading.getAreaName() : loading.getAreaCode());
|
||||||
|
after.setLoadingAddress(loading.getAddress());
|
||||||
|
after.setLoadingLongitude(loading.getLongitude());
|
||||||
|
after.setLoadingLatitude(loading.getLatitude());
|
||||||
|
after.setFreighterName(loading.getContactName());
|
||||||
|
after.setLoadingPhone(loading.getContactPhone());
|
||||||
|
after.setLoadingDate(loading.getLayDate());
|
||||||
|
}
|
||||||
|
if (unloading != null) {
|
||||||
|
after.setUnloadAreaId(unloading.getAreaCode());
|
||||||
|
after.setUnloadName(unloading.getAreaName() != null ? unloading.getAreaName() : unloading.getAreaCode());
|
||||||
|
after.setUnloadAddress(unloading.getAddress());
|
||||||
|
after.setUnloadLongitude(unloading.getLongitude());
|
||||||
|
after.setUnloadLatitude(unloading.getLatitude());
|
||||||
|
after.setDischargerName(unloading.getContactName());
|
||||||
|
after.setUnloadPhone(unloading.getContactPhone());
|
||||||
|
after.setUnloadingData(unloading.getLayDate());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private BusinessDocumentOrderAdjust buildAdjust(BusinessDocumentOrder dbOrder, LoginUser u, Date now,
|
||||||
|
boolean amountChanged, String reason) {
|
||||||
|
BusinessDocumentOrderAdjust adjust = new BusinessDocumentOrderAdjust();
|
||||||
|
adjust.setOrderId(dbOrder.getId());
|
||||||
|
adjust.setGoodsNumber(dbOrder.getGoodsNumber());
|
||||||
|
adjust.setAdjustBy(u != null ? String.valueOf(u.getUserid()) : null);
|
||||||
|
adjust.setAdjustByName(u != null && u.getWlhyLoginUser() != null ? u.getWlhyLoginUser().getRealname() : null);
|
||||||
|
adjust.setAdjustTime(now);
|
||||||
|
adjust.setAdjustReason(reason);
|
||||||
|
adjust.setIsAudit(amountChanged ? 1 : 0);
|
||||||
|
adjust.setAuditStatus(amountChanged ? AUDIT_WAIT : AUDIT_PASS);
|
||||||
|
adjust.setBeforeReviewStatus(dbOrder.getReviewStatus());
|
||||||
|
// 组织信息:参考业务单口径,取当前登录用户所属组织(调整人归属)
|
||||||
|
if (u != null && u.getUserPo() != null) {
|
||||||
|
if (u.getUserPo().getOrganizationId() != null) {
|
||||||
|
adjust.setOrgId(String.valueOf(u.getUserPo().getOrganizationId()));
|
||||||
|
} else {
|
||||||
|
adjust.setOrgId(dbOrder.getOrgId());
|
||||||
|
}
|
||||||
|
if (u.getUserPo().getTopOrganizationId() != null) {
|
||||||
|
adjust.setTopOrgId(String.valueOf(u.getUserPo().getTopOrganizationId()));
|
||||||
|
} else if (dbOrder.getTopOrganizationId() != null) {
|
||||||
|
adjust.setTopOrgId(String.valueOf(dbOrder.getTopOrganizationId()));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
adjust.setOrgId(dbOrder.getOrgId());
|
||||||
|
if (dbOrder.getTopOrganizationId() != null) {
|
||||||
|
adjust.setTopOrgId(String.valueOf(dbOrder.getTopOrganizationId()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
adjust.setCreateBy(adjust.getAdjustBy());
|
||||||
|
adjust.setCreateName(adjust.getAdjustByName());
|
||||||
|
adjust.setCreateTime(now);
|
||||||
|
adjust.setDelFlag(1);
|
||||||
|
return adjust;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 是否修改了金额:主表金额/费用列变化 或 明细 amount 变化
|
||||||
|
*/
|
||||||
|
private boolean isAmountChanged(BusinessDocumentOrder dbOrder, BusinessDocumentOrder front,
|
||||||
|
boolean hasFeeDetail, List<BusinessOrderAccount> dbFeeList,
|
||||||
|
List<BusinessOrderAccount> newFeeList) {
|
||||||
|
// a) 主表金额/费用列比对(金额列用 BigDecimal 比对,字符串列用 equals 比对)
|
||||||
|
boolean mainChanged = FEE_FIELDS.stream().anyMatch(field -> {
|
||||||
|
Object newVal = BeanUtil.getFieldValue(front, field);
|
||||||
|
if (newVal == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
Object oldVal = BeanUtil.getFieldValue(dbOrder, field);
|
||||||
|
if (newVal instanceof BigDecimal || oldVal instanceof BigDecimal) {
|
||||||
|
BigDecimal old = oldVal == null ? BigDecimal.ZERO : new BigDecimal(oldVal.toString());
|
||||||
|
BigDecimal now = new BigDecimal(newVal.toString());
|
||||||
|
return old.compareTo(now) != 0;
|
||||||
|
}
|
||||||
|
// 字符串字段(结算币种/收款账户等)
|
||||||
|
return !newVal.toString().equals(oldVal == null ? "" : oldVal.toString());
|
||||||
|
});
|
||||||
|
if (mainChanged) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
// b) 若前端未传明细,则只看主表;若传了明细,比较明细金额
|
||||||
|
if (!hasFeeDetail) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// 明细合计对比
|
||||||
|
BigDecimal oldSum = sumAmount(dbFeeList);
|
||||||
|
BigDecimal newSum = sumAmount(newFeeList);
|
||||||
|
return oldSum.compareTo(newSum) != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
private BigDecimal sumAmount(List<BusinessOrderAccount> list) {
|
||||||
|
BigDecimal sum = BigDecimal.ZERO;
|
||||||
|
if (list == null) {
|
||||||
|
return sum;
|
||||||
|
}
|
||||||
|
for (BusinessOrderAccount acc : list) {
|
||||||
|
if (acc.getAmount() != null) {
|
||||||
|
sum = sum.add(acc.getAmount());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return sum;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 覆盖业务单可编辑字段 + 替换费用明细(逻辑删旧 + 插新)
|
||||||
|
*/
|
||||||
|
/**
|
||||||
|
* 覆盖业务单可编辑字段 + 替换费用明细(逻辑删旧 + 插新)
|
||||||
|
* @param restoreReview 是否还原审核状态(审核通过/驳回后 true;直通 false 不改任何审核状态)
|
||||||
|
* @param beforeReviewStatus 调整前 review_status,用于还原
|
||||||
|
*/
|
||||||
|
private void saveOrderAndFee(Long orderId, BusinessDocumentOrder toSave,
|
||||||
|
List<BusinessOrderAccount> newFeeList,
|
||||||
|
LoginUser loginUser, Date now,
|
||||||
|
boolean restoreReview, Long beforeReviewStatus) {
|
||||||
|
if (restoreReview) {
|
||||||
|
// 仅还原 review_status 到调整前值;不影响 order_status / execute_status 等其它状态
|
||||||
|
toSave.setReviewStatus(beforeReviewStatus == null ? 0L : beforeReviewStatus);
|
||||||
|
}
|
||||||
|
businessDocumentOrderMapper.updateById(toSave);
|
||||||
|
|
||||||
|
// 逻辑删旧明细
|
||||||
|
List<BusinessOrderAccount> oldFeeList = businessOrderAccountMapper.selectList(
|
||||||
|
new LambdaQueryWrapper<BusinessOrderAccount>()
|
||||||
|
.eq(BusinessOrderAccount::getOrderId, orderId)
|
||||||
|
.eq(BusinessOrderAccount::getIsDelete, 0));
|
||||||
|
if (oldFeeList != null) {
|
||||||
|
for (BusinessOrderAccount oldAcc : oldFeeList) {
|
||||||
|
oldAcc.setIsDelete(1);
|
||||||
|
oldAcc.setUpdateBy(loginUser != null ? String.valueOf(loginUser.getUserid()) : null);
|
||||||
|
oldAcc.setUpdateTime(now);
|
||||||
|
businessOrderAccountMapper.updateById(oldAcc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 插新明细
|
||||||
|
if (newFeeList != null && !newFeeList.isEmpty()) {
|
||||||
|
for (BusinessOrderAccount acc : newFeeList) {
|
||||||
|
acc.setId(IdUtil.randomUUID());
|
||||||
|
acc.setOrderId(String.valueOf(orderId));
|
||||||
|
acc.setIsDelete(0);
|
||||||
|
acc.setCreateBy(loginUser != null ? String.valueOf(loginUser.getUserid()) : null);
|
||||||
|
acc.setCreateTime(now);
|
||||||
|
businessOrderAccountMapper.insert(acc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 同步地址明细表(business_document_address_multi):逻辑删旧 + 按调整后扁平字段插新
|
||||||
|
syncAddressDetail(orderId, toSave, loginUser, now);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 同步地址明细表:把「调整后业务单」的装/卸货扁平字段写回 business_document_address_multi。
|
||||||
|
* 与 applyAddressMapping 口径一致(装货取第一条、卸货取最后一条),此处各保留一条。
|
||||||
|
*/
|
||||||
|
private void syncAddressDetail(Long orderId, BusinessDocumentOrder toSave, LoginUser loginUser, Date now) {
|
||||||
|
// 逻辑删旧
|
||||||
|
List<BusinessDocumentAddressMulti> oldList = businessDocumentAddressMultiMapper.selectList(
|
||||||
|
new LambdaQueryWrapper<BusinessDocumentAddressMulti>()
|
||||||
|
.eq(BusinessDocumentAddressMulti::getOrderId, String.valueOf(orderId))
|
||||||
|
.eq(BusinessDocumentAddressMulti::getDelFlag, 1));
|
||||||
|
if (oldList != null) {
|
||||||
|
for (BusinessDocumentAddressMulti old : oldList) {
|
||||||
|
old.setDelFlag(0);
|
||||||
|
old.setUpdateBy(loginUser != null ? loginUser.getUserid() : null);
|
||||||
|
old.setUpdateTime(now);
|
||||||
|
businessDocumentAddressMultiMapper.updateById(old);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Long userId = loginUser != null ? loginUser.getUserid() : null;
|
||||||
|
// 装货
|
||||||
|
BusinessDocumentAddressMulti loading = new BusinessDocumentAddressMulti();
|
||||||
|
loading.setOrderId(String.valueOf(orderId));
|
||||||
|
loading.setAreaCode(toSave.getLoadingAreaId());
|
||||||
|
loading.setAreaName(toSave.getLoadingName());
|
||||||
|
loading.setAddress(toSave.getLoadingAddress());
|
||||||
|
loading.setLongitude(toSave.getLoadingLongitude());
|
||||||
|
loading.setLatitude(toSave.getLoadingLatitude());
|
||||||
|
loading.setContactName(toSave.getFreighterName());
|
||||||
|
loading.setContactPhone(toSave.getLoadingPhone());
|
||||||
|
loading.setLayDate(toSave.getLoadingDate());
|
||||||
|
loading.setLayType(1L);
|
||||||
|
loading.setDelFlag(1);
|
||||||
|
loading.setOrganizationId(toSave.getOrganizationId());
|
||||||
|
loading.setOrganizationName(toSave.getOrganizationName());
|
||||||
|
loading.setTopOrganizationId(toSave.getTopOrganizationId());
|
||||||
|
loading.setCreateBy(userId);
|
||||||
|
loading.setCreateTime(now);
|
||||||
|
loading.setUpdateBy(userId);
|
||||||
|
loading.setUpdateTime(now);
|
||||||
|
businessDocumentAddressMultiMapper.insert(loading);
|
||||||
|
|
||||||
|
// 卸货
|
||||||
|
BusinessDocumentAddressMulti unload = new BusinessDocumentAddressMulti();
|
||||||
|
unload.setOrderId(String.valueOf(orderId));
|
||||||
|
unload.setAreaCode(toSave.getUnloadAreaId());
|
||||||
|
unload.setAreaName(toSave.getUnloadName());
|
||||||
|
unload.setAddress(toSave.getUnloadAddress());
|
||||||
|
unload.setLongitude(toSave.getUnloadLongitude());
|
||||||
|
unload.setLatitude(toSave.getUnloadLatitude());
|
||||||
|
unload.setContactName(toSave.getDischargerName());
|
||||||
|
unload.setContactPhone(toSave.getUnloadPhone());
|
||||||
|
unload.setLayDate(toSave.getUnloadingData());
|
||||||
|
unload.setLayType(2L);
|
||||||
|
unload.setDelFlag(1);
|
||||||
|
unload.setOrganizationId(toSave.getOrganizationId());
|
||||||
|
unload.setOrganizationName(toSave.getOrganizationName());
|
||||||
|
unload.setTopOrganizationId(toSave.getTopOrganizationId());
|
||||||
|
unload.setCreateBy(userId);
|
||||||
|
unload.setCreateTime(now);
|
||||||
|
unload.setUpdateBy(userId);
|
||||||
|
unload.setUpdateTime(now);
|
||||||
|
businessDocumentAddressMultiMapper.insert(unload);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void copySnapshot(BusinessDocumentOrder order, BusinessDocumentOrderAdjustDetail detail) {
|
||||||
|
BeanUtil.copyProperties(order, detail, CopyOptions.create().setIgnoreNullValue(true)
|
||||||
|
.setIgnoreProperties("id", "adjustId", "orderId", "createBy", "createName",
|
||||||
|
"createTime", "updateBy", "updateTime", "delFlag",
|
||||||
|
"orderSnapshotJson", "feeDetailJson"));
|
||||||
|
try {
|
||||||
|
detail.setOrderSnapshotJson(JSONUtil.toJsonStr(order));
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.warn("生成调整快照JSON失败", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updateAdjustPass(Long adjustId, String auditBy, String auditByName, Date auditTime, String remark) {
|
||||||
|
BusinessDocumentOrderAdjust adjust = new BusinessDocumentOrderAdjust();
|
||||||
|
adjust.setId(adjustId);
|
||||||
|
adjust.setAuditStatus(AUDIT_PASS);
|
||||||
|
adjust.setAuditBy(auditBy);
|
||||||
|
adjust.setAuditByName(auditByName);
|
||||||
|
adjust.setAuditTime(auditTime);
|
||||||
|
adjust.setAuditRemark(remark);
|
||||||
|
adjust.setUpdateBy(auditBy);
|
||||||
|
adjust.setUpdateTime(auditTime);
|
||||||
|
adjustMapper.updateById(adjust);
|
||||||
|
}
|
||||||
|
|
||||||
|
private String[] toArray() {
|
||||||
|
return PROTECTED_FIELDS.toArray(new String[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void syncTmsAsync(String goodsNumber, BusinessDocumentOrder after) {
|
||||||
|
try {
|
||||||
|
List<ExecuteOrder> executeOrders = executeOrderMapper.selectList(
|
||||||
|
new LambdaQueryWrapper<ExecuteOrder>()
|
||||||
|
.eq(ExecuteOrder::getGoodsNumber, goodsNumber)
|
||||||
|
.eq(ExecuteOrder::getDelFlag, 1));
|
||||||
|
if (executeOrders == null || executeOrders.isEmpty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
for (ExecuteOrder executeOrder : executeOrders) {
|
||||||
|
// 仅已下发 TMS(存在 TMS 单号)的执行单需要同步修改
|
||||||
|
if (StrUtil.isBlank(executeOrder.getTmsOrderNumber())) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
syncTmsOrder(executeOrder, after);
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("同步TMS失败,不影响主流程", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 同步修改单个 TMS 订单:按调整后业务单重新组装 TmsOrderAddDTO,
|
||||||
|
* 带 executeOrderNumber 定位 TMS 订单,调用 TMS /feign/order/update 接口。
|
||||||
|
*/
|
||||||
|
private void syncTmsOrder(ExecuteOrder executeOrder, BusinessDocumentOrder after) {
|
||||||
|
TmsOrderAddDTO tmsOrderAddDTO = new TmsOrderAddDTO();
|
||||||
|
BeanUtil.copyProperties(after, tmsOrderAddDTO);
|
||||||
|
// id 传 OMS 业务单主键:TMS 侧用作 tms_order_account.order_id 口径;
|
||||||
|
// TMS 的 update 在覆盖前会保留 tms_order 真实主键,不会被污染
|
||||||
|
tmsOrderAddDTO.setId(String.valueOf(after.getId()));
|
||||||
|
// TMS 侧按执行单号定位订单
|
||||||
|
tmsOrderAddDTO.setExecuteOrderId(String.valueOf(executeOrder.getId()));
|
||||||
|
tmsOrderAddDTO.setExecuteOrderNumber(executeOrder.getGoodsNumber());
|
||||||
|
tmsOrderAddDTO.setGoodsNumber(after.getGoodsNumber());
|
||||||
|
tmsOrderAddDTO.setOrderSource("0");
|
||||||
|
|
||||||
|
// TMS 侧 update 按 appointShipperId(业务单货主) 定位货主,需显式带上,口径与下单一致
|
||||||
|
if (StrUtil.isNotBlank(after.getAppointShipperId())) {
|
||||||
|
tmsOrderAddDTO.setAppointShipperId(after.getAppointShipperId());
|
||||||
|
}
|
||||||
|
if (after.getAppointShipper() != null) {
|
||||||
|
tmsOrderAddDTO.setAppointShipper(after.getAppointShipper());
|
||||||
|
}
|
||||||
|
if (after.getSzwlUserId() != null) {
|
||||||
|
tmsOrderAddDTO.setSzwlUserId(after.getSzwlUserId());
|
||||||
|
}
|
||||||
|
|
||||||
|
// 货物信息
|
||||||
|
List<BusinessDocumentCargoMulti> cargoList = businessDocumentCargoMultiMapper.selectList(
|
||||||
|
new LambdaQueryWrapper<BusinessDocumentCargoMulti>()
|
||||||
|
.eq(BusinessDocumentCargoMulti::getOrderId, String.valueOf(after.getId()))
|
||||||
|
.eq(BusinessDocumentCargoMulti::getDelFlag, 1));
|
||||||
|
List<TmsCargoInfoDTO> cargoInfoList = new ArrayList<>();
|
||||||
|
if (cargoList != null) {
|
||||||
|
for (BusinessDocumentCargoMulti cargo : cargoList) {
|
||||||
|
TmsCargoInfoDTO dto = new TmsCargoInfoDTO();
|
||||||
|
BeanUtil.copyProperties(cargo, dto);
|
||||||
|
cargoInfoList.add(dto);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
tmsOrderAddDTO.setCargoInfoList(cargoInfoList);
|
||||||
|
|
||||||
|
// 装货地址:统一以「调整后业务单」的扁平字段为准,避免明细表(business_document_address_multi)旧值覆盖
|
||||||
|
TmsAddressMultiDTO loadingDto = new TmsAddressMultiDTO();
|
||||||
|
loadingDto.setAreaCode(after.getLoadingAreaId());
|
||||||
|
loadingDto.setAreaName(after.getLoadingName());
|
||||||
|
loadingDto.setAddress(after.getLoadingAddress());
|
||||||
|
loadingDto.setLongitude(after.getLoadingLongitude());
|
||||||
|
loadingDto.setLatitude(after.getLoadingLatitude());
|
||||||
|
loadingDto.setContactName(after.getFreighterName());
|
||||||
|
loadingDto.setContactPhone(after.getLoadingPhone());
|
||||||
|
loadingDto.setLayDate(after.getLoadingDate());
|
||||||
|
loadingDto.setLayType(1);
|
||||||
|
List<TmsAddressMultiDTO> loadingAddressList = new ArrayList<>();
|
||||||
|
loadingAddressList.add(loadingDto);
|
||||||
|
tmsOrderAddDTO.setLoadingAddressList(loadingAddressList);
|
||||||
|
|
||||||
|
// 卸货地址:同样以「调整后业务单」的扁平字段为准
|
||||||
|
TmsAddressMultiDTO unloadDto = new TmsAddressMultiDTO();
|
||||||
|
unloadDto.setAreaCode(after.getUnloadAreaId());
|
||||||
|
unloadDto.setAreaName(after.getUnloadName());
|
||||||
|
unloadDto.setAddress(after.getUnloadAddress());
|
||||||
|
unloadDto.setLongitude(after.getUnloadLongitude());
|
||||||
|
unloadDto.setLatitude(after.getUnloadLatitude());
|
||||||
|
unloadDto.setContactName(after.getDischargerName());
|
||||||
|
unloadDto.setContactPhone(after.getUnloadPhone());
|
||||||
|
unloadDto.setLayDate(after.getUnloadingData());
|
||||||
|
unloadDto.setLayType(2);
|
||||||
|
List<TmsAddressMultiDTO> unloadAddressList = new ArrayList<>();
|
||||||
|
unloadAddressList.add(unloadDto);
|
||||||
|
tmsOrderAddDTO.setUnloadAddressList(unloadAddressList);
|
||||||
|
|
||||||
|
// 费用明细
|
||||||
|
List<BusinessOrderAccount> accountList = businessOrderAccountMapper.selectList(
|
||||||
|
new LambdaQueryWrapper<BusinessOrderAccount>()
|
||||||
|
.eq(BusinessOrderAccount::getOrderId, after.getId())
|
||||||
|
.eq(BusinessOrderAccount::getIsDelete, 0));
|
||||||
|
List<TmsOrderAccount> tmsOrderAccountList = new ArrayList<>();
|
||||||
|
if (accountList != null) {
|
||||||
|
for (BusinessOrderAccount acc : accountList) {
|
||||||
|
TmsOrderAccount dto = new TmsOrderAccount();
|
||||||
|
BeanUtil.copyProperties(acc, dto);
|
||||||
|
tmsOrderAccountList.add(dto);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
tmsOrderAddDTO.setTmsOrderAccountList(tmsOrderAccountList);
|
||||||
|
|
||||||
|
AjaxResult result = wlhyServiceFeign.update(tmsOrderAddDTO);
|
||||||
|
if (result != null && "200".equals(String.valueOf(result.get("code")))) {
|
||||||
|
log.info("调整后同步修改TMS订单成功,执行单[{}],业务单[{}]", executeOrder.getGoodsNumber(), after.getGoodsNumber());
|
||||||
|
} else {
|
||||||
|
log.error("调整后同步修改TMS订单失败,执行单[{}],返回: {}", executeOrder.getGoodsNumber(),
|
||||||
|
result == null ? "null" : result.get("msg"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+6
-50
@@ -11,7 +11,6 @@ import com.mhd.oms.domain.outEntrustOrder.repository.po.OutEntrustOrderPO;
|
|||||||
import com.mhd.oms.domain.outEntrustOrder.repository.todo.OutEntrustOrderDO;
|
import com.mhd.oms.domain.outEntrustOrder.repository.todo.OutEntrustOrderDO;
|
||||||
import com.mhd.oms.domain.outEntrustOrder.repository.todo.OutEntrustOrderDetailDO;
|
import com.mhd.oms.domain.outEntrustOrder.repository.todo.OutEntrustOrderDetailDO;
|
||||||
import com.mhd.oms.domain.outEntrustOrder.service.OutEntrustOrderDomainService;
|
import com.mhd.oms.domain.outEntrustOrder.service.OutEntrustOrderDomainService;
|
||||||
import com.mhd.oms.domain.outEntrustOrder.repository.listener.OutEntrustExcelParseService;
|
|
||||||
import com.mhd.system.api.SystemServiceFeign;
|
import com.mhd.system.api.SystemServiceFeign;
|
||||||
import com.mhd.system.api.WmsServiceFeign;
|
import com.mhd.system.api.WmsServiceFeign;
|
||||||
import com.mhd.system.api.domain.NoticeMaterialDetailDTO;
|
import com.mhd.system.api.domain.NoticeMaterialDetailDTO;
|
||||||
@@ -21,10 +20,8 @@ import com.mhd.system.api.model.LoginUser;
|
|||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
import org.springframework.web.multipart.MultipartFile;
|
|
||||||
|
|
||||||
import javax.annotation.Resource;
|
import javax.annotation.Resource;
|
||||||
import java.io.IOException;
|
|
||||||
import java.math.BigDecimal;
|
import java.math.BigDecimal;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
@@ -49,15 +46,9 @@ public class OutEntrustOrderApplicationService {
|
|||||||
@Resource
|
@Resource
|
||||||
private SystemServiceFeign systemServiceFeign;
|
private SystemServiceFeign systemServiceFeign;
|
||||||
|
|
||||||
@Resource
|
|
||||||
private com.mhd.oms.application.service.WarehouseInfoApplicationService warehouseInfoApplicationService;
|
|
||||||
|
|
||||||
@Resource
|
@Resource
|
||||||
private WmsServiceFeign wmsServiceFeign;
|
private WmsServiceFeign wmsServiceFeign;
|
||||||
|
|
||||||
@Resource
|
|
||||||
private OutEntrustExcelParseService outEntrustExcelParseService;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 分页查询出仓委托单列表(不做默认状态过滤,显示全部数据)
|
* 分页查询出仓委托单列表(不做默认状态过滤,显示全部数据)
|
||||||
*/
|
*/
|
||||||
@@ -114,45 +105,6 @@ public class OutEntrustOrderApplicationService {
|
|||||||
return outEntrustOrderDomainService.insert(outEntrustOrderDO);
|
return outEntrustOrderDomainService.insert(outEntrustOrderDO);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 导入出仓委托单(模板与WMS出库管理导入一致:前11行表头+第12行起明细)
|
|
||||||
* 解析校验通过后复用新增链路落库:生成CKWT委托单号,状态待审核/未下发
|
|
||||||
*
|
|
||||||
* @return 校验错误信息;空串表示导入成功
|
|
||||||
*/
|
|
||||||
public StringBuilder importOutEntrustOrder(MultipartFile file, Long warehouseId, String warehouseCode, String warehouseName) throws IOException {
|
|
||||||
//解析+校验(客户解析/物料匹配/字典转换/必填项)
|
|
||||||
OutEntrustExcelParseService.ParseResult parseResult =
|
|
||||||
outEntrustExcelParseService.parseOutEntrustOrderExcel(file, warehouseName, warehouseCode, warehouseId);
|
|
||||||
if (parseResult.getErrorMsg().length() > 0) {
|
|
||||||
return parseResult.getErrorMsg();
|
|
||||||
}
|
|
||||||
OutEntrustOrderDO outEntrustOrderDO = parseResult.getOrder();
|
|
||||||
//审计信息(与WMS出库导入一致,导入人=当前登录人)
|
|
||||||
LoginUser loginUser = SecurityUtils.getLoginUser();
|
|
||||||
if (loginUser != null) {
|
|
||||||
String userRealName;
|
|
||||||
if (loginUser.getUserPo() != null && loginUser.getUserPo().getUserName() != null
|
|
||||||
&& !loginUser.getUserPo().getUserName().trim().isEmpty()) {
|
|
||||||
userRealName = loginUser.getUserPo().getUserName();
|
|
||||||
} else if (loginUser.getRealname() != null && !loginUser.getRealname().trim().isEmpty()) {
|
|
||||||
userRealName = loginUser.getRealname();
|
|
||||||
} else {
|
|
||||||
userRealName = loginUser.getUsername();
|
|
||||||
}
|
|
||||||
Date now = new Date();
|
|
||||||
outEntrustOrderDO.setCreateBy(loginUser.getUserid());
|
|
||||||
outEntrustOrderDO.setCreateByName(userRealName);
|
|
||||||
outEntrustOrderDO.setCreateTime(now);
|
|
||||||
outEntrustOrderDO.setUpdateBy(loginUser.getUserid());
|
|
||||||
outEntrustOrderDO.setUpdateByName(userRealName);
|
|
||||||
outEntrustOrderDO.setUpdateTime(now);
|
|
||||||
}
|
|
||||||
//复用新增链路:必填校验→默认普通出库→仓库校验→组织信息→汇总申报数量→生成CKWT委托单号(待审核/未下发)
|
|
||||||
insert(outEntrustOrderDO);
|
|
||||||
return new StringBuilder();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 修改出仓委托单(仅待审核/已驳回且未下发可修改;已驳回单编辑后状态重置为待审核)
|
* 修改出仓委托单(仅待审核/已驳回且未下发可修改;已驳回单编辑后状态重置为待审核)
|
||||||
*/
|
*/
|
||||||
@@ -400,10 +352,14 @@ public class OutEntrustOrderApplicationService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 仓库信息校验并回填编码/名称 (Feign失败走本地跨库兜底)
|
* 仓库信息校验并回填编码/名称
|
||||||
*/
|
*/
|
||||||
private void setWarehouseInfo(OutEntrustOrderDO outEntrustOrderDO) {
|
private void setWarehouseInfo(OutEntrustOrderDO outEntrustOrderDO) {
|
||||||
WarehouseFeignPO warehouseFeignPO = warehouseInfoApplicationService.getWarehouseInfo(outEntrustOrderDO.getWarehouseId());
|
AjaxResult ajaxResult = systemServiceFeign.getWarehouseInfoByWarehouseId(outEntrustOrderDO.getWarehouseId());
|
||||||
|
if (ajaxResult == null || !"200".equals(String.valueOf(ajaxResult.get("code")))) {
|
||||||
|
throw new ServiceException("获取仓库信息失败,请检查仓库是否有效");
|
||||||
|
}
|
||||||
|
WarehouseFeignPO warehouseFeignPO = JSONUtil.toBean(JSONUtil.toJsonStr(ajaxResult.get("data")), WarehouseFeignPO.class);
|
||||||
if (warehouseFeignPO == null || Objects.isNull(warehouseFeignPO.getWarehouseId())) {
|
if (warehouseFeignPO == null || Objects.isNull(warehouseFeignPO.getWarehouseId())) {
|
||||||
throw new ServiceException("仓库不存在,请重新选择");
|
throw new ServiceException("仓库不存在,请重新选择");
|
||||||
}
|
}
|
||||||
|
|||||||
+33
-1
@@ -8,6 +8,7 @@ import com.mhd.common.core.web.domain.BaseVOEntity;
|
|||||||
import java.math.BigDecimal;
|
import java.math.BigDecimal;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
|
import java.util.List;
|
||||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||||
import org.springframework.format.annotation.DateTimeFormat;
|
import org.springframework.format.annotation.DateTimeFormat;
|
||||||
|
|
||||||
@@ -659,7 +660,7 @@ public class BusinessDocumentOrder extends BaseVOEntity{
|
|||||||
@Excel(name = "${comment}", readConverterExp = "$column.readConverterExp()")
|
@Excel(name = "${comment}", readConverterExp = "$column.readConverterExp()")
|
||||||
private Date documentDate;
|
private Date documentDate;
|
||||||
|
|
||||||
@ApiModelProperty( "审核状态 0-未审核 1-审核通过 2-已驳回")
|
@ApiModelProperty( "审核状态 0-未审核 1-审核通过 2-已驳回 3-调整待审核 4-调整驳回")
|
||||||
private Long reviewStatus;
|
private Long reviewStatus;
|
||||||
|
|
||||||
@ApiModelProperty("审核时间")
|
@ApiModelProperty("审核时间")
|
||||||
@@ -825,4 +826,35 @@ public class BusinessDocumentOrder extends BaseVOEntity{
|
|||||||
@ApiModelProperty("车次")
|
@ApiModelProperty("车次")
|
||||||
@Excel(name = "车次")
|
@Excel(name = "车次")
|
||||||
private String shuttleNo;
|
private String shuttleNo;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 前端整单回传时携带的费用明细(business_order_account),非表字段,仅用于「订单调整」入参接收。
|
||||||
|
* 与顶层 feeDetailList 二选一,后端在 adjust() 中做回退兼容。
|
||||||
|
*/
|
||||||
|
@com.baomidou.mybatisplus.annotation.TableField(exist = false)
|
||||||
|
private List<com.mhd.oms.domain.businessOrderAccount.BusinessOrderAccount> businessOrderAccountList;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 前端整单回传时的装货地址(单个),非表字段,仅用于「订单调整」入参接收与映射到 loading* 扁平字段。
|
||||||
|
*/
|
||||||
|
@com.baomidou.mybatisplus.annotation.TableField(exist = false)
|
||||||
|
private com.mhd.oms.interfaces.dto.businessDocumentAddressMulti.BusinessDocumentAddressMultiDTO shipment;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 前端整单回传时的卸货地址(单个),非表字段,仅用于「订单调整」入参接收与映射到 unload* 扁平字段。
|
||||||
|
*/
|
||||||
|
@com.baomidou.mybatisplus.annotation.TableField(exist = false)
|
||||||
|
private com.mhd.oms.interfaces.dto.businessDocumentAddressMulti.BusinessDocumentAddressMultiDTO receipt;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 前端整单回传时的装货地址集合,非表字段,仅用于「订单调整」入参接收与映射。
|
||||||
|
*/
|
||||||
|
@com.baomidou.mybatisplus.annotation.TableField(exist = false)
|
||||||
|
private List<com.mhd.oms.interfaces.dto.businessDocumentAddressMulti.BusinessDocumentAddressMultiDTO> loadingAddressList;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 前端整单回传时的卸货地址集合,非表字段,仅用于「订单调整」入参接收与映射。
|
||||||
|
*/
|
||||||
|
@com.baomidou.mybatisplus.annotation.TableField(exist = false)
|
||||||
|
private List<com.mhd.oms.interfaces.dto.businessDocumentAddressMulti.BusinessDocumentAddressMultiDTO> unloadAddressList;
|
||||||
}
|
}
|
||||||
|
|||||||
+3
-3
@@ -39,8 +39,8 @@ public interface BusinessDocumentOrderMapper extends BaseMapper<BusinessDocument
|
|||||||
String getPushVerifyByOrgId(@Param("organizationId") Long organizationId);
|
String getPushVerifyByOrgId(@Param("organizationId") Long organizationId);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 查询指定日期前缀(yyMMdd)下已生成的新格式业务单号列表
|
* 统计指定日期前缀(yyMMdd)下已生成的新格式业务单号数量
|
||||||
* 仅查新格式(长度<=12),过滤历史16位旧数据,供取号器解析当日最大序号
|
* 仅统计新格式(长度<=12),过滤历史16位旧数据,保证序号每日从001正确累计
|
||||||
*/
|
*/
|
||||||
List<String> selectGoodsNumbersByPrefix(@Param("prefix") String prefix);
|
int countByGoodsNumberPrefix(@Param("prefix") String prefix);
|
||||||
}
|
}
|
||||||
|
|||||||
+5
-2
@@ -237,8 +237,11 @@ public class BusinessDocumentOrderImpl extends ServiceImpl<BusinessDocumentOrder
|
|||||||
subOrder.setRecipientName(user.getUserName());
|
subOrder.setRecipientName(user.getUserName());
|
||||||
|
|
||||||
|
|
||||||
//生成子单货源单号(yyMMdd + 当日顺序号)并落库, 撞唯一索引自动重新取号重试
|
//生成子单货源单号(yyMMdd + 当日顺序号)
|
||||||
goodsNumberGenerator.insertWithUniqueGoodsNumber(subOrder);
|
String orderCode = goodsNumberGenerator.generateUniqueGoodsNumber(subOrder.getDocumentDate());
|
||||||
|
subOrder.setGoodsNumber(orderCode);
|
||||||
|
|
||||||
|
businessDocumentOrderMapper.insert(subOrder);
|
||||||
subOrderCount++; // 增加子单计数
|
subOrderCount++; // 增加子单计数
|
||||||
|
|
||||||
// 保存子单的地址信息到BUSINESS_DOCUMENT_ADDRESS_MULTI表
|
// 保存子单的地址信息到BUSINESS_DOCUMENT_ADDRESS_MULTI表
|
||||||
|
|||||||
+19
-21
@@ -285,9 +285,24 @@ public class BusinessDocumentOrderDomainService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//生成货源单号并落库见下方 insertWithUniqueGoodsNumber:
|
//生成货源单号(yyMMdd + 当日顺序号,每日重置)
|
||||||
//取号与插单合并为原子重试(撞goods_number唯一索引自动重新取号),
|
String orderCode = goodsNumberGenerator.generateUniqueGoodsNumber(tmsOrder.getDocumentDate());
|
||||||
//出库/入库业务单的单号回填也移至插单成功之后,避免插单失败留下脏回填
|
tmsOrder.setGoodsNumber(orderCode);
|
||||||
|
|
||||||
|
ReservationStockOutOrder reservationStockOutOrder = reservationStockOutOrderMapper.selectOne(new LambdaQueryWrapper<ReservationStockOutOrder>()
|
||||||
|
.eq(ReservationStockOutOrder::getOutOrderNumber, tmsOrder.getInOrderNumber())
|
||||||
|
.eq(ReservationStockOutOrder::getDelFlag, 1));
|
||||||
|
if (reservationStockOutOrder != null){
|
||||||
|
reservationStockOutOrder.setBusinessNumber(tmsOrder.getGoodsNumber());
|
||||||
|
reservationStockOutOrderMapper.updateById(reservationStockOutOrder);
|
||||||
|
}
|
||||||
|
ReservationStockInOrder reservationStockInOrder = reservationStockInOrderMapper.selectOne(new LambdaQueryWrapper<ReservationStockInOrder>()
|
||||||
|
.eq(ReservationStockInOrder::getInOrderNumber, tmsOrder.getInOrderNumber())
|
||||||
|
.eq(ReservationStockInOrder::getDelFlag, 1));
|
||||||
|
if (reservationStockInOrder != null){
|
||||||
|
reservationStockInOrder.setBusinessNumber(tmsOrder.getGoodsNumber());
|
||||||
|
reservationStockInOrderMapper.updateById(reservationStockInOrder);
|
||||||
|
}
|
||||||
|
|
||||||
List<BusinessDocumentAddressMultiDTO> loadingAddressList = businessDocumentOrderDO.getLoadingAddressList();//装货地信息集合
|
List<BusinessDocumentAddressMultiDTO> loadingAddressList = businessDocumentOrderDO.getLoadingAddressList();//装货地信息集合
|
||||||
List<BusinessDocumentAddressMultiDTO> unloadAddressList = businessDocumentOrderDO.getUnloadAddressList();//卸货地信息集合
|
List<BusinessDocumentAddressMultiDTO> unloadAddressList = businessDocumentOrderDO.getUnloadAddressList();//卸货地信息集合
|
||||||
@@ -411,24 +426,7 @@ public class BusinessDocumentOrderDomainService {
|
|||||||
//一天后
|
//一天后
|
||||||
tmsOrder.setDocumentDate(businessDocumentOrderDO.getDocumentDate());
|
tmsOrder.setDocumentDate(businessDocumentOrderDO.getDocumentDate());
|
||||||
|
|
||||||
//生成货源单号(yyMMdd + 当日顺序号,每日重置)并落库, 撞唯一索引自动重新取号重试
|
boolean istrue = businessDocumentOrderMapper.insert(tmsOrder) > 0;
|
||||||
boolean istrue = goodsNumberGenerator.insertWithUniqueGoodsNumber(tmsOrder);
|
|
||||||
|
|
||||||
//落库成功后将运输业务单号回填至关联的出库/入库业务单
|
|
||||||
ReservationStockOutOrder reservationStockOutOrder = reservationStockOutOrderMapper.selectOne(new LambdaQueryWrapper<ReservationStockOutOrder>()
|
|
||||||
.eq(ReservationStockOutOrder::getOutOrderNumber, tmsOrder.getInOrderNumber())
|
|
||||||
.eq(ReservationStockOutOrder::getDelFlag, 1));
|
|
||||||
if (reservationStockOutOrder != null){
|
|
||||||
reservationStockOutOrder.setBusinessNumber(tmsOrder.getGoodsNumber());
|
|
||||||
reservationStockOutOrderMapper.updateById(reservationStockOutOrder);
|
|
||||||
}
|
|
||||||
ReservationStockInOrder reservationStockInOrder = reservationStockInOrderMapper.selectOne(new LambdaQueryWrapper<ReservationStockInOrder>()
|
|
||||||
.eq(ReservationStockInOrder::getInOrderNumber, tmsOrder.getInOrderNumber())
|
|
||||||
.eq(ReservationStockInOrder::getDelFlag, 1));
|
|
||||||
if (reservationStockInOrder != null){
|
|
||||||
reservationStockInOrder.setBusinessNumber(tmsOrder.getGoodsNumber());
|
|
||||||
reservationStockInOrderMapper.updateById(reservationStockInOrder);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (hasDetails) {
|
if (hasDetails) {
|
||||||
for (BusinessDeliveryDetailsLinkDTO businessDeliveryDetailsLinkDTO : businessDeliveryDetailsLinkDTOList) {
|
for (BusinessDeliveryDetailsLinkDTO businessDeliveryDetailsLinkDTO : businessDeliveryDetailsLinkDTOList) {
|
||||||
|
|||||||
+3
-89
@@ -5,44 +5,23 @@ import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
|||||||
import com.mhd.common.core.exception.ServiceException;
|
import com.mhd.common.core.exception.ServiceException;
|
||||||
import com.mhd.oms.domain.businessDocumentOrder.entity.BusinessDocumentOrder;
|
import com.mhd.oms.domain.businessDocumentOrder.entity.BusinessDocumentOrder;
|
||||||
import com.mhd.oms.domain.businessDocumentOrder.repository.mapper.BusinessDocumentOrderMapper;
|
import com.mhd.oms.domain.businessDocumentOrder.repository.mapper.BusinessDocumentOrderMapper;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.dao.DuplicateKeyException;
|
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
import org.springframework.util.CollectionUtils;
|
import org.springframework.util.CollectionUtils;
|
||||||
|
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 业务单据订单(goodsNumber)单号生成器
|
* 业务单据订单(goodsNumber)单号生成器
|
||||||
* 规则: yyMMdd(取自单据日期) + 当日顺序号(每日重置, 3位起步, 超999自动扩位)
|
* 规则: yyMMdd(取自单据日期) + 当日顺序号(每日重置, 3位起步, 超999自动扩位)
|
||||||
* 示例: 260804001、260804999、2608041000
|
* 示例: 260804001、260804999、2608041000
|
||||||
*
|
|
||||||
* 唯一性保障(不依赖唯一索引, 三层防线):
|
|
||||||
* 1) 取号: 当日已生成单号 MAX+1 作为基线 + 候选号存在性校验后移收敛
|
|
||||||
* (对齐入库单号修复先例 ReservationStockInOrderDomainService#generateReserveOrderNumber)
|
|
||||||
* 2) 落库: 按日期前缀分段的JVM锁串行化"取号+插单", 消除本实例内并发审核/
|
|
||||||
* 批量取号的check-then-act竞态(多实例部署时本层只覆盖各自实例)
|
|
||||||
* 3) 自检自愈: 插单后立即校验同号数量, >1 说明与并发插入撞号, 给本单重新
|
|
||||||
* 取号改号, 兜住跨实例残余竞态
|
|
||||||
* 若日后补建goods_number唯一索引(见 sql/20260906_oms_business_goods_number_unique.sql),
|
|
||||||
* 撞号将抛DuplicateKeyException由重试逻辑接住, 与上述防线叠加互不冲突
|
|
||||||
*/
|
*/
|
||||||
@Slf4j
|
|
||||||
@Component
|
@Component
|
||||||
public class GoodsNumberGenerator {
|
public class GoodsNumberGenerator {
|
||||||
|
|
||||||
private static final int MAX_RETRY = 100;
|
private static final int MAX_RETRY = 100;
|
||||||
|
|
||||||
/**
|
|
||||||
* 取号+插单分段锁: 按单号日期前缀(yyMMdd)分段, 同日串行、跨日并行,
|
|
||||||
* 锁对象常驻(每日新增1个, 增量可忽略)
|
|
||||||
*/
|
|
||||||
private static final Map<String, Object> LOCK_STRIPES = new ConcurrentHashMap<>();
|
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private BusinessDocumentOrderMapper businessDocumentOrderMapper;
|
private BusinessDocumentOrderMapper businessDocumentOrderMapper;
|
||||||
|
|
||||||
@@ -54,21 +33,8 @@ public class GoodsNumberGenerator {
|
|||||||
Date date = (documentDate == null) ? new Date() : documentDate;
|
Date date = (documentDate == null) ? new Date() : documentDate;
|
||||||
String datePart = DateUtil.format(date, "yyMMdd");
|
String datePart = DateUtil.format(date, "yyMMdd");
|
||||||
|
|
||||||
// 当日已生成单号的最大序号作为基线(MAX+1而非COUNT+1, 防脏数据/序号错位导致回退复用)
|
// count 只查一次作为序号基线
|
||||||
List<String> existNumbers = businessDocumentOrderMapper.selectGoodsNumbersByPrefix(datePart);
|
long seq = (long) businessDocumentOrderMapper.countByGoodsNumberPrefix(datePart) + 1;
|
||||||
long seq = 0;
|
|
||||||
for (String existNumber : existNumbers) {
|
|
||||||
if (existNumber == null || existNumber.length() <= datePart.length()) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
String numStr = existNumber.substring(datePart.length());
|
|
||||||
if (!numStr.matches("\\d+")) {
|
|
||||||
continue; // 防脏数据(非纯数字后缀)导致解析失败
|
|
||||||
}
|
|
||||||
seq = Math.max(seq, Long.parseLong(numStr));
|
|
||||||
}
|
|
||||||
seq = seq + 1;
|
|
||||||
|
|
||||||
int retryCount = 0;
|
int retryCount = 0;
|
||||||
while (retryCount < MAX_RETRY) {
|
while (retryCount < MAX_RETRY) {
|
||||||
String orderCode = datePart + String.format("%03d", seq);
|
String orderCode = datePart + String.format("%03d", seq);
|
||||||
@@ -80,60 +46,8 @@ public class GoodsNumberGenerator {
|
|||||||
if (CollectionUtils.isEmpty(exist)) {
|
if (CollectionUtils.isEmpty(exist)) {
|
||||||
return orderCode;
|
return orderCode;
|
||||||
}
|
}
|
||||||
seq++; // ← 关键:查重失败,序号往后递增找空位,而不是重新取基线
|
seq++; // ← 关键:查重失败,序号往后递增找空位,而不是重新count
|
||||||
}
|
}
|
||||||
throw new ServiceException("生成唯一业务单号失败,已达到最大重试次数:" + MAX_RETRY);
|
throw new ServiceException("生成唯一业务单号失败,已达到最大重试次数:" + MAX_RETRY);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 生成唯一业务单号并落库: JVM分段锁内完成"取号+插单",
|
|
||||||
* 插入撞goods_number唯一索引时自动重新取号重试(索引为可选兜底),
|
|
||||||
* 插单成功后自检同号并自愈改号。
|
|
||||||
* 供业务单创建入口(手动/审核新增、审核拆单、预约确认)统一使用。
|
|
||||||
* @return 是否插入成功(mapper.insert结果)
|
|
||||||
*/
|
|
||||||
public boolean insertWithUniqueGoodsNumber(BusinessDocumentOrder order) {
|
|
||||||
Date date = (order.getDocumentDate() == null) ? new Date() : order.getDocumentDate();
|
|
||||||
String lockKey = DateUtil.format(date, "yyMMdd");
|
|
||||||
synchronized (LOCK_STRIPES.computeIfAbsent(lockKey, k -> new Object())) {
|
|
||||||
int retryCount = 0;
|
|
||||||
while (retryCount < MAX_RETRY) {
|
|
||||||
retryCount++;
|
|
||||||
order.setGoodsNumber(generateUniqueGoodsNumber(order.getDocumentDate()));
|
|
||||||
try {
|
|
||||||
boolean inserted = businessDocumentOrderMapper.insert(order) > 0;
|
|
||||||
// 插单后自检自愈: 无唯一索引时跨实例并发窗口内的撞号双方都能落库,
|
|
||||||
// 同号数量>1说明本单撞号, 给本单重新取号改号, 防止单号重复扩散
|
|
||||||
healIfDuplicated(order);
|
|
||||||
return inserted;
|
|
||||||
} catch (DuplicateKeyException e) {
|
|
||||||
// 已建唯一索引时的兜底: 仅业务单号撞唯一索引时重试, 其他唯一约束冲突原样抛出
|
|
||||||
String message = e.getMessage();
|
|
||||||
if (message == null || !message.toLowerCase().contains("goods_number")) {
|
|
||||||
throw e;
|
|
||||||
}
|
|
||||||
log.warn("业务单号[{}]撞号, 自动重新取号重试(第{}次): {}", order.getGoodsNumber(), retryCount, message);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
throw new ServiceException("生成唯一业务单号失败,已达到最大重试次数:" + MAX_RETRY);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 插单后自检自愈: 查同号数量, >1 说明有并发插入撞号(本单为后插入方),
|
|
||||||
* 保持先落库单据单号不变, 重新取号给本单改号
|
|
||||||
*/
|
|
||||||
private void healIfDuplicated(BusinessDocumentOrder order) {
|
|
||||||
List<BusinessDocumentOrder> sameNumber = businessDocumentOrderMapper.selectList(
|
|
||||||
new QueryWrapper<BusinessDocumentOrder>().eq("goods_number", order.getGoodsNumber())
|
|
||||||
);
|
|
||||||
if (sameNumber != null && sameNumber.size() > 1) {
|
|
||||||
String oldNumber = order.getGoodsNumber();
|
|
||||||
String newNumber = generateUniqueGoodsNumber(order.getDocumentDate());
|
|
||||||
order.setGoodsNumber(newNumber);
|
|
||||||
businessDocumentOrderMapper.updateById(order);
|
|
||||||
log.warn("业务单号[{}]与并发插入撞号(无唯一索引兜底), 已自愈改号为[{}], orderId={}",
|
|
||||||
oldNumber, newNumber, order.getId());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
+103
@@ -0,0 +1,103 @@
|
|||||||
|
package com.mhd.oms.domain.businessDocumentOrderAdjust.entity;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.annotation.IdType;
|
||||||
|
import com.baomidou.mybatisplus.annotation.TableId;
|
||||||
|
import com.baomidou.mybatisplus.annotation.TableName;
|
||||||
|
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||||
|
import io.swagger.annotations.ApiModelProperty;
|
||||||
|
import lombok.Data;
|
||||||
|
import org.springframework.format.annotation.DateTimeFormat;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 运输业务单 调整主记录
|
||||||
|
*
|
||||||
|
* @author dev
|
||||||
|
* @date 2026-09-09
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@TableName("business_document_order_adjust")
|
||||||
|
public class BusinessDocumentOrderAdjust implements Serializable {
|
||||||
|
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
@ApiModelProperty("主键")
|
||||||
|
@TableId(type = IdType.ASSIGN_ID)
|
||||||
|
private Long id;
|
||||||
|
|
||||||
|
@ApiModelProperty("业务单ID")
|
||||||
|
private Long orderId;
|
||||||
|
|
||||||
|
@ApiModelProperty("业务单号")
|
||||||
|
private String goodsNumber;
|
||||||
|
|
||||||
|
@ApiModelProperty("调整人账号")
|
||||||
|
private String adjustBy;
|
||||||
|
|
||||||
|
@ApiModelProperty("调整人姓名")
|
||||||
|
private String adjustByName;
|
||||||
|
|
||||||
|
@ApiModelProperty("调整时间")
|
||||||
|
@JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss")
|
||||||
|
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||||
|
private Date adjustTime;
|
||||||
|
|
||||||
|
@ApiModelProperty("调整原因")
|
||||||
|
private String adjustReason;
|
||||||
|
|
||||||
|
@ApiModelProperty("是否需要审核 0-否 1-是")
|
||||||
|
private Integer isAudit;
|
||||||
|
|
||||||
|
@ApiModelProperty("调整前业务单审核状态(review_status原值,用于调整审核通过/驳回后还原,避免影响其它)")
|
||||||
|
private Long beforeReviewStatus;
|
||||||
|
|
||||||
|
@ApiModelProperty("审核状态 0-待审核 1-审核通过 2-驳回")
|
||||||
|
private Integer auditStatus;
|
||||||
|
|
||||||
|
@ApiModelProperty("审核人账号")
|
||||||
|
private String auditBy;
|
||||||
|
|
||||||
|
@ApiModelProperty("审核人姓名")
|
||||||
|
private String auditByName;
|
||||||
|
|
||||||
|
@ApiModelProperty("审核时间")
|
||||||
|
@JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss")
|
||||||
|
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||||
|
private Date auditTime;
|
||||||
|
|
||||||
|
@ApiModelProperty("审核/驳回意见")
|
||||||
|
private String auditRemark;
|
||||||
|
|
||||||
|
@ApiModelProperty("组织ID")
|
||||||
|
private String orgId;
|
||||||
|
|
||||||
|
@ApiModelProperty("一级组织ID")
|
||||||
|
private String topOrgId;
|
||||||
|
|
||||||
|
@ApiModelProperty("创建人")
|
||||||
|
private String createBy;
|
||||||
|
|
||||||
|
@ApiModelProperty("创建人姓名")
|
||||||
|
private String createName;
|
||||||
|
|
||||||
|
@ApiModelProperty("创建时间")
|
||||||
|
@JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss")
|
||||||
|
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||||
|
private Date createTime;
|
||||||
|
|
||||||
|
@ApiModelProperty("更新人")
|
||||||
|
private String updateBy;
|
||||||
|
|
||||||
|
@ApiModelProperty("更新人姓名")
|
||||||
|
private String updateName;
|
||||||
|
|
||||||
|
@ApiModelProperty("更新时间")
|
||||||
|
@JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss")
|
||||||
|
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||||
|
private Date updateTime;
|
||||||
|
|
||||||
|
@ApiModelProperty("删除标记 1-正常 0-删除")
|
||||||
|
private Integer delFlag;
|
||||||
|
}
|
||||||
+12
@@ -0,0 +1,12 @@
|
|||||||
|
package com.mhd.oms.domain.businessDocumentOrderAdjust.repository.mapper;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||||
|
import com.mhd.oms.domain.businessDocumentOrderAdjust.entity.BusinessDocumentOrderAdjust;
|
||||||
|
import org.apache.ibatis.annotations.Mapper;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 运输业务单 调整主记录 Mapper
|
||||||
|
*/
|
||||||
|
@Mapper
|
||||||
|
public interface BusinessDocumentOrderAdjustMapper extends BaseMapper<BusinessDocumentOrderAdjust> {
|
||||||
|
}
|
||||||
+189
@@ -0,0 +1,189 @@
|
|||||||
|
package com.mhd.oms.domain.businessDocumentOrderAdjustDetail.entity;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.annotation.IdType;
|
||||||
|
import com.baomidou.mybatisplus.annotation.TableId;
|
||||||
|
import com.baomidou.mybatisplus.annotation.TableName;
|
||||||
|
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||||
|
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
|
||||||
|
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
|
||||||
|
import io.swagger.annotations.ApiModelProperty;
|
||||||
|
import lombok.Data;
|
||||||
|
import org.springframework.format.annotation.DateTimeFormat;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 运输业务单 调整明细(调整后业务单整行快照)
|
||||||
|
*
|
||||||
|
* @author dev
|
||||||
|
* @date 2026-09-09
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@TableName("business_document_order_adjust_detail")
|
||||||
|
public class BusinessDocumentOrderAdjustDetail implements Serializable {
|
||||||
|
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
@ApiModelProperty("主键")
|
||||||
|
@TableId(type = IdType.ASSIGN_ID)
|
||||||
|
@JsonSerialize(using = ToStringSerializer.class)
|
||||||
|
private Long id;
|
||||||
|
|
||||||
|
@ApiModelProperty("关联调整主记录ID")
|
||||||
|
@JsonSerialize(using = ToStringSerializer.class)
|
||||||
|
private Long adjustId;
|
||||||
|
|
||||||
|
@ApiModelProperty("业务单ID")
|
||||||
|
private Long orderId;
|
||||||
|
|
||||||
|
@ApiModelProperty("业务单号")
|
||||||
|
private String goodsNumber;
|
||||||
|
|
||||||
|
@ApiModelProperty("货物类型ID")
|
||||||
|
private String goodsTypeId;
|
||||||
|
|
||||||
|
@ApiModelProperty("货物名称")
|
||||||
|
private String goodsName;
|
||||||
|
|
||||||
|
@ApiModelProperty("车型")
|
||||||
|
private String carType;
|
||||||
|
|
||||||
|
@ApiModelProperty("装货地")
|
||||||
|
private String loadingName;
|
||||||
|
|
||||||
|
@ApiModelProperty("装货地址")
|
||||||
|
private String loadingAddress;
|
||||||
|
|
||||||
|
@ApiModelProperty("装货时间")
|
||||||
|
@JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss")
|
||||||
|
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||||
|
private Date loadingDate;
|
||||||
|
|
||||||
|
@ApiModelProperty("卸货地")
|
||||||
|
private String unloadName;
|
||||||
|
|
||||||
|
@ApiModelProperty("卸货地址")
|
||||||
|
private String unloadAddress;
|
||||||
|
|
||||||
|
@ApiModelProperty("卸货时间")
|
||||||
|
@JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss")
|
||||||
|
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||||
|
private Date unloadingData;
|
||||||
|
|
||||||
|
@ApiModelProperty("发货人")
|
||||||
|
private String freighterName;
|
||||||
|
|
||||||
|
@ApiModelProperty("装货电话")
|
||||||
|
private String loadingPhone;
|
||||||
|
|
||||||
|
@ApiModelProperty("收货人")
|
||||||
|
private String dischargerName;
|
||||||
|
|
||||||
|
@ApiModelProperty("卸货电话")
|
||||||
|
private String unloadPhone;
|
||||||
|
|
||||||
|
@ApiModelProperty("备注")
|
||||||
|
private String remarks;
|
||||||
|
|
||||||
|
@ApiModelProperty("线路")
|
||||||
|
private String route;
|
||||||
|
|
||||||
|
@ApiModelProperty("单据日期")
|
||||||
|
@JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss")
|
||||||
|
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||||
|
private Date documentDate;
|
||||||
|
|
||||||
|
@ApiModelProperty("组织ID")
|
||||||
|
private String orgId;
|
||||||
|
|
||||||
|
@ApiModelProperty("组织ID")
|
||||||
|
private Long organizationId;
|
||||||
|
|
||||||
|
@ApiModelProperty("组织名称")
|
||||||
|
private String organizationName;
|
||||||
|
|
||||||
|
@ApiModelProperty("一级组织ID")
|
||||||
|
private Long topOrganizationId;
|
||||||
|
|
||||||
|
// ==================== 金额/费用快照 ====================
|
||||||
|
@ApiModelProperty("发货运费")
|
||||||
|
private BigDecimal deliveryFreight;
|
||||||
|
|
||||||
|
@ApiModelProperty("已收运费")
|
||||||
|
private BigDecimal collectedFreight;
|
||||||
|
|
||||||
|
@ApiModelProperty("未收运费")
|
||||||
|
private BigDecimal uncollectedFreight;
|
||||||
|
|
||||||
|
@ApiModelProperty("少收运费")
|
||||||
|
private BigDecimal collectLessFreight;
|
||||||
|
|
||||||
|
@ApiModelProperty("运费单价(元/吨)")
|
||||||
|
private BigDecimal transportationUnitPrice;
|
||||||
|
|
||||||
|
@ApiModelProperty("信息费")
|
||||||
|
private BigDecimal infoFee;
|
||||||
|
|
||||||
|
@ApiModelProperty("计费单价")
|
||||||
|
private BigDecimal freightUnitPrice;
|
||||||
|
|
||||||
|
@ApiModelProperty("货物保险金额")
|
||||||
|
private BigDecimal cargoInsuranceAmount;
|
||||||
|
|
||||||
|
@ApiModelProperty("运费")
|
||||||
|
private BigDecimal freightCharges;
|
||||||
|
|
||||||
|
@ApiModelProperty("运费")
|
||||||
|
private BigDecimal freightFee;
|
||||||
|
|
||||||
|
@ApiModelProperty("卸货费")
|
||||||
|
private BigDecimal unloadingFee;
|
||||||
|
|
||||||
|
@ApiModelProperty("报关费")
|
||||||
|
private BigDecimal customsFee;
|
||||||
|
|
||||||
|
@ApiModelProperty("差货费")
|
||||||
|
private BigDecimal shortageFee;
|
||||||
|
|
||||||
|
@ApiModelProperty("杂费")
|
||||||
|
private BigDecimal miscellaneousFee;
|
||||||
|
|
||||||
|
@ApiModelProperty("其他费用")
|
||||||
|
private BigDecimal otherFee;
|
||||||
|
|
||||||
|
@ApiModelProperty("滞车费")
|
||||||
|
private BigDecimal detentionFee;
|
||||||
|
|
||||||
|
@ApiModelProperty("税率")
|
||||||
|
private BigDecimal taxRate;
|
||||||
|
|
||||||
|
@ApiModelProperty("创建人")
|
||||||
|
private String createBy;
|
||||||
|
|
||||||
|
@ApiModelProperty("创建人姓名")
|
||||||
|
private String createName;
|
||||||
|
|
||||||
|
@ApiModelProperty("创建时间")
|
||||||
|
@JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss")
|
||||||
|
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||||
|
private Date createTime;
|
||||||
|
|
||||||
|
@ApiModelProperty("更新人")
|
||||||
|
private String updateBy;
|
||||||
|
|
||||||
|
@ApiModelProperty("更新时间")
|
||||||
|
@JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss")
|
||||||
|
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||||
|
private Date updateTime;
|
||||||
|
|
||||||
|
@ApiModelProperty("删除标记 1-正常 0-删除")
|
||||||
|
private Integer delFlag;
|
||||||
|
|
||||||
|
@ApiModelProperty("调整后业务单整行JSON快照(用于全字段精确还原)")
|
||||||
|
private String orderSnapshotJson;
|
||||||
|
|
||||||
|
@ApiModelProperty("调整后费用明细JSON快照(business_order_account列表)")
|
||||||
|
private String feeDetailJson;
|
||||||
|
}
|
||||||
+12
@@ -0,0 +1,12 @@
|
|||||||
|
package com.mhd.oms.domain.businessDocumentOrderAdjustDetail.repository.mapper;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||||
|
import com.mhd.oms.domain.businessDocumentOrderAdjustDetail.entity.BusinessDocumentOrderAdjustDetail;
|
||||||
|
import org.apache.ibatis.annotations.Mapper;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 运输业务单 调整明细 Mapper
|
||||||
|
*/
|
||||||
|
@Mapper
|
||||||
|
public interface BusinessDocumentOrderAdjustDetailMapper extends BaseMapper<BusinessDocumentOrderAdjustDetail> {
|
||||||
|
}
|
||||||
+1
-1
@@ -501,6 +501,6 @@ public class ExecutionInMaterialDetailPO extends ExecutionStockInOrderBasePO {
|
|||||||
private BigDecimal insureAmount;
|
private BigDecimal insureAmount;
|
||||||
|
|
||||||
@ApiModelProperty("货物类型:0-物料 1-半成品 2-成品")
|
@ApiModelProperty("货物类型:0-物料 1-半成品 2-成品")
|
||||||
@Excel(name = "货物类型", readConverterExp = "0=物料,1=半成品,2=成品")
|
@Excel(name = "货物类型")
|
||||||
private Integer goodsType;
|
private Integer goodsType;
|
||||||
}
|
}
|
||||||
+1
-16
@@ -1,7 +1,5 @@
|
|||||||
package com.mhd.oms.domain.executionInMaterialDetail.repository.po;
|
package com.mhd.oms.domain.executionInMaterialDetail.repository.po;
|
||||||
|
|
||||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
|
||||||
import com.mhd.common.core.annotation.Excel;
|
|
||||||
import io.swagger.annotations.ApiModelProperty;
|
import io.swagger.annotations.ApiModelProperty;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
|
||||||
@@ -17,34 +15,21 @@ import java.util.Date;
|
|||||||
public class ExecutionInMaterialDetailWithOrderPO extends ExecutionInMaterialDetailPO {
|
public class ExecutionInMaterialDetailWithOrderPO extends ExecutionInMaterialDetailPO {
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
@ApiModelProperty("入库单流转状态(参考): 1-已创建 2-已审核 3-收货中 4-上架中 5-已入库 6-已取消 7-已关闭")
|
@ApiModelProperty("入库单状态: 1-已创建 2-已审核 3-收货中 4-上架中 5-已入库 6-已取消 7-已关闭")
|
||||||
private Integer inOrderStatus;
|
private Integer inOrderStatus;
|
||||||
|
|
||||||
@ApiModelProperty("入库单展示状态: 0-已创建 2-已审核 3-已驳回 4-已入库(WMS回写status=5时同步/推送创建时置4,前端状态列绑定此字段)")
|
|
||||||
@Excel(name = "单据状态", readConverterExp = "0=已创建,2=已审核,3=已驳回,4=已入库")
|
|
||||||
private Integer issueStatus;
|
|
||||||
|
|
||||||
@ApiModelProperty("货物种类(物料分类名称,多个逗号分隔)")
|
|
||||||
@Excel(name = "货物种类")
|
|
||||||
private String materialClassifyName;
|
|
||||||
|
|
||||||
@ApiModelProperty("入库单审核状态: 1-未审核 2-审核不通过 3-审核通过")
|
@ApiModelProperty("入库单审核状态: 1-未审核 2-审核不通过 3-审核通过")
|
||||||
@Excel(name = "入库单审核状态: 1-未审核 2-审核不通过 3-审核通过")
|
|
||||||
private Integer inOrderAuditStatus;
|
private Integer inOrderAuditStatus;
|
||||||
|
|
||||||
@ApiModelProperty("货主ID")
|
@ApiModelProperty("货主ID")
|
||||||
private Long orderShipperId;
|
private Long orderShipperId;
|
||||||
|
|
||||||
@ApiModelProperty("货主编码")
|
@ApiModelProperty("货主编码")
|
||||||
@Excel(name = "货主编码")
|
|
||||||
private String orderShipperCode;
|
private String orderShipperCode;
|
||||||
|
|
||||||
@ApiModelProperty("货主名称")
|
@ApiModelProperty("货主名称")
|
||||||
@Excel(name = "货主名称")
|
|
||||||
private String orderShipperName;
|
private String orderShipperName;
|
||||||
|
|
||||||
@ApiModelProperty("入库日期")
|
@ApiModelProperty("入库日期")
|
||||||
@JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8")
|
|
||||||
@Excel(name = "入仓日期", width = 30, dateFormat = "yyyy-MM-dd")
|
|
||||||
private Date warehouseDate;
|
private Date warehouseDate;
|
||||||
}
|
}
|
||||||
|
|||||||
-12
@@ -45,12 +45,6 @@ public class ExecutionInMaterialDetailQueryDTO extends BaseVOEntity {
|
|||||||
@ApiModelProperty("入库单类型编码")
|
@ApiModelProperty("入库单类型编码")
|
||||||
private String inOrderTypeCode;
|
private String inOrderTypeCode;
|
||||||
|
|
||||||
@ApiModelProperty("入库单类型编码(与inOrderTypeCode同义)")
|
|
||||||
private String orderTypeCode;
|
|
||||||
|
|
||||||
@ApiModelProperty("入库单类型名称(模糊查询)")
|
|
||||||
private String orderTypeName;
|
|
||||||
|
|
||||||
@ApiModelProperty("入库状态: 1-已创建 2-已审核 3-收货中 4-上架中 5-已入库 6-已取消 7-已关闭")
|
@ApiModelProperty("入库状态: 1-已创建 2-已审核 3-收货中 4-上架中 5-已入库 6-已取消 7-已关闭")
|
||||||
private Integer inStatus;
|
private Integer inStatus;
|
||||||
|
|
||||||
@@ -72,10 +66,4 @@ public class ExecutionInMaterialDetailQueryDTO extends BaseVOEntity {
|
|||||||
|
|
||||||
@ApiModelProperty("物料名称")
|
@ApiModelProperty("物料名称")
|
||||||
private String materialName;
|
private String materialName;
|
||||||
|
|
||||||
@ApiModelProperty("实际入仓日期 开始(yyyy-MM-dd,为空按建档时间兜底)")
|
|
||||||
private String warehouseDateStart;
|
|
||||||
|
|
||||||
@ApiModelProperty("实际入仓日期 结束(yyyy-MM-dd,为空按建档时间兜底)")
|
|
||||||
private String warehouseDateEnd;
|
|
||||||
}
|
}
|
||||||
|
|||||||
-12
@@ -78,12 +78,6 @@ public class QueryOrderOverStockDO extends BaseVOEntity {
|
|||||||
@Excel(name = "入库单类型编码")
|
@Excel(name = "入库单类型编码")
|
||||||
private String inOrderTypeCode;
|
private String inOrderTypeCode;
|
||||||
|
|
||||||
@ApiModelProperty("入库单类型编码(与inOrderTypeCode同义)")
|
|
||||||
private String orderTypeCode;
|
|
||||||
|
|
||||||
@ApiModelProperty("入库单类型名称")
|
|
||||||
private String orderTypeName;
|
|
||||||
|
|
||||||
@ApiModelProperty("入库单类型名称")
|
@ApiModelProperty("入库单类型名称")
|
||||||
@Excel(name = "入库单类型名称")
|
@Excel(name = "入库单类型名称")
|
||||||
private String inOrderTypeName;
|
private String inOrderTypeName;
|
||||||
@@ -143,10 +137,4 @@ public class QueryOrderOverStockDO extends BaseVOEntity {
|
|||||||
@ApiModelProperty("越库单状态 0:无状态 1:处理中 2:越库完成")
|
@ApiModelProperty("越库单状态 0:无状态 1:处理中 2:越库完成")
|
||||||
@Excel(name = "越库单状态 0:无状态 1:处理中 2:越库完成")
|
@Excel(name = "越库单状态 0:无状态 1:处理中 2:越库完成")
|
||||||
private Integer overStockStatus;
|
private Integer overStockStatus;
|
||||||
|
|
||||||
@ApiModelProperty("实际入仓日期 开始(yyyy-MM-dd,为空按建档时间兜底)")
|
|
||||||
private String warehouseDateStart;
|
|
||||||
|
|
||||||
@ApiModelProperty("实际入仓日期 结束(yyyy-MM-dd,为空按建档时间兜底)")
|
|
||||||
private String warehouseDateEnd;
|
|
||||||
}
|
}
|
||||||
-17
@@ -85,21 +85,4 @@ public class ExecutionInMaterialDetailApplicationService {
|
|||||||
return inMaterialDetailDomainService.queryInOrderDetailList(queryOrderOverStockDO);
|
return inMaterialDetailDomainService.queryInOrderDetailList(queryOrderOverStockDO);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 入库明细导出(全字段,口径同 queryInOrderDetailList,不分页)
|
|
||||||
*/
|
|
||||||
public List<ExecutionInMaterialDetailWithOrderPO> exportInOrderDetailList(QueryOrderOverStockDO queryOrderOverStockDO) {
|
|
||||||
List<ExecutionInMaterialDetailWithOrderPO> list = queryInOrderDetailList(queryOrderOverStockDO);
|
|
||||||
// 货物种类=挂载分类的父级分类名称:material_classify_name为分类路径(如"食品,饮料"),取倒数第二段;
|
|
||||||
// 仅一级分类(无父级)时取自身名称
|
|
||||||
for (ExecutionInMaterialDetailWithOrderPO po : list) {
|
|
||||||
String names = po.getMaterialClassifyName();
|
|
||||||
if (names != null && names.contains(",")) {
|
|
||||||
String[] parts = names.split(",");
|
|
||||||
po.setMaterialClassifyName(parts[parts.length - 2].trim());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return list;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
-3
@@ -518,7 +518,4 @@ public class ExecutionOutMaterialDetail extends BaseVOEntity {
|
|||||||
private String inLineNumGw;
|
private String inLineNumGw;
|
||||||
private String opWhLocGw;
|
private String opWhLocGw;
|
||||||
private String warehouseGw;
|
private String warehouseGw;
|
||||||
|
|
||||||
@ApiModelProperty("反审标记: 0-无 1-已反审(业务单反审时软删del_flag=2并打标记)")
|
|
||||||
private Integer reverseFlag;
|
|
||||||
}
|
}
|
||||||
+1
-17
@@ -1,7 +1,6 @@
|
|||||||
package com.mhd.oms.domain.executionOutMaterialDetail.repository.po;
|
package com.mhd.oms.domain.executionOutMaterialDetail.repository.po;
|
||||||
|
|
||||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||||
import com.mhd.common.core.annotation.Excel;
|
|
||||||
import io.swagger.annotations.ApiModelProperty;
|
import io.swagger.annotations.ApiModelProperty;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
import org.springframework.format.annotation.DateTimeFormat;
|
import org.springframework.format.annotation.DateTimeFormat;
|
||||||
@@ -19,49 +18,34 @@ import java.util.Date;
|
|||||||
public class ExecutionOutMaterialDetailWithOrderPO extends ExecutionOutMaterialDetailPO {
|
public class ExecutionOutMaterialDetailWithOrderPO extends ExecutionOutMaterialDetailPO {
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
@ApiModelProperty("出库单流转状态(参考): 1-已创建 2-已审核 3-部分分配 4-已分配 5-拣货中 6-波次中 7-拣货完成 8-复核中 9-已出库 10-已取消 11-已关闭 12-已复核 13-已交接;WMS出库完成不回写此字段")
|
@ApiModelProperty("出库单状态: 1-已创建 2-已审核 3-部分分配 4-已分配 5-拣货中 6-波次中 7-拣货完成 8-复核中 9-已出库 10-已取消 11-已关闭")
|
||||||
private Integer outOrderStatus;
|
private Integer outOrderStatus;
|
||||||
|
|
||||||
@ApiModelProperty("出库单展示状态: 0-已创建 2-已审核 3-已驳回 4-已出库(WMS出库完成/推送创建时回写,前端状态列绑定此字段)")
|
|
||||||
@Excel(name = "单据状态", readConverterExp = "0=已创建,2=已审核,3=已驳回,4=已出库")
|
|
||||||
private Integer issueStatus;
|
|
||||||
|
|
||||||
@ApiModelProperty("出库单审核状态: 1-未审核 2-审核不通过 3-审核通过")
|
@ApiModelProperty("出库单审核状态: 1-未审核 2-审核不通过 3-审核通过")
|
||||||
@Excel(name = "出库单审核状态: 1-未审核 2-审核不通过 3-审核通过")
|
|
||||||
private Integer outOrderAuditStatus;
|
private Integer outOrderAuditStatus;
|
||||||
|
|
||||||
@ApiModelProperty("货主ID")
|
@ApiModelProperty("货主ID")
|
||||||
private Long orderShipperId;
|
private Long orderShipperId;
|
||||||
|
|
||||||
@ApiModelProperty("货主编码")
|
@ApiModelProperty("货主编码")
|
||||||
@Excel(name = "货主编码")
|
|
||||||
private String orderShipperCode;
|
private String orderShipperCode;
|
||||||
|
|
||||||
@ApiModelProperty("货主名称")
|
@ApiModelProperty("货主名称")
|
||||||
@Excel(name = "货主名称")
|
|
||||||
private String orderShipperName;
|
private String orderShipperName;
|
||||||
|
|
||||||
@ApiModelProperty("出仓日期")
|
@ApiModelProperty("出仓日期")
|
||||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
|
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
|
||||||
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||||
@Excel(name = "出仓日期", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss")
|
|
||||||
private Date orderOutboundDate;
|
private Date orderOutboundDate;
|
||||||
|
|
||||||
@ApiModelProperty("出库时间")
|
@ApiModelProperty("出库时间")
|
||||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
|
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
|
||||||
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||||
@Excel(name = "出库时间", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss")
|
|
||||||
private Date orderOutboundTime;
|
private Date orderOutboundTime;
|
||||||
|
|
||||||
@ApiModelProperty("保额")
|
@ApiModelProperty("保额")
|
||||||
@Excel(name = "保额")
|
|
||||||
private BigDecimal insureAmount;
|
private BigDecimal insureAmount;
|
||||||
|
|
||||||
@ApiModelProperty("货物类型:0-物料 1-半成品 2-成品")
|
@ApiModelProperty("货物类型:0-物料 1-半成品 2-成品")
|
||||||
@Excel(name = "货物类型", readConverterExp = "0=物料,1=半成品,2=成品")
|
|
||||||
private Integer goodsType;
|
private Integer goodsType;
|
||||||
|
|
||||||
@ApiModelProperty("货物种类(物料分类名称,多个逗号分隔)")
|
|
||||||
@Excel(name = "货物种类")
|
|
||||||
private String materialClassifyName;
|
|
||||||
}
|
}
|
||||||
|
|||||||
-12
@@ -45,12 +45,6 @@ public class ExecutionOutMaterialDetailQueryDTO extends BaseVOEntity {
|
|||||||
@ApiModelProperty("出库单类型编码")
|
@ApiModelProperty("出库单类型编码")
|
||||||
private String outOrderTypeCode;
|
private String outOrderTypeCode;
|
||||||
|
|
||||||
@ApiModelProperty("出库单类型编码(与outOrderTypeCode同义)")
|
|
||||||
private String orderTypeCode;
|
|
||||||
|
|
||||||
@ApiModelProperty("出库单类型名称(模糊查询)")
|
|
||||||
private String orderTypeName;
|
|
||||||
|
|
||||||
@ApiModelProperty("出库状态: 1-已创建 2-已审核 3-部分分配 4-已分配 5-拣货中 6-波次中 7-拣货完成 8-复核中 9-已出库 10-已取消 11-已关闭")
|
@ApiModelProperty("出库状态: 1-已创建 2-已审核 3-部分分配 4-已分配 5-拣货中 6-波次中 7-拣货完成 8-复核中 9-已出库 10-已取消 11-已关闭")
|
||||||
private Integer outStatus;
|
private Integer outStatus;
|
||||||
|
|
||||||
@@ -72,10 +66,4 @@ public class ExecutionOutMaterialDetailQueryDTO extends BaseVOEntity {
|
|||||||
|
|
||||||
@ApiModelProperty("物料名称")
|
@ApiModelProperty("物料名称")
|
||||||
private String materialName;
|
private String materialName;
|
||||||
|
|
||||||
@ApiModelProperty("实际出仓日期 开始(yyyy-MM-dd,为空按建档时间兜底)")
|
|
||||||
private String outboundDateStart;
|
|
||||||
|
|
||||||
@ApiModelProperty("实际出仓日期 结束(yyyy-MM-dd,为空按建档时间兜底)")
|
|
||||||
private String outboundDateEnd;
|
|
||||||
}
|
}
|
||||||
|
|||||||
-17
@@ -459,21 +459,4 @@ public class ExecutionStockInOrder extends BaseVOEntity {
|
|||||||
|
|
||||||
@ApiModelProperty("通知单备注")
|
@ApiModelProperty("通知单备注")
|
||||||
private String noticeRemark;
|
private String noticeRemark;
|
||||||
|
|
||||||
@ApiModelProperty("反审状态: 0-无 1-已反审")
|
|
||||||
private Integer reverseAuditStatus;
|
|
||||||
|
|
||||||
@ApiModelProperty("反审原因")
|
|
||||||
private String reverseAuditRemark;
|
|
||||||
|
|
||||||
@ApiModelProperty("反审人id")
|
|
||||||
private Long reverseAuditBy;
|
|
||||||
|
|
||||||
@ApiModelProperty("反审人姓名")
|
|
||||||
private String reverseAuditByName;
|
|
||||||
|
|
||||||
@ApiModelProperty("反审时间")
|
|
||||||
@JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss")
|
|
||||||
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
|
||||||
private Date reverseAuditTime;
|
|
||||||
}
|
}
|
||||||
-6
@@ -4,7 +4,6 @@ import com.baomidou.mybatisplus.extension.service.IService;
|
|||||||
import com.mhd.oms.domain.executionInMaterialDetail.repository.po.ExecutionInMaterialDetailPO;
|
import com.mhd.oms.domain.executionInMaterialDetail.repository.po.ExecutionInMaterialDetailPO;
|
||||||
import com.mhd.oms.domain.executionStockInOrder.entity.ExecutionStockInOrder;
|
import com.mhd.oms.domain.executionStockInOrder.entity.ExecutionStockInOrder;
|
||||||
import com.mhd.oms.domain.executionStockInOrder.repository.po.ExecutionStockInOrderPO;
|
import com.mhd.oms.domain.executionStockInOrder.repository.po.ExecutionStockInOrderPO;
|
||||||
import com.mhd.oms.domain.executionStockInOrder.repository.po.ExecutionStockInOrderTotalPO;
|
|
||||||
import com.mhd.oms.domain.executionStockInOrder.repository.todo.ExecutionStockInOrderDO;
|
import com.mhd.oms.domain.executionStockInOrder.repository.todo.ExecutionStockInOrderDO;
|
||||||
import com.mhd.oms.domain.executionStockInOrder.repository.vo.DeliveryDataDTO;
|
import com.mhd.oms.domain.executionStockInOrder.repository.vo.DeliveryDataDTO;
|
||||||
import com.mhd.oms.domain.executionStockInOrder.repository.vo.StockInDataDTO;
|
import com.mhd.oms.domain.executionStockInOrder.repository.vo.StockInDataDTO;
|
||||||
@@ -26,11 +25,6 @@ public interface IExecutionStockInOrderService extends IService<ExecutionStockIn
|
|||||||
*/
|
*/
|
||||||
public List<ExecutionStockInOrderPO> queryList(ExecutionStockInOrderDO stockInOrderDO);
|
public List<ExecutionStockInOrderPO> queryList(ExecutionStockInOrderDO stockInOrderDO);
|
||||||
|
|
||||||
/**
|
|
||||||
* 列表合计:按查询条件全量(不分页)汇总计划数量与入库数量
|
|
||||||
*/
|
|
||||||
public ExecutionStockInOrderTotalPO queryListTotal(ExecutionStockInOrderDO stockInOrderDO);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 新增入库单
|
* 新增入库单
|
||||||
*/
|
*/
|
||||||
|
|||||||
-6
@@ -7,7 +7,6 @@ import com.mhd.oms.domain.executionStockInOrder.repository.po.MaterialBaseInfoPO
|
|||||||
import com.mhd.oms.domain.executionStockInOrder.repository.po.MaterialGoodsRulePO;
|
import com.mhd.oms.domain.executionStockInOrder.repository.po.MaterialGoodsRulePO;
|
||||||
import com.mhd.oms.domain.executionStockInOrder.repository.po.MaterialWarehouseControlPO;
|
import com.mhd.oms.domain.executionStockInOrder.repository.po.MaterialWarehouseControlPO;
|
||||||
import com.mhd.oms.domain.executionStockInOrder.repository.po.ExecutionStockInOrderPO;
|
import com.mhd.oms.domain.executionStockInOrder.repository.po.ExecutionStockInOrderPO;
|
||||||
import com.mhd.oms.domain.executionStockInOrder.repository.po.ExecutionStockInOrderTotalPO;
|
|
||||||
import com.mhd.oms.domain.executionStockInOrder.repository.todo.ExecutionStockInOrderDO;
|
import com.mhd.oms.domain.executionStockInOrder.repository.todo.ExecutionStockInOrderDO;
|
||||||
//import com.mhd.oms.domain.reservationInMaterialDetail.repository.po.ExecutionInMaterialDetailPO;
|
//import com.mhd.oms.domain.reservationInMaterialDetail.repository.po.ExecutionInMaterialDetailPO;
|
||||||
import org.apache.ibatis.annotations.Param;
|
import org.apache.ibatis.annotations.Param;
|
||||||
@@ -28,11 +27,6 @@ public interface ExecutionStockInOrderMapper extends BaseMapper<ExecutionStockIn
|
|||||||
*/
|
*/
|
||||||
public List<ExecutionStockInOrderPO> queryList(ExecutionStockInOrderDO stockInOrderDO);
|
public List<ExecutionStockInOrderPO> queryList(ExecutionStockInOrderDO stockInOrderDO);
|
||||||
|
|
||||||
/**
|
|
||||||
* 列表合计:按查询条件全量(不分页)汇总计划数量与入库数量
|
|
||||||
*/
|
|
||||||
public ExecutionStockInOrderTotalPO queryListTotal(ExecutionStockInOrderDO stockInOrderDO);
|
|
||||||
|
|
||||||
public MaterialBaseInfoPO getinfo(@Param("id") Long id);
|
public MaterialBaseInfoPO getinfo(@Param("id") Long id);
|
||||||
|
|
||||||
public MaterialBaseInfoPO getByName(@Param("name") String name);
|
public MaterialBaseInfoPO getByName(@Param("name") String name);
|
||||||
|
|||||||
-10
@@ -26,7 +26,6 @@ import com.mhd.oms.domain.executionStockInOrder.repository.listener.StockInExcel
|
|||||||
import com.mhd.oms.domain.executionStockInOrder.repository.mapper.ExecutionStockInOrderMapper;
|
import com.mhd.oms.domain.executionStockInOrder.repository.mapper.ExecutionStockInOrderMapper;
|
||||||
import com.mhd.oms.domain.executionStockInOrder.repository.po.MaterialBaseInfoPO;
|
import com.mhd.oms.domain.executionStockInOrder.repository.po.MaterialBaseInfoPO;
|
||||||
import com.mhd.oms.domain.executionStockInOrder.repository.po.ExecutionStockInOrderPO;
|
import com.mhd.oms.domain.executionStockInOrder.repository.po.ExecutionStockInOrderPO;
|
||||||
import com.mhd.oms.domain.executionStockInOrder.repository.po.ExecutionStockInOrderTotalPO;
|
|
||||||
import com.mhd.oms.domain.executionStockInOrder.repository.todo.ExecutionStockInOrderDO;
|
import com.mhd.oms.domain.executionStockInOrder.repository.todo.ExecutionStockInOrderDO;
|
||||||
import com.mhd.oms.domain.executionStockInOrder.repository.vo.*;
|
import com.mhd.oms.domain.executionStockInOrder.repository.vo.*;
|
||||||
import com.mhd.oms.domain.executionStockOutOrder.entity.ExecutionStockOutOrder;
|
import com.mhd.oms.domain.executionStockOutOrder.entity.ExecutionStockOutOrder;
|
||||||
@@ -94,15 +93,6 @@ public class ExecutionStockInOrderImpl extends ServiceImpl<ExecutionStockInOrder
|
|||||||
return stockInOrderMapper.queryList(stockInOrderDO);
|
return stockInOrderMapper.queryList(stockInOrderDO);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 列表合计:按查询条件全量(不分页)汇总计划数量与入库数量
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public ExecutionStockInOrderTotalPO queryListTotal(ExecutionStockInOrderDO stockInOrderDO)
|
|
||||||
{
|
|
||||||
return stockInOrderMapper.queryListTotal(stockInOrderDO);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 新增入库单
|
* 新增入库单
|
||||||
*/
|
*/
|
||||||
|
|||||||
-17
@@ -482,21 +482,4 @@ public class ExecutionStockInOrderPO extends BaseVOEntity {
|
|||||||
private String khdm;
|
private String khdm;
|
||||||
@ApiModelProperty("通知单备注")
|
@ApiModelProperty("通知单备注")
|
||||||
private String noticeRemark;
|
private String noticeRemark;
|
||||||
|
|
||||||
@ApiModelProperty("反审状态: 0-无 1-已反审")
|
|
||||||
private Integer reverseAuditStatus;
|
|
||||||
|
|
||||||
@ApiModelProperty("反审原因")
|
|
||||||
private String reverseAuditRemark;
|
|
||||||
|
|
||||||
@ApiModelProperty("反审人id")
|
|
||||||
private Long reverseAuditBy;
|
|
||||||
|
|
||||||
@ApiModelProperty("反审人姓名")
|
|
||||||
private String reverseAuditByName;
|
|
||||||
|
|
||||||
@ApiModelProperty("反审时间")
|
|
||||||
@JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss")
|
|
||||||
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
|
||||||
private Date reverseAuditTime;
|
|
||||||
}
|
}
|
||||||
-30
@@ -1,30 +0,0 @@
|
|||||||
package com.mhd.oms.domain.executionStockInOrder.repository.po;
|
|
||||||
|
|
||||||
import io.swagger.annotations.ApiModel;
|
|
||||||
import io.swagger.annotations.ApiModelProperty;
|
|
||||||
import lombok.Data;
|
|
||||||
|
|
||||||
import java.io.Serializable;
|
|
||||||
import java.math.BigDecimal;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 入库执行单列表合计PO
|
|
||||||
*
|
|
||||||
* <p>当前筛选条件下不分页的全量合计,随分页列表一起返回
|
|
||||||
* (totalPlanQuantity/totalInQuantity),计划数量与入库数量分开计算</p>
|
|
||||||
*
|
|
||||||
* @author rcx
|
|
||||||
* @date 2026-09-14
|
|
||||||
*/
|
|
||||||
@Data
|
|
||||||
@ApiModel(value = "入库执行单列表合计对象", description = "入库执行单列表合计响应对象")
|
|
||||||
public class ExecutionStockInOrderTotalPO implements Serializable {
|
|
||||||
|
|
||||||
private static final long serialVersionUID = 1L;
|
|
||||||
|
|
||||||
@ApiModelProperty("计划数量总数")
|
|
||||||
private BigDecimal totalPlanQuantity;
|
|
||||||
|
|
||||||
@ApiModelProperty("入库数量总数")
|
|
||||||
private BigDecimal totalInQuantity;
|
|
||||||
}
|
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user