40 Commits
Author SHA1 Message Date
王奎兴 8324d8dc31 发31 2026-09-14 11:09:46 +08:00
王奎兴 6ce35b58e4 发30 2026-09-14 11:05:55 +08:00
王奎兴 700556ea63 发31 2026-09-14 10:58:00 +08:00
王奎兴 100a8d87ac 上架过滤已逻辑删除数据; 2026-09-14 10:54:02 +08:00
王奎兴 b0c9a41f07 Merge remote-tracking branch 'origin/dev' into dev 2026-09-14 09:33:14 +08:00
王奎兴 82d5eda139 上架过滤已逻辑删除数据; 2026-09-14 09:33:01 +08:00
秦鸿展 07393e43ff 31 2026-09-13 18:26:40 +08:00
秦鸿展 08858f24d6 30 2026-09-13 18:22:47 +08:00
秦鸿展 a994241400 BI月台指标新增字段 2026-09-13 18:21:26 +08:00
王奎兴 a9be03961a feign地址修改; 2026-09-12 17:57:49 +08:00
王奎兴 7f6006ca48 feign地址修改; 2026-09-12 17:20:01 +08:00
赵辉 defc8c3709 31 2026-09-12 10:03:33 +08:00
王奎兴 3c21c2c848 发30 2026-09-12 10:00:45 +08:00
王奎兴 71936b50a7 Merge remote-tracking branch 'origin/dev' into dev 2026-09-12 09:59:56 +08:00
赵辉 9cfffe1224 去除验证码校验 2026-09-12 09:59:39 +08:00
王奎兴 d7574d188a 客户月结报告; 2026-09-12 09:59:30 +08:00
赵辉 1c1b06c1bf 去除验证码校验 2026-09-12 09:24:11 +08:00
rcx 117019c55c 30 2026-09-11 17:46:07 +08:00
rcx 171909b68d 31 2026-09-11 17:44:15 +08:00
赵辉 31c27c16c6 user31 2026-09-11 17:28:40 +08:00
赵辉 8dfe9545aa user30 2026-09-11 17:22:50 +08:00
赵辉 028afb57d7 用户-yms同步新增与修改密码 2026-09-11 15:45:15 +08:00
rcx 37dd374bda fix(wms): 入库单导入"该货主下不存在该料号"误报修复
- 根因:Excel客户名称按USER表user_name解析货主ID,同名双账号(如3519/3525)解析到非档案归属账号,带错误shipperId查物料必为空
- 料号匹配:主查询(料号+顶级组织+解析shipperId)为空时,去掉货主条件按档案shipper_name与Excel客户名称等值兜底匹配,命中后以档案货主纠正单据shipperId/shipperCode/shipperName
- 新增pickMaterialByCode挑选:料号精确等值优先于LIKE模糊命中,避免子串料号截胡
- SKU校验:档案条码barCode为空时跳过比对,档案有值时仍严格校验
- 校验失败输出诊断日志并附解析shipperId/登录topOrganizationId,区分货主错配(原因A)与组织口径(原因B)
2026-09-11 15:14:46 +08:00
秦鸿展 d69af9ef20 30 2026-09-10 16:49:24 +08:00
秦鸿展 9704dbfb07 导入物料组织覆盖问题 2026-09-10 16:20:59 +08:00
秦鸿展 3276792bb5 告警修改 2026-09-10 13:20:07 +08:00
秦鸿展 b57db4b8cc 30 2026-09-10 11:49:34 +08:00
秦鸿展 8a31ed9974 BI月台指标检测修改 2026-09-10 11:46:34 +08:00
秦鸿展 9777156959 31 2026-09-09 23:46:09 +08:00
秦鸿展 ba5d78b36c 准时率统计修改 2026-09-09 23:40:33 +08:00
秦鸿展 dea39a1a4b 30 2026-09-09 22:05:47 +08:00
秦鸿展 0493030620 BI月台作业准时率计算 2026-09-09 22:02:31 +08:00
秦鸿展 3907b126d9 31 2026-09-09 19:42:39 +08:00
秦鸿展 7b76d5c203 BI接口业务类型恢复 2026-09-09 19:38:47 +08:00
秦鸿展 f02a2d52f2 OMS调整接口开发 2026-09-09 16:24:05 +08:00
秦鸿展 a3c0f15e39 30 2026-09-09 15:19:29 +08:00
秦鸿展 d2a6a5a4f6 BI启动报错 2026-09-09 15:12:55 +08:00
秦鸿展 752216ad45 31 2026-09-09 14:22:58 +08:00
秦鸿展 6a8661da63 BI模块修改 2026-09-09 13:59:55 +08:00
秦鸿展 2b6777abe4 BI模块修改 2026-09-09 13:47:46 +08:00
177 changed files with 1826 additions and 3789 deletions
@@ -19,7 +19,8 @@ import java.util.Set;
/**
* 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 {
@@ -17,7 +17,8 @@ import org.springframework.web.bind.annotation.RequestParam;
import java.util.List;
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 {
@@ -26,7 +26,8 @@ import org.springframework.web.bind.annotation.*;
import java.util.List;
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 {
/**
@@ -21,7 +21,8 @@ import java.util.Map;
* @description: TODO
* @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 {
/**
@@ -133,27 +134,6 @@ public interface WmsServiceFeign {
@PostMapping(value = "/stockInOrderApi/omsCancelInOrder")
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查询物料列表")
@GetMapping("/materialBaseInfoApi/queryList")
public TableDataInfo getMaterialBaseInfoList(MaterialInfoDTO materialInfoDTO);
@@ -13,7 +13,8 @@ import org.springframework.web.bind.annotation.*;
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 {
@@ -9,7 +9,8 @@ import com.mhd.system.api.feign.FeignAutoConfiguration;
import org.springframework.cloud.openfeign.FeignClient;
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 {
/**
@@ -82,12 +82,6 @@ public class RemoteWmsFallbackFactory implements FallbackFactory<WmsServiceFeign
return AjaxResult.error("WMS取消下发清理失败:" + cause.getMessage());
}
@Override
public AjaxResult omsReverseExecutionOrder(StockOutOrder stockOutOrder) {
//返回错误而非静默成功,让OMS反审事务能感知失败并整体回滚
return AjaxResult.error("WMS出库执行单反审失败(服务降级):" + cause.getMessage());
}
@Override
public void omsAutoAssign(StockOutOrderDTO stockOutOrderDTO) {
@@ -116,12 +110,6 @@ public class RemoteWmsFallbackFactory implements FallbackFactory<WmsServiceFeign
return AjaxResult.error("WMS取消下发清理失败:" + cause.getMessage());
}
@Override
public AjaxResult omsReverseInOrder(StockInOrder stockInOrder) {
//返回错误而非静默成功,让OMS侧反审能感知回退失败并整体回滚(反审可重试,WMS回退幂等)
return AjaxResult.error("WMS入库单反审回退失败(服务降级):" + cause.getMessage());
}
@Override
public TableDataInfo getMaterialBaseInfoList(MaterialInfoDTO materialInfoDTO) {
TableDataInfo tableDataInfo = new TableDataInfo();
@@ -130,9 +130,11 @@ public class TokenLoginApplicationService {
//验证码登录校验验证码
String key = CacheConstants.SMS_LOGIN + userPhone;
Object object = redisService.getCacheObject(key) == null ? "":redisService.getCacheObject(key);
if(!ObjectUtil.equal(String.valueOf(object),verificationCode) && !ObjectUtil.equal(verificationCode, SmsConstants.universalCode)){
recordLogininfor(userPhone, Constants.LOGIN_FAIL, "验证码错误", 1);
throw new ServiceException("验证码错误");
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("验证码错误");
// }
}
//获取包名对应的业务(存在需要查询业务,不存在保存为无业务模式)
@@ -168,7 +170,13 @@ public class TokenLoginApplicationService {
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;
}
@@ -40,4 +40,7 @@ public class LoginDTO {
@ApiModelProperty(name = "组织名称(司机选择组织时传入)")
private String organizationName;
@ApiModelProperty(name = "微信标识")
private Integer wechatFlag;
}
+4 -4
View File
@@ -12,10 +12,10 @@ spring:
cloud:
nacos:
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.102.192.31:6848
server-addr: 10.102.192.31:6848
username: nacos
password: manhuoda@2023
#线上正式环境
@@ -23,8 +23,8 @@ spring:
# username: nacos
# password: manhuoda@2023
config:
server-addr: 127.0.0.1:8848
# server-addr: 10.102.192.31:6848
# server-addr: 127.0.0.1:8848
server-addr: 10.102.192.31:6848
# 测试环境配置 容器名+端口号
# server-addr: 10.33.0.129:6010
# 线上测试环境配置 容器名+端口号
@@ -7,6 +7,9 @@ import com.mhd.bi.domain.biPlatformRealData.repository.po.RealTaskLoadPO;
import com.mhd.bi.domain.biPlatformRealData.repository.po.RealBusinessTypeStatPO;
import com.mhd.bi.domain.biPlatformRealData.repository.po.RealPlatformFloorStatPO;
import com.mhd.bi.domain.biPlatformRealData.repository.po.RealPlatformInfoPO;
import com.mhd.bi.domain.biPlatformRealData.repository.po.RealOnTimeStatPO;
import com.mhd.bi.domain.biPlatformRealData.repository.po.RealTaskTypeStatPO;
import com.mhd.bi.domain.biPlatformRealData.repository.po.RealMonthlyTaskDurationPO;
import java.util.List;
@@ -26,18 +29,27 @@ public interface BiPlatformRealDataMapper {
/** 今日作业任务数 */
Long countTodayTasks();
/** 车辆状态统计(今日) */
/** 车辆状态统计(今日,含叫号状态合计 callStatusTotal = 已签到+已叫号+已过号 */
RealVehicleStatusPO queryVehicleStatusToday();
/** 本月任务量 */
Long countMonthTasks();
/** 本月任务平均时长 / 完成率统计 */
RealMonthlyTaskDurationPO queryMonthTaskStats();
/** 任务负荷(今日 24 小时) */
List<RealTaskLoadPO> queryTaskLoadToday();
/** 今日预约-业务类型统计(按 businessName 分组统计今日预约数量) */
List<RealBusinessTypeStatPO> queryTodayBusinessTypeStats();
/** 今日作业准时率统计(total 今日预约总数;onTimeCount 今日准时车辆数) */
RealOnTimeStatPO queryTodayOnTimeStats();
/** 任务类型统计(本月 YMS QMS_MAIN_BUSINESS 预约按业务类型 BUSINESS_NAME 分组) */
List<RealTaskTypeStatPO> queryMonthTransportOrderByType();
/** 月台监控-按楼层统计月台车辆(楼层、月台数量、今日预约车辆、当前作业车辆) */
List<RealPlatformFloorStatPO> queryPlatformFloorStats();
@@ -0,0 +1,29 @@
package com.mhd.bi.domain.biPlatformRealData.repository.po;
import lombok.Data;
import java.io.Serializable;
/**
* 本月任务平均时长 / 完成率统计(真实数据,来自 TEST_NGWL_YMS.QMS_MAIN_BUSINESS
* avgDurationHours:累计 (EXIT_TIME - ENTRY_TIME) 小时数(仅 ENTRY_TIME/EXIT_TIME 都不为空时参与)
* durationCount:参与平均时长统计的有效条数
* completedCount:已出场(EXIT_TIME IS NOT NULL)且预约日期在本月的数量
* totalCount:本月(TARGET_DATE)预约总数量
*/
@Data
public class RealMonthlyTaskDurationPO implements Serializable {
private static final long serialVersionUID = 1L;
/** 平均作业时长(小时) */
private Double avgDurationHours;
/** 参与平均时长统计的有效条数 */
private Long durationCount;
/** 本月已出场数量 */
private Long completedCount;
/** 本月预约总数量(按 TARGET_DATE 统计) */
private Long totalCount;
}
@@ -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;
}
@@ -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;
}
@@ -16,6 +16,12 @@ public class RealVehicleStatusPO implements Serializable {
/** 当前未签到 */
private Long notCheckedIn;
/** 当前等待作业(FLOW_STATUS IN '1','2','3' 已预约/已签到/已叫号) */
private Long waiting;
/** 叫号状态合计:已签到 + 已叫号 + 已过号(FLOW_STATUS IN '2','3','4',预约日期为今天) */
private Long callStatusTotal;
/** 当前作业中 */
private Long operatingVehicles;
@@ -9,12 +9,19 @@ 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.RealPlatformFloorStatPO;
import com.mhd.bi.domain.biPlatformRealData.repository.po.RealPlatformInfoPO;
import com.mhd.bi.domain.biPlatformRealData.repository.po.RealOnTimeStatPO;
import com.mhd.bi.domain.biPlatformRealData.repository.po.RealTaskTypeStatPO;
import com.mhd.bi.domain.biPlatformRealData.repository.po.RealMonthlyTaskDurationPO;
import com.mhd.bi.domain.biPlatformSurveillance.repository.mapper.BiPlatformSurveillanceReportMapper;
import com.mhd.bi.domain.biSnapshotSync.repository.mapper.BiSnapshotWriteMapper;
import com.mhd.bi.domain.biSnapshotSync.support.BiSnapshotWeeklyRandomDataBuilder;
import com.mhd.bi.interfaces.facadeApi.biReport.vo.platform.PlatformSurveillanceVO;
import com.mhd.bi.interfaces.facadeApi.biReport.vo.platform.PlatformVehicleItemVO;
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 org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
@@ -91,16 +98,27 @@ public class BiPlatformRealDataService {
if (vo.getPlatformOverview() != null) {
fp.put("totalPlatforms", vo.getPlatformOverview().getTotalPlatforms());
fp.put("operatingPlatforms", vo.getPlatformOverview().getOperatingPlatforms());
fp.put("currentOccupancyRate", vo.getPlatformOverview().getCurrentOccupancyRate());
fp.put("todayTasks", vo.getPlatformOverview().getTodayTasks());
}
if (vo.getEfficiencyStatistics() != null) {
fp.put("platformOnTimeRate", vo.getEfficiencyStatistics().getPlatformOnTimeRate());
}
if (vo.getVehicleStatus() != null) {
fp.put("todayReservedVehicles", vo.getVehicleStatus().getTodayReservedVehicles());
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("completedVehicles", vo.getVehicleStatus().getCompletedVehicles());
}
if (vo.getMonthlyTaskStatistics() != null) {
fp.put("taskTotal", vo.getMonthlyTaskStatistics().getTaskTotal());
fp.put("avgTaskDuration", vo.getMonthlyTaskStatistics().getAvgTaskDuration());
fp.put("taskCompletionRate", vo.getMonthlyTaskStatistics().getTaskCompletionRate());
}
if (vo.getVehicles() != null) {
List<Map<String, Object>> vehicles = new ArrayList<>();
@@ -126,6 +144,27 @@ public class BiPlatformRealDataService {
}
fp.put("taskLoadStatistics", loads);
}
if (vo.getTaskTypeStatistics() != null) {
Map<String, Object> m = new LinkedHashMap<>();
m.put("totalTasks", vo.getTaskTypeStatistics().getTotalTasks());
if (vo.getTaskTypeStatistics().getTaskTypes() != null) {
List<Map<String, Object>> types = new ArrayList<>();
for (TaskTypeCountItemVO it : vo.getTaskTypeStatistics().getTaskTypes()) {
Map<String, Object> tm = new LinkedHashMap<>();
tm.put("type", it.getType());
tm.put("count", it.getCount());
types.add(tm);
}
m.put("taskTypes", types);
}
fp.put("taskTypeStatistics", m);
}
// 月台告警统计:按业务要求恒为 0,纳入指纹以确保旧快照(可能含非0写死值)能被覆盖更新为 0
if (vo.getPlatformAlarmStatistics() != null) {
fp.put("todayAlarmTotal", vo.getPlatformAlarmStatistics().getTodayAlarmTotal());
fp.put("handled", vo.getPlatformAlarmStatistics().getHandled());
fp.put("unhandled", vo.getPlatformAlarmStatistics().getUnhandled());
}
return objectMapper.writeValueAsString(fp);
}
@@ -166,12 +205,34 @@ 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() {
try {
RealVehicleStatusPO po = biPlatformRealDataMapper.queryVehicleStatusToday();
if (po == null) po = new RealVehicleStatusPO();
if (po.getTodayReservedVehicles() == null) po.setTodayReservedVehicles(0L);
if (po.getNotCheckedIn() == null) po.setNotCheckedIn(0L);
if (po.getWaiting() == null) po.setWaiting(0L);
if (po.getCallStatusTotal() == null) po.setCallStatusTotal(0L);
if (po.getOperatingVehicles() == null) po.setOperatingVehicles(0L);
if (po.getCompletedVehicles() == null) po.setCompletedVehicles(0L);
return po;
@@ -180,10 +241,14 @@ public class BiPlatformRealDataService {
RealVehicleStatusPO po = new RealVehicleStatusPO();
po.setTodayReservedVehicles(0L);
po.setNotCheckedIn(0L);
po.setWaiting(0L);
po.setCallStatusTotal(0L);
po.setOperatingVehicles(0L);
po.setCompletedVehicles(0L);
return po;
}
}
public long countMonthTasks() {
@@ -196,6 +261,21 @@ public class BiPlatformRealDataService {
}
}
/**
* 本月任务平均时长 / 完成率统计:
* - avgDurationHours:累计(EXIT_TIME - ENTRY_TIME)小时数 / 参与数;任一为空的行不参与
* - taskCompletionRate:已完成(EXIT_TIME 不为空 且 预约日期在本月)/ 本月预约总数量 ×100
* 任一查询失败均返回 null,由调用方决定是否覆盖模板值。
*/
public RealMonthlyTaskDurationPO queryMonthTaskStats() {
try {
return biPlatformRealDataMapper.queryMonthTaskStats();
} catch (Exception e) {
log.error("【YMS】统计本月任务平均时长/完成率失败: {}", e.getMessage(), e);
return null;
}
}
public List<RealTaskLoadPO> queryTaskLoadToday() {
try {
return biPlatformRealDataMapper.queryTaskLoadToday();
@@ -205,6 +285,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}
@@ -271,29 +380,68 @@ public class BiPlatformRealDataService {
template.setVehicles(vehicleVos);
// 月台实时概览:真实数据源,无条件覆盖
// 总月台 / 占用月台 来源:YMS 月台管理列表 QMS_WINDOW_INFOJOB_STATUS=1 表示占用)
// 月台占用率 = 占用 / 全部月台
// 今日作业任务 来源:QMS_MAIN_BUSINESS 按预约时间 TARGET_DATE = 今天 的全部数量
// 作业准时率 = 今日(实际进场时间在预约日期当天的车辆数) / 今日预约车辆总数 × 100%
if (template.getPlatformOverview() != null) {
RealPlatformOverviewPO ov = queryPlatformOverview();
int total = ov.getTotalPlatforms().intValue();
int occ = ov.getOperatingPlatforms().intValue();
List<RealPlatformInfoPO> platformList = queryPlatformInfoList();
int total = platformList == null ? 0 : platformList.size();
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;
int todayTasks = (int) countTodayTasks();
template.getPlatformOverview().setTotalPlatforms(total);
template.getPlatformOverview().setOperatingPlatforms(occ);
template.getPlatformOverview().setCurrentOccupancyRate(rate);
template.getPlatformOverview().setTodayTasks((int) countTodayTasks());
template.getPlatformOverview().setTodayTasks(todayTasks);
// 作业准时率(实际进入时间 < 预约日期+预约结束时间 的车辆 / 今日预约总数 × 100% 取整)
if (template.getEfficiencyStatistics() != null) {
template.getEfficiencyStatistics().setPlatformOnTimeRate(calcTodayOnTimeRate());
}
}
// 作业车辆状态统计:真实数据源,无条件覆盖
// 作业车辆状态统计:真实数据源,无条件覆盖(含等待作业 waiting = 今日预约且 已预约/已签到/已叫号)
if (template.getVehicleStatus() != null) {
RealVehicleStatusPO vs = queryVehicleStatusToday();
template.getVehicleStatus().setTodayReservedVehicles(vs.getTodayReservedVehicles().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().setCompletedVehicles(vs.getCompletedVehicles().intValue());
}
// 本月任务统计:taskTotal 有真实数据源无条件覆盖;YoY 等无真实数据源保留模板写死值
// 本月任务统计:taskTotal / avgTaskDuration / taskCompletionRate 均有真实数据源,无条件覆盖;YoY 保留模板写死值
if (template.getMonthlyTaskStatistics() != null) {
template.getMonthlyTaskStatistics().setTaskTotal((int) countMonthTasks());
RealMonthlyTaskDurationPO monthStats = queryMonthTaskStats();
if (monthStats != null) {
if (monthStats.getAvgDurationHours() != null) {
// 保留两位小数
double v = monthStats.getAvgDurationHours();
template.getMonthlyTaskStatistics().setAvgTaskDuration(Math.round(v * 100.0) / 100.0);
}
Long total = monthStats.getTotalCount();
Long completed = monthStats.getCompletedCount();
if (total != null && total > 0 && completed != null) {
int rate = (int) Math.round(((double) completed.longValue() / total.longValue()) * 100.0);
template.getMonthlyTaskStatistics().setTaskCompletionRate(rate);
} else {
template.getMonthlyTaskStatistics().setTaskCompletionRate(0);
}
}
}
// 任务负荷:有真实数据源;真实为空则清空不用模板模拟,有数据则按真实小时覆盖
@@ -313,6 +461,9 @@ public class BiPlatformRealDataService {
}
}
// 任务类型统计:本月 YMS QMS_MAIN_BUSINESS 按业务类型 BUSINESS_NAME 分组(真实业务数据)
template.setTaskTypeStatistics(queryMonthTransportOrderByType());
return template;
}
@@ -87,7 +87,9 @@ public final class BiReportSnapshotMapperSupport {
.platformOverview(PlatformOverviewVO.builder()
.totalPlatforms(0).currentOccupancyRate(0d).operatingPlatforms(0).todayTasks(0).build())
.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())
.monthlyTaskStatistics(MonthlyTaskStatisticsVO.builder()
.taskTotal(0).taskTotalYoY(0).avgTaskDuration(0d).avgDurationYoY(0)
@@ -16,7 +16,7 @@ import com.mhd.bi.interfaces.facadeApi.biReport.vo.warehouseZone.WarehouseOperat
import com.mhd.bi.interfaces.facadeApi.biReport.vo.platform.PlatformVehicleItemVO;
import com.mhd.bi.domain.biPlatformRealData.service.BiPlatformRealDataService;
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.RealTaskLoadPO;
import lombok.RequiredArgsConstructor;
@@ -173,18 +173,31 @@ public class BiReportSnapshotSyncService {
}
// ====== 真实数据:月台实时概览 ======
RealPlatformOverviewPO ov = biPlatformRealDataService.queryPlatformOverview();
// 总月台 / 占用月台 来源:YMS 月台管理列表 QMS_WINDOW_INFOJOB_STATUS=1 表示占用)
// 月台占用率 = 占用 / 全部月台
// 今日作业任务 来源:QMS_MAIN_BUSINESS 按预约时间 TARGET_DATE = 今天 的全部数量
if (template.getPlatformOverview() != null) {
template.getPlatformOverview().setTotalPlatforms(ov.getTotalPlatforms().intValue());
template.getPlatformOverview().setOperatingPlatforms(ov.getOperatingPlatforms().intValue());
int total = ov.getTotalPlatforms().intValue();
int occ = ov.getOperatingPlatforms().intValue();
List<RealPlatformInfoPO> platformList = biPlatformRealDataService.queryPlatformInfoList();
int total = platformList == null ? 0 : platformList.size();
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;
int todayTasks = (int) biPlatformRealDataService.countTodayTasks();
template.getPlatformOverview().setTotalPlatforms(total);
template.getPlatformOverview().setOperatingPlatforms(occ);
template.getPlatformOverview().setCurrentOccupancyRate(rate);
}
long todayTasks = biPlatformRealDataService.countTodayTasks();
if (template.getPlatformOverview() != null) {
template.getPlatformOverview().setTodayTasks((int) todayTasks);
template.getPlatformOverview().setTodayTasks(todayTasks);
// 作业准时率 = 实际进入时间 < 预约日期+预约结束时间 的车辆 / 今日预约总数 × 100%(取整)
if (template.getEfficiencyStatistics() != null) {
template.getEfficiencyStatistics().setPlatformOnTimeRate(biPlatformRealDataService.calcTodayOnTimeRate());
}
}
// ====== 真实数据:作业车辆状态统计 ======
@@ -192,14 +205,36 @@ public class BiReportSnapshotSyncService {
if (template.getVehicleStatus() != null) {
template.getVehicleStatus().setTodayReservedVehicles(vs.getTodayReservedVehicles().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().setCompletedVehicles(vs.getCompletedVehicles().intValue());
}
// ====== 真实数据:本月任务统计 taskTotal ======
// ====== 真实数据:本月任务统计 taskTotal / avgTaskDuration / taskCompletionRate ======
long monthTasks = biPlatformRealDataService.countMonthTasks();
if (template.getMonthlyTaskStatistics() != null) {
template.getMonthlyTaskStatistics().setTaskTotal((int) monthTasks);
com.mhd.bi.domain.biPlatformRealData.repository.po.RealMonthlyTaskDurationPO monthStats =
biPlatformRealDataService.queryMonthTaskStats();
if (monthStats != null) {
if (monthStats.getAvgDurationHours() != null) {
double v = monthStats.getAvgDurationHours();
template.getMonthlyTaskStatistics().setAvgTaskDuration(Math.round(v * 100.0) / 100.0);
}
Long total = monthStats.getTotalCount();
Long completed = monthStats.getCompletedCount();
if (total != null && total > 0 && completed != null) {
int rate = (int) Math.round(((double) completed.longValue() / total.longValue()) * 100.0);
template.getMonthlyTaskStatistics().setTaskCompletionRate(rate);
} else {
template.getMonthlyTaskStatistics().setTaskCompletionRate(0);
}
}
}
// ====== 真实数据:任务负荷(今日 24 小时) ======
@@ -218,6 +253,9 @@ public class BiReportSnapshotSyncService {
}
}
// ====== 真实数据:任务类型统计(本月 YMS QMS_MAIN_BUSINESS 按业务类型 BUSINESS_NAME 分组) ======
template.setTaskTypeStatistics(biPlatformRealDataService.queryMonthTransportOrderByType());
return template;
}
@@ -155,10 +155,13 @@ public final class BiSnapshotWeeklyRandomDataBuilder {
VehicleStatusVO vs = VehicleStatusVO.builder()
.todayReservedVehicles(Math.max(0, jitterInt(Baseline.P_RESV, 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)))
.completedVehicles(Math.max(0, jitterInt(Baseline.P_DONE, r)))
.build();
List<AvgOperationDurationTrendItemVO> avgTrend = new ArrayList<>();
for (int i = 0; i < Baseline.P_MO_LABELS.length; i++) {
avgTrend.add(AvgOperationDurationTrendItemVO.builder()
@@ -185,13 +188,8 @@ public final class BiSnapshotWeeklyRandomDataBuilder {
.build());
}
// 月台告警:按业务要求,全部置 0(趋势/统计/分布均不生成写死数据)
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<>();
for (int i = 0; i < Baseline.P_TT_TYPES.length; i++) {
@@ -201,18 +199,11 @@ public final class BiSnapshotWeeklyRandomDataBuilder {
.build());
}
int todayAl = Math.max(0, jitterInt(Baseline.P_AL_TOT, r));
int handled = Math.max(0, jitterInt(Baseline.P_AL_H, r));
handled = Math.min(handled, todayAl);
int unhandled = Math.max(0, todayAl - handled);
int todayAl = 0;
int handled = 0;
int unhandled = 0;
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()
.vehicles(vehicles)
@@ -415,6 +406,8 @@ public final class BiSnapshotWeeklyRandomDataBuilder {
static final int P_TASKS = 418;
static final int P_RESV = 2_850;
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_DONE = 1_420;
static final String[] P_MO_LABELS = {"5月", "6月", "7月"};
@@ -20,6 +20,12 @@ public class VehicleStatusVO {
@ApiModelProperty("当前未签到,单位:辆")
private Integer notCheckedIn;
@ApiModelProperty("当前等待作业(已预约/已签到/已叫号),单位:辆")
private Integer waiting;
@ApiModelProperty("已签到+已叫号+已过号(FLOW_STATUS IN 2/3/4),单位:辆")
private Integer callStatusTotal;
@ApiModelProperty("当前作业中,单位:辆")
private Integer operatingVehicles;
+2 -2
View File
@@ -19,14 +19,14 @@ spring:
# username: nacos
# password: manhuoda@2023
#线上正式环境
server-addr: 10.102.192.30:6848
server-addr: 10.102.192.31:6848
username: nacos
password: manhuoda@2023
config:
# server-addr: 127.0.0.1:8848
# 线上测试环境配置 容器名+端口号
# server-addr: 10.33.0.129:6010
server-addr: 10.102.192.30:6848
server-addr: 10.102.192.31:6848
username: nacos
password: manhuoda@2023
#线上正式环境
@@ -40,35 +40,85 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
FROM NGWL_TEST_YMS.QMS_WINDOW_INFO
</select>
<!-- 今日作业任务:实际进入时间是今日的 -->
<!-- 今日作业任务:按预约时间 TARGET_DATE(今日)统计主业务记录数 -->
<select id="countTodayTasks" resultType="java.lang.Long">
SELECT COUNT(1)
FROM NGWL_TEST_YMS.QMS_MAIN_BUSINESS
WHERE ENTRY_TIME IS NOT NULL
AND TRUNC(ENTRY_TIME) = TRUNC(SYSDATE)
WHERE TARGET_DATE IS NOT NULL
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 &lt; 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>
<!-- 车辆状态统计:今日的统计(按创建时间 CREATE_TIME / 流程状态)
todayReservedVehicles 改为按预约日期 TARGET_DATE(其它 3 项保持 CREATE_TIME
waiting 等待作业:FLOW_STATUS IN ('1','2','3') 已预约/已签到/已叫号 且 预约日期 = 今天
callStatusTotal 叫号状态合计:已签到 + 已叫号 + 已过号 = FLOW_STATUS IN ('2','3','4') 且 预约日期 = 今天
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
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 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 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
FROM NGWL_TEST_YMS.QMS_MAIN_BUSINESS
</select>
<!-- 本月任务量:实际进入时间是本月的 -->
<!-- 本月任务量:按预约日期 TARGET_DATE(Y预约日期)统计本月预约总数量 -->
<select id="countMonthTasks" resultType="java.lang.Long">
SELECT COUNT(1)
FROM NGWL_TEST_YMS.QMS_MAIN_BUSINESS
WHERE ENTRY_TIME IS NOT NULL
AND TO_CHAR(ENTRY_TIME, 'YYYY-MM') = TO_CHAR(SYSDATE, 'YYYY-MM')
WHERE TARGET_DATE IS NOT NULL
AND TO_CHAR(TARGET_DATE, 'YYYY-MM') = TO_CHAR(SYSDATE, 'YYYY-MM')
</select>
<!-- 今日预约-业务名称统计:按 BUSINESS_NAME(业务名称)分组统计今日预约数量,按预约日期 TARGET_DATE 过滤 -->
<!-- 本月任务平均作业时长 / 完成率统计:
avgDurationHours 平均时长(小时)= AVG((EXIT_TIME - ENTRY_TIME) * 24)
仅 ENTRY_TIME 与 EXIT_TIME 都不为空时参与;
durationCount 参与平均时长统计的有效条数;
completedCount 本月(TARGET_DATE)已出场(EXIT_TIME IS NOT NULL)的数量;
totalCount 本月(TARGET_DATE)预约总数量。
-->
<select id="queryMonthTaskStats" resultType="com.mhd.bi.domain.biPlatformRealData.repository.po.RealMonthlyTaskDurationPO">
SELECT
AVG(CASE WHEN ENTRY_TIME IS NOT NULL AND EXIT_TIME IS NOT NULL
THEN (EXIT_TIME - ENTRY_TIME) * 24
END) AS avgDurationHours,
SUM(CASE WHEN ENTRY_TIME IS NOT NULL AND EXIT_TIME IS NOT NULL
AND TO_CHAR(ENTRY_TIME, 'YYYY-MM') = TO_CHAR(SYSDATE, 'YYYY-MM')
THEN 1 ELSE 0 END) AS durationCount,
SUM(CASE WHEN EXIT_TIME IS NOT NULL
AND TARGET_DATE IS NOT NULL
AND TO_CHAR(TARGET_DATE, 'YYYY-MM') = TO_CHAR(SYSDATE, 'YYYY-MM')
THEN 1 ELSE 0 END) AS completedCount,
SUM(CASE WHEN TARGET_DATE IS NOT NULL
AND TO_CHAR(TARGET_DATE, 'YYYY-MM') = TO_CHAR(SYSDATE, 'YYYY-MM')
THEN 1 ELSE 0 END) AS totalCount
FROM NGWL_TEST_YMS.QMS_MAIN_BUSINESS
</select>
<!-- 今日预约-业务类型统计:按 BUSINESS_NAME(业务类型名称)分组统计今日预约数量,按预约日期 TARGET_DATE 过滤 -->
<select id="queryTodayBusinessTypeStats" resultType="com.mhd.bi.domain.biPlatformRealData.repository.po.RealBusinessTypeStatPO">
SELECT
BUSINESS_NAME AS businessName,
@@ -102,6 +152,20 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
ORDER BY 1 DESC
</select>
<!-- 任务类型统计(来自 NGWL_TEST_YMS.QMS_MAIN_BUSINESS 预约登记表):
按本月预约车辆数(TARGET_DATE 在当前月)按 BUSINESS_NAME 业务类型分组统计 -->
<select id="queryMonthTransportOrderByType" resultType="com.mhd.bi.domain.biPlatformRealData.repository.po.RealTaskTypeStatPO">
SELECT
BUSINESS_NAME AS businessName,
COUNT(1) AS count
FROM NGWL_TEST_YMS.QMS_MAIN_BUSINESS
WHERE BUSINESS_NAME IS NOT NULL
AND TARGET_DATE IS NOT NULL
AND TO_CHAR(TARGET_DATE, 'YYYY-MM') = TO_CHAR(SYSDATE, 'YYYY-MM')
GROUP BY BUSINESS_NAME
ORDER BY COUNT(1) DESC
</select>
<!-- 任务负荷(今日 24 小时时段):按 EXTRACT(HOUR FROM ENTRY_TIME) 统计 -->
<select id="queryTaskLoadToday" resultType="com.mhd.bi.domain.biPlatformRealData.repository.po.RealTaskLoadPO">
SELECT
@@ -26,7 +26,8 @@ import java.io.InputStream;
import java.util.List;
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 {
//查询当前组织所有三方接口信息
@@ -13,16 +13,16 @@ spring:
cloud:
nacos:
discovery:
# server-addr: 127.0.0.1:8848
server-addr: 10.33.0.129:6010
server-addr: 127.0.0.1:8848
# server-addr: 10.33.0.129:6010
# server-addr: 10.102.192.31:6848
username: nacos
password: manhuoda@2023
#线上正式环境
# server-addr: 10.102.192.105:6848
config:
# server-addr: 127.0.0.1:8848
server-addr: 10.33.0.129:6010
server-addr: 127.0.0.1:8848
# server-addr: 10.33.0.129:6010
# server-addr: 10.102.192.31:6848
username: nacos
password: manhuoda@2023
@@ -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.queryDTO.UserDocumentWarningQueryDTO;
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.vo.QueryAllShipperInfoVo;
import lombok.extern.slf4j.Slf4j;
@@ -214,6 +215,61 @@ public class UserApplicationService {
@Autowired
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 查询用户列表
* @Author Alex
@@ -1971,6 +2027,11 @@ public class UserApplicationService {
if (StrUtil.isEmpty(userDO.getUserName())) {
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);
//给小程序注册用户分配默认普通用户角色must本组织没有则找上级
userEntity.setUserPassword("Aa123456"); // 三方同步需要密码
@@ -100,6 +100,7 @@ public class UserYmsDomainService {
ymsSysUserDTO.setPhonenumber(userEntity.getUserPhone());
ymsSysUserDTO.setAvatar(userEntity.getAvatar());
ymsSysUserDTO.setUserAccountType(userEntity.getUserAccountType());
ymsSysUserDTO.setPassword(userEntity.getUserPassword());
if (StringUtils.isNotBlank(userEntity.getRoleCode())){
ymsSysUserDTO.setRoleCodes(Arrays.asList(userEntity.getRoleCode().split(",")));
@@ -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.system.api.model.LoginUser;
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.vo.QueryAllShipperInfoVo;
import io.swagger.annotations.Api;
@@ -1037,4 +1038,16 @@ public class UserAPI extends BaseController {
public R<String> finShipperEnterpriseNamedByUserId(@PathVariable("userId") Long 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:
nacos:
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.102.192.31:6848
# server-addr: 10.102.192.31:6848
username: nacos
password: manhuoda@2023
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.102.192.31:6848
# server-addr: 10.102.192.31:6848
username: nacos
password: manhuoda@2023
group: DEFAULT_GROUP # 默认分组就是DEFAULT_GROUP,如果使用默认分组可以不配置
@@ -49,4 +49,8 @@ feign:
readTimeout: 120000
mhd-third-party-service:
connectTimeout: 10000
readTimeout: 120000
readTimeout: 120000
#wechat:
# miniapp:
# appId: wxc9dd2810a77e4e30
# appSecret: 9354ff1215a82785ef14f2355fbf2185
@@ -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);
}
}
}
@@ -659,7 +659,7 @@ public class BusinessDocumentOrder extends BaseVOEntity{
@Excel(name = "${comment}", readConverterExp = "$column.readConverterExp()")
private Date documentDate;
@ApiModelProperty( "审核状态 0-未审核 1-审核通过 2-已驳回")
@ApiModelProperty( "审核状态 0-未审核 1-审核通过 2-已驳回 3-调整待审核")
private Long reviewStatus;
@ApiModelProperty("审核时间")
@@ -825,4 +825,7 @@ public class BusinessDocumentOrder extends BaseVOEntity{
@ApiModelProperty("车次")
@Excel(name = "车次")
private String shuttleNo;
@ApiModelProperty("业务单调整状态 0-无 1-调整待审核 2-调整驳回 3-调整已通过")
private Integer adjustStatus;
}
@@ -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;
}
@@ -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> {
}
@@ -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;
}
@@ -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> {
}
@@ -501,6 +501,6 @@ public class ExecutionInMaterialDetailPO extends ExecutionStockInOrderBasePO {
private BigDecimal insureAmount;
@ApiModelProperty("货物类型:0-物料 1-半成品 2-成品")
@Excel(name = "货物类型", readConverterExp = "0=物料,1=半成品,2=成品")
@Excel(name = "货物类型")
private Integer goodsType;
}
@@ -1,7 +1,5 @@
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 lombok.Data;
@@ -17,34 +15,21 @@ import java.util.Date;
public class ExecutionInMaterialDetailWithOrderPO extends ExecutionInMaterialDetailPO {
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;
@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-审核通过")
@Excel(name = "入库单审核状态: 1-未审核 2-审核不通过 3-审核通过")
private Integer inOrderAuditStatus;
@ApiModelProperty("货主ID")
private Long orderShipperId;
@ApiModelProperty("货主编码")
@Excel(name = "货主编码")
private String orderShipperCode;
@ApiModelProperty("货主名称")
@Excel(name = "货主名称")
private String orderShipperName;
@ApiModelProperty("入库日期")
@JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8")
@Excel(name = "入仓日期", width = 30, dateFormat = "yyyy-MM-dd")
private Date warehouseDate;
}
@@ -45,12 +45,6 @@ public class ExecutionInMaterialDetailQueryDTO extends BaseVOEntity {
@ApiModelProperty("入库单类型编码")
private String inOrderTypeCode;
@ApiModelProperty("入库单类型编码(与inOrderTypeCode同义)")
private String orderTypeCode;
@ApiModelProperty("入库单类型名称(模糊查询)")
private String orderTypeName;
@ApiModelProperty("入库状态: 1-已创建 2-已审核 3-收货中 4-上架中 5-已入库 6-已取消 7-已关闭")
private Integer inStatus;
@@ -72,10 +66,4 @@ public class ExecutionInMaterialDetailQueryDTO extends BaseVOEntity {
@ApiModelProperty("物料名称")
private String materialName;
@ApiModelProperty("实际入仓日期 开始(yyyy-MM-dd,为空按建档时间兜底)")
private String warehouseDateStart;
@ApiModelProperty("实际入仓日期 结束(yyyy-MM-dd,为空按建档时间兜底)")
private String warehouseDateEnd;
}
@@ -78,12 +78,6 @@ public class QueryOrderOverStockDO extends BaseVOEntity {
@Excel(name = "入库单类型编码")
private String inOrderTypeCode;
@ApiModelProperty("入库单类型编码(与inOrderTypeCode同义)")
private String orderTypeCode;
@ApiModelProperty("入库单类型名称")
private String orderTypeName;
@ApiModelProperty("入库单类型名称")
@Excel(name = "入库单类型名称")
private String inOrderTypeName;
@@ -143,10 +137,4 @@ public class QueryOrderOverStockDO extends BaseVOEntity {
@ApiModelProperty("越库单状态 0:无状态 1:处理中 2:越库完成")
@Excel(name = "越库单状态 0:无状态 1:处理中 2:越库完成")
private Integer overStockStatus;
@ApiModelProperty("实际入仓日期 开始(yyyy-MM-dd,为空按建档时间兜底)")
private String warehouseDateStart;
@ApiModelProperty("实际入仓日期 结束(yyyy-MM-dd,为空按建档时间兜底)")
private String warehouseDateEnd;
}
@@ -85,21 +85,4 @@ public class ExecutionInMaterialDetailApplicationService {
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;
}
}
@@ -518,7 +518,4 @@ public class ExecutionOutMaterialDetail extends BaseVOEntity {
private String inLineNumGw;
private String opWhLocGw;
private String warehouseGw;
@ApiModelProperty("反审标记: 0-无 1-已反审(业务单反审时软删del_flag=2并打标记)")
private Integer reverseFlag;
}
}
@@ -1,7 +1,6 @@
package com.mhd.oms.domain.executionOutMaterialDetail.repository.po;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.mhd.common.core.annotation.Excel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import org.springframework.format.annotation.DateTimeFormat;
@@ -19,49 +18,34 @@ import java.util.Date;
public class ExecutionOutMaterialDetailWithOrderPO extends ExecutionOutMaterialDetailPO {
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;
@ApiModelProperty("出库单展示状态: 0-已创建 2-已审核 3-已驳回 4-已出库(WMS出库完成/推送创建时回写,前端状态列绑定此字段)")
@Excel(name = "单据状态", readConverterExp = "0=已创建,2=已审核,3=已驳回,4=已出库")
private Integer issueStatus;
@ApiModelProperty("出库单审核状态: 1-未审核 2-审核不通过 3-审核通过")
@Excel(name = "出库单审核状态: 1-未审核 2-审核不通过 3-审核通过")
private Integer outOrderAuditStatus;
@ApiModelProperty("货主ID")
private Long orderShipperId;
@ApiModelProperty("货主编码")
@Excel(name = "货主编码")
private String orderShipperCode;
@ApiModelProperty("货主名称")
@Excel(name = "货主名称")
private String orderShipperName;
@ApiModelProperty("出仓日期")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@Excel(name = "出仓日期", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss")
private Date orderOutboundDate;
@ApiModelProperty("出库时间")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@Excel(name = "出库时间", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss")
private Date orderOutboundTime;
@ApiModelProperty("保额")
@Excel(name = "保额")
private BigDecimal insureAmount;
@ApiModelProperty("货物类型:0-物料 1-半成品 2-成品")
@Excel(name = "货物类型", readConverterExp = "0=物料,1=半成品,2=成品")
private Integer goodsType;
@ApiModelProperty("货物种类(物料分类名称,多个逗号分隔)")
@Excel(name = "货物种类")
private String materialClassifyName;
}
@@ -45,12 +45,6 @@ public class ExecutionOutMaterialDetailQueryDTO extends BaseVOEntity {
@ApiModelProperty("出库单类型编码")
private String outOrderTypeCode;
@ApiModelProperty("出库单类型编码(与outOrderTypeCode同义)")
private String orderTypeCode;
@ApiModelProperty("出库单类型名称(模糊查询)")
private String orderTypeName;
@ApiModelProperty("出库状态: 1-已创建 2-已审核 3-部分分配 4-已分配 5-拣货中 6-波次中 7-拣货完成 8-复核中 9-已出库 10-已取消 11-已关闭")
private Integer outStatus;
@@ -72,10 +66,4 @@ public class ExecutionOutMaterialDetailQueryDTO extends BaseVOEntity {
@ApiModelProperty("物料名称")
private String materialName;
@ApiModelProperty("实际出仓日期 开始(yyyy-MM-dd,为空按建档时间兜底)")
private String outboundDateStart;
@ApiModelProperty("实际出仓日期 结束(yyyy-MM-dd,为空按建档时间兜底)")
private String outboundDateEnd;
}
@@ -459,21 +459,4 @@ public class ExecutionStockInOrder extends BaseVOEntity {
@ApiModelProperty("通知单备注")
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;
}
@@ -482,21 +482,4 @@ public class ExecutionStockInOrderPO extends BaseVOEntity {
private String khdm;
@ApiModelProperty("通知单备注")
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;
}
@@ -513,21 +513,4 @@ public class ExecutionStockInOrderDO extends BaseVOEntity {
private String businessPriceWay;
@ApiModelProperty("通知单备注")
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;
}
@@ -510,21 +510,4 @@ public class ExecutionStockInOrderDTO extends ExecutionStockInOrderBaseDTO {
private String businessPriceWay;
@ApiModelProperty("通知单备注")
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;
}
@@ -263,16 +263,7 @@ public class ExecutionStockInOrderApplicationService {
*/
public ExecutionStockInOrderPO getInfo(Long inOrderId)
{
return getInfo(inOrderId, false);
}
/**
* 获取入库执行单详情getReverseAuditInfo 归档详情复用
* @param archive true-查询已反审tab 归档数据
*/
public ExecutionStockInOrderPO getInfo(Long inOrderId, boolean archive)
{
ExecutionStockInOrderPO info = stockInOrderDomainService.getInfo(inOrderId, archive);
ExecutionStockInOrderPO info = stockInOrderDomainService.getInfo(inOrderId);
String userNcCode = reservationStockInOrderMapper.getUserNcCode(info.getShipperId());
info.setKhdm(userNcCode);
List<ExecutionInMaterialDetailPO> materialDetailList = info.getMaterialDetailList();
@@ -285,14 +276,6 @@ public class ExecutionStockInOrderApplicationService {
return info;
}
/**
* 查询入库执行单已反审tab 归档详情已软删+已反审标记的数据含软删明细
*/
public ExecutionStockInOrderPO getReverseAuditInfo(Long inOrderId)
{
return getInfo(inOrderId, true);
}
/**
@@ -314,31 +314,14 @@ public class ExecutionStockInOrderDomainService {
* 获取入库单详细信息
*/
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);
if (archive && (stockInOrderPO.getDelFlag() == null || stockInOrderPO.getDelFlag() != 2
|| !Integer.valueOf(1).equals(stockInOrderPO.getReverseAuditStatus()))) {
throw new ServiceException("入库执行单非已反审归档数据,无法查看归档详情");
}
ExecutionInMaterialDetailDO inMaterialDetailDO = new ExecutionInMaterialDetailDO();
String inOrderNumber = stockInOrderPO.getInOrderNumber();
List<BusinessDocumentOrder> businessDocumentOrders = businessDocumentOrderMapper.selectList(new LambdaQueryWrapper<BusinessDocumentOrder>().eq(BusinessDocumentOrder::getInOrderNumber, inOrderNumber).notIn(BusinessDocumentOrder::getOrderStatus,4,5));
stockInOrderPO.setBusinessDocumentOrderDOList(businessDocumentOrders);
inMaterialDetailDO.setInOrderNumber(inOrderNumber);
inMaterialDetailDO.setLevel(1);
if (archive) {
//归档明细已随主单软删(del_flag=2)放行软删明细行
inMaterialDetailDO.setDelFlag(2);
}
List<ExecutionInMaterialDetailPO> inMaterialDetailPOList = materialDetailService.queryList(inMaterialDetailDO);
// 先通过入库单号查询收货单列表
@@ -516,7 +516,4 @@ public class ExecutionStockOutOrder extends BaseVOEntity {
@ApiModelProperty("折扣")
private BigDecimal discount;
@ApiModelProperty("反审标记: 0-无 1-已反审(业务单反审时软删del_flag=2并打标记)")
private Integer reverseFlag;
}
}
@@ -102,12 +102,6 @@ public class QueryOrderOverStockDO extends BaseVOEntity {
@Excel(name = "出库单类型编码")
private String outOrderTypeCode;
@ApiModelProperty("出库单类型编码(与outOrderTypeCode同义)")
private String orderTypeCode;
@ApiModelProperty("出库单类型名称")
private String orderTypeName;
@ApiModelProperty("出库单类型名称")
@Excel(name = "出库单类型名称")
private String outOrderTypeName;
@@ -143,10 +137,4 @@ public class QueryOrderOverStockDO extends BaseVOEntity {
@ApiModelProperty("越库单状态 0:无状态 1:处理中 2:越库完成")
@Excel(name = "越库单状态 0:无状态 1:处理中 2:越库完成")
private Integer overStockStatus;
@ApiModelProperty("实际出仓日期 开始(yyyy-MM-dd,为空按建档时间兜底)")
private String outboundDateStart;
@ApiModelProperty("实际出仓日期 结束(yyyy-MM-dd,为空按建档时间兜底)")
private String outboundDateEnd;
}
@@ -456,21 +456,4 @@ public class ReservationStockInOrder extends BaseVOEntity {
@ApiModelProperty("业务计价方式")
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;
}
@@ -502,21 +502,4 @@ public class ReservationStockInOrderPO extends BaseVOEntity {
@ApiModelProperty("业务计价方式")
private String businessPriceWay;
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;
}
@@ -513,21 +513,4 @@ public class ReservationStockInOrderDO extends BaseVOEntity {
@ApiModelProperty("业务计价方式")
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;
}
@@ -507,21 +507,4 @@ public class ReservationStockInOrderDTO extends ReservationStockInOrderBaseDTO {
@ApiModelProperty("业务计价方式")
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;
}
@@ -282,7 +282,8 @@ public class ReservationStockInOrderApplicationService {
* @return Boolean
*/
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()) {
// ReservationStockInOrder stockInOrder = reservationStockInOrderMapper.selectById(inOrderIds.get(0));
// Integer needCustomsDeclaration = stockInOrder.getNeedCustomsDeclaration();
@@ -301,15 +302,6 @@ public class ReservationStockInOrderApplicationService {
return b;
}
/**
* 反审入库业务单业务单状态改为已驳回(issueStatus=3)并打已反审标记落入已反审tab
* 入库执行单+明细逻辑删除WMS侧整链回退库存扣减+单据清理+反审异常记录
* W入库单有出库记录时WMS侧拦截已推送关务直接拦截
*/
public Boolean reverseAudit(ReservationStockInOrderDO stockInOrderDO){
return stockInOrderDomainService.reverseAudit(stockInOrderDO);
}
/**
* @description 下发入库单
* @author ZhouGY
@@ -13,9 +13,6 @@ 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.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.repository.facade.IExecutionInMaterialDetailService;
import com.mhd.oms.domain.executionStockInOrder.entity.ExecutionStockInOrder;
@@ -94,10 +91,6 @@ public class ReservationStockInOrderDomainService {
private ExecutionStockInOrderMapper executionStockInOrderMapper;
@Autowired
private ReserveStockInOrderMapper reserveStockInOrderMapper;
@Autowired
private IElectronicSignatureService electronicSignatureService;
@Autowired
private IElectronicSignatureMaterialDetailService electronicSignatureMaterialDetailService;
/**
* 分页查询入库单列表
@@ -774,167 +767,6 @@ public class ReservationStockInOrderDomainService {
}
}
/**
* 反审入库业务单需求已入库/已出库的单子客户通知需要回退的场景单子回退到最原始状态
* 页面状态列按 issueStatus0-已创建 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侧逐执行单回退omsReverseInOrderW入库单有出库记录则拦截按入库单号+动作"分配库存/出库"
* 查库存调整记录&gt;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)
.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)
public Boolean executeAndIssue(ReservationStockInOrderDO stockInOrderDO) {
// 防重复执行校验 issueOrder 的防重逻辑对齐issueTime 有值表示已下发/执行过
@@ -515,21 +515,4 @@ public class ReservationStockOutOrder extends BaseVOEntity {
@ApiModelProperty("折扣")
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;
}
@@ -538,21 +538,4 @@ public class ReservationStockOutOrderPO extends BaseVOEntity {
@ApiModelProperty("折扣")
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;
}
@@ -591,19 +591,4 @@ public class ReservationStockOutOrderDO extends BaseVOEntity {
@ApiModelProperty("折扣")
private BigDecimal discount;
@ApiModelProperty("反审状态: 0-无 1-已反审(反审后status回退为1-已创建,重新审核通过自动复位0)")
private Integer reverseStatus;
@ApiModelProperty("反审人id")
private Long reverseBy;
@ApiModelProperty("反审人姓名")
private String reverseByName;
@ApiModelProperty("反审时间")
private Date reverseTime;
@ApiModelProperty("反审原因")
private String reverseRemark;
}
@@ -580,21 +580,4 @@ public class ReservationStockOutOrderDTO extends ReservationStockOutOrderBaseDTO
@ApiModelProperty("折扣")
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;
}
@@ -881,14 +881,6 @@ public class ReservationStockOutOrderApplicationService {
return stockOutOrderDomainService.cancelIssueOrder(stockOutOrderDO);
}
/**
* @description 反审出库业务单(已出库/已复核单据回退到已创建, WMS库存还原并生成反审异常记录)
* @date 2026/9/8
*/
public Boolean reverseAudit(ReservationStockOutOrderDO stockOutOrderDO){
return stockOutOrderDomainService.reverseAudit(stockOutOrderDO);
}
public Boolean executeAndIssue(ReservationStockOutOrderDO stockOutOrderDO){
return stockOutOrderDomainService.executeAndIssue(stockOutOrderDO);
}
@@ -48,8 +48,6 @@ import com.mhd.oms.domain.reservationStockInOrder.repository.mapper.ReservationS
import com.mhd.oms.domain.reservationStockInOrder.repository.po.MaterialBaseInfoPO;
import com.mhd.oms.domain.reservationStockInOrder.repository.todo.ReservationStockInOrderDO;
import com.mhd.oms.domain.reservationStockOutOrder.entity.ReservationStockOutOrder;
import com.mhd.oms.domain.reservationInventoryAdjustmentRecord.entity.ReservationInventoryAdjustmentRecord;
import com.mhd.oms.domain.reservationInventoryAdjustmentRecord.repository.mapper.ReservationInventoryAdjustmentRecordMapper;
import com.mhd.oms.domain.reservationStockOutOrder.repository.facade.IReservationStockOutOrderService;
import com.mhd.oms.domain.reservationStockOutOrder.repository.mapper.ReservationStockOutOrderMapper;
import com.mhd.oms.domain.reservationStockOutOrder.repository.po.ReservationStockOutOrderPO;
@@ -120,8 +118,6 @@ public class ReservationStockOutOrderDomainService {
private ReserveStockOutOrderMapper reserveStockOutOrderMapper;
@Autowired
private MaterialBaseInfoResolveService materialBaseInfoResolveService;
@Resource
private ReservationInventoryAdjustmentRecordMapper inventoryAdjustmentRecordMapper;
/**
* 分页查询出库单列表
@@ -413,8 +409,7 @@ public class ReservationStockOutOrderDomainService {
String userRealName = loginUser.getUserPo() != null && loginUser.getUserPo().getUserName() != null
? loginUser.getUserPo().getUserName()
: (loginUser.getRealname() != null ? loginUser.getRealname() : loginUser.getUsername());
boolean updateResult;
LambdaUpdateWrapper<ReservationStockOutOrder> auditUpdateWrapper = new UpdateWrapper<ReservationStockOutOrder>().lambda()
boolean updateResult = stockOutOrderService.update(null, new UpdateWrapper<ReservationStockOutOrder>().lambda()
.set(ReservationStockOutOrder::getReservationAuditId, loginUser.getUserid())
.set(ReservationStockOutOrder::getReservationAuditName, userRealName)
.set(ReservationStockOutOrder::getReservationAuditTime, new Date())
@@ -422,12 +417,7 @@ public class ReservationStockOutOrderDomainService {
.set(ReservationStockOutOrder::getUpdateByName, userRealName)
.set(ReservationStockOutOrder::getUpdateTime, new Date())
.set(ReservationStockOutOrder::getIssueStatus, issueStatus)
.in(ReservationStockOutOrder::getOutOrderId, stockOutOrderDO.getOutOrderIds());
// 重新审核通过时复位反审标记: 单据离开已反审页签回到正常流转
if (issueStatus == 2) {
auditUpdateWrapper.set(ReservationStockOutOrder::getReverseStatus, 0);
}
updateResult = stockOutOrderService.update(null, auditUpdateWrapper);
.in(ReservationStockOutOrder::getOutOrderId, stockOutOrderDO.getOutOrderIds()));
//审核通过时同步线路/车次到关联的运输业务单
if (issueStatus == 2) {
@@ -672,121 +662,6 @@ public class ReservationStockOutOrderDomainService {
return update;
}
/**
* @description 反审出库业务单(按前端展示字段 issueStatus 判断可反审范围: 2-已审核(未出库) / 4-已出库 均可反审;
* 0-已创建无需反审3-已驳回可直接编辑; status 字段在出库完成后不一定同步为9, 故不作为判断依据,
* 仅兜底排除 10-已取消/11-已关闭)
* 反审将单据回退到最原始状态(1-已创建, issueStatus=0)并打上反审标记:
* WMS 侧按出库单实际状态分支还原库存(已出库: 实物库存还原+推OMS; 未出库: 仅还原分配/冻结占用)
* 清理执行单据(出库单/明细/拣货/复核/交接/配送, 软删+reverseFlag=1 划归已反审tab)
* 每个执行出库单生成1条出库异常记录反审记录(out_order_abnormal, abnormalType=3);
* OMS 侧软删执行出库单及明细软删预约库存调整记录
* 反审后单据进入已反审页签(status=1 reverse_status=1), 可继续编辑/审核/撤销;
* 重新审核通过时 reverse_status 自动复位 0( auditState)
* @date 2026/9/8
*/
@Transactional(rollbackFor = Exception.class)
public Boolean reverseAudit(ReservationStockOutOrderDO stockOutOrderDO) {
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> outOrderIds = stockOutOrderDO.getOutOrderIds();
if (outOrderIds == null || outOrderIds.isEmpty()) {
throw new ServiceException("请选择需要反审的出库单");
}
String reverseRemark = stockOutOrderDO.getReverseRemark();
for (Long outOrderId : outOrderIds) {
ReservationStockOutOrder byId = stockOutOrderService.getById(outOrderId);
if (byId == null) {
throw new ServiceException("出库单不存在, outOrderId=" + outOrderId);
}
Integer status = byId.getStatus();
if (status != null && (status == 10 || status == 11)) {
throw new ServiceException("出库单[" + byId.getOutOrderNumber() + "]已取消/已关闭, 不能反审");
}
// 反审条件按前端展示字段 issueStatus 判断: 2-已审核(未出库) / 4-已出库 均可反审
Integer issueStatus = byId.getIssueStatus();
if (!Integer.valueOf(2).equals(issueStatus) && !Integer.valueOf(4).equals(issueStatus)) {
throw new ServiceException("出库单[" + byId.getOutOrderNumber() + "]当前状态(issueStatus=" + issueStatus
+ ")不支持反审, 仅已审核/已出库状态可反审");
}
// 逐个执行出库单调 WMS 反审: 还原实物库存+推送OMS库存清理WMS单据生成反审异常记录;
// 任一失败抛异常整体回滚, 避免单边反审
List<ExecutionStockOutOrder> executionOrders = executionStockOutOrderService.list(new QueryWrapper<ExecutionStockOutOrder>().lambda()
.eq(ExecutionStockOutOrder::getBusinessOutOrderNumber, byId.getOutOrderNumber())
.eq(ExecutionStockOutOrder::getDelFlag, 1));
for (ExecutionStockOutOrder executionStockOutOrder : executionOrders) {
String executionOutOrderNumber = executionStockOutOrder.getOutOrderNumber();
StockOutOrder wmsOutOrder = new StockOutOrder();
wmsOutOrder.setOutOrderNumber(executionOutOrderNumber);
// 反审原因经 remark 透传 WMS, 记入反审异常记录备注
wmsOutOrder.setRemark("业务单号:" + byId.getOutOrderNumber()
+ (reverseRemark != null && !reverseRemark.isEmpty() ? ",反审原因:" + reverseRemark : ""));
AjaxResult wmsResult = wmsServiceFeign.omsReverseExecutionOrder(wmsOutOrder);
if (wmsResult == null || !"200".equals(String.valueOf(wmsResult.get("code")))) {
throw new ServiceException("执行出库单[" + executionOutOrderNumber + "]WMS反审失败:"
+ (wmsResult == null ? "WMS服务不可用" : wmsResult.get("msg")));
}
// 软删执行出库单明细 + 执行出库单(与取消下发 cancelIssueOrder 一致)
List<ExecutionOutMaterialDetail> materialDetails = executionOutMaterialDetailService.list(new QueryWrapper<ExecutionOutMaterialDetail>().lambda()
.eq(ExecutionOutMaterialDetail::getOutOrderNumber, executionOutOrderNumber)
.eq(ExecutionOutMaterialDetail::getDelFlag, 1));
materialDetails.forEach(executionOutMaterialDetail -> {
executionOutMaterialDetailService.update(null, new UpdateWrapper<ExecutionOutMaterialDetail>().lambda()
.set(ExecutionOutMaterialDetail::getDelFlag, 2)
.set(ExecutionOutMaterialDetail::getReverseFlag, 1)
.eq(ExecutionOutMaterialDetail::getMaterialDetailId, executionOutMaterialDetail.getMaterialDetailId()));
});
executionStockOutOrderService.update(null, new UpdateWrapper<ExecutionStockOutOrder>().lambda()
.set(ExecutionStockOutOrder::getDelFlag, 2)
.set(ExecutionStockOutOrder::getReverseFlag, 1)
.eq(ExecutionStockOutOrder::getOutOrderNumber, executionOutOrderNumber));
// 软删预约库存调整记录(下发分配时生成): 仅软删留痕, 库存数量由 WMS omsEdit 推送还原
inventoryAdjustmentRecordMapper.update(null, new UpdateWrapper<ReservationInventoryAdjustmentRecord>().lambda()
.set(ReservationInventoryAdjustmentRecord::getDelFlag, 2)
.eq(ReservationInventoryAdjustmentRecord::getExecutionOrderNumber, executionOutOrderNumber)
.eq(ReservationInventoryAdjustmentRecord::getDelFlag, 1));
}
}
// 主单回退到已创建并打反审标记; 更新条件带 issueStatus in (2,4) + 排除已取消/已关闭 兜底防并发重复反审
// issueStatus 回退到 0-已创建(前端展示映射: 0-已创建 2-已审核 3-已驳回 4-已出库);
// 清空执行出库单号执行单已随反审软删, 前端"是否执行"列由该字段有无值推导, 不清空会仍显示已执行
return stockOutOrderService.update(null, new UpdateWrapper<ReservationStockOutOrder>().lambda()
.set(ReservationStockOutOrder::getStatus, 1)
.set(ReservationStockOutOrder::getIssueStatus, 0)
.set(ReservationStockOutOrder::getExecutionOutOrderNumber, null)
.set(ReservationStockOutOrder::getIssueId, null)
.set(ReservationStockOutOrder::getIssueName, null)
.set(ReservationStockOutOrder::getIssueTime, null)
.set(ReservationStockOutOrder::getReservationAuditId, null)
.set(ReservationStockOutOrder::getReservationAuditName, null)
.set(ReservationStockOutOrder::getReservationAuditTime, null)
.set(ReservationStockOutOrder::getAllocationQuantity, BigDecimal.ZERO)
.set(ReservationStockOutOrder::getAlreadyAllocationQuantity, BigDecimal.ZERO)
.set(ReservationStockOutOrder::getPickingQuantity, BigDecimal.ZERO)
.set(ReservationStockOutOrder::getCheckQuantity, BigDecimal.ZERO)
.set(ReservationStockOutOrder::getCheckStatus, 1)
.set(ReservationStockOutOrder::getCheckTaskDistribution, 2)
.set(ReservationStockOutOrder::getCheckTaskDistributionTime, null)
.set(ReservationStockOutOrder::getCompleteTime, null)
.set(ReservationStockOutOrder::getOutboundTime, null)
.set(ReservationStockOutOrder::getReverseStatus, 1)
.set(ReservationStockOutOrder::getReverseBy, loginUser.getUserid())
.set(ReservationStockOutOrder::getReverseByName, userRealName)
.set(ReservationStockOutOrder::getReverseTime, new Date())
.set(ReservationStockOutOrder::getReverseRemark, reverseRemark)
.set(ReservationStockOutOrder::getUpdateBy, loginUser.getUserid())
.set(ReservationStockOutOrder::getUpdateByName, userRealName)
.set(ReservationStockOutOrder::getUpdateTime, new Date())
.in(ReservationStockOutOrder::getOutOrderId, outOrderIds)
.in(ReservationStockOutOrder::getIssueStatus, 2, 4)
.notIn(ReservationStockOutOrder::getStatus, 10, 11));
}
@Transactional(rollbackFor = Exception.class)
public Boolean executeAndIssue(ReservationStockOutOrderDO stockOutOrderDO) {
LoginUser loginUser = SecurityUtils.getLoginUser();
@@ -22,7 +22,8 @@ import java.util.Map;
/**
* 三方服务 Feign
*/
@FeignClient(contextId = "thirdPartyServiceFeign",url = "http://10.33.0.129:8012", value = ServiceNameConstants.THIRDPARTY_CENTER, configuration = FeignAutoConfiguration.class)
// 目标地址由 nacos 配置项 feign.url.mhd-third-party-service 指定未配置时按服务名走服务发现
@FeignClient(contextId = "thirdPartyServiceFeign",url = "http://10.102.192.31:8012", value = ServiceNameConstants.THIRDPARTY_CENTER, configuration = FeignAutoConfiguration.class)
public interface ThirdPartyServiceFeign {
//查询当前组织所有三方接口信息
@@ -0,0 +1,24 @@
package com.mhd.oms.interfaces.dto.businessDocumentOrderAdjust;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.io.Serializable;
/**
* 运输业务单 调整 审核入参
*/
@Data
public class BusinessDocumentOrderAdjustAuditDTO implements Serializable {
private static final long serialVersionUID = 1L;
@ApiModelProperty("调整记录ID(必传)")
private Long adjustId;
@ApiModelProperty("审核结果 1-通过 2-驳回")
private Integer auditResult;
@ApiModelProperty("审核/驳回意见")
private String auditRemark;
}
@@ -0,0 +1,37 @@
package com.mhd.oms.interfaces.dto.businessDocumentOrderAdjust;
import com.mhd.oms.domain.businessDocumentOrder.entity.BusinessDocumentOrder;
import com.mhd.oms.domain.businessOrderAccount.BusinessOrderAccount;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.io.Serializable;
import java.util.List;
/**
* 运输业务单 调整提交入参
*
* 前端整单回传 business_document_order 全部字段 + 费用明细 business_order_account
* - amountChanged=true (本次修改了金额) -> 需要业务主管审核
* - amountChanged=false (仅改其它字段) -> 无需审核直接更新
*
* order: 前端把调整后业务单整单字段回传 id 定位deliveryFreight 合计可由后端按明细自动算
* feeDetailList: 调整后费用明细business_order_account amount 之和 = 主表 deliveryFreight
*/
@Data
public class BusinessDocumentOrderAdjustDTO implements Serializable {
private static final long serialVersionUID = 1L;
@ApiModelProperty("调整后业务单(整单字段,含 id 定位;金额合计 deliveryFreight 可由后端按明细自动算)")
private BusinessDocumentOrder order;
@ApiModelProperty("调整后费用明细(business_order_account)amount 之和作为主表 deliveryFreight 合计")
private List<BusinessOrderAccount> feeDetailList;
@ApiModelProperty("是否修改了金额(前端判定传入):true-需审核,false-直通")
private Boolean amountChanged;
@ApiModelProperty("调整原因")
private String adjustReason;
}
@@ -0,0 +1,36 @@
package com.mhd.oms.interfaces.dto.businessDocumentOrderAdjust;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.io.Serializable;
/**
* 运输业务单 调整记录 查询条件(管理列表用可不按订单查全部)
*/
@Data
public class BusinessDocumentOrderAdjustQueryDTO implements Serializable {
private static final long serialVersionUID = 1L;
@ApiModelProperty("业务单号(模糊)")
private String goodsNumber;
@ApiModelProperty("业务单ID")
private Long orderId;
@ApiModelProperty("是否需要审核 0-否 1-是")
private Integer isAudit;
@ApiModelProperty("审核状态 0-待审核 1-审核通过 2-驳回")
private Integer auditStatus;
@ApiModelProperty("调整人姓名(模糊)")
private String adjustByName;
@ApiModelProperty("所属组织ID(调整人/业务单所属组织)")
private Long organizationId;
@ApiModelProperty("一级组织ID(组织隔离用)")
private Long topOrganizationId;
}
@@ -0,0 +1,59 @@
package com.mhd.oms.interfaces.dto.businessDocumentOrderAdjust;
import com.mhd.oms.domain.businessDocumentOrderAdjustDetail.entity.BusinessDocumentOrderAdjustDetail;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.io.Serializable;
import java.util.Date;
/**
* 运输业务单 调整记录(主记录) 列表/详情返回 VO
*/
@Data
public class BusinessDocumentOrderAdjustRecordDTO implements Serializable {
private static final long serialVersionUID = 1L;
@ApiModelProperty("主记录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("审核状态 0-待审核 1-审核通过 2-驳回")
private Integer auditStatus;
@ApiModelProperty("审核人账号")
private String auditBy;
@ApiModelProperty("审核人姓名")
private String auditByName;
@ApiModelProperty("审核时间")
private Date auditTime;
@ApiModelProperty("审核/驳回意见")
private String auditRemark;
@ApiModelProperty("调整后整行快照明细(详情查询时带出)")
private BusinessDocumentOrderAdjustDetail detail;
}
@@ -159,17 +159,6 @@ public class ReservationStockOutOrderApi extends BaseController {
return AjaxResult.success(stockOutOrderApplicationService.cancelIssueOrder(stockOutOrderDO));
}
/**
* 反审出库单: 已出库/已复核(issueStatus=2已审核)的单据回退到已创建并打反审标记,
* WMS还原实物库存并生成出库异常记录反审记录, 单据划归已反审页签
*/
@ApiOperation("反审出库单")
@PostMapping(value = "/reverseAudit")
public AjaxResult reverseAudit(@RequestBody ReservationStockOutOrderDTO stockOutOrderDTO) {
ReservationStockOutOrderDO stockOutOrderDO = stockOutOrderAssembler.toDO(stockOutOrderDTO);
return AjaxResult.success(stockOutOrderApplicationService.reverseAudit(stockOutOrderDO));
}
@ApiOperation("下发出库单")
@PostMapping(value = "/executeAndIssue")
public AjaxResult executeAndIssue(@RequestBody ReservationStockOutOrderDTO stockOutOrderDTO) {
@@ -10,7 +10,12 @@ import org.springframework.web.bind.annotation.*;
import com.mhd.oms.interfaces.dto.businessDocumentOrder.BusinessDocumentOrderDTO;
import com.mhd.oms.domain.businessDocumentOrder.repository.todo.BusinessDocumentOrderDO;
import com.mhd.oms.domain.businessDocumentOrder.repository.po.BusinessDocumentOrderPO;
import com.mhd.oms.application.service.businessDocumentOrder.BusinessDocumentOrderAdjustService;
import com.mhd.oms.application.service.businessDocumentOrder.BusinessDocumentOrderApplicationService;
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.oms.interfaces.assembler.businessDocumentOrder.BusinessDocumentOrderAssembler;
import com.github.pagehelper.PageHelper;
import javax.annotation.Resource;
@@ -33,6 +38,9 @@ public class BusinessDocumentOrderApi extends BaseController{
@Resource
private BusinessDocumentOrderAssembler businessDocumentOrderAssembler;
@Resource
private BusinessDocumentOrderAdjustService businessDocumentOrderAdjustService;
/**
* 分页查询业务单列表
*/
@@ -161,7 +169,64 @@ public class BusinessDocumentOrderApi extends BaseController{
}
}
/**
* 订单调整 - 提交调整
* 若修改了金额字段则进入调整待审核否则直通更新
*/
@ApiOperation("订单调整 - 提交调整")
@PostMapping("/adjust")
public AjaxResult adjust(@RequestBody BusinessDocumentOrderAdjustDTO adjustDTO) {
try {
return businessDocumentOrderAdjustService.adjust(adjustDTO);
} catch (Exception e) {
e.printStackTrace();
return AjaxResult.error(e.getMessage());
}
}
/**
* 订单调整 - 调整记录列表(查全部可分页/按业务单号或审核状态筛选)
*/
@ApiOperation("订单调整 - 调整记录列表")
@GetMapping("/listAdjustRecord")
public TableDataInfo listAdjustRecord(BusinessDocumentOrderAdjustQueryDTO query,
@RequestParam(value = "pageNo", required = false, defaultValue = "1") Integer pageNo,
@RequestParam(value = "pageSize", required = false, defaultValue = "20") Integer pageSize) {
PageHelper.startPage(pageNo, pageSize);
List<BusinessDocumentOrderAdjustRecordDTO> list = businessDocumentOrderAdjustService.listAdjustRecord(query);
return getDataTable(list);
}
/**
* 订单调整 - 按业务单查询调整记录(供订单详情页展示)
*/
@ApiOperation("订单调整 - 按业务单查询调整记录")
@GetMapping("/listAdjustRecordByOrder/{orderId}")
public AjaxResult listAdjustRecordByOrder(@PathVariable("orderId") Long orderId) {
return AjaxResult.success(businessDocumentOrderAdjustService.listAdjustRecordByOrder(orderId));
}
/**
* 订单调整 - 调整记录详情
*/
@ApiOperation("订单调整 - 调整记录详情")
@GetMapping("/getAdjustRecord/{adjustId}")
public AjaxResult getAdjustRecord(@PathVariable("adjustId") Long adjustId) {
return AjaxResult.success(businessDocumentOrderAdjustService.getAdjustRecord(adjustId));
}
/**
* 订单调整 - 审核(通过/驳回)
*/
@ApiOperation("订单调整 - 审核")
@PostMapping("/auditAdjust")
public AjaxResult auditAdjust(@RequestBody BusinessDocumentOrderAdjustAuditDTO auditDTO) {
try {
return businessDocumentOrderAdjustService.auditAdjust(auditDTO);
} catch (Exception e) {
e.printStackTrace();
return AjaxResult.error(e.getMessage());
}
}
}
@@ -3,7 +3,6 @@ package com.mhd.oms.interfaces.facade.executionInMaterialDetail;
import com.mhd.common.core.web.controller.BaseController;
import com.mhd.common.core.web.domain.AjaxResult;
import com.mhd.common.core.web.page.TableDataInfo;
import com.mhd.common.core.utils.poi.ExcelUtil;
import com.mhd.oms.domain.executionInMaterialDetail.repository.po.ExecutionInMaterialDetailPO;
import com.mhd.oms.domain.executionInMaterialDetail.repository.po.ExecutionInMaterialDetailWithOrderPO;
import com.mhd.oms.domain.executionInMaterialDetail.repository.todo.ExecutionInMaterialDetailDO;
@@ -17,8 +16,6 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.net.URLEncoder;
import java.util.List;
/**
@@ -99,24 +96,4 @@ public class ExecutionInMaterialDetailApi extends BaseController {
return getDataTable(list);
}
/**
* 导出入库明细查询Excel关联入库执行单全量不分页
* SQL固定只统计已入库(5)单据可按单据类型(如退货入库tui_huo_ru_ku)与实际入仓日期区间过滤
*/
@ApiOperation("导出入库明细查询Excel")
@GetMapping("/exportWithOrder")
public void exportWithOrder(HttpServletResponse response, ExecutionInMaterialDetailQueryDTO queryDTO) throws Exception
{
//转换实体不分页导出全量
QueryOrderOverStockDO queryDO = inMaterialDetailAssembler.toQueryDO(queryDTO);
List<ExecutionInMaterialDetailWithOrderPO> list = inMaterialDetailApplicationService.exportInOrderDetailList(queryDO);
String fileName = URLEncoder.encode("入库明细查询", "UTF-8").replaceAll("\\+", "%20");
response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
response.setCharacterEncoding("utf-8");
response.setHeader("Content-disposition", "attachment;filename=" + fileName + ".xlsx");
ExcelUtil<ExecutionInMaterialDetailWithOrderPO> util = new ExcelUtil<>(ExecutionInMaterialDetailWithOrderPO.class);
util.exportExcel(response, list, "入库明细查询");
}
}
@@ -2,7 +2,6 @@ package com.mhd.oms.interfaces.facade.executionOutMaterialDetail;
import com.mhd.common.core.web.controller.BaseController;
import com.mhd.common.core.web.page.TableDataInfo;
import com.mhd.common.core.utils.poi.ExcelUtil;
import com.mhd.oms.domain.executionOutMaterialDetail.repository.po.ExecutionOutMaterialDetailWithOrderPO;
import com.mhd.oms.domain.executionOutMaterialDetail.repository.todo.ExecutionOutMaterialDetailQueryDTO;
import com.mhd.oms.domain.executionOutMaterialDetail.service.ExecutionOutMaterialDetailApplicationService;
@@ -15,8 +14,6 @@ import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.net.URLEncoder;
import java.util.List;
/**
@@ -44,23 +41,4 @@ public class ExecutionOutMaterialDetailApi extends BaseController {
List<ExecutionOutMaterialDetailWithOrderPO> list = outMaterialDetailApplicationService.queryOutOrderDetailList(queryDO);
return getDataTable(list);
}
/**
* 导出出库明细查询Excel关联出库执行单全量不分页
* SQL固定只统计已出库(9/12/13)单据可按单据类型与实际出仓日期区间过滤
*/
@ApiOperation("导出出库明细查询Excel")
@GetMapping("/exportWithOrder")
public void exportWithOrder(HttpServletResponse response, ExecutionOutMaterialDetailQueryDTO queryDTO) throws Exception {
//转换实体不分页导出全量
QueryOrderOverStockDO queryDO = outMaterialDetailAssembler.toQueryDO(queryDTO);
List<ExecutionOutMaterialDetailWithOrderPO> list = outMaterialDetailApplicationService.queryOutOrderDetailList(queryDO);
String fileName = URLEncoder.encode("出库明细查询", "UTF-8").replaceAll("\\+", "%20");
response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
response.setCharacterEncoding("utf-8");
response.setHeader("Content-disposition", "attachment;filename=" + fileName + ".xlsx");
ExcelUtil<ExecutionOutMaterialDetailWithOrderPO> util = new ExcelUtil<>(ExecutionOutMaterialDetailWithOrderPO.class);
util.exportExcel(response, list, "出库明细查询");
}
}
@@ -93,16 +93,6 @@ public class ExecutionStockInOrderApi extends BaseController {
return AjaxResult.success(stockInOrderApplicationService.getInfo(inOrderId));
}
/**
* 查询入库执行单已反审tab 归档详情已软删+已反审标记的数据含软删明细
*/
@ApiOperation("查询入库执行单已反审归档详情")
@GetMapping(value = "/getReverseAuditInfo/{inOrderId}")
public AjaxResult getReverseAuditInfo(@PathVariable("inOrderId") Long inOrderId)
{
return AjaxResult.success(stockInOrderApplicationService.getReverseAuditInfo(inOrderId));
}
/**
* 导入入库单
*/
@@ -122,19 +122,6 @@ public class ReservationStockInOrderApi extends BaseController {
return AjaxResult.success(stockInOrderApplicationService.auditState(stockInOrderDO));
}
/**
* 反审入库业务单已入库/已出库的单子客户通知需要回退的场景单子回退到最原始状态
* 业务单状态改为"已驳回"(issueStatus=3与审核不通过同语义可编辑重新审核重新下发)
* 并打已反审标记落入已反审tab入库执行单+明细软删并打已反审标记
* W入库单有出库记录时WMS侧拦截不允许反审已推送关务(pushStatus=3)直接拦截
*/
@ApiOperation("反审入库业务单")
@PostMapping(value = "/reverseAudit")
public AjaxResult reverseAudit(@RequestBody ReservationStockInOrderDTO stockInOrderDTO) {
ReservationStockInOrderDO stockInOrderDO = stockInOrderAssembler.toDO(stockInOrderDTO);
return AjaxResult.success(stockInOrderApplicationService.reverseAudit(stockInOrderDO));
}
/**
* 下发入库单
*/
+4 -4
View File
@@ -18,15 +18,15 @@ spring:
discovery:
# server-addr: 127.0.0.1:8848
# 线上测试环境配置 容器名+端口号
server-addr: 10.33.0.129:6010
# server-addr: 10.102.192.31:6848
# server-addr: 10.33.0.129:6010
server-addr: 10.102.192.31:6848
username: nacos
password: manhuoda@2023
config:
# server-addr: 127.0.0.1:8848
# 线上测试环境配置 容器名+端口号
server-addr: 10.33.0.129:6010
# server-addr: 10.102.192.31:6848
# server-addr: 10.33.0.129:6010
server-addr: 10.102.192.31:6848
username: nacos
password: manhuoda@2023
#线上正式环境
@@ -365,10 +365,6 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<resultMap type="com.mhd.oms.domain.executionInMaterialDetail.repository.po.ExecutionInMaterialDetailWithOrderPO" id="InMaterialDetailWithOrderResult" extends="MaterialDetailResult">
<result property="inOrderStatus" column="in_order_status" />
<result property="inOrderAuditStatus" column="in_order_audit_status" />
<result property="issueStatus" column="issue_status" />
<result property="materialClassifyName" column="material_classify_name" />
<result property="orderTypeCode" column="order_type_code" />
<result property="orderTypeName" column="order_type_name" />
<result property="orderShipperId" column="order_shipper_id" />
<result property="orderShipperCode" column="order_shipper_code" />
<result property="orderShipperName" column="order_shipper_name" />
@@ -407,15 +403,12 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
a.single_volume, a.single_gross_weight, a.lot_no,
a.drink_date, a.fire_insure_fee, a.unit_price,
a.line_num_gw, a.spec_gw, a.unit_gw, a.qty_gw, a.erp_curr_gw, a.erp_price_gw, a.amount_gw,
c.insure_amount, c.goods_type, c.material_classify_name,
c.insure_amount, c.goods_type,
b.shipper_id as order_shipper_id,
b.shipper_code as order_shipper_code,
b.shipper_name as order_shipper_name,
b.order_type_code,
b.order_type_name,
b.status as in_order_status,
b.audit_status as in_order_audit_status,
b.issue_status as issue_status,
b.warehouse_date
from execution_in_material_detail a
left join execution_stock_in_order b on a.in_order_number = b.in_order_number
@@ -457,28 +450,15 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<if test="inOrderTypeCode != null and inOrderTypeCode != ''">
and b.order_type_code = #{inOrderTypeCode}
</if>
<if test="orderTypeCode != null and orderTypeCode != ''">
and b.order_type_code = #{orderTypeCode}
<if test="inStatus != null ">
and b.status = #{inStatus}
</if>
<if test="orderTypeName != null and orderTypeName != ''">
and b.order_type_name like concat('%', #{orderTypeName}, '%')
</if>
<!-- 入库单展示状态issue_status: 0-已创建 2-已审核 3-已驳回 4-已入库(WMS回写status=5时同步为4)
"已入库"以issue_status=4为准(推送创建的单据直接置4status不一定为5 -->
and b.issue_status = 4
<if test="inOrderExpectStartTime != null">
and b.expect_time &gt;= #{inOrderExpectStartTime}
</if>
<if test="inOrderExpectEndTime != null">
and b.expect_time &lt;= #{inOrderExpectEndTime}
</if>
<!-- 实际入仓日期区间(为空的历史单按建档时间兜底),用于统计当天入库 -->
<if test="warehouseDateStart != null and warehouseDateStart != ''">
and date_format(IFNULL(b.warehouse_date, b.create_time), '%Y-%m-%d') &gt;= #{warehouseDateStart}
</if>
<if test="warehouseDateEnd != null and warehouseDateEnd != ''">
and date_format(IFNULL(b.warehouse_date, b.create_time), '%Y-%m-%d') &lt;= #{warehouseDateEnd}
</if>
and a.del_flag = 1
and b.del_flag = 1
</where>
@@ -454,10 +454,6 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
id="OutMaterialDetailWithOrderResult" extends="MaterialDetailResult">
<result property="outOrderStatus" column="out_order_status" />
<result property="outOrderAuditStatus" column="out_order_audit_status" />
<result property="issueStatus" column="issue_status" />
<result property="materialClassifyName" column="material_classify_name" />
<result property="orderTypeCode" column="order_type_code" />
<result property="orderTypeName" column="order_type_name" />
<result property="orderShipperId" column="order_shipper_id" />
<result property="orderShipperCode" column="order_shipper_code" />
<result property="orderShipperName" column="order_shipper_name" />
@@ -499,17 +495,14 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
a.stock_unit, a.stock_quantity, a.inventory_quantity,
a.line_num_gw, a.spec_gw, a.unit_gw, a.qty_gw,
a.erp_curr_gw, a.erp_price_gw, a.amount_gw, a.in_order_number_gw, a.in_line_num_gw,
c.insure_amount, c.goods_type, c.material_classify_name,
c.insure_amount, c.goods_type,
b.shipper_id as order_shipper_id,
b.shipper_code as order_shipper_code,
b.shipper_name as order_shipper_name,
b.order_type_code,
b.order_type_name,
b.OUTBOUND_DATE as order_outbound_date,
b.OUTBOUND_TIME as order_outbound_time,
b.status as out_order_status,
b.audit_status as out_order_audit_status,
b.issue_status as issue_status
b.audit_status as out_order_audit_status
from execution_out_material_detail a
left join execution_stock_out_order b on a.out_order_number = b.out_order_number
left join NGWL_TEST_WMS.material_base_info c on a.material_base_info_id = c.material_base_info_id
@@ -550,28 +543,15 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<if test="outOrderTypeCode != null and outOrderTypeCode != ''">
and b.order_type_code = #{outOrderTypeCode}
</if>
<if test="orderTypeCode != null and orderTypeCode != ''">
and b.order_type_code = #{orderTypeCode}
<if test="outStatus != null ">
and b.status = #{outStatus}
</if>
<if test="orderTypeName != null and orderTypeName != ''">
and b.order_type_name like concat('%', #{orderTypeName}, '%')
</if>
<!-- 出库单展示状态issue_status: 0-已创建 2-已审核 3-已驳回 4-已出库;
执行出库单status不随WMS出库完成流转(回写被注释)"已出库"以issue_status=4为准 -->
and b.issue_status = 4
<if test="outOrderExpectStartTime != null">
and b.expect_time &gt;= #{outOrderExpectStartTime}
</if>
<if test="outOrderExpectEndTime != null">
and b.expect_time &lt;= #{outOrderExpectEndTime}
</if>
<!-- 出库时间区间(统计当天出库):严格按出仓日期OUTBOUND_DATE过滤(页面所见即所筛) -->
<if test="outboundDateStart != null and outboundDateStart != ''">
and date_format(b.OUTBOUND_DATE, '%Y-%m-%d') &gt;= #{outboundDateStart}
</if>
<if test="outboundDateEnd != null and outboundDateEnd != ''">
and date_format(b.OUTBOUND_DATE, '%Y-%m-%d') &lt;= #{outboundDateEnd}
</if>
and a.del_flag = 1
and b.del_flag = 1
</where>
@@ -108,11 +108,6 @@
<result property="discount" column="DISCOUNT" />
<result property="isFreeManpowerFee" column="IS_FREE_MANPOWER_FEE" />
<result property="businessInOrderNumber" column="BUSINESS_IN_ORDER_NUMBER" />
<result property="reverseAuditStatus" column="REVERSE_AUDIT_STATUS" />
<result property="reverseAuditRemark" column="REVERSE_AUDIT_REMARK" />
<result property="reverseAuditBy" column="REVERSE_AUDIT_BY" />
<result property="reverseAuditByName" column="REVERSE_AUDIT_BY_NAME" />
<result property="reverseAuditTime" column="REVERSE_AUDIT_TIME" />
</resultMap>
@@ -150,8 +145,7 @@
a.WAREHOUSE_DATE, a.COMPLETION_TIME, a.ORDER_DATE,a.reservation_audit_time,a.reservation_audit_name
,a.reservation_audit_id,a.issue_name,a.issue_id,a.issue_time,a.issue_status,a.RESERVATION_ORDER_SOURCE,a.tms_order_number
,a.DIRECTOR_NAME ,a.DIRECTOR_PHONE,a.DIRECTOR_ID,a.STORAGE_TIME,a.in_quantity,
a.PUSH_TIME,a.PUSH_STATUS,a.PUSH_BY,a.PUSH_BY_NAME,
a.REVERSE_AUDIT_STATUS,a.REVERSE_AUDIT_REMARK,a.REVERSE_AUDIT_BY,a.REVERSE_AUDIT_BY_NAME,a.REVERSE_AUDIT_TIME
a.PUSH_TIME,a.PUSH_STATUS,a.PUSH_BY,a.PUSH_BY_NAME
</sql>
<sql id="joinStockInOrderPo">
@@ -294,7 +288,7 @@
and a.order_type_code = #{orderTypeCode}
</if>
<if test="orderTypeName != null and orderTypeName != ''">
and (a.ORDER_TYPE_NAME like concat('%', #{orderTypeName}, '%') or a.BUSINESS_TYPE like concat('%', #{orderTypeName}, '%') or a.ORDER_TYPE_CODE like concat('%', #{orderTypeName}, '%'))
and (a.BUSINESS_TYPE like concat('%', #{orderTypeName}, '%') or a.ORDER_TYPE_CODE like concat('%', #{orderTypeName}, '%'))
</if>
<if test="supplierId != null ">
and a.supplier_id = #{supplierId}
@@ -507,18 +501,9 @@
</if>
)
</if>
<!-- 反审状态过滤:入库执行单【已反审】tab 传 reverseAuditStatus=1,查询已软删且打反审标记的归档数据 -->
<choose>
<when test="reverseAuditStatus != null">
and a.REVERSE_AUDIT_STATUS = #{reverseAuditStatus}
and a.del_flag = 2
</when>
<otherwise>
<choose>
<when test="delFlag != null"> and a.del_flag = #{delFlag} </when>
<otherwise> and a.del_flag = 1 </otherwise>
</choose>
</otherwise>
<when test="delFlag != null"> and a.del_flag = #{delFlag} </when>
<otherwise> and a.del_flag = 1 </otherwise>
</choose>
</sql>
@@ -109,11 +109,6 @@
<result property="discount" column="DISCOUNT" />
<result property="isFreeManpowerFee" column="IS_FREE_MANPOWER_FEE" />
<result property="executionInOrderNumber" column="EXECUTION_IN_ORDER_NUMBER" />
<result property="reverseAuditStatus" column="REVERSE_AUDIT_STATUS" />
<result property="reverseAuditRemark" column="REVERSE_AUDIT_REMARK" />
<result property="reverseAuditBy" column="REVERSE_AUDIT_BY" />
<result property="reverseAuditByName" column="REVERSE_AUDIT_BY_NAME" />
<result property="reverseAuditTime" column="REVERSE_AUDIT_TIME" />
<!-- 饮用有效日期:queryList联查明细表聚合带出,其他查询无此列时不填充 -->
<result property="drinkDate" column="drink_date" />
</resultMap>
@@ -160,8 +155,7 @@
a.WAREHOUSE_DATE, a.COMPLETION_TIME, a.ORDER_DATE,a.reservation_audit_time,a.reservation_audit_name
,a.reservation_audit_id,a.issue_name,a.issue_id,a.issue_time,a.issue_status,a.RESERVATION_ORDER_SOURCE,a.tms_order_number
,a.DIRECTOR_NAME ,a.DIRECTOR_PHONE,a.DIRECTOR_ID,a.STORAGE_TIME,a.in_quantity,
a.PUSH_TIME,a.PUSH_STATUS,a.PUSH_BY,a.PUSH_BY_NAME,a.execution_in_order_number,
a.REVERSE_AUDIT_STATUS,a.REVERSE_AUDIT_REMARK,a.REVERSE_AUDIT_BY,a.REVERSE_AUDIT_BY_NAME,a.REVERSE_AUDIT_TIME
a.PUSH_TIME,a.PUSH_STATUS,a.PUSH_BY,a.PUSH_BY_NAME,a.execution_in_order_number
</sql>
<sql id="joinStockInOrderPo">
@@ -245,7 +239,7 @@
and a.notice_number = #{noticeNumber}
</if>
<if test="inOrderNumber != null and inOrderNumber != ''">
and a.in_order_number like concat('%', #{inOrderNumber}, '%')
and a.in_order_number = #{inOrderNumber}
</if>
<if test="status != null ">
and a.status = #{status}
@@ -280,10 +274,6 @@
<if test="issueStatus != null">
and a.issue_status = #{issueStatus}
</if>
<!-- 反审状态过滤:入库业务单【已反审】tab 传 reverseAuditStatus=1 -->
<if test="reverseAuditStatus != null">
and a.REVERSE_AUDIT_STATUS = #{reverseAuditStatus}
</if>
<if test="warehouseId != null ">
and a.warehouse_id = #{warehouseId}
</if>
@@ -303,7 +293,7 @@
and a.order_type_code = #{orderTypeCode}
</if>
<if test="orderTypeName != null and orderTypeName != ''">
and (a.ORDER_TYPE_NAME like concat('%', #{orderTypeName}, '%') or a.BUSINESS_TYPE like concat('%', #{orderTypeName}, '%') or a.ORDER_TYPE_CODE like concat('%', #{orderTypeName}, '%'))
and (a.BUSINESS_TYPE like concat('%', #{orderTypeName}, '%') or a.ORDER_TYPE_CODE like concat('%', #{orderTypeName}, '%'))
</if>
<if test="supplierId != null ">
and a.supplier_id = #{supplierId}
@@ -117,11 +117,6 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<result property="businessPriceWay" column="BUSINESS_PRICE_WAY" />
<result property="discount" column="DISCOUNT" />
<result property="totalOutboundQuantity" column="TOTAL_OUTBOUND_QUANTITY" />
<result property="reverseStatus" column="REVERSE_STATUS" />
<result property="reverseBy" column="REVERSE_BY" />
<result property="reverseByName" column="REVERSE_BY_NAME" />
<result property="reverseTime" column="REVERSE_TIME" />
<result property="reverseRemark" column="REVERSE_REMARK" />
</resultMap>
@@ -141,8 +136,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
,a.reservation_audit_id,a.issue_name,a.issue_id,a.issue_time,a.issue_status,a.tms_order_number,
a.DIRECTOR_NAME ,a.DIRECTOR_PHONE,a.DIRECTOR_ID,a.RESERVATION_ORDER_SOURCE,a.OUTBOUND_TIME,a.RETURN_QUANTITY,a.DELIVERY_NAME,a.CUSTOMER_NUMBER,a.INVOICE_NUMBER,a.RETURN_ORDER_NUMBER,a.TOTAL_AMOUNT,
a.ROUTE,a.PUSH_TIME,a.PUSH_STATUS,a.PUSH_BY,a.PUSH_BY_NAME,a.execution_out_order_number,a.LINE_CODE,a.LINE_NAME,a.SHUTTLE_NO,
a.TOTAL_WAREHOUSE_RENT,a.BUSINESS_CHARGE_TYPE,a.BUSINESS_PRICE_WAY,a.DISCOUNT,
a.REVERSE_STATUS,a.REVERSE_BY,a.REVERSE_BY_NAME,a.REVERSE_TIME,a.REVERSE_REMARK
a.TOTAL_WAREHOUSE_RENT,a.BUSINESS_CHARGE_TYPE,a.BUSINESS_PRICE_WAY,a.DISCOUNT
</sql>
@@ -184,21 +178,11 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<!-- 出库状态: 3-部分分配 4-已分配 5-拣货中 6-波次中 7-拣货完成 8-复核中-->
and a.status IN (3, 4, 5, 6, 7, 8)
</when>
<when test="status == -2 "> <!-- 已反审 -->
<!-- 反审后单据回退为 1-已创建 且打上反审标记, 与【已创建】页签互斥 -->
and a.status = 1 and a.reverse_status = 1
</when>
<when test="status == 1 "> <!-- 已创建: 排除已反审的单据(已划归【已反审】页签) -->
and a.status = 1 and (a.reverse_status is null or a.reverse_status = 0)
</when>
<otherwise>
and a.status = #{status}
</otherwise>
</choose>
</if>
<if test="reverseStatus != null ">
and a.reverse_status = #{reverseStatus}
</if>
<!-- 出库状态: 1-已创建 2-已审核 3-部分分配 4-已分配 5-拣货中 6-波次中 7-拣货完成 8-复核中 9-已出库 10-已取消 11-已关闭 -->
<if test="gtStatus != null ">
and a.status &gt; #{gtStatus}
@@ -32,6 +32,7 @@ import lombok.extern.slf4j.Slf4j;
import org.apache.poi.ss.formula.functions.T;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.text.ParseException;
import java.util.List;
@@ -157,14 +158,6 @@ public class HandoverTaskOrderApplicationService {
return handoverTaskOrderDomainService.getInfo(outTaskOrderId);
}
/**
* 获取交接作业单归档详情(已反审): 反审时交接单已软删, 已反审tab 查看归档详情
*/
public HandoverTaskOrderPO getReverseInfo(Long outTaskOrderId)
{
return handoverTaskOrderDomainService.getReverseInfo(outTaskOrderId);
}
/**
* 按作业单号获取交接作业单详细信息PDA
* 用于下发任务(taskType=7) trackingNumber 对应交接作业单的 taskNumber
@@ -213,6 +206,7 @@ public class HandoverTaskOrderApplicationService {
* @param handoverTaskOrderDO
* @return Boolean
*/
@Transactional(rollbackFor = Exception.class)
public Boolean completeHandover(HandoverTaskOrderDO handoverTaskOrderDO){
Boolean result = handoverTaskOrderDomainService.completeHandover(handoverTaskOrderDO);
List<MaterialInventoryParamDO> clearoutParamDOs = handoverTaskOrderDomainService.getLastClearoutParamDOs();
@@ -2,12 +2,9 @@ package com.mhd.wms.application.service.inMaterialDetail;
import com.mhd.common.security.utils.SecurityUtils;
import com.mhd.system.api.model.LoginUser;
import com.mhd.wms.domain.inMaterialDetail.repository.po.InMaterialDetailExportPO;
import com.mhd.wms.domain.inMaterialDetail.repository.po.InMaterialDetailPO;
import com.mhd.wms.domain.inMaterialDetail.repository.po.InMaterialDetailWithOrderPO;
import com.mhd.wms.domain.inMaterialDetail.repository.todo.InMaterialDetailDO;
import com.mhd.wms.domain.inMaterialDetail.service.InMaterialDetailDomainService;
import com.mhd.wms.domain.overStock.repository.todo.QueryOrderOverStockDO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@@ -42,51 +39,6 @@ public class InMaterialDetailApplicationService {
return inMaterialDetailDomainService.queryList(inMaterialDetailDO);
}
/**
* 入库明细查询关联入库单只统计已入库(5)单据
*/
public List<InMaterialDetailWithOrderPO> queryInOrderDetailList(QueryOrderOverStockDO queryOrderOverStockDO) {
LoginUser loginUser = SecurityUtils.getLoginUser();
if (loginUser != null){
Long topOrganizationId = loginUser.getUserPo().getTopOrganizationId();
if (topOrganizationId != null && topOrganizationId != 1){
queryOrderOverStockDO.setTopOrganizationId(loginUser.getUserPo().getTopOrganizationId());
}
}
return inMaterialDetailDomainService.queryInOrderDetailList(queryOrderOverStockDO);
}
/**
* 入库明细导出专用列集口径同 queryInOrderDetailList不分页
*/
public List<InMaterialDetailExportPO> exportInOrderDetailList(QueryOrderOverStockDO queryOrderOverStockDO) {
List<InMaterialDetailExportPO> list = inMaterialDetailDomainService.exportInOrderDetailList(setDataPermission(queryOrderOverStockDO));
// 货物种类=挂载分类的父级分类名称material_classify_name为分类路径("食品,饮料")取倒数第二段
// 仅一级分类(无父级)时取自身名称
for (InMaterialDetailExportPO po : list) {
String names = po.getMaterialClassifyName();
if (names != null && names.contains(",")) {
String[] parts = names.split(",");
po.setMaterialClassifyName(parts[parts.length - 2].trim());
}
}
return list;
}
/**
* 数据权限非平台超管(1)按登录人一级组织过滤
*/
private QueryOrderOverStockDO setDataPermission(QueryOrderOverStockDO queryOrderOverStockDO) {
LoginUser loginUser = SecurityUtils.getLoginUser();
if (loginUser != null){
Long topOrganizationId = loginUser.getUserPo().getTopOrganizationId();
if (topOrganizationId != null && topOrganizationId != 1){
queryOrderOverStockDO.setTopOrganizationId(topOrganizationId);
}
}
return queryOrderOverStockDO;
}
/**
* 新增物料明细
@@ -167,11 +167,7 @@ public class InvestigationManageApplicationService {
}
List<InvestigetionManageDetailPO> detailList = investigationManagePO.getInvestigetionManageDetailList();
// 物料编码相同的明细排在一起展示稳定排序同编码内保持原顺序仅排序不聚合各条明细独立
detailList.sort(Comparator.comparing(InvestigetionManageDetailPO::getMaterialCode,
Comparator.nullsLast(Comparator.naturalOrder())));
// 性能优化批量获取批次属性避免N+1查询问题
// 1. 收集所有唯一的materialBaseInfoId
Set<Long> materialBaseInfoIdSet = detailList.stream()
@@ -240,9 +236,8 @@ public class InvestigationManageApplicationService {
if (materialBaseInfoId != null && batchDetailMap.containsKey(materialBaseInfoId)) {
List<BatchDetailFeignPO> batchDetailFeignPOList = batchDetailMap.get(materialBaseInfoId);
// 用于跟踪已添加到列表中的batchDetailIdbatchDetailId为空的配置行改用标签去重不再丢弃
// 用于跟踪已添加到列表中的batchDetailId
Set<Long> addedBatchDetailIds = new HashSet<>();
Set<String> addedLabelKeys = new HashSet<>();
for (BatchDetailFeignPO batchDetailFeignPO : batchDetailFeignPOList) {
MaterialMoreDetailPO materialMoreDetailPO = new MaterialMoreDetailPO();
@@ -254,44 +249,40 @@ public class InvestigationManageApplicationService {
materialMoreDetailPO.setAttributeOption(batchDetailFeignPO.getAttributeOption());
materialMoreDetailPO.setRemark(batchDetailFeignPO.getRemark());
// 确保添加到列表中batchDetailId+标签双重去重batchDetailId为空的配置行也保留
// 确保添加到列表中使用batchDetailId来避免重复
Long batchDetailId = batchDetailFeignPO.getBatchDetailId();
String labelKey = batchDetailFeignPO.getBatchLabels() == null ? "" : batchDetailFeignPO.getBatchLabels().trim();
boolean duplicated = addedLabelKeys.contains(labelKey)
|| (batchDetailId != null && addedBatchDetailIds.contains(batchDetailId));
if (!duplicated) {
if (batchDetailId != null && !addedBatchDetailIds.contains(batchDetailId)) {
materialMoreDetailList.add(materialMoreDetailPO);
addedLabelKeys.add(labelKey);
if (batchDetailId != null) {
addedBatchDetailIds.add(batchDetailId);
}
addedBatchDetailIds.add(batchDetailId);
}
// 根据fieldName或batchLabels从库存表中获取对应的字段值
if (materialInventoryPO != null) {
String fieldValue = null;
String usedFieldName = null;
// 优先使用fieldName如果存在
if (StringUtils.isNotBlank(batchDetailFeignPO.getFieldName())) {
String usedFieldName = batchDetailFeignPO.getFieldName();
usedFieldName = batchDetailFeignPO.getFieldName();
fieldValue = getFieldValueByFieldName(materialInventoryPO, usedFieldName);
log.info("批次属性 batchDetailId={}, fieldName={}, 从库存表获取到的值={}",
log.info("批次属性 batchDetailId={}, fieldName={}, 从库存表获取到的值={}",
batchDetailFeignPO.getBatchDetailId(), usedFieldName, fieldValue);
}
// fieldName没取到值时回退按batchLabels映射字段名再取一次修复fieldName配置失效导致值永远为空
if (fieldValue == null && StringUtils.isNotBlank(batchDetailFeignPO.getBatchLabels())) {
}
// 如果fieldName为空尝试根据batchLabels映射字段名
else if (StringUtils.isNotBlank(batchDetailFeignPO.getBatchLabels())) {
String fieldNameByLabel = getFieldNameByBatchLabel(batchDetailFeignPO.getBatchLabels());
if (StringUtils.isNotBlank(fieldNameByLabel)) {
fieldValue = getFieldValueByFieldName(materialInventoryPO, fieldNameByLabel);
log.info("批次属性 batchDetailId={}, batchLabels={}, 映射字段名={}, 从库存表获取到的值={}",
batchDetailFeignPO.getBatchDetailId(), batchDetailFeignPO.getBatchLabels(),
fieldNameByLabel, fieldValue);
usedFieldName = fieldNameByLabel;
fieldValue = getFieldValueByFieldName(materialInventoryPO, usedFieldName);
log.info("批次属性 batchDetailId={}, batchLabels={}, 映射字段名={}, 从库存表获取到的值={}",
batchDetailFeignPO.getBatchDetailId(), batchDetailFeignPO.getBatchLabels(),
usedFieldName, fieldValue);
}
}
// 只有当获取到值时才更新attributeValue
if (fieldValue != null) {
materialMoreDetailPO.setAttributeValue(fieldValue);
log.info("设置更多属性:batchDetailId={}, batchLabels={}, attributeValue={}",
materialMoreDetailPO.getBatchDetailId(), materialMoreDetailPO.getBatchLabels(),
log.info("设置更多属性:batchDetailId={}, batchLabels={}, attributeValue={}",
materialMoreDetailPO.getBatchDetailId(), materialMoreDetailPO.getBatchLabels(),
materialMoreDetailPO.getAttributeValue());
}
}
@@ -315,29 +306,22 @@ public class InvestigationManageApplicationService {
return null;
}
// 批次标签到字段名的映射关系LinkedHashMap保证匹配优先级稳定长key放前面避免短标签模糊匹配被抢先误匹配
Map<String, String> labelToFieldNameMap = new LinkedHashMap<>();
labelToFieldNameMap.put("Batch Ref NO's", "batchRefNo");
labelToFieldNameMap.put("Sheet Ref NO's", "sheetRefNo");
labelToFieldNameMap.put("箱号/卡板号", "boxPalletNo");
// 批次标签到字段名的映射关系
Map<String, String> labelToFieldNameMap = new HashMap<>();
labelToFieldNameMap.put("Invoice No.", "invoiceNo");
labelToFieldNameMap.put("Invoice No", "invoiceNo");
labelToFieldNameMap.put("发票号", "invoiceNo");
labelToFieldNameMap.put("Batch Ref NO's", "batchRefNo");
labelToFieldNameMap.put("Batch Ref NO", "batchRefNo");
labelToFieldNameMap.put("批次参考号", "batchRefNo");
labelToFieldNameMap.put("Sheet Ref NO's", "sheetRefNo");
labelToFieldNameMap.put("Sheet Ref NO", "sheetRefNo");
labelToFieldNameMap.put("单据参考号", "sheetRefNo");
labelToFieldNameMap.put("箱号/卡板号", "boxPalletNo");
labelToFieldNameMap.put("箱号", "boxPalletNo");
labelToFieldNameMap.put("卡板号", "boxPalletNo");
labelToFieldNameMap.put("Batch Number", "batchNumber");
labelToFieldNameMap.put("Production Date", "productionDate");
labelToFieldNameMap.put("生产日期", "productionDate");
labelToFieldNameMap.put("Expiry Date", "expiryDate");
labelToFieldNameMap.put("EXP Date", "expiryDate");
labelToFieldNameMap.put("过期日期", "expiryDate");
labelToFieldNameMap.put("Batch No", "batchNumber");
labelToFieldNameMap.put("批次号", "batchNumber");
labelToFieldNameMap.put("入库日期", "createTime");
labelToFieldNameMap.put("入库时间", "createTime");
labelToFieldNameMap.put("存货日期", "inventoryDate");
labelToFieldNameMap.put("扩展字段1", "extAttr1");
labelToFieldNameMap.put("扩展字段2", "extAttr2");
@@ -350,16 +334,14 @@ public class InvestigationManageApplicationService {
return fieldName;
}
// 模糊匹配包含关系多个key命中时取最长的key保证同一标签映射结果稳定
String bestMatchKey = null;
// 模糊匹配包含关系
for (Map.Entry<String, String> entry : labelToFieldNameMap.entrySet()) {
if (batchLabel.contains(entry.getKey()) || entry.getKey().contains(batchLabel)) {
if (bestMatchKey == null || entry.getKey().length() > bestMatchKey.length()) {
bestMatchKey = entry.getKey();
}
return entry.getValue();
}
}
return bestMatchKey != null ? labelToFieldNameMap.get(bestMatchKey) : null;
return null;
}
/**
@@ -573,10 +573,11 @@ public class MaterialBaseInfoApplicationService {
normalizeImportBarCodeWhenDuplicateOfHs(row);
fillIdsFromExistingMasterData(row);
fillOrganizationFromShipperIfNeeded(row);
if (!isValidOrgId(row.getOrganizationId()) && isValidOrgId(loginOrgId)) {
// 登录组织优先以登录账号的组织为准覆盖货主解析带来的组织避免用货主组织导致包装规格等主数据查不到
if (isValidOrgId(loginOrgId)) {
row.setOrganizationId(loginOrgId);
}
if (row.getTopOrganizationId() == null && isValidOrgId(loginTopOrgId)) {
if (isValidOrgId(loginTopOrgId)) {
row.setTopOrganizationId(loginTopOrgId);
}
fillOrganizationName(row, loginUser);
@@ -128,10 +128,11 @@ public class MaterialBaseInfoAsyncService {
materialBaseInfoApplicationService.normalizeImportBarCodeWhenDuplicateOfHs(row);
materialBaseInfoApplicationService.fillIdsFromExistingMasterData(row);
materialBaseInfoApplicationService.fillOrganizationFromShipperIfNeeded(row);
if (!isValidOrgId(row.getOrganizationId()) && isValidOrgId(loginOrgId)) {
// 登录组织优先以登录账号的组织为准覆盖货主解析带来的组织避免用货主组织(如2841)导致包装规格等主数据查不到
if (isValidOrgId(loginOrgId)) {
row.setOrganizationId(loginOrgId);
}
if (row.getTopOrganizationId() == null && isValidOrgId(loginTopOrgId)) {
if (isValidOrgId(loginTopOrgId)) {
row.setTopOrganizationId(loginTopOrgId);
}
materialBaseInfoApplicationService.fillOrganizationName(row, loginUser);
@@ -1,54 +0,0 @@
package com.mhd.wms.application.service.outMaterialDetail;
import com.mhd.common.security.utils.SecurityUtils;
import com.mhd.system.api.model.LoginUser;
import com.mhd.wms.domain.outMaterialDetail.repository.po.OutMaterialDetailExportPO;
import com.mhd.wms.domain.outMaterialDetail.repository.po.OutMaterialDetailWithOrderPO;
import com.mhd.wms.domain.outMaterialDetail.service.OutMaterialDetailDomainService;
import com.mhd.wms.domain.overStock.repository.todo.QueryOrderOverStockDO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
/**
* 出库物料明细ApplicationService
*
* @author rcx
* @date 2026-09-09
*/
@Service
@Slf4j
public class OutMaterialDetailApplicationService {
@Autowired
private OutMaterialDetailDomainService outMaterialDetailDomainService;
/**
* 出库明细查询关联出库单只统计已出库(9/12/13)单据
*/
public List<OutMaterialDetailWithOrderPO> queryOutOrderDetailList(QueryOrderOverStockDO queryOrderOverStockDO) {
return outMaterialDetailDomainService.queryOutOrderDetailList(setDataPermission(queryOrderOverStockDO));
}
/**
* 出库明细导出专用列集口径同 queryOutOrderDetailList不分页
*/
public List<OutMaterialDetailExportPO> exportOutOrderDetailList(QueryOrderOverStockDO queryOrderOverStockDO) {
return outMaterialDetailDomainService.exportOutOrderDetailList(setDataPermission(queryOrderOverStockDO));
}
/**
* 数据权限非平台超管(1)按登录人一级组织过滤
*/
private QueryOrderOverStockDO setDataPermission(QueryOrderOverStockDO queryOrderOverStockDO) {
LoginUser loginUser = SecurityUtils.getLoginUser();
if (loginUser != null){
Long topOrganizationId = loginUser.getUserPo().getTopOrganizationId();
if (topOrganizationId != null && topOrganizationId != 1){
queryOrderOverStockDO.setTopOrganizationId(topOrganizationId);
}
}
return queryOrderOverStockDO;
}
}
@@ -282,18 +282,11 @@ public class PickingOrderApplicationService {
setMaterialMoreDetailListRecursively(pickingMaterialDetailPOList, batchDetailMap);
pickingOrderPO.setMaterialDetailList(pickingMaterialDetailPOList);
log.info("返回拣货单信息,pickingOrderId={}, materialDetailList大小={}",
pickingOrderPO.getPickingOrderId(),
log.info("返回拣货单信息,pickingOrderId={}, materialDetailList大小={}",
pickingOrderPO.getPickingOrderId(),
pickingMaterialDetailPOList != null ? pickingMaterialDetailPOList.size() : 0);
return pickingOrderPO;
}
/**
* 获取拣货单归档详情(已反审): 反审时拣货单已软删(del_flag=2), 已反审tab 查看归档详情
*/
public PickingOrderPO getReverseInfoByIdAndType(Long pickingOrderId, Integer type) {
return pickingOrderDomainService.getReverseInfoByIdAndType(pickingOrderId, type);
}
/**
* 递归为物料明细设置更多属性
@@ -186,27 +186,6 @@ public class ReviewOrderApplicationService {
header.setMaterialDetailList(details);
return header;
}
/**
* 获取复核单归档详情(已反审): 反审时复核单/明细均已软删(del_flag=2), 已反审tab 查看归档详情
*/
public ReviewOrderPO getReverseDetailByReviewOrderId(Long reviewOrderId) {
if (reviewOrderId == null) {
throw new ServiceException("复核单ID不能为空");
}
ReviewOrderPO header = reviewOrderMapper.selectHeaderByReviewOrderIdReverse(reviewOrderId);
if (header == null) {
throw new ServiceException("复核单不存在");
}
List<ReviewMaterialDetailPO> details = reviewOrderMapper.queryDetailByReviewOrderIdReverse(reviewOrderId);
fillDisplayQtyFields(details);
Map<Long, List<BatchDetailFeignPO>> batchDetailMap = loadDisplayBatchDetailMap(details);
fillDynamicBatchDisplayFields(details, batchDetailMap);
buildReviewMaterialMoreDetailListLikeShelf(details, batchDetailMap);
fillHeaderSummary(header, details);
header.setMaterialDetailList(details);
return header;
}
public ReviewOrderPO getDetailByReviewOrderNumber(String reviewOrderNumber) {
@@ -667,16 +667,7 @@ public class StockInOrderApplicationService {
*/
public StockInOrderPO getInfo(Long inOrderId)
{
return getInfo(inOrderId, false);
}
/**
* 获取入库单详情
* @param archive true-查询已反审tab 归档数据已软删+已反审标记明细放行软删行
*/
public StockInOrderPO getInfo(Long inOrderId, boolean archive)
{
StockInOrderPO info = stockInOrderDomainService.getInfo(inOrderId, archive);
StockInOrderPO info = stockInOrderDomainService.getInfo(inOrderId);
String userNcCode = stockOutOrderMapper.getUserNcCode(info.getShipperId());
info.setKhdm(userNcCode);
List<InMaterialDetailPO> materialDetailList = info.getMaterialDetailList();
@@ -771,14 +762,6 @@ public class StockInOrderApplicationService {
return info;
}
/**
* 查询入库单已反审tab 归档详情已软删+已反审标记的数据含软删明细/收货单/上架单
*/
public StockInOrderPO getReverseAuditInfo(Long inOrderId)
{
return getInfo(inOrderId, true);
}
/**
@@ -972,14 +955,6 @@ public class StockInOrderApplicationService {
stockInOrderDomainService.cancelExecutionOrder(stockInOrder);
}
/**
* OMS入库业务单反审WMS侧回退已完成单据出库拦截 -> 回退库存 ->
* 逻辑删除收货/上架链路 -> 写入库异常反审记录已产生出库则报错拦截
*/
public void omsReverseInOrder(StockInOrder stockInOrder){
stockInOrderDomainService.reverseExecutionOrder(stockInOrder);
}
/**
* @description 取消入库单
* @author ZhouGY
@@ -2065,21 +2040,71 @@ public class StockInOrderApplicationService {
r.getMaterialCode(), topOrganizationId, shipperId);
List<MaterialBaseInfoPO> materialList = materialBaseInfoService.queryList(queryDO);
log.info("料号查询结果,查询到 {} 条记录", materialList != null ? materialList.size() : 0);
MaterialBaseInfoPO materialBaseInfoPO = null;
if (materialList != null && !materialList.isEmpty()) {
materialBaseInfoPO = materialList.get(0);
MaterialBaseInfoPO materialBaseInfoPO = pickMaterialByCode(materialList, r.getMaterialCode(), shipperId, order.getShipperName());
// 兜底按名称解析出的shipperId可能与物料档案shipper_id不一致系统中存在同名货主账号
// 按user_name精确匹配解析到了另一个同名列货主此时去掉货主ID条件再查一次
// 用物料档案冗余的shipper_name与Excel客户名称等值匹配
if (materialBaseInfoPO == null && StringUtils.isNotBlank(order.getShipperName())) {
MaterialBaseInfoDO fallbackDO = new MaterialBaseInfoDO();
fallbackDO.setMaterialCode(r.getMaterialCode());
if (topOrganizationId != null) {
fallbackDO.setTopOrganizationId(topOrganizationId);
}
List<MaterialBaseInfoPO> fallbackList = materialBaseInfoService.queryList(fallbackDO);
materialBaseInfoPO = pickMaterialByCode(fallbackList, r.getMaterialCode(), null, order.getShipperName());
if (materialBaseInfoPO != null) {
log.warn("导入料号校验:按解析shipperId未匹配到物料,已按档案货主名称兜底匹配。料号: [{}], 解析shipperId: {}, 档案shipperId: {}, 档案shipperName: {}",
r.getMaterialCode(), shipperId, materialBaseInfoPO.getShipperId(), materialBaseInfoPO.getShipperName());
// 以档案货主为准纠正单据货主信息避免后续shipperParam按错误的shipperId反查覆盖货主名称
if (materialBaseInfoPO.getShipperId() != null) {
shipperId = materialBaseInfoPO.getShipperId();
order.setShipperId(shipperId);
}
if (StringUtils.isNotBlank(materialBaseInfoPO.getShipperCode())) {
order.setShipperCode(materialBaseInfoPO.getShipperCode());
}
if (StringUtils.isNotBlank(materialBaseInfoPO.getShipperName())) {
order.setShipperName(materialBaseInfoPO.getShipperName());
}
}
}
if (materialBaseInfoPO != null) {
materialBaseInfoId = materialBaseInfoPO.getMaterialBaseInfoId();
log.info("通过料号查询到物料基础信息,料号: {}, 物料ID: {}, 货主ID: {}",
log.info("通过料号查询到物料基础信息,料号: {}, 物料ID: {}, 货主ID: {}",
r.getMaterialCode(), materialBaseInfoId, shipperId);
} else {
// 如果提供了料号但查询不到或不属于该货主直接报错不允许导入
String errorMsg = String.format("导入失败:该货主下不存在该料号(货主名称=%s,料号=%s)。请确保该料号已在物料管理中创建,且属于该货主",
order.getShipperName(), r.getMaterialCode());
// 诊断对照查询仅用于日志定位不影响流程去掉货主ID条件再查一次
// 用于区分两类原因A-按名称解析出的shipperId与物料档案shipper_id不一致货主错配
// B-登录人topOrganizationId与物料档案top_organization_id不一致组织口径不一致
try {
MaterialBaseInfoDO diagDO = new MaterialBaseInfoDO();
diagDO.setMaterialCode(r.getMaterialCode());
if (topOrganizationId != null) {
diagDO.setTopOrganizationId(topOrganizationId);
}
List<MaterialBaseInfoPO> diagList = materialBaseInfoService.queryList(diagDO);
if (diagList != null && !diagList.isEmpty()) {
MaterialBaseInfoPO diagPo = diagList.get(0);
log.error("导入料号校验诊断:去掉货主条件后可查到物料,判定为货主解析错配(原因A)。料号: [{}], 解析shipperId: {}, 登录topOrganizationId: {}, 物料ID: {}, 档案shipperId: {}, 档案shipperName: {}, 档案topOrganizationId: {}",
r.getMaterialCode(), shipperId, topOrganizationId,
diagPo.getMaterialBaseInfoId(), diagPo.getShipperId(), diagPo.getShipperName(), diagPo.getTopOrganizationId());
} else {
log.error("导入料号校验诊断:去掉货主条件后仍查不到物料,判定为组织口径不一致(原因B)。料号: [{}], 解析shipperId: {}, 登录topOrganizationId: {}",
r.getMaterialCode(), shipperId, topOrganizationId);
}
} catch (Exception diagEx) {
log.warn("导入料号校验诊断查询异常,料号: [{}], 错误: {}", r.getMaterialCode(), diagEx.getMessage());
}
String errorMsg = String.format("导入失败:该货主下不存在该料号(货主名称=%s,料号=%s,解析shipperId=%s,登录topOrganizationId=%s)。请确保该料号已在物料管理中创建,且属于该货主",
order.getShipperName(), r.getMaterialCode(),
shipperId == null ? "" : shipperId, topOrganizationId == null ? "" : topOrganizationId);
log.error(errorMsg);
throw new ServiceException(errorMsg);
}
// 校验料号与规格型号/SKU码一致性按料号查到档案后逐项比对任何一项不符直接报对应错误
// 双方trim后必须完全一致Excel留空而档案有值或Excel填了值而档案为空均视为不一致报错
// 规格型号trim后双方必须完全一致Excel留空而档案有值或Excel填了值而档案为空均视为不一致报错
// SKU码档案条码barCode为空时跳过比对存量档案普遍未维护条码档案有值时仍严格比对
String excelSpec = StringUtils.trimToEmpty(r.getSpecificationModel());
String dbSpec = StringUtils.trimToEmpty(materialBaseInfoPO.getSpecificationModel());
if (!excelSpec.equals(dbSpec)) {
@@ -2089,7 +2114,7 @@ public class StockInOrderApplicationService {
}
String excelSku = StringUtils.trimToEmpty(r.getSkuCode());
String dbSku = StringUtils.trimToEmpty(materialBaseInfoPO.getBarCode());
if (!excelSku.equals(dbSku)) {
if (StringUtils.isNotEmpty(dbSku) && !excelSku.equals(dbSku)) {
throw new ServiceException(String.format("导入失败:料号[%s](商品名称:%s)SKU码与物料档案不一致(Excel:%s / 档案:%s",
r.getMaterialCode(), r.getMaterialName(),
excelSku.isEmpty() ? "" : excelSku, dbSku.isEmpty() ? "" : dbSku));
@@ -2423,6 +2448,46 @@ public class StockInOrderApplicationService {
return oid != null && loginOrganizationId.equals(oid);
}
/**
* 导入校验从按料号SQL为LIKE模糊查出的物料列表中挑选匹配记录
* 优先级料号精确等值优先于模糊命中避免子串料号误匹配
* 同级内优先 shipperId 精确匹配其次 shipperName 等值匹配最后取排序第一条与原 get(0) 行为一致
*/
private MaterialBaseInfoPO pickMaterialByCode(List<MaterialBaseInfoPO> materialList, String materialCode, Long shipperId, String shipperName) {
if (materialList == null || materialList.isEmpty()) {
return null;
}
String code = StringUtils.trimToEmpty(materialCode);
String name = StringUtils.trimToEmpty(shipperName);
MaterialBaseInfoPO exactCodeFirst = null;
MaterialBaseInfoPO anyFirst = null;
// 第一轮料号精确等值中优先 shipperId 精确匹配
for (MaterialBaseInfoPO po : materialList) {
if (anyFirst == null) {
anyFirst = po;
}
if (StringUtils.isEmpty(code) || !code.equals(StringUtils.trimToEmpty(po.getMaterialCode()))) {
continue;
}
if (exactCodeFirst == null) {
exactCodeFirst = po;
}
if (shipperId != null && shipperId.equals(po.getShipperId())) {
return po;
}
}
// 第二轮料号精确等值中按档案货主名称等值匹配
if (StringUtils.isNotEmpty(name)) {
for (MaterialBaseInfoPO po : materialList) {
if (StringUtils.isNotEmpty(code) && code.equals(StringUtils.trimToEmpty(po.getMaterialCode()))
&& name.equals(StringUtils.trimToEmpty(po.getShipperName()))) {
return po;
}
}
}
return exactCodeFirst != null ? exactCodeFirst : anyFirst;
}
/**
* @description 根据货主名称或编号获取货主ID用于导入时提前获取货主ID
* @param shipperName 货主名称
@@ -500,15 +500,7 @@ public class StockOutOrderApplicationService {
return stockOutOrderPO;
}
/**
* 获取出库单归档详情(已反审): 反审时单据已软删, 已反审tab 查看归档详情
*/
public StockOutOrderPO getReverseInfoChildren(Long outOrderId)
{
return stockOutOrderDomainService.getReverseInfoChildren(outOrderId);
}
/**
* 出库交接场景递归过滤 pickingQuantity 0 的明细与交接详情一致
* @param detailList 物料明细树
@@ -1958,13 +1950,6 @@ public class StockOutOrderApplicationService {
stockOutOrderDomainService.cancelExecutionOrder(stockOutOrder);
}
/**
* oms出库执行单反审(已出库单据回退): 还原实物库存并推送OMS清理单据生成反审异常记录
*/
public void reverseExecutionOrder(StockOutOrder stockOutOrder){
stockOutOrderDomainService.reverseExecutionOrder(stockOutOrder);
}
public void omsOrderAddDetail(List<OutMaterialDetail> outMaterialDetails){
stockOutOrderDomainService.omsOrderAddDetail(outMaterialDetails);
}
@@ -144,7 +144,4 @@ public class HandoverTaskOrder extends BaseVOEntity {
private String operatorsName;
@ApiModelProperty("计费信息")
private String billingJson;
@ApiModelProperty("反审标记: 0-无 1-已反审(反审时软删del_flag=2并打标记)")
private Integer reverseFlag;
}
}
@@ -146,7 +146,4 @@ public class HandoverTaskOrderPO extends BaseVOEntity {
private List<TaskHandoverMaterialDetailPO> materialDetailList;
@ApiModelProperty("计费信息")
private String billingJson;
@ApiModelProperty("反审标记: 0-无 1-已反审(反审时软删del_flag=2并打标记)")
private Integer reverseFlag;
}
}
@@ -146,7 +146,4 @@ public class HandoverTaskOrderDO extends BaseVOEntity {
private String pictureApp;
private String billingJson;
@ApiModelProperty("反审标记: 1-已反审(查询【已反审】tab时与delFlag=2一起传入)")
private Integer reverseFlag;
}
}
@@ -44,7 +44,6 @@ import com.mhd.wms.domain.materialInventory.repository.mapper.MaterialInventoryM
import com.mhd.wms.domain.materialInventory.repository.todo.MaterialInventoryParamDO;
import com.mhd.wms.domain.outMaterialDetail.entity.OutMaterialDetail;
import com.mhd.wms.domain.outMaterialDetail.repository.mapper.OutMaterialDetailMapper;
import com.mhd.wms.domain.pickingMaterialDetail.entity.PickingMaterialDetail;
import com.mhd.wms.domain.pickingMaterialDetail.repository.mapper.PickingMaterialDetailMapper;
import com.mhd.wms.domain.pickingMaterialDetail.repository.po.PickingMaterialDetailPO;
import com.mhd.wms.domain.shelfMaterialDetail.repository.todo.ShelfMaterialDetailDO;
@@ -243,90 +242,6 @@ public class HandoverTaskOrderDomainService {
return handoverTaskOrderPO;
}
/**
* 获取交接作业单归档详情(已反审): 出库单反审时交接单及关联出库明细均已软删(del_flag=2),
* 本方法镜像 getInfo del_flag=2 查归档数据, 供交接单已反审tab 查看详情
*/
public HandoverTaskOrderPO getReverseInfo(Long outTaskOrderId)
{
HandoverTaskOrderPO handoverTaskOrderPO = handoverTaskOrderService.getInfo(outTaskOrderId);
if (handoverTaskOrderPO == null) {
return null;
}
String orderNumber = handoverTaskOrderPO.getOrderNumber();
if (orderNumber != null && !orderNumber.trim().isEmpty()) {
StockOutOrder stockOutOrder = stockOutOrderMapper.selectOne(new QueryWrapper<StockOutOrder>().lambda()
.eq(StockOutOrder::getOutOrderNumber, orderNumber)
.eq(StockOutOrder::getDelFlag, 2));
Integer review = stockOutOrder != null ? stockOutOrder.getReview() : null;
// 归档明细: 出库明细已随反审软删, del_flag=2
LambdaQueryWrapper<OutMaterialDetail> omdQuery = new QueryWrapper<OutMaterialDetail>().lambda()
.eq(OutMaterialDetail::getOutOrderNumber, orderNumber)
.eq(OutMaterialDetail::getDelFlag, 2);
List<OutMaterialDetail> outMaterialDetailList = outMaterialDetailMapper.selectList(omdQuery);
List<TaskHandoverMaterialDetailPO> materialDetailList = new ArrayList<>();
for (OutMaterialDetail omd : outMaterialDetailList) {
BigDecimal handoverQuantity;
BigDecimal pickQty;
if (Integer.valueOf(1).equals(review)) {
// 需要复核时仅限复核单上的明细picking_material_detail 有拣货的 unique_id
List<PickingMaterialDetail> pmdList = pickingMaterialDetailMapper.selectList(new QueryWrapper<PickingMaterialDetail>().lambda()
.eq(PickingMaterialDetail::getOutUniqueId, omd.getUniqueId())
.eq(PickingMaterialDetail::getDelFlag, 2)
.gt(PickingMaterialDetail::getPickingQuantity, BigDecimal.ZERO));
if (pmdList == null || pmdList.isEmpty()) {
continue;
}
if (omd.getCheckQuantity() == null || omd.getCheckQuantity().compareTo(BigDecimal.ZERO) <= 0) {
continue;
}
PickingMaterialDetailPO pickingSummary = pickingMaterialDetailMapper.queryTotalsByOutNumberAndBaseId(omd.getUniqueId());
pickQty = (pickingSummary != null && pickingSummary.getPickingQuantity() != null) ? pickingSummary.getPickingQuantity() : BigDecimal.ZERO;
if (pickQty.compareTo(BigDecimal.ZERO) <= 0) {
continue;
}
handoverQuantity = omd.getCheckQuantity();
} else {
BigDecimal qty = omd.getPickingQuantity() != null ? omd.getPickingQuantity() : omd.getQuantity();
if (qty == null || qty.compareTo(BigDecimal.ZERO) <= 0) {
continue;
}
pickQty = qty;
handoverQuantity = qty;
}
TaskHandoverMaterialDetailPO detail = new TaskHandoverMaterialDetailPO();
detail.setMaterialDetailId(omd.getMaterialDetailId());
detail.setUniqueId(omd.getUniqueId());
detail.setTaskNumber(handoverTaskOrderPO.getTaskNumber());
detail.setOrganizationId(omd.getOrganizationId());
detail.setOrganizationName(omd.getOrganizationName());
detail.setTopOrganizationId(omd.getTopOrganizationId());
detail.setMaterialBaseInfoId(omd.getMaterialBaseInfoId());
detail.setMaterialCode(omd.getMaterialCode() != null ? omd.getMaterialCode() : omd.getMaterialNo());
detail.setMaterialName(omd.getMaterialName() != null ? omd.getMaterialName() : omd.getCommodityName());
detail.setBarCode(omd.getBarCode());
detail.setWeightLimit(omd.getWeightLimit());
detail.setVolumeLimit(omd.getVolumeLimit());
detail.setQuantity(omd.getQuantity());
detail.setPickingQuantity(pickQty);
detail.setCheckQuantity(handoverQuantity);
detail.setPackId(omd.getPackId());
detail.setPackCode(omd.getPackCode());
detail.setPackName(omd.getPackName());
detail.setPackDetailId(omd.getPackDetailId() != null ? String.valueOf(omd.getPackDetailId()) : null);
detail.setUnitCode(omd.getUnitCode());
detail.setUnitName(omd.getUnitName());
detail.setUnitNumber(omd.getUnitNumber());
detail.setMaterialWarehouseControlId(omd.getMaterialWarehouseControlId());
detail.setSerialNumberManage(omd.getSerialNumberManage());
detail.setRemark(omd.getRemark());
materialDetailList.add(detail);
}
handoverTaskOrderPO.setMaterialDetailList(materialDetailList);
}
return handoverTaskOrderPO;
}
/**
* @description 分配月台
@@ -2,9 +2,7 @@ package com.mhd.wms.domain.inMaterialDetail.repository.facade;
import com.baomidou.mybatisplus.extension.service.IService;
import com.mhd.wms.domain.inMaterialDetail.entity.InMaterialDetail;
import com.mhd.wms.domain.inMaterialDetail.repository.po.InMaterialDetailExportPO;
import com.mhd.wms.domain.inMaterialDetail.repository.po.InMaterialDetailPO;
import com.mhd.wms.domain.inMaterialDetail.repository.po.InMaterialDetailWithOrderPO;
import com.mhd.wms.domain.inMaterialDetail.repository.po.InStockListMaterialAgg;
import com.mhd.wms.domain.inMaterialDetail.repository.todo.InMaterialDetailBaseDO;
import com.mhd.wms.domain.inMaterialDetail.repository.todo.InMaterialDetailDO;
@@ -29,16 +27,6 @@ public interface IInMaterialDetailService extends IService<InMaterialDetail>
public List<InMaterialDetailPO> queryInOrderList(QueryOrderOverStockDO queryOrderOverStockDO);
/**
* 入库明细查询关联入库单只统计已入库(5)单据
*/
public List<InMaterialDetailWithOrderPO> queryInOrderDetailList(QueryOrderOverStockDO queryOrderOverStockDO);
/**
* 入库明细导出专用列集口径同 queryInOrderDetailList不分页
*/
public List<InMaterialDetailExportPO> exportInOrderDetailList(QueryOrderOverStockDO queryOrderOverStockDO);
/**
* 分页查询物料明细列表
*/
@@ -2,9 +2,7 @@ package com.mhd.wms.domain.inMaterialDetail.repository.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.mhd.wms.domain.inMaterialDetail.entity.InMaterialDetail;
import com.mhd.wms.domain.inMaterialDetail.repository.po.InMaterialDetailExportPO;
import com.mhd.wms.domain.inMaterialDetail.repository.po.InMaterialDetailPO;
import com.mhd.wms.domain.inMaterialDetail.repository.po.InMaterialDetailWithOrderPO;
import com.mhd.wms.domain.inMaterialDetail.repository.po.InStockListMaterialAgg;
import com.mhd.wms.domain.inMaterialDetail.repository.todo.InMaterialDetailDO;
import com.mhd.wms.domain.overStock.repository.todo.QueryOrderOverStockDO;
@@ -30,16 +28,6 @@ public interface InMaterialDetailMapper extends BaseMapper<InMaterialDetail>
*/
public List<InMaterialDetailPO> queryInOrderList(QueryOrderOverStockDO queryOrderOverStockDO);
/**
* 入库明细查询关联入库单只统计已入库(5)单据
*/
public List<InMaterialDetailWithOrderPO> queryInOrderDetailList(QueryOrderOverStockDO queryOrderOverStockDO);
/**
* 入库明细导出专用列集口径同 queryInOrderDetailList不分页
*/
public List<InMaterialDetailExportPO> exportInOrderDetailList(QueryOrderOverStockDO queryOrderOverStockDO);
/**
* 入库列表页按入库单号批量取去重后的 Invoice No level=1
*/
@@ -13,9 +13,7 @@ import com.mhd.system.api.model.LoginUser;
import com.mhd.wms.domain.inMaterialDetail.entity.InMaterialDetail;
import com.mhd.wms.domain.inMaterialDetail.repository.facade.IInMaterialDetailService;
import com.mhd.wms.domain.inMaterialDetail.repository.mapper.InMaterialDetailMapper;
import com.mhd.wms.domain.inMaterialDetail.repository.po.InMaterialDetailExportPO;
import com.mhd.wms.domain.inMaterialDetail.repository.po.InMaterialDetailPO;
import com.mhd.wms.domain.inMaterialDetail.repository.po.InMaterialDetailWithOrderPO;
import com.mhd.wms.domain.inMaterialDetail.repository.po.InStockListMaterialAgg;
import com.mhd.wms.domain.inMaterialDetail.repository.todo.InMaterialDetailBaseDO;
import com.mhd.wms.domain.inMaterialDetail.repository.todo.InMaterialDetailDO;
@@ -74,22 +72,6 @@ public class InMaterialDetailImpl extends ServiceImpl<InMaterialDetailMapper, In
return inMaterialDetailMapper.queryInOrderList(queryOrderOverStockDO);
}
/**
* 入库明细查询关联入库单只统计已入库(5)单据
*/
@Override
public List<InMaterialDetailWithOrderPO> queryInOrderDetailList(QueryOrderOverStockDO queryOrderOverStockDO) {
return inMaterialDetailMapper.queryInOrderDetailList(queryOrderOverStockDO);
}
/**
* 入库明细导出专用列集口径同 queryInOrderDetailList不分页
*/
@Override
public List<InMaterialDetailExportPO> exportInOrderDetailList(QueryOrderOverStockDO queryOrderOverStockDO) {
return inMaterialDetailMapper.exportInOrderDetailList(queryOrderOverStockDO);
}
/**
* 查询物料明细列表
*/
@@ -1,112 +0,0 @@
package com.mhd.wms.domain.inMaterialDetail.repository.po;
import com.mhd.common.core.annotation.Excel;
import lombok.Data;
import java.math.BigDecimal;
import java.util.Date;
/**
* 入库明细导出专用PO仅含客户要求的导出列列顺序即导出顺序
* 火险保费 WMS 库暂无数据来源先占位导出空列
* 单件净重(KG) 入库明细表无单件净重列先占位导出空列
*
* @author rcx
* @date 2026-09-09
*/
@Data
public class InMaterialDetailExportPO {
@Excel(name = "客户编号", sort = 1)
private String customerCode;
@Excel(name = "客户名称", sort = 2)
private String customerName;
@Excel(name = "入库单号", sort = 3)
private String inOrderNumber;
@Excel(name = "入库日期", width = 30, dateFormat = "yyyy-MM-dd", sort = 4)
private Date warehouseDate;
@Excel(name = "LOT编号", sort = 5)
private String lotNo;
@Excel(name = "客户预约名称", sort = 6)
private String customerOrderNumber;
@Excel(name = "物料名称", sort = 7)
private String materialName;
@Excel(name = "物料编码", sort = 8)
private String materialCode;
@Excel(name = "库存单位", sort = 9)
private String unitName;
@Excel(name = "件数", sort = 10)
private BigDecimal pieceCount;
@Excel(name = "仓库", sort = 11)
private String warehouseName;
@Excel(name = "饮用日期", width = 30, dateFormat = "yyyy-MM-dd", sort = 12)
private Date drinkDate;
@Excel(name = "库位", sort = 13)
private String storageLocationName;
@Excel(name = "单件净重(KG)", sort = 14)
private BigDecimal netWeight;
@Excel(name = "单件体积(CBM)", sort = 15)
private BigDecimal singleVolume;
@Excel(name = "单价", sort = 16)
private BigDecimal unitPrice;
@Excel(name = "总价", sort = 17)
private BigDecimal totalPrice;
@Excel(name = "折扣(%)", sort = 18)
private BigDecimal discountRate;
@Excel(name = "每月仓租", sort = 19)
private BigDecimal monthlyWarehouseFee;
@Excel(name = "半月仓租", sort = 20)
private BigDecimal halfMonthWhFee;
@Excel(name = "合同收费", sort = 21)
private BigDecimal contractFee;
@Excel(name = "火险保费", sort = 22)
private BigDecimal fireInsureFee;
@Excel(name = "备注", sort = 23)
private String remark;
@Excel(name = "货物种类", sort = 24)
private String materialClassifyName;
@Excel(name = "总重量", sort = 25)
private BigDecimal totalGrossWeight;
@Excel(name = "每件保额", sort = 26)
private BigDecimal insureAmount;
@Excel(name = "仓位/库位", sort = 27)
private String storageName;
@Excel(name = "收费标准", sort = 28)
private BigDecimal chargeStandard;
@Excel(name = "有效期", width = 30, dateFormat = "yyyy-MM-dd", sort = 29)
private Date expiryDate;
@Excel(name = "单据状态", sort = 30, readConverterExp = "5=已入库")
private Integer inOrderStatus;
@Excel(name = "业务单据类型", sort = 31)
private String orderTypeName;
}
@@ -1,47 +0,0 @@
package com.mhd.wms.domain.inMaterialDetail.repository.po;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.mhd.common.core.annotation.Excel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.math.BigDecimal;
import java.util.Date;
/**
* 入库明细查询结果关联入库单只统计已入库单据
*
* @author rcx
* @date 2026-09-09
*/
@Data
public class InMaterialDetailWithOrderPO extends InMaterialDetailPO {
private static final long serialVersionUID = 1L;
@ApiModelProperty("入库单状态: 1-已创建 2-已审核 3-收货中 4-上架中 5-已入库 6-已取消 7-已关闭")
@Excel(name = "入库单状态: 1-已创建 2-已审核 3-收货中 4-上架中 5-已入库 6-已取消 7-已关闭")
private Integer inOrderStatus;
@ApiModelProperty("入库单状态(与inOrderStatus同值,便于前端按status字段名绑定)")
private Integer status;
@ApiModelProperty("入库单审核状态: 1-未审核 2-审核不通过 3-审核通过")
@Excel(name = "入库单审核状态: 1-未审核 2-审核不通过 3-审核通过")
private Integer inOrderAuditStatus;
@ApiModelProperty("入仓日期")
@JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8")
@Excel(name = "入仓日期", width = 30, dateFormat = "yyyy-MM-dd")
private Date warehouseDate;
@ApiModelProperty("保额")
@Excel(name = "保额")
private BigDecimal insureAmount;
@ApiModelProperty("货物类型: 0-物料 1-半成品 2-成品")
@Excel(name = "货物类型: 0-物料 1-半成品 2-成品")
private Integer goodsType;
@ApiModelProperty("货物种类(物料分类名称,多个逗号分隔)")
private String materialClassifyName;
}
@@ -1,11 +1,8 @@
package com.mhd.wms.domain.inMaterialDetail.service;
import com.mhd.wms.domain.inMaterialDetail.repository.facade.IInMaterialDetailService;
import com.mhd.wms.domain.inMaterialDetail.repository.po.InMaterialDetailExportPO;
import com.mhd.wms.domain.inMaterialDetail.repository.po.InMaterialDetailPO;
import com.mhd.wms.domain.inMaterialDetail.repository.po.InMaterialDetailWithOrderPO;
import com.mhd.wms.domain.inMaterialDetail.repository.todo.InMaterialDetailDO;
import com.mhd.wms.domain.overStock.repository.todo.QueryOrderOverStockDO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@@ -33,20 +30,6 @@ public class InMaterialDetailDomainService {
return materialDetailService.queryList(inMaterialDetailDO);
}
/**
* 入库明细查询关联入库单只统计已入库(5)单据
*/
public List<InMaterialDetailWithOrderPO> queryInOrderDetailList(QueryOrderOverStockDO queryOrderOverStockDO) {
return materialDetailService.queryInOrderDetailList(queryOrderOverStockDO);
}
/**
* 入库明细导出专用列集口径同 queryInOrderDetailList不分页
*/
public List<InMaterialDetailExportPO> exportInOrderDetailList(QueryOrderOverStockDO queryOrderOverStockDO) {
return materialDetailService.exportInOrderDetailList(queryOrderOverStockDO);
}
/**
* 新增物料明细

Some files were not shown because too many files have changed in this diff Show More