Compare commits
46
Commits
e60f22979c
..
dev
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
43b95f3f07 | ||
|
|
44f2579e3f | ||
|
|
ca5b6e4672 | ||
|
|
6b991363c6 | ||
|
|
84c7fa7647 | ||
|
|
c0d2faaaf1 | ||
|
|
8324d8dc31 | ||
|
|
6ce35b58e4 | ||
|
|
700556ea63 | ||
|
|
100a8d87ac | ||
|
|
b0c9a41f07 | ||
|
|
82d5eda139 | ||
|
|
07393e43ff | ||
|
|
08858f24d6 | ||
|
|
a994241400 | ||
|
|
a9be03961a | ||
|
|
7f6006ca48 | ||
|
|
defc8c3709 | ||
|
|
3c21c2c848 | ||
|
|
71936b50a7 | ||
|
|
9cfffe1224 | ||
|
|
d7574d188a | ||
|
|
1c1b06c1bf | ||
|
|
117019c55c | ||
|
|
171909b68d | ||
|
|
31c27c16c6 | ||
|
|
8dfe9545aa | ||
|
|
028afb57d7 | ||
|
|
37dd374bda | ||
|
|
d69af9ef20 | ||
|
|
9704dbfb07 | ||
|
|
3276792bb5 | ||
|
|
b57db4b8cc | ||
|
|
8a31ed9974 | ||
|
|
9777156959 | ||
|
|
ba5d78b36c | ||
|
|
dea39a1a4b | ||
|
|
0493030620 | ||
|
|
3907b126d9 | ||
|
|
7b76d5c203 | ||
|
|
f02a2d52f2 | ||
|
|
a3c0f15e39 | ||
|
|
d2a6a5a4f6 | ||
|
|
752216ad45 | ||
|
|
6a8661da63 | ||
|
|
2b6777abe4 |
@@ -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 {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -539,13 +540,6 @@ public interface WlhyServiceFeign {
|
|||||||
@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,url = "http://10.33.0.109:8016",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);
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -133,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,7 +13,8 @@ import org.springframework.web.bind.annotation.*;
|
|||||||
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
@FeignClient(contextId = "XxlJobService", value = ServiceNameConstants.XXL_JOB_SERVICE,url = "http://127.0.0.1:8020",fallbackFactory = RemoteXxlJobFeignFallbackFactory.class, configuration = FeignAutoConfiguration.class)
|
// 目标地址由 nacos 配置项 feign.url.xxl-job-service 指定,未配置时按服务名走服务发现
|
||||||
|
@FeignClient(contextId = "XxlJobService", value = ServiceNameConstants.XXL_JOB_SERVICE,url = "http://10.102.192.33: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 {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
-6
@@ -551,12 +551,6 @@ public class RemoteWlhyFallbackFactory implements FallbackFactory<WlhyServiceFei
|
|||||||
return AjaxResult.error(cause.getMessage());
|
return AjaxResult.error(cause.getMessage());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public AjaxResult deleteChainByExecuteOrderNumber(String executeOrderNumber) {
|
|
||||||
//返回错误而非静默成功, 让OMS反审事务能感知失败并整体回滚
|
|
||||||
return AjaxResult.error("TMS反审联动软删链路失败(服务降级):" + cause.getMessage());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public AjaxResult<?> queryList(Integer pageNo, Integer pageSize, String pushStatus, String organizationId) {
|
public AjaxResult<?> queryList(Integer pageNo, Integer pageSize, String pushStatus, String organizationId) {
|
||||||
return AjaxResult.error(cause.getMessage());
|
return AjaxResult.error(cause.getMessage());
|
||||||
|
|||||||
+4
-19
@@ -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) {
|
||||||
|
|
||||||
@@ -119,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();
|
||||||
|
|||||||
+11
-3
@@ -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)) {
|
||||||
|
// recordLogininfor(userPhone, Constants.LOGIN_FAIL, "验证码错误", 1);
|
||||||
throw new ServiceException("验证码错误");
|
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
|
||||||
# 线上测试环境配置 容器名+端口号
|
# 线上测试环境配置 容器名+端口号
|
||||||
|
|||||||
+27
@@ -0,0 +1,27 @@
|
|||||||
|
package com.mhd.bi.domain.biComprehensive.repository.mapper;
|
||||||
|
|
||||||
|
import com.mhd.bi.domain.biComprehensive.repository.po.RealFuelStatPO;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 综合态势-真实业务数据 Mapper(跨库查询,与月台监测 BiPlatformRealDataMapper 同方案)
|
||||||
|
*
|
||||||
|
* <p>数据来源:</p>
|
||||||
|
* <ul>
|
||||||
|
* <li>运输订单量:NGWL_TEST_OMS.BUSINESS_DOCUMENT_ORDER(OMS 运输业务单)</li>
|
||||||
|
* <li>百公里油耗:NGWL_TEST_WLHY.TMS_EXPENSE_REPORT(TMS 运输作业单,字段 FUEL_CONSUMPTION / HEAVYLOAD_MILEAGE)</li>
|
||||||
|
* </ul>
|
||||||
|
*/
|
||||||
|
public interface BiComprehensiveRealDataMapper {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 运输订单量:统计本年度(CREATE_TIME 在当前年)全部组织的运输业务单数量。
|
||||||
|
* 统计范围:全部组织,不按机构过滤。
|
||||||
|
*/
|
||||||
|
Long countCurrentYearTransportOrders();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 百公里油耗统计:统计本年度油耗量与重载里程均非空的记录,
|
||||||
|
* 返回 总油耗量 / 总重载里程 / 参与条数,由调用方计算百公里油耗。
|
||||||
|
*/
|
||||||
|
RealFuelStatPO queryCurrentYearFuelStat();
|
||||||
|
}
|
||||||
+26
@@ -0,0 +1,26 @@
|
|||||||
|
package com.mhd.bi.domain.biComprehensive.repository.po;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 百公里油耗统计(真实数据,来自 TMS 运输作业单 TMS_EXPENSE_REPORT)
|
||||||
|
*
|
||||||
|
* <p>统计口径:本年度、全部组织、油耗量(FUEL_CONSUMPTION)与重载里程(HEAVYLOAD_MILEAGE)均非空的记录。</p>
|
||||||
|
* <p>百公里油耗 = 总油耗量 ÷ 总重载里程 × 100</p>
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class RealFuelStatPO implements Serializable {
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
/** 总油耗量(仅统计油耗量非空的记录) */
|
||||||
|
private BigDecimal totalOil;
|
||||||
|
|
||||||
|
/** 总重载里程(仅统计重载里程非空的记录,且油量非空) */
|
||||||
|
private BigDecimal totalHeavyMileage;
|
||||||
|
|
||||||
|
/** 参与统计的记录数 */
|
||||||
|
private Long totalCount;
|
||||||
|
}
|
||||||
+63
@@ -0,0 +1,63 @@
|
|||||||
|
package com.mhd.bi.domain.biComprehensive.service;
|
||||||
|
|
||||||
|
import com.mhd.bi.domain.biComprehensive.repository.mapper.BiComprehensiveRealDataMapper;
|
||||||
|
import com.mhd.bi.domain.biComprehensive.repository.po.RealFuelStatPO;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import javax.annotation.Resource;
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
import java.math.RoundingMode;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 综合态势-真实业务数据业务层(封装 OMS / TMS 跨库查询)
|
||||||
|
*
|
||||||
|
* <p>实现方案与「月台监测指标查询」一致:每次调用实时查库,查不到/查库异常返回 0,不影响其它字段。</p>
|
||||||
|
*/
|
||||||
|
@Slf4j
|
||||||
|
@Service
|
||||||
|
public class BiComprehensiveRealDataService {
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private BiComprehensiveRealDataMapper biComprehensiveRealDataMapper;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 运输订单量:本年度 OMS 运输业务单数量,范围全部组织。
|
||||||
|
* 查询失败或无数据返回 0。
|
||||||
|
*/
|
||||||
|
public long countCurrentYearTransportOrders() {
|
||||||
|
try {
|
||||||
|
Long n = biComprehensiveRealDataMapper.countCurrentYearTransportOrders();
|
||||||
|
return n == null ? 0L : n;
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("【OMS】统计本年度运输订单量失败: {}", e.getMessage(), e);
|
||||||
|
return 0L;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 百公里油耗 = 总油耗量 ÷ 总重载里程 × 100,保留一位小数。
|
||||||
|
*
|
||||||
|
* <p>统计范围:TMS 运输作业单 TMS_EXPENSE_REPORT,本年度、全部组织、油耗量与重载里程均非空。</p>
|
||||||
|
* <p>总重载里程为 0 或查询失败时返回 0,避免除零。</p>
|
||||||
|
*/
|
||||||
|
public double calcCurrentYearFuelConsumptionPerHundredKm() {
|
||||||
|
try {
|
||||||
|
RealFuelStatPO po = biComprehensiveRealDataMapper.queryCurrentYearFuelStat();
|
||||||
|
if (po == null) {
|
||||||
|
return 0d;
|
||||||
|
}
|
||||||
|
BigDecimal totalOil = po.getTotalOil();
|
||||||
|
BigDecimal totalMileage = po.getTotalHeavyMileage();
|
||||||
|
if (totalOil == null || totalMileage == null || totalMileage.compareTo(BigDecimal.ZERO) <= 0) {
|
||||||
|
return 0d;
|
||||||
|
}
|
||||||
|
return totalOil.multiply(BigDecimal.valueOf(100))
|
||||||
|
.divide(totalMileage, 1, RoundingMode.HALF_UP)
|
||||||
|
.doubleValue();
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("【TMS】计算本年度百公里油耗失败: {}", e.getMessage(), e);
|
||||||
|
return 0d;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+79
-1
@@ -1,21 +1,99 @@
|
|||||||
package com.mhd.bi.domain.biComprehensive.service;
|
package com.mhd.bi.domain.biComprehensive.service;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
import com.mhd.bi.domain.biComprehensive.repository.mapper.BiComprehensiveReportMapper;
|
import com.mhd.bi.domain.biComprehensive.repository.mapper.BiComprehensiveReportMapper;
|
||||||
|
import com.mhd.bi.domain.biSnapshotSync.repository.mapper.BiSnapshotWriteMapper;
|
||||||
import com.mhd.bi.interfaces.facadeApi.biReport.vo.ComprehensiveSituationVO;
|
import com.mhd.bi.interfaces.facadeApi.biReport.vo.ComprehensiveSituationVO;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
import javax.annotation.Resource;
|
import javax.annotation.Resource;
|
||||||
|
import java.util.LinkedHashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 综合态势:数据访问仅经 Mapper(含 XML 内 SQL 与 Mapper 默认方法组装)。
|
* 综合态势:数据访问仅经 Mapper(含 XML 内 SQL 与 Mapper 默认方法组装)。
|
||||||
|
*
|
||||||
|
* <p>其中「运输订单量」「百公里油耗」为实时查询业务库的真实数据,
|
||||||
|
* 每次调用实时组装并覆盖更新快照表最新一条,实现方案与「月台监测指标查询」一致;</p>
|
||||||
|
* <p>其余字段仍取自 BI_COMPREHENSIVE_SNAPSHOT 最新快照。</p>
|
||||||
|
*
|
||||||
|
* <p>仅当这两项实时数据发生变化时才覆盖更新快照,避免无意义的写库。</p>
|
||||||
*/
|
*/
|
||||||
|
@Slf4j
|
||||||
@Service
|
@Service
|
||||||
public class BiComprehensiveReportService {
|
public class BiComprehensiveReportService {
|
||||||
|
|
||||||
|
private static final String REMARK_REALTIME = "realtime comprehensive";
|
||||||
|
|
||||||
@Resource
|
@Resource
|
||||||
private BiComprehensiveReportMapper biComprehensiveReportMapper;
|
private BiComprehensiveReportMapper biComprehensiveReportMapper;
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private BiSnapshotWriteMapper biSnapshotWriteMapper;
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private BiComprehensiveRealDataService biComprehensiveRealDataService;
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private ObjectMapper objectMapper;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 实时组装综合态势:快照其余字段 + 实时业务数据(运输订单量、百公里油耗);
|
||||||
|
* 仅当实时业务数据发生变化时,才覆盖更新 BI_COMPREHENSIVE_SNAPSHOT 快照表最新一条后返回。
|
||||||
|
* 表中尚无记录时插入一条兜底。
|
||||||
|
*/
|
||||||
public ComprehensiveSituationVO loadLatestComprehensive() {
|
public ComprehensiveSituationVO loadLatestComprehensive() {
|
||||||
return biComprehensiveReportMapper.loadLatestComprehensive();
|
ComprehensiveSituationVO vo = biComprehensiveReportMapper.loadLatestComprehensive();
|
||||||
|
if (vo == null) {
|
||||||
|
vo = new ComprehensiveSituationVO();
|
||||||
|
}
|
||||||
|
|
||||||
|
// 实时业务数据:运输订单量(OMS 运输业务单,本年度、全部组织)
|
||||||
|
vo.setOrderCount(biComprehensiveRealDataService.countCurrentYearTransportOrders());
|
||||||
|
// 实时业务数据:百公里油耗(TMS 运输作业单,本年度、全部组织,油耗量与重载里程均非空)
|
||||||
|
vo.setFuelConsumptionPerHundredKm(
|
||||||
|
biComprehensiveRealDataService.calcCurrentYearFuelConsumptionPerHundredKm());
|
||||||
|
|
||||||
|
try {
|
||||||
|
String fullJson = objectMapper.writeValueAsString(vo);
|
||||||
|
String fingerprint = realDataFingerprint(vo);
|
||||||
|
|
||||||
|
String latestJson = biComprehensiveReportMapper.selectLatestPayloadJson();
|
||||||
|
if (StringUtils.isNotBlank(latestJson)) {
|
||||||
|
ComprehensiveSituationVO latestVo =
|
||||||
|
objectMapper.readValue(latestJson.trim(), ComprehensiveSituationVO.class);
|
||||||
|
if (Objects.equals(fingerprint, realDataFingerprint(latestVo))) {
|
||||||
|
log.info("BI 综合态势实时业务数据未变化,跳过落库");
|
||||||
|
return vo;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int rows = biSnapshotWriteMapper.updateLatestComprehensiveSnapshot(fullJson, REMARK_REALTIME);
|
||||||
|
if (rows < 1) {
|
||||||
|
// 表中无最新记录可更新,插入一条兜底
|
||||||
|
biSnapshotWriteMapper.insertComprehensiveSnapshot(fullJson, REMARK_REALTIME);
|
||||||
|
}
|
||||||
|
log.info("BI 综合态势实时数据已落库(覆盖最新, 数据变化), affectedRows={}", rows);
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("BI 综合态势实时数据落库失败", e);
|
||||||
|
}
|
||||||
|
return vo;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 实时业务数据指纹:仅含实时查库得到的字段(运输订单量、百公里油耗),
|
||||||
|
* 用于判断是否需要覆盖更新快照;其余字段取自快照,不纳入指纹。
|
||||||
|
*/
|
||||||
|
private String realDataFingerprint(ComprehensiveSituationVO vo) throws Exception {
|
||||||
|
Map<String, Object> fp = new LinkedHashMap<>();
|
||||||
|
if (vo == null) {
|
||||||
|
return objectMapper.writeValueAsString(fp);
|
||||||
|
}
|
||||||
|
fp.put("orderCount", vo.getOrderCount());
|
||||||
|
fp.put("fuelConsumptionPerHundredKm", vo.getFuelConsumptionPerHundredKm());
|
||||||
|
return objectMapper.writeValueAsString(fp);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+43
-1
@@ -7,6 +7,18 @@ 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.biPlatformRealData.repository.po.RealMonthlyAvgDurationPO;
|
||||||
|
import com.mhd.bi.domain.biPlatformRealData.repository.po.RealTodayAvgDurationPO;
|
||||||
|
import com.mhd.bi.domain.biPlatformRealData.repository.po.RealOvertimeStatPO;
|
||||||
|
import com.mhd.bi.domain.biPlatformRealData.repository.po.RealOvertimeRecordPO;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
import org.apache.ibatis.annotations.Param;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
@@ -26,18 +38,48 @@ public interface BiPlatformRealDataMapper {
|
|||||||
/** 今日作业任务数 */
|
/** 今日作业任务数 */
|
||||||
Long countTodayTasks();
|
Long countTodayTasks();
|
||||||
|
|
||||||
/** 车辆状态统计(今日) */
|
/** 车辆状态统计(今日,含叫号状态合计 callStatusTotal = 已签到+已叫号+已过号) */
|
||||||
RealVehicleStatusPO queryVehicleStatusToday();
|
RealVehicleStatusPO queryVehicleStatusToday();
|
||||||
|
|
||||||
/** 本月任务量 */
|
/** 本月任务量 */
|
||||||
Long countMonthTasks();
|
Long countMonthTasks();
|
||||||
|
|
||||||
|
/** 本月任务平均时长 / 完成率统计 */
|
||||||
|
RealMonthlyTaskDurationPO queryMonthTaskStats();
|
||||||
|
|
||||||
/** 任务负荷(今日 24 小时) */
|
/** 任务负荷(今日 24 小时) */
|
||||||
List<RealTaskLoadPO> queryTaskLoadToday();
|
List<RealTaskLoadPO> queryTaskLoadToday();
|
||||||
|
|
||||||
|
/** 近半年平均作业时长(按月分组:月台作业时长 / 园区作业时长 合计 + 任务数) */
|
||||||
|
List<RealMonthlyAvgDurationPO> queryMonthlyAvgDuration();
|
||||||
|
|
||||||
|
/** 今日平均作业时长(月台作业平均时长 / 园区平均时长,仅统计两端时间都非空的记录) */
|
||||||
|
RealTodayAvgDurationPO queryTodayAvgDuration();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 今日月台作业超时统计(超时记录数 / 有效记录总数)。
|
||||||
|
* 参考用时取自 YMS QMS_STATIC_FIELD.FIELD_CODE = 'platform_work_ref_minutes'
|
||||||
|
*/
|
||||||
|
RealOvertimeStatPO queryTodayOvertimeStat(@Param("refCode") String refCode);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 今日园区作业超时统计(超时记录数 / 有效记录总数)。
|
||||||
|
* 参考用时取自 YMS QMS_STATIC_FIELD.FIELD_CODE = 'yard_work_ref_minutes'
|
||||||
|
*/
|
||||||
|
RealOvertimeStatPO queryTodayYardOvertimeStat(@Param("refCode") String refCode);
|
||||||
|
|
||||||
|
/** 今日月台作业超时记录列表(月台名称 / 车牌号 / 超时时长) */
|
||||||
|
List<RealOvertimeRecordPO> queryTodayOvertimeList(@Param("refCode") String refCode);
|
||||||
|
|
||||||
/** 今日预约-业务类型统计(按 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();
|
||||||
|
|
||||||
|
|||||||
+32
@@ -0,0 +1,32 @@
|
|||||||
|
package com.mhd.bi.domain.biPlatformRealData.repository.po;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 按月平均作业时长(真实数据,来自 TEST_NGWL_YMS.QMS_MAIN_BUSINESS)
|
||||||
|
*
|
||||||
|
* <p>用于「平均作业时长」近半年趋势图,双系列:月台作业 / 园区作业。</p>
|
||||||
|
* <ul>
|
||||||
|
* <li>月台作业时长 = 离开月台时间(OUT_WINDOWS_TIME) - 进入月台时间(IN_WINDOWS_TIME)</li>
|
||||||
|
* <li>园区作业时长 = 实际出场时间(EXIT_TIME) - 实际进入时间(ENTRY_TIME)</li>
|
||||||
|
* </ul>
|
||||||
|
* <p>各月平均 = 该月有效记录的时长合计 ÷ 该月任务数。</p>
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class RealMonthlyAvgDurationPO implements Serializable {
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
/** 月份,格式 yyyy-MM */
|
||||||
|
private String monthOfYear;
|
||||||
|
|
||||||
|
/** 该月任务数(预约记录数,作为平均时长的分母) */
|
||||||
|
private Long taskCount;
|
||||||
|
|
||||||
|
/** 该月月台作业时长合计(小时);未进入月台计 0,已进入未离开按 SYSDATE - IN_WINDOWS_TIME */
|
||||||
|
private Double platformWorkHours;
|
||||||
|
|
||||||
|
/** 该月园区作业时长合计(小时);未进场计 0,已进场未出场按 SYSDATE - ENTRY_TIME */
|
||||||
|
private Double yardWorkHours;
|
||||||
|
}
|
||||||
+33
@@ -0,0 +1,33 @@
|
|||||||
|
package com.mhd.bi.domain.biPlatformRealData.repository.po;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 本月任务平均时长 / 完成率统计(真实数据,来自 TEST_NGWL_YMS.QMS_MAIN_BUSINESS)
|
||||||
|
* totalWorkHours:本月任务作业时长合计(小时),未进入月台计 0、已进入未离开按 SYSDATE - IN_WINDOWS_TIME
|
||||||
|
* completedCount:已出场(EXIT_TIME IS NOT NULL)且预约日期在本月的数量
|
||||||
|
* totalCount:本月(TARGET_DATE)预约总数量(作为平均时长的分母)
|
||||||
|
*
|
||||||
|
* <p>任务平均作业时长 = totalWorkHours ÷ totalCount,由 Service 层计算。</p>
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class RealMonthlyTaskDurationPO implements Serializable {
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
/** 本月任务作业时长合计(小时) */
|
||||||
|
private Double totalWorkHours;
|
||||||
|
|
||||||
|
/** 平均作业时长(小时),由 Service 层按 totalWorkHours ÷ totalCount 计算 */
|
||||||
|
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;
|
||||||
|
}
|
||||||
+30
@@ -0,0 +1,30 @@
|
|||||||
|
package com.mhd.bi.domain.biPlatformRealData.repository.po;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 今日月台作业超时记录(真实数据)
|
||||||
|
*
|
||||||
|
* <p>用于「超时记录列表」:月台名称 / 车牌号码 / 超时时长(分钟)。</p>
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class RealOvertimeRecordPO implements Serializable {
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
/** 月台名称 */
|
||||||
|
private String windowName;
|
||||||
|
|
||||||
|
/** 车牌号码 */
|
||||||
|
private String carNo;
|
||||||
|
|
||||||
|
/** 超时时长(分钟)= 月台作业时长 - 参考用时 */
|
||||||
|
private Long overtimeMinutes;
|
||||||
|
|
||||||
|
/** 月台作业参考用时(分钟) */
|
||||||
|
private Long refMinutes;
|
||||||
|
|
||||||
|
/** 月台作业时长(分钟) */
|
||||||
|
private Long platformMinutes;
|
||||||
|
}
|
||||||
+27
@@ -0,0 +1,27 @@
|
|||||||
|
package com.mhd.bi.domain.biPlatformRealData.repository.po;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 今日作业超时统计(月台作业 / 园区作业 通用)
|
||||||
|
*
|
||||||
|
* <p>分母只计入「能取到参考用时 且 作业时长两端时间都非空」的记录。</p>
|
||||||
|
* <ul>
|
||||||
|
* <li>月台作业:参考用时 code = platform_work_ref_minutes;
|
||||||
|
* 时长 = OUT_WINDOWS_TIME - IN_WINDOWS_TIME</li>
|
||||||
|
* <li>园区作业:参考用时 code = yard_work_ref_minutes;
|
||||||
|
* 时长 = EXIT_TIME - ENTRY_TIME</li>
|
||||||
|
* </ul>
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class RealOvertimeStatPO implements Serializable {
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
/** 超时记录数:作业时长 > 参考用时 */
|
||||||
|
private Long overtimeCount;
|
||||||
|
|
||||||
|
/** 有效记录总数(分母) */
|
||||||
|
private Long totalCount;
|
||||||
|
}
|
||||||
+4
@@ -23,4 +23,8 @@ public class RealPlatformFloorStatPO implements Serializable {
|
|||||||
|
|
||||||
/** 当前作业车辆数(FLOW_STATUS IN 5,6,7,8,9,10) */
|
/** 当前作业车辆数(FLOW_STATUS IN 5,6,7,8,9,10) */
|
||||||
private Long operatingVehicles;
|
private Long operatingVehicles;
|
||||||
|
|
||||||
|
/** 该楼层月台作业平均时长(分钟)= SUM(该楼层有效月台作业时长) ÷ 该楼层有效记录数 */
|
||||||
|
private Double avgPlatformMinutes;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+5
-3
@@ -4,15 +4,17 @@ import lombok.Data;
|
|||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 任务负荷统计(按小时,来自 TEST_NGWL_YMS.QMS_MAIN_BUSINESS)
|
* 任务负荷统计(按 2 小时分组,来自 TEST_NGWL_YMS.QMS_MAIN_BUSINESS)
|
||||||
|
*
|
||||||
|
* <p>「小时趋势」需求:每 2 小时分组统计一次,按车辆进入月台时间 IN_WINDOWS_TIME 分桶。</p>
|
||||||
*/
|
*/
|
||||||
@Data
|
@Data
|
||||||
public class RealTaskLoadPO implements Serializable {
|
public class RealTaskLoadPO implements Serializable {
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
/** 0-23 小时 */
|
/** 2 小时分组的起始小时,取值 0,2,4,...,22 */
|
||||||
private Integer hourOfDay;
|
private Integer hourOfDay;
|
||||||
|
|
||||||
/** 该小时段任务数 */
|
/** 该 2 小时时段任务数 */
|
||||||
private Long taskCount;
|
private Long taskCount;
|
||||||
}
|
}
|
||||||
+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;
|
||||||
|
}
|
||||||
+34
@@ -0,0 +1,34 @@
|
|||||||
|
package com.mhd.bi.domain.biPlatformRealData.repository.po;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 今日平均作业时长(真实数据,来自 TEST_NGWL_YMS.QMS_MAIN_BUSINESS)
|
||||||
|
*
|
||||||
|
* <p>用于「效率统计(本日)」中的:</p>
|
||||||
|
* <ul>
|
||||||
|
* <li>月台作业平均时长 avgPlatformDurationHours</li>
|
||||||
|
* <li>园区平均时长 avgYardDurationHours</li>
|
||||||
|
* </ul>
|
||||||
|
*
|
||||||
|
* <p>统计范围:今日预约记录(TARGET_DATE = 今天),且只统计时长两端的字段都非空的记录:</p>
|
||||||
|
* <ul>
|
||||||
|
* <li>月台作业时长 = 离开月台时间(OUT_WINDOWS_TIME) - 进入月台时间(IN_WINDOWS_TIME)
|
||||||
|
* → 只统计 IN_WINDOWS_TIME 与 OUT_WINDOWS_TIME 都非空的记录</li>
|
||||||
|
* <li>园区作业时长 = 实际出场时间(EXIT_TIME) - 实际进入时间(ENTRY_TIME)
|
||||||
|
* → 只统计 ENTRY_TIME 与 EXIT_TIME 都非空的记录</li>
|
||||||
|
* </ul>
|
||||||
|
* <p>平均时长 = 有效记录时长合计 ÷ 有效记录数,由 Service 层或 SQL 直接完成。</p>
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class RealTodayAvgDurationPO implements Serializable {
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
/** 月台作业平均时长(小时),仅统计同时有进入与离开月台时间的记录 */
|
||||||
|
private Double avgPlatformDurationHours;
|
||||||
|
|
||||||
|
/** 园区平均时长(小时),仅统计同时有实际进入与实际出场时间的记录 */
|
||||||
|
private Double avgYardDurationHours;
|
||||||
|
}
|
||||||
+9
@@ -16,6 +16,15 @@ public class RealVehicleStatusPO implements Serializable {
|
|||||||
/** 当前未签到 */
|
/** 当前未签到 */
|
||||||
private Long notCheckedIn;
|
private Long notCheckedIn;
|
||||||
|
|
||||||
|
/** 当前等待作业(FLOW_STATUS IN '1','2','3' 已预约/已签到/已叫号) */
|
||||||
|
private Long waiting;
|
||||||
|
|
||||||
|
/** 叫号状态合计:已签到 + 已叫号 + 已过号(FLOW_STATUS IN '2','3','4',预约日期为今天) */
|
||||||
|
private Long callStatusTotal;
|
||||||
|
|
||||||
|
/** 今日已出场(FLOW_STATUS = '11',预约日期为今天),用于月台周转率 */
|
||||||
|
private Long todayExited;
|
||||||
|
|
||||||
/** 当前作业中 */
|
/** 当前作业中 */
|
||||||
private Long operatingVehicles;
|
private Long operatingVehicles;
|
||||||
|
|
||||||
|
|||||||
+420
-20
@@ -9,12 +9,29 @@ 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.biPlatformRealData.repository.po.RealMonthlyAvgDurationPO;
|
||||||
|
import com.mhd.bi.domain.biPlatformRealData.repository.po.RealTodayAvgDurationPO;
|
||||||
|
import com.mhd.bi.domain.biPlatformRealData.repository.po.RealOvertimeStatPO;
|
||||||
|
import com.mhd.bi.domain.biPlatformRealData.repository.po.RealOvertimeRecordPO;
|
||||||
|
|
||||||
import com.mhd.bi.domain.biPlatformSurveillance.repository.mapper.BiPlatformSurveillanceReportMapper;
|
import com.mhd.bi.domain.biPlatformSurveillance.repository.mapper.BiPlatformSurveillanceReportMapper;
|
||||||
|
import com.mhd.bi.domain.biStaticField.service.BiStaticFieldService;
|
||||||
|
|
||||||
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.AvgOperationDurationTrendItemVO;
|
||||||
|
import com.mhd.bi.interfaces.facadeApi.biReport.vo.platform.OvertimeRecordItemVO;
|
||||||
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 +108,33 @@ 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());
|
||||||
|
fp.put("platformTurnoverRate", vo.getPlatformOverview().getPlatformTurnoverRate());
|
||||||
|
}
|
||||||
|
// 入园超时率/超时数量 按业务要求恒为 0,不纳入指纹
|
||||||
|
// 准时率与平均时长为实时业务数据,纳入指纹
|
||||||
|
if (vo.getEfficiencyStatistics() != null) {
|
||||||
|
fp.put("platformOnTimeRate", vo.getEfficiencyStatistics().getPlatformOnTimeRate());
|
||||||
|
fp.put("yardOnTimeRate", vo.getEfficiencyStatistics().getYardOnTimeRate());
|
||||||
|
fp.put("avgPlatformDuration", vo.getEfficiencyStatistics().getAvgPlatformDuration());
|
||||||
|
fp.put("avgYardDuration", vo.getEfficiencyStatistics().getAvgYardDuration());
|
||||||
}
|
}
|
||||||
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("callStatusTotal", vo.getVehicleStatus().getCallStatusTotal());
|
||||||
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 +160,54 @@ public class BiPlatformRealDataService {
|
|||||||
}
|
}
|
||||||
fp.put("taskLoadStatistics", loads);
|
fp.put("taskLoadStatistics", loads);
|
||||||
}
|
}
|
||||||
|
if (vo.getAvgOperationDurationTrend() != null) {
|
||||||
|
|
||||||
|
|
||||||
|
List<Map<String, Object>> trend = new ArrayList<>();
|
||||||
|
for (AvgOperationDurationTrendItemVO item : vo.getAvgOperationDurationTrend()) {
|
||||||
|
Map<String, Object> m = new LinkedHashMap<>();
|
||||||
|
m.put("month", item.getMonth());
|
||||||
|
m.put("yardDuration", item.getYardDuration());
|
||||||
|
m.put("platformDuration", item.getPlatformDuration());
|
||||||
|
trend.add(m);
|
||||||
|
}
|
||||||
|
fp.put("avgOperationDurationTrend", trend);
|
||||||
|
}
|
||||||
|
fp.put("taskOvertimeRate", vo.getTaskOvertimeRate());
|
||||||
|
if (vo.getOvertimeRecords() != null) {
|
||||||
|
List<Map<String, Object>> recs = new ArrayList<>();
|
||||||
|
for (OvertimeRecordItemVO r : vo.getOvertimeRecords()) {
|
||||||
|
Map<String, Object> m = new LinkedHashMap<>();
|
||||||
|
m.put("windowName", r.getWindowName());
|
||||||
|
m.put("carNo", r.getCarNo());
|
||||||
|
m.put("overtimeMinutes", r.getOvertimeMinutes());
|
||||||
|
recs.add(m);
|
||||||
|
}
|
||||||
|
fp.put("overtimeRecords", recs);
|
||||||
|
}
|
||||||
|
|
||||||
|
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 +248,35 @@ 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.getCallStatusTotal() == null) po.setCallStatusTotal(0L);
|
||||||
|
if (po.getTodayExited() == null) po.setTodayExited(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,13 +285,20 @@ 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.setCallStatusTotal(0L);
|
||||||
|
po.setTodayExited(0L);
|
||||||
po.setOperatingVehicles(0L);
|
po.setOperatingVehicles(0L);
|
||||||
po.setCompletedVehicles(0L);
|
po.setCompletedVehicles(0L);
|
||||||
return po;
|
return po;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public long countMonthTasks() {
|
public long countMonthTasks() {
|
||||||
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
Long n = biPlatformRealDataMapper.countMonthTasks();
|
Long n = biPlatformRealDataMapper.countMonthTasks();
|
||||||
return n == null ? 0L : n;
|
return n == null ? 0L : n;
|
||||||
@@ -196,6 +308,33 @@ public class BiPlatformRealDataService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 本月任务平均时长 / 完成率统计:
|
||||||
|
* - totalWorkHours:本月任务作业时长合计(小时);未进入月台计 0,已进入未离开按 SYSDATE - IN_WINDOWS_TIME
|
||||||
|
* - avgDurationHours:任务平均作业时长 = totalWorkHours ÷ 本月任务数(totalCount),保留两位小数
|
||||||
|
* - taskCompletionRate:已完成(EXIT_TIME 不为空 且 预约日期在本月)/ 本月预约总数量 ×100
|
||||||
|
* 任一查询失败均返回 null,由调用方决定是否覆盖模板值。
|
||||||
|
*/
|
||||||
|
public RealMonthlyTaskDurationPO queryMonthTaskStats() {
|
||||||
|
try {
|
||||||
|
RealMonthlyTaskDurationPO po = biPlatformRealDataMapper.queryMonthTaskStats();
|
||||||
|
if (po == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
// 任务平均作业时长 = 本月作业时长合计 ÷ 本月任务数(分母为 0 时返回 0)
|
||||||
|
long totalCount = po.getTotalCount() == null ? 0L : po.getTotalCount();
|
||||||
|
double totalHours = po.getTotalWorkHours() == null ? 0d : po.getTotalWorkHours();
|
||||||
|
po.setAvgDurationHours(totalCount > 0
|
||||||
|
? Math.round((totalHours / (double) totalCount) * 100.0) / 100.0
|
||||||
|
: 0d);
|
||||||
|
return po;
|
||||||
|
} 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 +344,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,63 +439,295 @@ 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%(需求约定)
|
||||||
|
// 月台作业准时率 = 100 - 月台作业超时率
|
||||||
|
double platformOvertime = calcTodayTaskOvertimeRate();
|
||||||
|
template.getEfficiencyStatistics().setPlatformOnTimeRate(
|
||||||
|
(int) Math.round(100.0 - platformOvertime));
|
||||||
|
// 园区作业准时率 = 100 - 园区作业超时率
|
||||||
|
double yardOvertime = calcTodayYardOvertimeRate();
|
||||||
|
template.getEfficiencyStatistics().setYardOnTimeRate(
|
||||||
|
(int) Math.round(100.0 - yardOvertime));
|
||||||
}
|
}
|
||||||
|
|
||||||
// 作业车辆状态统计:真实数据源,无条件覆盖
|
|
||||||
|
// 平均作业时长(本日):月台作业平均时长 / 园区平均时长(真实数据,仅统计两端时间都非空的今日记录)
|
||||||
|
if (template.getEfficiencyStatistics() != null) {
|
||||||
|
RealTodayAvgDurationPO avg = queryTodayAvgDuration();
|
||||||
|
template.getEfficiencyStatistics().setAvgPlatformDuration(avg.getAvgPlatformDurationHours());
|
||||||
|
template.getEfficiencyStatistics().setAvgYardDuration(avg.getAvgYardDurationHours());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// 作业车辆状态统计:真实数据源,无条件覆盖(含等待作业 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().setCallStatusTotal(vs.getCallStatusTotal().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());
|
||||||
|
|
||||||
|
// 月台周转率 = 今日已出场记录数 ÷ 今日全部记录数 × 100%(保留两位小数)
|
||||||
|
if (template.getPlatformOverview() != null) {
|
||||||
|
long todayTotal = vs.getTodayReservedVehicles() == null ? 0L : vs.getTodayReservedVehicles();
|
||||||
|
long todayExited = vs.getTodayExited() == null ? 0L : vs.getTodayExited();
|
||||||
|
double turnover = todayTotal > 0
|
||||||
|
? Math.round(((double) todayExited / (double) todayTotal) * 100.0 * 100.0) / 100.0
|
||||||
|
: 0d;
|
||||||
|
template.getPlatformOverview().setPlatformTurnoverRate(turnover);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 本月任务统计: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) {
|
||||||
|
// 任务平均作业时长 = 本月任务作业时长合计 ÷ 本月任务数(已在 Service 层算好),保留两位小数
|
||||||
|
template.getMonthlyTaskStatistics().setAvgTaskDuration(monthStats.getAvgDurationHours());
|
||||||
|
}
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 任务负荷:有真实数据源;真实为空则清空不用模板模拟,有数据则按真实小时覆盖
|
// 平均装卸时长按业务要求恒为 0,不用真实值覆盖
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// 小时趋势(今日,每 2 小时分组):有真实数据源则按真实分桶重建,无数据则清空
|
||||||
List<RealTaskLoadPO> loads = queryTaskLoadToday();
|
List<RealTaskLoadPO> loads = queryTaskLoadToday();
|
||||||
if (loads.isEmpty()) {
|
if (loads.isEmpty()) {
|
||||||
template.setTaskLoadStatistics(new ArrayList<>());
|
template.setTaskLoadStatistics(new ArrayList<>());
|
||||||
} else if (template.getTaskLoadStatistics() != null) {
|
} else {
|
||||||
Map<Integer, Long> hourMap = new HashMap<>();
|
Map<Integer, Long> bucketMap = new HashMap<>();
|
||||||
for (RealTaskLoadPO l : loads) {
|
for (RealTaskLoadPO l : loads) {
|
||||||
hourMap.put(l.getHourOfDay(), l.getTaskCount());
|
if (l != null && l.getHourOfDay() != null) {
|
||||||
}
|
bucketMap.put(l.getHourOfDay(), l.getTaskCount() == null ? 0L : l.getTaskCount());
|
||||||
for (TaskLoadItemVO item : template.getTaskLoadStatistics()) {
|
|
||||||
Integer hour = parseHourFromLabel(item.getTime());
|
|
||||||
if (hour != null && hourMap.containsKey(hour)) {
|
|
||||||
item.setTaskCount(hourMap.get(hour).intValue());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// 固定输出 0,2,4,...,22 共 12 个桶,无数据桶补 0,保证前端坐标轴连续
|
||||||
|
List<TaskLoadItemVO> items = new ArrayList<>();
|
||||||
|
for (int h = 0; h < 24; h += 2) {
|
||||||
|
Long cnt = bucketMap.get(h);
|
||||||
|
items.add(TaskLoadItemVO.builder()
|
||||||
|
.time(String.format("%02d:00", h))
|
||||||
|
.taskCount(cnt == null ? 0 : cnt.intValue())
|
||||||
|
.build());
|
||||||
}
|
}
|
||||||
|
template.setTaskLoadStatistics(items);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// 任务类型统计:本月 YMS QMS_MAIN_BUSINESS 按业务类型 BUSINESS_NAME 分组(真实业务数据)
|
||||||
|
template.setTaskTypeStatistics(queryMonthTransportOrderByType());
|
||||||
|
|
||||||
|
// 平均作业时长趋势:近半年按月统计(月台作业平均时长 / 园区作业平均时长)
|
||||||
|
template.setAvgOperationDurationTrend(queryAvgOperationDurationTrend());
|
||||||
|
|
||||||
|
// 任务超时率 + 月台作业超时记录列表(依赖 YMS QMS_STATIC_FIELD 参考用时配置)
|
||||||
|
template.setTaskOvertimeRate(calcTodayTaskOvertimeRate());
|
||||||
|
template.setOvertimeRecords(queryTodayOvertimeRecords());
|
||||||
|
|
||||||
return template;
|
return template;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Integer parseHourFromLabel(String label) {
|
|
||||||
if (label == null) return null;
|
|
||||||
|
/**
|
||||||
|
* 今日平均作业时长(效率统计-本日),保留两位小数,单位:小时。
|
||||||
|
* - avgPlatformDurationHours:月台作业平均时长;仅统计同时有进入与离开月台时间的今日记录
|
||||||
|
* - avgYardDurationHours: 园区平均时长;仅统计同时有实际进入与实际出场时间的今日记录
|
||||||
|
* 查询失败或无有效记录时返回 0。
|
||||||
|
*/
|
||||||
|
public RealTodayAvgDurationPO queryTodayAvgDuration() {
|
||||||
|
RealTodayAvgDurationPO po = new RealTodayAvgDurationPO();
|
||||||
|
po.setAvgPlatformDurationHours(0d);
|
||||||
|
po.setAvgYardDurationHours(0d);
|
||||||
try {
|
try {
|
||||||
String s = label.replace("时", "").trim();
|
RealTodayAvgDurationPO row = biPlatformRealDataMapper.queryTodayAvgDuration();
|
||||||
return Integer.parseInt(s);
|
if (row != null) {
|
||||||
|
if (row.getAvgPlatformDurationHours() != null) {
|
||||||
|
po.setAvgPlatformDurationHours(
|
||||||
|
Math.round(row.getAvgPlatformDurationHours() * 100.0) / 100.0);
|
||||||
|
}
|
||||||
|
if (row.getAvgYardDurationHours() != null) {
|
||||||
|
po.setAvgYardDurationHours(
|
||||||
|
Math.round(row.getAvgYardDurationHours() * 100.0) / 100.0);
|
||||||
|
}
|
||||||
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
return null;
|
log.error("【YMS】统计今日平均作业时长失败: {}", e.getMessage(), e);
|
||||||
|
}
|
||||||
|
return po;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 今日任务超时率(%)= 超时记录数 ÷ 有效记录总数 × 100%,保留两位小数。
|
||||||
|
* 有效记录:月台已配置参考用时(platform_work_ref_minutes),且该记录同时有进入/离开月台时间。
|
||||||
|
* 无有效记录时返回 0。
|
||||||
|
*/
|
||||||
|
public double calcTodayTaskOvertimeRate() {
|
||||||
|
try {
|
||||||
|
RealOvertimeStatPO po = biPlatformRealDataMapper
|
||||||
|
.queryTodayOvertimeStat(BiStaticFieldService.CODE_PLATFORM_WORK_REF_MINUTES);
|
||||||
|
return calcRateFromStat(po);
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("【YMS】统计今日任务超时率失败: {}", e.getMessage(), e);
|
||||||
|
return 0d;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 今日园区作业超时率(%)= 园区作业时长 > 园区参考用时的记录数 ÷ 有效记录总数 × 100%。
|
||||||
|
* 有效记录:能取到园区参考用时(yard_work_ref_minutes),且记录同时有实际进入/实际出场时间。
|
||||||
|
* 无有效记录时返回 0。
|
||||||
|
*/
|
||||||
|
public double calcTodayYardOvertimeRate() {
|
||||||
|
try {
|
||||||
|
RealOvertimeStatPO po = biPlatformRealDataMapper
|
||||||
|
.queryTodayYardOvertimeStat(BiStaticFieldService.CODE_YARD_WORK_REF_MINUTES);
|
||||||
|
return calcRateFromStat(po);
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("【YMS】统计今日园区作业超时率失败: {}", e.getMessage(), e);
|
||||||
|
return 0d;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 由超时统计 PO 计算百分比,保留两位小数;无有效记录返回 0 */
|
||||||
|
private static double calcRateFromStat(RealOvertimeStatPO po) {
|
||||||
|
if (po == null) {
|
||||||
|
return 0d;
|
||||||
|
}
|
||||||
|
long total = po.getTotalCount() == null ? 0L : po.getTotalCount();
|
||||||
|
long overtime = po.getOvertimeCount() == null ? 0L : po.getOvertimeCount();
|
||||||
|
if (total <= 0) {
|
||||||
|
return 0d;
|
||||||
|
}
|
||||||
|
return Math.round(((double) overtime / (double) total) * 100.0 * 100.0) / 100.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 今日月台作业超时记录列表(月台名称 / 车牌号码 / 超时时长分钟)。
|
||||||
|
* 查询失败返回空列表。
|
||||||
|
*/
|
||||||
|
public List<OvertimeRecordItemVO> queryTodayOvertimeRecords() {
|
||||||
|
List<OvertimeRecordItemVO> result = new ArrayList<>();
|
||||||
|
try {
|
||||||
|
List<RealOvertimeRecordPO> rows = biPlatformRealDataMapper
|
||||||
|
.queryTodayOvertimeList(BiStaticFieldService.CODE_PLATFORM_WORK_REF_MINUTES);
|
||||||
|
|
||||||
|
if (rows == null) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
for (RealOvertimeRecordPO r : rows) {
|
||||||
|
if (r == null) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
result.add(OvertimeRecordItemVO.builder()
|
||||||
|
.windowName(r.getWindowName())
|
||||||
|
.carNo(r.getCarNo())
|
||||||
|
.overtimeMinutes(r.getOvertimeMinutes())
|
||||||
|
.refMinutes(r.getRefMinutes())
|
||||||
|
.platformMinutes(r.getPlatformMinutes())
|
||||||
|
.build());
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("【YMS】查询今日月台作业超时记录失败: {}", e.getMessage(), e);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 近半年「平均作业时长」趋势(近 6 个月,按月正序,含无数据月份补 0):
|
||||||
|
|
||||||
|
|
||||||
|
* - platformDuration:月台作业平均时长 = SUM(月台作业时长) ÷ 该月任务数
|
||||||
|
* - yardDuration: 园区作业平均时长 = SUM(园区作业时长) ÷ 该月任务数
|
||||||
|
* 均保留两位小数,单位:小时。
|
||||||
|
*/
|
||||||
|
public List<AvgOperationDurationTrendItemVO> queryAvgOperationDurationTrend() {
|
||||||
|
List<AvgOperationDurationTrendItemVO> result = new ArrayList<>();
|
||||||
|
Map<String, RealMonthlyAvgDurationPO> map = new HashMap<>();
|
||||||
|
try {
|
||||||
|
List<RealMonthlyAvgDurationPO> rows = biPlatformRealDataMapper.queryMonthlyAvgDuration();
|
||||||
|
if (rows != null) {
|
||||||
|
for (RealMonthlyAvgDurationPO r : rows) {
|
||||||
|
if (r != null && r.getMonthOfYear() != null) {
|
||||||
|
map.put(r.getMonthOfYear().trim(), r);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("【YMS】统计近半年平均作业时长失败: {}", e.getMessage(), e);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 生成近 6 个月的标签(含当前月),保证无数据月份也返回一条(值为 0)
|
||||||
|
java.time.LocalDate now = java.time.LocalDate.now();
|
||||||
|
java.time.format.DateTimeFormatter keyFmt = java.time.format.DateTimeFormatter.ofPattern("yyyy-MM");
|
||||||
|
for (int i = 5; i >= 0; i--) {
|
||||||
|
java.time.LocalDate m = now.minusMonths(i);
|
||||||
|
String key = m.format(keyFmt);
|
||||||
|
RealMonthlyAvgDurationPO po = map.get(key);
|
||||||
|
AvgOperationDurationTrendItemVO item = new AvgOperationDurationTrendItemVO();
|
||||||
|
// 展示用月份标签,如 "9月"
|
||||||
|
item.setMonth(m.getMonthValue() + "月");
|
||||||
|
if (po != null) {
|
||||||
|
long cnt = po.getTaskCount() == null ? 0L : po.getTaskCount();
|
||||||
|
double platformHours = po.getPlatformWorkHours() == null ? 0d : po.getPlatformWorkHours();
|
||||||
|
double yardHours = po.getYardWorkHours() == null ? 0d : po.getYardWorkHours();
|
||||||
|
item.setPlatformDuration(cnt > 0
|
||||||
|
? Math.round((platformHours / (double) cnt) * 100.0) / 100.0 : 0d);
|
||||||
|
item.setYardDuration(cnt > 0
|
||||||
|
? Math.round((yardHours / (double) cnt) * 100.0) / 100.0 : 0d);
|
||||||
|
} else {
|
||||||
|
item.setPlatformDuration(0d);
|
||||||
|
item.setYardDuration(0d);
|
||||||
|
}
|
||||||
|
result.add(item);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 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已取消
|
||||||
|
|
||||||
*/
|
*/
|
||||||
private static String translateFlowStatus(String flowStatus) {
|
private static String translateFlowStatus(String flowStatus) {
|
||||||
if (flowStatus == null) return null;
|
if (flowStatus == null) return null;
|
||||||
|
|||||||
+9
-4
@@ -43,9 +43,9 @@ public final class BiReportSnapshotMapperSupport {
|
|||||||
return ComprehensiveSituationVO.builder()
|
return ComprehensiveSituationVO.builder()
|
||||||
.valueAddedServiceIncome(0L)
|
.valueAddedServiceIncome(0L)
|
||||||
.inventoryTurnover(0)
|
.inventoryTurnover(0)
|
||||||
.orderCount(0)
|
.orderCount(0L)
|
||||||
.vehicleUtilizationRate(0d)
|
.vehicleUtilizationRate(0d)
|
||||||
.fuelConsumptionPerHundredKm(0)
|
.fuelConsumptionPerHundredKm(0d)
|
||||||
.incomeTrend(Collections.emptyList())
|
.incomeTrend(Collections.emptyList())
|
||||||
.build();
|
.build();
|
||||||
}
|
}
|
||||||
@@ -85,9 +85,12 @@ public final class BiReportSnapshotMapperSupport {
|
|||||||
.entryOvertimeRate(0).overtimeCount(0).platformOnTimeRate(0)
|
.entryOvertimeRate(0).overtimeCount(0).platformOnTimeRate(0)
|
||||||
.avgPlatformDuration(0d).yardOnTimeRate(0).avgYardDuration(0d).build())
|
.avgPlatformDuration(0d).yardOnTimeRate(0).avgYardDuration(0d).build())
|
||||||
.platformOverview(PlatformOverviewVO.builder()
|
.platformOverview(PlatformOverviewVO.builder()
|
||||||
.totalPlatforms(0).currentOccupancyRate(0d).operatingPlatforms(0).todayTasks(0).build())
|
.totalPlatforms(0).currentOccupancyRate(0d).operatingPlatforms(0).todayTasks(0)
|
||||||
|
.platformTurnoverRate(0d).build())
|
||||||
.vehicleStatus(VehicleStatusVO.builder()
|
.vehicleStatus(VehicleStatusVO.builder()
|
||||||
.todayReservedVehicles(0).notCheckedIn(0).operatingVehicles(0).completedVehicles(0).build())
|
.todayReservedVehicles(0).notCheckedIn(0).waiting(0)
|
||||||
|
.callStatusTotal(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)
|
||||||
@@ -99,6 +102,8 @@ public final class BiReportSnapshotMapperSupport {
|
|||||||
.platformAlarmStatistics(PlatformAlarmStatisticsVO.builder()
|
.platformAlarmStatistics(PlatformAlarmStatisticsVO.builder()
|
||||||
.todayAlarmTotal(0).handled(0).unhandled(0).build())
|
.todayAlarmTotal(0).handled(0).unhandled(0).build())
|
||||||
.platformAlarmDistribution(Collections.emptyList())
|
.platformAlarmDistribution(Collections.emptyList())
|
||||||
|
.taskOvertimeRate(0d)
|
||||||
|
.overtimeRecords(Collections.emptyList())
|
||||||
.build();
|
.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+5
@@ -9,8 +9,13 @@ public interface BiSnapshotWriteMapper {
|
|||||||
|
|
||||||
int insertComprehensiveSnapshot(@Param("payloadJson") String payloadJson, @Param("remark") String remark);
|
int insertComprehensiveSnapshot(@Param("payloadJson") String payloadJson, @Param("remark") String remark);
|
||||||
|
|
||||||
|
int updateLatestComprehensiveSnapshot(@Param("payloadJson") String payloadJson, @Param("remark") String remark);
|
||||||
|
|
||||||
|
|
||||||
int insertWarehouseTransportSnapshot(@Param("payloadJson") String payloadJson, @Param("remark") String remark);
|
int insertWarehouseTransportSnapshot(@Param("payloadJson") String payloadJson, @Param("remark") String remark);
|
||||||
|
|
||||||
|
int updateLatestWarehouseTransportSnapshot(@Param("payloadJson") String payloadJson, @Param("remark") String remark);
|
||||||
|
|
||||||
int insertPlatformSurveillanceSnapshot(@Param("payloadJson") String payloadJson, @Param("remark") String remark);
|
int insertPlatformSurveillanceSnapshot(@Param("payloadJson") String payloadJson, @Param("remark") String remark);
|
||||||
|
|
||||||
int updateLatestPlatformSurveillanceSnapshot(@Param("payloadJson") String payloadJson, @Param("remark") String remark);
|
int updateLatestPlatformSurveillanceSnapshot(@Param("payloadJson") String payloadJson, @Param("remark") String remark);
|
||||||
|
|||||||
+125
-32
@@ -16,9 +16,11 @@ 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 com.mhd.bi.domain.biWarehouseTransport.repository.po.RealWarehouseOrderStatPO;
|
||||||
|
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
@@ -45,6 +47,8 @@ public class BiReportSnapshotSyncService {
|
|||||||
private final BiSnapshotWriteMapper biSnapshotWriteMapper;
|
private final BiSnapshotWriteMapper biSnapshotWriteMapper;
|
||||||
private final ObjectMapper objectMapper;
|
private final ObjectMapper objectMapper;
|
||||||
private final BiPlatformRealDataService biPlatformRealDataService;
|
private final BiPlatformRealDataService biPlatformRealDataService;
|
||||||
|
private final com.mhd.bi.domain.biWarehouseTransport.service.BiWarehouseTransportRealDataService biWarehouseTransportRealDataService;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 依次同步各快照表;单表失败不影响其它表,只记日志。
|
* 依次同步各快照表;单表失败不影响其它表,只记日志。
|
||||||
@@ -143,11 +147,33 @@ public class BiReportSnapshotSyncService {
|
|||||||
return BiSnapshotWeeklyRandomDataBuilder.comprehensive(new Random());
|
return BiSnapshotWeeklyRandomDataBuilder.comprehensive(new Random());
|
||||||
}
|
}
|
||||||
|
|
||||||
/** TODO 业务落地:改为查询真实数据。临时实现见 {@link BiSnapshotWeeklyRandomDataBuilder#warehouseTransport(Random)}。 */
|
/**
|
||||||
|
* 仓储运输:订单量 / 今日订单 / 今日运输车次 / 客户贡献排名 用真实数据覆盖;
|
||||||
|
* 其余(趋势类、周转率、货量等)仍为写死模板。
|
||||||
|
*/
|
||||||
protected WarehouseTransportSituationVO buildWarehouseTransportSnapshot() {
|
protected WarehouseTransportSituationVO buildWarehouseTransportSnapshot() {
|
||||||
return BiSnapshotWeeklyRandomDataBuilder.warehouseTransport(new Random());
|
WarehouseTransportSituationVO template =
|
||||||
|
BiSnapshotWeeklyRandomDataBuilder.warehouseTransport(new Random(20260825L));
|
||||||
|
|
||||||
|
// ====== 真实数据:仓储订单量(WMS 入库单 + 出库单,本年度/本季度/本月度,全部组织) ======
|
||||||
|
RealWarehouseOrderStatPO orderStat = biWarehouseTransportRealDataService.queryWarehouseOrderStat();
|
||||||
|
template.setCurrentYearOrders(orderStat.getCurrentYearOrders());
|
||||||
|
template.setCurrentQuarterOrders(orderStat.getCurrentQuarterOrders().intValue());
|
||||||
|
template.setCurrentMonthOrders(orderStat.getCurrentMonthOrders().intValue());
|
||||||
|
|
||||||
|
// ====== 真实数据:今日订单数量(OMS 运输业务单) ======
|
||||||
|
template.setOrderCount((int) biWarehouseTransportRealDataService.countTodayTransportOrders());
|
||||||
|
|
||||||
|
// ====== 真实数据:今日运输车次(TMS 运输单) ======
|
||||||
|
template.setTransportTrips((int) biWarehouseTransportRealDataService.countTodayTransportTrips());
|
||||||
|
|
||||||
|
// ====== 真实数据:客户贡献排名(OMS 近半年前 5 名货主) ======
|
||||||
|
template.setCustomerContributionRank(biWarehouseTransportRealDataService.queryCustomerContributionRank());
|
||||||
|
|
||||||
|
return template;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/** TODO 业务落地:部分字段改为真实数据,其余仍写死。 */
|
/** TODO 业务落地:部分字段改为真实数据,其余仍写死。 */
|
||||||
protected PlatformSurveillanceVO buildPlatformSurveillanceSnapshot() {
|
protected PlatformSurveillanceVO buildPlatformSurveillanceSnapshot() {
|
||||||
// 固定种子,保证写死字段每次生成值一致(真实字段随后实时覆盖)
|
// 固定种子,保证写死字段每次生成值一致(真实字段随后实时覆盖)
|
||||||
@@ -173,68 +199,135 @@ 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);
|
||||||
|
|
||||||
|
// 作业准时率:任务超时率 + 月台作业准时率 = 100%;园区作业准时率 = 100 - 园区超时率
|
||||||
|
template.getEfficiencyStatistics().setPlatformOnTimeRate(
|
||||||
|
(int) Math.round(100.0 - biPlatformRealDataService.calcTodayTaskOvertimeRate()));
|
||||||
|
template.getEfficiencyStatistics().setYardOnTimeRate(
|
||||||
|
(int) Math.round(100.0 - biPlatformRealDataService.calcTodayYardOvertimeRate()));
|
||||||
}
|
}
|
||||||
long todayTasks = biPlatformRealDataService.countTodayTasks();
|
|
||||||
if (template.getPlatformOverview() != null) {
|
|
||||||
template.getPlatformOverview().setTodayTasks((int) todayTasks);
|
// ====== 真实数据:平均作业时长(本日)月台作业平均时长 / 园区平均时长 ======
|
||||||
|
if (template.getEfficiencyStatistics() != null) {
|
||||||
|
com.mhd.bi.domain.biPlatformRealData.repository.po.RealTodayAvgDurationPO avg =
|
||||||
|
biPlatformRealDataService.queryTodayAvgDuration();
|
||||||
|
template.getEfficiencyStatistics().setAvgPlatformDuration(avg.getAvgPlatformDurationHours());
|
||||||
|
template.getEfficiencyStatistics().setAvgYardDuration(avg.getAvgYardDurationHours());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// ====== 真实数据:作业车辆状态统计 ======
|
// ====== 真实数据:作业车辆状态统计 ======
|
||||||
RealVehicleStatusPO vs = biPlatformRealDataService.queryVehicleStatusToday();
|
RealVehicleStatusPO vs = biPlatformRealDataService.queryVehicleStatusToday();
|
||||||
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().setCallStatusTotal(vs.getCallStatusTotal() == null ? 0 : vs.getCallStatusTotal().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());
|
||||||
|
|
||||||
|
// 月台周转率 = 今日已出场记录数 ÷ 今日全部记录数 × 100%(保留两位小数)
|
||||||
|
if (template.getPlatformOverview() != null) {
|
||||||
|
long todayTotal = vs.getTodayReservedVehicles() == null ? 0L : vs.getTodayReservedVehicles();
|
||||||
|
long todayExited = vs.getTodayExited() == null ? 0L : vs.getTodayExited();
|
||||||
|
double turnover = todayTotal > 0
|
||||||
|
? Math.round(((double) todayExited / (double) todayTotal) * 100.0 * 100.0) / 100.0
|
||||||
|
: 0d;
|
||||||
|
template.getPlatformOverview().setPlatformTurnoverRate(turnover);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ====== 真实数据:本月任务统计 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) {
|
||||||
|
// 任务平均作业时长 = 本月作业时长合计 ÷ 本月任务数(Service 层已算好)
|
||||||
|
template.getMonthlyTaskStatistics().setAvgTaskDuration(monthStats.getAvgDurationHours());
|
||||||
|
}
|
||||||
|
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 小时) ======
|
// ====== 真实数据:小时趋势(今日,每 2 小时分组) ======
|
||||||
List<RealTaskLoadPO> loads = biPlatformRealDataService.queryTaskLoadToday();
|
List<RealTaskLoadPO> loads = biPlatformRealDataService.queryTaskLoadToday();
|
||||||
if (!loads.isEmpty() && template.getTaskLoadStatistics() != null) {
|
if (loads.isEmpty()) {
|
||||||
Map<Integer, Long> hourMap = new HashMap<>();
|
template.setTaskLoadStatistics(new ArrayList<>());
|
||||||
|
} else {
|
||||||
|
Map<Integer, Long> bucketMap = new HashMap<>();
|
||||||
for (RealTaskLoadPO l : loads) {
|
for (RealTaskLoadPO l : loads) {
|
||||||
hourMap.put(l.getHourOfDay(), l.getTaskCount());
|
if (l != null && l.getHourOfDay() != null) {
|
||||||
}
|
bucketMap.put(l.getHourOfDay(), l.getTaskCount() == null ? 0L : l.getTaskCount());
|
||||||
for (com.mhd.bi.interfaces.facadeApi.biReport.vo.platform.TaskLoadItemVO item : template.getTaskLoadStatistics()) {
|
|
||||||
Integer hour = parseHourFromLabel(item.getTime());
|
|
||||||
if (hour != null) {
|
|
||||||
Long n = hourMap.get(hour);
|
|
||||||
if (n != null) item.setTaskCount(n.intValue());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// 固定输出 0,2,4,...,22 共 12 个桶,无数据桶补 0
|
||||||
|
List<com.mhd.bi.interfaces.facadeApi.biReport.vo.platform.TaskLoadItemVO> items = new ArrayList<>();
|
||||||
|
for (int h = 0; h < 24; h += 2) {
|
||||||
|
Long cnt = bucketMap.get(h);
|
||||||
|
items.add(com.mhd.bi.interfaces.facadeApi.biReport.vo.platform.TaskLoadItemVO.builder()
|
||||||
|
.time(String.format("%02d:00", h))
|
||||||
|
.taskCount(cnt == null ? 0 : cnt.intValue())
|
||||||
|
.build());
|
||||||
}
|
}
|
||||||
|
template.setTaskLoadStatistics(items);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// ====== 真实数据:任务类型统计(本月 YMS QMS_MAIN_BUSINESS 按业务类型 BUSINESS_NAME 分组) ======
|
||||||
|
template.setTaskTypeStatistics(biPlatformRealDataService.queryMonthTransportOrderByType());
|
||||||
|
|
||||||
|
// ====== 真实数据:平均作业时长趋势(近半年按月:月台作业平均时长 / 园区作业平均时长) ======
|
||||||
|
template.setAvgOperationDurationTrend(biPlatformRealDataService.queryAvgOperationDurationTrend());
|
||||||
|
|
||||||
|
// ====== 真实数据:任务超时率 + 月台作业超时记录列表(依赖 YMS QMS_STATIC_FIELD 参考用时) ======
|
||||||
|
template.setTaskOvertimeRate(biPlatformRealDataService.calcTodayTaskOvertimeRate());
|
||||||
|
template.setOvertimeRecords(biPlatformRealDataService.queryTodayOvertimeRecords());
|
||||||
|
|
||||||
return template;
|
return template;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Integer parseHourFromLabel(String label) {
|
|
||||||
if (label == null) return null;
|
|
||||||
// "15时" -> 15
|
|
||||||
try {
|
|
||||||
String s = label.replace("时", "").trim();
|
|
||||||
return Integer.parseInt(s);
|
|
||||||
} catch (Exception e) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* TODO 业务落地:改为查询真实数据组装 VO。当前为 {@link WarehouseOperationZoneDemoData} 静态示例。
|
* TODO 业务落地:改为查询真实数据组装 VO。当前为 {@link WarehouseOperationZoneDemoData} 静态示例。
|
||||||
*/
|
*/
|
||||||
|
|
||||||
protected WarehouseOperationZoneVO buildWarehouseOperationZoneSnapshot() {
|
protected WarehouseOperationZoneVO buildWarehouseOperationZoneSnapshot() {
|
||||||
return WarehouseOperationZoneDemoData.build();
|
return WarehouseOperationZoneDemoData.build();
|
||||||
}
|
}
|
||||||
|
|||||||
+29
-33
@@ -79,9 +79,9 @@ public final class BiSnapshotWeeklyRandomDataBuilder {
|
|||||||
return ComprehensiveSituationVO.builder()
|
return ComprehensiveSituationVO.builder()
|
||||||
.valueAddedServiceIncome(jitterLong(Baseline.COMP_INCOME, r))
|
.valueAddedServiceIncome(jitterLong(Baseline.COMP_INCOME, r))
|
||||||
.inventoryTurnover(Math.max(1, jitterInt(Baseline.COMP_TURNOVER, r)))
|
.inventoryTurnover(Math.max(1, jitterInt(Baseline.COMP_TURNOVER, r)))
|
||||||
.orderCount(Math.max(0, jitterInt(Baseline.COMP_ORDERS, r)))
|
.orderCount((long) Math.max(0, jitterInt(Baseline.COMP_ORDERS, r)))
|
||||||
.vehicleUtilizationRate(jitterPercentDouble(Baseline.COMP_VEHICLE_PCT, r))
|
.vehicleUtilizationRate(jitterPercentDouble(Baseline.COMP_VEHICLE_PCT, r))
|
||||||
.fuelConsumptionPerHundredKm(Math.max(1, jitterInt(Baseline.COMP_FUEL, r)))
|
.fuelConsumptionPerHundredKm(Math.max(1.0, jitterDouble(Baseline.COMP_FUEL, r)))
|
||||||
.incomeTrend(jitterIntArray(Baseline.COMP_INCOME_TREND, r))
|
.incomeTrend(jitterIntArray(Baseline.COMP_INCOME_TREND, r))
|
||||||
.build();
|
.build();
|
||||||
}
|
}
|
||||||
@@ -136,13 +136,14 @@ public final class BiSnapshotWeeklyRandomDataBuilder {
|
|||||||
.build());
|
.build());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 效率统计(本日):入园区超时率、超时数量、月台作业准时率、园区作业准时率 按业务要求恒为 0
|
||||||
EfficiencyStatisticsVO eff = EfficiencyStatisticsVO.builder()
|
EfficiencyStatisticsVO eff = EfficiencyStatisticsVO.builder()
|
||||||
.entryOvertimeRate(jitterPercentInt(Baseline.P_ENT_OT, r))
|
.entryOvertimeRate(0)
|
||||||
.overtimeCount(Math.max(0, jitterInt(Baseline.P_OT_CNT, r)))
|
.overtimeCount(0)
|
||||||
.platformOnTimeRate(jitterPercentInt(Baseline.P_PL_OT, r))
|
.platformOnTimeRate(0)
|
||||||
.avgPlatformDuration(Math.max(0.1, jitterDouble(Baseline.P_AVG_PL, r)))
|
.avgPlatformDuration(0d)
|
||||||
.yardOnTimeRate(jitterPercentInt(Baseline.P_YD_OT, r))
|
.yardOnTimeRate(0)
|
||||||
.avgYardDuration(Math.max(0.1, jitterDouble(Baseline.P_AVG_YD, r)))
|
.avgYardDuration(0d)
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
PlatformOverviewVO overview = PlatformOverviewVO.builder()
|
PlatformOverviewVO overview = PlatformOverviewVO.builder()
|
||||||
@@ -150,15 +151,19 @@ public final class BiSnapshotWeeklyRandomDataBuilder {
|
|||||||
.currentOccupancyRate((double) jitterPercentInt(Baseline.P_OCC, r))
|
.currentOccupancyRate((double) jitterPercentInt(Baseline.P_OCC, r))
|
||||||
.operatingPlatforms(Math.max(0, jitterInt(Baseline.P_OP, r)))
|
.operatingPlatforms(Math.max(0, jitterInt(Baseline.P_OP, r)))
|
||||||
.todayTasks(Math.max(0, jitterInt(Baseline.P_TASKS, r)))
|
.todayTasks(Math.max(0, jitterInt(Baseline.P_TASKS, r)))
|
||||||
|
.platformTurnoverRate(jitterPercentDouble(Baseline.P_TURNOVER, r))
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
VehicleStatusVO vs = VehicleStatusVO.builder()
|
VehicleStatusVO vs = VehicleStatusVO.builder()
|
||||||
.todayReservedVehicles(Math.max(0, jitterInt(Baseline.P_RESV, r)))
|
.todayReservedVehicles(Math.max(0, jitterInt(Baseline.P_RESV, r)))
|
||||||
.notCheckedIn(Math.max(0, jitterInt(Baseline.P_NC, r)))
|
.notCheckedIn(Math.max(0, jitterInt(Baseline.P_NC, r)))
|
||||||
|
.waiting(Math.max(0, jitterInt(Baseline.P_WAIT, r)))
|
||||||
|
.callStatusTotal(Math.max(0, jitterInt(Baseline.P_CALL_STATUS_TOTAL, r)))
|
||||||
.operatingVehicles(Math.max(0, jitterInt(Baseline.P_OPV, r)))
|
.operatingVehicles(Math.max(0, jitterInt(Baseline.P_OPV, r)))
|
||||||
.completedVehicles(Math.max(0, jitterInt(Baseline.P_DONE, r)))
|
.completedVehicles(Math.max(0, jitterInt(Baseline.P_DONE, r)))
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
|
|
||||||
List<AvgOperationDurationTrendItemVO> avgTrend = new ArrayList<>();
|
List<AvgOperationDurationTrendItemVO> avgTrend = new ArrayList<>();
|
||||||
for (int i = 0; i < Baseline.P_MO_LABELS.length; i++) {
|
for (int i = 0; i < Baseline.P_MO_LABELS.length; i++) {
|
||||||
avgTrend.add(AvgOperationDurationTrendItemVO.builder()
|
avgTrend.add(AvgOperationDurationTrendItemVO.builder()
|
||||||
@@ -185,13 +190,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 +201,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)
|
||||||
@@ -233,9 +226,13 @@ public final class BiSnapshotWeeklyRandomDataBuilder {
|
|||||||
.unhandled(unhandled)
|
.unhandled(unhandled)
|
||||||
.build())
|
.build())
|
||||||
.platformAlarmDistribution(dist)
|
.platformAlarmDistribution(dist)
|
||||||
|
// 任务超时率 / 超时记录列表:实时查库覆盖,模板给 0/空兜底
|
||||||
|
.taskOvertimeRate(0d)
|
||||||
|
.overtimeRecords(new ArrayList<>())
|
||||||
.build();
|
.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 总体运营态势:与 {@code create_bi_overall_operation_dm.sql} 内置 PAYLOAD_JSON 一致(不随 Random 抖动)。
|
* 总体运营态势:与 {@code create_bi_overall_operation_dm.sql} 内置 PAYLOAD_JSON 一致(不随 Random 抖动)。
|
||||||
*/
|
*/
|
||||||
@@ -371,7 +368,7 @@ public final class BiSnapshotWeeklyRandomDataBuilder {
|
|||||||
static final int COMP_TURNOVER = 18;
|
static final int COMP_TURNOVER = 18;
|
||||||
static final int COMP_ORDERS = 50_120;
|
static final int COMP_ORDERS = 50_120;
|
||||||
static final double COMP_VEHICLE_PCT = 93.2;
|
static final double COMP_VEHICLE_PCT = 93.2;
|
||||||
static final int COMP_FUEL = 12;
|
static final double COMP_FUEL = 12.5;
|
||||||
static final int[] COMP_INCOME_TREND = {195, 248, 302, 415, 366, 488};
|
static final int[] COMP_INCOME_TREND = {195, 248, 302, 415, 366, 488};
|
||||||
|
|
||||||
static final double W_WH_RATE = 96.8;
|
static final double W_WH_RATE = 96.8;
|
||||||
@@ -403,18 +400,15 @@ public final class BiSnapshotWeeklyRandomDataBuilder {
|
|||||||
{"闽D99887", "作业中", "#07", "142"},
|
{"闽D99887", "作业中", "#07", "142"},
|
||||||
{"粤B66220", "已离园", "#29", "201"}
|
{"粤B66220", "已离园", "#29", "201"}
|
||||||
};
|
};
|
||||||
static final int P_ENT_OT = 42;
|
|
||||||
static final int P_OT_CNT = 28;
|
|
||||||
static final int P_PL_OT = 88;
|
|
||||||
static final double P_AVG_PL = 3.8;
|
|
||||||
static final int P_YD_OT = 91;
|
|
||||||
static final double P_AVG_YD = 5.2;
|
|
||||||
static final int P_TOT_PL = 58;
|
static final int P_TOT_PL = 58;
|
||||||
static final int P_OCC = 62;
|
static final int P_OCC = 62;
|
||||||
static final int P_OP = 31;
|
static final int P_OP = 31;
|
||||||
static final int P_TASKS = 418;
|
static final int P_TASKS = 418;
|
||||||
|
static final double P_TURNOVER = 72.5;
|
||||||
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_CALL_STATUS_TOTAL = 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月"};
|
||||||
@@ -426,8 +420,10 @@ public final class BiSnapshotWeeklyRandomDataBuilder {
|
|||||||
static final int P_MT_AVG_YOY = -3;
|
static final int P_MT_AVG_YOY = -3;
|
||||||
static final int P_MT_CR = 97;
|
static final int P_MT_CR = 97;
|
||||||
static final int P_MT_CR_YOY = 2;
|
static final int P_MT_CR_YOY = 2;
|
||||||
static final String[] P_LOAD_T = {"8时", "10时", "14时"};
|
/** 小时趋势:每 2 小时一个桶,0:00 ~ 22:00 共 12 个 */
|
||||||
static final int[] P_LOAD_C = {45, 120, 156};
|
static final String[] P_LOAD_T = {"00:00", "02:00", "04:00", "06:00", "08:00", "10:00",
|
||||||
|
"12:00", "14:00", "16:00", "18:00", "20:00", "22:00"};
|
||||||
|
static final int[] P_LOAD_C = {5, 3, 2, 8, 45, 120, 130, 156, 110, 70, 30, 12};
|
||||||
static final String[] P_AL_D = {"1日", "2日", "3日"};
|
static final String[] P_AL_D = {"1日", "2日", "3日"};
|
||||||
static final int[] P_AL_C = {6, 9, 4};
|
static final int[] P_AL_C = {6, 9, 4};
|
||||||
static final int P_TT_TOT = 5_100;
|
static final int P_TT_TOT = 5_100;
|
||||||
|
|||||||
+23
@@ -0,0 +1,23 @@
|
|||||||
|
package com.mhd.bi.domain.biStaticField.repository.mapper;
|
||||||
|
|
||||||
|
import com.mhd.bi.domain.biStaticField.repository.po.BiStaticFieldPO;
|
||||||
|
import org.apache.ibatis.annotations.Param;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* BI 业务静态字段配置 Mapper(YMS 库 NGWL_TEST_YMS.QMS_STATIC_FIELD)
|
||||||
|
*
|
||||||
|
* <p>SQL 见 BiStaticFieldMapper.xml。</p>
|
||||||
|
*/
|
||||||
|
public interface BiStaticFieldMapper {
|
||||||
|
|
||||||
|
/** 按字段编码查询全部有效配置(含 GLOBAL / FLOOR / WINDOW 各作用域,供程序按优先级取值) */
|
||||||
|
List<BiStaticFieldPO> queryByCode(@Param("fieldCode") String fieldCode);
|
||||||
|
|
||||||
|
/** 批量按字段编码查询有效配置 */
|
||||||
|
List<BiStaticFieldPO> queryByCodes(@Param("fieldCodes") List<String> fieldCodes);
|
||||||
|
|
||||||
|
/** 查询全部有效配置 */
|
||||||
|
List<BiStaticFieldPO> queryAll();
|
||||||
|
}
|
||||||
+38
@@ -0,0 +1,38 @@
|
|||||||
|
package com.mhd.bi.domain.biStaticField.repository.po;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 业务静态字段配置(来自 NGWL_TEST_YMS.QMS_STATIC_FIELD)
|
||||||
|
*
|
||||||
|
* <p>集中存放指标计算所需的参考值/基准值,当前使用:</p>
|
||||||
|
* <ul>
|
||||||
|
* <li>platform_work_ref_minutes 月台作业参考用时(分钟)</li>
|
||||||
|
* <li>yard_work_ref_minutes 园区作业参考用时(分钟)</li>
|
||||||
|
* </ul>
|
||||||
|
* <p>后续新增静态字段只需往表里 INSERT,无需改代码结构。</p>
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class BiStaticFieldPO implements Serializable {
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
/** 静态字段编码 */
|
||||||
|
private String fieldCode;
|
||||||
|
|
||||||
|
/** 静态字段名称 */
|
||||||
|
private String fieldName;
|
||||||
|
|
||||||
|
/** 作用域类型:GLOBAL-全局 FLOOR-按楼层 WINDOW-按月台 */
|
||||||
|
private String scopeType;
|
||||||
|
|
||||||
|
/** 作用域编码:GLOBAL 时为 ALL;FLOOR 时为楼层;WINDOW 时为月台名 */
|
||||||
|
private String scopeCode;
|
||||||
|
|
||||||
|
/** 字段值(字符串,程序按需转换) */
|
||||||
|
private String fieldValue;
|
||||||
|
|
||||||
|
/** 单位 */
|
||||||
|
private String unit;
|
||||||
|
}
|
||||||
+108
@@ -0,0 +1,108 @@
|
|||||||
|
package com.mhd.bi.domain.biStaticField.service;
|
||||||
|
|
||||||
|
import com.mhd.bi.domain.biStaticField.repository.mapper.BiStaticFieldMapper;
|
||||||
|
import com.mhd.bi.domain.biStaticField.repository.po.BiStaticFieldPO;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import javax.annotation.Resource;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* BI 业务静态字段配置业务层(YMS 库 QMS_STATIC_FIELD)
|
||||||
|
*
|
||||||
|
* <p>集中提供参考值/基准值等静态配置的读取能力,后续新增静态字段只需往表里 INSERT。</p>
|
||||||
|
*/
|
||||||
|
@Slf4j
|
||||||
|
@Service
|
||||||
|
public class BiStaticFieldService {
|
||||||
|
|
||||||
|
/** 月台作业参考用时(分钟) */
|
||||||
|
public static final String CODE_PLATFORM_WORK_REF_MINUTES = "platform_work_ref_minutes";
|
||||||
|
|
||||||
|
/** 园区作业参考用时(分钟) */
|
||||||
|
public static final String CODE_YARD_WORK_REF_MINUTES = "yard_work_ref_minutes";
|
||||||
|
|
||||||
|
/** 作用域:全局 */
|
||||||
|
private static final String SCOPE_GLOBAL = "GLOBAL";
|
||||||
|
/** 作用域:按月台 */
|
||||||
|
private static final String SCOPE_WINDOW = "WINDOW";
|
||||||
|
/** 作用域:按楼层 */
|
||||||
|
private static final String SCOPE_FLOOR = "FLOOR";
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private BiStaticFieldMapper biStaticFieldMapper;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 按字段编码查询全部有效配置;查询失败返回空列表。
|
||||||
|
*/
|
||||||
|
public List<BiStaticFieldPO> queryByCode(String fieldCode) {
|
||||||
|
try {
|
||||||
|
List<BiStaticFieldPO> list = biStaticFieldMapper.queryByCode(fieldCode);
|
||||||
|
return list == null ? Collections.emptyList() : list;
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("【YMS】查询静态字段配置失败, fieldCode={}: {}", fieldCode, e.getMessage(), e);
|
||||||
|
return Collections.emptyList();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 按「WINDOW > FLOOR > GLOBAL」优先级取静态字段值(字符串)。取不到返回 null。
|
||||||
|
*
|
||||||
|
* @param fieldCode 字段编码
|
||||||
|
* @param windowName 月台名(可为空)
|
||||||
|
* @param floor 楼层(可为空)
|
||||||
|
*/
|
||||||
|
public String resolveValue(String fieldCode, String windowName, String floor) {
|
||||||
|
List<BiStaticFieldPO> list = queryByCode(fieldCode);
|
||||||
|
if (list.isEmpty()) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
String globalVal = null;
|
||||||
|
String floorVal = null;
|
||||||
|
for (BiStaticFieldPO po : list) {
|
||||||
|
if (po == null || po.getFieldValue() == null) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
String scopeType = po.getScopeType() == null ? "" : po.getScopeType().trim().toUpperCase();
|
||||||
|
String scopeCode = po.getScopeCode();
|
||||||
|
if (SCOPE_WINDOW.equals(scopeType) && windowName != null && windowName.equals(scopeCode)) {
|
||||||
|
return po.getFieldValue(); // 最高优先级,直接返回
|
||||||
|
}
|
||||||
|
if (SCOPE_FLOOR.equals(scopeType) && floor != null && floor.equals(scopeCode)) {
|
||||||
|
floorVal = po.getFieldValue();
|
||||||
|
}
|
||||||
|
if (SCOPE_GLOBAL.equals(scopeType)) {
|
||||||
|
globalVal = po.getFieldValue();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return floorVal != null ? floorVal : globalVal;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 取静态字段的数值(分钟等整数),取不到或非数字返回 null。
|
||||||
|
*/
|
||||||
|
public Long resolveLongValue(String fieldCode, String windowName, String floor) {
|
||||||
|
String v = resolveValue(fieldCode, windowName, floor);
|
||||||
|
if (v == null || v.trim().isEmpty()) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
return Long.valueOf(v.trim());
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.warn("【YMS】静态字段值非数字, fieldCode={}, value={}", fieldCode, v);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 月台作业参考用时(分钟),按月台/楼层解析;取不到返回 null */
|
||||||
|
public Long resolvePlatformWorkRefMinutes(String windowName, String floor) {
|
||||||
|
return resolveLongValue(CODE_PLATFORM_WORK_REF_MINUTES, windowName, floor);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 园区作业参考用时(分钟),按月台/楼层解析;取不到返回 null */
|
||||||
|
public Long resolveYardWorkRefMinutes(String windowName, String floor) {
|
||||||
|
return resolveLongValue(CODE_YARD_WORK_REF_MINUTES, windowName, floor);
|
||||||
|
}
|
||||||
|
}
|
||||||
+32
@@ -0,0 +1,32 @@
|
|||||||
|
package com.mhd.bi.domain.biWarehouseTransport.repository.mapper;
|
||||||
|
|
||||||
|
import com.mhd.bi.domain.biWarehouseTransport.repository.po.RealCustomerRankPO;
|
||||||
|
import com.mhd.bi.domain.biWarehouseTransport.repository.po.RealWarehouseOrderStatPO;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 仓储运输-真实业务数据 Mapper(跨库查询,与月台监测同方案)
|
||||||
|
*
|
||||||
|
* <p>数据来源:</p>
|
||||||
|
* <ul>
|
||||||
|
* <li>库存订单量:NGWL_TEST_WMS.STOCK_IN_ORDER + NGWL_TEST_WMS.STOCK_OUT_ORDER</li>
|
||||||
|
* <li>今日订单数量:NGWL_TEST_OMS.BUSINESS_DOCUMENT_ORDER</li>
|
||||||
|
* <li>今日运输车次:NGWL_TEST_WLHY.TMS_TRANSPORT_NOTE</li>
|
||||||
|
* <li>客户贡献排名:NGWL_TEST_OMS.BUSINESS_DOCUMENT_ORDER 按货主聚合近半年</li>
|
||||||
|
* </ul>
|
||||||
|
*/
|
||||||
|
public interface BiWarehouseTransportRealDataMapper {
|
||||||
|
|
||||||
|
/** 仓储订单量:本年度 / 本季度 / 本月度(WMS 入库单 + 出库单),全部组织 */
|
||||||
|
RealWarehouseOrderStatPO queryWarehouseOrderStat();
|
||||||
|
|
||||||
|
/** 今日订单数量:OMS 运输业务单,今日创建 */
|
||||||
|
Long countTodayTransportOrders();
|
||||||
|
|
||||||
|
/** 今日运输车次:TMS 运单(运输单),今日创建,一个单 = 一个车次 */
|
||||||
|
Long countTodayTransportTrips();
|
||||||
|
|
||||||
|
/** 客户贡献排名:OMS 运输业务单,近半年按货主聚合订单数,取前 5 名 */
|
||||||
|
List<RealCustomerRankPO> queryCustomerRankTop5();
|
||||||
|
}
|
||||||
+21
@@ -0,0 +1,21 @@
|
|||||||
|
package com.mhd.bi.domain.biWarehouseTransport.repository.po;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 客户贡献排名项(真实数据,来自 OMS 运输业务单)
|
||||||
|
*
|
||||||
|
* <p>统计范围:全部组织,近半年,按货主聚合作业量,取前 5 名。</p>
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class RealCustomerRankPO implements Serializable {
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
/** 货主/客户名称 */
|
||||||
|
private String customerName;
|
||||||
|
|
||||||
|
/** 订单数(单) */
|
||||||
|
private Long customerAmount;
|
||||||
|
}
|
||||||
+25
@@ -0,0 +1,25 @@
|
|||||||
|
package com.mhd.bi.domain.biWarehouseTransport.repository.po;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 仓储订单量统计(真实数据)
|
||||||
|
*
|
||||||
|
* <p>数据来源:WMS 入库业务单 NGWL_TEST_WMS.STOCK_IN_ORDER + 出库业务单 NGWL_TEST_WMS.STOCK_OUT_ORDER</p>
|
||||||
|
* <p>统计范围:全部组织</p>
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class RealWarehouseOrderStatPO implements Serializable {
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
/** 本年度订单数(入库 + 出库) */
|
||||||
|
private Long currentYearOrders;
|
||||||
|
|
||||||
|
/** 本季度订单数(入库 + 出库) */
|
||||||
|
private Long currentQuarterOrders;
|
||||||
|
|
||||||
|
/** 本月度订单数(入库 + 出库) */
|
||||||
|
private Long currentMonthOrders;
|
||||||
|
}
|
||||||
+99
@@ -0,0 +1,99 @@
|
|||||||
|
package com.mhd.bi.domain.biWarehouseTransport.service;
|
||||||
|
|
||||||
|
import com.mhd.bi.domain.biWarehouseTransport.repository.mapper.BiWarehouseTransportRealDataMapper;
|
||||||
|
import com.mhd.bi.domain.biWarehouseTransport.repository.po.RealCustomerRankPO;
|
||||||
|
import com.mhd.bi.domain.biWarehouseTransport.repository.po.RealWarehouseOrderStatPO;
|
||||||
|
import com.mhd.bi.interfaces.facadeApi.biReport.vo.CustomerContributionRankVO;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import javax.annotation.Resource;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 仓储运输-真实业务数据业务层(封装 WMS / OMS / TMS 跨库查询)
|
||||||
|
*
|
||||||
|
* <p>实现方案与「月台监测指标查询」一致:实时查库,查不到或异常返回 0/空,不影响其它字段。</p>
|
||||||
|
*/
|
||||||
|
@Slf4j
|
||||||
|
@Service
|
||||||
|
public class BiWarehouseTransportRealDataService {
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private BiWarehouseTransportRealDataMapper biWarehouseTransportRealDataMapper;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 仓储订单量:本年度 / 本季度 / 本月度(WMS 入库单 + 出库单),全部组织。
|
||||||
|
* 查询失败返回全 0。
|
||||||
|
*/
|
||||||
|
public RealWarehouseOrderStatPO queryWarehouseOrderStat() {
|
||||||
|
RealWarehouseOrderStatPO po = new RealWarehouseOrderStatPO();
|
||||||
|
po.setCurrentYearOrders(0L);
|
||||||
|
po.setCurrentQuarterOrders(0L);
|
||||||
|
po.setCurrentMonthOrders(0L);
|
||||||
|
try {
|
||||||
|
RealWarehouseOrderStatPO row = biWarehouseTransportRealDataMapper.queryWarehouseOrderStat();
|
||||||
|
if (row != null) {
|
||||||
|
po.setCurrentYearOrders(row.getCurrentYearOrders() == null ? 0L : row.getCurrentYearOrders());
|
||||||
|
po.setCurrentQuarterOrders(row.getCurrentQuarterOrders() == null ? 0L : row.getCurrentQuarterOrders());
|
||||||
|
po.setCurrentMonthOrders(row.getCurrentMonthOrders() == null ? 0L : row.getCurrentMonthOrders());
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("【WMS】统计仓储订单量失败: {}", e.getMessage(), e);
|
||||||
|
}
|
||||||
|
return po;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 今日订单数量:OMS 运输业务单,今日创建;查询失败返回 0 */
|
||||||
|
public long countTodayTransportOrders() {
|
||||||
|
try {
|
||||||
|
Long n = biWarehouseTransportRealDataMapper.countTodayTransportOrders();
|
||||||
|
return n == null ? 0L : n;
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("【OMS】统计今日订单数量失败: {}", e.getMessage(), e);
|
||||||
|
return 0L;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 今日运输车次:TMS 运输单,今日创建(一个单 = 一个车次);查询失败返回 0 */
|
||||||
|
public long countTodayTransportTrips() {
|
||||||
|
try {
|
||||||
|
Long n = biWarehouseTransportRealDataMapper.countTodayTransportTrips();
|
||||||
|
return n == null ? 0L : n;
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("【TMS】统计今日运输车次失败: {}", e.getMessage(), e);
|
||||||
|
return 0L;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 客户贡献排名(前 5 名货主,近半年订单数)。
|
||||||
|
* 查询失败返回空数组结构的对象,前端可正常渲染。
|
||||||
|
*/
|
||||||
|
public CustomerContributionRankVO queryCustomerContributionRank() {
|
||||||
|
List<String> names = new ArrayList<>();
|
||||||
|
List<Integer> amounts = new ArrayList<>();
|
||||||
|
try {
|
||||||
|
List<RealCustomerRankPO> rows = biWarehouseTransportRealDataMapper.queryCustomerRankTop5();
|
||||||
|
if (rows != null) {
|
||||||
|
for (RealCustomerRankPO r : rows) {
|
||||||
|
if (r == null || r.getCustomerName() == null) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
names.add(r.getCustomerName());
|
||||||
|
amounts.add(r.getCustomerAmount() == null ? 0 : r.getCustomerAmount().intValue());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("【OMS】查询客户贡献排名失败: {}", e.getMessage(), e);
|
||||||
|
names = new ArrayList<>();
|
||||||
|
amounts = new ArrayList<>();
|
||||||
|
}
|
||||||
|
return CustomerContributionRankVO.builder()
|
||||||
|
.customerName(names.isEmpty() ? Collections.emptyList() : names)
|
||||||
|
.customerAmount(amounts.isEmpty() ? Collections.emptyList() : amounts)
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
}
|
||||||
+107
-1
@@ -1,18 +1,124 @@
|
|||||||
package com.mhd.bi.domain.biWarehouseTransport.service;
|
package com.mhd.bi.domain.biWarehouseTransport.service;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
|
import com.mhd.bi.domain.biSnapshotSync.repository.mapper.BiSnapshotWriteMapper;
|
||||||
import com.mhd.bi.domain.biWarehouseTransport.repository.mapper.BiWarehouseTransportReportMapper;
|
import com.mhd.bi.domain.biWarehouseTransport.repository.mapper.BiWarehouseTransportReportMapper;
|
||||||
|
import com.mhd.bi.domain.biWarehouseTransport.repository.po.RealWarehouseOrderStatPO;
|
||||||
import com.mhd.bi.interfaces.facadeApi.biReport.vo.WarehouseTransportSituationVO;
|
import com.mhd.bi.interfaces.facadeApi.biReport.vo.WarehouseTransportSituationVO;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
import javax.annotation.Resource;
|
import javax.annotation.Resource;
|
||||||
|
import java.util.LinkedHashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 仓储运输:数据访问仅经 Mapper(含 XML 内 SQL 与 Mapper 默认方法组装)。
|
||||||
|
*
|
||||||
|
* <p>实现方案与「月台监测指标查询」完全一致:</p>
|
||||||
|
* <ol>
|
||||||
|
* <li>先读快照最新一条作为基底;</li>
|
||||||
|
* <li>实时查业务库,用真实数据覆盖以下字段:
|
||||||
|
* 本年度订单 / 本季度订单 / 本月度订单(WMS 入库业务单 + 出库业务单)、
|
||||||
|
* 今日订单数量(OMS 运输业务单)、今日运输车次(TMS 运单)、
|
||||||
|
* 客户贡献排名(OMS 近半年前 5 名货主);</li>
|
||||||
|
* <li>对「真实业务数据」计算指纹,与快照最新一条比对:
|
||||||
|
* 未变化则跳过落库直接返回;已变化则覆盖更新快照最新一条,无记录时插入兜底。</li>
|
||||||
|
* </ol>
|
||||||
|
* <p>其余字段(趋势类、周转率、货量等)仍取自快照模板值,不纳入指纹。</p>
|
||||||
|
*/
|
||||||
|
@Slf4j
|
||||||
@Service
|
@Service
|
||||||
public class BiWarehouseTransportReportService {
|
public class BiWarehouseTransportReportService {
|
||||||
|
|
||||||
|
private static final String REMARK_REALTIME = "realtime warehouse-transport";
|
||||||
|
|
||||||
@Resource
|
@Resource
|
||||||
private BiWarehouseTransportReportMapper biWarehouseTransportReportMapper;
|
private BiWarehouseTransportReportMapper biWarehouseTransportReportMapper;
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private BiWarehouseTransportRealDataService biWarehouseTransportRealDataService;
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private BiSnapshotWriteMapper biSnapshotWriteMapper;
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private ObjectMapper objectMapper;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 实时组装仓储运输数据:快照基底 + 实时业务数据覆盖;
|
||||||
|
* 仅当实时业务数据(WMS/OMS/TMS 查出的字段)发生变化时,才覆盖更新
|
||||||
|
* BI_WAREHOUSE_TRANSPORT_SNAPSHOT 快照表最新一条后返回。
|
||||||
|
* 表中尚无记录时插入一条兜底。
|
||||||
|
*/
|
||||||
public WarehouseTransportSituationVO loadLatestWarehouseTransport() {
|
public WarehouseTransportSituationVO loadLatestWarehouseTransport() {
|
||||||
return biWarehouseTransportReportMapper.loadLatestWarehouseTransport();
|
WarehouseTransportSituationVO vo = biWarehouseTransportReportMapper.loadLatestWarehouseTransport();
|
||||||
|
if (vo == null) {
|
||||||
|
vo = new WarehouseTransportSituationVO();
|
||||||
|
}
|
||||||
|
|
||||||
|
// 仓储订单量:WMS 入库业务单 + 出库业务单(本年度 / 本季度 / 本月度,全部组织)
|
||||||
|
RealWarehouseOrderStatPO orderStat = biWarehouseTransportRealDataService.queryWarehouseOrderStat();
|
||||||
|
vo.setCurrentYearOrders(orderStat.getCurrentYearOrders());
|
||||||
|
vo.setCurrentQuarterOrders(orderStat.getCurrentQuarterOrders().intValue());
|
||||||
|
vo.setCurrentMonthOrders(orderStat.getCurrentMonthOrders().intValue());
|
||||||
|
|
||||||
|
// 今日订单数量:OMS 运输业务单
|
||||||
|
vo.setOrderCount((int) biWarehouseTransportRealDataService.countTodayTransportOrders());
|
||||||
|
|
||||||
|
// 今日运输车次:TMS 运输单(一个单 = 一个车次)
|
||||||
|
vo.setTransportTrips((int) biWarehouseTransportRealDataService.countTodayTransportTrips());
|
||||||
|
|
||||||
|
// 客户贡献排名:OMS 运输业务单,近半年前 5 名货主(订单数)
|
||||||
|
vo.setCustomerContributionRank(biWarehouseTransportRealDataService.queryCustomerContributionRank());
|
||||||
|
|
||||||
|
try {
|
||||||
|
String fullJson = objectMapper.writeValueAsString(vo);
|
||||||
|
String fingerprint = realDataFingerprint(vo);
|
||||||
|
|
||||||
|
String latestJson = biWarehouseTransportReportMapper.selectLatestPayloadJson();
|
||||||
|
if (StringUtils.isNotBlank(latestJson)) {
|
||||||
|
WarehouseTransportSituationVO latestVo =
|
||||||
|
objectMapper.readValue(latestJson.trim(), WarehouseTransportSituationVO.class);
|
||||||
|
if (Objects.equals(fingerprint, realDataFingerprint(latestVo))) {
|
||||||
|
log.info("BI 仓储运输实时业务数据未变化,跳过落库");
|
||||||
|
return vo;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int rows = biSnapshotWriteMapper.updateLatestWarehouseTransportSnapshot(fullJson, REMARK_REALTIME);
|
||||||
|
if (rows < 1) {
|
||||||
|
// 表中无最新记录可更新,插入一条兜底
|
||||||
|
biSnapshotWriteMapper.insertWarehouseTransportSnapshot(fullJson, REMARK_REALTIME);
|
||||||
|
}
|
||||||
|
log.info("BI 仓储运输实时数据已落库(覆盖最新, 数据变化), affectedRows={}", rows);
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("BI 仓储运输实时数据落库失败", e);
|
||||||
|
}
|
||||||
|
return vo;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 实时业务数据指纹:仅含实时查库得到的字段(本年度/本季度/本月度订单、今日订单数量、
|
||||||
|
* 今日运输车次、客户贡献排名),用于判断是否需要覆盖更新快照;
|
||||||
|
* 其余字段取自快照模板,不纳入指纹,其变化不会触发更新。
|
||||||
|
*/
|
||||||
|
private String realDataFingerprint(WarehouseTransportSituationVO vo) throws Exception {
|
||||||
|
Map<String, Object> fp = new LinkedHashMap<>();
|
||||||
|
if (vo == null) {
|
||||||
|
return objectMapper.writeValueAsString(fp);
|
||||||
|
}
|
||||||
|
fp.put("currentYearOrders", vo.getCurrentYearOrders());
|
||||||
|
fp.put("currentQuarterOrders", vo.getCurrentQuarterOrders());
|
||||||
|
fp.put("currentMonthOrders", vo.getCurrentMonthOrders());
|
||||||
|
fp.put("orderCount", vo.getOrderCount());
|
||||||
|
fp.put("transportTrips", vo.getTransportTrips());
|
||||||
|
if (vo.getCustomerContributionRank() != null) {
|
||||||
|
fp.put("customerName", vo.getCustomerContributionRank().getCustomerName());
|
||||||
|
fp.put("customerAmount", vo.getCustomerContributionRank().getCustomerAmount());
|
||||||
|
}
|
||||||
|
return objectMapper.writeValueAsString(fp);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+4
-4
@@ -25,14 +25,14 @@ public class ComprehensiveSituationVO {
|
|||||||
@ApiModelProperty("库存周转率,单位:次")
|
@ApiModelProperty("库存周转率,单位:次")
|
||||||
private Integer inventoryTurnover;
|
private Integer inventoryTurnover;
|
||||||
|
|
||||||
@ApiModelProperty("运输订单量,单位:单")
|
@ApiModelProperty("运输订单量,单位:单(实时统计 OMS 运输业务单,本年度、全部组织)")
|
||||||
private Integer orderCount;
|
private Long orderCount;
|
||||||
|
|
||||||
@ApiModelProperty("车辆利用率,单位:%")
|
@ApiModelProperty("车辆利用率,单位:%")
|
||||||
private Double vehicleUtilizationRate;
|
private Double vehicleUtilizationRate;
|
||||||
|
|
||||||
@ApiModelProperty("百公里油耗,单位:升")
|
@ApiModelProperty("百公里油耗,单位:升(实时统计 TMS 运输作业单:总油耗量 ÷ 总重载里程 × 100)")
|
||||||
private Integer fuelConsumptionPerHundredKm;
|
private Double fuelConsumptionPerHundredKm;
|
||||||
|
|
||||||
@ApiModelProperty("运输收入趋势,单位:万元(近半年,按月正序)")
|
@ApiModelProperty("运输收入趋势,单位:万元(近半年,按月正序)")
|
||||||
private List<Integer> incomeTrend;
|
private List<Integer> incomeTrend;
|
||||||
|
|||||||
+1
-1
@@ -19,6 +19,6 @@ public class CustomerContributionRankVO {
|
|||||||
@ApiModelProperty("客户名称")
|
@ApiModelProperty("客户名称")
|
||||||
private List<String> customerName;
|
private List<String> customerName;
|
||||||
|
|
||||||
@ApiModelProperty("客户金额,单位:万元")
|
@ApiModelProperty("客户订单数,单位:单")
|
||||||
private List<Integer> customerAmount;
|
private List<Integer> customerAmount;
|
||||||
}
|
}
|
||||||
|
|||||||
+31
@@ -0,0 +1,31 @@
|
|||||||
|
package com.mhd.bi.interfaces.facadeApi.biReport.vo.platform;
|
||||||
|
|
||||||
|
import io.swagger.annotations.ApiModel;
|
||||||
|
import io.swagger.annotations.ApiModelProperty;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Builder;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
@Builder
|
||||||
|
@NoArgsConstructor
|
||||||
|
@AllArgsConstructor
|
||||||
|
@ApiModel("月台监测-月台作业超时记录")
|
||||||
|
public class OvertimeRecordItemVO {
|
||||||
|
|
||||||
|
@ApiModelProperty("月台名称")
|
||||||
|
private String windowName;
|
||||||
|
|
||||||
|
@ApiModelProperty("车牌号码")
|
||||||
|
private String carNo;
|
||||||
|
|
||||||
|
@ApiModelProperty("超时时长,单位:分钟(= 月台作业时长 - 参考用时)")
|
||||||
|
private Long overtimeMinutes;
|
||||||
|
|
||||||
|
@ApiModelProperty("月台作业参考用时,单位:分钟")
|
||||||
|
private Long refMinutes;
|
||||||
|
|
||||||
|
@ApiModelProperty("月台作业时长,单位:分钟")
|
||||||
|
private Long platformMinutes;
|
||||||
|
}
|
||||||
+3
@@ -25,4 +25,7 @@ public class PlatformOverviewVO {
|
|||||||
|
|
||||||
@ApiModelProperty("今日作业任务,单位:个")
|
@ApiModelProperty("今日作业任务,单位:个")
|
||||||
private Integer todayTasks;
|
private Integer todayTasks;
|
||||||
|
|
||||||
|
@ApiModelProperty("月台周转率,单位:%(今日已出场的记录数 ÷ 今日全部记录数 × 100)")
|
||||||
|
private Double platformTurnoverRate;
|
||||||
}
|
}
|
||||||
|
|||||||
+6
@@ -48,4 +48,10 @@ public class PlatformSurveillanceVO {
|
|||||||
|
|
||||||
@ApiModelProperty("月台告警分布")
|
@ApiModelProperty("月台告警分布")
|
||||||
private List<PlatformAlarmDistItemVO> platformAlarmDistribution;
|
private List<PlatformAlarmDistItemVO> platformAlarmDistribution;
|
||||||
|
|
||||||
|
@ApiModelProperty("任务超时率,单位:%(月台作业时长 > 参考用时的记录数 ÷ 总记录数 × 100)")
|
||||||
|
private Double taskOvertimeRate;
|
||||||
|
|
||||||
|
@ApiModelProperty("月台作业超时记录列表(月台名称 / 车牌号码 / 超时时长分钟)")
|
||||||
|
private List<OvertimeRecordItemVO> overtimeRecords;
|
||||||
}
|
}
|
||||||
|
|||||||
+6
@@ -20,6 +20,12 @@ public class VehicleStatusVO {
|
|||||||
@ApiModelProperty("当前未签到,单位:辆")
|
@ApiModelProperty("当前未签到,单位:辆")
|
||||||
private Integer notCheckedIn;
|
private Integer notCheckedIn;
|
||||||
|
|
||||||
|
@ApiModelProperty("当前等待作业(已预约/已签到/已叫号),单位:辆")
|
||||||
|
private Integer waiting;
|
||||||
|
|
||||||
|
@ApiModelProperty("已签到+已叫号+已过号(FLOW_STATUS IN 2/3/4),单位:辆")
|
||||||
|
private Integer callStatusTotal;
|
||||||
|
|
||||||
@ApiModelProperty("当前作业中,单位:辆")
|
@ApiModelProperty("当前作业中,单位:辆")
|
||||||
private Integer operatingVehicles;
|
private Integer operatingVehicles;
|
||||||
|
|
||||||
|
|||||||
@@ -19,14 +19,14 @@ spring:
|
|||||||
# username: nacos
|
# username: nacos
|
||||||
# password: manhuoda@2023
|
# password: manhuoda@2023
|
||||||
#线上正式环境
|
#线上正式环境
|
||||||
server-addr: 10.102.192.30: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.30:6848
|
server-addr: 10.102.192.31:6848
|
||||||
username: nacos
|
username: nacos
|
||||||
password: manhuoda@2023
|
password: manhuoda@2023
|
||||||
#线上正式环境
|
#线上正式环境
|
||||||
|
|||||||
@@ -0,0 +1,35 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" ?>
|
||||||
|
<!DOCTYPE mapper
|
||||||
|
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||||
|
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||||
|
<mapper namespace="com.mhd.bi.domain.biComprehensive.repository.mapper.BiComprehensiveRealDataMapper">
|
||||||
|
|
||||||
|
<!-- 运输订单量:本年度、全部组织
|
||||||
|
数据来源:OMS 运输业务单 NGWL_TEST_OMS.BUSINESS_DOCUMENT_ORDER
|
||||||
|
统计口径:CREATE_TIME 在本年度;IS_DELETE = 0 表示未删除。
|
||||||
|
注:若该表删除标记实际为 DEL_FLAG,请将下方 IS_DELETE 替换为 DEL_FLAG -->
|
||||||
|
<select id="countCurrentYearTransportOrders" resultType="java.lang.Long">
|
||||||
|
SELECT COUNT(1)
|
||||||
|
FROM NGWL_TEST_OMS.BUSINESS_DOCUMENT_ORDER
|
||||||
|
WHERE CREATE_TIME IS NOT NULL
|
||||||
|
AND TO_CHAR(CREATE_TIME, 'YYYY') = TO_CHAR(SYSDATE, 'YYYY')
|
||||||
|
AND IS_DELETE = 0
|
||||||
|
</select>
|
||||||
|
|
||||||
|
<!-- 百公里油耗:本年度、全部组织,油耗量与重载里程均非空的记录
|
||||||
|
数据来源:TMS 运输作业单 NGWL_TEST_WLHY.TMS_EXPENSE_REPORT
|
||||||
|
返回:总油耗量、总重载里程、参与条数(由 Service 层做除法)
|
||||||
|
公式:百公里油耗 = 总油耗量(FUEL_CONSUMPTION) ÷ 总重载里程(HEAVYLOAD_MILEAGE) × 100 -->
|
||||||
|
<select id="queryCurrentYearFuelStat" resultType="com.mhd.bi.domain.biComprehensive.repository.po.RealFuelStatPO">
|
||||||
|
SELECT
|
||||||
|
SUM(FUEL_CONSUMPTION) AS totalOil,
|
||||||
|
SUM(HEAVYLOAD_MILEAGE) AS totalHeavyMileage,
|
||||||
|
COUNT(1) AS totalCount
|
||||||
|
FROM NGWL_TEST_WLHY.TMS_EXPENSE_REPORT
|
||||||
|
WHERE FUEL_CONSUMPTION IS NOT NULL
|
||||||
|
AND HEAVYLOAD_MILEAGE IS NOT NULL
|
||||||
|
AND CREATE_TIME IS NOT NULL
|
||||||
|
AND TO_CHAR(CREATE_TIME, 'YYYY') = TO_CHAR(SYSDATE, 'YYYY')
|
||||||
|
</select>
|
||||||
|
|
||||||
|
</mapper>
|
||||||
@@ -8,7 +8,10 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
|||||||
plateNumber <- qms_main_business.CAR_NO
|
plateNumber <- qms_main_business.CAR_NO
|
||||||
status <- qms_main_business.FLOW_STATUS
|
status <- qms_main_business.FLOW_STATUS
|
||||||
platformId <- qms_main_business.WINDOW_NAME(叫号月台,主业务表直接有)
|
platformId <- qms_main_business.WINDOW_NAME(叫号月台,主业务表直接有)
|
||||||
platformDuration <- qms_main_business.EXIT_TIME - ENTRY_TIME(分钟)
|
platformDuration <- 月台作业时长(分钟),用「进入月台 / 离开月台」时间:
|
||||||
|
未进入月台(IN_WINDOWS_TIME 为空) -> 0
|
||||||
|
已进入且已离开月台(OUT_WINDOWS_TIME 非空) -> OUT_WINDOWS_TIME - IN_WINDOWS_TIME
|
||||||
|
已进入但未离开月台 -> SYSDATE - IN_WINDOWS_TIME
|
||||||
appointmentTime <- qms_main_business.CREATE_TIME
|
appointmentTime <- qms_main_business.CREATE_TIME
|
||||||
workFloor <- qms_window_info.PLATFORM_FLOOR(按 WINDOW_NAME 关联)
|
workFloor <- qms_window_info.PLATFORM_FLOOR(按 WINDOW_NAME 关联)
|
||||||
-->
|
-->
|
||||||
@@ -18,9 +21,10 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
|||||||
mb.FLOW_STATUS AS status,
|
mb.FLOW_STATUS AS status,
|
||||||
mb.WINDOW_NAME AS platformId,
|
mb.WINDOW_NAME AS platformId,
|
||||||
CASE
|
CASE
|
||||||
WHEN mb.EXIT_TIME IS NOT NULL AND mb.ENTRY_TIME IS NOT NULL
|
WHEN mb.IN_WINDOWS_TIME IS NULL THEN 0
|
||||||
THEN CAST((mb.EXIT_TIME - mb.ENTRY_TIME) * 24 * 60 AS BIGINT)
|
WHEN mb.OUT_WINDOWS_TIME IS NOT NULL
|
||||||
ELSE 0
|
THEN CAST((mb.OUT_WINDOWS_TIME - mb.IN_WINDOWS_TIME) * 24 * 60 AS BIGINT)
|
||||||
|
ELSE CAST((SYSDATE - mb.IN_WINDOWS_TIME) * 24 * 60 AS BIGINT)
|
||||||
END AS platformDuration,
|
END AS platformDuration,
|
||||||
TO_CHAR(mb.CREATE_TIME, 'YYYY-MM-DD HH24:MI:SS') AS appointmentTime,
|
TO_CHAR(mb.CREATE_TIME, 'YYYY-MM-DD HH24:MI:SS') AS appointmentTime,
|
||||||
wi.PLATFORM_FLOOR AS workFloor
|
wi.PLATFORM_FLOOR AS workFloor
|
||||||
@@ -32,6 +36,8 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
|||||||
ORDER BY mb.CREATE_TIME DESC
|
ORDER BY mb.CREATE_TIME DESC
|
||||||
</select>
|
</select>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<!-- 月台概览:totalPlatforms(总条数)、operatingPlatforms(作业状态=占用,JOB_STATUS: 0空闲 1占用) -->
|
<!-- 月台概览:totalPlatforms(总条数)、operatingPlatforms(作业状态=占用,JOB_STATUS: 0空闲 1占用) -->
|
||||||
<select id="queryPlatformOverview" resultType="com.mhd.bi.domain.biPlatformRealData.repository.po.RealPlatformOverviewPO">
|
<select id="queryPlatformOverview" resultType="com.mhd.bi.domain.biPlatformRealData.repository.po.RealPlatformOverviewPO">
|
||||||
SELECT
|
SELECT
|
||||||
@@ -40,35 +46,176 @@ 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') 已预约/已签到/已叫号 且 预约日期 = 今天
|
||||||
|
callStatusTotal 叫号状态合计:已签到 + 已叫号 + 已过号 = FLOW_STATUS IN ('2','3','4') 且 预约日期 = 今天
|
||||||
|
todayExited 今日已出场:FLOW_STATUS = '11' 且 预约日期 = 今天(月台周转率的分子)
|
||||||
|
completedVehicles 今日作业车辆总数:FLOW_STATUS = '11' 且 预约日期 = 今天
|
||||||
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 ('2','3','4') AND TRUNC(TARGET_DATE) = TRUNC(SYSDATE) THEN 1 ELSE 0 END) AS callStatusTotal,
|
||||||
|
SUM(CASE WHEN FLOW_STATUS = '11' AND TRUNC(TARGET_DATE) = TRUNC(SYSDATE) THEN 1 ELSE 0 END) AS todayExited,
|
||||||
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(TARGET_DATE) = 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>
|
||||||
|
|
||||||
<!-- 本月任务量:实际进入时间是本月的 -->
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<!-- ======================= 月台作业参考用时 / 超时相关 =======================
|
||||||
|
参考用时取自 YMS 库静态字段配置表 NGWL_TEST_YMS.QMS_STATIC_FIELD:
|
||||||
|
FIELD_CODE = 'platform_work_ref_minutes'
|
||||||
|
取值优先级:WINDOW(按月台) > FLOOR(按楼层) > GLOBAL(全局)
|
||||||
|
下面用 LEFT JOIN 三级关联 + COALESCE 实现优先级取值,
|
||||||
|
REF_MINUTES 为空表示该月台未配置参考用时,其记录不计入超时率分母 -->
|
||||||
|
|
||||||
|
<!-- 可复用的参考用时关联条件(YMS 库静态字段配置表 QMS_STATIC_FIELD)
|
||||||
|
取值优先级:WINDOW(按月台) > FLOOR(按楼层) > GLOBAL(全局) -->
|
||||||
|
<sql id="joinStaticRef">
|
||||||
|
INNER JOIN NGWL_TEST_YMS.QMS_STATIC_FIELD ref
|
||||||
|
ON ref.FIELD_CODE = #{refCode}
|
||||||
|
AND ref.DEL_FLAG = 1
|
||||||
|
AND ref.FIELD_VALUE IS NOT NULL
|
||||||
|
AND (
|
||||||
|
(ref.SCOPE_TYPE = 'WINDOW' AND ref.SCOPE_CODE = mb.WINDOW_NAME)
|
||||||
|
OR (ref.SCOPE_TYPE = 'FLOOR' AND ref.SCOPE_CODE = wi.PLATFORM_FLOOR)
|
||||||
|
OR (ref.SCOPE_TYPE = 'GLOBAL')
|
||||||
|
)
|
||||||
|
</sql>
|
||||||
|
|
||||||
|
<!-- 今日作业超时统计(通用:月台作业 / 园区作业,由 refCode + 时长表达式区分)
|
||||||
|
分母只计入「能取到参考用时 且 时长两端时间都非空」的记录
|
||||||
|
overtimeCount 超时记录数:作业时长(分钟) > 参考用时
|
||||||
|
totalCount 有效记录总数(分母)
|
||||||
|
超时率 = overtimeCount / totalCount × 100%,由 Service 层计算 -->
|
||||||
|
<select id="queryTodayOvertimeStat" resultType="com.mhd.bi.domain.biPlatformRealData.repository.po.RealOvertimeStatPO">
|
||||||
|
SELECT
|
||||||
|
SUM(CASE WHEN (mb.OUT_WINDOWS_TIME - mb.IN_WINDOWS_TIME) * 24 * 60 > ref.REF_MINUTES
|
||||||
|
THEN 1 ELSE 0 END) AS overtimeCount,
|
||||||
|
COUNT(1) AS totalCount
|
||||||
|
FROM NGWL_TEST_YMS.QMS_MAIN_BUSINESS mb
|
||||||
|
LEFT JOIN NGWL_TEST_YMS.QMS_WINDOW_INFO wi
|
||||||
|
ON wi.WINDOW_NAME = mb.WINDOW_NAME
|
||||||
|
<include refid="joinStaticRef"/>
|
||||||
|
WHERE mb.TARGET_DATE IS NOT NULL
|
||||||
|
AND TRUNC(mb.TARGET_DATE) = TRUNC(SYSDATE)
|
||||||
|
AND mb.IN_WINDOWS_TIME IS NOT NULL
|
||||||
|
AND mb.OUT_WINDOWS_TIME IS NOT NULL
|
||||||
|
</select>
|
||||||
|
|
||||||
|
<!-- 今日园区作业超时统计(时长 = 实际出场 - 实际进入;参考用时 yard_work_ref_minutes)
|
||||||
|
用于计算「园区作业准时率 = 1 - 超时率」 -->
|
||||||
|
<select id="queryTodayYardOvertimeStat" resultType="com.mhd.bi.domain.biPlatformRealData.repository.po.RealOvertimeStatPO">
|
||||||
|
SELECT
|
||||||
|
SUM(CASE WHEN (mb.EXIT_TIME - mb.ENTRY_TIME) * 24 * 60 > ref.REF_MINUTES
|
||||||
|
THEN 1 ELSE 0 END) AS overtimeCount,
|
||||||
|
COUNT(1) AS totalCount
|
||||||
|
FROM NGWL_TEST_YMS.QMS_MAIN_BUSINESS mb
|
||||||
|
LEFT JOIN NGWL_TEST_YMS.QMS_WINDOW_INFO wi
|
||||||
|
ON wi.WINDOW_NAME = mb.WINDOW_NAME
|
||||||
|
<include refid="joinStaticRef"/>
|
||||||
|
WHERE mb.TARGET_DATE IS NOT NULL
|
||||||
|
AND TRUNC(mb.TARGET_DATE) = TRUNC(SYSDATE)
|
||||||
|
AND mb.ENTRY_TIME IS NOT NULL
|
||||||
|
AND mb.EXIT_TIME IS NOT NULL
|
||||||
|
</select>
|
||||||
|
|
||||||
|
<!-- 今日月台作业超时记录列表(月台名称 / 车牌号码 / 超时时长分钟):
|
||||||
|
超时时长 = 月台作业时长 - 参考用时 -->
|
||||||
|
<select id="queryTodayOvertimeList" resultType="com.mhd.bi.domain.biPlatformRealData.repository.po.RealOvertimeRecordPO">
|
||||||
|
SELECT
|
||||||
|
mb.WINDOW_NAME AS windowName,
|
||||||
|
mb.CAR_NO AS carNo,
|
||||||
|
CAST(((mb.OUT_WINDOWS_TIME - mb.IN_WINDOWS_TIME) * 24 * 60 - ref.REF_MINUTES) AS BIGINT) AS overtimeMinutes,
|
||||||
|
ref.REF_MINUTES AS refMinutes,
|
||||||
|
CAST((mb.OUT_WINDOWS_TIME - mb.IN_WINDOWS_TIME) * 24 * 60 AS BIGINT) AS platformMinutes
|
||||||
|
FROM NGWL_TEST_YMS.QMS_MAIN_BUSINESS mb
|
||||||
|
LEFT JOIN NGWL_TEST_YMS.QMS_WINDOW_INFO wi
|
||||||
|
ON wi.WINDOW_NAME = mb.WINDOW_NAME
|
||||||
|
<include refid="joinStaticRef"/>
|
||||||
|
WHERE mb.TARGET_DATE IS NOT NULL
|
||||||
|
AND TRUNC(mb.TARGET_DATE) = TRUNC(SYSDATE)
|
||||||
|
AND mb.IN_WINDOWS_TIME IS NOT NULL
|
||||||
|
AND mb.OUT_WINDOWS_TIME IS NOT NULL
|
||||||
|
AND (mb.OUT_WINDOWS_TIME - mb.IN_WINDOWS_TIME) * 24 * 60 > ref.REF_MINUTES
|
||||||
|
ORDER BY overtimeMinutes DESC
|
||||||
|
</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 过滤 -->
|
<!-- 本月任务平均作业时长 / 完成率统计(统计范围:本月 TARGET_DATE 在当月的记录):
|
||||||
|
totalWorkHours 本月任务作业时长合计(小时),用「进入月台 / 离开月台」时间:
|
||||||
|
未进入月台(IN_WINDOWS_TIME 为空) -> 0
|
||||||
|
已进入且已离开月台(OUT_WINDOWS_TIME 非空) -> OUT_WINDOWS_TIME - IN_WINDOWS_TIME
|
||||||
|
已进入但未离开月台 -> SYSDATE - IN_WINDOWS_TIME
|
||||||
|
completedCount 本月已出场(EXIT_TIME IS NOT NULL)的数量;
|
||||||
|
totalCount 本月预约总数量(作为平均时长的分母)。
|
||||||
|
avgDurationHours 由 Service 层计算 = totalWorkHours ÷ totalCount(任务平均作业时长)
|
||||||
|
-->
|
||||||
|
<select id="queryMonthTaskStats" resultType="com.mhd.bi.domain.biPlatformRealData.repository.po.RealMonthlyTaskDurationPO">
|
||||||
|
SELECT
|
||||||
|
SUM(CASE
|
||||||
|
WHEN IN_WINDOWS_TIME IS NULL THEN 0
|
||||||
|
WHEN OUT_WINDOWS_TIME IS NOT NULL THEN (OUT_WINDOWS_TIME - IN_WINDOWS_TIME) * 24
|
||||||
|
ELSE (SYSDATE - IN_WINDOWS_TIME) * 24
|
||||||
|
END) AS totalWorkHours,
|
||||||
|
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
|
||||||
|
WHERE TARGET_DATE IS NOT NULL
|
||||||
|
AND TO_CHAR(TARGET_DATE, 'YYYY-MM') = TO_CHAR(SYSDATE, 'YYYY-MM')
|
||||||
|
</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,
|
||||||
@@ -80,11 +227,18 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
|||||||
ORDER BY COUNT(1) DESC
|
ORDER BY COUNT(1) DESC
|
||||||
</select>
|
</select>
|
||||||
|
|
||||||
<!-- 月台监控-按楼层统计:楼层从叫号月台 WINDOW_NAME 解析(如 S1-01 / N1-02 -> F1),不依赖字母前缀,只取 - 前面那段的数字
|
<!-- 月台监控-按楼层统计:
|
||||||
platformCount 来自 QMS_WINDOW_INFO;todayReservedVehicles/operatingVehicles 来自 QMS_MAIN_BUSINESS(按 TARGET_DATE=今天) -->
|
floorNo 楼层号,取自月台表 QMS_WINDOW_INFO.PLATFORM_FLOOR
|
||||||
|
platformCount 该楼层月台数量(QMS_WINDOW_INFO)
|
||||||
|
todayReservedVehicles 该楼层今日预约车辆数(按预约时已选的月台/叫号月台关联楼层)
|
||||||
|
operatingVehicles 该楼层当前作业车辆数(FLOW_STATUS IN 5,6,7,8,9,10)
|
||||||
|
avgPlatformMinutes 该楼层月台作业平均时长(分钟)
|
||||||
|
公式:SUM(该楼层有效记录的月台作业时长) ÷ 该楼层有效记录数
|
||||||
|
有效记录:同时有进入月台(IN_WINDOWS_TIME)与离开月台(OUT_WINDOWS_TIME)时间
|
||||||
|
说明:楼层维度以「月台表」为准;车辆预约时若已选月台(WINDOW_NAME 非空)即计入对应楼层。 -->
|
||||||
<select id="queryPlatformFloorStats" resultType="com.mhd.bi.domain.biPlatformRealData.repository.po.RealPlatformFloorStatPO">
|
<select id="queryPlatformFloorStats" resultType="com.mhd.bi.domain.biPlatformRealData.repository.po.RealPlatformFloorStatPO">
|
||||||
SELECT
|
SELECT
|
||||||
'F' || SUBSTR(W.WINDOW_NAME, INSTR(W.WINDOW_NAME,'-')-1, 1) AS floorNo,
|
W.PLATFORM_FLOOR AS floorNo,
|
||||||
COUNT(DISTINCT W.WINDOW_NAME) AS platformCount,
|
COUNT(DISTINCT W.WINDOW_NAME) AS platformCount,
|
||||||
COUNT(DISTINCT CASE
|
COUNT(DISTINCT CASE
|
||||||
WHEN TRUNC(mb.TARGET_DATE) = TRUNC(SYSDATE) THEN mb.CAR_NO
|
WHEN TRUNC(mb.TARGET_DATE) = TRUNC(SYSDATE) THEN mb.CAR_NO
|
||||||
@@ -93,27 +247,102 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
|||||||
WHEN TRUNC(mb.TARGET_DATE) = TRUNC(SYSDATE)
|
WHEN TRUNC(mb.TARGET_DATE) = TRUNC(SYSDATE)
|
||||||
AND mb.FLOW_STATUS IN ('5','6','7','8','9','10')
|
AND mb.FLOW_STATUS IN ('5','6','7','8','9','10')
|
||||||
THEN mb.CAR_NO
|
THEN mb.CAR_NO
|
||||||
END) AS operatingVehicles
|
END) AS operatingVehicles,
|
||||||
|
ROUND(AVG(CASE
|
||||||
|
WHEN mb.IN_WINDOWS_TIME IS NOT NULL AND mb.OUT_WINDOWS_TIME IS NOT NULL
|
||||||
|
THEN (mb.OUT_WINDOWS_TIME - mb.IN_WINDOWS_TIME) * 24 * 60
|
||||||
|
END), 0) AS avgPlatformMinutes
|
||||||
FROM NGWL_TEST_YMS.QMS_WINDOW_INFO W
|
FROM NGWL_TEST_YMS.QMS_WINDOW_INFO W
|
||||||
LEFT JOIN NGWL_TEST_YMS.QMS_MAIN_BUSINESS mb
|
LEFT JOIN NGWL_TEST_YMS.QMS_MAIN_BUSINESS mb
|
||||||
ON mb.WINDOW_NAME = W.WINDOW_NAME
|
ON mb.WINDOW_NAME = W.WINDOW_NAME
|
||||||
WHERE W.WINDOW_NAME LIKE '%-%'
|
WHERE W.PLATFORM_FLOOR IS NOT NULL
|
||||||
GROUP BY SUBSTR(W.WINDOW_NAME, INSTR(W.WINDOW_NAME,'-')-1, 1)
|
GROUP BY W.PLATFORM_FLOOR
|
||||||
ORDER BY 1 DESC
|
ORDER BY W.PLATFORM_FLOOR DESC
|
||||||
</select>
|
</select>
|
||||||
|
|
||||||
<!-- 任务负荷(今日 24 小时时段):按 EXTRACT(HOUR FROM ENTRY_TIME) 统计 -->
|
|
||||||
|
|
||||||
|
<!-- 任务类型统计(来自 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>
|
||||||
|
|
||||||
|
<!-- 今日平均作业时长(效率统计-本日):
|
||||||
|
avgPlatformDurationHours 月台作业平均时长(小时)
|
||||||
|
统计范围:今日预约记录中「同时有进入月台时间(IN_WINDOWS_TIME)和离开月台时间(OUT_WINDOWS_TIME)」的记录
|
||||||
|
公式:AVG((OUT_WINDOWS_TIME - IN_WINDOWS_TIME) * 24)
|
||||||
|
avgYardDurationHours 园区平均时长(小时)
|
||||||
|
统计范围:今日预约记录中「同时有实际进入时间(ENTRY_TIME)和实际出场时间(EXIT_TIME)」的记录
|
||||||
|
公式:AVG((EXIT_TIME - ENTRY_TIME) * 24) -->
|
||||||
|
<select id="queryTodayAvgDuration" resultType="com.mhd.bi.domain.biPlatformRealData.repository.po.RealTodayAvgDurationPO">
|
||||||
|
SELECT
|
||||||
|
AVG(CASE WHEN IN_WINDOWS_TIME IS NOT NULL AND OUT_WINDOWS_TIME IS NOT NULL
|
||||||
|
THEN (OUT_WINDOWS_TIME - IN_WINDOWS_TIME) * 24
|
||||||
|
END) AS avgPlatformDurationHours,
|
||||||
|
AVG(CASE WHEN ENTRY_TIME IS NOT NULL AND EXIT_TIME IS NOT NULL
|
||||||
|
THEN (EXIT_TIME - ENTRY_TIME) * 24
|
||||||
|
END) AS avgYardDurationHours
|
||||||
|
FROM NGWL_TEST_YMS.QMS_MAIN_BUSINESS
|
||||||
|
WHERE TARGET_DATE IS NOT NULL
|
||||||
|
AND TRUNC(TARGET_DATE) = TRUNC(SYSDATE)
|
||||||
|
</select>
|
||||||
|
|
||||||
|
<!-- 近半年「平均作业时长」趋势(按月分组,取最近 6 个月):
|
||||||
|
|
||||||
|
taskCount 该月任务数(预约记录数,作为平均时长的分母);
|
||||||
|
platformWorkHours 该月月台作业时长合计(小时):
|
||||||
|
未进入月台(IN_WINDOWS_TIME 为空) -> 0
|
||||||
|
已进入且已离开月台(OUT_WINDOWS_TIME 非空) -> OUT_WINDOWS_TIME - IN_WINDOWS_TIME
|
||||||
|
已进入但未离开月台 -> SYSDATE - IN_WINDOWS_TIME
|
||||||
|
yardWorkHours 该月园区作业时长合计(小时):
|
||||||
|
未进场(ENTRY_TIME 为空) -> 0
|
||||||
|
已进场且已出场(EXIT_TIME 非空) -> EXIT_TIME - ENTRY_TIME
|
||||||
|
已进场但未出场 -> SYSDATE - ENTRY_TIME
|
||||||
|
平均时长由 Service 层计算 = 时长合计 ÷ taskCount -->
|
||||||
|
<select id="queryMonthlyAvgDuration" resultType="com.mhd.bi.domain.biPlatformRealData.repository.po.RealMonthlyAvgDurationPO">
|
||||||
|
SELECT
|
||||||
|
TO_CHAR(TARGET_DATE, 'YYYY-MM') AS monthOfYear,
|
||||||
|
COUNT(1) AS taskCount,
|
||||||
|
SUM(CASE
|
||||||
|
WHEN IN_WINDOWS_TIME IS NULL THEN 0
|
||||||
|
WHEN OUT_WINDOWS_TIME IS NOT NULL THEN (OUT_WINDOWS_TIME - IN_WINDOWS_TIME) * 24
|
||||||
|
ELSE (SYSDATE - IN_WINDOWS_TIME) * 24
|
||||||
|
END) AS platformWorkHours,
|
||||||
|
SUM(CASE
|
||||||
|
WHEN ENTRY_TIME IS NULL THEN 0
|
||||||
|
WHEN EXIT_TIME IS NOT NULL THEN (EXIT_TIME - ENTRY_TIME) * 24
|
||||||
|
ELSE (SYSDATE - ENTRY_TIME) * 24
|
||||||
|
END) AS yardWorkHours
|
||||||
|
FROM NGWL_TEST_YMS.QMS_MAIN_BUSINESS
|
||||||
|
WHERE TARGET_DATE IS NOT NULL
|
||||||
|
AND TARGET_DATE >= ADD_MONTHS(TRUNC(SYSDATE, 'MM'), -5)
|
||||||
|
GROUP BY TO_CHAR(TARGET_DATE, 'YYYY-MM')
|
||||||
|
ORDER BY 1
|
||||||
|
</select>
|
||||||
|
|
||||||
|
<!-- 小时趋势(今日,每 2 小时分组统计一次):
|
||||||
|
按车辆进入月台时间 IN_WINDOWS_TIME 分桶,桶为 0,2,4,...,22 -->
|
||||||
<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
|
||||||
EXTRACT(HOUR FROM ENTRY_TIME) AS hourOfDay,
|
FLOOR(EXTRACT(HOUR FROM IN_WINDOWS_TIME) / 2) * 2 AS hourOfDay,
|
||||||
COUNT(1) AS taskCount
|
COUNT(1) AS taskCount
|
||||||
FROM NGWL_TEST_YMS.QMS_MAIN_BUSINESS
|
FROM NGWL_TEST_YMS.QMS_MAIN_BUSINESS
|
||||||
WHERE ENTRY_TIME IS NOT NULL
|
WHERE IN_WINDOWS_TIME IS NOT NULL
|
||||||
AND TRUNC(ENTRY_TIME) = TRUNC(SYSDATE)
|
AND TRUNC(IN_WINDOWS_TIME) = TRUNC(SYSDATE)
|
||||||
GROUP BY EXTRACT(HOUR FROM ENTRY_TIME)
|
GROUP BY FLOOR(EXTRACT(HOUR FROM IN_WINDOWS_TIME) / 2) * 2
|
||||||
ORDER BY EXTRACT(HOUR FROM ENTRY_TIME)
|
ORDER BY 1
|
||||||
</select>
|
</select>
|
||||||
|
|
||||||
|
|
||||||
<!-- 月台管理列表:查询 YMS qms_window_info 月台/鹤位窗口
|
<!-- 月台管理列表:查询 YMS qms_window_info 月台/鹤位窗口
|
||||||
机构名称 deptName <- sys_dept.DEPT_NAME(d.dept_id = a.ORG_NO 关联)
|
机构名称 deptName <- sys_dept.DEPT_NAME(d.dept_id = a.ORG_NO 关联)
|
||||||
鹤位屏名称 berrNames <- qms_window_berr(WINDOW_ID/BERR_ID) join qms_berr_config(ID/BERR_NAME),WM_CONCAT 拼接
|
鹤位屏名称 berrNames <- qms_window_berr(WINDOW_ID/BERR_ID) join qms_berr_config(ID/BERR_NAME),WM_CONCAT 拼接
|
||||||
|
|||||||
@@ -8,11 +8,33 @@
|
|||||||
values (#{payloadJson}, SYSDATE, SYSDATE, 1, #{remark})
|
values (#{payloadJson}, SYSDATE, SYSDATE, 1, #{remark})
|
||||||
</insert>
|
</insert>
|
||||||
|
|
||||||
|
<!-- 覆盖更新综合态势快照最新一条(实时组装后落库,同月台监测) -->
|
||||||
|
<update id="updateLatestComprehensiveSnapshot">
|
||||||
|
update NGWL_TEST_BI.BI_COMPREHENSIVE_SNAPSHOT
|
||||||
|
set PAYLOAD_JSON = #{payloadJson},
|
||||||
|
UPDATE_TIME = SYSDATE,
|
||||||
|
REMARK = #{remark}
|
||||||
|
where DEL_FLAG = 1
|
||||||
|
and ID = (select max(t.ID) from NGWL_TEST_BI.BI_COMPREHENSIVE_SNAPSHOT t where t.DEL_FLAG = 1)
|
||||||
|
</update>
|
||||||
|
|
||||||
|
|
||||||
<insert id="insertWarehouseTransportSnapshot">
|
<insert id="insertWarehouseTransportSnapshot">
|
||||||
insert into NGWL_TEST_BI.BI_WAREHOUSE_TRANSPORT_SNAPSHOT (PAYLOAD_JSON, CREATE_TIME, UPDATE_TIME, DEL_FLAG, REMARK)
|
insert into NGWL_TEST_BI.BI_WAREHOUSE_TRANSPORT_SNAPSHOT (PAYLOAD_JSON, CREATE_TIME, UPDATE_TIME, DEL_FLAG, REMARK)
|
||||||
values (#{payloadJson}, SYSDATE, SYSDATE, 1, #{remark})
|
values (#{payloadJson}, SYSDATE, SYSDATE, 1, #{remark})
|
||||||
</insert>
|
</insert>
|
||||||
|
|
||||||
|
<!-- 覆盖更新仓储运输快照最新一条(实时组装后落库,同月台监测) -->
|
||||||
|
<update id="updateLatestWarehouseTransportSnapshot">
|
||||||
|
update NGWL_TEST_BI.BI_WAREHOUSE_TRANSPORT_SNAPSHOT
|
||||||
|
set PAYLOAD_JSON = #{payloadJson},
|
||||||
|
UPDATE_TIME = SYSDATE,
|
||||||
|
REMARK = #{remark}
|
||||||
|
where DEL_FLAG = 1
|
||||||
|
and ID = (select max(t.ID) from NGWL_TEST_BI.BI_WAREHOUSE_TRANSPORT_SNAPSHOT t where t.DEL_FLAG = 1)
|
||||||
|
</update>
|
||||||
|
|
||||||
|
|
||||||
<insert id="insertPlatformSurveillanceSnapshot">
|
<insert id="insertPlatformSurveillanceSnapshot">
|
||||||
insert into NGWL_TEST_BI.BI_PLATFORM_SURVEILLANCE_SNAPSHOT (PAYLOAD_JSON, CREATE_TIME, UPDATE_TIME, DEL_FLAG, REMARK)
|
insert into NGWL_TEST_BI.BI_PLATFORM_SURVEILLANCE_SNAPSHOT (PAYLOAD_JSON, CREATE_TIME, UPDATE_TIME, DEL_FLAG, REMARK)
|
||||||
values (#{payloadJson}, SYSDATE, SYSDATE, 1, #{remark})
|
values (#{payloadJson}, SYSDATE, SYSDATE, 1, #{remark})
|
||||||
|
|||||||
@@ -0,0 +1,52 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" ?>
|
||||||
|
<!DOCTYPE mapper
|
||||||
|
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||||
|
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||||
|
<mapper namespace="com.mhd.bi.domain.biStaticField.repository.mapper.BiStaticFieldMapper">
|
||||||
|
|
||||||
|
<!-- 业务静态字段配置(YMS 库):按字段编码查询全部有效配置
|
||||||
|
含 GLOBAL / FLOOR / WINDOW 各作用域,由程序按「WINDOW > FLOOR > GLOBAL」优先级取值 -->
|
||||||
|
<select id="queryByCode" resultType="com.mhd.bi.domain.biStaticField.repository.po.BiStaticFieldPO">
|
||||||
|
SELECT
|
||||||
|
FIELD_CODE AS fieldCode,
|
||||||
|
FIELD_NAME AS fieldName,
|
||||||
|
SCOPE_TYPE AS scopeType,
|
||||||
|
SCOPE_CODE AS scopeCode,
|
||||||
|
FIELD_VALUE AS fieldValue,
|
||||||
|
UNIT AS unit
|
||||||
|
FROM NGWL_TEST_YMS.QMS_STATIC_FIELD
|
||||||
|
WHERE DEL_FLAG = 1
|
||||||
|
AND FIELD_CODE = #{fieldCode}
|
||||||
|
</select>
|
||||||
|
|
||||||
|
<!-- 批量按字段编码查询 -->
|
||||||
|
<select id="queryByCodes" resultType="com.mhd.bi.domain.biStaticField.repository.po.BiStaticFieldPO">
|
||||||
|
SELECT
|
||||||
|
FIELD_CODE AS fieldCode,
|
||||||
|
FIELD_NAME AS fieldName,
|
||||||
|
SCOPE_TYPE AS scopeType,
|
||||||
|
SCOPE_CODE AS scopeCode,
|
||||||
|
FIELD_VALUE AS fieldValue,
|
||||||
|
UNIT AS unit
|
||||||
|
FROM NGWL_TEST_YMS.QMS_STATIC_FIELD
|
||||||
|
WHERE DEL_FLAG = 1
|
||||||
|
AND FIELD_CODE IN
|
||||||
|
<foreach collection="fieldCodes" item="c" open="(" separator="," close=")">
|
||||||
|
#{c}
|
||||||
|
</foreach>
|
||||||
|
</select>
|
||||||
|
|
||||||
|
<!-- 查询全部有效配置 -->
|
||||||
|
<select id="queryAll" resultType="com.mhd.bi.domain.biStaticField.repository.po.BiStaticFieldPO">
|
||||||
|
SELECT
|
||||||
|
FIELD_CODE AS fieldCode,
|
||||||
|
FIELD_NAME AS fieldName,
|
||||||
|
SCOPE_TYPE AS scopeType,
|
||||||
|
SCOPE_CODE AS scopeCode,
|
||||||
|
FIELD_VALUE AS fieldValue,
|
||||||
|
UNIT AS unit
|
||||||
|
FROM NGWL_TEST_YMS.QMS_STATIC_FIELD
|
||||||
|
WHERE DEL_FLAG = 1
|
||||||
|
</select>
|
||||||
|
|
||||||
|
</mapper>
|
||||||
+77
@@ -0,0 +1,77 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" ?>
|
||||||
|
<!DOCTYPE mapper
|
||||||
|
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||||
|
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||||
|
<mapper namespace="com.mhd.bi.domain.biWarehouseTransport.repository.mapper.BiWarehouseTransportRealDataMapper">
|
||||||
|
|
||||||
|
<!-- 仓储订单量:本年度 / 本季度 / 本月度 = 入库业务单 + 出库业务单 数量合计
|
||||||
|
统计范围:全部组织
|
||||||
|
口径:del_flag = 1(有效);本季度用「月份向上取整 / 3」判断同季度 -->
|
||||||
|
|
||||||
|
<select id="queryWarehouseOrderStat" resultType="com.mhd.bi.domain.biWarehouseTransport.repository.po.RealWarehouseOrderStatPO">
|
||||||
|
SELECT
|
||||||
|
(SELECT NVL(SUM(c), 0) FROM (
|
||||||
|
SELECT COUNT(1) AS c FROM NGWL_TEST_WMS.STOCK_IN_ORDER
|
||||||
|
WHERE del_flag = 1 AND TO_CHAR(CREATE_TIME, 'YYYY') = TO_CHAR(SYSDATE, 'YYYY')
|
||||||
|
UNION ALL
|
||||||
|
SELECT COUNT(1) FROM NGWL_TEST_WMS.STOCK_OUT_ORDER
|
||||||
|
WHERE del_flag = 1 AND TO_CHAR(CREATE_TIME, 'YYYY') = TO_CHAR(SYSDATE, 'YYYY')
|
||||||
|
)) AS currentYearOrders,
|
||||||
|
(SELECT NVL(SUM(c), 0) FROM (
|
||||||
|
SELECT COUNT(1) AS c FROM NGWL_TEST_WMS.STOCK_IN_ORDER
|
||||||
|
WHERE del_flag = 1 AND TO_CHAR(CREATE_TIME, 'YYYY') = TO_CHAR(SYSDATE, 'YYYY')
|
||||||
|
AND CEIL(TO_NUMBER(TO_CHAR(CREATE_TIME, 'MM')) / 3) = CEIL(TO_NUMBER(TO_CHAR(SYSDATE, 'MM')) / 3)
|
||||||
|
UNION ALL
|
||||||
|
SELECT COUNT(1) FROM NGWL_TEST_WMS.STOCK_OUT_ORDER
|
||||||
|
WHERE del_flag = 1 AND TO_CHAR(CREATE_TIME, 'YYYY') = TO_CHAR(SYSDATE, 'YYYY')
|
||||||
|
AND CEIL(TO_NUMBER(TO_CHAR(CREATE_TIME, 'MM')) / 3) = CEIL(TO_NUMBER(TO_CHAR(SYSDATE, 'MM')) / 3)
|
||||||
|
)) AS currentQuarterOrders,
|
||||||
|
(SELECT NVL(SUM(c), 0) FROM (
|
||||||
|
SELECT COUNT(1) AS c FROM NGWL_TEST_WMS.STOCK_IN_ORDER
|
||||||
|
WHERE del_flag = 1 AND TO_CHAR(CREATE_TIME, 'YYYY-MM') = TO_CHAR(SYSDATE, 'YYYY-MM')
|
||||||
|
UNION ALL
|
||||||
|
SELECT COUNT(1) FROM NGWL_TEST_WMS.STOCK_OUT_ORDER
|
||||||
|
WHERE del_flag = 1 AND TO_CHAR(CREATE_TIME, 'YYYY-MM') = TO_CHAR(SYSDATE, 'YYYY-MM')
|
||||||
|
)) AS currentMonthOrders
|
||||||
|
FROM DUAL
|
||||||
|
</select>
|
||||||
|
|
||||||
|
<!-- 今日订单数量:OMS 运输业务单,今日创建,全部组织 -->
|
||||||
|
<select id="countTodayTransportOrders" resultType="java.lang.Long">
|
||||||
|
SELECT COUNT(1)
|
||||||
|
FROM NGWL_TEST_OMS.BUSINESS_DOCUMENT_ORDER
|
||||||
|
WHERE CREATE_TIME IS NOT NULL
|
||||||
|
AND TRUNC(CREATE_TIME) = TRUNC(SYSDATE)
|
||||||
|
AND IS_DELETE = 0
|
||||||
|
</select>
|
||||||
|
|
||||||
|
<!-- 今日运输车次:TMS 运输单(运单),今日创建,全部组织
|
||||||
|
口径:一个单 = 一个车次,直接按单计数(不做单号去重,避免单号为空被漏计) -->
|
||||||
|
<select id="countTodayTransportTrips" resultType="java.lang.Long">
|
||||||
|
SELECT COUNT(1)
|
||||||
|
FROM NGWL_TEST_WLHY.TMS_TRANSPORT_NOTE
|
||||||
|
WHERE CREATE_TIME IS NOT NULL
|
||||||
|
AND TRUNC(CREATE_TIME) = TRUNC(SYSDATE)
|
||||||
|
AND (IS_DELETE IS NULL OR IS_DELETE = 0)
|
||||||
|
</select>
|
||||||
|
|
||||||
|
<!-- 客户贡献排名:OMS 运输业务单,近半年按货主(APPOINT_SHIPPER)聚合订单数,取前 5 名
|
||||||
|
统计范围:全部组织;口径:一个单 = 一单,COUNT(1) -->
|
||||||
|
<select id="queryCustomerRankTop5" resultType="com.mhd.bi.domain.biWarehouseTransport.repository.po.RealCustomerRankPO">
|
||||||
|
SELECT * FROM (
|
||||||
|
SELECT
|
||||||
|
APPOINT_SHIPPER AS customerName,
|
||||||
|
CEIL(COUNT(1)) AS customerAmount
|
||||||
|
FROM NGWL_TEST_OMS.BUSINESS_DOCUMENT_ORDER
|
||||||
|
WHERE CREATE_TIME IS NOT NULL
|
||||||
|
AND CREATE_TIME >= ADD_MONTHS(TRUNC(SYSDATE, 'MM'), -5)
|
||||||
|
AND IS_DELETE = 0
|
||||||
|
AND APPOINT_SHIPPER IS NOT NULL
|
||||||
|
AND APPOINT_SHIPPER != ''
|
||||||
|
GROUP BY APPOINT_SHIPPER
|
||||||
|
ORDER BY COUNT(1) DESC
|
||||||
|
)
|
||||||
|
WHERE ROWNUM <= 5
|
||||||
|
</select>
|
||||||
|
|
||||||
|
</mapper>
|
||||||
+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.31:8012", configuration = FeignAutoConfiguration.class)
|
||||||
public interface ThirdPartyServiceFeign {
|
public interface ThirdPartyServiceFeign {
|
||||||
|
|
||||||
//查询当前组织所有三方接口信息
|
//查询当前组织所有三方接口信息
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
+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
|
||||||
-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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
+554
@@ -0,0 +1,554 @@
|
|||||||
|
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.exception.ServiceException;
|
||||||
|
import com.mhd.common.core.web.domain.AjaxResult;
|
||||||
|
import com.mhd.common.security.utils.SecurityUtils;
|
||||||
|
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.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.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.stream.Collectors;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 运输业务单「订单调整」应用服务
|
||||||
|
*
|
||||||
|
* 规则(定稿):
|
||||||
|
* 1. 每次调整都生成:1 条主记录 + 1 条明细快照
|
||||||
|
* 2. 费用数据源 = 前端回传的费用明细 business_order_account(feeDetailList);
|
||||||
|
* 主表金额 deliveryFreight 为其 amount 合计(冗余汇总,后端自动算)。
|
||||||
|
* 3. 是否需审核:一旦任一「金额」发生变化
|
||||||
|
* = feeDetailList 明细 amount 变化,或主表金额列变化 -> 走业务主管审核;
|
||||||
|
* 否则(仅改非金额字段) -> 直通。
|
||||||
|
* 4. 涉及金额提交 -> 仅把业务单 review_status 置为「调整待审核(3)」;主记录 AUDIT_STATUS=0(待审核);
|
||||||
|
* 不更新业务单数据,不影响其它状态(order_status / execute_status 不动)。
|
||||||
|
* 5. 审核通过 -> 覆盖业务单(金额) + 替换费用明细;review_status 一律置为 1(已审核),
|
||||||
|
* 不影响 order_status / execute_status。
|
||||||
|
* 审核驳回 -> 不更新业务单数据,review_status 还原为调整前值(主记录 before_review_status),可再次调整。
|
||||||
|
* 6. 直通(未改金额) -> 覆盖业务单可编辑字段 + deliveryFreight(明细合计),并替换 business_order_account
|
||||||
|
* (逻辑删旧 is_delete=1 + 插新 is_delete=0);不改动任何审核/执行状态。
|
||||||
|
* 7. 前端以 amountChanged 告知是否改金额(默认前端判定);未传时后端兜底比对。
|
||||||
|
*
|
||||||
|
* 说明: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; // 调整记录:驳回
|
||||||
|
|
||||||
|
/** 主表金额(费用)字段,任一变化触发审核 */
|
||||||
|
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");
|
||||||
|
|
||||||
|
/** 不允许被前端调整覆盖的系统字段 */
|
||||||
|
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", "adjustStatus",
|
||||||
|
"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 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 则视为保持库中不变
|
||||||
|
List<BusinessOrderAccount> newFeeList = dto.getFeeDetailList();
|
||||||
|
|
||||||
|
// 3. 生成"调整后"业务单对象:DB原值 + 前端可编辑字段覆盖(忽略null)
|
||||||
|
BusinessDocumentOrder afterOrder = buildAfterOrder(dbOrder, front);
|
||||||
|
|
||||||
|
// 4. 若提供了费用明细,则 deliveryFreight(合计)=明细 amount 之和,并联动到 afterOrder
|
||||||
|
boolean hasFeeDetail = newFeeList != null && !newFeeList.isEmpty();
|
||||||
|
if (hasFeeDetail) {
|
||||||
|
BigDecimal sum = sumAmount(newFeeList);
|
||||||
|
afterOrder.setDeliveryFreight(sum);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 5. 判定是否修改了金额:以前端 amountChanged 为准(前端整单回传已自行判定);
|
||||||
|
// 若前端未传则后端兜底比对(主表金额列 或 明细 amount 变化)
|
||||||
|
boolean amountChanged;
|
||||||
|
if (dto.getAmountChanged() != null) {
|
||||||
|
amountChanged = dto.getAmountChanged();
|
||||||
|
} else {
|
||||||
|
amountChanged = isAmountChanged(dbOrder, front, hasFeeDetail, dbFeeList, newFeeList);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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(3L); // 调整待审核
|
||||||
|
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用)
|
||||||
|
*/
|
||||||
|
public List<BusinessDocumentOrderAdjustRecordDTO> listAdjustRecordByOrder(Long orderId) {
|
||||||
|
BusinessDocumentOrderAdjustQueryDTO query = new BusinessDocumentOrderAdjustQueryDTO();
|
||||||
|
query.setOrderId(orderId);
|
||||||
|
return listAdjustRecord(query);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 调整记录详情(主记录 + 调整后明细快照)
|
||||||
|
*/
|
||||||
|
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.setAuditBy(auditBy);
|
||||||
|
adjust.setAuditByName(auditByName);
|
||||||
|
adjust.setAuditTime(now);
|
||||||
|
adjust.setAuditRemark(auditDTO.getAuditRemark());
|
||||||
|
adjust.setUpdateBy(auditBy);
|
||||||
|
adjust.setUpdateTime(now);
|
||||||
|
adjustMapper.updateById(adjust);
|
||||||
|
|
||||||
|
// 驳回:不更新业务单数据,仅把 review_status 还原为调整前值(不影响其它状态)
|
||||||
|
BusinessDocumentOrder statusOnly = new BusinessDocumentOrder();
|
||||||
|
statusOnly.setId(adjust.getOrderId());
|
||||||
|
statusOnly.setReviewStatus(adjust.getBeforeReviewStatus() == null ? 0L : adjust.getBeforeReviewStatus());
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
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) 主表金额列比对
|
||||||
|
boolean mainChanged = FEE_FIELDS.stream().anyMatch(field -> {
|
||||||
|
Object newVal = BeanUtil.getFieldValue(front, field);
|
||||||
|
if (newVal == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
Object oldVal = BeanUtil.getFieldValue(dbOrder, field);
|
||||||
|
BigDecimal old = oldVal == null ? BigDecimal.ZERO : (BigDecimal) oldVal;
|
||||||
|
BigDecimal now = (BigDecimal) newVal;
|
||||||
|
return old.compareTo(now) != 0;
|
||||||
|
});
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
log.info("业务单[{}]调整完成,关联执行单[{}]。如需回写TMS请接入TMS改费Feign。", goodsNumber,
|
||||||
|
executeOrders.stream().map(ExecuteOrder::getGoodsNumber).collect(Collectors.toList()));
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("同步TMS失败,不影响主流程", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+6
-5
@@ -46,9 +46,6 @@ 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;
|
||||||
|
|
||||||
@@ -355,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("仓库不存在,请重新选择");
|
||||||
}
|
}
|
||||||
|
|||||||
+4
-1
@@ -659,7 +659,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-调整待审核")
|
||||||
private Long reviewStatus;
|
private Long reviewStatus;
|
||||||
|
|
||||||
@ApiModelProperty("审核时间")
|
@ApiModelProperty("审核时间")
|
||||||
@@ -825,4 +825,7 @@ public class BusinessDocumentOrder extends BaseVOEntity{
|
|||||||
@ApiModelProperty("车次")
|
@ApiModelProperty("车次")
|
||||||
@Excel(name = "车次")
|
@Excel(name = "车次")
|
||||||
private String shuttleNo;
|
private String shuttleNo;
|
||||||
|
|
||||||
|
@ApiModelProperty("业务单调整状态 0-无 1-调整待审核 2-调整驳回 3-调整已通过")
|
||||||
|
private Integer adjustStatus;
|
||||||
}
|
}
|
||||||
|
|||||||
+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());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
+93
@@ -0,0 +1,93 @@
|
|||||||
|
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 io.swagger.annotations.ApiModelProperty;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
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("调整时间")
|
||||||
|
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("审核时间")
|
||||||
|
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("创建时间")
|
||||||
|
private Date createTime;
|
||||||
|
|
||||||
|
@ApiModelProperty("更新人")
|
||||||
|
private String updateBy;
|
||||||
|
|
||||||
|
@ApiModelProperty("更新人姓名")
|
||||||
|
private String updateName;
|
||||||
|
|
||||||
|
@ApiModelProperty("更新时间")
|
||||||
|
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> {
|
||||||
|
}
|
||||||
+173
@@ -0,0 +1,173 @@
|
|||||||
|
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 io.swagger.annotations.ApiModelProperty;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
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)
|
||||||
|
private Long id;
|
||||||
|
|
||||||
|
@ApiModelProperty("关联调整主记录ID")
|
||||||
|
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("装货时间")
|
||||||
|
private Date loadingDate;
|
||||||
|
|
||||||
|
@ApiModelProperty("卸货地")
|
||||||
|
private String unloadName;
|
||||||
|
|
||||||
|
@ApiModelProperty("卸货地址")
|
||||||
|
private String unloadAddress;
|
||||||
|
|
||||||
|
@ApiModelProperty("卸货时间")
|
||||||
|
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("单据日期")
|
||||||
|
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("创建时间")
|
||||||
|
private Date createTime;
|
||||||
|
|
||||||
|
@ApiModelProperty("更新人")
|
||||||
|
private String updateBy;
|
||||||
|
|
||||||
|
@ApiModelProperty("更新时间")
|
||||||
|
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;
|
|
||||||
}
|
}
|
||||||
-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;
|
|
||||||
}
|
}
|
||||||
-17
@@ -513,21 +513,4 @@ public class ExecutionStockInOrderDO extends BaseVOEntity {
|
|||||||
private String businessPriceWay;
|
private String businessPriceWay;
|
||||||
@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;
|
|
||||||
}
|
}
|
||||||
-17
@@ -510,21 +510,4 @@ public class ExecutionStockInOrderDTO extends ExecutionStockInOrderBaseDTO {
|
|||||||
private String businessPriceWay;
|
private String businessPriceWay;
|
||||||
@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;
|
|
||||||
}
|
}
|
||||||
+1
-18
@@ -263,16 +263,7 @@ public class ExecutionStockInOrderApplicationService {
|
|||||||
*/
|
*/
|
||||||
public ExecutionStockInOrderPO getInfo(Long inOrderId)
|
public ExecutionStockInOrderPO getInfo(Long inOrderId)
|
||||||
{
|
{
|
||||||
return getInfo(inOrderId, false);
|
ExecutionStockInOrderPO info = stockInOrderDomainService.getInfo(inOrderId);
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取入库执行单详情(getReverseAuditInfo 归档详情复用)
|
|
||||||
* @param archive true-查询【已反审】tab 归档数据
|
|
||||||
*/
|
|
||||||
public ExecutionStockInOrderPO getInfo(Long inOrderId, boolean archive)
|
|
||||||
{
|
|
||||||
ExecutionStockInOrderPO info = stockInOrderDomainService.getInfo(inOrderId, archive);
|
|
||||||
String userNcCode = reservationStockInOrderMapper.getUserNcCode(info.getShipperId());
|
String userNcCode = reservationStockInOrderMapper.getUserNcCode(info.getShipperId());
|
||||||
info.setKhdm(userNcCode);
|
info.setKhdm(userNcCode);
|
||||||
List<ExecutionInMaterialDetailPO> materialDetailList = info.getMaterialDetailList();
|
List<ExecutionInMaterialDetailPO> materialDetailList = info.getMaterialDetailList();
|
||||||
@@ -285,14 +276,6 @@ public class ExecutionStockInOrderApplicationService {
|
|||||||
return info;
|
return info;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 查询入库执行单【已反审】tab 归档详情(已软删+已反审标记的数据,含软删明细)
|
|
||||||
*/
|
|
||||||
public ExecutionStockInOrderPO getReverseAuditInfo(Long inOrderId)
|
|
||||||
{
|
|
||||||
return getInfo(inOrderId, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
-17
@@ -314,31 +314,14 @@ public class ExecutionStockInOrderDomainService {
|
|||||||
* 获取入库单详细信息
|
* 获取入库单详细信息
|
||||||
*/
|
*/
|
||||||
public ExecutionStockInOrderPO getInfo(Long inOrderId)
|
public ExecutionStockInOrderPO getInfo(Long inOrderId)
|
||||||
{
|
|
||||||
return getInfo(inOrderId, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取入库执行单详情
|
|
||||||
* @param archive true-查询【已反审】tab 归档数据(主单须为已软删+已反审标记,明细放行软删行)
|
|
||||||
*/
|
|
||||||
public ExecutionStockInOrderPO getInfo(Long inOrderId, boolean archive)
|
|
||||||
{
|
{
|
||||||
ExecutionStockInOrderPO stockInOrderPO = stockInOrderService.getInfo(inOrderId);
|
ExecutionStockInOrderPO stockInOrderPO = stockInOrderService.getInfo(inOrderId);
|
||||||
if (archive && (stockInOrderPO.getDelFlag() == null || stockInOrderPO.getDelFlag() != 2
|
|
||||||
|| !Integer.valueOf(1).equals(stockInOrderPO.getReverseAuditStatus()))) {
|
|
||||||
throw new ServiceException("入库执行单非已反审归档数据,无法查看归档详情");
|
|
||||||
}
|
|
||||||
ExecutionInMaterialDetailDO inMaterialDetailDO = new ExecutionInMaterialDetailDO();
|
ExecutionInMaterialDetailDO inMaterialDetailDO = new ExecutionInMaterialDetailDO();
|
||||||
String inOrderNumber = stockInOrderPO.getInOrderNumber();
|
String inOrderNumber = stockInOrderPO.getInOrderNumber();
|
||||||
List<BusinessDocumentOrder> businessDocumentOrders = businessDocumentOrderMapper.selectList(new LambdaQueryWrapper<BusinessDocumentOrder>().eq(BusinessDocumentOrder::getInOrderNumber, inOrderNumber).notIn(BusinessDocumentOrder::getOrderStatus,4,5));
|
List<BusinessDocumentOrder> businessDocumentOrders = businessDocumentOrderMapper.selectList(new LambdaQueryWrapper<BusinessDocumentOrder>().eq(BusinessDocumentOrder::getInOrderNumber, inOrderNumber).notIn(BusinessDocumentOrder::getOrderStatus,4,5));
|
||||||
stockInOrderPO.setBusinessDocumentOrderDOList(businessDocumentOrders);
|
stockInOrderPO.setBusinessDocumentOrderDOList(businessDocumentOrders);
|
||||||
inMaterialDetailDO.setInOrderNumber(inOrderNumber);
|
inMaterialDetailDO.setInOrderNumber(inOrderNumber);
|
||||||
inMaterialDetailDO.setLevel(1);
|
inMaterialDetailDO.setLevel(1);
|
||||||
if (archive) {
|
|
||||||
//归档明细已随主单软删(del_flag=2),放行软删明细行
|
|
||||||
inMaterialDetailDO.setDelFlag(2);
|
|
||||||
}
|
|
||||||
List<ExecutionInMaterialDetailPO> inMaterialDetailPOList = materialDetailService.queryList(inMaterialDetailDO);
|
List<ExecutionInMaterialDetailPO> inMaterialDetailPOList = materialDetailService.queryList(inMaterialDetailDO);
|
||||||
|
|
||||||
// 先通过入库单号查询收货单列表
|
// 先通过入库单号查询收货单列表
|
||||||
|
|||||||
-3
@@ -516,7 +516,4 @@ public class ExecutionStockOutOrder extends BaseVOEntity {
|
|||||||
@ApiModelProperty("折扣")
|
@ApiModelProperty("折扣")
|
||||||
private BigDecimal discount;
|
private BigDecimal discount;
|
||||||
|
|
||||||
|
|
||||||
@ApiModelProperty("反审标记: 0-无 1-已反审(业务单反审时软删del_flag=2并打标记)")
|
|
||||||
private Integer reverseFlag;
|
|
||||||
}
|
}
|
||||||
-2
@@ -29,8 +29,6 @@ public class ExecutionStockOutOrderPO extends BaseVOEntity {
|
|||||||
|
|
||||||
@ApiModelProperty("出库单id")
|
@ApiModelProperty("出库单id")
|
||||||
private Long outOrderId;
|
private Long outOrderId;
|
||||||
@ApiModelProperty("反审标记: 1-已反审(反审软删归档, 【已反审】tab按 delFlag=2+reverseFlag=1 查询)")
|
|
||||||
private Integer reverseFlag;
|
|
||||||
@ApiModelProperty("总价")
|
@ApiModelProperty("总价")
|
||||||
@Excel(name = "总价")
|
@Excel(name = "总价")
|
||||||
private BigDecimal amount;
|
private BigDecimal amount;
|
||||||
|
|||||||
-3
@@ -29,9 +29,6 @@ public class ExecutionStockOutOrderDO extends BaseVOEntity {
|
|||||||
@ApiModelProperty("出库单id")
|
@ApiModelProperty("出库单id")
|
||||||
private Long outOrderId;
|
private Long outOrderId;
|
||||||
|
|
||||||
@ApiModelProperty("反审标记查询: 1-已反审(与delFlag=2成对传, 查【已反审】tab归档数据)")
|
|
||||||
private Integer reverseFlag;
|
|
||||||
|
|
||||||
@ApiModelProperty("组织表ID")
|
@ApiModelProperty("组织表ID")
|
||||||
@Excel(name = "组织表ID")
|
@Excel(name = "组织表ID")
|
||||||
private Long organizationId;
|
private Long organizationId;
|
||||||
|
|||||||
-3
@@ -27,9 +27,6 @@ public class ExecutionStockOutOrderDTO extends ExecutionStockOutOrderBaseDTO {
|
|||||||
@ApiModelProperty("出库单id")
|
@ApiModelProperty("出库单id")
|
||||||
private Long outOrderId;
|
private Long outOrderId;
|
||||||
|
|
||||||
@ApiModelProperty("反审标记查询: 1-已反审(与delFlag=2成对传, 查【已反审】tab归档数据)")
|
|
||||||
private Integer reverseFlag;
|
|
||||||
|
|
||||||
@ApiModelProperty("组织表ID")
|
@ApiModelProperty("组织表ID")
|
||||||
@Excel(name = "组织表ID")
|
@Excel(name = "组织表ID")
|
||||||
private Long organizationId;
|
private Long organizationId;
|
||||||
|
|||||||
+5
-4
@@ -66,8 +66,6 @@ import java.util.stream.Collectors;
|
|||||||
public class ExecutionStockOutOrderApplicationService {
|
public class ExecutionStockOutOrderApplicationService {
|
||||||
@Autowired
|
@Autowired
|
||||||
private ExecutionStockOutOrderDomainService stockOutOrderDomainService;
|
private ExecutionStockOutOrderDomainService stockOutOrderDomainService;
|
||||||
@Autowired
|
|
||||||
private com.mhd.oms.application.service.WarehouseInfoApplicationService warehouseInfoApplicationService;
|
|
||||||
// @Autowired
|
// @Autowired
|
||||||
// private ExecutionOutMaterialDetailDomainService outMaterialDetailDomainService;
|
// private ExecutionOutMaterialDetailDomainService outMaterialDetailDomainService;
|
||||||
// @Autowired
|
// @Autowired
|
||||||
@@ -864,8 +862,11 @@ public class ExecutionStockOutOrderApplicationService {
|
|||||||
if (stockOutOrderDO.getWarehouseId() == null) {
|
if (stockOutOrderDO.getWarehouseId() == null) {
|
||||||
throw new ServiceException("仓库ID不能为空");
|
throw new ServiceException("仓库ID不能为空");
|
||||||
}
|
}
|
||||||
// Feign失败走本地跨库兜底, 避免保存被"获取仓库信息失败"阻断
|
AjaxResult ajaxResult = systemServiceFeign.getWarehouseInfoByWarehouseId(stockOutOrderDO.getWarehouseId());
|
||||||
WarehouseFeignPO warehouseFeignPO = warehouseInfoApplicationService.getWarehouseInfo(stockOutOrderDO.getWarehouseId());
|
if(!"200".equals(String.valueOf(ajaxResult.get("code")))){
|
||||||
|
throw new ServiceException("获取仓库信息失败");
|
||||||
|
}
|
||||||
|
WarehouseFeignPO warehouseFeignPO = JSON.parseObject(JSONObject.toJSONString(ajaxResult.get("data")), WarehouseFeignPO.class);
|
||||||
stockOutOrderDO.setWarehouseCode(warehouseFeignPO.getWarehouseCode());
|
stockOutOrderDO.setWarehouseCode(warehouseFeignPO.getWarehouseCode());
|
||||||
stockOutOrderDO.setWarehouseName(warehouseFeignPO.getWarehouseName());
|
stockOutOrderDO.setWarehouseName(warehouseFeignPO.getWarehouseName());
|
||||||
}
|
}
|
||||||
|
|||||||
+17
-23
@@ -71,8 +71,6 @@ public class ExecutionStockOutOrderDomainService {
|
|||||||
@Autowired
|
@Autowired
|
||||||
private IExecutionStockOutOrderService stockOutOrderService;
|
private IExecutionStockOutOrderService stockOutOrderService;
|
||||||
@Autowired
|
@Autowired
|
||||||
private com.mhd.oms.application.service.WarehouseInfoApplicationService warehouseInfoApplicationService;
|
|
||||||
@Autowired
|
|
||||||
private IExecutionOutMaterialDetailService outMaterialDetailService;
|
private IExecutionOutMaterialDetailService outMaterialDetailService;
|
||||||
@Autowired
|
@Autowired
|
||||||
private IReservationDeliveryDetailsLinkService deliveryDetailsLinkService;
|
private IReservationDeliveryDetailsLinkService deliveryDetailsLinkService;
|
||||||
@@ -150,9 +148,14 @@ public class ExecutionStockOutOrderDomainService {
|
|||||||
public Boolean insert(ExecutionStockOutOrderDO stockOutOrderDO) {
|
public Boolean insert(ExecutionStockOutOrderDO stockOutOrderDO) {
|
||||||
//建单校验:明细数量必须大于0(0数量单下发WMS后自动分配必失败,出库单会卡死在已审核状态)
|
//建单校验:明细数量必须大于0(0数量单下发WMS后自动分配必失败,出库单会卡死在已审核状态)
|
||||||
validateMaterialDetailQuantity(stockOutOrderDO.getMaterialDetailList());
|
validateMaterialDetailQuantity(stockOutOrderDO.getMaterialDetailList());
|
||||||
//设置单号(仓库信息: Feign优先, system服务失败/降级时本地跨库兜底)
|
//设置单号
|
||||||
Long warehouseId = stockOutOrderDO.getWarehouseId();
|
Long warehouseId = stockOutOrderDO.getWarehouseId();
|
||||||
WarehouseFeignPO warehouseFeignPO = warehouseInfoApplicationService.getWarehouseInfo(warehouseId);
|
AjaxResult ajaxResult = systemServiceFeign.getWarehouseInfoByWarehouseId(warehouseId);
|
||||||
|
if (!"200".equals(String.valueOf(ajaxResult.get("code")))) {
|
||||||
|
throw new ServiceException("获取仓库信息失败");
|
||||||
|
}
|
||||||
|
//仓库信息
|
||||||
|
WarehouseFeignPO warehouseFeignPO = com.alibaba.fastjson.JSON.parseObject(com.alibaba.fastjson2.JSONObject.toJSONString(ajaxResult.get("data")), WarehouseFeignPO.class);
|
||||||
String orderNoGenerateRule = warehouseFeignPO.getOrderNoGenerateRule();
|
String orderNoGenerateRule = warehouseFeignPO.getOrderNoGenerateRule();
|
||||||
String prefix = warehouseFeignPO.getOutOrderNoPrefix();
|
String prefix = warehouseFeignPO.getOutOrderNoPrefix();
|
||||||
if ("yang_pin_chu_ku".equals(stockOutOrderDO.getBusinessType())) {
|
if ("yang_pin_chu_ku".equals(stockOutOrderDO.getBusinessType())) {
|
||||||
@@ -215,9 +218,14 @@ public class ExecutionStockOutOrderDomainService {
|
|||||||
@Transactional(rollbackFor = Exception.class)
|
@Transactional(rollbackFor = Exception.class)
|
||||||
public Boolean batchInsert(List<ExecutionStockOutOrderDO> stockOutOrderDOList) {
|
public Boolean batchInsert(List<ExecutionStockOutOrderDO> stockOutOrderDOList) {
|
||||||
for (ExecutionStockOutOrderDO stockOutOrderDO : stockOutOrderDOList){
|
for (ExecutionStockOutOrderDO stockOutOrderDO : stockOutOrderDOList){
|
||||||
//设置单号(仓库信息: Feign优先, system服务失败/降级时本地跨库兜底)
|
//设置单号
|
||||||
Long warehouseId = stockOutOrderDO.getWarehouseId();
|
Long warehouseId = stockOutOrderDO.getWarehouseId();
|
||||||
WarehouseFeignPO warehouseFeignPO = warehouseInfoApplicationService.getWarehouseInfo(warehouseId);
|
AjaxResult ajaxResult = systemServiceFeign.getWarehouseInfoByWarehouseId(warehouseId);
|
||||||
|
if (!"200".equals(String.valueOf(ajaxResult.get("code")))) {
|
||||||
|
throw new ServiceException("获取仓库信息失败");
|
||||||
|
}
|
||||||
|
//仓库信息
|
||||||
|
WarehouseFeignPO warehouseFeignPO = com.alibaba.fastjson.JSON.parseObject(com.alibaba.fastjson2.JSONObject.toJSONString(ajaxResult.get("data")), WarehouseFeignPO.class);
|
||||||
String orderNoGenerateRule = warehouseFeignPO.getOrderNoGenerateRule();
|
String orderNoGenerateRule = warehouseFeignPO.getOrderNoGenerateRule();
|
||||||
String prefix = warehouseFeignPO.getOutOrderNoPrefix();
|
String prefix = warehouseFeignPO.getOutOrderNoPrefix();
|
||||||
if ("yang_pin_chu_ku".equals(stockOutOrderDO.getBusinessType())) {
|
if ("yang_pin_chu_ku".equals(stockOutOrderDO.getBusinessType())) {
|
||||||
@@ -534,12 +542,7 @@ public class ExecutionStockOutOrderDomainService {
|
|||||||
stockOutOrder.setOrganizationId(orgId);
|
stockOutOrder.setOrganizationId(orgId);
|
||||||
stockOutOrder.setOrganizationName(orgName);
|
stockOutOrder.setOrganizationName(orgName);
|
||||||
stockOutOrder.setTopOrganizationId(topOrgId);
|
stockOutOrder.setTopOrganizationId(topOrgId);
|
||||||
//单头/配送明细推送同样校验返回值: 降级吞掉会残留"有单无明细"等半截单
|
wmsServiceFeign.omsOutOrderAdd(stockOutOrder);
|
||||||
AjaxResult orderAddResult = wmsServiceFeign.omsOutOrderAdd(stockOutOrder);
|
|
||||||
if (orderAddResult == null || !"200".equals(String.valueOf(orderAddResult.get("code")))) {
|
|
||||||
throw new ServiceException("出库单[" + currentOrderNumber + "]WMS出库单推送失败:"
|
|
||||||
+ (orderAddResult == null ? "WMS服务不可用或已降级" : orderAddResult.get("msg")));
|
|
||||||
}
|
|
||||||
|
|
||||||
List<ReservationDeliveryDetailsLink> list = deliveryDetailsLinkService.list(new QueryWrapper<ReservationDeliveryDetailsLink>().lambda().eq(ReservationDeliveryDetailsLink::getOrderNumber, byId.getOutOrderNumber()));
|
List<ReservationDeliveryDetailsLink> list = deliveryDetailsLinkService.list(new QueryWrapper<ReservationDeliveryDetailsLink>().lambda().eq(ReservationDeliveryDetailsLink::getOrderNumber, byId.getOutOrderNumber()));
|
||||||
List<DeliveryDetailsLink> deliveryDetailsLinkList = new ArrayList<>();
|
List<DeliveryDetailsLink> deliveryDetailsLinkList = new ArrayList<>();
|
||||||
@@ -549,11 +552,7 @@ public class ExecutionStockOutOrderDomainService {
|
|||||||
deliveryDetailsLink.setOmsId(reservationDeliveryDetailsLink.getId());
|
deliveryDetailsLink.setOmsId(reservationDeliveryDetailsLink.getId());
|
||||||
deliveryDetailsLinkList.add(deliveryDetailsLink);
|
deliveryDetailsLinkList.add(deliveryDetailsLink);
|
||||||
}
|
}
|
||||||
AjaxResult linkAddResult = wmsServiceFeign.omsOutOrderAddDeliveryDetailsLink(deliveryDetailsLinkList);
|
wmsServiceFeign.omsOutOrderAddDeliveryDetailsLink(deliveryDetailsLinkList);
|
||||||
if (linkAddResult == null || !"200".equals(String.valueOf(linkAddResult.get("code")))) {
|
|
||||||
throw new ServiceException("出库单[" + currentOrderNumber + "]WMS配送明细推送失败:"
|
|
||||||
+ (linkAddResult == null ? "WMS服务不可用或已降级" : linkAddResult.get("msg")));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
String inOrderNumber = stockOutOrder.getOutOrderNumber();
|
String inOrderNumber = stockOutOrder.getOutOrderNumber();
|
||||||
@@ -567,12 +566,7 @@ public class ExecutionStockOutOrderDomainService {
|
|||||||
outMaterialDetail.setTopOrganizationId(topOrgId);
|
outMaterialDetail.setTopOrganizationId(topOrgId);
|
||||||
outMaterialDetailList.add(outMaterialDetail);
|
outMaterialDetailList.add(outMaterialDetail);
|
||||||
}
|
}
|
||||||
//明细推送必须校验返回值: 失败被降级吞掉时WMS会残留"有单无明细"的出库单, 自动分配报"可用库存为0"难定位
|
wmsServiceFeign.omsOutOrderAddDetail(outMaterialDetailList);
|
||||||
AjaxResult detailAddResult = wmsServiceFeign.omsOutOrderAddDetail(outMaterialDetailList);
|
|
||||||
if (detailAddResult == null || !"200".equals(String.valueOf(detailAddResult.get("code")))) {
|
|
||||||
throw new ServiceException("出库单[" + currentOrderNumber + "]WMS出库明细推送失败:"
|
|
||||||
+ (detailAddResult == null ? "WMS服务不可用或已降级" : detailAddResult.get("msg")));
|
|
||||||
}
|
|
||||||
|
|
||||||
String outOrderNumber = byId.getOutOrderNumber();
|
String outOrderNumber = byId.getOutOrderNumber();
|
||||||
com.mhd.system.api.domain.StockOutOrderDTO stockOutOrderDTO = new com.mhd.system.api.domain.StockOutOrderDTO();
|
com.mhd.system.api.domain.StockOutOrderDTO stockOutOrderDTO = new com.mhd.system.api.domain.StockOutOrderDTO();
|
||||||
|
|||||||
-12
@@ -102,12 +102,6 @@ public class QueryOrderOverStockDO extends BaseVOEntity {
|
|||||||
@Excel(name = "出库单类型编码")
|
@Excel(name = "出库单类型编码")
|
||||||
private String outOrderTypeCode;
|
private String outOrderTypeCode;
|
||||||
|
|
||||||
@ApiModelProperty("出库单类型编码(与outOrderTypeCode同义)")
|
|
||||||
private String orderTypeCode;
|
|
||||||
|
|
||||||
@ApiModelProperty("出库单类型名称")
|
|
||||||
private String orderTypeName;
|
|
||||||
|
|
||||||
@ApiModelProperty("出库单类型名称")
|
@ApiModelProperty("出库单类型名称")
|
||||||
@Excel(name = "出库单类型名称")
|
@Excel(name = "出库单类型名称")
|
||||||
private String outOrderTypeName;
|
private String outOrderTypeName;
|
||||||
@@ -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 outboundDateStart;
|
|
||||||
|
|
||||||
@ApiModelProperty("实际出仓日期 结束(yyyy-MM-dd,为空按建档时间兜底)")
|
|
||||||
private String outboundDateEnd;
|
|
||||||
}
|
}
|
||||||
-17
@@ -456,21 +456,4 @@ public class ReservationStockInOrder extends BaseVOEntity {
|
|||||||
|
|
||||||
@ApiModelProperty("业务计价方式")
|
@ApiModelProperty("业务计价方式")
|
||||||
private String businessPriceWay;
|
private String businessPriceWay;
|
||||||
|
|
||||||
@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;
|
|
||||||
}
|
}
|
||||||
-7
@@ -54,13 +54,6 @@ public interface ReservationStockInOrderMapper extends BaseMapper<ReservationSto
|
|||||||
|
|
||||||
public String getWarehouseName(@Param("id") Long id);
|
public String getWarehouseName(@Param("id") Long id);
|
||||||
|
|
||||||
/**
|
|
||||||
* 本地跨库直查仓库信息(编码/名称/单号生成规则),
|
|
||||||
* 供下发等流程在 system 服务 Feign 失败/降级时兜底, 与 getWarehouseInfoByWarehouseId Feign 接口同数据源。
|
|
||||||
* 不含 STOCK_LOCK_MODE(冻结功能列, 各环境库结构不一致), 兜底时 stockLockMode 为 null 即默认分配库存冻结模式
|
|
||||||
*/
|
|
||||||
public com.mhd.system.api.domain.WarehouseFeignPO getWarehouseInfoFallback(@Param("id") Long id);
|
|
||||||
|
|
||||||
List<ReservationStockInOrderPO> queryNoticePrint(ReservationStockInOrderDO stockInOrderDO);
|
List<ReservationStockInOrderPO> queryNoticePrint(ReservationStockInOrderDO stockInOrderDO);
|
||||||
List<ReservationInMaterialDetailPO> queryNoticePrintDetail(ReservationStockInOrderDO stockInOrderDO);
|
List<ReservationInMaterialDetailPO> queryNoticePrintDetail(ReservationStockInOrderDO stockInOrderDO);
|
||||||
public void updateByTransportationNumber(@Param("transportationNumber") String transportationNumber);
|
public void updateByTransportationNumber(@Param("transportationNumber") String transportationNumber);
|
||||||
|
|||||||
-17
@@ -502,21 +502,4 @@ public class ReservationStockInOrderPO extends BaseVOEntity {
|
|||||||
@ApiModelProperty("业务计价方式")
|
@ApiModelProperty("业务计价方式")
|
||||||
private String businessPriceWay;
|
private String businessPriceWay;
|
||||||
private String khdm;
|
private String khdm;
|
||||||
|
|
||||||
@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;
|
|
||||||
}
|
}
|
||||||
-17
@@ -513,21 +513,4 @@ public class ReservationStockInOrderDO extends BaseVOEntity {
|
|||||||
|
|
||||||
@ApiModelProperty("业务计价方式")
|
@ApiModelProperty("业务计价方式")
|
||||||
private String businessPriceWay;
|
private String businessPriceWay;
|
||||||
|
|
||||||
@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;
|
|
||||||
}
|
}
|
||||||
-17
@@ -507,21 +507,4 @@ public class ReservationStockInOrderDTO extends ReservationStockInOrderBaseDTO {
|
|||||||
|
|
||||||
@ApiModelProperty("业务计价方式")
|
@ApiModelProperty("业务计价方式")
|
||||||
private String businessPriceWay;
|
private String businessPriceWay;
|
||||||
|
|
||||||
@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;
|
|
||||||
}
|
}
|
||||||
+2
-10
@@ -282,7 +282,8 @@ public class ReservationStockInOrderApplicationService {
|
|||||||
* @return Boolean
|
* @return Boolean
|
||||||
*/
|
*/
|
||||||
public Boolean auditState(ReservationStockInOrderDO stockInOrderDO){
|
public Boolean auditState(ReservationStockInOrderDO stockInOrderDO){
|
||||||
Boolean b = stockInOrderDomainService.auditState(stockInOrderDO);// List<Long> inOrderIds = stockInOrderDO.getInOrderIds();
|
Boolean b = stockInOrderDomainService.auditState(stockInOrderDO);
|
||||||
|
// List<Long> inOrderIds = stockInOrderDO.getInOrderIds();
|
||||||
// if (inOrderIds != null && !inOrderIds.isEmpty()) {
|
// if (inOrderIds != null && !inOrderIds.isEmpty()) {
|
||||||
// ReservationStockInOrder stockInOrder = reservationStockInOrderMapper.selectById(inOrderIds.get(0));
|
// ReservationStockInOrder stockInOrder = reservationStockInOrderMapper.selectById(inOrderIds.get(0));
|
||||||
// Integer needCustomsDeclaration = stockInOrder.getNeedCustomsDeclaration();
|
// Integer needCustomsDeclaration = stockInOrder.getNeedCustomsDeclaration();
|
||||||
@@ -301,15 +302,6 @@ public class ReservationStockInOrderApplicationService {
|
|||||||
return b;
|
return b;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 反审入库业务单:业务单状态改为已驳回(issueStatus=3)并打已反审标记落入【已反审】tab,
|
|
||||||
* 入库执行单+明细逻辑删除,WMS侧整链回退(库存扣减+单据清理+反审异常记录),
|
|
||||||
* W入库单有出库记录时WMS侧拦截,已推送关务直接拦截
|
|
||||||
*/
|
|
||||||
public Boolean reverseAudit(ReservationStockInOrderDO stockInOrderDO){
|
|
||||||
return stockInOrderDomainService.reverseAudit(stockInOrderDO);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @description 下发入库单
|
* @description 下发入库单
|
||||||
* @author ZhouGY
|
* @author ZhouGY
|
||||||
|
|||||||
+2
-176
@@ -13,9 +13,6 @@ 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.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 com.mhd.oms.domain.electronicSignature.entity.ElectronicSignature;
|
|
||||||
import com.mhd.oms.domain.electronicSignature.repository.facade.IElectronicSignatureMaterialDetailService;
|
|
||||||
import com.mhd.oms.domain.electronicSignature.repository.facade.IElectronicSignatureService;
|
|
||||||
import com.mhd.oms.domain.executionInMaterialDetail.entity.ExecutionInMaterialDetail;
|
import com.mhd.oms.domain.executionInMaterialDetail.entity.ExecutionInMaterialDetail;
|
||||||
import com.mhd.oms.domain.executionInMaterialDetail.repository.facade.IExecutionInMaterialDetailService;
|
import com.mhd.oms.domain.executionInMaterialDetail.repository.facade.IExecutionInMaterialDetailService;
|
||||||
import com.mhd.oms.domain.executionStockInOrder.entity.ExecutionStockInOrder;
|
import com.mhd.oms.domain.executionStockInOrder.entity.ExecutionStockInOrder;
|
||||||
@@ -94,10 +91,6 @@ public class ReservationStockInOrderDomainService {
|
|||||||
private ExecutionStockInOrderMapper executionStockInOrderMapper;
|
private ExecutionStockInOrderMapper executionStockInOrderMapper;
|
||||||
@Autowired
|
@Autowired
|
||||||
private ReserveStockInOrderMapper reserveStockInOrderMapper;
|
private ReserveStockInOrderMapper reserveStockInOrderMapper;
|
||||||
@Autowired
|
|
||||||
private IElectronicSignatureService electronicSignatureService;
|
|
||||||
@Autowired
|
|
||||||
private IElectronicSignatureMaterialDetailService electronicSignatureMaterialDetailService;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 分页查询入库单列表
|
* 分页查询入库单列表
|
||||||
@@ -176,10 +169,6 @@ public class ReservationStockInOrderDomainService {
|
|||||||
// //统计总体积
|
// //统计总体积
|
||||||
// BigDecimal volumeLimit = stockInOrderDO.getMaterialDetailList().stream().map(ReservationInMaterialDetailDO::getVolumeLimit).filter(Objects::nonNull).reduce(BigDecimal.ZERO, BigDecimal::add);
|
// BigDecimal volumeLimit = stockInOrderDO.getMaterialDetailList().stream().map(ReservationInMaterialDetailDO::getVolumeLimit).filter(Objects::nonNull).reduce(BigDecimal.ZERO, BigDecimal::add);
|
||||||
// stockInOrderDO.setVolumeLimit(volumeLimit);
|
// stockInOrderDO.setVolumeLimit(volumeLimit);
|
||||||
// 订单来源为空时兜底为手动创建(导入/预约下发等路径已显式设置,不受影响),下发执行单时随业务单继承
|
|
||||||
if (stockInOrderDO.getReservationOrderSource() == null || stockInOrderDO.getReservationOrderSource().isEmpty()) {
|
|
||||||
stockInOrderDO.setReservationOrderSource("手动创建");
|
|
||||||
}
|
|
||||||
stockInOrderService.insert(stockInOrderDO);
|
stockInOrderService.insert(stockInOrderDO);
|
||||||
return materialDetailService.batchInsert(stockInOrderDO.getInOrderNumber(), stockInOrderDO.getMaterialDetailList());
|
return materialDetailService.batchInsert(stockInOrderDO.getInOrderNumber(), stockInOrderDO.getMaterialDetailList());
|
||||||
}
|
}
|
||||||
@@ -618,6 +607,7 @@ public class ReservationStockInOrderDomainService {
|
|||||||
reservationStockInOrder.setOrderTypeName("普通入库");
|
reservationStockInOrder.setOrderTypeName("普通入库");
|
||||||
reservationStockInOrder.setBusinessType("pu_tong_ru_ku");
|
reservationStockInOrder.setBusinessType("pu_tong_ru_ku");
|
||||||
}
|
}
|
||||||
|
reservationStockInOrder.setReservationOrderSource("客户预约");
|
||||||
reservationStockInOrder.setWarehouseId(warehouseId);
|
reservationStockInOrder.setWarehouseId(warehouseId);
|
||||||
if (warehouseId == null || warehouseId == 0L){
|
if (warehouseId == null || warehouseId == 0L){
|
||||||
reservationStockInOrder.setWarehouseId(byId.getWarehouseId());
|
reservationStockInOrder.setWarehouseId(byId.getWarehouseId());
|
||||||
@@ -777,171 +767,6 @@ public class ReservationStockInOrderDomainService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 反审入库业务单(需求:已入库/已出库的单子客户通知需要回退的场景,单子回退到最原始状态):
|
|
||||||
* 页面状态列按 issueStatus(0-已创建 1-进行中 2-已审核 3-已驳回 4-已入库 5-部分完成)展示,
|
|
||||||
* 反审条件按 issueStatus 判断——进行中(1)/已审核(2)/已入库(4)/部分完成(5)可反审,
|
|
||||||
* 已创建(0)无需反审、已驳回(3)可直接编辑;已取消/已关闭(status 6/7)兜底拦截。
|
|
||||||
* 反审动作("审核不通过"同语义 + 全链路回退,补齐 auditState 审核不通过缺失的下游联动):
|
|
||||||
* <ul>
|
|
||||||
* <li>业务单状态改为"已驳回"(issueStatus=3),打已反审标记(REVERSE_AUDIT_STATUS=1)落入【已反审】tab,
|
|
||||||
* 之后可「编辑」→重新「审核」→重新「下发」生成全新执行单</li>
|
|
||||||
* <li>入库执行单+物料明细软删(del_flag=2)并打已反审标记——执行单【已反审】tab按
|
|
||||||
* "已软删+已反审"查询归档数据;软删后不出现在正常tab,避免归档单被误「审核/下发」</li>
|
|
||||||
* <li>清空WMS完成上架跨库回写的完成数据(业务单 IN_QUANTITY/STORAGE_TIME、明细 INBOUND_ITEMS/TOTAL_NET_WEIGHT)</li>
|
|
||||||
* <li>WMS侧逐执行单回退(omsReverseInOrder):W入库单有出库记录则拦截(按入库单号+动作"分配库存/出库"
|
|
||||||
* 查库存调整记录>0)→ 库存还原扣减 → W入库单/W收货单/W上架单整链软删并打已反审标记
|
|
||||||
* (数据划归W入库单/W收货单/W上架单【已反审】tab归档)→
|
|
||||||
* 写1条W入库异常【反审记录】用于记录跟踪</li>
|
|
||||||
* </ul>
|
|
||||||
* 已推送关务(pushStatus=3)直接拦截。WMS回退幂等,反审失败可安全重试。
|
|
||||||
*/
|
|
||||||
@Transactional(rollbackFor = Exception.class)
|
|
||||||
public Boolean reverseAudit(ReservationStockInOrderDO stockInOrderDO) {
|
|
||||||
LoginUser loginUser = SecurityUtils.getLoginUser();
|
|
||||||
// 获取用户姓名(优先从UserPo获取,如果为空则使用realname,最后使用username作为兜底)
|
|
||||||
String userRealName = loginUser.getUserPo() != null && loginUser.getUserPo().getUserName() != null
|
|
||||||
? loginUser.getUserPo().getUserName()
|
|
||||||
: (loginUser.getRealname() != null ? loginUser.getRealname() : loginUser.getUsername());
|
|
||||||
|
|
||||||
List<Long> inOrderIds = stockInOrderDO.getInOrderIds();
|
|
||||||
if (inOrderIds == null || inOrderIds.isEmpty()) {
|
|
||||||
throw new ServiceException("未选择反审的入库业务单");
|
|
||||||
}
|
|
||||||
Date now = new Date();
|
|
||||||
for (Long inOrderId : inOrderIds) {
|
|
||||||
ReservationStockInOrder businessOrder = stockInOrderService.getById(inOrderId);
|
|
||||||
if (businessOrder == null
|
|
||||||
|| (businessOrder.getDelFlag() != null && businessOrder.getDelFlag() != 1)) {
|
|
||||||
throw new ServiceException("入库业务单不存在或已被删除,无法反审");
|
|
||||||
}
|
|
||||||
String businessNumber = businessOrder.getInOrderNumber();
|
|
||||||
Integer issueStatus = businessOrder.getIssueStatus();
|
|
||||||
if (issueStatus == null || issueStatus == 0) {
|
|
||||||
throw new ServiceException("入库业务单[" + businessNumber + "]为已创建状态,无需反审");
|
|
||||||
}
|
|
||||||
if (issueStatus == 3) {
|
|
||||||
throw new ServiceException("入库业务单[" + businessNumber + "]已驳回,无需反审,可直接编辑后重新提交审核");
|
|
||||||
}
|
|
||||||
if (issueStatus != 1 && issueStatus != 2 && issueStatus != 4 && issueStatus != 5) {
|
|
||||||
throw new ServiceException("入库业务单[" + businessNumber + "]仅进行中/已审核/已入库状态可反审,当前状态值:" + issueStatus);
|
|
||||||
}
|
|
||||||
if (businessOrder.getStatus() != null && (businessOrder.getStatus() == 6 || businessOrder.getStatus() == 7)) {
|
|
||||||
throw new ServiceException("入库业务单[" + businessNumber + "]已取消/已关闭,无法反审");
|
|
||||||
}
|
|
||||||
if (businessOrder.getPushStatus() != null && businessOrder.getPushStatus() == 3) {
|
|
||||||
throw new ServiceException("入库业务单[" + businessNumber + "]已推送关务/NC,无法反审,请先在关务侧处理");
|
|
||||||
}
|
|
||||||
|
|
||||||
//该业务单下全部有效执行单:逐张调WMS回退后软删并打已反审标记
|
|
||||||
List<ExecutionStockInOrder> executionOrders = executionStockInOrderService.list(
|
|
||||||
new LambdaQueryWrapper<ExecutionStockInOrder>()
|
|
||||||
.eq(ExecutionStockInOrder::getBusinessInOrderNumber, businessNumber)
|
|
||||||
.eq(ExecutionStockInOrder::getDelFlag, 1));
|
|
||||||
for (ExecutionStockInOrder executionOrder : executionOrders) {
|
|
||||||
String executionNumber = executionOrder.getInOrderNumber();
|
|
||||||
if (executionOrder.getPushStatus() != null && executionOrder.getPushStatus() == 3) {
|
|
||||||
throw new ServiceException("执行入库单[" + executionNumber + "]已推送关务/NC,无法反审,请先在关务侧处理");
|
|
||||||
}
|
|
||||||
//WMS侧回退(对称收货/上架完成链路,见 WMS StockInOrderDomainService.reverseExecutionOrder):
|
|
||||||
//有出库/库存已被分配时WMS报错,此处抛错整体回滚;WMS无数据时幂等成功(未下发执行单反审)
|
|
||||||
StockInOrder reverseParam = new StockInOrder();
|
|
||||||
reverseParam.setInOrderNumber(executionNumber);
|
|
||||||
reverseParam.setRemark("业务单号:" + businessNumber
|
|
||||||
+ (StringUtils.isNotEmpty(stockInOrderDO.getReverseAuditRemark())
|
|
||||||
? ",反审原因:" + stockInOrderDO.getReverseAuditRemark() : ""));
|
|
||||||
//组织三字段:WMS幂等跳过分支(未下发单反审)写反审记录时取不到W入库单,需经Feign透传
|
|
||||||
reverseParam.setOrganizationId(executionOrder.getOrganizationId());
|
|
||||||
reverseParam.setOrganizationName(executionOrder.getOrganizationName());
|
|
||||||
reverseParam.setTopOrganizationId(executionOrder.getTopOrganizationId());
|
|
||||||
reverseParam.setUpdateBy(loginUser.getUserid());
|
|
||||||
reverseParam.setUpdateByName(userRealName);
|
|
||||||
AjaxResult reverseResult = wmsServiceFeign.omsReverseInOrder(reverseParam);
|
|
||||||
if (reverseResult == null || !"200".equals(String.valueOf(reverseResult.get("code")))) {
|
|
||||||
throw new ServiceException("反审失败:执行入库单[" + executionNumber + "]WMS回退失败:"
|
|
||||||
+ (reverseResult == null ? "WMS服务不可用或已降级" : reverseResult.get("msg")));
|
|
||||||
}
|
|
||||||
//清理下发自动审核生成的待签名电子签名记录(signatureStatus=1,已签名记录保留作凭证)
|
|
||||||
cancelPendingSignature(executionNumber);
|
|
||||||
//执行单+物料明细软删(del_flag=2)并打已反审标记:
|
|
||||||
//执行单【已反审】tab按"已软删+已反审"(del_flag=2 and REVERSE_AUDIT_STATUS=1)查询归档数据;
|
|
||||||
//软删后不出现在正常tab,避免归档单被误「审核/下发」;业务单重新下发时生成全新执行单
|
|
||||||
executionInMaterialDetailService.update(new UpdateWrapper<ExecutionInMaterialDetail>().lambda()
|
|
||||||
.set(ExecutionInMaterialDetail::getDelFlag, 2)
|
|
||||||
.set(ExecutionInMaterialDetail::getUpdateBy, loginUser.getUserid())
|
|
||||||
.set(ExecutionInMaterialDetail::getUpdateByName, userRealName)
|
|
||||||
.set(ExecutionInMaterialDetail::getUpdateTime, now)
|
|
||||||
.eq(ExecutionInMaterialDetail::getInOrderNumber, executionNumber)
|
|
||||||
.eq(ExecutionInMaterialDetail::getDelFlag, 1));
|
|
||||||
executionStockInOrderService.update(new UpdateWrapper<ExecutionStockInOrder>().lambda()
|
|
||||||
.set(ExecutionStockInOrder::getDelFlag, 2)
|
|
||||||
.set(ExecutionStockInOrder::getReverseAuditStatus, 1)
|
|
||||||
.set(ExecutionStockInOrder::getReverseAuditRemark, stockInOrderDO.getReverseAuditRemark())
|
|
||||||
.set(ExecutionStockInOrder::getReverseAuditBy, loginUser.getUserid())
|
|
||||||
.set(ExecutionStockInOrder::getReverseAuditByName, userRealName)
|
|
||||||
.set(ExecutionStockInOrder::getReverseAuditTime, now)
|
|
||||||
.set(ExecutionStockInOrder::getUpdateBy, loginUser.getUserid())
|
|
||||||
.set(ExecutionStockInOrder::getUpdateByName, userRealName)
|
|
||||||
.set(ExecutionStockInOrder::getUpdateTime, now)
|
|
||||||
.eq(ExecutionStockInOrder::getInOrderId, executionOrder.getInOrderId())
|
|
||||||
.eq(ExecutionStockInOrder::getDelFlag, 1));
|
|
||||||
}
|
|
||||||
|
|
||||||
//清空WMS完成上架跨库回写的业务单明细入库数量(INBOUND_ITEMS/TOTAL_NET_WEIGHT 上架时按上架量覆写过)
|
|
||||||
materialDetailService.update(new UpdateWrapper<ReservationInMaterialDetail>().lambda()
|
|
||||||
.set(ReservationInMaterialDetail::getInboundQuantity, BigDecimal.ZERO)
|
|
||||||
.set(ReservationInMaterialDetail::getTotalNetWeight, BigDecimal.ZERO)
|
|
||||||
.eq(ReservationInMaterialDetail::getInOrderNumber, businessNumber)
|
|
||||||
.eq(ReservationInMaterialDetail::getDelFlag, 1));
|
|
||||||
}
|
|
||||||
|
|
||||||
//业务单状态改为"已驳回"(与审核不通过同语义)+ 已反审标记落入【已反审】tab + 清空完成回写数据
|
|
||||||
return stockInOrderService.update(null, new UpdateWrapper<ReservationStockInOrder>().lambda()
|
|
||||||
.set(ReservationStockInOrder::getIssueStatus, 3)
|
|
||||||
//清空下发/执行时间(前端"是否执行"列按执行时间判断,不清会仍显示已执行,与取消下发 cancelIssueOrder 同口径)
|
|
||||||
.set(ReservationStockInOrder::getIssueTime, null)
|
|
||||||
//入库进度状态(1-已创建 2-已审核 3-收货中 4-上架中 5-已入库):首轮"完成上架"会经WMS回传写成5,
|
|
||||||
//不重置的话重新下发时copy给执行单→W入库单→收货单,收货单带着"已完成"状态导致前端不给收货按钮;
|
|
||||||
//重置为1(已创建),与手工新单首次下发链路一致(W入库单/收货单起点=1-待收货)
|
|
||||||
.set(ReservationStockInOrder::getStatus, 1)
|
|
||||||
.set(ReservationStockInOrder::getInQuantity, BigDecimal.ZERO)
|
|
||||||
.set(ReservationStockInOrder::getStorageTime, null)
|
|
||||||
.set(ReservationStockInOrder::getExecutionInOrderNumber, null)
|
|
||||||
//反审标记与反审痕迹(【已反审】tab 按 reverseAuditStatus=1 过滤;业务单本身不软删,保持可编辑重新下发)
|
|
||||||
.set(ReservationStockInOrder::getReverseAuditStatus, 1)
|
|
||||||
.set(ReservationStockInOrder::getReverseAuditRemark, stockInOrderDO.getReverseAuditRemark())
|
|
||||||
.set(ReservationStockInOrder::getReverseAuditBy, loginUser.getUserid())
|
|
||||||
.set(ReservationStockInOrder::getReverseAuditByName, userRealName)
|
|
||||||
.set(ReservationStockInOrder::getReverseAuditTime, now)
|
|
||||||
.set(ReservationStockInOrder::getUpdateBy, loginUser.getUserid())
|
|
||||||
.set(ReservationStockInOrder::getUpdateByName, userRealName)
|
|
||||||
.set(ReservationStockInOrder::getUpdateTime, now)
|
|
||||||
.in(ReservationStockInOrder::getInOrderId, inOrderIds));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 反审时清理下发自动审核生成的待签名电子签名记录(signatureStatus=1)及其明细,
|
|
||||||
* 已签名记录保留作凭证;清理失败仅记日志不阻断反审主流程(同取消下发)
|
|
||||||
*/
|
|
||||||
private void cancelPendingSignature(String inOrderNumber) {
|
|
||||||
try {
|
|
||||||
List<ElectronicSignature> signatures = electronicSignatureService.list(
|
|
||||||
new LambdaQueryWrapper<ElectronicSignature>()
|
|
||||||
.eq(ElectronicSignature::getOrderNumber, inOrderNumber)
|
|
||||||
.eq(ElectronicSignature::getOrderType, "IN")
|
|
||||||
.eq(ElectronicSignature::getSignatureStatus, 1)
|
|
||||||
.eq(ElectronicSignature::getDelFlag, 1));
|
|
||||||
for (ElectronicSignature signature : signatures) {
|
|
||||||
electronicSignatureMaterialDetailService.deleteBySignatureId(signature.getSignatureId());
|
|
||||||
electronicSignatureService.update(new UpdateWrapper<ElectronicSignature>().lambda()
|
|
||||||
.set(ElectronicSignature::getDelFlag, 2)
|
|
||||||
.eq(ElectronicSignature::getSignatureId, signature.getSignatureId()));
|
|
||||||
}
|
|
||||||
} catch (Exception e) {
|
|
||||||
log.error("反审清理电子签名记录失败,入库单号:{}", inOrderNumber, e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Transactional(rollbackFor = Exception.class)
|
@Transactional(rollbackFor = Exception.class)
|
||||||
public Boolean executeAndIssue(ReservationStockInOrderDO stockInOrderDO) {
|
public Boolean executeAndIssue(ReservationStockInOrderDO stockInOrderDO) {
|
||||||
// 防重复执行校验(与 issueOrder 的防重逻辑对齐):issueTime 有值表示已下发/执行过。
|
// 防重复执行校验(与 issueOrder 的防重逻辑对齐):issueTime 有值表示已下发/执行过。
|
||||||
@@ -1045,6 +870,7 @@ public class ReservationStockInOrderDomainService {
|
|||||||
reservationStockInOrder.setOrderTypeName("普通入库");
|
reservationStockInOrder.setOrderTypeName("普通入库");
|
||||||
reservationStockInOrder.setBusinessType("pu_tong_ru_ku");
|
reservationStockInOrder.setBusinessType("pu_tong_ru_ku");
|
||||||
}
|
}
|
||||||
|
reservationStockInOrder.setReservationOrderSource("客户预约");
|
||||||
reservationStockInOrder.setWarehouseId(warehouseId);
|
reservationStockInOrder.setWarehouseId(warehouseId);
|
||||||
// reservationStockInOrder.setOrganizationId(orgId);
|
// reservationStockInOrder.setOrganizationId(orgId);
|
||||||
// reservationStockInOrder.setOrganizationName(orgName);
|
// reservationStockInOrder.setOrganizationName(orgName);
|
||||||
|
|||||||
-17
@@ -515,21 +515,4 @@ public class ReservationStockOutOrder extends BaseVOEntity {
|
|||||||
@ApiModelProperty("折扣")
|
@ApiModelProperty("折扣")
|
||||||
private BigDecimal discount;
|
private BigDecimal discount;
|
||||||
|
|
||||||
@ApiModelProperty("反审状态: 0-无 1-已反审(反审后status回退为1-已创建,重新审核通过自动复位0)")
|
|
||||||
private Integer reverseStatus;
|
|
||||||
|
|
||||||
@ApiModelProperty("反审人id")
|
|
||||||
private Long reverseBy;
|
|
||||||
|
|
||||||
@ApiModelProperty("反审人姓名")
|
|
||||||
private String reverseByName;
|
|
||||||
|
|
||||||
@ApiModelProperty("反审时间")
|
|
||||||
@JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss")
|
|
||||||
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
|
||||||
private Date reverseTime;
|
|
||||||
|
|
||||||
@ApiModelProperty("反审原因")
|
|
||||||
private String reverseRemark;
|
|
||||||
|
|
||||||
}
|
}
|
||||||
-17
@@ -538,21 +538,4 @@ public class ReservationStockOutOrderPO extends BaseVOEntity {
|
|||||||
@ApiModelProperty("折扣")
|
@ApiModelProperty("折扣")
|
||||||
private BigDecimal discount;
|
private BigDecimal discount;
|
||||||
|
|
||||||
@ApiModelProperty("反审状态: 0-无 1-已反审(反审后status回退为1-已创建,重新审核通过自动复位0)")
|
|
||||||
private Integer reverseStatus;
|
|
||||||
|
|
||||||
@ApiModelProperty("反审人id")
|
|
||||||
private Long reverseBy;
|
|
||||||
|
|
||||||
@ApiModelProperty("反审人姓名")
|
|
||||||
private String reverseByName;
|
|
||||||
|
|
||||||
@ApiModelProperty("反审时间")
|
|
||||||
@JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss")
|
|
||||||
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
|
||||||
private Date reverseTime;
|
|
||||||
|
|
||||||
@ApiModelProperty("反审原因")
|
|
||||||
private String reverseRemark;
|
|
||||||
|
|
||||||
}
|
}
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user