Merge branch 'dev' into dev-bms-260826

This commit is contained in:
王奎兴
2026-09-09 16:44:07 +08:00
48 changed files with 1819 additions and 182 deletions
@@ -19,7 +19,7 @@ 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)
@FeignClient(contextId = "BmsService", value = ServiceNameConstants.BMS_SERVICE, url = "http://10.102.192.32:8012",fallbackFactory = RemoteBmsFeignFallbackFactory.class, configuration = FeignAutoConfiguration.class)
public interface BmsServiceFeign {
@@ -12,11 +12,12 @@ import org.springframework.scheduling.annotation.Async;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
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)
@FeignClient(contextId = "OmsService", value = ServiceNameConstants.OMS_SERVICE,url = "http://10.102.192.33:8017",fallbackFactory = RemoteOmsFeignFallbackFactory.class, configuration = FeignAutoConfiguration.class)
public interface OmsServiceFeign {
@@ -28,6 +29,10 @@ public interface OmsServiceFeign {
@PostMapping(value = "/reservationStockInOrderApi/pushInOrderDetail")
public AjaxResult pushInOrderDetail(@RequestBody InMaterialDetailTZPD inMaterialDetail);
@ApiOperation("wms回传入库结果:按入库单号同步入库状态(3-收货中 4-上架中 5-已入库)到OMS入库业务单,type非1为入库")
@GetMapping(value = "/executionStockInOrderApi/returnResult")
public AjaxResult returnInResult(@RequestParam("orderNumber") String orderNumber, @RequestParam("status") Long status, @RequestParam("type") String type);
@ApiOperation("wms推送入库单")
@PostMapping(value = "/reservationStockOutOrderApi/pushOutOrder")
@@ -26,7 +26,7 @@ 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)
@FeignClient(contextId = "commonWlhyServiceFeign",value = ServiceNameConstants.WLHY_SERVICE,url = "http://10.102.192.31:8014",configuration = FeignAutoConfiguration.class)
public interface WlhyServiceFeign {
/**
@@ -21,7 +21,7 @@ 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)
@FeignClient(contextId = "remoteWmsServiceFeign",value = ServiceNameConstants.WMS_SERVICE,url = "http://10.102.192.32:8016",fallbackFactory = RemoteWmsFallbackFactory.class, configuration = FeignAutoConfiguration.class)
public interface WmsServiceFeign {
/**
@@ -9,7 +9,7 @@ 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)
@FeignClient(contextId = "YmsService", value = ServiceNameConstants.YMS_SERVICE,url = "http://10.102.192.33:8018",fallbackFactory = RemoteBmsFeignFallbackFactory.class, configuration = FeignAutoConfiguration.class)
public interface YmsServiceFeign {
/**
@@ -41,6 +41,11 @@ public class RemoteOmsFeignFallbackFactory implements FallbackFactory<OmsService
return null;
}
@Override
public AjaxResult returnInResult(String orderNumber, Long status, String type) {
return null;
}
@Override
public AjaxResult pushOutOrder(StockOutOrderTZPD stockOutOrder) {
return null;
@@ -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;
@@ -32,12 +35,21 @@ public interface BiPlatformRealDataMapper {
/** 本月任务量 */
Long countMonthTasks();
/** 本月任务平均时长 / 完成率统计 */
RealMonthlyTaskDurationPO queryMonthTaskStats();
/** 任务负荷(今日 24 小时) */
List<RealTaskLoadPO> queryTaskLoadToday();
/** 今日预约-业务类型统计(按 businessName 分组统计今日预约数量) */
/** 今日预约-租户统计(按 tenantName 分组统计今日预约数量) */
List<RealBusinessTypeStatPO> queryTodayBusinessTypeStats();
/** 今日作业准时率统计(total 今日预约总数;onTimeCount 今日准时车辆数) */
RealOnTimeStatPO queryTodayOnTimeStats();
/** 任务类型统计(当月 OMS 运输订单按业务类型分组:1-跨境 2-国内) */
List<RealTaskTypeStatPO> queryMonthTransportOrderByType();
/** 月台监控-按楼层统计月台车辆(楼层、月台数量、今日预约车辆、当前作业车辆) */
List<RealPlatformFloorStatPO> queryPlatformFloorStats();
@@ -5,15 +5,15 @@ import lombok.Data;
import java.io.Serializable;
/**
* 今日预约-业务类型统计(真实数据,来自 TEST_NGWL_YMS.QMS_MAIN_BUSINESS
* 按业务类型分组统计今日预约数量
* 今日预约-租户统计(真实数据,来自 TEST_NGWL_YMS.QMS_MAIN_BUSINESS
* 按租户名称分组统计今日预约数量
*/
@Data
public class RealBusinessTypeStatPO implements Serializable {
private static final long serialVersionUID = 1L;
/** 业务类型名称(qms_main_business.businessName */
private String businessName;
/** 租户名称(qms_main_business.tenantName */
private String tenantName;
/** 今日预约数量 */
private Long count;
@@ -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_OMS.BUSINESS_DOCUMENT_ORDER 运输订单)
* 按业务类型 businessCategory 分组统计当月数量:1-跨境运输 2-国内运输
*/
@Data
public class RealTaskTypeStatPO implements Serializable {
private static final long serialVersionUID = 1L;
/** 业务类型:1-跨境 2-国内 */
private Integer businessCategory;
/** 该类型当月单量 */
private Long count;
}
@@ -16,6 +16,9 @@ public class RealVehicleStatusPO implements Serializable {
/** 当前未签到 */
private Long notCheckedIn;
/** 当前等待作业(FLOW_STATUS IN '1','2','3' 已预约/已签到/已叫号) */
private Long waiting;
/** 当前作业中 */
private Long operatingVehicles;
@@ -9,12 +9,17 @@ import com.mhd.bi.domain.biPlatformRealData.repository.po.RealTaskLoadPO;
import com.mhd.bi.domain.biPlatformRealData.repository.po.RealBusinessTypeStatPO;
import com.mhd.bi.domain.biPlatformRealData.repository.po.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 +96,23 @@ 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("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 +138,21 @@ 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);
}
return objectMapper.writeValueAsString(fp);
}
@@ -166,12 +193,34 @@ public class BiPlatformRealDataService {
}
}
/**
* 今日作业准时率 = 准时车辆数 / 今日预约车辆总数 × 100%
* 准时:今日(TARGET_DATE=今天)已进场且实际进场时间不超过该预约的预约结束时间 bookingEndTime
* 实际进场时间超过 bookingEndTime 视为不准时。
* 今日预约总数为 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.getOperatingVehicles() == null) po.setOperatingVehicles(0L);
if (po.getCompletedVehicles() == null) po.setCompletedVehicles(0L);
return po;
@@ -180,6 +229,7 @@ public class BiPlatformRealDataService {
RealVehicleStatusPO po = new RealVehicleStatusPO();
po.setTodayReservedVehicles(0L);
po.setNotCheckedIn(0L);
po.setWaiting(0L);
po.setOperatingVehicles(0L);
po.setCompletedVehicles(0L);
return po;
@@ -196,6 +246,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();
@@ -206,14 +271,50 @@ public class BiPlatformRealDataService {
}
/**
* 今日预约-业务类型统计:按业务类型分组统计今日预约数量
* 例:今日预约航空打板 3 条 → 返回 {businessName:"航空打板", count:3}
* 任务类型统计:当月 OMS 运输订单按业务类型分组(1-跨境运输,2-国内运输)
* 返回 {totalTasks: 当月跨境+国内运输总单量, taskTypes: [{type, count}]}
* 查询失败时返回空结构,不影响写死字段。
*/
/**
* 任务类型统计:固定输出「跨境运输」「国内运输」两类,count 取当月 OMS 业务单真实单量;
* 当月无数据或查询失败时仍返回两类、count=0(不使用写死模板兜底)。
*/
public TaskTypeStatisticsVO queryMonthTransportOrderByType() {
int crossBorder = 0; // 跨境运输 BUSINESS_CATEGORY=1
int domestic = 0; // 国内运输 BUSINESS_CATEGORY=2
try {
List<RealTaskTypeStatPO> rows = biPlatformRealDataMapper.queryMonthTransportOrderByType();
if (rows != null) {
for (RealTaskTypeStatPO r : rows) {
if (r == null || r.getBusinessCategory() == null || r.getCount() == null) {
continue;
}
if (r.getBusinessCategory() == 1) {
crossBorder = r.getCount().intValue();
} else if (r.getBusinessCategory() == 2) {
domestic = r.getCount().intValue();
}
}
}
} catch (Exception e) {
log.error("【OMS】统计当月运输订单业务类型失败: {}", e.getMessage(), e);
// 失败时不回退写死模板,保持两类 count=0
}
List<TaskTypeCountItemVO> items = new ArrayList<>();
items.add(TaskTypeCountItemVO.builder().type("跨境运输").count(crossBorder).build());
items.add(TaskTypeCountItemVO.builder().type("国内运输").count(domestic).build());
return TaskTypeStatisticsVO.builder().totalTasks(crossBorder + domestic).taskTypes(items).build();
}
/**
* 今日预约-租户统计:按租户名称分组统计今日预约数量。
* 例:今日预约某租户 3 条 → 返回 {tenantName:"某租户", count:3}
*/
public List<RealBusinessTypeStatPO> queryTodayBusinessTypeStats() {
try {
return biPlatformRealDataMapper.queryTodayBusinessTypeStats();
} catch (Exception e) {
log.error("【YMS】统计今日业务类型失败: {}", e.getMessage(), e);
log.error("【YMS】统计今日租户预约失败: {}", e.getMessage(), e);
return java.util.Collections.emptyList();
}
}
@@ -271,29 +372,63 @@ 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%(今日总数为 0 时返回 0)
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().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 +448,9 @@ public class BiPlatformRealDataService {
}
}
// 任务类型统计:当月 OMS 业务单真实数据(固定跨境运输/国内运输两类,不使用写死模板兜底)
template.setTaskTypeStatistics(queryMonthTransportOrderByType());
return template;
}
@@ -87,7 +87,7 @@ 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).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,33 @@ 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%
// 准时今日TARGET_DATE=今天已进场且 ENTRY_TIME <= bookingEndTime预约结束时间超过视为不准时
// 今日预约总数 = 0 时返回 0
if (template.getEfficiencyStatistics() != null) {
template.getEfficiencyStatistics().setPlatformOnTimeRate(biPlatformRealDataService.calcTodayOnTimeRate());
}
}
// ====== 真实数据作业车辆状态统计 ======
@@ -192,14 +207,31 @@ 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().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 +250,9 @@ public class BiReportSnapshotSyncService {
}
}
// ====== 真实数据任务类型统计当月 OMS 业务单固定跨境运输/国内运输两类不使用写死模板兜底 ======
template.setTaskTypeStatistics(biPlatformRealDataService.queryMonthTransportOrderByType());
return template;
}
@@ -415,6 +415,7 @@ 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_OPV = 1_180;
static final int P_DONE = 1_420;
static final String[] P_MO_LABELS = {"5月", "6月", "7月"};
@@ -122,9 +122,9 @@ public class BiReportApi extends BaseController {
}
/**
* 今日预约-业务类型统计实时查 YMS 不落库
* 今日预约-租户统计实时查 YMS 不落库
*/
@ApiOperation(value = "今日预约业务类型统计", notes = "业务类型分组统计今日预约数量,实时查询 YMS 库,不落库;例:航空打板 3 条")
@ApiOperation(value = "今日预约租户统计", notes = "租户名称分组统计今日预约数量,实时查询 YMS 库,不落库;例:某租户 3 条")
@GetMapping("/businessTypeStats")
public BiApiResult<List<RealBusinessTypeStatPO>> businessTypeStats() {
List<RealBusinessTypeStatPO> data = biPlatformRealDataService.queryTodayBusinessTypeStats();
@@ -20,6 +20,9 @@ public class VehicleStatusVO {
@ApiModelProperty("当前未签到,单位:辆")
private Integer notCheckedIn;
@ApiModelProperty("当前等待作业(已预约/已签到/已叫号),单位:辆")
private Integer waiting;
@ApiModelProperty("当前作业中,单位:辆")
private Integer operatingVehicles;
@@ -40,43 +40,86 @@ 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 今日预约总车辆数(TARGET_DATE = 今天)
onTimeCount 今日准时车辆数(已进场且实际进场时间不超过该预约的预约结束时间 BOOKING_END_TIME
「准时」= 今日(TARGET_DATE=今天)已进场且 ENTRY_TIME <= BOOKING_END_TIME;超过则视为不准时
准时率 = onTimeCount / total × 100%
-->
<select id="queryTodayOnTimeStats" resultType="com.mhd.bi.domain.biPlatformRealData.repository.po.RealOnTimeStatPO">
SELECT
SUM(CASE WHEN 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;= BOOKING_END_TIME
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') 已预约/已签到/已叫号 且 预约日期 = 今天
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 ('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>
<!-- 今日预约-租户统计:按 TENANT_NAME(租户名称)分组统计今日预约数量,按预约日期 TARGET_DATE 过滤 -->
<select id="queryTodayBusinessTypeStats" resultType="com.mhd.bi.domain.biPlatformRealData.repository.po.RealBusinessTypeStatPO">
SELECT
BUSINESS_NAME AS businessName,
COUNT(1) AS count
TENANT_NAME AS tenantName,
COUNT(1) AS count
FROM NGWL_TEST_YMS.QMS_MAIN_BUSINESS
WHERE BUSINESS_NAME IS NOT NULL
WHERE TENANT_NAME IS NOT NULL
AND TRUNC(TARGET_DATE) = TRUNC(SYSDATE)
GROUP BY BUSINESS_NAME
GROUP BY TENANT_NAME
ORDER BY COUNT(1) DESC
</select>
@@ -102,6 +145,21 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
ORDER BY 1 DESC
</select>
<!-- 任务类型统计(运输订单,来自 NGWL_TEST_OMS.BUSINESS_DOCUMENT_ORDER):
当月(CREATE_TIME 在当前月)按业务类型 BUSINESS_CATEGORY 分组统计
BUSINESS_CATEGORY: 1-跨境运输 2-国内运输 -->
<select id="queryMonthTransportOrderByType" resultType="com.mhd.bi.domain.biPlatformRealData.repository.po.RealTaskTypeStatPO">
SELECT
BUSINESS_CATEGORY AS businessCategory,
COUNT(1) AS count
FROM NGWL_TEST_OMS.BUSINESS_DOCUMENT_ORDER
WHERE BUSINESS_CATEGORY IN (1, 2)
AND CREATE_TIME IS NOT NULL
AND TO_CHAR(CREATE_TIME, 'YYYY-MM') = TO_CHAR(SYSDATE, 'YYYY-MM')
GROUP BY BUSINESS_CATEGORY
ORDER BY BUSINESS_CATEGORY
</select>
<!-- 任务负荷(今日 24 小时时段):按 EXTRACT(HOUR FROM ENTRY_TIME) 统计 -->
<select id="queryTaskLoadToday" resultType="com.mhd.bi.domain.biPlatformRealData.repository.po.RealTaskLoadPO">
SELECT
@@ -26,7 +26,7 @@ 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)
@FeignClient(value = "mhd-third-party-service",url = "http://10.102.192.31:8012", configuration = FeignAutoConfiguration.class)
public interface ThirdPartyServiceFeign {
//查询当前组织所有三方接口信息
@@ -3,6 +3,7 @@ package com.mhd.user.interfaces.facade;
import com.github.pagehelper.PageHelper;
import com.mhd.common.core.domain.entity.R;
import com.mhd.common.core.utils.bean.BeanUtils;
import com.mhd.common.core.utils.poi.ExcelUtil;
import com.mhd.common.log.annotation.Log;
import com.mhd.common.log.enums.BusinessType;
import com.mhd.common.security.utils.SecurityUtils;
@@ -24,6 +25,7 @@ import com.mhd.user.application.service.WechatMiniAppService;
import com.mhd.user.interfaces.dto.updateDTO.SettlementInfoUpdateDTO;
import com.mhd.user.interfaces.vo.SettlementInfoQueryVo;
import com.mhd.user.interfaces.vo.ShipperMasterDataSyncTimeVo;
import com.mhd.user.interfaces.vo.UserShipperExportVO;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
@@ -31,6 +33,9 @@ import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.net.URLEncoder;
import java.util.*;
@Api(tags = "用户中台管理-托运人管理")
@@ -128,6 +133,33 @@ public class UserShipperAPI extends BaseController {
return getDataTable(list);
}
@Log(title = "托运人管理-导出", description ="导出托运人列表",businessType = BusinessType.EXPORT)
@ApiOperation("导出托运人列表")
@GetMapping(value = "/exportUserShipper", produces = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet")
public void exportUserShipper(UserShipperDTO userShipperDTO, HttpServletResponse response) throws IOException {
//转换实体
UserShipperDO userShipperDO = userShipperAssember.toUserShipperDO(userShipperDTO);
//查询全量不分页复用列表查询逻辑含数据权限过滤
List<UserShipperPo> list = userShipperApplicationService.userShipperList(userShipperDO);
List<UserShipperExportVO> exportList = new ArrayList<>();
if (list != null) {
for (UserShipperPo po : list) {
UserShipperExportVO vo = new UserShipperExportVO();
BeanUtils.copyProperties(po, vo);
exportList.add(vo);
}
}
//设置下载头防止浏览器乱码
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<UserShipperExportVO> util = new ExcelUtil<>(UserShipperExportVO.class);
util.exportExcel(response, exportList, "托运人列表");
}
@ApiOperation("查询托运人列表统计表单")
@GetMapping("/userShipperCount")
@@ -0,0 +1,73 @@
package com.mhd.user.interfaces.vo;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.mhd.common.core.annotation.Excel;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.math.BigDecimal;
import java.util.Date;
/**
* 托运人委托方列表导出对象
*
* @author gen
*/
@Data
@ApiModel(value = "托运人列表导出对象", description = "托运人列表导出对象")
public class UserShipperExportVO {
@Excel(name = "登录账号", sort = 1, width = 20)
@ApiModelProperty(value = "登录账号")
private String userAccount;
@Excel(name = "公司名称", sort = 2, width = 30)
@ApiModelProperty(value = "公司名称")
private String shipperEnterpriseName;
@Excel(name = "联系人", sort = 3, width = 15)
@ApiModelProperty(value = "联系人")
private String emergencyContactName;
@Excel(name = "联系电话", sort = 4, width = 18)
@ApiModelProperty(value = "联系电话")
private String emergencyContactPhone;
@Excel(name = "地址", sort = 5, width = 30)
@ApiModelProperty(value = "企业注册地址")
private String shipperEnterpriseAddress;
@Excel(name = "详细地址", sort = 6, width = 30)
@ApiModelProperty(value = "详细地址")
private String userAreaAddressShipper;
@Excel(name = "备注", sort = 7, width = 25)
@ApiModelProperty(value = "备注")
private String remark;
@Excel(name = "结算币种", sort = 8, width = 12)
@ApiModelProperty(value = "结算币种")
private String settlementCurrency;
@Excel(name = "信用额度", sort = 9, width = 15)
@ApiModelProperty(value = "信用额度(授权额度)")
private BigDecimal authorizedQuota;
@Excel(name = "信用占用", sort = 10, width = 15)
@ApiModelProperty(value = "信用占用")
private BigDecimal authorizedUsedAmount;
@Excel(name = "信用余额", sort = 11, width = 15)
@ApiModelProperty(value = "信用余额")
private BigDecimal creditAmount;
@Excel(name = "客户协议", sort = 12, width = 12)
@ApiModelProperty(value = "客户协议数量")
private BigDecimal agreementCount;
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
@Excel(name = "最近同步信用时间", sort = 13, width = 22, dateFormat = "yyyy-MM-dd HH:mm:ss")
@ApiModelProperty(value = "最近同步信用时间")
private Date limitTime;
}
@@ -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> {
}
@@ -78,6 +78,16 @@ public class ExecutionStockInOrderAssembler {
// 最后使用username账号作为兜底
userRealName = loginUser.getUsername();
}
// 单据类型跟随业务类型页面唯一的类型选择项是"业务类型"(只提交businessType)
// 编辑时前端回显提交的orderTypeCode/orderTypeName是旧值若以回显值为准会导致编辑改类型不生效
// 系统内businessType与orderTypeCode同值域(pu_tong_ru_ku/tui_huo_ru_ku)以businessType为准保持三者一致
if (stockInOrderDO.getBusinessType() != null && stockInOrderDO.getBusinessType().trim().length() > 0) {
stockInOrderDO.setOrderTypeCode(stockInOrderDO.getBusinessType().trim());
} else if (stockInOrderDTO.getInOrderId() == null
&& (stockInOrderDO.getOrderTypeCode() == null || stockInOrderDO.getOrderTypeCode().trim().length() == 0)) {
// 仅新增且无业务类型时兜底普通入库编辑时两字段都为空则不覆盖(updateById跳过null字段)
stockInOrderDO.setOrderTypeCode("pu_tong_ru_ku");
}
if(stockInOrderDTO.getInOrderId() != null){
stockInOrderDO.setUpdateBy(userId);
stockInOrderDO.setUpdateByName(userRealName);
@@ -91,11 +101,6 @@ public class ExecutionStockInOrderAssembler {
stockInOrderDO.setCreateByName(userRealName);
stockInOrderDO.setCreateTime(new Date());
stockInOrderDO.setDelFlag(1);
// 新增入库单时如果入库单类型为空默认设置为普通入库
String orderTypeCode = stockInOrderDO.getOrderTypeCode();
if (orderTypeCode == null || orderTypeCode.trim().length() == 0) {
stockInOrderDO.setOrderTypeCode("pu_tong_ru_ku");
}
String orderTypeName = stockInOrderDO.getOrderTypeName();
if (orderTypeName == null || orderTypeName.trim().length() == 0) {
stockInOrderDO.setOrderTypeName("普通入库单");
@@ -4,6 +4,7 @@ import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.mhd.common.core.exception.ServiceException;
import com.mhd.common.core.utils.OrderSequence;
@@ -32,6 +33,8 @@ import com.mhd.oms.domain.executionStockInOrder.repository.po.ExecutionStockInOr
import com.mhd.oms.domain.executionStockInOrder.repository.todo.ExecutionStockInOrderDO;
import com.mhd.oms.domain.executionStockOutOrder.entity.ExecutionStockOutOrder;
import com.mhd.oms.domain.executionStockOutOrder.repository.facade.IExecutionStockOutOrderService;
import com.mhd.oms.domain.reservationStockInOrder.entity.ReservationStockInOrder;
import com.mhd.oms.domain.reservationStockInOrder.repository.facade.IReservationStockInOrderService;
import com.mhd.oms.domain.reservationStockInOrder.repository.mapper.ReservationStockInOrderMapper;
import com.mhd.oms.domain.reserveStockInOrder.repository.mapper.ReserveStockInOrderMapper;
import com.mhd.system.api.SystemServiceFeign;
@@ -70,6 +73,8 @@ public class ExecutionStockInOrderDomainService {
private IExecutionInMaterialDetailService materialDetailService;
@Autowired
private IExecutionStockOutOrderService stockOutOrderService;
@Autowired
private IReservationStockInOrderService reservationStockInOrderService;
// @Autowired
// private ReservationStockReceiptOrderDomainService stockReceiptOrderDomainService;
// @Autowired
@@ -613,9 +618,15 @@ public class ExecutionStockInOrderDomainService {
}
// 入参去重同一请求内重复ID会导致同一执行单被多次推送WMS
List<Long> distinctInOrderIds = inOrderIds.stream().distinct().collect(Collectors.toList());
// 只校验有效单据已删除(软删)执行单混入ID过期页面提交时在此拦截
// 此前list/getById均不过滤del_flag软删单照样被推到WMS形成"幽灵单"
List<ExecutionStockInOrder> checkOrders = stockInOrderService.list(
new QueryWrapper<ExecutionStockInOrder>().lambda()
.in(ExecutionStockInOrder::getInOrderId, distinctInOrderIds));
.in(ExecutionStockInOrder::getInOrderId, distinctInOrderIds)
.eq(ExecutionStockInOrder::getDelFlag, 1));
if (checkOrders.size() != distinctInOrderIds.size()) {
throw new ServiceException("下发失败:存在已删除的单据,请刷新后重新选择");
}
for (ExecutionStockInOrder order : checkOrders) {
if (order.getIssueTime() != null) {
throw new ServiceException("下发失败:单据[" + order.getInOrderNumber() + "]已下发,不可重复下发;如需重新下发请先取消下发");
@@ -704,24 +715,88 @@ public class ExecutionStockInOrderDomainService {
* @return Boolean
*/
public Boolean returnResult(String orderNumber, Long status, String type) {
// WMS内部Feign回传可能无登录上下文(如PDA异步完成上架)SecurityUtils.getLoginUser()会返回null
// 更新人信息判空兜底无用户时只更新状态不覆盖原有更新人字段
LoginUser loginUser = SecurityUtils.getLoginUser();
String userRealName = loginUser.getUserPo() != null && loginUser.getUserPo().getUserName() != null
? loginUser.getUserPo().getUserName()
: (loginUser.getRealname() != null ? loginUser.getRealname() : loginUser.getUsername());
String userRealName = null;
Long updateBy = null;
if (loginUser != null) {
userRealName = loginUser.getUserPo() != null && loginUser.getUserPo().getUserName() != null
? loginUser.getUserPo().getUserName()
: (loginUser.getRealname() != null ? loginUser.getRealname() : loginUser.getUsername());
updateBy = loginUser.getUserid();
}
if (type != null && type.equals("1")) {
return stockOutOrderService.update(null, new UpdateWrapper<ExecutionStockOutOrder>().lambda()
.set(ExecutionStockOutOrder::getStatus, status)
.set(ExecutionStockOutOrder::getUpdateBy, loginUser.getUserid())
.set(ExecutionStockOutOrder::getUpdateByName, userRealName)
.set(ExecutionStockOutOrder::getUpdateTime, new Date())
.in(ExecutionStockOutOrder::getOutOrderNumber, orderNumber));
LambdaUpdateWrapper<ExecutionStockOutOrder> wrapper = new LambdaUpdateWrapper<ExecutionStockOutOrder>()
.set(ExecutionStockOutOrder::getStatus, status);
if (updateBy != null) {
wrapper.set(ExecutionStockOutOrder::getUpdateBy, updateBy)
.set(ExecutionStockOutOrder::getUpdateByName, userRealName)
.set(ExecutionStockOutOrder::getUpdateTime, new Date());
}
wrapper.in(ExecutionStockOutOrder::getOutOrderNumber, orderNumber);
return stockOutOrderService.update(null, wrapper);
} else {
return stockInOrderService.update(null, new UpdateWrapper<ExecutionStockInOrder>().lambda()
.set(ExecutionStockInOrder::getStatus, status)
.set(ExecutionStockInOrder::getUpdateBy, loginUser.getUserid())
.set(ExecutionStockInOrder::getUpdateByName, userRealName)
.set(ExecutionStockInOrder::getUpdateTime, new Date())
.in(ExecutionStockInOrder::getInOrderNumber, orderNumber));
LambdaUpdateWrapper<ExecutionStockInOrder> wrapper = new LambdaUpdateWrapper<ExecutionStockInOrder>()
.set(ExecutionStockInOrder::getStatus, status);
// 已入库(5)时同步issueStatus=4供前端"入库执行单"列表入库状态列展示"已入库"
if (status != null && status == 5L) {
wrapper.set(ExecutionStockInOrder::getIssueStatus, 4);
}
if (updateBy != null) {
wrapper.set(ExecutionStockInOrder::getUpdateBy, updateBy)
.set(ExecutionStockInOrder::getUpdateByName, userRealName)
.set(ExecutionStockInOrder::getUpdateTime, new Date());
}
wrapper.in(ExecutionStockInOrder::getInOrderNumber, orderNumber);
boolean updated = stockInOrderService.update(null, wrapper);
// 同步预约入库单(前端"入库业务单"列表)状态
syncReservationStatus(orderNumber, status, updateBy, userRealName);
return updated;
}
}
/**
* 入库执行单状态回传后同步预约入库单
* 执行单通过business_in_order_number关联预约单已入库(5)且该预约单名下关联执行单全部完成时
* 预约单同步置为已入库同步失败只记日志不影响执行单状态更新结果
*/
private void syncReservationStatus(String orderNumber, Long status, Long updateBy, String userRealName) {
try {
if (status == null || status != 5L) {
return;
}
ExecutionStockInOrder execution = stockInOrderService.getOne(new QueryWrapper<ExecutionStockInOrder>().lambda()
.eq(ExecutionStockInOrder::getInOrderNumber, orderNumber)
.eq(ExecutionStockInOrder::getDelFlag, 1)
.last("limit 1"));
if (execution == null || execution.getBusinessInOrderNumber() == null
|| execution.getBusinessInOrderNumber().trim().isEmpty()) {
return;
}
// 多仓库拆单时存在多个关联执行单全部已入库才同步预约单
long unfinished = stockInOrderService.count(new QueryWrapper<ExecutionStockInOrder>().lambda()
.eq(ExecutionStockInOrder::getBusinessInOrderNumber, execution.getBusinessInOrderNumber())
.eq(ExecutionStockInOrder::getDelFlag, 1)
.and(w -> w.isNull(ExecutionStockInOrder::getStatus).or().lt(ExecutionStockInOrder::getStatus, 5)));
if (unfinished > 0) {
log.info("预约入库单[{}]名下仍有{}张执行单未完成,暂不同步已入库状态", execution.getBusinessInOrderNumber(), unfinished);
return;
}
LambdaUpdateWrapper<ReservationStockInOrder> reservationWrapper = new LambdaUpdateWrapper<ReservationStockInOrder>()
.set(ReservationStockInOrder::getStatus, 5)
// issueStatus=4 为前端"入库业务单"列表入库状态列的"已入库"展示值
.set(ReservationStockInOrder::getIssueStatus, 4);
if (updateBy != null) {
reservationWrapper.set(ReservationStockInOrder::getUpdateBy, updateBy)
.set(ReservationStockInOrder::getUpdateByName, userRealName)
.set(ReservationStockInOrder::getUpdateTime, new Date());
}
reservationWrapper.in(ReservationStockInOrder::getInOrderNumber, execution.getBusinessInOrderNumber());
reservationStockInOrderService.update(reservationWrapper);
log.info("预约入库单[{}]已同步为已入库", execution.getBusinessInOrderNumber());
} catch (Exception e) {
log.warn("同步预约入库单状态失败: orderNumber={}, status={}", orderNumber, status, e);
}
}
@@ -336,6 +336,12 @@ public class ReservationStockInOrderImpl extends ServiceImpl<ReservationStockInO
if (productDetailList.isEmpty()) {
throw new Exception("未解析到产品明细数据,请检查模板中是否填写了產品編號");
}
// 行级必填校验支数缺失的行直接给出明确提示避免后续 new BigDecimal(null) 抛无信息的NPE
for (ProductDetail productDetail : productDetailList) {
if (productDetail.getPieceCount() == null) {
throw new Exception("产品[" + productDetail.getProductCode() + "]的【支/件数】未填写,请补全后重新导入");
}
}
LOGGER.info("页签[{}]解析完成,货品明细{}条,客户配送明细{}条",
sheetName, productDetailList.size(), customerDeliveryDetailList.size());
@@ -658,6 +664,9 @@ public class ReservationStockInOrderImpl extends ServiceImpl<ReservationStockInO
preparedOrders.add(prepared); // null=空页签跳过
}
} catch (Exception e) {
// 完整堆栈进服务端日志便于定位页签内解析异常的具体行号
LOGGER.error("页签[{}]入库导入解析失败", name, e);
// 非模板页签的解析异常如NPEmessage 可能为空兜底用异常类名避免报错显示"页签[x]null"
sheetProblems.add("页签[" + name + "]" + (e.getMessage() == null ? e.toString() : e.getMessage()));
}
}
@@ -710,6 +719,15 @@ public class ReservationStockInOrderImpl extends ServiceImpl<ReservationStockInO
if (productDetailList == null || productDetailList.isEmpty()) {
return null;
}
// 行级必填校验编号/支数缺失的行直接给出明确提示避免后续 new BigDecimal(null) 抛无信息的NPE
for (StockInProductDetail productDetail : productDetailList) {
if (productDetail.getProductCode() == null || productDetail.getProductCode().trim().isEmpty()) {
throw new ServiceException("存在未填写【產品編號】的明细行,请补全后重新导入");
}
if (productDetail.getPieceCount() == null) {
throw new ServiceException("产品[" + productDetail.getProductCode() + "]的【支/件数】未填写,请补全后重新导入");
}
}
StockInHeader stockInHeader = resultDTO.getStockInHeader();
// ====== 第一步物料编号存在性校验模板只填物料编号即可名称按编号自动匹配 ======
// 查询结果为空说明库中没有该物料先收集全部缺失编号不立即报错
@@ -1948,7 +1948,6 @@ public class ReservationStockInOrderApplicationService {
}
stockInOrderDO.setOrderTypeName(documentTypeData.getDictLabel());
}
//翻译优先级别类型
if (StringUtils.isNotBlank(stockInOrderDO.getPriorityLevelCode())){
AjaxResult priorityLevelResult = systemServiceFeign.selectListByDictType(DictCode.PRIORITY_LEVEL.getCode());
@@ -78,6 +78,16 @@ public class ReservationStockInOrderAssembler {
// 最后使用username账号作为兜底
userRealName = loginUser.getUsername();
}
// 单据类型跟随业务类型页面唯一的类型选择项是"业务类型"(只提交businessType)
// 编辑时前端回显提交的orderTypeCode/orderTypeName是旧值若以回显值为准会导致编辑改类型不生效
// 系统内businessType与orderTypeCode同值域(pu_tong_ru_ku/tui_huo_ru_ku)以businessType为准保持三者一致
if (stockInOrderDO.getBusinessType() != null && stockInOrderDO.getBusinessType().trim().length() > 0) {
stockInOrderDO.setOrderTypeCode(stockInOrderDO.getBusinessType().trim());
} else if (stockInOrderDTO.getInOrderId() == null
&& (stockInOrderDO.getOrderTypeCode() == null || stockInOrderDO.getOrderTypeCode().trim().length() == 0)) {
// 仅新增且无业务类型时兜底普通入库编辑时两字段都为空则不覆盖(updateById跳过null字段)
stockInOrderDO.setOrderTypeCode("pu_tong_ru_ku");
}
if(stockInOrderDTO.getInOrderId() != null){
stockInOrderDO.setUpdateBy(userId);
stockInOrderDO.setUpdateByName(userRealName);
@@ -91,11 +101,6 @@ public class ReservationStockInOrderAssembler {
stockInOrderDO.setCreateByName(userRealName);
stockInOrderDO.setCreateTime(new Date());
stockInOrderDO.setDelFlag(1);
// 新增入库单时如果入库单类型为空默认设置为普通入库
String orderTypeCode = stockInOrderDO.getOrderTypeCode();
if (orderTypeCode == null || orderTypeCode.trim().length() == 0) {
stockInOrderDO.setOrderTypeCode("pu_tong_ru_ku");
}
String orderTypeName = stockInOrderDO.getOrderTypeName();
if (orderTypeName == null || orderTypeName.trim().length() == 0) {
stockInOrderDO.setOrderTypeName("普通入库单");
@@ -525,9 +525,14 @@ public class ReservationStockInOrderDomainService {
if (inOrderIds == null || inOrderIds.isEmpty()) {
throw new ServiceException("下发失败:未选择单据");
}
// 只校验有效单据软删单混入ID过期页面提交时在此拦截
List<ReservationStockInOrder> checkOrders = stockInOrderService.list(
new QueryWrapper<ReservationStockInOrder>().lambda()
.in(ReservationStockInOrder::getInOrderId, inOrderIds));
.in(ReservationStockInOrder::getInOrderId, inOrderIds)
.eq(ReservationStockInOrder::getDelFlag, 1));
if (checkOrders.size() != inOrderIds.stream().distinct().count()) {
throw new ServiceException("下发失败:存在已删除的单据,请刷新后重新选择");
}
for (ReservationStockInOrder order : checkOrders) {
// 校验1必须已审核issueStatus==2 表示审核成功
if (order.getIssueStatus() == null || order.getIssueStatus() != 2) {
@@ -560,50 +565,12 @@ public class ReservationStockInOrderDomainService {
.set(ReservationStockInOrder::getUpdateTime, new Date())
.in(ReservationStockInOrder::getInOrderId, stockInOrderDO.getInOrderIds()));
//todo下发推送到wms
for (Long inOrderId : inOrderIds) {
ReservationStockInOrder byId = stockInOrderService.getById(inOrderId);
StockInOrder stockInOrder = new StockInOrder();
BeanUtils.copyProperties(byId, stockInOrder, "inOrderId");
stockInOrder.setOmsStockInOrderId(String.valueOf(byId.getInOrderId()));
// 业务链路2026-09与业务确认生产验证预约单下发生成执行单执行单下发时才推送WMS
// 预约单下发此前会先把预约单自身推到WMSomsInOrderAdd/omsInOrderAddDetail执行单下发又推一次
// 导致WMS入库管理出现预约单号(R260907001)+执行单号(RK260907001)两张单仓库收两道货
// 已移除预约单的WMS推送WMS推送唯一入口收敛到 ExecutionStockInOrderDomainService.issueOrder
// 历史已推送的预约单数据由"取消下发"cancelIssueOrderomsCancelInOrder幂等负责清理
try {
//WMS保存结果必须校验此前接口返回voidFeign降级被静默吞掉OMS标记已下发但WMS无数据/缺明细
//收货流程无从进行流程阻断失败抛错回滚下发标记WMS侧幂等主单/明细判重重下发安全
AjaxResult addResult = wmsServiceFeign.omsInOrderAdd(stockInOrder); // 推主单
if (addResult == null || !"200".equals(String.valueOf(addResult.get("code")))) {
throw new ServiceException("下发到WMS失败:入库单[" + stockInOrder.getInOrderNumber() + "]保存主单失败:"
+ (addResult == null ? "WMS服务不可用或已降级" : addResult.get("msg")));
}
String inOrderNumber = stockInOrder.getInOrderNumber();
List<ReservationInMaterialDetail> materialDetailList = materialDetailService.list(
new QueryWrapper<ReservationInMaterialDetail>().lambda()
.eq(ReservationInMaterialDetail::getInOrderNumber, inOrderNumber)
.eq(ReservationInMaterialDetail::getDelFlag, 1));
List<InMaterialDetail> inMaterialDetailList = new ArrayList<>();
for (ReservationInMaterialDetail reservationInMaterialDetail : materialDetailList) {
InMaterialDetail inMaterialDetail = new InMaterialDetail();
BeanUtils.copyProperties(reservationInMaterialDetail, inMaterialDetail, "materialDetailId");
inMaterialDetail.setOmsInMaterialDetail(String.valueOf(reservationInMaterialDetail.getMaterialDetailId()));
// 过期日期为空且饮用日期有值时用饮用日期补齐过期日期食品业务饮用日期即效期
// 确保下发WMS后入库/收货/库存链路的过期日期能正常回显
if (inMaterialDetail.getExpiryDate() == null && inMaterialDetail.getDrinkDate() != null) {
inMaterialDetail.setExpiryDate(inMaterialDetail.getDrinkDate());
}
inMaterialDetailList.add(inMaterialDetail);
}
AjaxResult detailResult = wmsServiceFeign.omsInOrderAddDetail(inMaterialDetailList); // 推明细会触发WMS自动审核
if (detailResult == null || !"200".equals(String.valueOf(detailResult.get("code")))) {
throw new ServiceException("下发到WMS失败:入库单[" + inOrderNumber + "]保存明细失败:"
+ (detailResult == null ? "WMS服务不可用或已降级" : detailResult.get("msg")));
}
log.info("下发到WMS成功,单据号:{}", byId.getInOrderNumber());
} catch (Exception e) {
log.error("下发到WMS失败,单据号:{}", byId.getInOrderNumber(), e);
throw new ServiceException("下发到WMS失败:" + e.getMessage());
}
}
//todo下发推送到入库业务单
for (Long inOrderId : inOrderIds) {
// Long inOrderId = stockInOrderDO.getInOrderId();
@@ -630,9 +597,16 @@ public class ReservationStockInOrderDomainService {
// 执行单"运输业务单号"列永远显示入库业务单号未选运输也显示
BeanUtils.copyProperties(byId, reservationStockInOrder,"inOrderId","issueStatus","issueTime","issueId","issueName","reservationAuditId","reservationAuditName","reservationAuditTime","businessOrderNo","businessNumber","tmsOrderNumber");
reservationStockInOrder.setIssueStatus(0);
reservationStockInOrder.setOrderTypeCode("pu_tong_ru_ku");
reservationStockInOrder.setOrderTypeName("普通入库");
reservationStockInOrder.setBusinessType("pu_tong_ru_ku");
// 退货入库单下发时类型跟随预约单避免执行入库单被固定写成普通入库
if ("tui_huo_ru_ku".equals(byId.getOrderTypeCode()) || "退货入库".equals(byId.getOrderTypeName())) {
reservationStockInOrder.setOrderTypeCode("tui_huo_ru_ku");
reservationStockInOrder.setOrderTypeName("退货入库");
reservationStockInOrder.setBusinessType("tui_huo_ru_ku");
} else {
reservationStockInOrder.setOrderTypeCode("pu_tong_ru_ku");
reservationStockInOrder.setOrderTypeName("普通入库");
reservationStockInOrder.setBusinessType("pu_tong_ru_ku");
}
reservationStockInOrder.setReservationOrderSource("客户预约");
reservationStockInOrder.setWarehouseId(warehouseId);
if (warehouseId == null || warehouseId == 0L){
@@ -801,9 +775,14 @@ public class ReservationStockInOrderDomainService {
if (inOrderIds == null || inOrderIds.isEmpty()) {
throw new ServiceException("执行失败:未选择单据");
}
// 只校验有效单据软删单混入ID过期页面提交时在此拦截 issueOrder 校验口径一致
List<ReservationStockInOrder> checkOrders = stockInOrderService.list(
new QueryWrapper<ReservationStockInOrder>().lambda()
.in(ReservationStockInOrder::getInOrderId, inOrderIds));
.in(ReservationStockInOrder::getInOrderId, inOrderIds)
.eq(ReservationStockInOrder::getDelFlag, 1));
if (checkOrders.size() != inOrderIds.stream().distinct().count()) {
throw new ServiceException("执行失败:存在已删除的单据,请刷新后重新选择");
}
for (ReservationStockInOrder order : checkOrders) {
if (order.getIssueTime() != null) {
throw new ServiceException("执行失败:单据[" + order.getInOrderNumber() + "]已下发,不可重复执行;如需重新下发请先取消下发");
@@ -881,9 +860,16 @@ public class ReservationStockInOrderDomainService {
// 运输业务单号不直接从业务单头复制避免历史已取消运输单号残留下发到执行单
BeanUtils.copyProperties(byId, reservationStockInOrder,"inOrderId","issueStatus","issueTime","issueId","issueName","reservationAuditId","reservationAuditName","reservationAuditTime","businessOrderNo","businessNumber","tmsOrderNumber");
reservationStockInOrder.setIssueStatus(0);
reservationStockInOrder.setOrderTypeCode("pu_tong_ru_ku");
reservationStockInOrder.setOrderTypeName("普通入库");
reservationStockInOrder.setBusinessType("pu_tong_ru_ku");
// 退货入库单下发时类型跟随预约单避免执行入库单被固定写成普通入库
if ("tui_huo_ru_ku".equals(byId.getOrderTypeCode()) || "退货入库".equals(byId.getOrderTypeName())) {
reservationStockInOrder.setOrderTypeCode("tui_huo_ru_ku");
reservationStockInOrder.setOrderTypeName("退货入库");
reservationStockInOrder.setBusinessType("tui_huo_ru_ku");
} else {
reservationStockInOrder.setOrderTypeCode("pu_tong_ru_ku");
reservationStockInOrder.setOrderTypeName("普通入库");
reservationStockInOrder.setBusinessType("pu_tong_ru_ku");
}
reservationStockInOrder.setReservationOrderSource("客户预约");
reservationStockInOrder.setWarehouseId(warehouseId);
// reservationStockInOrder.setOrganizationId(orgId);
@@ -22,7 +22,7 @@ import java.util.Map;
/**
* 三方服务 Feign
*/
@FeignClient(contextId = "thirdPartyServiceFeign",url = "http://10.33.0.129:8012", value = ServiceNameConstants.THIRDPARTY_CENTER, configuration = FeignAutoConfiguration.class)
@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;
}
@@ -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());
}
}
}
+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.30: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.30:6848
# server-addr: 10.33.0.129:6010
server-addr: 10.102.192.31:6848
username: nacos
password: manhuoda@2023
#线上正式环境
@@ -116,6 +116,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<result property="businessChargeType" column="BUSINESS_CHARGE_TYPE" />
<result property="businessPriceWay" column="BUSINESS_PRICE_WAY" />
<result property="discount" column="DISCOUNT" />
<result property="totalOutboundQuantity" column="TOTAL_OUTBOUND_QUANTITY" />
</resultMap>
@@ -405,7 +406,14 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<select id="queryList" parameterType="com.mhd.oms.domain.reservationStockOutOrder.repository.todo.ReservationStockOutOrderDO" resultMap="StockOutOrderResult">
select
<include refid="selectStockOutOrderPo"/>
<include refid="selectStockOutOrderPo"/>,
<!-- 出库数量:汇总明细表实际出库数量,只统计一级明细(level=1),与详情页汇总口径一致;
原逻辑为Java循环逐单调getInfoChildren汇总(N+1)后注释,未再赋值导致列表该字段恒为null -->
(select coalesce(sum(omd.outbound_quantity), 0)
from reservation_out_material_detail omd
where omd.out_order_number = a.out_order_number
and omd.del_flag = 1
and (omd.level is null or omd.level = 1)) as total_outbound_quantity
from reservation_stock_out_order a
<where>
<include refid="selectStockOutOrderPo1"/>
@@ -208,9 +208,9 @@ public class HandoverTaskOrderApplicationService {
public Boolean completeHandover(HandoverTaskOrderDO handoverTaskOrderDO){
Boolean result = handoverTaskOrderDomainService.completeHandover(handoverTaskOrderDO);
List<MaterialInventoryParamDO> clearoutParamDOs = handoverTaskOrderDomainService.getLastClearoutParamDOs();
for (MaterialInventoryParamDO paramDO : clearoutParamDOs) {
materialInventoryApplicationService.pushBillingRecordClearout(paramDO.getMaterialInventoryId(), paramDO.getQuantity());
}
// for (MaterialInventoryParamDO paramDO : clearoutParamDOs) {
// materialInventoryApplicationService.pushBillingRecordClearout(paramDO.getMaterialInventoryId(), paramDO.getQuantity());
// }
return result;
}
@@ -309,9 +309,9 @@ public class HandoverTaskOrderApplicationService {
completeDO.setBillingJson(handoverTaskOrderDO.getBillingJson());
handoverTaskOrderDomainService.completeHandover(completeDO);
List<MaterialInventoryParamDO> clearoutParamDOs = handoverTaskOrderDomainService.getLastClearoutParamDOs();
for (MaterialInventoryParamDO paramDO : clearoutParamDOs) {
materialInventoryApplicationService.pushBillingRecordClearout(paramDO.getMaterialInventoryId(), paramDO.getQuantity());
}
// for (MaterialInventoryParamDO paramDO : clearoutParamDOs) {
// materialInventoryApplicationService.pushBillingRecordClearout(paramDO.getMaterialInventoryId(), paramDO.getQuantity());
// }
}
}
}
@@ -226,6 +226,14 @@ public class InvestigationManageApplicationService {
materialInventoryPO = materialInventoryMapper.selectByIdWithBatchAttributes(materialInventoryId);
}
// 从库存表回填批次号入库日期生产日期过期日期入库日期取库存记录入库时间create_time
if (materialInventoryPO != null) {
investigetionManageDetailPO.setBatchNumber(materialInventoryPO.getBatchNumber());
investigetionManageDetailPO.setInboundDate(materialInventoryPO.getCreateTime());
investigetionManageDetailPO.setProductionDate(materialInventoryPO.getProductionDate());
investigetionManageDetailPO.setExpiryDate(materialInventoryPO.getExpiryDate());
}
if (materialBaseInfoId != null && batchDetailMap.containsKey(materialBaseInfoId)) {
List<BatchDetailFeignPO> batchDetailFeignPOList = batchDetailMap.get(materialBaseInfoId);
// 用于跟踪已添加到列表中的batchDetailId
@@ -1,6 +1,7 @@
package com.mhd.wms.domain.investigetionManageDetail.repository.po;
import com.baomidou.mybatisplus.annotation.TableField;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.mhd.common.core.annotation.Excel;
import com.mhd.common.core.web.domain.BaseVOEntity;
import com.mhd.wms.domain.materialMoreDetail.repository.po.MaterialMoreDetailPO;
@@ -9,6 +10,7 @@ import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.math.BigDecimal;
import java.util.Date;
import java.util.List;
@@ -219,4 +221,20 @@ public class InvestigetionManageDetailPO extends BaseVOEntity {
@TableField(exist = false)
private List<MaterialMoreDetailPO> materialMoreDetailList;
@ApiModelProperty("批次号")
@Excel(name = "批次号")
private String batchNumber;
@ApiModelProperty("入库日期(库存入库时间)")
@JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8")
private Date inboundDate;
@ApiModelProperty("生产日期")
@JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8")
private Date productionDate;
@ApiModelProperty("过期日期")
@JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8")
private Date expiryDate;
}
@@ -810,8 +810,21 @@ public class StockShelfOrderDomainService {
stockInOrder.setUpdateBy(loginUser.getUserid());
stockInOrder.setUpdateByName(loginUser.getUsername());
stockInOrder.setUpdateTime(new Date());
return stockInOrderService.update(stockInOrder,
boolean updated = stockInOrderService.update(stockInOrder,
new QueryWrapper<StockInOrder>().lambda().eq(StockInOrder::getInOrderNumber, stockShelfOrderPO.getInOrderNumber()));
if (updated) {
// 上架推进入库状态(4-上架中/5-已入库)后回传OMS入库业务单保证OMS入库状态与WMS一致
// OMS不可用或回传失败只记日志不影响WMS上架主流程
try {
AjaxResult notifyResult = omsServiceFeign.returnInResult(stockShelfOrderPO.getInOrderNumber(), Long.valueOf(status), "0");
if (notifyResult == null || !"200".equals(String.valueOf(notifyResult.get("code")))) {
log.warn("回传OMS入库状态失败: orderNumber={}, status={}, result={}", stockShelfOrderPO.getInOrderNumber(), status, notifyResult);
}
} catch (Exception e) {
log.warn("回传OMS入库状态异常: orderNumber={}, status={}", stockShelfOrderPO.getInOrderNumber(), status, e);
}
}
return updated;
}
/**
* @description 完成上架
@@ -9,46 +9,46 @@ import org.springframework.context.annotation.Configuration;
/**
* XXL-JOB 配置类
*/
@Configuration
//@Configuration
public class XxlJobConfig {
private Logger logger = LoggerFactory.getLogger(XxlJobConfig.class);
@Value("${xxl.job.admin.addresses}")
private String adminAddresses;
@Value("${xxl.job.accessToken}")
private String accessToken;
@Value("${xxl.job.executor.appname}")
private String appname;
@Value("${xxl.job.executor.address}")
private String address;
@Value("${xxl.job.executor.ip}")
private String ip;
@Value("${xxl.job.executor.port}")
private int port;
@Value("${xxl.job.executor.logpath}")
private String logPath;
@Value("${xxl.job.executor.logretentiondays}")
private int logRetentionDays;
@Bean
public XxlJobSpringExecutor xxlJobExecutor() {
logger.info(">>>>>>>>>>> xxl-job config init.");
XxlJobSpringExecutor xxlJobSpringExecutor = new XxlJobSpringExecutor();
xxlJobSpringExecutor.setAdminAddresses(adminAddresses);
xxlJobSpringExecutor.setAppname(appname);
xxlJobSpringExecutor.setAddress(address);
xxlJobSpringExecutor.setIp(ip);
xxlJobSpringExecutor.setPort(port);
xxlJobSpringExecutor.setAccessToken(accessToken);
xxlJobSpringExecutor.setLogPath(logPath);
xxlJobSpringExecutor.setLogRetentionDays(logRetentionDays);
return xxlJobSpringExecutor;
}
// private Logger logger = LoggerFactory.getLogger(XxlJobConfig.class);
//
// @Value("${xxl.job.admin.addresses}")
// private String adminAddresses;
//
// @Value("${xxl.job.accessToken}")
// private String accessToken;
//
// @Value("${xxl.job.executor.appname}")
// private String appname;
//
// @Value("${xxl.job.executor.address}")
// private String address;
//
// @Value("${xxl.job.executor.ip}")
// private String ip;
//
// @Value("${xxl.job.executor.port}")
// private int port;
//
// @Value("${xxl.job.executor.logpath}")
// private String logPath;
//
// @Value("${xxl.job.executor.logretentiondays}")
// private int logRetentionDays;
//
// @Bean
// public XxlJobSpringExecutor xxlJobExecutor() {
// logger.info(">>>>>>>>>>> xxl-job config init.");
// XxlJobSpringExecutor xxlJobSpringExecutor = new XxlJobSpringExecutor();
// xxlJobSpringExecutor.setAdminAddresses(adminAddresses);
// xxlJobSpringExecutor.setAppname(appname);
// xxlJobSpringExecutor.setAddress(address);
// xxlJobSpringExecutor.setIp(ip);
// xxlJobSpringExecutor.setPort(port);
// xxlJobSpringExecutor.setAccessToken(accessToken);
// xxlJobSpringExecutor.setLogPath(logPath);
// xxlJobSpringExecutor.setLogRetentionDays(logRetentionDays);
// return xxlJobSpringExecutor;
// }
}
+4 -4
View File
@@ -14,18 +14,18 @@ spring:
nacos:
discovery:
# server-addr: 127.0.0.1:8848
server-addr: 10.33.0.129:6010
# server-addr: 10.33.0.129:6010
# 线上测试环境配置 容器名+端口号
# server-addr: 10.102.192.30:6848
server-addr: 10.102.192.31:6848
username: nacos
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: 10.33.0.129:6010
# 线上测试环境配置 容器名+端口号
# server-addr: 10.102.192.30:6848
server-addr: 10.102.192.31:6848
username: nacos
password: manhuoda@2023
#线上正式环境