Author SHA1 Message Date
王奎兴 568ce3f96d Merge branch 'dev' into dev-bms-0723
# Conflicts:
#	mhd_bms/src/main/resources/bootstrap.yml
#	mhd_bms/src/main/resources/mapper/SettlementCustomersMapper.xml
2026-08-05 18:19:19 +08:00
王奎兴 0ee27d796f 回显应收应付; 2026-08-05 18:16:25 +08:00
王奎兴 7842ceaf71 回显应收应付; 2026-08-05 18:13:30 +08:00
王奎兴 987a7c564d 发31 2026-08-05 17:54:11 +08:00
王奎兴 18c8c4d18d 发31 2026-08-05 17:32:17 +08:00
王奎兴 0f4da97358 新增应收账单推送nc 2026-08-05 17:30:17 +08:00
秦鸿展 2787f7651e 30 2026-08-05 17:14:03 +08:00
王奎兴 b9fe4bc4d2 新增应收账单推送nc 2026-08-05 17:01:52 +08:00
王奎兴 7a6c570a88 查货主卡死; 2026-08-05 15:17:00 +08:00
王奎兴 f1567eb81e 查货主卡死; 2026-08-05 14:48:09 +08:00
王奎兴 885d38565c 业务单详情添加执行单信息; 2026-08-05 14:45:32 +08:00
王奎兴 476d7c8b0e 发测试 2026-08-04 17:18:22 +08:00
秦鸿展 93dd653ca9 31 2026-08-04 16:35:35 +08:00
秦鸿展 f84c7b0843 BI月台字段修改 2026-08-04 16:34:41 +08:00
秦鸿展 3feb3851e4 30 2026-08-04 14:27:17 +08:00
秦鸿展 38a04d6d30 BI月台新增字段 2026-08-04 14:12:00 +08:00
秦鸿展 c58112a719 正式31 2026-08-03 20:43:22 +08:00
秦鸿展 a4a29c7c8e 正式30 2026-08-03 20:33:23 +08:00
秦鸿展 9283cc9df8 BI报表增加字段 2026-08-03 18:23:21 +08:00
王奎兴 076c915a4c 发31 2026-08-03 16:23:38 +08:00
王奎兴 55c958bde5 发30 2026-08-03 16:13:10 +08:00
zhaoqing c5babe103e feat(sys):合同新增报错 2026-07-31 23:57:48 +08:00
王奎兴 287ae8f22b Merge branch 'dev' into dev-ty1.2 2026-07-31 22:39:30 +08:00
王奎兴 1779bc2b23 发30 2026-07-31 18:02:30 +08:00
王奎兴 2a56ce433f 发31 2026-07-31 17:57:50 +08:00
王奎兴 2dd8e7f0a2 发30 2026-07-31 17:51:26 +08:00
王奎兴 b8605c6b43 预约单老系统数据导入; 2026-07-31 17:12:24 +08:00
秦鸿展 5fec54ac63 发测试 2026-07-31 16:41:19 +08:00
秦鸿展 564b8ff8aa 发测试 2026-07-31 16:07:17 +08:00
王奎兴 76a5c987b2 预约单老系统数据导入; 2026-07-31 15:53:35 +08:00
王奎兴 f6ee1a3eee 预约单老系统数据导入; 2026-07-31 15:47:20 +08:00
zhaoqing 1297f920be fix(bms):单据计费查询条件添加 2026-07-31 14:59:20 +08:00
王奎兴 d4ba4f0c0b Merge remote-tracking branch 'origin/dev' into dev 2026-07-30 17:22:11 +08:00
王奎兴 0ed45fee69 仓库出租率计算定时任务重复执行问题;发30; 2026-07-30 17:21:59 +08:00
秦鸿展 69412f7293 发测试 2026-07-30 11:43:06 +08:00
秦鸿展 2bd4d5bb63 发测试 2026-07-30 10:08:24 +08:00
秦鸿展 8b9b29dbf1 发测试 2026-07-30 10:04:03 +08:00
zhaoqing 5890660fe4 feat(bms):导出应收账单 2026-07-29 18:39:05 +08:00
zhaoqing fa6ccad965 feat(bms):导出应收账单 2026-07-29 18:29:54 +08:00
秦鸿展 e12beb1e0c 发30 2026-07-29 17:23:52 +08:00
秦鸿展 8c722deac6 发测试 2026-07-29 16:34:59 +08:00
秦鸿展 a1494846db 编辑库区 2026-07-29 16:33:40 +08:00
秦鸿展 0d70450997 费用修改 2026-07-29 15:51:11 +08:00
zhaoqing 6c6649368c sql(bms) 2026-07-29 15:24:41 +08:00
zhaoqing 92d53ad90d fix(bms):新增合同(费用类别) 2026-07-29 15:21:36 +08:00
秦鸿展 8b9cd8c749 复制订单 2026-07-29 14:57:31 +08:00
王奎兴 c200645a15 发30 2026-07-29 14:32:11 +08:00
王奎兴 674f56b2c2 库存数量和单位名称 2026-07-29 14:25:12 +08:00
王奎兴 44e7581b2c 发31 2026-07-29 11:02:00 +08:00
王奎兴 01b2723e1f 维他奶导入添加库存信息; 2026-07-29 10:54:22 +08:00
秦鸿展 489515f865 30 2026-07-28 21:18:04 +08:00
秦鸿展 d8aa1e9490 31 2026-07-28 21:10:15 +08:00
秦鸿展 07d9dacded 31 2026-07-28 16:10:37 +08:00
秦鸿展 538a3b42bd 登录校验手机号格式注释 2026-07-28 16:07:00 +08:00
赵辉 55dfb6f4a1 30 2026-07-28 14:47:06 +08:00
赵辉 1f84ad71d8 单点登录修改 2026-07-28 14:43:31 +08:00
赵辉 4d0eb901c9 单点登录修改 2026-07-28 14:43:24 +08:00
秦鸿展 23984e69d6 上架库存货主显示异常,出库复核数量显示BUG 2026-07-28 11:06:07 +08:00
秦鸿展 a1f4953fb5 30 2026-07-25 22:08:20 +08:00
秦鸿展 25ed516000 31 2026-07-25 21:55:16 +08:00
秦鸿展 9f2e8f1855 测试 2026-07-25 21:02:13 +08:00
秦鸿展 1488405397 31 2026-07-25 19:51:53 +08:00
秦鸿展 ad55d49d6b 测试 2026-07-25 19:49:47 +08:00
秦鸿展 7aa7576799 测试 2026-07-25 19:37:11 +08:00
秦鸿展 96c95dabc6 测试 2026-07-25 19:31:11 +08:00
秦鸿展 f3fc2b3093 31 2026-07-25 17:54:17 +08:00
秦鸿展 a112aa1163 30 2026-07-25 17:21:22 +08:00
秦鸿展 57cce338b1 导入物料BUG修改 2026-07-25 13:13:32 +08:00
秦鸿展 33a6e875ce 导入物料BUG修改 2026-07-25 10:16:17 +08:00
秦鸿展 cdc098fdd3 导入物料BUG修改 2026-07-25 10:09:26 +08:00
秦鸿展 e544b76db6 导入物料BUG修改 2026-07-25 10:05:12 +08:00
秦鸿展 4f727fadc1 导入物料BUG修改 2026-07-24 20:01:18 +08:00
秦鸿展 5b98ae9435 导入物料BUG修改 2026-07-24 19:42:40 +08:00
秦鸿展 82909efe6b 导入物料BUG修改 2026-07-24 18:49:14 +08:00
zhaoqing d268718f9b fix(oms):入库/出库 预约/业务单号生成 2026-07-23 17:53:32 +08:00
王奎兴 895c8d6a4b 发测试; 2026-07-23 17:48:19 +08:00
王奎兴 914a751d96 bms2.0应收单和收款单推送nc修改; 2026-07-23 17:46:32 +08:00
王奎兴 fc16c1edf2 发30 2026-07-23 14:54:15 +08:00
王奎兴 4bd655e4da nc推送改造(进行中); 2026-07-23 14:51:14 +08:00
王奎兴 a96b03a060 nc推送改造(进行中); 2026-07-23 14:49:19 +08:00
zhaoqing 8681042a32 发测试 2026-07-23 11:47:53 +08:00
高正杨 44c9953875 oms启动报错 2026-07-23 11:00:06 +08:00
zhaoqing c48b8aa39a fix(oms):预约确认后,物料明细查询问题 2026-07-23 10:50:57 +08:00
王奎兴 36b31e5d52 Merge branch 'dev' into dev_crkbh_260721
# Conflicts:
#	mhd_oms/src/main/java/com/mhd/oms/domain/reservationStockInOrder/repository/persistence/ReservationStockInOrderImpl.java
#	mhd_oms/src/main/resources/bootstrap.yml
2026-07-23 10:44:31 +08:00
秦鸿展 f5c096fe39 发30 2026-07-23 00:39:52 +08:00
秦鸿展 75e77c0476 发31 2026-07-23 00:18:41 +08:00
王奎兴 709b151e3f 参数类型 2026-07-22 22:45:08 +08:00
王奎兴 fa731e1fa5 发30 2026-07-22 22:44:26 +08:00
王奎兴 d1448b2746 发30 2026-07-22 22:42:39 +08:00
王奎兴 32d38b7721 发30 2026-07-22 22:08:21 +08:00
王奎兴 ebc7bee5be 发31 2026-07-22 22:06:05 +08:00
王奎兴 19ca4bbe6c 物料根据组织查询; 2026-07-22 21:53:09 +08:00
王奎兴 2f6988abac 修改预约单更新预约数量 2026-07-22 21:46:28 +08:00
王奎兴 e322e28d05 修改预约单更新预约数量 2026-07-22 21:44:22 +08:00
zhaoqing 9f70b236a0 fix(oms):修改导入的单号 2026-07-22 21:35:29 +08:00
秦鸿展 7dcedab498 委托方导入修改 2026-07-22 21:03:07 +08:00
zhaoqing e2f5896be2 fix(oms):修改预约确认的单号生成 2026-07-22 20:14:19 +08:00
秦鸿展 effa681709 导入修改 2026-07-22 19:01:18 +08:00
秦鸿展 8ea6a82acd 发测试 2026-07-22 16:26:45 +08:00
秦鸿展 e7f2a79dee 委托方导入修改 2026-07-22 14:31:15 +08:00
秦鸿展 8a78122fcb 委托方导入修改以及OMS库存查询调整 2026-07-22 14:10:29 +08:00
zhaoqing 49b3722328 发测试 2026-07-22 13:43:29 +08:00
zhaoqing cb96a3700d 区分预约单和业务单 2026-07-22 11:45:06 +08:00
秦鸿展 9250d03ab1 委托方导入 2026-07-22 11:26:19 +08:00
秦鸿展 494f49ee1b 库存查询按照过期日期来过滤查询 2026-07-22 10:39:34 +08:00
zhaoqing be597775d9 fix(oms):修改预约单 2026-07-21 22:10:27 +08:00
zhaoqing 9eff15e483 fix(oms):修改orderNo 2026-07-21 21:51:33 +08:00
zhaoqing 496548558b fix(oms):出入库预约单单号 2026-07-21 21:20:56 +08:00
zhaoqing 7bd2e0b87c fix(oms):出入库执行单修改 2026-07-21 20:29:38 +08:00
zhaoqing 266d416912 fix(oms):出入库预约确认 2026-07-21 20:00:06 +08:00
zhaoqing f2216adb06 fix(oms):出库执行修改 2026-07-21 19:08:43 +08:00
zhaoqing b825f1a789 fix(oms):入库执行修改 2026-07-21 18:51:53 +08:00
zhaoqing 6177b70b34 feat(oms):出库预约单号 2026-07-21 17:57:35 +08:00
zhaoqing 30dd4abe43 feat(oms):入库预约单号 2026-07-21 17:34:24 +08:00
王奎兴 5dd23e9f42 Merge branch 'dev_jinji' into dev 2026-07-21 16:53:01 +08:00
秦鸿展 f91a2248af 调整账单时间为保存修改 2026-07-21 16:49:53 +08:00
王奎兴 b4db0a8cdb 修改预约单更新预约数量 2026-07-21 15:42:52 +08:00
秦鸿展 65fd1e6a19 31 2026-07-20 16:18:19 +08:00
秦鸿展 bab7f048eb 31 2026-07-20 16:18:12 +08:00
秦鸿展 f543c4a00f 新增费用科目BUG修改 2026-07-20 16:16:33 +08:00
秦鸿展 98004ba989 30 2026-07-20 15:40:18 +08:00
秦鸿展 76c8b1f5aa 备注字段修改 2026-07-20 15:38:34 +08:00
秦鸿展 8542a25238 31 2026-07-20 14:43:33 +08:00
秦鸿展 22590abbb8 调整账单报错 2026-07-20 14:40:11 +08:00
秦鸿展 bb68e118fa 30 2026-07-20 12:51:19 +08:00
秦鸿展 1d28170d46 新增账单金额不一致报错 2026-07-20 12:47:00 +08:00
秦鸿展 1b85098063 发31 2026-07-17 22:18:59 +08:00
秦鸿展 d6d9ee1d5e 发30 2026-07-17 22:14:14 +08:00
秦鸿展 2d9a4eaad2 发30 2026-07-17 21:44:52 +08:00
秦鸿展 1423d5d140 发30 2026-07-17 21:39:53 +08:00
秦鸿展 80e1639b83 发测试 2026-07-17 20:37:17 +08:00
秦鸿展 07862301e6 应收账单新增报错 2026-07-17 20:31:35 +08:00
秦鸿展 d6fae412cd 应收账单新增报错 2026-07-17 20:17:04 +08:00
秦鸿展 7ee70dd06c 应收账单新增报错 2026-07-17 20:11:34 +08:00
秦鸿展 6f33fc3b64 应收账单添加明细报错 2026-07-17 19:40:49 +08:00
王奎兴 a9e3d6cb6b Merge branch 'dev' into dev_jinji 2026-07-17 18:06:41 +08:00
王奎兴 5fe5ce7e82 复核添加货主id查询; 2026-07-17 18:04:56 +08:00
秦鸿展 5cc987c2c4 应收账单明细修改 2026-07-17 16:14:21 +08:00
秦鸿展 9ed1797b59 紧急任务修改 2026-07-17 15:32:11 +08:00
秦鸿展 2373be59e6 紧急任务修改 2026-07-17 15:27:17 +08:00
王奎兴 587550025d 发30 2026-07-17 14:29:43 +08:00
王奎兴 9dfcf4ef5a 发31 2026-07-17 14:22:38 +08:00
秦鸿展 914957e683 新增账单 2026-07-17 11:41:39 +08:00
99 changed files with 4418 additions and 771 deletions
@@ -79,6 +79,7 @@ public class SsoAuthorizeController {
// 5. 重定向到前端页面,token通过URL参数传递 // 5. 重定向到前端页面,token通过URL参数传递
// 前端页面需读取URL中的token参数并存入localStorage // 前端页面需读取URL中的token参数并存入localStorage
log.info("SSO单点登录成功, account={}", account); log.info("SSO单点登录成功, account={}", account);
log.info("SSO单点登录成功, account={}, token={} , redirectUrl={}", account, accessToken, redirectUrl);
response.sendRedirect(redirectUrl + "?token=" + URLEncoder.encode(accessToken, StandardCharsets.UTF_8.name())); response.sendRedirect(redirectUrl + "?token=" + URLEncoder.encode(accessToken, StandardCharsets.UTF_8.name()));
} catch (Exception e) { } catch (Exception e) {
@@ -50,7 +50,7 @@ public class SsoAuthorizeService {
@Value("${sso.public-key}") @Value("${sso.public-key}")
private String publicKeyStr; private String publicKeyStr;
@Value("https://diglog.namkwong.com.mo/main_app/sso") @Value("${sso.redirect-url}")
private String redirectUrl; private String redirectUrl;
@Resource @Resource
@@ -550,11 +550,11 @@ public class SysLoginService {
throw new ServiceException("请输入手机号和短信验证码"); throw new ServiceException("请输入手机号和短信验证码");
} }
//调用工具类校验,校验手机号格式错误 // //调用工具类校验,校验手机号格式错误
if (!RegexUtil.isPhoneLegal(userPhone)) { // if (!RegexUtil.isPhoneLegal(userPhone)) {
recordLogininfor(userPhone, Constants.LOGIN_FAIL, UserError.USER_PHONE_REG_ERROR.errmsg(), 1); // recordLogininfor(userPhone, Constants.LOGIN_FAIL, UserError.USER_PHONE_REG_ERROR.errmsg(), 1);
throw new DigitalLogisticsException(UserError.USER_PHONE_REG_ERROR); // throw new DigitalLogisticsException(UserError.USER_PHONE_REG_ERROR);
} // }
//根据域名获取一级组织ID //根据域名获取一级组织ID
AjaxResult topOrganizationIdR = organizationServiceFeign.getOrganizationByPath(path, SecurityConstants.INNER); AjaxResult topOrganizationIdR = organizationServiceFeign.getOrganizationByPath(path, SecurityConstants.INNER);
+3 -3
View File
@@ -15,7 +15,7 @@ spring:
# server-addr: 127.0.0.1:8848 # server-addr: 127.0.0.1:8848
# 线上测试环境配置 容器名+端口号 # 线上测试环境配置 容器名+端口号
# server-addr: 10.33.0.129:6010 # server-addr: 10.33.0.129:6010
server-addr: 10.102.192.30:6848 server-addr: 10.102.192.31:6848
username: nacos username: nacos
password: manhuoda@2023 password: manhuoda@2023
#线上正式环境 #线上正式环境
@@ -24,7 +24,7 @@ spring:
# password: manhuoda@2023 # password: manhuoda@2023
config: config:
# server-addr: 127.0.0.1:8848 # server-addr: 127.0.0.1:8848
server-addr: 10.102.192.30:6848 server-addr: 10.102.192.31:6848
# 测试环境配置 容器名+端口号 # 测试环境配置 容器名+端口号
# server-addr: 10.33.0.129:6010 # server-addr: 10.33.0.129:6010
# 线上测试环境配置 容器名+端口号 # 线上测试环境配置 容器名+端口号
@@ -52,4 +52,4 @@ sso:
AwIDAQAB AwIDAQAB
-----END PUBLIC KEY----- -----END PUBLIC KEY-----
# SSO登录成功后跳转的前端页面地址 # SSO登录成功后跳转的前端页面地址
redirect-url: "/" redirect-url: "https://diglog.namkwong.com.mo/main_app/sso"
@@ -127,6 +127,8 @@ public final class BiSnapshotWeeklyRandomDataBuilder {
for (String[] row : Baseline.P_PLATES) { for (String[] row : Baseline.P_PLATES) {
int dur = jitterInt(Integer.parseInt(row[3]), r); int dur = jitterInt(Integer.parseInt(row[3]), r);
vehicles.add(PlatformVehicleItemVO.builder() vehicles.add(PlatformVehicleItemVO.builder()
.appointmentTime(Baseline.P_APPOINTMENT_TIME)
.workFloor(Baseline.P_WORK_FLOOR)
.plateNumber(row[0]) .plateNumber(row[0])
.status(row[1]) .status(row[1])
.platformId(row[2]) .platformId(row[2])
@@ -394,6 +396,8 @@ public final class BiSnapshotWeeklyRandomDataBuilder {
static final String[] W_CUST_NAMES = {"华东冷链", "华南汽配", "西南快消", "华北家电", "跨境达"}; static final String[] W_CUST_NAMES = {"华东冷链", "华南汽配", "西南快消", "华北家电", "跨境达"};
static final int[] W_CUST_AMT = {198, 172, 205, 189, 221}; static final int[] W_CUST_AMT = {198, 172, 205, 189, 221};
static final String P_APPOINTMENT_TIME = "2026-08-03 09:30:00";
static final String P_WORK_FLOOR = "一楼";
static final String[][] P_PLATES = { static final String[][] P_PLATES = {
{"粤A12345", "待入场", "#12", "88"}, {"粤A12345", "待入场", "#12", "88"},
{"闽D99887", "作业中", "#07", "142"}, {"闽D99887", "作业中", "#07", "142"},
@@ -14,6 +14,12 @@ import lombok.NoArgsConstructor;
@ApiModel("月台监测-作业车辆") @ApiModel("月台监测-作业车辆")
public class PlatformVehicleItemVO { public class PlatformVehicleItemVO {
@ApiModelProperty("预约申请时间")
private String appointmentTime;
@ApiModelProperty("作业楼层")
private String workFloor;
@ApiModelProperty("车牌号码") @ApiModelProperty("车牌号码")
private String plateNumber; private String plateNumber;
+4 -4
View File
@@ -16,12 +16,12 @@ spring:
# 线上测试环境配置 容器名+端口号 # 线上测试环境配置 容器名+端口号
# server-addr: 10.33.0.129:6010 # server-addr: 10.33.0.129:6010
# server-addr: 10.102.192.5:6848 # server-addr: 10.102.192.5:6848
# username: nacos
# password: manhuoda@2023
#线上正式环境
server-addr: 10.102.192.31:6848
username: nacos username: nacos
password: manhuoda@2023 password: manhuoda@2023
#线上正式环境
server-addr: 10.102.192.31:6848
# username: nacos
# password: manhuoda@2023
config: config:
# server-addr: 127.0.0.1:8848 # server-addr: 127.0.0.1:8848
# 线上测试环境配置 容器名+端口号 # 线上测试环境配置 容器名+端口号
+8 -8
View File
@@ -13,24 +13,24 @@ spring:
cloud: cloud:
nacos: nacos:
discovery: discovery:
# server-addr: 127.0.0.1:8848 server-addr: 127.0.0.1:8848
# 线上测试环境配置 容器名+端口号 # 线上测试环境配置 容器名+端口号
# server-addr: 10.102.192.31:6848 # server-addr: 10.102.192.31:6848
server-addr: 10.33.0.129:6010 # server-addr: 10.33.0.129:6010
#线上正式环境 #线上正式环境
# server-addr: 127.0.0.1:8848 # server-addr: 127.0.0.1:8848
# server-addr: 10.102.192.31:6848 # server-addr: 10.102.192.31:6848
username: nacos # username: nacos
password: manhuoda@2023 # password: manhuoda@2023
config: config:
# server-addr: 127.0.0.1:8848 server-addr: 127.0.0.1:8848
# 线上测试环境配置 容器名+端口号 # 线上测试环境配置 容器名+端口号
server-addr: 10.33.0.129:6010 # server-addr: 10.33.0.129:6010
#线上正式环境 #线上正式环境
# server-addr: 127.0.0.1:8848 # server-addr: 127.0.0.1:8848
# server-addr: 10.102.192.31:6848 # server-addr: 10.102.192.31:6848
username: nacos # username: nacos
password: manhuoda@2023 # password: manhuoda@2023
group: DEFAULT_GROUP # 默认分组就是DEFAULT_GROUP,如果使用默认分组可以不配置 group: DEFAULT_GROUP # 默认分组就是DEFAULT_GROUP,如果使用默认分组可以不配置
file-extension: yml #默认properties file-extension: yml #默认properties
# 共享配置 # 共享配置
@@ -270,7 +270,7 @@ public class LeaseApplicationService {
* 货主租赁明细 * 货主租赁明细
* 定时任务:每天凌晨1点执行,计算前一天的货主租赁明细 * 定时任务:每天凌晨1点执行,计算前一天的货主租赁明细
*/ */
@Scheduled(cron = "0 0 1 * * ?") // @Scheduled(cron = "0 0 1 * * ?")
public void shipperLeaseDetails() { public void shipperLeaseDetails() {
log.info("开始执行货主租赁明细定时任务"); log.info("开始执行货主租赁明细定时任务");
// 计算前一天的日期,将时间设置为当天的0点0分0秒,只保留日期部分 // 计算前一天的日期,将时间设置为当天的0点0分0秒,只保留日期部分
@@ -537,7 +537,7 @@ public class LeaseApplicationService {
/** /**
* 定时任务散租推送到bms * 定时任务散租推送到bms
*/ */
@Scheduled(cron = "0 0 0 * * ?") // @Scheduled(cron = "0 0 0 * * ?")
public void ScatteredRentalSynchronization() { public void ScatteredRentalSynchronization() {
LeaseDO leaseDO = new LeaseDO(); LeaseDO leaseDO = new LeaseDO();
leaseDO.setTime(new Date()); leaseDO.setTime(new Date());
@@ -98,4 +98,10 @@ public class ContractManageDetail extends BaseVOEntity{
@ApiModelProperty("单据类型") @ApiModelProperty("单据类型")
private String documentType; private String documentType;
@ApiModelProperty("费用类别编码")
private String serviceItemsCode;
@ApiModelProperty("费用类别名称")
private String serviceItemsName;
} }
@@ -97,4 +97,10 @@ public class ContractManageDetailPO extends BaseVOEntity{
@ApiModelProperty("单据类型") @ApiModelProperty("单据类型")
private String documentType; private String documentType;
@ApiModelProperty("费用类别编码")
private String serviceItemsCode;
@ApiModelProperty("费用类别名称")
private String serviceItemsName;
} }
@@ -102,4 +102,10 @@ public class ContractManageDetailDO extends BaseVOEntity{
@ApiModelProperty("单据类型") @ApiModelProperty("单据类型")
private String documentType; private String documentType;
@ApiModelProperty("费用类别编码")
private String serviceItemsCode;
@ApiModelProperty("费用类别名称")
private String serviceItemsName;
} }
@@ -91,31 +91,15 @@ public class StorageSectionDomainService {
public Boolean update(StorageSectionDO storageSectionDO) { public Boolean update(StorageSectionDO storageSectionDO) {
LoginUser loginUser = SecurityUtils.getLoginUser(); LoginUser loginUser = SecurityUtils.getLoginUser();
Long topOrganizationId = loginUser.getUserPo().getTopOrganizationId(); Long topOrganizationId = loginUser.getUserPo().getTopOrganizationId();
AssociationWarehouseCacheDO associationWarehouseCacheDO = SystemServiceCacheUtil.getAssociationWarehouseCache(loginUser.getUserid()); if (topOrganizationId == null || topOrganizationId == 0) {
if (topOrganizationId == null || topOrganizationId == 0 || associationWarehouseCacheDO == null) { throw new ServiceException("获取当前登陆人组织失败!");
throw new ServiceException("获取当前登陆人组织与登陆仓库失败!");
} }
checkStorageSectionDuplicate(topOrganizationId, associationWarehouseCacheDO.getWarehouseId(), // 直接用记录自身的 warehouseId 做唯一校验,不再依赖缓存仓库
checkStorageSectionDuplicate(topOrganizationId, storageSectionDO.getWarehouseId(),
storageSectionDO.getStorageCode(), storageSectionDO.getStorageName(), storageSectionDO.getStorageCode(), storageSectionDO.getStorageName(),
storageSectionDO.getStorageSectionId()); storageSectionDO.getStorageSectionId());
//设置仓库 //设置仓库
setWarehouseInfo(storageSectionDO); setWarehouseInfo(storageSectionDO);
String storageCode = storageSectionDO.getStorageCode();
String storageName = storageSectionDO.getStorageName();
Long warehouseId = storageSectionDO.getWarehouseId();
List<StorageSection> codelist = storageSectionService.list(new QueryWrapper<StorageSection>().lambda()
.eq(StorageSection::getStorageCode, storageCode)
.eq(StorageSection::getWarehouseId, warehouseId)
.ne(StorageSection::getStorageSectionId, storageSectionDO.getStorageSectionId())
.eq(StorageSection::getDelFlag, 1));
List<StorageSection> namelist = storageSectionService.list(new QueryWrapper<StorageSection>().lambda()
.eq(StorageSection::getStorageName, storageName)
.eq(StorageSection::getWarehouseId, warehouseId)
.ne(StorageSection::getStorageSectionId, storageSectionDO.getStorageSectionId())
.eq(StorageSection::getDelFlag, 1));
if ((codelist != null && codelist.size() > 0) || (namelist != null && namelist.size() > 0)) {
throw new ServiceException("库区编码或名称已存在");
}
return storageSectionService.update(storageSectionDO); return storageSectionService.update(storageSectionDO);
} }
@@ -102,4 +102,10 @@ public class ContractManageDetailDTO extends BaseVOEntity{
@ApiModelProperty("单据类型") @ApiModelProperty("单据类型")
private String documentType; private String documentType;
@ApiModelProperty("费用类别编码")
private String serviceItemsCode;
@ApiModelProperty("费用类别名称")
private String serviceItemsName;
} }
@@ -107,7 +107,10 @@
<select id="selectCostSubject" parameterType="com.mhd.basic.domain.expenseAccount.repository.todo.ExpenseAccountDO" <select id="selectCostSubject" parameterType="com.mhd.basic.domain.expenseAccount.repository.todo.ExpenseAccountDO"
resultType="com.mhd.basic.domain.expenseAccount.repository.po.ExpenseAccountPO"> resultType="com.mhd.basic.domain.expenseAccount.repository.po.ExpenseAccountPO">
select select
a.* a.* ,
b.tax_rate,
b.service_items_name,
b.service_items_code
from expense_account a left join service_items_manage b ON a.service_items_manage_id = b.service_items_manage_id from expense_account a left join service_items_manage b ON a.service_items_manage_id = b.service_items_manage_id
where where
a.del_flag = 1 a.del_flag = 1
@@ -118,13 +121,17 @@
<select id="selectAllCostSubject" <select id="selectAllCostSubject"
resultType="com.mhd.basic.domain.expenseAccount.repository.po.ExpenseAccountPO"> resultType="com.mhd.basic.domain.expenseAccount.repository.po.ExpenseAccountPO">
select select
* a.* ,
from expense_account b.tax_rate,
b.service_items_name,
b.service_items_code
from expense_account a
left join service_items_manage b ON a.service_items_manage_id = b.service_items_manage_id
where where
del_flag = 1 a.del_flag = 1
and status = 1 and a.status = 1
and first_subject_flag = 2 and a.first_subject_flag = 2
and upper_subject_code = #{subjectCode} and a.upper_subject_code = #{subjectCode}
</select> </select>
<select id="getInfoByCode" resultType="com.mhd.basic.domain.expenseAccount.repository.po.ExpenseAccountPO" parameterType="com.mhd.basic.domain.expenseAccount.repository.todo.ExpenseAccountDO"> <select id="getInfoByCode" resultType="com.mhd.basic.domain.expenseAccount.repository.po.ExpenseAccountPO" parameterType="com.mhd.basic.domain.expenseAccount.repository.todo.ExpenseAccountDO">
@@ -141,6 +148,7 @@
AND a.top_organization_id = #{expenseAccountDO.topOrganizationId} AND a.top_organization_id = #{expenseAccountDO.topOrganizationId}
AND a.subject_code = #{expenseAccountDO.subjectCode} AND a.subject_code = #{expenseAccountDO.subjectCode}
AND a.status = 1 AND a.status = 1
LIMIT 1
</select> </select>
@@ -1,12 +1,22 @@
package com.mhd.user.application.service; package com.mhd.user.application.service;
import cn.hutool.core.util.ObjectUtil;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.mhd.common.security.utils.SecurityUtils;
import com.mhd.user.domain.userAggregate.entity.AgreementDetails; import com.mhd.user.domain.userAggregate.entity.AgreementDetails;
import com.mhd.user.domain.userAggregate.entity.UserShipperEntity;
import com.mhd.user.domain.userAggregate.repository.mapper.AgreementDetailsMapper; import com.mhd.user.domain.userAggregate.repository.mapper.AgreementDetailsMapper;
import com.mhd.user.domain.userAggregate.repository.mapper.UserShipperMapper;
import com.mhd.user.domain.userAggregate.repository.po.AgreementDetailsPo;
import com.mhd.system.api.model.LoginUser;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import javax.annotation.Resource; import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List; import java.util.List;
/** /**
@@ -19,18 +29,87 @@ public class AgreementDetailsApplicationService {
@Resource @Resource
private AgreementDetailsMapper agreementDetailsMapper; private AgreementDetailsMapper agreementDetailsMapper;
@Resource
private UserShipperMapper userShipperMapper;
/** /**
* 根据货主ID查询所有协议明细 * 根据货主ID查询当前登录用户组织下的协议明细
* 从user_shipper表的orgCode字段解析JSON,匹配当前登录用户组织code,
* 返回该组织下的agreedaydatas列表
* *
* @param shipperId 货主ID * @param shipperId 货主ID
* @return 协议明细列表 * @return 协议明细列表
*/ */
public List<AgreementDetails> listByShipperId(Long shipperId) { public List<AgreementDetailsPo> listByShipperId(Long shipperId) {
return agreementDetailsMapper.selectList( // 1. 获取当前登录用户组织ID
new LambdaQueryWrapper<AgreementDetails>() LoginUser loginUser = SecurityUtils.getLoginUser();
.eq(AgreementDetails::getShipperId, shipperId) if (ObjectUtil.isNull(loginUser) || ObjectUtil.isNull(loginUser.getUserPo())) {
.orderByDesc(AgreementDetails::getCreateTime) log.warn("未获取到登录用户信息");
); return Collections.emptyList();
}
Long organizationId = loginUser.getUserPo().getOrganizationId();
if (ObjectUtil.isNull(organizationId)) {
log.warn("当前登录用户无组织信息");
return Collections.emptyList();
}
// 2. 根据shipperId查询货主信息,获取orgCode字段
UserShipperEntity shipperEntity = userShipperMapper.selectById(shipperId);
if (ObjectUtil.isNull(shipperEntity)) {
log.warn("未找到货主信息,shipperId={}", shipperId);
return Collections.emptyList();
}
String orgCodeJson = shipperEntity.getOrgCode();
if (ObjectUtil.isNull(orgCodeJson) || orgCodeJson.isEmpty()) {
log.warn("货主orgCode为空,shipperId={}", shipperId);
return Collections.emptyList();
}
// 3. 解析orgCode JSON数组,匹配当前登录用户组织code
JSONArray orgCodeArray = JSONArray.parseArray(orgCodeJson);
if (orgCodeArray == null || orgCodeArray.isEmpty()) {
return Collections.emptyList();
}
JSONObject matchedOrg = null;
for (int i = 0; i < orgCodeArray.size(); i++) {
JSONObject orgItem = orgCodeArray.getJSONObject(i);
Long code = orgItem.getLong("code");
if (organizationId.equals(code)) {
matchedOrg = orgItem;
break;
}
}
if (matchedOrg == null) {
log.info("未匹配到当前组织的协议信息,shipperId={}organizationId={}", shipperId, organizationId);
return Collections.emptyList();
}
// 4. 获取匹配组织的agreedaydatas
JSONArray agreedaydatas = matchedOrg.getJSONArray("agreedaydatas");
if (agreedaydatas == null || agreedaydatas.isEmpty()) {
log.info("当前组织下无协议天数数据,shipperId={}organizationId={}", shipperId, organizationId);
return Collections.emptyList();
}
// 5. 转换为AgreementDetailsPo列表
List<AgreementDetailsPo> result = new ArrayList<>();
for (int i = 0; i < agreedaydatas.size(); i++) {
JSONObject item = agreedaydatas.getJSONObject(i);
AgreementDetailsPo po = new AgreementDetailsPo();
po.setCode(item.getString("code"));
po.setOrgcode(item.getString("orgcode"));
po.setPtypename(item.getString("ptypename"));
po.setPtype(item.getString("ptype"));
po.setPcode(item.getString("pcode"));
po.setPname(item.getString("pname"));
po.setPday(item.getString("pday"));
result.add(po);
}
log.info("查询协议明细成功,shipperId={}organizationId={},共{}条", shipperId, organizationId, result.size());
return result;
} }
/** /**
@@ -23,7 +23,10 @@ import com.mhd.common.core.enums.MessageTypeEnum;
import com.mhd.common.core.enums.WebsocketTypeEnum; import com.mhd.common.core.enums.WebsocketTypeEnum;
import com.mhd.common.core.feign.ThirdPartyServiceFeign; import com.mhd.common.core.feign.ThirdPartyServiceFeign;
import com.mhd.common.core.service.jPush.AsyncJPushApplicationService; import com.mhd.common.core.service.jPush.AsyncJPushApplicationService;
import com.mhd.common.core.utils.AESUtil;
import com.mhd.common.core.utils.OConvertUtils;
import com.mhd.common.core.utils.StringUtils; import com.mhd.common.core.utils.StringUtils;
import com.mhd.common.security.utils.password.PasswordUtil;
import com.mhd.system.api.FinanceServiceFeign; import com.mhd.system.api.FinanceServiceFeign;
import com.mhd.system.api.WlhyServiceFeign; import com.mhd.system.api.WlhyServiceFeign;
import com.mhd.system.api.domain.UserShipperEntityFeign; import com.mhd.system.api.domain.UserShipperEntityFeign;
@@ -359,6 +362,254 @@ public class UserShipperApplicationService {
return result; return result;
} }
/**
* 从 Excel 导入委托方
* 模版列:登录账号、公司名称、联系人、联系电话、地址、详细地址、备注、结算币种、NC客户编码
*/
public com.mhd.common.core.web.domain.AjaxResult importShipperFromExcel(org.springframework.web.multipart.MultipartFile file) {
if (file == null || file.isEmpty()) {
return com.mhd.common.core.web.domain.AjaxResult.error("文件不能为空");
}
try {
org.apache.poi.ss.usermodel.Workbook workbook = org.apache.poi.ss.usermodel.WorkbookFactory.create(file.getInputStream());
org.apache.poi.ss.usermodel.Sheet sheet = workbook.getSheetAt(0);
int total = 0, success = 0, failed = 0;
java.util.List<String> errors = new java.util.ArrayList<>();
LoginUser loginUser = SecurityUtils.getLoginUser();
if (loginUser == null || loginUser.getUserPo() == null) {
return com.mhd.common.core.web.domain.AjaxResult.error("登录信息失效");
}
Long currentOrgId = loginUser.getUserPo().getOrganizationId();
String currentOrgName = loginUser.getUserPo().getOrganizationName();
for (int i = 1; i <= sheet.getLastRowNum(); i++) {
org.apache.poi.ss.usermodel.Row row = sheet.getRow(i);
if (row == null) continue;
String userAccount = getCellStr(row.getCell(0));
String companyName = getCellStr(row.getCell(1));
if (org.springframework.util.StringUtils.isEmpty(companyName)) continue;
total++;
try {
String contactName = getCellStr(row.getCell(2));
String contactPhone = getCellStr(row.getCell(3));
String address = getCellStr(row.getCell(4));
String detailedAddress = getCellStr(row.getCell(5));
String remark = getCellStr(row.getCell(6));
String settlementCurrency = getCellStr(row.getCell(7));
String ncCustomerCode = getCellStr(row.getCell(8));
// 先按公司名称查是否已存在委托方
UserShipperEntity existingShipper = findFirstByShipperEnterpriseNameAcrossOrgs(companyName);
if (existingShipper != null && existingShipper.getShipperId() != null) {
// 已存在:按模板更新指定字段
updateShipperFromExcel(existingShipper, userAccount, companyName,
contactName, contactPhone, address, detailedAddress,
remark, settlementCurrency, ncCustomerCode, loginUser, currentOrgId);
success++;
} else {
UserShipperDO shipperDO = new UserShipperDO();
shipperDO.setShipperType(2);
shipperDO.setDataSource(2);
shipperDO.setUserAccount(userAccount);
shipperDO.setShipperEnterpriseName(companyName);
// NC客户编码使用模板中的独立字段,不再复用登录账号
shipperDO.setCustomerNcCode(ncCustomerCode);
// 联系人 -> user表 user_name + user_shipper表 user_name_shipper
shipperDO.setUserName(contactName);
shipperDO.setUserNameShipper(contactName);
// 联系电话 -> user表 user_phone
shipperDO.setUserPhone(contactPhone);
// 地址 -> user表 user_area_name,详细地址 -> user表 user_area_address
shipperDO.setUserAreaName(address);
shipperDO.setUserAreaAddress(detailedAddress);
shipperDO.setRemark(remark);
shipperDO.setSettlementCurrency(settlementCurrency);
// 新导入账号默认密码 Aa123456(按前端加密约定先 AES 加密)
shipperDO.setUserPassword(AESUtil.encrypt("Aa123456"));
// 初始化 orgCode:记录当前组织信息和NC客户编码
com.alibaba.fastjson.JSONArray orgCodeArray = new com.alibaba.fastjson.JSONArray();
com.alibaba.fastjson.JSONObject orgItem = new com.alibaba.fastjson.JSONObject();
orgItem.put("name", currentOrgName);
orgItem.put("code", currentOrgId);
orgItem.put("ncCustomer", ncCustomerCode);
orgItem.put("names", currentOrgId);
orgCodeArray.add(orgItem);
shipperDO.setOrgCode(orgCodeArray.toJSONString());
Map<String, Object> addResult = addShipper(shipperDO);
Object newUserIdObj = addResult.get("userId");
if (newUserIdObj instanceof Long) {
assignCompanyRoleIfMissing((Long) newUserIdObj, currentOrgId);
}
success++;
}
} catch (Exception e) {
failed++;
errors.add("" + (i + 1) + "行[" + companyName + "]导入失败:" + e.getMessage());
log.error("导入委托方第{}行失败", i + 1, e);
}
}
workbook.close();
java.util.Map<String, Object> result = new java.util.HashMap<>();
result.put("total", total);
result.put("success", success);
result.put("failed", failed);
result.put("errorMessages", errors);
return com.mhd.common.core.web.domain.AjaxResult.success("导入完成", result);
} catch (Exception e) {
log.error("解析Excel失败", e);
return com.mhd.common.core.web.domain.AjaxResult.error("解析Excel失败:" + e.getMessage());
}
}
/**
* 导入时若账号没有任何角色,则补分配企业货主角色
*/
private void assignCompanyRoleIfMissing(Long userId, Long organizationId) {
if (userId == null || organizationId == null) {
return;
}
List<UserRoleMenuPO> existingRoles = userRoleDomainService.selectRolesByUserId(userId);
if (CollUtil.isNotEmpty(existingRoles)) {
return;
}
// 按 role_code + organization_id 精确匹配角色(selectByOrganizationIdAndRoleCode 的 common_where 不含 roleCode 过滤,不适用)
RolePO rolePO = roleDomainService.selectByRoleCodeAndOrganizationId(RoleEnum.COMPANY.getCode(), organizationId);
if (rolePO == null) {
log.warn("组织{}下未找到{}角色,无法为导入用户{}分配角色", organizationId, RoleEnum.COMPANY.getCode(), userId);
return;
}
// 1. 写入 user_role 表
UserRoleDo userRoleDo = new UserRoleDo();
userRoleDo.setUserId(userId);
userRoleDo.setRoleId(rolePO.getRoleId());
userRoleDomainService.addUserRole(userRoleDo);
// 2. 同步更新 user 表的 role_code / role_name
UserDO userDO = new UserDO();
userDO.setUserId(userId);
userDO.setRoleCode(RoleEnum.COMPANY.getCode());
userDO.setRoleName(RoleEnum.COMPANY.getName());
userDomainService.updateUser(userDO);
}
/**
* 按Excel模板更新已存在的委托方(只更新模板中的字段)
*/
private void updateShipperFromExcel(UserShipperEntity existingShipper, String userAccount,
String companyName, String contactName, String contactPhone,
String address, String detailedAddress, String remark,
String settlementCurrency, String ncCustomerCode,
LoginUser loginUser, Long currentOrgId) {
Long userId = existingShipper.getUserId();
// 从 user 主表读取当前登录账号(user_shipper 表无 user_account 字段)
UserPo existingUser = null;
String existingUserAccount = null;
if (userId != null) {
existingUser = userDomainService.selectByUserId(userId);
if (existingUser != null) {
existingUserAccount = existingUser.getUserAccount();
}
}
if (StringUtils.isBlank(existingUserAccount) && StringUtils.isBlank(userAccount)) {
throw new ServiceException("登录账号不能为空");
}
// 登录账号变更时校验唯一性
if (StringUtils.isNotBlank(userAccount) && !userAccount.equals(existingUserAccount)) {
UserDO checkDO = new UserDO();
checkDO.setUserAccount(userAccount);
checkDO.setTopOrganizationId(existingShipper.getTopOrganizationId());
UserPo existedUser = userDomainService.findByTopOrganizationIdAndUserAccount(checkDO);
if (existedUser != null && !existedUser.getUserId().equals(userId)) {
throw new ServiceException("登录账号已存在:" + userAccount);
}
}
Date now = new Date();
Long updateBy = loginUser.getUserPo().getUserId();
String updateByName = loginUser.getUserPo().getUserName();
// 1. 更新 user_shipper 表指定字段
// 注意:user_shipper 表没有 user_account 字段,登录账号在 user 主表维护
UserShipperEntity shipperUpdate = new UserShipperEntity();
shipperUpdate.setShipperId(existingShipper.getShipperId());
shipperUpdate.setShipperEnterpriseName(companyName);
shipperUpdate.setUserNameShipper(contactName);
shipperUpdate.setUserAreaName(address);
shipperUpdate.setUserAreaAddress(detailedAddress);
shipperUpdate.setRemark(remark);
shipperUpdate.setSettlementCurrency(settlementCurrency);
shipperUpdate.setCustomerNcCode(ncCustomerCode);
shipperUpdate.setUpdateBy(updateBy);
shipperUpdate.setUpdateByName(updateByName);
shipperUpdate.setUpdateTime(now);
userShipperMapper.updateById(shipperUpdate);
// 2. 同步更新 user 表指定字段
if (userId != null) {
UserDO userDO = new UserDO();
userDO.setUserId(userId);
if (StringUtils.isNotBlank(userAccount)) {
userDO.setUserAccount(userAccount);
}
userDO.setUserName(contactName);
userDO.setUserPhone(contactPhone);
userDO.setUserAreaName(address);
userDO.setUserAreaAddress(detailedAddress);
userDO.setUpdateBy(updateBy);
userDO.setUpdateByName(updateByName);
userDO.setUpdateTime(now);
// 如果现有账号没有密码,设置默认密码 Aa123456(与 addUserInfoShipper 一致的加密流程)
if (existingUser != null && StringUtils.isBlank(existingUser.getUserPassword())) {
String finalAccount = StringUtils.isNotBlank(userAccount) ? userAccount : existingUser.getUserAccount();
String salt = OConvertUtils.randomGen(8);
String passwordEncode = PasswordUtil.encrypt(finalAccount, "Aa123456", salt);
userDO.setUserPassword(passwordEncode);
userDO.setUserSalt(salt);
}
userDomainService.updateUser(userDO);
// 如果该账号没有任何角色,补分配企业货主角色,避免登录报“账号未授权角色信息”
assignCompanyRoleIfMissing(userId, existingShipper.getOrganizationId());
}
// 3. 更新 orgCode 中当前组织的 ncCustomer
String existingOrgCode = existingShipper.getOrgCode();
com.alibaba.fastjson.JSONArray orgCodeArray = new com.alibaba.fastjson.JSONArray();
boolean hasOrg = false;
if (StringUtils.isNotEmpty(existingOrgCode)) {
try {
orgCodeArray = com.alibaba.fastjson.JSONArray.parseArray(existingOrgCode);
for (int i = 0; i < orgCodeArray.size(); i++) {
com.alibaba.fastjson.JSONObject orgItem = orgCodeArray.getJSONObject(i);
if (currentOrgId != null && currentOrgId.equals(orgItem.getLong("code"))) {
orgItem.put("ncCustomer", ncCustomerCode);
hasOrg = true;
}
}
} catch (Exception e) {
log.error("解析orgCode失败,shipperId={}", existingShipper.getShipperId(), e);
}
}
if (!hasOrg) {
com.alibaba.fastjson.JSONObject newOrgItem = new com.alibaba.fastjson.JSONObject();
newOrgItem.put("name", loginUser.getUserPo().getOrganizationName());
newOrgItem.put("code", currentOrgId);
newOrgItem.put("ncCustomer", ncCustomerCode);
newOrgItem.put("names", currentOrgId);
orgCodeArray.add(newOrgItem);
}
UserShipperEntity orgCodeUpdate = new UserShipperEntity();
orgCodeUpdate.setShipperId(existingShipper.getShipperId());
orgCodeUpdate.setOrgCode(orgCodeArray.toJSONString());
orgCodeUpdate.setUpdateBy(updateBy);
orgCodeUpdate.setUpdateByName(updateByName);
orgCodeUpdate.setUpdateTime(now);
userShipperMapper.updateById(orgCodeUpdate);
}
private String getCellStr(org.apache.poi.ss.usermodel.Cell cell) {
if (cell == null) return null;
cell.setCellType(org.apache.poi.ss.usermodel.CellType.STRING);
String v = cell.getStringCellValue();
return v == null ? null : v.trim();
}
/** /**
* 个人货主认证 * 个人货主认证
* *
@@ -0,0 +1,32 @@
package com.mhd.user.domain.userAggregate.repository.po;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
/**
* 协议天数PO
*/
@Data
public class AgreementDetailsPo {
@ApiModelProperty("客户编码")
private String code;
@ApiModelProperty("协议组织编码")
private String orgcode;
@ApiModelProperty("协议类型名称")
private String ptypename;
@ApiModelProperty("协议类型:1-付款协议天数,2-收款协议天数")
private String ptype;
@ApiModelProperty("财务系统协议编码")
private String pcode;
@ApiModelProperty("协议天数名称")
private String pname;
@ApiModelProperty("协议天数")
private String pday;
}
@@ -244,6 +244,12 @@ public class UserShipperDO extends UserDO {
@ApiModelProperty("货主/供应商/客户名称") @ApiModelProperty("货主/供应商/客户名称")
private String userNameShipper; private String userNameShipper;
@ApiModelProperty("用户名称")
private String userName;
@ApiModelProperty("用户电话")
private String userPhone;
@ApiModelProperty("联系人") @ApiModelProperty("联系人")
private String emergencyContactName; private String emergencyContactName;
@@ -356,4 +356,16 @@ public class UserShipperAPI extends BaseController {
? loginUser.getUserPo().getOrganizationId() : null; ? loginUser.getUserPo().getOrganizationId() : null;
return wechatMiniAppService.wxGetPhoneNumber(dto, organizationId); return wechatMiniAppService.wxGetPhoneNumber(dto, organizationId);
} }
@Log(title = "托运人管理-导入", description = "从Excel导入委托方", businessType = BusinessType.IMPORT)
@ApiOperation("导入委托方(Excel批量)")
@PostMapping("/import")
public AjaxResult importShipper(@RequestParam("file") org.springframework.web.multipart.MultipartFile file) {
try {
return userShipperApplicationService.importShipperFromExcel(file);
} catch (Exception e) {
log.error("导入委托方失败", e);
return AjaxResult.error("导入失败:" + e.getMessage());
}
}
} }
@@ -20,15 +20,15 @@ spring:
discovery: discovery:
# server-addr: 127.0.0.1:8848 # server-addr: 127.0.0.1:8848
# 线上测试环境配置 容器名+端口号 # 线上测试环境配置 容器名+端口号
server-addr: 10.33.0.129:6010 # server-addr: 10.33.0.129:6010
# server-addr: 10.102.192.30:6848 server-addr: 10.102.192.31:6848
username: nacos username: nacos
password: manhuoda@2023 password: manhuoda@2023
config: config:
# server-addr: 127.0.0.1:8848 # server-addr: 127.0.0.1:8848
# 线上测试环境配置 容器名+端口号 # 线上测试环境配置 容器名+端口号
server-addr: 10.33.0.129:6010 # server-addr: 10.33.0.129:6010
# server-addr: 10.102.192.30:6848 server-addr: 10.102.192.31:6848
username: nacos username: nacos
password: manhuoda@2023 password: manhuoda@2023
group: DEFAULT_GROUP # 默认分组就是DEFAULT_GROUP,如果使用默认分组可以不配置 group: DEFAULT_GROUP # 默认分组就是DEFAULT_GROUP,如果使用默认分组可以不配置
@@ -75,7 +75,9 @@
AND b.del_flag = 1 AND b.del_flag = 1
</sql> </sql>
<sql id="selectShipperVo1"> <sql id="selectShipperVo1">
SELECT b.shipper_id, SELECT b.area,
b.detail_address,
b.shipper_id,
a.user_id, a.user_id,
b.parent_shipper_id, b.parent_shipper_id,
b.shipper_type, b.shipper_type,
@@ -7,6 +7,7 @@ import com.mhd.bms.application.server.receiptManage.ReceiptManageApplicationServ
import com.mhd.bms.domain.billManage.entity.BillDetail; import com.mhd.bms.domain.billManage.entity.BillDetail;
import com.mhd.bms.domain.billManage.entity.BillManage; import com.mhd.bms.domain.billManage.entity.BillManage;
import com.mhd.bms.domain.billManage.repository.facade.IBillDetailService; import com.mhd.bms.domain.billManage.repository.facade.IBillDetailService;
import com.mhd.bms.domain.billManage.repository.facade.IBillManageService;
import com.mhd.bms.domain.billManage.repository.mapper.BillDetailMapper; import com.mhd.bms.domain.billManage.repository.mapper.BillDetailMapper;
import com.mhd.bms.domain.billManage.repository.po.BillDetailPO; import com.mhd.bms.domain.billManage.repository.po.BillDetailPO;
import com.mhd.bms.domain.billManage.repository.po.BillManagePO; import com.mhd.bms.domain.billManage.repository.po.BillManagePO;
@@ -18,6 +19,7 @@ import com.mhd.bms.domain.billOperationLog.repository.todo.BillOperationLogDO;
import com.mhd.bms.domain.billOperationLog.service.BillOperationLogDomainService; import com.mhd.bms.domain.billOperationLog.service.BillOperationLogDomainService;
import com.mhd.bms.domain.billingStatement.entity.BillingStatement; import com.mhd.bms.domain.billingStatement.entity.BillingStatement;
import com.mhd.bms.domain.billingStatement.repository.po.BillingStatementPO; import com.mhd.bms.domain.billingStatement.repository.po.BillingStatementPO;
import com.mhd.bms.domain.billingStatement.repository.todo.BillingStatementDO;
import com.mhd.bms.domain.billingStatement.service.BillingStatementDomainService; import com.mhd.bms.domain.billingStatement.service.BillingStatementDomainService;
import com.mhd.bms.domain.ncLog.entity.NcLog; import com.mhd.bms.domain.ncLog.entity.NcLog;
import com.mhd.bms.domain.ncLog.repository.mapper.NcLogMapper; import com.mhd.bms.domain.ncLog.repository.mapper.NcLogMapper;
@@ -77,6 +79,8 @@ public class BillManageApplicationService {
private BillDetailMapper billDetailMapper; private BillDetailMapper billDetailMapper;
@Autowired @Autowired
private NcLogMapper ncLogMapper; private NcLogMapper ncLogMapper;
@Autowired
private IBillManageService billManageService;
/** /**
@@ -132,8 +136,12 @@ public class BillManageApplicationService {
List<BillManagePO> billManagePOS = billManageDomainService.queryList(billManageDO); List<BillManagePO> billManagePOS = billManageDomainService.queryList(billManageDO);
for (BillManagePO billManagePO : billManagePOS) { for (BillManagePO billManagePO : billManagePOS) {
String billNumber = billManagePO.getBillNumber(); // 获取账单编号 String billNumber = billManagePO.getBillNumber(); // 获取账单编号
// 原有 - 前端列表用,不变
List<BillDetail> billDetails = billDetailMapper.selectList(new LambdaQueryWrapper<BillDetail>().eq(BillDetail::getBillNumber, billNumber)); List<BillDetail> billDetails = billDetailMapper.selectList(new LambdaQueryWrapper<BillDetail>().eq(BillDetail::getBillNumber, billNumber));
billManagePO.setBillDetailList(billDetails); billManagePO.setBillDetailList(billDetails);
// 新增 - 导出用,LEFT JOIN billing_statement 拿到费用科目
List<BillDetailPO> billDetailPOs = billDetailMapper.getDetailsByBillManageId(billManagePO.getBillManageId());
billManagePO.setBillDetailPOList(billDetailPOs);
} }
return billManagePOS; return billManagePOS;
} }
@@ -333,7 +341,10 @@ public class BillManageApplicationService {
BigDecimal billingDiscountAmount = billDetailDTOList.stream().map(BillDetailDTO::getBillingDiscountAmount).reduce(BigDecimal.ZERO, BigDecimal::add); BigDecimal billingDiscountAmount = billDetailDTOList.stream().map(BillDetailDTO::getBillingDiscountAmount).reduce(BigDecimal.ZERO, BigDecimal::add);
//比较传来的账单总额、账单金额、账单优惠金额与计算的是否一致,不一致则报错 //比较传来的账单总额、账单金额、账单优惠金额与计算的是否一致,不一致则报错
if(billingTotalAmount.compareTo(billManageDTO.getBillTotalAmount())!=0 || billingAmount.compareTo(billManageDTO.getBillAmount())!=0 || billingDiscountAmount.compareTo(billManageDTO.getBillDiscountAmount())!=0){ if(billingTotalAmount.compareTo(billManageDTO.getBillTotalAmount())!=0 || billingAmount.compareTo(billManageDTO.getBillAmount())!=0 || billingDiscountAmount.compareTo(billManageDTO.getBillDiscountAmount())!=0){
throw new ServiceException("账单金额不一致,调整失败,请重试"); // 金额不一致时,用明细累加值覆盖前端传值,不再抛异常
billManageDTO.setBillTotalAmount(billingTotalAmount);
billManageDTO.setBillAmount(billingAmount);
billManageDTO.setBillDiscountAmount(billingDiscountAmount);
} }
//将集合中没有计费流水id的过滤到另一个集合,将添加费用的集合保存到计费流水并返回计费流水id //将集合中没有计费流水id的过滤到另一个集合,将添加费用的集合保存到计费流水并返回计费流水id
List<BillDetailDTO> billDetailDTOListNoBillingStatementId = billDetailDTOList.stream().filter(billDetailDTO -> billDetailDTO.getBillingStatementId()==null).collect(Collectors.toList()); List<BillDetailDTO> billDetailDTOListNoBillingStatementId = billDetailDTOList.stream().filter(billDetailDTO -> billDetailDTO.getBillingStatementId()==null).collect(Collectors.toList());
@@ -356,6 +367,19 @@ public class BillManageApplicationService {
billDetailDTO1.setFeeType(billDetailDTO1.getServiceItemsName()); billDetailDTO1.setFeeType(billDetailDTO1.getServiceItemsName());
}); });
} }
//同步更新已有计费流水(调整账单时可修改已有费用)
List<BillDetailDTO> billDetailDTOListHasBillingStatementId = billDetailDTOList.stream()
.filter(billDetailDTO -> billDetailDTO.getBillingStatementId() != null)
.collect(Collectors.toList());
for (BillDetailDTO billDetailDTO : billDetailDTOListHasBillingStatementId) {
BillingStatementDO billingStatementDO = new BillingStatementDO();
BeanUtils.copyProperties(billDetailDTO, billingStatementDO);
billingStatementDO.setBillingStatementId(billDetailDTO.getBillingStatementId());
billingStatementDO.setBillManageId(billManagePO.getBillManageId());
billingStatementDO.setBillingState(3);
billingStatementDO.setAccountExpenseType(billDetailDTO.getBillType());
billingStatementApplicationService.update(billingStatementDO);
}
//保存账单明细 //保存账单明细
Boolean flag = billDetailDomainService.saveBatch(billDetailDTOList); Boolean flag = billDetailDomainService.saveBatch(billDetailDTOList);
//更新账单金额 //更新账单金额
@@ -369,7 +393,10 @@ public class BillManageApplicationService {
billManageDO.setTailCalculationCode(billManageDTO.getTailCalculationCode()); billManageDO.setTailCalculationCode(billManageDTO.getTailCalculationCode());
billManageDO.setAmountAccuracyCode(billManageDTO.getAmountAccuracyCode()); billManageDO.setAmountAccuracyCode(billManageDTO.getAmountAccuracyCode());
billManageDO.setBillDiscount(billManageDTO.getBillDiscount()); billManageDO.setBillDiscount(billManageDTO.getBillDiscount());
billManageDO.setBillRemark(billManageDTO.getBillRemark());
billManageDO.setBillDiscountLimit(billManageDTO.getBillDiscountLimit()); billManageDO.setBillDiscountLimit(billManageDTO.getBillDiscountLimit());
billManageDO.setCycleBeginTime(billManageDTO.getCycleBeginTime());
billManageDO.setCycleEndTime(billManageDTO.getCycleEndTime());
billManageDO.setCreateTime(billManageDTO.getCreateTime()); billManageDO.setCreateTime(billManageDTO.getCreateTime());
billManageDO.setUpdateTime(new Date()); billManageDO.setUpdateTime(new Date());
billManageDO.setUpdateBy(loginUser.getUserid()); billManageDO.setUpdateBy(loginUser.getUserid());
@@ -386,105 +413,183 @@ public class BillManageApplicationService {
} }
/** /**
* 复制账单 * 新增账单
*/ */
@Transactional @Transactional
public Boolean copyBill(BillManageDTO billManageDTO) { public Boolean addBill(BillManageDTO billManageDTO) {
LoginUser loginUser = SecurityUtils.getLoginUser(); LoginUser loginUser = SecurityUtils.getLoginUser();
if (ObjectUtil.isNull(loginUser)) { if (ObjectUtil.isNull(loginUser)) {
throw new DigitalLogisticsException(UserError.TIMEOUT); throw new DigitalLogisticsException(UserError.TIMEOUT);
} }
if (billManageDTO.getBillDetailDTOList() == null || billManageDTO.getBillDetailDTOList().size() == 0) {
throw new ServiceException("账单明细不能为空");
}
List<BillDetailDTO> billDetailDTOList = billManageDTO.getBillDetailDTOList();
//计算集合中所有账单总额、账单金额、账单优惠金额
BigDecimal billingTotalAmount = billDetailDTOList.stream().map(BillDetailDTO::getBillingTotalAmount).reduce(BigDecimal.ZERO, BigDecimal::add);
BigDecimal billingAmount = billDetailDTOList.stream().map(BillDetailDTO::getBillingAmount).reduce(BigDecimal.ZERO, BigDecimal::add);
BigDecimal billingDiscountAmount = billDetailDTOList.stream().map(BillDetailDTO::getBillingDiscountAmount).reduce(BigDecimal.ZERO, BigDecimal::add);
//生成账单编号
String billNumber = OrderSequence.getOrderCode("ZD");
//创建账单主记录
BillManageDO billManageDO = new BillManageDO();
BeanUtils.copyProperties(billManageDTO, billManageDO);
billManageDO.setBillNumber(billNumber);
billManageDO.setTopOrganizationId(loginUser.getUserPo().getTopOrganizationId());
billManageDO.setOrganizationId(loginUser.getUserPo().getOrganizationId());
billManageDO.setOrganizationName(loginUser.getUserPo().getOrganizationName());
billManageDO.setBillAmount(billingAmount);
billManageDO.setBillAmountUnsettled(billingAmount);
billManageDO.setBillAmountSettlement(BigDecimal.ZERO);
billManageDO.setBillDiscountAmount(billingDiscountAmount);
billManageDO.setBillTotalAmount(billingTotalAmount);
billManageDO.setBillState(1);
billManageDO.setBillStep(1);
billManageDO.setReconciliationStatus(1);
billManageDO.setCreateTime(new Date());
billManageDO.setCreateBy(loginUser.getUserid());
billManageDO.setSalesmanId(String.valueOf(loginUser.getUserid()));
billManageDO.setCreateByName(loginUser.getUserPo().getUserName());
billManageDO.setUpdateTime(new Date());
billManageDO.setUpdateBy(loginUser.getUserid());
billManageDO.setUpdateByName(loginUser.getUserPo().getUserName());
billManageDomainService.handlData(billManageDO);
Boolean flag = billManageDomainService.insert(billManageDO);
if (!flag) {
throw new ServiceException("新增账单失败");
}
// insert后按账单编号重新查一次拿自增ID
List<BillManage> insertedList = billManageDomainService.queryListLambda(
new LambdaQueryWrapper<BillManage>().eq(BillManage::getBillNumber, billNumber));
if (insertedList != null && !insertedList.isEmpty()) {
billManageDO.setBillManageId(insertedList.get(0).getBillManageId());
}
//将集合中没有计费流水id的过滤到另一个集合,将添加费用的集合保存到计费流水并返回计费流水id
List<BillDetailDTO> billDetailDTOListNoBillingStatementId = billDetailDTOList.stream().filter(item -> item.getBillingStatementId() == null).collect(Collectors.toList());
//遍历集合并保存流水
for (BillDetailDTO billDetailDTO : billDetailDTOListNoBillingStatementId) {
BillingStatementDTO billingStatementDTO = new BillingStatementDTO();
BeanUtils.copyProperties(billDetailDTO, billingStatementDTO);
String firstSubjectCode = billDetailDTO.getFirstSubjectCode();
Double taxRate = billDetailMapper.getTaxRate(firstSubjectCode);
BigDecimal amount = billingStatementDTO.getBillingAmount();
BigDecimal taxAmount = amount.divide(BigDecimal.ONE.add(new BigDecimal(taxRate).divide(BigDecimal.valueOf(100))),10, BigDecimal.ROUND_HALF_UP).multiply(new BigDecimal(taxRate).divide(BigDecimal.valueOf(100))).setScale(2, BigDecimal.ROUND_HALF_UP);
BigDecimal taxFreeFee = amount.subtract(taxAmount);
billingStatementDTO.setTaxAmount(taxAmount);
billingStatementDTO.setTaxFreeFee(taxFreeFee);
billingStatementDTO.setTaxRate(taxRate);
billingStatementDTO.setBillingAmount(amount);
billingStatementDTO.setAccountExpenseType(billDetailDTO.getBillType());
billingStatementDTO.setBillManageId(billManageDO.getBillManageId());
billingStatementDTO.setBillingState(3);
Long billingStatementId = billingStatementApplicationService.insertAndReturnId(billingStatementDTO);
//遍历billDetailDTOList集合,将计费流水号相同的,赋值计费流水id
billDetailDTOList.stream().filter(item -> item.getBillingFlow().equals(billDetailDTO.getBillingFlow())).forEach(item -> {
item.setBillingStatementId(billingStatementId);
item.setBillType(billManageDTO.getBillType());
item.setBillManageId(billManageDO.getBillManageId());
item.setBillNumber(billNumber);
item.setInvoiceItem(item.getFirstSubjectCode());
item.setInvoiceItemName(item.getFirstSubjectName());
item.setFeeType(item.getServiceItemsName());
});
}
//同步更新已有计费流水(新增账单时可修改已有费用)
List<BillDetailDTO> billDetailDTOListHasBillingStatementId = billDetailDTOList.stream()
.filter(item -> item.getBillingStatementId() != null)
.collect(Collectors.toList());
for (BillDetailDTO billDetailDTO : billDetailDTOListHasBillingStatementId) {
BillingStatementDO billingStatementDO = new BillingStatementDO();
BeanUtils.copyProperties(billDetailDTO, billingStatementDO);
billingStatementDO.setBillingStatementId(billDetailDTO.getBillingStatementId());
billingStatementDO.setBillManageId(billManageDO.getBillManageId());
billingStatementDO.setBillingState(3);
billingStatementDO.setAccountExpenseType(billDetailDTO.getBillType());
billingStatementApplicationService.update(billingStatementDO);
}
//保存账单明细
double allTaxRate = 0.0d;
BigDecimal allTaxAmount = BigDecimal.ZERO;
BigDecimal allTaxFreeFee = BigDecimal.ZERO;
for (BillDetailDTO item : billDetailDTOList) {
String firstSubjectCode = item.getFirstSubjectCode();
Double taxRate = billDetailMapper.getTaxRate(firstSubjectCode);
BigDecimal amount = item.getBillingAmount();
BigDecimal taxAmount = amount.divide(BigDecimal.ONE.add(new BigDecimal(taxRate).divide(BigDecimal.valueOf(100))),10, BigDecimal.ROUND_HALF_UP).multiply(new BigDecimal(taxRate).divide(BigDecimal.valueOf(100))).setScale(2, BigDecimal.ROUND_HALF_UP);
BigDecimal taxFreeFee = amount.subtract(taxAmount);
item.setTaxAmount(taxAmount);
item.setTaxFreeFee(taxFreeFee);
item.setTaxRate(taxRate);
allTaxRate += taxRate;
allTaxAmount = allTaxAmount.add(taxAmount);
allTaxFreeFee = allTaxFreeFee.add(taxFreeFee);
}
BillManage billManage = billManageService.getById(billManageDO.getBillManageId());
if (billManage != null) {
billManage.setTaxRate(allTaxRate);
billManage.setTaxAmount(allTaxAmount);
billManage.setTaxFreeFee(allTaxFreeFee);
billManage.setSalesmanId(String.valueOf(loginUser.getUserid()));
billManageService.updateById(billManage);
}
Boolean flagTwo = billDetailDomainService.saveBatch(billDetailDTOList);
//保存操作记录
BillOperationLogDO billOperationLogDO = new BillOperationLogDO();
billOperationLogDO.setBillManageId(billManageDO.getBillManageId());
billOperationLogDO.setOperationInfo(StringUtils.format(BillLogsConstants.create_bill_text, billNumber, billingAmount));
billOperationLogDO.setOperationType(1);
boolean flagThree = billOperationLogDomainService.saveBillOperationLog(billOperationLogDO);
return flag && flagTwo && flagThree;
}
/**
* 复制账单-获取原账单数据供前端回显
* 前端拿到数据后跳转到类似修改/新增账单的页面,用户修改后通过addBill接口提交新增
*/
public BillManagePO copyBill(BillManageDTO billManageDTO) {
if (billManageDTO.getBillManageId() == null) { if (billManageDTO.getBillManageId() == null) {
throw new ServiceException("原账单id不能为空"); throw new ServiceException("原账单id不能为空");
} }
// 1. 获取原账单信息 // 获取原账单信息
BillManagePO originalBill = billManageDomainService.getInfo(billManageDTO.getBillManageId()); BillManagePO originalBill = billManageDomainService.getInfo(billManageDTO.getBillManageId());
if (null == originalBill) { if (null == originalBill) {
throw new ServiceException("原账单信息未找到"); throw new ServiceException("原账单信息未找到");
} }
// 2. 获取原账单明细 // 获取原账单明细
List<BillDetailPO> originalDetails = billDetailDomainService.getDetailsByBillManageId(billManageDTO.getBillManageId()); List<BillDetailPO> originalDetails = billDetailDomainService.getDetailsByBillManageId(billManageDTO.getBillManageId());
if (originalDetails == null || originalDetails.isEmpty()) { if (originalDetails == null || originalDetails.isEmpty()) {
throw new ServiceException("原账单明细为空,无法复制"); throw new ServiceException("原账单明细为空,无法复制");
} }
// 3. 创建新账单,除账单编号外完全复制原账单 // 重置关键字段为初始值,清空id等,方便前端回显后直接提交新增
String newBillNumber = OrderSequence.getOrderCode("ZD"); originalBill.setBillManageId(null);
BillManage newBill = new BillManage(); originalBill.setBillNumber(null);
BeanUtils.copyProperties(originalBill, newBill); originalBill.setBillState(1);
newBill.setBillManageId(null); originalBill.setBillStep(1);
newBill.setBillNumber(newBillNumber); originalBill.setReconciliationStatus(0);
newBill.setCreateBy(loginUser.getUserPo().getUserId()); originalBill.setIsInvoice(0);
newBill.setCreateByName(loginUser.getUserPo().getUserName()); originalBill.setActualReceivedAmount(BigDecimal.ZERO);
newBill.setCreateTime(new Date()); originalBill.setBillAmountUnsettled(originalBill.getBillAmount());
newBill.setUpdateBy(loginUser.getUserPo().getUserId()); originalBill.setBillAmountSettlement(BigDecimal.ZERO);
newBill.setUpdateByName(loginUser.getUserPo().getUserName()); originalBill.setSynchronousStatus(0);
newBill.setUpdateTime(new Date()); originalBill.setSkSynchronousStatus(0);
newBill.setDelFlag(1); originalBill.setApplyNumber(null);
// 复制后重置状态字段为初始值 originalBill.setSettlementTime(null);
// 账单状态、对账状态、发票状态重置 originalBill.setSynchronousTime(null);
newBill.setBillState(1); // 1-未确认 originalBill.setSkSynchronousTime(null);
newBill.setBillStep(1); // 1-发起对账 originalBill.setInvoiceId(null);
newBill.setReconciliationStatus(0); // 1-暂未确认 originalBill.setInvoiceMakeTime(null);
newBill.setIsInvoice(0); // 0-未索取 originalBill.setNcId(null);
// 实收=0,未收=账单金额 originalBill.setSkNcId(null);
newBill.setActualReceivedAmount(BigDecimal.ZERO); // 明细也清空id
newBill.setBillAmountUnsettled(newBill.getBillAmount()); for (BillDetailPO detail : originalDetails) {
newBill.setBillAmountSettlement(BigDecimal.ZERO); detail.setBillDetailId(null);
// NC同步状态重置 detail.setBillManageId(null);
newBill.setSynchronousStatus(0); // 0-未同步 detail.setBillNumber(null);
newBill.setSkSynchronousStatus(0); // 0-未同步
// 清空发票、收款、推送相关字段
newBill.setApplyNumber(null); // 发票申请单号
newBill.setSettlementTime(null); // 收款时间
newBill.setSynchronousTime(null); // 应收单推送时间
newBill.setSkSynchronousTime(null); // 收款单推送时间
newBill.setInvoiceId(null); // 发票表ID
newBill.setInvoiceMakeTime(null); // 开票时间
newBill.setNcId(null); // nc唯一标识(应收)
newBill.setSkNcId(null); // nc唯一标识(收款)
// 保存新账单
boolean flag = billManageDomainService.saveEntity(newBill);
if (!flag) {
throw new ServiceException("复制账单失败,请重试");
} }
// 4. 复制账单明细 originalBill.setBillDetailPOList(originalDetails);
List<BillDetail> newDetailList = new ArrayList<>(); return originalBill;
for (BillDetailPO originalDetail : originalDetails) {
BillDetail newDetail = new BillDetail();
BeanUtils.copyProperties(originalDetail, newDetail);
newDetail.setBillDetailId(null);
newDetail.setBillManageId(newBill.getBillManageId());
newDetail.setBillNumber(newBillNumber);
newDetail.setCreateBy(loginUser.getUserPo().getUserId());
newDetail.setCreateByName(loginUser.getUserPo().getUserName());
newDetail.setCreateTime(new Date());
newDetailList.add(newDetail);
}
Boolean flagTwo = billDetailDomainService.insertBatch(newDetailList);
// 5. 复制计费流水(billing_statement
List<BillingStatementPO> originalStatements = billingStatementDomainService.getDetailsByManageId(billManageDTO.getBillManageId());
boolean flagThree = true;
if (originalStatements != null && !originalStatements.isEmpty()) {
List<BillingStatement> newStatementList = new ArrayList<>();
for (BillingStatementPO originalStatement : originalStatements) {
BillingStatement newStatement = new BillingStatement();
BeanUtils.copyProperties(originalStatement, newStatement);
newStatement.setBillingStatementId(null);
newStatement.setBillManageId(newBill.getBillManageId());
newStatement.setCreateBy(loginUser.getUserPo().getUserId());
newStatement.setCreateByName(loginUser.getUserPo().getUserName());
newStatement.setCreateTime(new Date());
newStatementList.add(newStatement);
}
flagThree = billingStatementDomainService.saveEntityBatch(newStatementList);
}
// 6. 保存操作日志
BillOperationLogDO billOperationLogDO = new BillOperationLogDO();
billOperationLogDO.setBillManageId(newBill.getBillManageId());
billOperationLogDO.setOperationInfo(StringUtils.format(BillLogsConstants.copy_bill_text, originalBill.getBillNumber(), newBillNumber));
billOperationLogDO.setOperationType(1);
boolean three = billOperationLogDomainService.saveBillOperationLog(billOperationLogDO);
return flag && flagTwo && flagThree && three;
} }
/** /**
@@ -666,6 +771,76 @@ public class BillManageApplicationService {
return billManageDomainService.synchronousNcSK(businessDocumentDetaliIds); return billManageDomainService.synchronousNcSK(businessDocumentDetaliIds);
} }
/**
* 修改账单明细
*/
@Transactional
public Boolean updateBillDetail(BillManageDTO billManageDTO) {
LoginUser loginUser = SecurityUtils.getLoginUser();
if (ObjectUtil.isNull(loginUser)) {
throw new DigitalLogisticsException(UserError.TIMEOUT);
}
BillDetailDTO detailDTO = billManageDTO.getBillDetailDTOList() != null && !billManageDTO.getBillDetailDTOList().isEmpty()
? billManageDTO.getBillDetailDTOList().get(0) : null;
if (detailDTO == null || detailDTO.getBillDetailId() == null) {
throw new ServiceException("明细id不能为空");
}
BillDetailPO billDetailPO = billDetailDomainService.getInfo(detailDTO.getBillDetailId());
if (billDetailPO == null) {
throw new ServiceException("明细不存在");
}
BillManagePO billManagePO = billManageDomainService.getInfo(billDetailPO.getBillManageId());
if (billManagePO == null || billManagePO.getBillState() != 1) {
throw new ServiceException("账单状态不为未确认,不可修改明细");
}
BillDetailDO billDetailDO = new BillDetailDO();
BeanUtils.copyProperties(detailDTO, billDetailDO);
billDetailDO.setBillDetailId(detailDTO.getBillDetailId());
billDetailDO.setInvoiceItem(detailDTO.getFirstSubjectCode());
billDetailDO.setInvoiceItemName(detailDTO.getFirstSubjectName());
billDetailDO.setFeeType(detailDTO.getServiceItemsName());
billDetailDO.setUpdateBy(loginUser.getUserid());
billDetailDO.setUpdateByName(loginUser.getUserPo().getUserName());
billDetailDO.setUpdateTime(new Date());
// 同步更新计费流水的费用科目、服务项(因为这些字段在 billing_statement 表,不在 bill_detail 表)
if (billDetailPO.getBillingStatementId() != null) {
BillingStatementDO billingStatementDO = new BillingStatementDO();
billingStatementDO.setBillingStatementId(billDetailPO.getBillingStatementId());
billingStatementDO.setFirstSubjectCode(detailDTO.getFirstSubjectCode());
billingStatementDO.setFirstSubjectName(detailDTO.getFirstSubjectName());
billingStatementDO.setServiceItemsCode(detailDTO.getServiceItemsCode());
billingStatementDO.setServiceItemsName(detailDTO.getServiceItemsName());
billingStatementDO.setUpdateBy(loginUser.getUserid());
billingStatementDO.setUpdateByName(loginUser.getUserPo().getUserName());
billingStatementDO.setUpdateTime(new Date());
billingStatementApplicationService.update(billingStatementDO);
}
Boolean flag = billDetailDomainService.update(billDetailDO);
// 重新计算账单总金额并更新主表
List<BillDetailPO> allDetails = billDetailDomainService.getDetailsByBillManageId(billManagePO.getBillManageId());
allDetails = allDetails.stream().map(item -> {
if (item.getBillDetailId().equals(detailDTO.getBillDetailId())) {
item.setBillingTotalAmount(detailDTO.getBillingTotalAmount());
item.setBillingAmount(detailDTO.getBillingAmount());
item.setBillingDiscountAmount(detailDTO.getBillingDiscountAmount());
}
return item;
}).collect(Collectors.toList());
BigDecimal totalAmount = allDetails.stream().map(BillDetailPO::getBillingTotalAmount).reduce(BigDecimal.ZERO, BigDecimal::add);
BigDecimal amount = allDetails.stream().map(BillDetailPO::getBillingAmount).reduce(BigDecimal.ZERO, BigDecimal::add);
BigDecimal discountAmount = allDetails.stream().map(BillDetailPO::getBillingDiscountAmount).reduce(BigDecimal.ZERO, BigDecimal::add);
BillManageDO billManageDO = new BillManageDO();
billManageDO.setBillManageId(billManagePO.getBillManageId());
billManageDO.setBillTotalAmount(totalAmount);
billManageDO.setBillAmount(amount);
billManageDO.setBillAmountUnsettled(amount);
billManageDO.setBillDiscountAmount(discountAmount);
billManageDO.setUpdateBy(loginUser.getUserid());
billManageDO.setUpdateByName(loginUser.getUserPo().getUserName());
billManageDO.setUpdateTime(new Date());
Boolean flagTwo = billManageDomainService.update(billManageDO);
return flag && flagTwo;
}
} }
@@ -585,6 +585,8 @@ public class BillingStatementApplicationService {
此方法只进行实体返回,并不进行数据保存 此方法只进行实体返回,并不进行数据保存
*/ */
LoginUser loginUser = SecurityUtils.getLoginUser(); LoginUser loginUser = SecurityUtils.getLoginUser();
billingStatementDO.setAccountExpenseType(billingStatementDO.getAccountExpenseType());
if (ObjectUtil.isNull(loginUser)) { if (ObjectUtil.isNull(loginUser)) {
throw new DigitalLogisticsException(UserError.TIMEOUT); throw new DigitalLogisticsException(UserError.TIMEOUT);
} }
@@ -598,6 +600,9 @@ public class BillingStatementApplicationService {
billingStatementPO.setTopOrganizationId(loginUser.getUserPo().getTopOrganizationId()); billingStatementPO.setTopOrganizationId(loginUser.getUserPo().getTopOrganizationId());
billingStatementPO.setOrganizationId(loginUser.getUserPo().getOrganizationId()); billingStatementPO.setOrganizationId(loginUser.getUserPo().getOrganizationId());
billingStatementPO.setOrganizationName(loginUser.getUserPo().getOrganizationName()); billingStatementPO.setOrganizationName(loginUser.getUserPo().getOrganizationName());
// 默认填充当前登录人为业务员
billingStatementPO.setSalesmanId(String.valueOf(loginUser.getUserid()));
billingStatementPO.setSalesmanName(loginUser.getUserPo().getUserName());
return billingStatementPO; return billingStatementPO;
} }
@@ -38,4 +38,6 @@ public interface IBillDetailService extends IService<BillDetail>
public BillDetailPO getInfo(Long billDetailId); public BillDetailPO getInfo(Long billDetailId);
List<BillDetailPO> getDetailsByBillManageId(Long billManageId); List<BillDetailPO> getDetailsByBillManageId(Long billManageId);
List<BillDetail> getDetailsByBillManageIdAndGroup(Long billManageId);
} }
@@ -5,6 +5,7 @@ import com.mhd.bms.domain.billManage.entity.BillDetail;
import com.mhd.bms.domain.billManage.repository.po.BillDetailPO; import com.mhd.bms.domain.billManage.repository.po.BillDetailPO;
import org.apache.ibatis.annotations.Param; import org.apache.ibatis.annotations.Param;
import java.math.BigDecimal;
import java.util.List; import java.util.List;
/** /**
@@ -17,4 +18,8 @@ public interface BillDetailMapper extends BaseMapper<BillDetail>
{ {
List<BillDetailPO> getDetailsByBillManageId(@Param("billManageId") Long billManageId); List<BillDetailPO> getDetailsByBillManageId(@Param("billManageId") Long billManageId);
List<BillDetail> getDetailsByBillManageIdAndGroup(@Param("billManageId") Long billManageId);
Double getTaxRate(@Param("code") String code);
} }
@@ -44,4 +44,6 @@ public interface BillManageMapper extends BaseMapper<BillManage>
String getDeptName(@Param("dictCode") String dictCode); String getDeptName(@Param("dictCode") String dictCode);
String getOrgCodeNc(@Param("organizationId") Long organizationId); String getOrgCodeNc(@Param("organizationId") Long organizationId);
Long getShipperId(@Param("userId") Long userId, @Param("organizationId") Long organizationId);
} }
@@ -75,4 +75,9 @@ public class BillDetailImpl extends ServiceImpl<BillDetailMapper, BillDetail> im
public List<BillDetailPO> getDetailsByBillManageId(Long billManageId) { public List<BillDetailPO> getDetailsByBillManageId(Long billManageId) {
return billDetailMapper.getDetailsByBillManageId(billManageId); return billDetailMapper.getDetailsByBillManageId(billManageId);
} }
@Override
public List<BillDetail> getDetailsByBillManageIdAndGroup(Long billManageId) {
return billDetailMapper.getDetailsByBillManageIdAndGroup(billManageId);
}
} }
@@ -264,4 +264,6 @@ public class BillManageDO extends BaseVOEntity{
private String paymentAccountId; private String paymentAccountId;
@ApiModelProperty("收款帐户名称") @ApiModelProperty("收款帐户名称")
private String paymentAccountName; private String paymentAccountName;
@ApiModelProperty("业务员ID")
private String salesmanId;
} }
@@ -100,6 +100,10 @@ public class BillingStatementPO extends BaseVOEntity{
@Excel(name = "收支类型", readConverterExp = "1=-应收,2-应付") @Excel(name = "收支类型", readConverterExp = "1=-应收,2-应付")
private Integer accountExpenseType; private Integer accountExpenseType;
@ApiModelProperty("收支类型(1-应收,2-应付)")
@Excel(name = "收支类型", readConverterExp = "1=-应收,2-应付")
private Integer billType;
@ApiModelProperty("流水备注") @ApiModelProperty("流水备注")
@Excel(name = "流水备注") @Excel(name = "流水备注")
private String billingRemark; private String billingRemark;
@@ -101,6 +101,10 @@ public class BillingStatementDO extends BaseVOEntity{
@Excel(name = "收支类型", readConverterExp = "1=-应收,2-应付") @Excel(name = "收支类型", readConverterExp = "1=-应收,2-应付")
private Integer accountExpenseType; private Integer accountExpenseType;
@ApiModelProperty("收支类型(1-应收,2-应付)")
@Excel(name = "收支类型", readConverterExp = "1=-应收,2-应付")
private Integer billType;
@ApiModelProperty("流水备注") @ApiModelProperty("流水备注")
@Excel(name = "流水备注") @Excel(name = "流水备注")
private String billingRemark; private String billingRemark;
@@ -675,6 +675,9 @@ public class BillingStatementDomainService {
*/ */
public List<BillingStatementPO> getBillDetailsList(BillingStatementDO billingStatementDO) { public List<BillingStatementPO> getBillDetailsList(BillingStatementDO billingStatementDO) {
//查询当前账单的五大信息组织信息结算对象来源系统收支类型账单周期 //查询当前账单的五大信息组织信息结算对象来源系统收支类型账单周期
if (billingStatementDO.getBillManageId() == null || billingStatementDO.getBillManageId() <= 0) {
return new ArrayList<>();
}
BillManagePO billManagePO = billManageDomainService.getInfo(billingStatementDO.getBillManageId()); BillManagePO billManagePO = billManageDomainService.getInfo(billingStatementDO.getBillManageId());
if(null == billManagePO){ if(null == billManagePO){
throw new ServiceException("账单信息未找到"); throw new ServiceException("账单信息未找到");
@@ -8,6 +8,7 @@ import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.mhd.bms.domain.billManage.entity.BillManage; import com.mhd.bms.domain.billManage.entity.BillManage;
import com.mhd.bms.domain.billManage.repository.mapper.BillManageMapper; import com.mhd.bms.domain.billManage.repository.mapper.BillManageMapper;
import com.mhd.common.core.web.domain.AjaxResult;
import com.mhd.bms.domain.bmsInvoiceList.entity.BmsInvoiceList; import com.mhd.bms.domain.bmsInvoiceList.entity.BmsInvoiceList;
import com.mhd.bms.domain.bmsInvoiceList.entity.BmsSettlementPartyInvoice; import com.mhd.bms.domain.bmsInvoiceList.entity.BmsSettlementPartyInvoice;
import com.mhd.bms.domain.bmsInvoiceList.repository.facade.IBmsInvoiceListService; import com.mhd.bms.domain.bmsInvoiceList.repository.facade.IBmsInvoiceListService;
@@ -56,6 +57,8 @@ public class BmsInvoiceListServiceImpl extends ServiceImpl<BmsInvoiceListMapper,
private BmsMakeOutInvoiceItemMapper bmsMakeOutInvoiceItemMapper; private BmsMakeOutInvoiceItemMapper bmsMakeOutInvoiceItemMapper;
@Resource @Resource
private BillManageMapper billManageMapper; private BillManageMapper billManageMapper;
@Resource
private com.mhd.system.api.SystemServiceFeign systemServiceFeign;
/*@Resource /*@Resource
private BmsSettlementPartyInvoiceMapper bmsSettlementPartyInvoiceMapper;*/ private BmsSettlementPartyInvoiceMapper bmsSettlementPartyInvoiceMapper;*/
@@ -327,7 +330,7 @@ public class BmsInvoiceListServiceImpl extends ServiceImpl<BmsInvoiceListMapper,
/** /**
* 发票详情 * 发票详情
* *
* @param id * @param
* @return * @return
*/ */
@Override @Override
@@ -415,6 +418,23 @@ public class BmsInvoiceListServiceImpl extends ServiceImpl<BmsInvoiceListMapper,
bmsMakeOutInvoiceItem.setMakeId(bmsMakeOutInvoice.getId()); bmsMakeOutInvoiceItem.setMakeId(bmsMakeOutInvoice.getId());
//bmsMakeOutInvoiceItem.setCreateBy(sysUser.getId()); //bmsMakeOutInvoiceItem.setCreateBy(sysUser.getId());
bmsMakeOutInvoiceItem.setCreateTime(date); bmsMakeOutInvoiceItem.setCreateTime(date);
// 如果前端没传 invoiceItemName invoiceItem编码从费用科目反查名称补齐
if (StringUtils.isEmpty(bmsMakeOutInvoiceItem.getInvoiceItemName())
&& StringUtils.isNotEmpty(bmsMakeOutInvoiceItem.getInvoiceItem())) {
try {
AjaxResult ajaxResult = systemServiceFeign.getSubInfoByCode(bmsMakeOutInvoiceItem.getInvoiceItem());
if ("200".equals(String.valueOf(ajaxResult.get("code"))) && ajaxResult.get("data") != null) {
com.alibaba.fastjson.JSONObject dataObj = com.alibaba.fastjson.JSON.parseObject(
com.alibaba.fastjson.JSON.toJSONString(ajaxResult.get("data")));
String subjectName = dataObj.getString("subjectName");
if (StringUtils.isNotEmpty(subjectName)) {
bmsMakeOutInvoiceItem.setInvoiceItemName(subjectName);
}
}
} catch (Exception e) {
log.warn("开票项目名称反查失败 invoiceItem=" + bmsMakeOutInvoiceItem.getInvoiceItem() + " " + e.getMessage());
}
}
bmsMakeOutInvoiceItemMapper.insert(bmsMakeOutInvoiceItem); bmsMakeOutInvoiceItemMapper.insert(bmsMakeOutInvoiceItem);
} }
} }
@@ -0,0 +1,145 @@
package com.mhd.bms.interfaces.dto.billManage;
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;
@Data
@ApiModel(value = "应收账单导出对象")
public class BillManageExportVO {
/** ====== 原有账单头字段(与 BillManagePO 的 @Excel 一致) ====== */
@Excel(name = "一级组织表ID")
private Long topOrganizationId;
@Excel(name = "组织表ID")
private Long organizationId;
@Excel(name = "组织名称")
private String organizationName;
@Excel(name = "账单编号")
private String billNumber;
@Excel(name = "账单类型", readConverterExp = "1=-应收,2-应付")
private Integer billType;
@Excel(name = "账单状态", readConverterExp = "1=-未确认,2-对账中,3-未收款/付款,4-部分收款/付款,5-已收款/付款,6-已作废,7-已退款")
private Integer billState;
@Excel(name = "账单流程节点", readConverterExp = "1=-发起对账,2-客户确认,3-财务审核,4-收款/付款")
private Integer billStep;
@Excel(name = "系统来源")
private String belongModule;
@Excel(name = "系统来源code")
private String belongModuleCode;
@Excel(name = "结算对象id")
private Long settlementCustomersId;
@Excel(name = "结算对象code")
private String settlementCustomersCode;
@Excel(name = "结算对象")
private String settlementEntity;
@Excel(name = "账单总金额")
private BigDecimal billTotalAmount;
@Excel(name = "优惠金额")
private BigDecimal billDiscountAmount;
@Excel(name = "账单金额")
private BigDecimal billAmount;
@Excel(name = "已收/付金额")
private BigDecimal billAmountSettlement;
@Excel(name = "未收/付金额")
private BigDecimal billAmountUnsettled;
@Excel(name = "期望金额")
private BigDecimal billExpectedAmount;
@Excel(name = "对账状态", readConverterExp = "1=-暂未确认,2-申请调账,3-财务调账,4-核对无误")
private Integer reconciliationStatus;
@Excel(name = "对账意见描述")
private String reconciliationOpinion;
@Excel(name = "客户凭证地址")
private String voucherAddress;
@Excel(name = "财务审核结果(1-同意,2-拒绝)")
private Integer financialReviewFlag;
@Excel(name = "审核意见描述")
private String financialReviewOpinion;
@Excel(name = "周期开始时间", width = 30, dateFormat = "yyyy-MM-dd")
private Date cycleBeginTime;
@Excel(name = "周期结束时间", width = 30, dateFormat = "yyyy-MM-dd")
private Date cycleEndTime;
@Excel(name = "收款/付款时间", width = 30, dateFormat = "yyyy-MM-dd")
private Date settlementTime;
@Excel(name = "备注")
private String billRemark;
@Excel(name = "折扣百分比")
private BigDecimal billDiscount;
@Excel(name = "折扣上限金额")
private BigDecimal billDiscountLimit;
@Excel(name = "费用计算精度code")
private String costAccuracyCode;
@Excel(name = "费用计算精度name")
private String costAccuracyName;
@Excel(name = "尾数计算code")
private String tailCalculationCode;
@Excel(name = "尾数计算name")
private String tailCalculationName;
@Excel(name = "账单金额精度code")
private String amountAccuracyCode;
@Excel(name = "账单金额精度name")
private String amountAccuracyName;
/** ====== 新增明细字段(来源于 bill_detail + billing_statement ====== */
@Excel(name = "费用类别")
private String feeType;
@Excel(name = "费用类型code")
private String serviceItemsCode;
@Excel(name = "费用类型")
private String serviceItemsName;
@Excel(name = "一级费用科目code")
private String firstSubjectCode;
@Excel(name = "一级费用科目")
private String firstSubjectName;
@Excel(name = "二级费用科目code")
private String secondSubjectCode;
@Excel(name = "二级费用科目")
private String secondSubjectName;
@Excel(name = "明细金额")
private BigDecimal billingAmount;
}
@@ -102,6 +102,10 @@ public class BillingStatementDTO extends BaseVOEntity{
@Excel(name = "收支类型", readConverterExp = "1=-应收,2-应付") @Excel(name = "收支类型", readConverterExp = "1=-应收,2-应付")
private Integer accountExpenseType; private Integer accountExpenseType;
@ApiModelProperty("收支类型(1-应收,2-应付)")
@Excel(name = "收支类型", readConverterExp = "1=-应收,2-应付")
private Integer billType;
@ApiModelProperty("流水备注") @ApiModelProperty("流水备注")
@Excel(name = "流水备注") @Excel(name = "流水备注")
private String billingRemark; private String billingRemark;
@@ -6,6 +6,8 @@ import java.util.Set;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import java.util.stream.Stream; import java.util.stream.Stream;
import java.io.IOException;
import java.net.URLEncoder;
import com.mhd.bms.application.server.billManage.BillManageApplicationService; import com.mhd.bms.application.server.billManage.BillManageApplicationService;
import com.mhd.bms.domain.billManage.repository.po.BillDetailPO; import com.mhd.bms.domain.billManage.repository.po.BillDetailPO;
@@ -13,7 +15,9 @@ import com.mhd.bms.domain.billingStatement.repository.todo.BillingStatementDO;
import com.mhd.bms.domain.ncLog.entity.NcLog; import com.mhd.bms.domain.ncLog.entity.NcLog;
import com.mhd.bms.infrastructure.utils.UniqueKeyUtil; import com.mhd.bms.infrastructure.utils.UniqueKeyUtil;
import com.mhd.bms.interfaces.dto.billingStatement.BillingStatementDTO; import com.mhd.bms.interfaces.dto.billingStatement.BillingStatementDTO;
import com.mhd.bms.interfaces.dto.billManage.BillManageExportVO;
import com.mhd.common.core.exception.ServiceException; import com.mhd.common.core.exception.ServiceException;
import com.mhd.common.core.utils.poi.ExcelUtil;
import com.mhd.common.log.annotation.Log; import com.mhd.common.log.annotation.Log;
import com.mhd.common.log.enums.BusinessType; import com.mhd.common.log.enums.BusinessType;
import com.mhd.common.redis.enums.RedisLockTypeEnum; import com.mhd.common.redis.enums.RedisLockTypeEnum;
@@ -31,6 +35,7 @@ import com.mhd.bms.domain.billManage.repository.todo.BillManageDO;
import com.mhd.bms.domain.billManage.repository.po.BillManagePO; import com.mhd.bms.domain.billManage.repository.po.BillManagePO;
import com.mhd.bms.interfaces.assembler.billManage.BillManageAssembler; import com.mhd.bms.interfaces.assembler.billManage.BillManageAssembler;
import javax.annotation.Resource; import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import com.mhd.common.core.web.controller.BaseController; import com.mhd.common.core.web.controller.BaseController;
import com.mhd.common.core.web.domain.AjaxResult; import com.mhd.common.core.web.domain.AjaxResult;
import com.mhd.common.core.web.page.TableDataInfo; import com.mhd.common.core.web.page.TableDataInfo;
@@ -79,6 +84,55 @@ public class BillManageApi extends BaseController{
return AjaxResult.success(billManageApplicationService.listCount(billManageDO)); return AjaxResult.success(billManageApplicationService.listCount(billManageDO));
} }
@ApiOperation("导出应收账单")
@GetMapping(value = "/exportReceivableList", produces = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet")
public void exportReceivableList(BillManageDTO billManageDTO, HttpServletResponse response) throws IOException
{
//转换实体
BillManageDO billManageDO = new BillManageDO();
BeanUtils.copyProperties(billManageDTO,billManageDO);
billManageDO.setBillType(1);
//查全部不分页
List<BillManagePO> list = billManageApplicationService.queryList(billManageDO);
//扁平化处理一条明细生成一行
List<BillManageExportVO> exportList = new ArrayList<>();
for (BillManagePO bill : list) {
List<BillDetailPO> details = bill.getBillDetailPOList();
if (details != null && !details.isEmpty()) {
for (BillDetailPO detail : details) {
BillManageExportVO vo = new BillManageExportVO();
//复制全部账单头字段
BeanUtils.copyProperties(bill, vo);
//覆盖明细字段
vo.setFeeType(detail.getFeeType());
vo.setServiceItemsCode(detail.getServiceItemsCode());
vo.setServiceItemsName(detail.getServiceItemsName());
vo.setFirstSubjectCode(detail.getFirstSubjectCode());
vo.setFirstSubjectName(detail.getFirstSubjectName());
vo.setSecondSubjectCode(detail.getSecondSubjectCode());
vo.setSecondSubjectName(detail.getSecondSubjectName());
vo.setBillingAmount(detail.getBillingAmount());
exportList.add(vo);
}
} else {
//没有明细也要有一行
BillManageExportVO vo = new BillManageExportVO();
BeanUtils.copyProperties(bill, 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<BillManageExportVO> util = new ExcelUtil<>(BillManageExportVO.class);
util.exportExcel(response, exportList, "应收账单");
}
@ApiOperation("获取nc推送日志") @ApiOperation("获取nc推送日志")
@GetMapping(value = "/getNcLog") @GetMapping(value = "/getNcLog")
public AjaxResult getNcLog(@RequestParam(name = "billManageId") Long billManageId, @RequestParam(name = "type") Long type) public AjaxResult getNcLog(@RequestParam(name = "billManageId") Long billManageId, @RequestParam(name = "type") Long type)
@@ -229,7 +283,36 @@ public class BillManageApi extends BaseController{
} }
@ApiOperation("复制账单") @ApiOperation("修改账单明细")
@PostMapping("/updateBillDetail")
public AjaxResult updateBillDetail(@RequestBody BillManageDTO billManageDTO)
{
try {
billManageApplicationService.updateBillDetail(billManageDTO);
return AjaxResult.success("操作成功");
}catch (Exception e){
return AjaxResult.error("修改明细失败:"+e.getMessage());
}
}
@ApiOperation("新增账单")
@PostMapping("/addBill")
public AjaxResult addBill(@RequestBody BillManageDTO billManageDTO)
{
if(billManageDTO.getBillDetailDTOList() == null || billManageDTO.getBillDetailDTOList().size() == 0){
throw new ServiceException("账单明细不能为空");
}
try {
billManageApplicationService.addBill(billManageDTO);
return AjaxResult.success("操作成功");
}catch (Exception e){
return AjaxResult.error("新增账单失败:"+e.getMessage());
}
}
@ApiOperation("复制账单-获取原账单数据用于回显")
@PostMapping("/copyBill") @PostMapping("/copyBill")
public AjaxResult copyBill(@RequestBody BillManageDTO billManageDTO) public AjaxResult copyBill(@RequestBody BillManageDTO billManageDTO)
{ {
@@ -237,8 +320,8 @@ public class BillManageApi extends BaseController{
throw new ServiceException("原账单id不能为空"); throw new ServiceException("原账单id不能为空");
} }
try { try {
Boolean result = billManageApplicationService.copyBill(billManageDTO); BillManagePO result = billManageApplicationService.copyBill(billManageDTO);
return toAjax(result); return AjaxResult.success(result);
}catch (Exception e){ }catch (Exception e){
return AjaxResult.error("复制账单失败:"+e.getMessage()); return AjaxResult.error("复制账单失败:"+e.getMessage());
} }
+4 -4
View File
@@ -18,15 +18,15 @@ spring:
discovery: discovery:
# server-addr: 127.0.0.1:8848 # server-addr: 127.0.0.1:8848
# 线上测试环境配置 容器名+端口号 # 线上测试环境配置 容器名+端口号
# server-addr: 10.33.0.129:6010 server-addr: 10.33.0.129:6010
server-addr: 10.102.192.30:6848 # server-addr: 10.102.192.31:6848
username: nacos username: nacos
password: manhuoda@2023 password: manhuoda@2023
config: config:
# server-addr: 127.0.0.1:8848 # server-addr: 127.0.0.1:8848
# 线上测试环境配置 容器名+端口号 # 线上测试环境配置 容器名+端口号
# server-addr: 10.33.0.129:6010 server-addr: 10.33.0.129:6010
server-addr: 10.102.192.30:6848 # server-addr: 10.102.192.31:6848
username: nacos username: nacos
password: manhuoda@2023 password: manhuoda@2023
group: DEFAULT_GROUP # 默认分组就是DEFAULT_GROUP,如果使用默认分组可以不配置 group: DEFAULT_GROUP # 默认分组就是DEFAULT_GROUP,如果使用默认分组可以不配置
@@ -27,5 +27,35 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
AND bd.bill_manage_id = #{billManageId} AND bd.bill_manage_id = #{billManageId}
</select> </select>
<select id="getDetailsByBillManageIdAndGroup" resultType="com.mhd.bms.domain.billManage.entity.BillDetail" parameterType="java.lang.Long">
SELECT
SUM(BILLING_AMOUNT) as BILLING_AMOUNT,
SUM(TAX_AMOUNT) as TAX_AMOUNT,
SUM(TAX_FREE_FEE) as TAX_FREE_FEE,
AVG(TAX_RATE) as TAX_RATE,
BILL_MANAGE_ID as BILL_MANAGE_ID,
TOP_ORGANIZATION_ID as TOP_ORGANIZATION_ID,
ORGANIZATION_NAME,
INVOICE_ITEM,
INVOICE_ITEM_NAME,
FEE_TYPE,
BILL_NUMBER
FROM
bill_detail
WHERE
del_flag = 1
AND bill_manage_id = #{billManageId} GROUP BY INVOICE_ITEM,INVOICE_ITEM_NAME,FEE_TYPE
</select>
<select id="getTaxRate" resultType="java.lang.Double" parameterType="java.lang.String">
SELECT
rate
FROM
NGWL_TEST_SYSTEM.EXPENSE_ACCOUNT
WHERE
del_flag = 1
AND SUBJECT_CODE = #{code}
</select>
</mapper> </mapper>
@@ -162,4 +162,8 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
SELECT NC_CODE FROM NGWL_TEST_PRODUCT."SYS_ORGANIZATION" where DEL_FLAG = 1 and organization_id = #{organizationId} limit 1 SELECT NC_CODE FROM NGWL_TEST_PRODUCT."SYS_ORGANIZATION" where DEL_FLAG = 1 and organization_id = #{organizationId} limit 1
</select> </select>
<select id="getShipperId" resultType="java.lang.Long">
SELECT SHIPPER_ID FROM NGWL_TEST_USER."USER_SHIPPER" where DEL_FLAG = '1' and user_id = #{userId} and organization_id = #{organizationId} limit 1
</select>
</mapper> </mapper>
@@ -166,12 +166,18 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<if test="businessDocumentDO.contractName != null and businessDocumentDO.contractName != ''"> <if test="businessDocumentDO.contractName != null and businessDocumentDO.contractName != ''">
AND contract_name like concat('%', #{businessDocumentDO.contractName}, '%') AND contract_name like concat('%', #{businessDocumentDO.contractName}, '%')
</if> </if>
<!-- <if test="businessDocumentDO.billAmount != null and businessDocumentDO.billAmount != ''">-->
<!-- AND bill_amount like concat('%', #{businessDocumentDO.billAmount}, '%')-->
<!-- </if>-->
<if test="businessDocumentDO.billAmount != null and businessDocumentDO.billAmount != ''"> <if test="businessDocumentDO.billAmount != null and businessDocumentDO.billAmount != ''">
AND bill_amount like concat('%', #{businessDocumentDO.billAmount}, '%') and bill_amount = #{businessDocumentDO.billAmount}
</if> </if>
<if test="businessDocumentDO.estimatedCost != null and businessDocumentDO.estimatedCost != ''"> <if test="businessDocumentDO.estimatedCost != null and businessDocumentDO.estimatedCost != ''">
AND estimated_cost like concat('%', #{businessDocumentDO.estimatedCost}, '%') AND estimated_cost = #{businessDocumentDO.estimatedCost}
</if> </if>
<!-- <if test="businessDocumentDO.estimatedCost != null and businessDocumentDO.estimatedCost != ''">-->
<!-- AND estimated_cost like concat('%', #{businessDocumentDO.estimatedCost}, '%')-->
<!-- </if>-->
<if test="businessDocumentDO.firstSubjectName != null and businessDocumentDO.firstSubjectName != ''"> <if test="businessDocumentDO.firstSubjectName != null and businessDocumentDO.firstSubjectName != ''">
AND first_subject_name like concat('%', #{businessDocumentDO.firstSubjectName}, '%') AND first_subject_name like concat('%', #{businessDocumentDO.firstSubjectName}, '%')
</if> </if>
@@ -193,6 +199,9 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<if test="businessDocumentDO.documentTypeCode != null and businessDocumentDO.documentTypeCode != ''"> <if test="businessDocumentDO.documentTypeCode != null and businessDocumentDO.documentTypeCode != ''">
AND document_type_code = #{businessDocumentDO.documentTypeCode} AND document_type_code = #{businessDocumentDO.documentTypeCode}
</if> </if>
<if test="businessDocumentDO.salesmanId != null and businessDocumentDO.salesmanId != ''">
AND document_type_code = #{businessDocumentDO.salesmanId}
</if>
<if test="businessDocumentDO.businessDocumentIdSet != null"> <if test="businessDocumentDO.businessDocumentIdSet != null">
and business_document_id in and business_document_id in
<foreach item="id" collection="businessDocumentDO.businessDocumentIdSet" open="(" separator="," close=")"> <foreach item="id" collection="businessDocumentDO.businessDocumentIdSet" open="(" separator="," close=")">
@@ -200,10 +200,6 @@
<if test="settlementCustomersDO.organizationId != null"> <if test="settlementCustomersDO.organizationId != null">
AND ( AND (
a.organization_id = #{settlementCustomersDO.organizationId} a.organization_id = #{settlementCustomersDO.organizationId}
OR b.org_code LIKE concat('%"code":"', #{settlementCustomersDO.organizationId}, '"%')
OR b.org_code LIKE concat('%code:', #{settlementCustomersDO.organizationId}, '%')
OR b.org_code LIKE concat('%code: ', #{settlementCustomersDO.organizationId}, '%')
OR b.org_code LIKE concat('%"code":', #{settlementCustomersDO.organizationId}, '%')
) )
</if> </if>
<if test="settlementCustomersDO.topOrganizationId != null and settlementCustomersDO.topOrganizationId != ''"> <if test="settlementCustomersDO.topOrganizationId != null and settlementCustomersDO.topOrganizationId != ''">
@@ -68,4 +68,5 @@ public interface ExecutionStockInOrderMapper extends BaseMapper<ExecutionStockIn
String getNcUrl(@Param("interfaceType") String interfaceType,@Param("organizationName") String organizationName,@Param("organizationId") Long organizationId); String getNcUrl(@Param("interfaceType") String interfaceType,@Param("organizationName") String organizationName,@Param("organizationId") Long organizationId);
int countByOrderNumberPrefix(@Param("prefix") String prefix);
} }
@@ -37,4 +37,5 @@ public interface ExecutionStockOutOrderMapper extends BaseMapper<ExecutionStockO
public void delWOrderDetail(@Param("outOrderNumber") String outOrderNumber); public void delWOrderDetail(@Param("outOrderNumber") String outOrderNumber);
int countByOrderNumberPrefix(@Param("prefix") String prefix);
} }
@@ -29,6 +29,8 @@ public interface ReservationMaterialInventoryMapper extends BaseMapper<Reservati
public List<ReservationMaterialInventoryPO> queryListByWl(ReservationMaterialInventoryDO materialInventoryDO); public List<ReservationMaterialInventoryPO> queryListByWl(ReservationMaterialInventoryDO materialInventoryDO);
//查物料库存列表-货主 //查物料库存列表-货主
public List<ReservationMaterialInventoryPO> queryListByHz(ReservationMaterialInventoryDO materialInventoryDO); public List<ReservationMaterialInventoryPO> queryListByHz(ReservationMaterialInventoryDO materialInventoryDO);
//查物料库存列表-物料+过期日期
public List<ReservationMaterialInventoryPO> queryListByWlExpiry(ReservationMaterialInventoryDO materialInventoryDO);
public MaterialBaseInfo getByInfoId(@Param("id") Long id); public MaterialBaseInfo getByInfoId(@Param("id") Long id);
@@ -64,6 +64,8 @@ public class ReservationMaterialInventoryImpl extends ServiceImpl<ReservationMat
return materialInventoryMapper.queryListByKw(materialInventoryDO); return materialInventoryMapper.queryListByKw(materialInventoryDO);
} else if ("wlkw".equals(queryRule)) { } else if ("wlkw".equals(queryRule)) {
return materialInventoryMapper.queryListByWlKw(materialInventoryDO); return materialInventoryMapper.queryListByWlKw(materialInventoryDO);
} else if ("wlExpiry".equals(queryRule)) {
return materialInventoryMapper.queryListByWlExpiry(materialInventoryDO);
} else if ("all".equals(queryRule)) { } else if ("all".equals(queryRule)) {
return materialInventoryMapper.queryList(materialInventoryDO); return materialInventoryMapper.queryList(materialInventoryDO);
} else { } else {
@@ -253,4 +253,6 @@ public class ReservationMaterialInventoryDO extends MaterialBaseDO {
private String createTimeEnd; private String createTimeEnd;
private String expiryDateStr; private String expiryDateStr;
private String productionDateStr; private String productionDateStr;
private String expiryDateStart;
private String expiryDateEnd;
} }
@@ -2,6 +2,7 @@ package com.mhd.oms.domain.reservationStockInOrder.repository.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.mhd.oms.domain.reservationInMaterialDetail.repository.po.ReservationInMaterialDetailPO; import com.mhd.oms.domain.reservationInMaterialDetail.repository.po.ReservationInMaterialDetailPO;
import com.mhd.oms.domain.reservationMaterialInventory.repository.po.ReservationMaterialInventoryPO;
import com.mhd.oms.domain.reservationStockInOrder.entity.ReservationStockInOrder; import com.mhd.oms.domain.reservationStockInOrder.entity.ReservationStockInOrder;
import com.mhd.oms.domain.reservationStockInOrder.repository.po.MaterialBaseInfoPO; import com.mhd.oms.domain.reservationStockInOrder.repository.po.MaterialBaseInfoPO;
import com.mhd.oms.domain.reservationStockInOrder.repository.po.MaterialGoodsRulePO; import com.mhd.oms.domain.reservationStockInOrder.repository.po.MaterialGoodsRulePO;
@@ -30,13 +31,16 @@ public interface ReservationStockInOrderMapper extends BaseMapper<ReservationSto
public MaterialBaseInfoPO getByName(@Param("name") String name); public MaterialBaseInfoPO getByName(@Param("name") String name);
public MaterialBaseInfoPO getByCode(@Param("code") String code); public MaterialBaseInfoPO getByCode(@Param("code") String code,@Param("orgId") Long orgId);
public List<MaterialBaseInfoPO> getMaterialBaseInfoList(@Param("id") String id); public List<MaterialBaseInfoPO> getMaterialBaseInfoList(@Param("id") String id);
public List<ReservationMaterialInventoryPO> getkcId(@Param("id") Long id,@Param("q") BigDecimal q);
public MaterialWarehouseControlPO getInfoByMaterialBaseInfoIds(@Param("id") Long id); public MaterialWarehouseControlPO getInfoByMaterialBaseInfoIds(@Param("id") Long id);
public MaterialGoodsRulePO getGoodsInfoByMaterialBaseInfoIds(@Param("id") Long id); public MaterialGoodsRulePO getGoodsInfoByMaterialBaseInfoIds(@Param("id") Long id);
// public List<ReservationMaterialInventoryPO> getkcId(@Param("id") Long id, @Param("q") BigDecimal q);
public String getUserNcCode(@Param("id") Long id); public String getUserNcCode(@Param("id") Long id);
@@ -67,4 +71,8 @@ public interface ReservationStockInOrderMapper extends BaseMapper<ReservationSto
String getNcUrl(@Param("interfaceType") String interfaceType,@Param("organizationName") String organizationName,@Param("organizationId") Long organizationId); String getNcUrl(@Param("interfaceType") String interfaceType,@Param("organizationName") String organizationName,@Param("organizationId") Long organizationId);
String getCustomerOrgCode(@Param("id") Long id); String getCustomerOrgCode(@Param("id") Long id);
int countByOrderNumberPrefix(@Param("prefix") String prefix);
List<String> generateReserveOrderNumber1(@Param("prefix") String prefix);
} }
@@ -20,6 +20,7 @@ import com.mhd.oms.domain.reservationDeliveryDetailsLink.repository.facade.IRese
import com.mhd.oms.domain.reservationInMaterialDetail.repository.facade.IReservationInMaterialDetailService; import com.mhd.oms.domain.reservationInMaterialDetail.repository.facade.IReservationInMaterialDetailService;
import com.mhd.oms.domain.reservationInMaterialDetail.repository.po.ReservationInMaterialDetailPO; import com.mhd.oms.domain.reservationInMaterialDetail.repository.po.ReservationInMaterialDetailPO;
import com.mhd.oms.domain.reservationInMaterialDetail.repository.todo.ReservationInMaterialDetailDO; import com.mhd.oms.domain.reservationInMaterialDetail.repository.todo.ReservationInMaterialDetailDO;
import com.mhd.oms.domain.reservationMaterialInventory.repository.po.ReservationMaterialInventoryPO;
import com.mhd.oms.domain.reservationOutMaterialDetail.repository.facade.IReservationOutMaterialDetailService; import com.mhd.oms.domain.reservationOutMaterialDetail.repository.facade.IReservationOutMaterialDetailService;
import com.mhd.oms.domain.reservationOutMaterialDetail.repository.todo.ReservationOutMaterialDetailDO; import com.mhd.oms.domain.reservationOutMaterialDetail.repository.todo.ReservationOutMaterialDetailDO;
import com.mhd.oms.domain.reservationStockInOrder.entity.ReservationStockInOrder; import com.mhd.oms.domain.reservationStockInOrder.entity.ReservationStockInOrder;
@@ -32,6 +33,7 @@ import com.mhd.oms.domain.reservationStockInOrder.repository.po.MaterialBaseInfo
import com.mhd.oms.domain.reservationStockInOrder.repository.po.ReservationStockInOrderPO; import com.mhd.oms.domain.reservationStockInOrder.repository.po.ReservationStockInOrderPO;
import com.mhd.oms.domain.reservationStockInOrder.repository.todo.ReservationStockInOrderDO; import com.mhd.oms.domain.reservationStockInOrder.repository.todo.ReservationStockInOrderDO;
import com.mhd.oms.domain.reservationStockInOrder.repository.vo.*; import com.mhd.oms.domain.reservationStockInOrder.repository.vo.*;
import com.mhd.oms.domain.reservationStockInOrder.service.ReservationStockInOrderDomainService;
import com.mhd.oms.domain.reservationStockOutOrder.entity.ReservationStockOutOrder; import com.mhd.oms.domain.reservationStockOutOrder.entity.ReservationStockOutOrder;
import com.mhd.oms.domain.reservationStockOutOrder.repository.facade.IReservationStockOutOrderService; import com.mhd.oms.domain.reservationStockOutOrder.repository.facade.IReservationStockOutOrderService;
import com.mhd.oms.domain.reservationStockOutOrder.repository.mapper.ReservationStockOutOrderMapper; import com.mhd.oms.domain.reservationStockOutOrder.repository.mapper.ReservationStockOutOrderMapper;
@@ -83,6 +85,8 @@ public class ReservationStockInOrderImpl extends ServiceImpl<ReservationStockInO
private SystemServiceFeign systemServiceFeign; private SystemServiceFeign systemServiceFeign;
@Autowired @Autowired
private IReservationInMaterialDetailService materialDetailService; private IReservationInMaterialDetailService materialDetailService;
@Autowired
private ReservationStockInOrderDomainService reservationStockInOrderDomainService;
/** /**
* 查询入库单列表 * 查询入库单列表
@@ -192,7 +196,7 @@ public class ReservationStockInOrderImpl extends ServiceImpl<ReservationStockInO
List<Map<String,Object>> shipperIds = new ArrayList<>(); List<Map<String,Object>> shipperIds = new ArrayList<>();
Set<Long> processedShipperIds = new HashSet<>(); Set<Long> processedShipperIds = new HashSet<>();
for (ProductDetail productDetail : productDetailList) { for (ProductDetail productDetail : productDetailList) {
MaterialBaseInfoPO materialBaseInfoPO = stockInOrderMapper.getByCode(productDetail.getProductCode()); MaterialBaseInfoPO materialBaseInfoPO = stockInOrderMapper.getByCode(productDetail.getProductCode(),loginUser.getUserPo().getOrganizationId());
if (materialBaseInfoPO != null && materialBaseInfoPO.getShipperId() != null) { if (materialBaseInfoPO != null && materialBaseInfoPO.getShipperId() != null) {
Long shipperId = materialBaseInfoPO.getShipperId(); Long shipperId = materialBaseInfoPO.getShipperId();
if (processedShipperIds.add(shipperId)) { if (processedShipperIds.add(shipperId)) {
@@ -216,7 +220,10 @@ public class ReservationStockInOrderImpl extends ServiceImpl<ReservationStockInO
} }
ReservationStockOutOrderDO reservationStockOutOrderDO = new ReservationStockOutOrderDO(); ReservationStockOutOrderDO reservationStockOutOrderDO = new ReservationStockOutOrderDO();
reservationStockOutOrderDO.setOutOrderNumber(OrderSequence.getOrderCode("CK")); // 生成出库业务单号
String orderNumber = reservationStockOutOrderApplicationService.generateReserveOrderNumber();
reservationStockOutOrderDO.setOutOrderNumber(orderNumber);
reservationStockOutOrderDO.setBusinessOrderNo(orderNumber);
// 货主信息有货品明细时从解析结果取无货品明细时从登录用户取 // 货主信息有货品明细时从解析结果取无货品明细时从登录用户取
if (!shipperIds.isEmpty()) { if (!shipperIds.isEmpty()) {
reservationStockOutOrderDO.setShipperId((Long) shipperIds.get(0).get("shipperId")); reservationStockOutOrderDO.setShipperId((Long) shipperIds.get(0).get("shipperId"));
@@ -254,9 +261,38 @@ public class ReservationStockInOrderImpl extends ServiceImpl<ReservationStockInO
for (ProductDetail productDetail : productDetailList) { for (ProductDetail productDetail : productDetailList) {
ReservationOutMaterialDetailDO reservationOutMaterialDetailDO = new ReservationOutMaterialDetailDO(); ReservationOutMaterialDetailDO reservationOutMaterialDetailDO = new ReservationOutMaterialDetailDO();
reservationOutMaterialDetailDO.setOutOrderNumber(reservationStockOutOrderDO.getOutOrderNumber()); reservationOutMaterialDetailDO.setOutOrderNumber(reservationStockOutOrderDO.getOutOrderNumber());
MaterialBaseInfoPO materialBaseInfoPO = stockInOrderMapper.getByCode(productDetail.getProductCode()); MaterialBaseInfoPO materialBaseInfoPO = stockInOrderMapper.getByCode(productDetail.getProductCode(),loginUser.getUserPo().getOrganizationId());
reservationOutMaterialDetailDO.setQuantity(new BigDecimal(productDetail.getPieceCount()).setScale(2, BigDecimal.ROUND_HALF_UP)); reservationOutMaterialDetailDO.setQuantity(new BigDecimal(productDetail.getPieceCount()).setScale(2, BigDecimal.ROUND_HALF_UP));
if (materialBaseInfoPO != null) { if (materialBaseInfoPO != null) {
Long materialBaseInfoId = materialBaseInfoPO.getMaterialBaseInfoId();
List<ReservationMaterialInventoryPO> reservationMaterialInventoryPOS = stockInOrderMapper.getkcId(materialBaseInfoId, new BigDecimal(productDetail.getPieceCount()).setScale(2, BigDecimal.ROUND_HALF_UP));
if (reservationMaterialInventoryPOS != null&&reservationMaterialInventoryPOS.size() > 0) {
ReservationMaterialInventoryPO reservationMaterialInventoryPO = reservationMaterialInventoryPOS.get(0);
Long materialInventoryId = reservationMaterialInventoryPO.getMaterialInventoryId();
String batchNumber = reservationMaterialInventoryPO.getBatchNumber();
String lotNumber = reservationMaterialInventoryPO.getLotNumber();
Long warehouseId = reservationMaterialInventoryPO.getWarehouseId();
String warehouseCode = reservationMaterialInventoryPO.getWarehouseCode();
String warehouseName = reservationMaterialInventoryPO.getWarehouseName();
String inOrderNumber = reservationMaterialInventoryPO.getInOrderNumber();
BigDecimal inventoryQuantity = reservationMaterialInventoryPO.getInventoryQuantity();
String unit = reservationMaterialInventoryPO.getUnit();
String unitName = reservationMaterialInventoryPO.getUnitName();
reservationOutMaterialDetailDO.setMaterialInventoryId(materialInventoryId);
reservationOutMaterialDetailDO.setBatchNumber(batchNumber);
reservationOutMaterialDetailDO.setLotNo(lotNumber);
reservationOutMaterialDetailDO.setWarehouseId(warehouseId);
reservationOutMaterialDetailDO.setWarehouseCode(warehouseCode);
reservationOutMaterialDetailDO.setWarehouseName(warehouseName);
reservationOutMaterialDetailDO.setInOrderNumber(inOrderNumber);
reservationOutMaterialDetailDO.setStockQuantity(inventoryQuantity);
reservationOutMaterialDetailDO.setUnit(unit);
reservationOutMaterialDetailDO.setStockUnit(unitName);
reservationOutMaterialDetailDO.setInventoryQuantity(inventoryQuantity);
reservationOutMaterialDetailDO.setUnitName(unitName);
} else {
throw new RuntimeException("物料批次库存数量少于出库数量!");
}
reservationOutMaterialDetailDO.setMaterialBaseInfoId(materialBaseInfoPO.getMaterialBaseInfoId()); reservationOutMaterialDetailDO.setMaterialBaseInfoId(materialBaseInfoPO.getMaterialBaseInfoId());
reservationOutMaterialDetailDO.setMaterialCode(materialBaseInfoPO.getMaterialCode()); reservationOutMaterialDetailDO.setMaterialCode(materialBaseInfoPO.getMaterialCode());
reservationOutMaterialDetailDO.setMaterialName(materialBaseInfoPO.getMaterialName()); reservationOutMaterialDetailDO.setMaterialName(materialBaseInfoPO.getMaterialName());
@@ -360,7 +396,7 @@ public class ReservationStockInOrderImpl extends ServiceImpl<ReservationStockInO
List<Map<String,Object>> shipperIds = new ArrayList<>(); List<Map<String,Object>> shipperIds = new ArrayList<>();
Set<Long> processedShipperIds = new HashSet<>(); Set<Long> processedShipperIds = new HashSet<>();
for (StockInProductDetail productDetail : productDetailList) { for (StockInProductDetail productDetail : productDetailList) {
MaterialBaseInfoPO materialBaseInfoPO = stockInOrderMapper.getByCode(productDetail.getProductCode()); MaterialBaseInfoPO materialBaseInfoPO = stockInOrderMapper.getByCode(productDetail.getProductCode(),loginUser.getUserPo().getOrganizationId());
if (materialBaseInfoPO != null && materialBaseInfoPO.getShipperId() != null) { if (materialBaseInfoPO != null && materialBaseInfoPO.getShipperId() != null) {
Long shipperId = materialBaseInfoPO.getShipperId(); Long shipperId = materialBaseInfoPO.getShipperId();
if (processedShipperIds.add(shipperId)) { if (processedShipperIds.add(shipperId)) {
@@ -373,7 +409,10 @@ public class ReservationStockInOrderImpl extends ServiceImpl<ReservationStockInO
} }
} }
ReservationStockInOrderDO reservationStockInOrderDO = new ReservationStockInOrderDO(); ReservationStockInOrderDO reservationStockInOrderDO = new ReservationStockInOrderDO();
reservationStockInOrderDO.setInOrderNumber(OrderSequence.getOrderCode("RK")); // 生成业务单号
String orderNumber = reservationStockInOrderDomainService.generateReserveOrderNumber();
reservationStockInOrderDO.setInOrderNumber(orderNumber);
reservationStockInOrderDO.setBusinessOrderNo(orderNumber);
reservationStockInOrderDO.setOrganizationId(loginUser.getUserPo().getOrganizationId()); reservationStockInOrderDO.setOrganizationId(loginUser.getUserPo().getOrganizationId());
reservationStockInOrderDO.setOrganizationName(loginUser.getUserPo().getOrganizationName()); reservationStockInOrderDO.setOrganizationName(loginUser.getUserPo().getOrganizationName());
reservationStockInOrderDO.setTopOrganizationId(loginUser.getUserPo().getTopOrganizationId()); reservationStockInOrderDO.setTopOrganizationId(loginUser.getUserPo().getTopOrganizationId());
@@ -399,7 +438,6 @@ public class ReservationStockInOrderImpl extends ServiceImpl<ReservationStockInO
reservationStockInOrderDO.setWarehouseDate(stockInHeader.getStockInDate()); reservationStockInOrderDO.setWarehouseDate(stockInHeader.getStockInDate());
reservationStockInOrderDO.setStorageTime(stockInHeader.getStockInDate()); reservationStockInOrderDO.setStorageTime(stockInHeader.getStockInDate());
reservationStockInOrderDO.setExpectTime(stockInHeader.getStockInDate()); reservationStockInOrderDO.setExpectTime(stockInHeader.getStockInDate());
reservationStockInOrderDO.setBusinessOrderNo(stockInHeader.getOrderNo());
reservationStockInOrderDO.setReservationOrderSource("数据导入"); reservationStockInOrderDO.setReservationOrderSource("数据导入");
List<ReservationInMaterialDetailDO> reservationInMaterialDetailDOList = new ArrayList<>(); List<ReservationInMaterialDetailDO> reservationInMaterialDetailDOList = new ArrayList<>();
int index = 1; int index = 1;
@@ -412,7 +450,7 @@ public class ReservationStockInOrderImpl extends ServiceImpl<ReservationStockInO
reservationInMaterialDetailDO.setCreateBy(loginUser.getUserPo().getUserId()); reservationInMaterialDetailDO.setCreateBy(loginUser.getUserPo().getUserId());
reservationInMaterialDetailDO.setCreateByName(loginUser.getUserPo().getUserName()); reservationInMaterialDetailDO.setCreateByName(loginUser.getUserPo().getUserName());
reservationInMaterialDetailDO.setCreateTime(new Date()); reservationInMaterialDetailDO.setCreateTime(new Date());
MaterialBaseInfoPO materialBaseInfoPO = stockInOrderMapper.getByCode(stockInProductDetail.getProductCode()); MaterialBaseInfoPO materialBaseInfoPO = stockInOrderMapper.getByCode(stockInProductDetail.getProductCode(),loginUser.getUserPo().getOrganizationId());
reservationInMaterialDetailDO.setQuantity(new BigDecimal(stockInProductDetail.getBoxCount()).setScale(2, BigDecimal.ROUND_HALF_UP)); reservationInMaterialDetailDO.setQuantity(new BigDecimal(stockInProductDetail.getBoxCount()).setScale(2, BigDecimal.ROUND_HALF_UP));
if (materialBaseInfoPO != null) { if (materialBaseInfoPO != null) {
reservationInMaterialDetailDO.setMaterialBaseInfoId(materialBaseInfoPO.getMaterialBaseInfoId()); reservationInMaterialDetailDO.setMaterialBaseInfoId(materialBaseInfoPO.getMaterialBaseInfoId());
@@ -469,7 +507,8 @@ public class ReservationStockInOrderImpl extends ServiceImpl<ReservationStockInO
@Transactional(rollbackFor = Exception.class) @Transactional(rollbackFor = Exception.class)
public Boolean insertDomain(ReservationStockInOrderDO stockInOrderDO) { public Boolean insertDomain(ReservationStockInOrderDO stockInOrderDO) {
if (stockInOrderDO.getInOrderNumber() == null) { if (stockInOrderDO.getInOrderNumber() == null) {
stockInOrderDO.setInOrderNumber(OrderSequence.getOrderCode("RK")); stockInOrderDO.setInOrderNumber(reservationStockInOrderDomainService.generateReserveOrderNumber());
stockInOrderDO.setBusinessOrderNo(stockInOrderDO.getInOrderNumber());
} }
// //统计总计划数 // //统计总计划数
BigDecimal quantity = stockInOrderDO.getMaterialDetailList().stream().map(ReservationInMaterialDetailDO::getQuantity).filter(Objects::nonNull).reduce(BigDecimal.ZERO, BigDecimal::add); BigDecimal quantity = stockInOrderDO.getMaterialDetailList().stream().map(ReservationInMaterialDetailDO::getQuantity).filter(Objects::nonNull).reduce(BigDecimal.ZERO, BigDecimal::add);
@@ -2286,4 +2286,11 @@ public class ReservationStockInOrderApplicationService {
return filteredList; return filteredList;
} }
public String generateReserveOrderNumber() {
return stockInOrderDomainService.generateReserveOrderNumber();
}
public String generateReserveOrderNumber1() {
return stockInOrderDomainService.generateReserveOrderNumber1();
}
} }
@@ -17,6 +17,7 @@ import com.mhd.oms.domain.executionInMaterialDetail.entity.ExecutionInMaterialDe
import com.mhd.oms.domain.executionInMaterialDetail.repository.facade.IExecutionInMaterialDetailService; import com.mhd.oms.domain.executionInMaterialDetail.repository.facade.IExecutionInMaterialDetailService;
import com.mhd.oms.domain.executionStockInOrder.entity.ExecutionStockInOrder; import com.mhd.oms.domain.executionStockInOrder.entity.ExecutionStockInOrder;
import com.mhd.oms.domain.executionStockInOrder.repository.facade.IExecutionStockInOrderService; import com.mhd.oms.domain.executionStockInOrder.repository.facade.IExecutionStockInOrderService;
import com.mhd.oms.domain.executionStockInOrder.repository.mapper.ExecutionStockInOrderMapper;
import com.mhd.oms.domain.executionStockInOrder.repository.todo.ExecutionStockInOrderDO; import com.mhd.oms.domain.executionStockInOrder.repository.todo.ExecutionStockInOrderDO;
import com.mhd.oms.domain.executionStockInOrder.service.ExecutionStockInOrderApplicationService; import com.mhd.oms.domain.executionStockInOrder.service.ExecutionStockInOrderApplicationService;
import com.mhd.oms.domain.reservationInMaterialDetail.entity.ReservationInMaterialDetail; import com.mhd.oms.domain.reservationInMaterialDetail.entity.ReservationInMaterialDetail;
@@ -37,6 +38,7 @@ import com.mhd.oms.domain.reservationStockOutOrder.entity.ReservationStockOutOrd
import com.mhd.oms.domain.reservationStockOutOrder.repository.facade.IReservationStockOutOrderService; import com.mhd.oms.domain.reservationStockOutOrder.repository.facade.IReservationStockOutOrderService;
import com.mhd.oms.domain.reserveInMaterialDetail.entity.ReserveInMaterialDetail; import com.mhd.oms.domain.reserveInMaterialDetail.entity.ReserveInMaterialDetail;
import com.mhd.oms.domain.reserveStockInOrder.entity.ReserveStockInOrder; import com.mhd.oms.domain.reserveStockInOrder.entity.ReserveStockInOrder;
import com.mhd.oms.domain.reserveStockInOrder.repository.mapper.ReserveStockInOrderMapper;
import com.mhd.system.api.SystemServiceFeign; import com.mhd.system.api.SystemServiceFeign;
import com.mhd.system.api.WmsServiceFeign; import com.mhd.system.api.WmsServiceFeign;
import com.mhd.system.api.domain.*; import com.mhd.system.api.domain.*;
@@ -85,6 +87,10 @@ public class ReservationStockInOrderDomainService {
private ExecutionStockInOrderApplicationService stockInOrderApplicationService; private ExecutionStockInOrderApplicationService stockInOrderApplicationService;
@Autowired @Autowired
private BusinessDocumentOrderMapper businessDocumentOrderMapper; private BusinessDocumentOrderMapper businessDocumentOrderMapper;
@Autowired
private ExecutionStockInOrderMapper executionStockInOrderMapper;
@Autowired
private ReserveStockInOrderMapper reserveStockInOrderMapper;
/** /**
* 分页查询入库单列表 * 分页查询入库单列表
@@ -100,7 +106,8 @@ public class ReservationStockInOrderDomainService {
@Transactional(rollbackFor = Exception.class) @Transactional(rollbackFor = Exception.class)
public Boolean insert(ReservationStockInOrderDO stockInOrderDO) { public Boolean insert(ReservationStockInOrderDO stockInOrderDO) {
if (stockInOrderDO.getInOrderNumber() == null) { if (stockInOrderDO.getInOrderNumber() == null) {
stockInOrderDO.setInOrderNumber(OrderSequence.getOrderCode("RK")); stockInOrderDO.setInOrderNumber(generateReserveOrderNumber());
stockInOrderDO.setBusinessOrderNo(stockInOrderDO.getInOrderNumber());
} }
// //设置默认值 // //设置默认值
// setDefaultValues(stockInOrderDO); // setDefaultValues(stockInOrderDO);
@@ -534,11 +541,7 @@ public class ReservationStockInOrderDomainService {
reservationStockInOrder.setWarehouseCode(warehouseCode); reservationStockInOrder.setWarehouseCode(warehouseCode);
reservationStockInOrder.setWarehouseName(warehouseName); reservationStockInOrder.setWarehouseName(warehouseName);
reservationStockInOrder.setBusinessInOrderNumber(inOrderNumber); reservationStockInOrder.setBusinessInOrderNumber(inOrderNumber);
if (materialDetailGroupByWarehouse!=null&&materialDetailGroupByWarehouse.size()>1) { reservationStockInOrder.setInOrderNumber(generateExecutionOrderNumber(warehouseCode));
reservationStockInOrder.setInOrderNumber(OrderSequence.getOrderCode("RK"));
} else {
reservationStockInOrder.setInOrderNumber(inOrderNumber);
}
List<ExecutionInMaterialDetail> inMaterialDetailList = new ArrayList<>(); List<ExecutionInMaterialDetail> inMaterialDetailList = new ArrayList<>();
int index = 1; int index = 1;
@@ -691,11 +694,7 @@ public class ReservationStockInOrderDomainService {
reservationStockInOrder.setWarehouseCode(warehouseCode); reservationStockInOrder.setWarehouseCode(warehouseCode);
reservationStockInOrder.setWarehouseName(warehouseName); reservationStockInOrder.setWarehouseName(warehouseName);
reservationStockInOrder.setBusinessInOrderNumber(inOrderNumber); reservationStockInOrder.setBusinessInOrderNumber(inOrderNumber);
if (materialDetailGroupByWarehouse!=null&&materialDetailGroupByWarehouse.size()>1) { reservationStockInOrder.setInOrderNumber(generateExecutionOrderNumber(warehouseCode));
reservationStockInOrder.setInOrderNumber(OrderSequence.getOrderCode("RK"));
} else {
reservationStockInOrder.setInOrderNumber(inOrderNumber);
}
List<ExecutionInMaterialDetail> inMaterialDetailList = new ArrayList<>(); List<ExecutionInMaterialDetail> inMaterialDetailList = new ArrayList<>();
int index = 1; int index = 1;
@@ -1212,4 +1211,49 @@ public class ReservationStockInOrderDomainService {
return stockInOrderService.queryNoticePrintDetail(stockInOrderDO); return stockInOrderService.queryNoticePrintDetail(stockInOrderDO);
} }
/**
* 生成执行入库单号仓库代码简称 + YYMMDD + 当日累加3位不足补零
*/
public String generateExecutionOrderNumber(String warehouseCode) {
SimpleDateFormat sdf = new SimpleDateFormat("yyMMdd");
String datePart = sdf.format(new Date());
String prefix = "R" + warehouseCode + datePart;
int todayCount = executionStockInOrderMapper.countByOrderNumberPrefix(prefix);
String seq = String.format("%03d", todayCount + 1);
return prefix + seq;
}
/**
* 生成入库预约单号
*/
public String generateReserveOrderNumber() {
SimpleDateFormat sdf = new SimpleDateFormat("yyMMdd");
String datePart = sdf.format(new Date());
String prefix = "R" + datePart;
int todayCount = reservationStockInOrderMapper.countByOrderNumberPrefix(prefix);
String seq = String.format("%03d", todayCount + 1);
return prefix + seq;
}
public String generateReserveOrderNumber1() {
SimpleDateFormat sdf = new SimpleDateFormat("yyMMdd");
String datePart = sdf.format(new Date());
String prefix = "R" + datePart;
List<String> orderNumber1 = reservationStockInOrderMapper.generateReserveOrderNumber1(prefix);
List<String> orderNumber2 = reserveStockInOrderMapper.generateReserveOrderNumber1(prefix);
List<String> allOrders = new ArrayList<>();
allOrders.addAll(orderNumber1);
allOrders.addAll(orderNumber2);
int maxseq = 0;
for(String order:allOrders)
{
String numStr = order.substring(prefix.length());
int num = Integer.parseInt(numStr);
if(num > maxseq){
maxseq = num;
}
}
String seq = String.format("%03d", maxseq + 1);
return prefix + seq;
}
} }
@@ -37,4 +37,8 @@ public interface ReservationStockOutOrderMapper extends BaseMapper<ReservationSt
List<ReservationOutMaterialDetailPO> queryOutStockNoticePrintDetail(ReservationStockOutOrderDO stockOutOrderDO); List<ReservationOutMaterialDetailPO> queryOutStockNoticePrintDetail(ReservationStockOutOrderDO stockOutOrderDO);
Long queryShipperId(@Param("userMemberCode") String userMemberCode,@Param("organizationId") Long organizationId); Long queryShipperId(@Param("userMemberCode") String userMemberCode,@Param("organizationId") Long organizationId);
int countByOrderNumberPrefix(@Param("prefix") String prefix);
List<String> generateReserveOrderNumber1(@Param("prefix") String prefix);
} }
@@ -1743,4 +1743,11 @@ public class ReservationStockOutOrderApplicationService {
return filteredList; return filteredList;
} }
public String generateReserveOrderNumber() {
return stockOutOrderDomainService.generateReserveOrderNumber();
}
public String generateReserveOrderNumber1() {
return stockOutOrderDomainService.generateReserveOrderNumber1();
}
} }
@@ -27,6 +27,7 @@ import com.mhd.oms.domain.executionOutMaterialDetail.repository.facade.IExecutio
import com.mhd.oms.domain.executionStockInOrder.entity.ExecutionStockInOrder; import com.mhd.oms.domain.executionStockInOrder.entity.ExecutionStockInOrder;
import com.mhd.oms.domain.executionStockOutOrder.entity.ExecutionStockOutOrder; import com.mhd.oms.domain.executionStockOutOrder.entity.ExecutionStockOutOrder;
import com.mhd.oms.domain.executionStockOutOrder.repository.facade.IExecutionStockOutOrderService; import com.mhd.oms.domain.executionStockOutOrder.repository.facade.IExecutionStockOutOrderService;
import com.mhd.oms.domain.executionStockOutOrder.repository.mapper.ExecutionStockOutOrderMapper;
import com.mhd.oms.domain.executionStockOutOrder.repository.todo.ExecutionStockOutOrderDO; import com.mhd.oms.domain.executionStockOutOrder.repository.todo.ExecutionStockOutOrderDO;
import com.mhd.oms.domain.executionStockOutOrder.service.ExecutionStockOutOrderApplicationService; import com.mhd.oms.domain.executionStockOutOrder.service.ExecutionStockOutOrderApplicationService;
import com.mhd.oms.domain.reservationDeliveryDetailsLink.entity.ReservationDeliveryDetailsLink; import com.mhd.oms.domain.reservationDeliveryDetailsLink.entity.ReservationDeliveryDetailsLink;
@@ -47,8 +48,10 @@ import com.mhd.oms.domain.reservationStockInOrder.repository.po.MaterialBaseInfo
import com.mhd.oms.domain.reservationStockInOrder.repository.todo.ReservationStockInOrderDO; import com.mhd.oms.domain.reservationStockInOrder.repository.todo.ReservationStockInOrderDO;
import com.mhd.oms.domain.reservationStockOutOrder.entity.ReservationStockOutOrder; import com.mhd.oms.domain.reservationStockOutOrder.entity.ReservationStockOutOrder;
import com.mhd.oms.domain.reservationStockOutOrder.repository.facade.IReservationStockOutOrderService; import com.mhd.oms.domain.reservationStockOutOrder.repository.facade.IReservationStockOutOrderService;
import com.mhd.oms.domain.reservationStockOutOrder.repository.mapper.ReservationStockOutOrderMapper;
import com.mhd.oms.domain.reservationStockOutOrder.repository.po.ReservationStockOutOrderPO; import com.mhd.oms.domain.reservationStockOutOrder.repository.po.ReservationStockOutOrderPO;
import com.mhd.oms.domain.reservationStockOutOrder.repository.todo.ReservationStockOutOrderDO; import com.mhd.oms.domain.reservationStockOutOrder.repository.todo.ReservationStockOutOrderDO;
import com.mhd.oms.domain.reserveStockOutOrder.repository.mapper.ReserveStockOutOrderMapper;
import com.mhd.system.api.SystemServiceFeign; import com.mhd.system.api.SystemServiceFeign;
import com.mhd.system.api.WmsServiceFeign; import com.mhd.system.api.WmsServiceFeign;
import com.mhd.system.api.domain.*; import com.mhd.system.api.domain.*;
@@ -62,6 +65,7 @@ import org.springframework.util.CollectionUtils;
import javax.annotation.Resource; import javax.annotation.Resource;
import java.math.BigDecimal; import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.*; import java.util.*;
import java.util.stream.Collectors; import java.util.stream.Collectors;
@@ -95,6 +99,8 @@ public class ReservationStockOutOrderDomainService {
private ExecuteOrderMapper executeOrderMapper; private ExecuteOrderMapper executeOrderMapper;
@Autowired @Autowired
private ExecutionStockOutOrderApplicationService stockOutOrderApplicationService; private ExecutionStockOutOrderApplicationService stockOutOrderApplicationService;
@Autowired
private ExecutionStockOutOrderMapper executionStockOutOrderMapper;
@Resource @Resource
private SystemServiceFeign systemServiceFeign; private SystemServiceFeign systemServiceFeign;
@Resource @Resource
@@ -105,6 +111,10 @@ public class ReservationStockOutOrderDomainService {
private IBusinessDeliveryDetailsLinkService businessDeliveryDetailsLinkService; private IBusinessDeliveryDetailsLinkService businessDeliveryDetailsLinkService;
@Autowired @Autowired
private BusinessDeliveryDetailsLinkMapper businessDeliveryDetailsLinkMapper; private BusinessDeliveryDetailsLinkMapper businessDeliveryDetailsLinkMapper;
@Autowired
private ReservationStockOutOrderMapper reservationStockOutOrderMapper;
@Autowired
private ReserveStockOutOrderMapper reserveStockOutOrderMapper;
/** /**
* 分页查询出库单列表 * 分页查询出库单列表
@@ -120,7 +130,8 @@ public class ReservationStockOutOrderDomainService {
@Transactional(rollbackFor = Exception.class) @Transactional(rollbackFor = Exception.class)
public Boolean insert(ReservationStockOutOrderDO stockOutOrderDO) { public Boolean insert(ReservationStockOutOrderDO stockOutOrderDO) {
if (stockOutOrderDO.getOutOrderNumber() == null) { if (stockOutOrderDO.getOutOrderNumber() == null) {
stockOutOrderDO.setOutOrderNumber(OrderSequence.getOrderCode("CK")); stockOutOrderDO.setOutOrderNumber(generateReserveOrderNumber());
stockOutOrderDO.setBusinessOrderNo(stockOutOrderDO.getOutOrderNumber());
} }
// update / batchInsert 一致前端传计划数量为 quantity outboundQuantity // update / batchInsert 一致前端传计划数量为 quantity outboundQuantity
setMaterialDetailInfo(stockOutOrderDO); setMaterialDetailInfo(stockOutOrderDO);
@@ -385,11 +396,8 @@ public class ReservationStockOutOrderDomainService {
// reservationStockInOrder.setTopOrganizationId(topOrgId); // reservationStockInOrder.setTopOrganizationId(topOrgId);
reservationStockInOrder.setBusinessOutOrderNumber(inOrderNumber); reservationStockInOrder.setBusinessOutOrderNumber(inOrderNumber);
if (materialDetailGroupByWarehouse!=null&&materialDetailGroupByWarehouse.size()>1) { reservationStockInOrder.setOutOrderNumber(generateExecutionOrderNumber(warehouseCode));
reservationStockInOrder.setOutOrderNumber(OrderSequence.getOrderCode("CK"));
} else {
reservationStockInOrder.setOutOrderNumber(inOrderNumber);
}
List<ExecutionOutMaterialDetail> inMaterialDetailList = new ArrayList<>(); List<ExecutionOutMaterialDetail> inMaterialDetailList = new ArrayList<>();
for (ReservationOutMaterialDetail reservationOutMaterialDetail : details) { for (ReservationOutMaterialDetail reservationOutMaterialDetail : details) {
@@ -513,11 +521,7 @@ public class ReservationStockOutOrderDomainService {
reservationStockInOrder.setWarehouseCode(warehouseCode); reservationStockInOrder.setWarehouseCode(warehouseCode);
reservationStockInOrder.setWarehouseName(warehouseName); reservationStockInOrder.setWarehouseName(warehouseName);
reservationStockInOrder.setBusinessOutOrderNumber(inOrderNumber); reservationStockInOrder.setBusinessOutOrderNumber(inOrderNumber);
if (materialDetailGroupByWarehouse!=null&&materialDetailGroupByWarehouse.size()>1) { reservationStockInOrder.setOutOrderNumber(generateExecutionOrderNumber(warehouseCode));
reservationStockInOrder.setOutOrderNumber(OrderSequence.getOrderCode("CK"));
} else {
reservationStockInOrder.setOutOrderNumber(inOrderNumber);
}
List<ExecutionOutMaterialDetail> inMaterialDetailList = new ArrayList<>(); List<ExecutionOutMaterialDetail> inMaterialDetailList = new ArrayList<>();
for (ReservationOutMaterialDetail reservationOutMaterialDetail : details) { for (ReservationOutMaterialDetail reservationOutMaterialDetail : details) {
@@ -1051,4 +1055,49 @@ public class ReservationStockOutOrderDomainService {
} }
} }
/**
* 生成执行出库单号仓库代码简称 + YYMMDD + 当日累加3位不足补零
*/
public String generateExecutionOrderNumber(String warehouseCode) {
SimpleDateFormat sdf = new SimpleDateFormat("yyMMdd");
String datePart = sdf.format(new Date());
String prefix = "C" + warehouseCode + datePart;
int todayCount = executionStockOutOrderMapper.countByOrderNumberPrefix(prefix);
String seq = String.format("%03d", todayCount + 1);
return prefix + seq;
}
/**
* 生成出库预约单号
*/
public String generateReserveOrderNumber() {
SimpleDateFormat sdf = new SimpleDateFormat("yyMMdd");
String datePart = sdf.format(new Date());
String prefix = "C" + datePart;
int todayCount = reservationStockOutOrderMapper.countByOrderNumberPrefix(prefix);
String seq = String.format("%03d", todayCount + 1);
return prefix + seq;
}
public String generateReserveOrderNumber1() {
SimpleDateFormat sdf = new SimpleDateFormat("yyMMdd");
String datePart = sdf.format(new Date());
String prefix = "R" + datePart;
List<String> orderNumber1 = reservationStockOutOrderMapper.generateReserveOrderNumber1(prefix);
List<String> orderNumber2 = reserveStockOutOrderMapper.generateReserveOrderNumber1(prefix);
List<String> allOrders = new ArrayList<>();
allOrders.addAll(orderNumber1);
allOrders.addAll(orderNumber2);
int maxseq = 0;
for(String order:allOrders)
{
String numStr = order.substring(prefix.length());
int num = Integer.parseInt(numStr);
if(num > maxseq){
maxseq = num;
}
}
String seq = String.format("%03d", maxseq + 1);
return prefix + seq;
}
} }
@@ -2,6 +2,8 @@ package com.mhd.oms.domain.reserveStockInOrder.repository.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.core.mapper.BaseMapper;
//import com.mhd.oms.domain.reservationInMaterialDetail.repository.po.ReserveInMaterialDetailPO; //import com.mhd.oms.domain.reservationInMaterialDetail.repository.po.ReserveInMaterialDetailPO;
import com.mhd.common.core.domain.po.UserPo;
import com.mhd.common.core.domain.po.WarehousePO;
import com.mhd.oms.domain.reservationStockInOrder.repository.po.MaterialBaseInfoPO; import com.mhd.oms.domain.reservationStockInOrder.repository.po.MaterialBaseInfoPO;
import com.mhd.oms.domain.reservationStockInOrder.repository.po.MaterialGoodsRulePO; import com.mhd.oms.domain.reservationStockInOrder.repository.po.MaterialGoodsRulePO;
import com.mhd.oms.domain.reservationStockInOrder.repository.po.MaterialWarehouseControlPO; import com.mhd.oms.domain.reservationStockInOrder.repository.po.MaterialWarehouseControlPO;
@@ -46,4 +48,33 @@ public interface ReserveStockInOrderMapper extends BaseMapper<ReserveStockInOrde
List<ReserveInMaterialDetailPO> queryNoticePrintDetail(ReserveStockInOrderDO stockInOrderDO); List<ReserveInMaterialDetailPO> queryNoticePrintDetail(ReserveStockInOrderDO stockInOrderDO);
public String getJsbz(@Param("id") Long id); public String getJsbz(@Param("id") Long id);
int countByOrderNumberPrefix(@Param("prefix") String prefix);
List<String> generateReserveOrderNumber1(@Param("prefix") String prefix);
/**
* 根据货主名称查询用户老系统数据导入用
*/
List<UserPo> getShipperByName(@Param("name") String name);
/**
* 根据仓库名称查询仓库老系统数据导入用
*/
List<WarehousePO> getWarehouseByName(@Param("name") String name);
/**
* 根据仓库类型查询仓库老系统数据导入用1=干仓 2=冬仓
*/
List<WarehousePO> getWarehouseByType(@Param("warehouseType") String warehouseType);
/**
* 根据货主用户ID查询NC客户编码
*/
String getCustomerNcCodeByUserId(@Param("id") Long id);
/**
* 根据入库单号精确统计导入防重用
*/
int countByInOrderNumber(@Param("inOrderNumber") String inOrderNumber);
} }
@@ -1,12 +1,16 @@
package com.mhd.oms.domain.reserveStockInOrder.repository.util; package com.mhd.oms.domain.reserveStockInOrder.repository.util;
import com.alibaba.excel.EasyExcel; import com.alibaba.excel.EasyExcel;
import com.mhd.common.core.utils.StringUtils;
import com.mhd.oms.domain.reserveStockInOrder.repository.listener.ReservedInventoryListener; import com.mhd.oms.domain.reserveStockInOrder.repository.listener.ReservedInventoryListener;
import com.mhd.oms.domain.reserveStockInOrder.repository.vo.LegacyReserveInDetailVO;
import com.mhd.oms.domain.reserveStockInOrder.repository.vo.LegacyReserveInOrderVO;
import com.mhd.oms.domain.reserveStockInOrder.repository.vo.ReservedInventory; import com.mhd.oms.domain.reserveStockInOrder.repository.vo.ReservedInventory;
import org.springframework.web.multipart.MultipartFile; import org.springframework.web.multipart.MultipartFile;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.util.List; import java.util.List;
import java.util.stream.Collectors;
/** /**
* Excel解析工具类 * Excel解析工具类
@@ -56,6 +60,50 @@ public class ExcelParseUtil {
return dataList; return dataList;
} }
/**
* 解析老系统入库预约单列表Excel表头第1行数据从第2行开始
* @param file 上传的Excel文件
* @return 老系统入库预约单主表行列表
* @throws IOException 文件处理异常
*/
public static List<LegacyReserveInOrderVO> parseLegacyOrderExcel(MultipartFile file) throws IOException {
validateFile(file);
List<LegacyReserveInOrderVO> dataList;
try (InputStream inputStream = file.getInputStream()) {
dataList = EasyExcel.read(inputStream)
.head(LegacyReserveInOrderVO.class)
.sheet(0)
.headRowNumber(1)
.doReadSync();
}
// 过滤入库单号为空的无效行
return dataList.stream()
.filter(row -> row != null && StringUtils.isNotBlank(row.getInOrderNumber()))
.collect(Collectors.toList());
}
/**
* 解析老系统入库预约单明细列表Excel表头第1行数据从第2行开始
* @param file 上传的Excel文件
* @return 老系统入库预约单明细行列表
* @throws IOException 文件处理异常
*/
public static List<LegacyReserveInDetailVO> parseLegacyDetailExcel(MultipartFile file) throws IOException {
validateFile(file);
List<LegacyReserveInDetailVO> dataList;
try (InputStream inputStream = file.getInputStream()) {
dataList = EasyExcel.read(inputStream)
.head(LegacyReserveInDetailVO.class)
.sheet(0)
.headRowNumber(1)
.doReadSync();
}
// 过滤入库单号为空的无效行
return dataList.stream()
.filter(row -> row != null && StringUtils.isNotBlank(row.getInOrderNumber()))
.collect(Collectors.toList());
}
/** /**
* 验证Excel文件合法性 * 验证Excel文件合法性
*/ */
@@ -0,0 +1,77 @@
package com.mhd.oms.domain.reserveStockInOrder.repository.vo;
import com.alibaba.excel.annotation.ExcelProperty;
import com.mhd.oms.domain.reserveStockInOrder.repository.util.StringToBigDecimalConverter;
import com.mhd.oms.domain.reserveStockInOrder.repository.util.StringToDateConverter;
import lombok.Data;
import java.math.BigDecimal;
import java.util.Date;
/**
* 老系统入库预约单明细行
* 与老系统导出Excel入库预约单明细列表字段一一映射表头第1行数据从第2行开始
*/
@Data
public class LegacyReserveInDetailVO {
/**
* 入库单号必填与主表关联键
*/
@ExcelProperty(index = 0, value = "入库单号")
private String inOrderNumber;
/**
* 计划数量必填
*/
@ExcelProperty(index = 1, value = "计划数量", converter = StringToBigDecimalConverter.class)
private BigDecimal quantity;
/**
* 物料名称必填用于匹配新系统物料基础信息
*/
@ExcelProperty(index = 2, value = "物料名称")
private String materialName;
/**
* 单位名称
*/
@ExcelProperty(index = 3, value = "单位名称")
private String unitName;
/**
* 创建时间老系统
*/
@ExcelProperty(index = 4, value = "创建时间", converter = StringToDateConverter.class)
private Date createTime;
/**
* 修改时间老系统
*/
@ExcelProperty(index = 5, value = "修改时间", converter = StringToDateConverter.class)
private Date updateTime;
/**
* 创建人名称老系统
*/
@ExcelProperty(index = 6, value = "创建人名称")
private String createByName;
/**
* 修改人名称老系统
*/
@ExcelProperty(index = 7, value = "修改人名称")
private String updateByName;
/**
* 总净重(KG)
*/
@ExcelProperty(index = 8, value = "总净重(KG)", converter = StringToBigDecimalConverter.class)
private BigDecimal totalNetWeight;
/**
* 备注
*/
@ExcelProperty(index = 9, value = "备注")
private String remark;
}
@@ -0,0 +1,93 @@
package com.mhd.oms.domain.reserveStockInOrder.repository.vo;
import com.alibaba.excel.annotation.ExcelProperty;
import com.mhd.oms.domain.reserveStockInOrder.repository.util.StringToDateConverter;
import lombok.Data;
import java.util.Date;
/**
* 老系统入库预约单主表行
* 与老系统导出Excel入库预约单列表字段一一映射表头第1行数据从第2行开始
*/
@Data
public class LegacyReserveInOrderVO {
/**
* 入库单号必填与明细表关联键
*/
@ExcelProperty(index = 0, value = "入库单号")
private String inOrderNumber;
/**
* 入仓时间
*/
@ExcelProperty(index = 1, value = "入仓时间", converter = StringToDateConverter.class)
private Date warehouseDate;
/**
* 制单人
*/
@ExcelProperty(index = 2, value = "制单人")
private String documentCreator;
/**
* 制单时间
*/
@ExcelProperty(index = 3, value = "制单时间", converter = StringToDateConverter.class)
private Date documentDate;
/**
* 货主名称必填用于匹配新系统用户
*/
@ExcelProperty(index = 4, value = "货主名称")
private String shipperName;
/**
* 备注
*/
@ExcelProperty(index = 5, value = "备注")
private String remark;
/**
* 创建时间老系统
*/
@ExcelProperty(index = 6, value = "创建时间", converter = StringToDateConverter.class)
private Date createTime;
/**
* 修改时间老系统
*/
@ExcelProperty(index = 7, value = "修改时间", converter = StringToDateConverter.class)
private Date updateTime;
/**
* 创建人名称老系统
*/
@ExcelProperty(index = 8, value = "创建人名称")
private String createByName;
/**
* 修改人名称老系统
*/
@ExcelProperty(index = 9, value = "修改人名称")
private String updateByName;
/**
* 老系统仓库id跨系统id不可用仅做占位
*/
@ExcelProperty(index = 10, value = "仓库id")
private String oldWarehouseId;
/**
* 仓库名称用于匹配新系统仓库
*/
@ExcelProperty(index = 11, value = "仓库名称")
private String warehouseName;
/**
* 仓库类型1=干仓 2=冬仓用于仓库名称匹配兜底
*/
@ExcelProperty(index = 12, value = "仓库类型")
private String warehouseType;
}
@@ -5,6 +5,7 @@ import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson2.JSONObject; import com.alibaba.fastjson2.JSONObject;
import com.mhd.common.core.domain.po.UserPo; import com.mhd.common.core.domain.po.UserPo;
import com.mhd.common.core.domain.po.WarehousePO;
import com.mhd.common.core.enums.DictCode; import com.mhd.common.core.enums.DictCode;
import com.mhd.common.core.exception.ServiceException; import com.mhd.common.core.exception.ServiceException;
import com.mhd.common.core.utils.OrderSequence; import com.mhd.common.core.utils.OrderSequence;
@@ -16,15 +17,21 @@ import com.mhd.oms.domain.reservationMaterialInventory.repository.todo.MaterialB
import com.mhd.oms.domain.reservationStockInOrder.repository.mapper.ReservationStockInOrderMapper; import com.mhd.oms.domain.reservationStockInOrder.repository.mapper.ReservationStockInOrderMapper;
import com.mhd.oms.domain.reservationStockInOrder.repository.po.MaterialBaseInfoPO; import com.mhd.oms.domain.reservationStockInOrder.repository.po.MaterialBaseInfoPO;
import com.mhd.oms.domain.reserveInMaterialDetail.entity.ReserveInMaterialDetail; import com.mhd.oms.domain.reserveInMaterialDetail.entity.ReserveInMaterialDetail;
import com.mhd.oms.domain.reserveInMaterialDetail.repository.facade.IReserveInMaterialDetailService;
import com.mhd.oms.domain.reserveInMaterialDetail.repository.po.ReserveInMaterialDetailPO; import com.mhd.oms.domain.reserveInMaterialDetail.repository.po.ReserveInMaterialDetailPO;
import com.mhd.oms.domain.reserveInMaterialDetail.repository.todo.ReserveInMaterialDetailDO; import com.mhd.oms.domain.reserveInMaterialDetail.repository.todo.ReserveInMaterialDetailDO;
import com.mhd.oms.domain.reserveStockInOrder.entity.ReserveStockInOrder; import com.mhd.oms.domain.reserveStockInOrder.entity.ReserveStockInOrder;
import com.mhd.oms.domain.reserveStockInOrder.repository.facade.IReserveStockInOrderService;
import com.mhd.oms.domain.reserveStockInOrder.repository.listener.ValidationException;
import com.mhd.oms.domain.reserveStockInOrder.repository.mapper.ReserveStockInOrderMapper; import com.mhd.oms.domain.reserveStockInOrder.repository.mapper.ReserveStockInOrderMapper;
import com.mhd.oms.domain.reserveStockInOrder.repository.po.ReserveStockInOrderPO; import com.mhd.oms.domain.reserveStockInOrder.repository.po.ReserveStockInOrderPO;
import com.mhd.oms.domain.reserveStockInOrder.repository.todo.ReserveStockInOrderDO; import com.mhd.oms.domain.reserveStockInOrder.repository.todo.ReserveStockInOrderDO;
import com.mhd.oms.domain.reserveStockInOrder.repository.todo.ReserveStockInOrderDTO; import com.mhd.oms.domain.reserveStockInOrder.repository.todo.ReserveStockInOrderDTO;
import com.mhd.oms.domain.reserveStockInOrder.repository.vo.InAndOutListVo; import com.mhd.oms.domain.reserveStockInOrder.repository.vo.InAndOutListVo;
import com.mhd.oms.domain.reserveStockInOrder.repository.vo.LegacyReserveInDetailVO;
import com.mhd.oms.domain.reserveStockInOrder.repository.vo.LegacyReserveInOrderVO;
import com.mhd.oms.domain.reserveStockInOrder.repository.vo.ReservedInventory; import com.mhd.oms.domain.reserveStockInOrder.repository.vo.ReservedInventory;
import com.mhd.oms.domain.reserveStockOutOrder.repository.mapper.ReserveStockOutOrderMapper;
import com.mhd.system.api.SystemServiceFeign; import com.mhd.system.api.SystemServiceFeign;
import com.mhd.system.api.UserServiceFeign; import com.mhd.system.api.UserServiceFeign;
import com.mhd.system.api.WmsServiceFeign; import com.mhd.system.api.WmsServiceFeign;
@@ -38,6 +45,7 @@ import org.apache.poi.ss.usermodel.DateUtil;
import org.springframework.beans.BeanUtils; import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.math.BigDecimal; import java.math.BigDecimal;
import java.text.ParseException; import java.text.ParseException;
@@ -61,6 +69,8 @@ public class ReserveStockInOrderApplicationService {
@Autowired @Autowired
private ReserveStockInOrderMapper reserveStockInOrderMapper; private ReserveStockInOrderMapper reserveStockInOrderMapper;
@Autowired @Autowired
private ReserveStockOutOrderMapper reserveStockOutOrderMapper;
@Autowired
private ReservationMaterialInventoryMapper reservationMaterialInventoryMapper; private ReservationMaterialInventoryMapper reservationMaterialInventoryMapper;
@Autowired @Autowired
private UserServiceFeign userServiceFeign; private UserServiceFeign userServiceFeign;
@@ -70,6 +80,10 @@ public class ReserveStockInOrderApplicationService {
private WmsServiceFeign wmsServiceFeign; private WmsServiceFeign wmsServiceFeign;
@Autowired @Autowired
private ReservationStockInOrderMapper reservationStockInOrderMapper; private ReservationStockInOrderMapper reservationStockInOrderMapper;
@Autowired
private IReserveStockInOrderService stockInOrderService;
@Autowired
private IReserveInMaterialDetailService materialDetailService;
// @Autowired // @Autowired
// private IMaterialBaseInfoService materialBaseInfoService; // private IMaterialBaseInfoService materialBaseInfoService;
@@ -2039,6 +2053,241 @@ public class ReserveStockInOrderApplicationService {
insert(reserveStockInOrder); insert(reserveStockInOrder);
} }
/**
* 老系统入库预约单数据导入主表+明细两个Excel多单批量导入
* 老系统的id类字段不可用货主仓库物料均按名称匹配新系统基础数据
*/
@Transactional(rollbackFor = Exception.class)
public Map<String, Object> importLegacyData(List<LegacyReserveInOrderVO> orderList, List<LegacyReserveInDetailVO> detailList) {
if (orderList == null || orderList.isEmpty()) {
throw new ValidationException("入库预约单列表文件中没有有效数据");
}
if (detailList == null || detailList.isEmpty()) {
throw new ValidationException("入库预约单明细列表文件中没有有效数据");
}
// 明细按入库单号分组
Map<String, List<LegacyReserveInDetailVO>> detailGroupMap = new LinkedHashMap<>();
for (LegacyReserveInDetailVO detailRow : detailList) {
detailGroupMap.computeIfAbsent(detailRow.getInOrderNumber().trim(), k -> new ArrayList<>()).add(detailRow);
}
List<String> errorList = new ArrayList<>();
// 名称匹配结果缓存避免重复查库
Map<String, UserPo> shipperCache = new HashMap<>();
Map<String, WarehousePO> warehouseCache = new HashMap<>();
// 仓库类型 -> 仓库 缓存用于名称匹配失败时的兜底
Map<String, WarehousePO> warehouseTypeCache = new HashMap<>();
Map<String, MaterialBaseInfoPO> materialCache = new HashMap<>();
Set<String> orderNumberSet = new HashSet<>();
List<ReserveStockInOrderDO> stockInOrderList = new ArrayList<>();
int lotIndex = 1;
for (LegacyReserveInOrderVO orderRow : orderList) {
String orderNumber = orderRow.getInOrderNumber().trim();
if (!orderNumberSet.add(orderNumber)) {
errorList.add("入库单号【" + orderNumber + "】在主表文件中重复");
continue;
}
if (reserveStockInOrderMapper.countByInOrderNumber(orderNumber) > 0) {
errorList.add("入库单号【" + orderNumber + "】在系统中已存在,请勿重复导入");
continue;
}
// 按货主名称匹配用户查不到则用Excel中的名称兜底不阻断导入
UserPo shipper = null;
String shipperName = StringUtils.trimToEmpty(orderRow.getShipperName());
if (StringUtils.isBlank(shipperName)) {
errorList.add("入库单号【" + orderNumber + "】货主名称为空");
} else {
shipper = shipperCache.get(shipperName);
if (shipper == null) {
List<UserPo> userPoList = reserveStockInOrderMapper.getShipperByName(shipperName);
if (userPoList == null || userPoList.isEmpty()) {
errorList.add("入库单号【" + orderNumber + "】货主【" + shipperName + "】未找到对应用户,将仅以名称导入");
} else {
shipper = userPoList.get(0);
shipperCache.put(shipperName, shipper);
}
}
}
// 按仓库类型匹配仓库老系统仓库类型 1=干仓 2=冬仓查不到则用类型名兜底
String warehouseName = "";
WarehousePO warehouse = null;
String warehouseType = StringUtils.trimToEmpty(orderRow.getWarehouseType());
if (StringUtils.isNotBlank(warehouseType)) {
warehouse = warehouseTypeCache.get(warehouseType);
if (warehouse == null) {
List<WarehousePO> warehousePOList = reserveStockOutOrderMapper.getWarehouseByType(warehouseType);
if (warehousePOList == null || warehousePOList.isEmpty()) {
warehouseName = "1".equals(warehouseType) ? "干仓" : ("2".equals(warehouseType) ? "冻仓" : "");
errorList.add("出库单号【" + orderNumber + "】仓库类型【" + warehouseType + "】未找到对应仓库,将仅以名称导入");
warehouseTypeCache.put(warehouseType, null);
warehouse = null;
} else {
warehouse = warehousePOList.get(0);
warehouseName = warehouse.getWarehouseName();
warehouseTypeCache.put(warehouseType, warehouse);
}
}
}
// 明细匹配
List<LegacyReserveInDetailVO> detailRows = detailGroupMap.get(orderNumber);
if (detailRows == null || detailRows.isEmpty()) {
errorList.add("入库单号【" + orderNumber + "】在明细文件中没有明细数据");
continue;
}
List<ReserveInMaterialDetailDO> materialDetailList = new ArrayList<>();
for (LegacyReserveInDetailVO detailRow : detailRows) {
String materialName = StringUtils.trimToEmpty(detailRow.getMaterialName());
if (StringUtils.isBlank(materialName)) {
errorList.add("入库单号【" + orderNumber + "】存在物料名称为空的明细行");
continue;
}
// 按物料名称匹配物料基础信息查不到则用Excel中的名称兜底不阻断导入
MaterialBaseInfoPO materialBaseInfoPO = materialCache.get(materialName);
if (materialBaseInfoPO == null) {
List<MaterialBaseInfoPO> materialBaseInfoPOS = reserveStockInOrderMapper.getByName(materialName);
if (materialBaseInfoPOS == null || materialBaseInfoPOS.isEmpty()) {
errorList.add("入库单号【" + orderNumber + "】物料【" + materialName + "】未找到对应物料,将仅以名称导入");
} else {
materialBaseInfoPO = materialBaseInfoPOS.get(0);
materialCache.put(materialName, materialBaseInfoPO);
}
}
ReserveInMaterialDetailDO materialDetail = new ReserveInMaterialDetailDO();
if (materialBaseInfoPO != null) {
materialDetail.setMaterialBaseInfoId(materialBaseInfoPO.getMaterialBaseInfoId());
materialDetail.setMaterialCode(materialBaseInfoPO.getMaterialCode());
materialDetail.setUnitCode(materialBaseInfoPO.getUnitCode());
materialDetail.setUnitName(StringUtils.isNotBlank(materialBaseInfoPO.getUnitName()) ? materialBaseInfoPO.getUnitName() : detailRow.getUnitName());
} else {
// 未匹配到物料基础信息仅以Excel中的名称作为物料名称
materialDetail.setUnitName(detailRow.getUnitName());
}
materialDetail.setMaterialName(materialName);
materialDetail.setReserveMaterialName(materialName);
materialDetail.setQuantity(detailRow.getQuantity());
materialDetail.setReserveQuantity(detailRow.getQuantity());
materialDetail.setTotalNetWeight(detailRow.getTotalNetWeight());
materialDetail.setTotalGrossWeight(detailRow.getTotalNetWeight());
materialDetail.setRemark(detailRow.getRemark());
materialDetail.setContractFee(BigDecimal.ZERO);
materialDetail.setLotNo(generateDateSerialNumber() + "-" + lotIndex);
lotIndex++;
// if (shipper != null) {
materialDetail.setOrganizationId(2841L);
materialDetail.setOrganizationName("仓码");
materialDetail.setTopOrganizationId(2827L);
// }
// 创建人/修改人名称取老系统Excel中的值不使用当前登录人
materialDetail.setCreateTime(detailRow.getCreateTime() != null ? detailRow.getCreateTime() : new Date());
materialDetail.setCreateByName(detailRow.getCreateByName());
materialDetail.setUpdateTime(detailRow.getUpdateTime());
materialDetail.setUpdateByName(detailRow.getUpdateByName());
materialDetailList.add(materialDetail);
}
// 组装入库预约单
ReserveStockInOrderDO stockInOrderDO = new ReserveStockInOrderDO();
stockInOrderDO.setInOrderNumber(orderNumber);
stockInOrderDO.setBusinessOrderNo(orderNumber);
// 老系统历史数据状态直接置为最终状态已入库审核通过已完成
stockInOrderDO.setStatus(5);
stockInOrderDO.setAuditStatus(3);
stockInOrderDO.setIssueStatus(3);
stockInOrderDO.setOrderStatus("已确认");
stockInOrderDO.setStorageTime(orderRow.getWarehouseDate());
stockInOrderDO.setNeedTransport(0);
stockInOrderDO.setNeedCustomsDeclaration(0);
stockInOrderDO.setWarehouseDate(orderRow.getWarehouseDate());
stockInOrderDO.setExpectTime(orderRow.getWarehouseDate() != null ? orderRow.getWarehouseDate() : new Date());
stockInOrderDO.setDocumentDate(orderRow.getDocumentDate() != null ? orderRow.getDocumentDate() : new Date());
stockInOrderDO.setDocumentCreator(orderRow.getDocumentCreator());
stockInOrderDO.setRemark(orderRow.getRemark());
if (shipper != null) {
stockInOrderDO.setShipperId(shipper.getUserId());
stockInOrderDO.setShipperName(shipper.getUserName());
stockInOrderDO.setCustomerId(shipper.getUserId());
stockInOrderDO.setCustomerName(shipper.getUserName());
stockInOrderDO.setSalesmanId(String.valueOf(shipper.getUserId()));
stockInOrderDO.setSalesmanName(shipper.getUserName());
stockInOrderDO.setCustomerCode(reserveStockInOrderMapper.getCustomerNcCodeByUserId(shipper.getUserId()));
// stockInOrderDO.setOrganizationId(shipper.getOrganizationId());
// stockInOrderDO.setOrganizationName(shipper.getOrganizationName());
// stockInOrderDO.setTopOrganizationId(shipper.getTopOrganizationId());
} else {
// 货主未匹配到仅以Excel中的名称作为名称字段id/组织留空
stockInOrderDO.setShipperName(shipperName);
stockInOrderDO.setCustomerName(shipperName);
stockInOrderDO.setSalesmanName(shipperName);
}
stockInOrderDO.setOrganizationId(2841L);
stockInOrderDO.setOrganizationName("仓码");
stockInOrderDO.setTopOrganizationId(2827L);
if (warehouse != null) {
stockInOrderDO.setWarehouseId(warehouse.getWarehouseId());
stockInOrderDO.setWarehouseCode(warehouse.getWarehouseCode());
stockInOrderDO.setWarehouseName(warehouse.getWarehouseName());
} else if (StringUtils.isNotBlank(warehouseName)) {
// 仓库未匹配到仅以Excel中的名称作为仓库名称id/编码留空
stockInOrderDO.setWarehouseName(warehouseName);
}
// 创建人/修改人名称取老系统Excel中的值不使用当前登录人
stockInOrderDO.setCreateTime(orderRow.getCreateTime() != null ? orderRow.getCreateTime() : new Date());
stockInOrderDO.setCreateByName(orderRow.getCreateByName());
stockInOrderDO.setUpdateTime(orderRow.getUpdateTime());
stockInOrderDO.setUpdateByName(orderRow.getUpdateByName());
stockInOrderDO.setMaterialDetailList(materialDetailList);
stockInOrderList.add(stockInOrderDO);
}
// 明细文件中存在但主表文件中不存在的单号
for (String detailOrderNumber : detailGroupMap.keySet()) {
if (!orderNumberSet.contains(detailOrderNumber)) {
errorList.add("明细文件中入库单号【" + detailOrderNumber + "】在主表文件中不存在");
}
}
// 逐单入库即使有未匹配到基础数据的警告也不阻断错误信息随结果返回
// 直接走 MyBatis-Plus 入库绕过领域服务/应用服务层的参数补全逻辑避免货主/物料未匹配等场景报错
int detailCount = 0;
for (ReserveStockInOrderDO stockInOrderDO : stockInOrderList) {
// 主表DO -> 实体 -> save
ReserveStockInOrder stockInOrder = new ReserveStockInOrder();
BeanUtils.copyProperties(stockInOrderDO, stockInOrder);
stockInOrder.setMaterialQuantity(stockInOrderDO.getMaterialDetailList().size());
BigDecimal totalQuantity = stockInOrderDO.getMaterialDetailList().stream()
.map(ReserveInMaterialDetailDO::getQuantity).filter(Objects::nonNull)
.reduce(BigDecimal.ZERO, BigDecimal::add);
stockInOrder.setQuantity(totalQuantity);
stockInOrder.setReserveQuantity(totalQuantity);
stockInOrderService.save(stockInOrder);
// 明细DO -> 实体 -> saveBatch
List<ReserveInMaterialDetail> detailEntities = new ArrayList<>();
for (ReserveInMaterialDetailDO detailDO : stockInOrderDO.getMaterialDetailList()) {
ReserveInMaterialDetail detail = new ReserveInMaterialDetail();
BeanUtils.copyProperties(detailDO, detail);
detail.setInOrderNumber(stockInOrderDO.getInOrderNumber());
detail.setLevel(1);
detailEntities.add(detail);
}
if (!detailEntities.isEmpty()) {
materialDetailService.saveBatch(detailEntities);
}
detailCount += detailEntities.size();
}
Map<String, Object> result = new HashMap<>();
result.put("orderCount", stockInOrderList.size());
result.put("detailCount", detailCount);
if (!errorList.isEmpty()) {
result.put("warnings", errorList);
}
return result;
}
public static String generateDateTimeWithRandom() { public static String generateDateTimeWithRandom() {
// 1. 获取当前时间格式化yyMMddHHmmss // 1. 获取当前时间格式化yyMMddHHmmss
LocalDateTime now = LocalDateTime.now(); LocalDateTime now = LocalDateTime.now();
@@ -2066,4 +2315,8 @@ public class ReserveStockInOrderApplicationService {
// 3. 拼接结果 // 3. 拼接结果
return datePart + randomPart; return datePart + randomPart;
} }
public String generateReserveOrderNumber() {
return stockInOrderDomainService.generateReserveOrderNumber();
}
} }
@@ -18,6 +18,7 @@ import com.mhd.oms.domain.reservationInMaterialDetail.repository.facade.IReserva
import com.mhd.oms.domain.reservationInMaterialDetail.repository.todo.InventoryAdjustmentRecordPO; import com.mhd.oms.domain.reservationInMaterialDetail.repository.todo.InventoryAdjustmentRecordPO;
import com.mhd.oms.domain.reservationStockInOrder.entity.ReservationStockInOrder; import com.mhd.oms.domain.reservationStockInOrder.entity.ReservationStockInOrder;
import com.mhd.oms.domain.reservationStockInOrder.repository.facade.IReservationStockInOrderService; import com.mhd.oms.domain.reservationStockInOrder.repository.facade.IReservationStockInOrderService;
import com.mhd.oms.domain.reservationStockInOrder.service.ReservationStockInOrderDomainService;
import com.mhd.oms.domain.reservationStockInOrder.repository.po.MaterialBaseInfoPO; import com.mhd.oms.domain.reservationStockInOrder.repository.po.MaterialBaseInfoPO;
import com.mhd.oms.domain.reservationStockInOrder.repository.po.MaterialGoodsRulePO; import com.mhd.oms.domain.reservationStockInOrder.repository.po.MaterialGoodsRulePO;
import com.mhd.oms.domain.reservationStockInOrder.repository.po.MaterialWarehouseControlPO; import com.mhd.oms.domain.reservationStockInOrder.repository.po.MaterialWarehouseControlPO;
@@ -78,6 +79,8 @@ public class ReserveStockInOrderDomainService {
private IReservationStockInOrderService reservationStockInOrderService; private IReservationStockInOrderService reservationStockInOrderService;
@Autowired @Autowired
private IReservationInMaterialDetailService reservationInMaterialDetailService; private IReservationInMaterialDetailService reservationInMaterialDetailService;
@Autowired
private ReservationStockInOrderDomainService reservationStockInOrderDomainService;
/** /**
* 分页查询入库单列表 * 分页查询入库单列表
@@ -101,7 +104,7 @@ public class ReserveStockInOrderDomainService {
@Transactional(rollbackFor = Exception.class) @Transactional(rollbackFor = Exception.class)
public Boolean insert(ReserveStockInOrderDO stockInOrderDO) { public Boolean insert(ReserveStockInOrderDO stockInOrderDO) {
if (stockInOrderDO.getInOrderNumber() == null) { if (stockInOrderDO.getInOrderNumber() == null) {
stockInOrderDO.setInOrderNumber(OrderSequence.getOrderCode("RK")); stockInOrderDO.setInOrderNumber(generateReserveOrderNumber());
} }
// //设置默认值 // //设置默认值
// setDefaultValues(stockInOrderDO); // setDefaultValues(stockInOrderDO);
@@ -134,7 +137,7 @@ public class ReserveStockInOrderDomainService {
public Boolean batchInsert(List<ReserveStockInOrderDO> stockInOrderDOList) { public Boolean batchInsert(List<ReserveStockInOrderDO> stockInOrderDOList) {
for (ReserveStockInOrderDO stockInOrderDO : stockInOrderDOList){ for (ReserveStockInOrderDO stockInOrderDO : stockInOrderDOList){
if (StringUtils.isBlank(stockInOrderDO.getInOrderNumber())){ if (StringUtils.isBlank(stockInOrderDO.getInOrderNumber())){
stockInOrderDO.setInOrderNumber(OrderSequence.getOrderCode("RK")); stockInOrderDO.setInOrderNumber(generateReserveOrderNumber());
} }
// //设置物料信息 // //设置物料信息
// setMaterialDetailInfo(stockInOrderDO); // setMaterialDetailInfo(stockInOrderDO);
@@ -176,6 +179,10 @@ public class ReserveStockInOrderDomainService {
BigDecimal quantity = stockInOrderDO.getMaterialDetailList().stream().map(ReserveInMaterialDetailDO::getQuantity).filter(Objects::nonNull).reduce(BigDecimal.ZERO, BigDecimal::add); BigDecimal quantity = stockInOrderDO.getMaterialDetailList().stream().map(ReserveInMaterialDetailDO::getQuantity).filter(Objects::nonNull).reduce(BigDecimal.ZERO, BigDecimal::add);
stockInOrderPO.setQuantity(quantity); stockInOrderPO.setQuantity(quantity);
stockInOrderDO.setQuantity(quantity); stockInOrderDO.setQuantity(quantity);
//统计预约数量
BigDecimal reserceQuantity = stockInOrderDO.getMaterialDetailList().stream().map(ReserveInMaterialDetailDO::getReserveQuantity).filter(Objects::nonNull).reduce(BigDecimal.ZERO, BigDecimal::add);
stockInOrderPO.setReserveQuantity(reserceQuantity);
stockInOrderDO.setReserveQuantity(reserceQuantity);
//统计总重量 //统计总重量
BigDecimal weightLimit = stockInOrderDO.getMaterialDetailList().stream().map(ReserveInMaterialDetailDO::getWeightLimit).filter(Objects::nonNull).reduce(BigDecimal.ZERO, BigDecimal::add); BigDecimal weightLimit = stockInOrderDO.getMaterialDetailList().stream().map(ReserveInMaterialDetailDO::getWeightLimit).filter(Objects::nonNull).reduce(BigDecimal.ZERO, BigDecimal::add);
stockInOrderDO.setWeightLimit(weightLimit); stockInOrderDO.setWeightLimit(weightLimit);
@@ -467,13 +474,18 @@ public class ReserveStockInOrderDomainService {
Long shipperId = reservationStockInOrder.getShipperId(); Long shipperId = reservationStockInOrder.getShipperId();
String jsbz = reservationStockInOrderMapper.getJsbz(shipperId); String jsbz = reservationStockInOrderMapper.getJsbz(shipperId);
reservationStockInOrder.setSettlementCurrency(jsbz); reservationStockInOrder.setSettlementCurrency(jsbz);
String inOrderNumber = reservationStockInOrder.getInOrderNumber(); String oldInOrderNumber = reservationStockInOrder.getInOrderNumber();
List<ReserveInMaterialDetail> materialDetailList = materialDetailService.list(new QueryWrapper<ReserveInMaterialDetail>().lambda().eq(ReserveInMaterialDetail::getInOrderNumber, inOrderNumber)); // 生成新业务单号防止与已生成的入库业务单号重复
String newOrderNumber = reservationStockInOrderDomainService.generateReserveOrderNumber();
reservationStockInOrder.setInOrderNumber(newOrderNumber);
reservationStockInOrder.setBusinessOrderNo(newOrderNumber);
List<ReserveInMaterialDetail> materialDetailList = materialDetailService.list(new QueryWrapper<ReserveInMaterialDetail>().lambda().eq(ReserveInMaterialDetail::getInOrderNumber, oldInOrderNumber));
List<ReservationInMaterialDetail> inMaterialDetailList = new ArrayList<>(); List<ReservationInMaterialDetail> inMaterialDetailList = new ArrayList<>();
int index = 1; int index = 1;
for (ReserveInMaterialDetail reserveInMaterialDetail : materialDetailList) { for (ReserveInMaterialDetail reserveInMaterialDetail : materialDetailList) {
ReservationInMaterialDetail reservationInMaterialDetail = new ReservationInMaterialDetail(); ReservationInMaterialDetail reservationInMaterialDetail = new ReservationInMaterialDetail();
BeanUtils.copyProperties(reserveInMaterialDetail, reservationInMaterialDetail,"materialDetailId"); BeanUtils.copyProperties(reserveInMaterialDetail, reservationInMaterialDetail,"materialDetailId");
reservationInMaterialDetail.setInOrderNumber(newOrderNumber); // 使用新单号保持与主表关联
reservationInMaterialDetail.setQuantity(reserveInMaterialDetail.getReserveQuantity()); reservationInMaterialDetail.setQuantity(reserveInMaterialDetail.getReserveQuantity());
String lot = generateDateSerialNumber(); String lot = generateDateSerialNumber();
lot = lot+"-"+index; lot = lot+"-"+index;
@@ -969,4 +981,16 @@ public class ReserveStockInOrderDomainService {
return stockInOrderService.queryNoticePrintDetail(stockInOrderDO); return stockInOrderService.queryNoticePrintDetail(stockInOrderDO);
} }
/**
* 生成入库预约单号
*/
public String generateReserveOrderNumber() {
SimpleDateFormat sdf = new SimpleDateFormat("yyMMdd");
String datePart = sdf.format(new Date());
String prefix = "R" + datePart;
int todayCount = reservationStockInOrderMapper.countByOrderNumberPrefix(prefix);
String seq = String.format("%03d", todayCount + 1);
return prefix + seq;
}
} }
@@ -2,10 +2,12 @@ package com.mhd.oms.domain.reserveStockOutOrder.repository.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.core.mapper.BaseMapper;
//import com.mhd.oms.domain.reservationOutMaterialDetail.repository.po.ReserveOutMaterialDetailPO; //import com.mhd.oms.domain.reservationOutMaterialDetail.repository.po.ReserveOutMaterialDetailPO;
import com.mhd.common.core.domain.po.WarehousePO;
import com.mhd.oms.domain.reserveOutMaterialDetail.repository.po.ReserveOutMaterialDetailPO; import com.mhd.oms.domain.reserveOutMaterialDetail.repository.po.ReserveOutMaterialDetailPO;
import com.mhd.oms.domain.reserveStockOutOrder.entity.ReserveStockOutOrder; import com.mhd.oms.domain.reserveStockOutOrder.entity.ReserveStockOutOrder;
import com.mhd.oms.domain.reserveStockOutOrder.repository.po.ReserveStockOutOrderPO; import com.mhd.oms.domain.reserveStockOutOrder.repository.po.ReserveStockOutOrderPO;
import com.mhd.oms.domain.reserveStockOutOrder.repository.todo.ReserveStockOutOrderDO; import com.mhd.oms.domain.reserveStockOutOrder.repository.todo.ReserveStockOutOrderDO;
import org.apache.ibatis.annotations.Param;
import java.util.List; import java.util.List;
@@ -33,4 +35,19 @@ public interface ReserveStockOutOrderMapper extends BaseMapper<ReserveStockOutOr
* 出库单提货单打印-明细 * 出库单提货单打印-明细
*/ */
List<ReserveOutMaterialDetailPO> queryOutStockNoticePrintDetail(ReserveStockOutOrderDO stockOutOrderDO); List<ReserveOutMaterialDetailPO> queryOutStockNoticePrintDetail(ReserveStockOutOrderDO stockOutOrderDO);
int countByOrderNumberPrefix(@Param("prefix") String prefix);
List<String> generateReserveOrderNumber1(@Param("prefix") String prefix);
/**
* 老系统数据导入根据出库单号精确统计防重
*/
int countByOutOrderNumber(@Param("outOrderNumber") String outOrderNumber);
/**
* 老系统数据导入根据仓库类型查询仓库
* @param warehouseType 仓库类型编码 "1"/"2"
*/
List<WarehousePO> getWarehouseByType(@Param("warehouseType") String warehouseType);
} }
@@ -1,7 +1,10 @@
package com.mhd.oms.domain.reserveStockOutOrder.repository.util; package com.mhd.oms.domain.reserveStockOutOrder.repository.util;
import com.alibaba.excel.EasyExcel; import com.alibaba.excel.EasyExcel;
import com.mhd.common.core.utils.StringUtils;
import com.mhd.oms.domain.reserveStockOutOrder.repository.listener.ReservedInventoryOutListener; import com.mhd.oms.domain.reserveStockOutOrder.repository.listener.ReservedInventoryOutListener;
import com.mhd.oms.domain.reserveStockOutOrder.repository.vo.LegacyReserveOutDetailVO;
import com.mhd.oms.domain.reserveStockOutOrder.repository.vo.LegacyReserveOutOrderVO;
import com.mhd.oms.domain.reserveStockOutOrder.repository.vo.ReservedInventoryOut; import com.mhd.oms.domain.reserveStockOutOrder.repository.vo.ReservedInventoryOut;
import org.springframework.web.multipart.MultipartFile; import org.springframework.web.multipart.MultipartFile;
@@ -55,6 +58,55 @@ public class ExcelParseUtil {
return dataList; return dataList;
} }
/**
* 解析老系统出库预约单列表Excel表头第1行数据从第2行开始
*/
public static List<LegacyReserveOutOrderVO> parseLegacyOrderExcel(MultipartFile file) throws IOException {
validateFile(file);
List<LegacyReserveOutOrderVO> dataList;
try (InputStream inputStream = file.getInputStream()) {
dataList = EasyExcel.read(inputStream)
.head(LegacyReserveOutOrderVO.class)
.sheet(0)
.headRowNumber(1)
.doReadSync();
}
// 过滤出库单号为空的无效行
return dataList.stream()
.filter(row -> row != null && StringUtils.isNotBlank(row.getOutOrderNumber()))
.collect(java.util.stream.Collectors.toList());
}
/**
* 解析老系统出库预约单明细列表Excel表头第1行数据从第2行开始
* 物料名称取物料名称1和物料名称2中有值的那一个
*/
public static List<LegacyReserveOutDetailVO> parseLegacyDetailExcel(MultipartFile file) throws IOException {
validateFile(file);
List<LegacyReserveOutDetailVO> dataList;
try (InputStream inputStream = file.getInputStream()) {
dataList = EasyExcel.read(inputStream)
.head(LegacyReserveOutDetailVO.class)
.sheet(0)
.headRowNumber(1)
.doReadSync();
}
// 过滤出库单号为空的无效行同时把 materialName1/materialName2 中有值的赋给 materialName
return dataList.stream()
.filter(row -> row != null && StringUtils.isNotBlank(row.getOutOrderNumber()))
.map(row -> {
if (StringUtils.isBlank(row.getMaterialName())) {
if (StringUtils.isNotBlank(row.getMaterialName1())) {
row.setMaterialName(row.getMaterialName1());
} else if (StringUtils.isNotBlank(row.getMaterialName2())) {
row.setMaterialName(row.getMaterialName2());
}
}
return row;
})
.collect(java.util.stream.Collectors.toList());
}
/** /**
* 验证Excel文件合法性 * 验证Excel文件合法性
*/ */
@@ -0,0 +1,91 @@
package com.mhd.oms.domain.reserveStockOutOrder.repository.vo;
import com.alibaba.excel.annotation.ExcelIgnore;
import com.alibaba.excel.annotation.ExcelProperty;
import com.mhd.oms.domain.reserveStockInOrder.repository.util.StringToBigDecimalConverter;
import com.mhd.oms.domain.reserveStockInOrder.repository.util.StringToDateConverter;
import lombok.Data;
import java.math.BigDecimal;
import java.util.Date;
/**
* 老系统出库预约单明细行
* 与老系统导出Excel出库预约单明细列表字段一一映射表头第1行数据从第2行开始
* 物料名称取物料名称1和物料名称2中有值的那一个
*/
@Data
public class LegacyReserveOutDetailVO {
/**
* 老系统明细id跨系统id不可用仅做占位
*/
@ExcelProperty(index = 0, value = "id")
private String oldDetailId;
/**
* 出库单号必填关联主表
*/
@ExcelProperty(index = 1, value = "出库单号")
private String outOrderNumber;
/**
* 出库数量
*/
@ExcelProperty(index = 2, value = "出库数量", converter = StringToBigDecimalConverter.class)
private BigDecimal quantity;
/**
* 入库单号老系统关联的入库单号保留到备注或来源单号字段
*/
@ExcelProperty(index = 3, value = "入库单号")
private String inOrderNumber;
/**
* 物料名称1
*/
@ExcelProperty(index = 4, value = "物料名称1")
private String materialName1;
/**
* 物料名称2
*/
@ExcelProperty(index = 5, value = "物料名称2")
private String materialName2;
/**
* 重量KG
*/
@ExcelProperty(index = 6, value = "重量", converter = StringToBigDecimalConverter.class)
private BigDecimal weight;
/**
* 创建时间老系统
*/
@ExcelProperty(index = 7, value = "创建时间", converter = StringToDateConverter.class)
private Date createTime;
/**
* 修改时间老系统
*/
@ExcelProperty(index = 8, value = "修改时间", converter = StringToDateConverter.class)
private Date updateTime;
/**
* 创建人名称老系统
*/
@ExcelProperty(index = 9, value = "创建人名称")
private String createByName;
/**
* 修改人名称老系统
*/
@ExcelProperty(index = 10, value = "修改人名称")
private String updateByName;
/**
* 取物料名称1和物料名称2中有值的那一个不映射Excel列运行时计算
*/
@ExcelIgnore
private String materialName;
}
@@ -0,0 +1,82 @@
package com.mhd.oms.domain.reserveStockOutOrder.repository.vo;
import com.alibaba.excel.annotation.ExcelProperty;
import com.mhd.oms.domain.reserveStockInOrder.repository.util.StringToDateConverter;
import lombok.Data;
import java.util.Date;
/**
* 老系统出库预约单主表行
* 与老系统导出Excel出库预约单列表字段一一映射表头第1行数据从第2行开始
*/
@Data
public class LegacyReserveOutOrderVO {
/**
* 出库单号必填与明细表关联键
*/
@ExcelProperty(index = 0, value = "出库单号")
private String outOrderNumber;
/**
* 出库时间
*/
@ExcelProperty(index = 1, value = "出库时间", converter = StringToDateConverter.class)
private Date outboundDate;
/**
* 制单人名称
*/
@ExcelProperty(index = 2, value = "制单人名称")
private String documentCreator;
/**
* 制单时间
*/
@ExcelProperty(index = 3, value = "制单时间", converter = StringToDateConverter.class)
private Date documentDate;
/**
* 货主名称必填用于匹配新系统用户
*/
@ExcelProperty(index = 4, value = "货主名称")
private String shipperName;
/**
* 备注
*/
@ExcelProperty(index = 5, value = "备注")
private String remark;
/**
* 创建时间老系统
*/
@ExcelProperty(index = 6, value = "创建时间", converter = StringToDateConverter.class)
private Date createTime;
/**
* 修改时间老系统
*/
@ExcelProperty(index = 7, value = "修改时间", converter = StringToDateConverter.class)
private Date updateTime;
/**
* 创建人名称老系统
*/
@ExcelProperty(index = 8, value = "创建人名称")
private String createByName;
/**
* 修改人名称老系统
*/
@ExcelProperty(index = 9, value = "修改人名称")
private String updateByName;
/**
* 仓库类型1-干仓 2-冬仓
* 用于按类型匹配新系统仓库老系统没有仓库名称只有仓库类型
*/
@ExcelProperty(index = 10, value = "仓库类型")
private String warehouseType;
}
@@ -5,7 +5,9 @@ import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson2.JSONObject; import com.alibaba.fastjson2.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.mhd.common.core.constant.SnowFlakeConstants;
import com.mhd.common.core.domain.po.UserPo; import com.mhd.common.core.domain.po.UserPo;
import com.mhd.common.core.domain.po.WarehousePO;
import com.mhd.common.core.enums.DictCode; import com.mhd.common.core.enums.DictCode;
import com.mhd.common.core.exception.ServiceException; import com.mhd.common.core.exception.ServiceException;
import com.mhd.common.core.utils.StringUtils; import com.mhd.common.core.utils.StringUtils;
@@ -23,14 +25,20 @@ import com.mhd.oms.domain.reserveInMaterialDetail.repository.todo.ReserveInMater
import com.mhd.oms.domain.reserveOutMaterialDetail.repository.facade.IReserveOutMaterialDetailService; import com.mhd.oms.domain.reserveOutMaterialDetail.repository.facade.IReserveOutMaterialDetailService;
import com.mhd.oms.domain.reserveOutMaterialDetail.repository.po.ReserveOutMaterialDetailPO; import com.mhd.oms.domain.reserveOutMaterialDetail.repository.po.ReserveOutMaterialDetailPO;
import com.mhd.oms.domain.reserveOutMaterialDetail.repository.todo.ReserveOutMaterialDetailDO; import com.mhd.oms.domain.reserveOutMaterialDetail.repository.todo.ReserveOutMaterialDetailDO;
import com.mhd.oms.domain.reserveStockInOrder.repository.listener.ValidationException;
import com.mhd.oms.domain.reserveStockInOrder.repository.mapper.ReserveStockInOrderMapper; import com.mhd.oms.domain.reserveStockInOrder.repository.mapper.ReserveStockInOrderMapper;
import com.mhd.oms.domain.reserveStockInOrder.repository.todo.ReserveStockInOrderDO; import com.mhd.oms.domain.reserveStockInOrder.repository.todo.ReserveStockInOrderDO;
import com.mhd.oms.domain.reserveStockInOrder.repository.vo.ReservedInventory; import com.mhd.oms.domain.reserveStockInOrder.repository.vo.ReservedInventory;
import com.mhd.oms.domain.reserveStockOutOrder.entity.ReserveStockOutOrder;
import com.mhd.oms.domain.reserveStockOutOrder.repository.facade.IReserveStockOutOrderService; import com.mhd.oms.domain.reserveStockOutOrder.repository.facade.IReserveStockOutOrderService;
import com.mhd.oms.domain.reserveStockOutOrder.repository.mapper.ReserveStockOutOrderMapper;
import com.mhd.oms.domain.reserveStockOutOrder.repository.po.ReserveStockOutOrderPO; import com.mhd.oms.domain.reserveStockOutOrder.repository.po.ReserveStockOutOrderPO;
import com.mhd.oms.domain.reserveStockOutOrder.repository.todo.ReserveStockOutOrderDO; import com.mhd.oms.domain.reserveStockOutOrder.repository.todo.ReserveStockOutOrderDO;
import com.mhd.oms.domain.reserveStockOutOrder.repository.todo.ReserveStockOutOrderDTO; import com.mhd.oms.domain.reserveStockOutOrder.repository.todo.ReserveStockOutOrderDTO;
import com.mhd.oms.domain.reserveStockOutOrder.repository.vo.LegacyReserveOutDetailVO;
import com.mhd.oms.domain.reserveStockOutOrder.repository.vo.LegacyReserveOutOrderVO;
import com.mhd.oms.domain.reserveStockOutOrder.repository.vo.ReservedInventoryOut; import com.mhd.oms.domain.reserveStockOutOrder.repository.vo.ReservedInventoryOut;
import com.mhd.oms.domain.reserveOutMaterialDetail.entity.ReserveOutMaterialDetail;
import com.mhd.system.api.SystemServiceFeign; import com.mhd.system.api.SystemServiceFeign;
import com.mhd.system.api.UserServiceFeign; import com.mhd.system.api.UserServiceFeign;
import com.mhd.system.api.domain.*; import com.mhd.system.api.domain.*;
@@ -38,6 +46,7 @@ import com.mhd.system.api.model.LoginUser;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils; import org.springframework.util.CollectionUtils;
import java.lang.reflect.Field; import java.lang.reflect.Field;
@@ -68,6 +77,8 @@ public class ReserveStockOutOrderApplicationService {
@Autowired @Autowired
private ReserveStockInOrderMapper reserveStockInOrderMapper; private ReserveStockInOrderMapper reserveStockInOrderMapper;
@Autowired @Autowired
private ReserveStockOutOrderMapper reserveStockOutOrderMapper;
@Autowired
private ReservationMaterialInventoryMapper reservationMaterialInventoryMapper; private ReservationMaterialInventoryMapper reservationMaterialInventoryMapper;
@Autowired @Autowired
private UserServiceFeign userServiceFeign; private UserServiceFeign userServiceFeign;
@@ -1112,6 +1123,238 @@ public class ReserveStockOutOrderApplicationService {
return stockOutOrderDomainService.queryOutStockNoticePrintDetail(stockOutOrderDO); return stockOutOrderDomainService.queryOutStockNoticePrintDetail(stockOutOrderDO);
} }
/**
* 老系统出库预约单数据导入主表+明细两个Excel多单批量导入
* 老系统的id类字段不可用货主按名称匹配新系统用户仓库按仓库类型1=干仓 2=冬仓匹配新系统仓库物料按名称匹配
* 明细表物料名称取物料名称1和物料名称2中有值的那一个
*/
@Transactional(rollbackFor = Exception.class)
public Map<String, Object> importLegacyData(List<LegacyReserveOutOrderVO> orderList, List<LegacyReserveOutDetailVO> detailList) {
if (orderList == null || orderList.isEmpty()) {
throw new ValidationException("出库预约单列表文件中没有有效数据");
}
if (detailList == null || detailList.isEmpty()) {
throw new ValidationException("出库预约单明细列表文件中没有有效数据");
}
// 明细按出库单号分组
Map<String, List<LegacyReserveOutDetailVO>> detailGroupMap = new LinkedHashMap<>();
for (LegacyReserveOutDetailVO detailRow : detailList) {
detailGroupMap.computeIfAbsent(detailRow.getOutOrderNumber().trim(), k -> new ArrayList<>()).add(detailRow);
}
List<String> errorList = new ArrayList<>();
// 名称匹配结果缓存避免重复查库
Map<String, UserPo> shipperCache = new HashMap<>();
// 仓库类型 -> 仓库 缓存老系统只有仓库类型没有仓库名称
Map<String, WarehousePO> warehouseTypeCache = new HashMap<>();
Map<String, MaterialBaseInfoPO> materialCache = new HashMap<>();
Set<String> orderNumberSet = new HashSet<>();
List<ReserveStockOutOrderDO> stockOutOrderList = new ArrayList<>();
int lotIndex = 1;
for (LegacyReserveOutOrderVO orderRow : orderList) {
String orderNumber = orderRow.getOutOrderNumber().trim();
if (!orderNumberSet.add(orderNumber)) {
errorList.add("出库单号【" + orderNumber + "】在主表文件中重复");
continue;
}
if (reserveStockOutOrderMapper.countByOutOrderNumber(orderNumber) > 0) {
errorList.add("出库单号【" + orderNumber + "】在系统中已存在,请勿重复导入");
continue;
}
// 按货主名称匹配用户查不到则用Excel中的名称兜底不阻断导入
UserPo shipper = null;
String shipperName = StringUtils.trimToEmpty(orderRow.getShipperName());
if (StringUtils.isBlank(shipperName)) {
errorList.add("出库单号【" + orderNumber + "】货主名称为空");
} else {
shipper = shipperCache.get(shipperName);
if (shipper == null) {
List<UserPo> userPoList = reserveStockInOrderMapper.getShipperByName(shipperName);
if (userPoList == null || userPoList.isEmpty()) {
errorList.add("出库单号【" + orderNumber + "】货主【" + shipperName + "】未找到对应用户,将仅以名称导入");
} else {
shipper = userPoList.get(0);
shipperCache.put(shipperName, shipper);
}
}
}
// 按仓库类型匹配仓库老系统仓库类型 1=干仓 2=冬仓查不到则用类型名兜底
WarehousePO warehouse = null;
String warehouseType = StringUtils.trimToEmpty(orderRow.getWarehouseType());
if (StringUtils.isNotBlank(warehouseType)) {
warehouse = warehouseTypeCache.get(warehouseType);
if (warehouse == null) {
List<WarehousePO> warehousePOList = reserveStockOutOrderMapper.getWarehouseByType(warehouseType);
if (warehousePOList == null || warehousePOList.isEmpty()) {
String fallbackName = "1".equals(warehouseType) ? "干仓" : ("2".equals(warehouseType) ? "冻仓" : "");
errorList.add("出库单号【" + orderNumber + "】仓库类型【" + warehouseType + "】未找到对应仓库,将仅以名称导入");
warehouseTypeCache.put(warehouseType, null);
warehouse = null;
} else {
warehouse = warehousePOList.get(0);
warehouseTypeCache.put(warehouseType, warehouse);
}
}
}
// 明细匹配
List<LegacyReserveOutDetailVO> detailRows = detailGroupMap.get(orderNumber);
if (detailRows == null || detailRows.isEmpty()) {
errorList.add("出库单号【" + orderNumber + "】在明细文件中没有明细数据");
continue;
}
List<ReserveOutMaterialDetailDO> materialDetailList = new ArrayList<>();
for (LegacyReserveOutDetailVO detailRow : detailRows) {
String materialName = StringUtils.trimToEmpty(detailRow.getMaterialName());
if (StringUtils.isBlank(materialName)) {
errorList.add("出库单号【" + orderNumber + "】存在物料名称为空的明细行");
continue;
}
// 按物料名称匹配物料基础信息查不到则用Excel中的名称兜底不阻断导入
MaterialBaseInfoPO materialBaseInfoPO = materialCache.get(materialName);
if (materialBaseInfoPO == null) {
List<MaterialBaseInfoPO> materialBaseInfoPOS = reserveStockInOrderMapper.getByName(materialName);
if (materialBaseInfoPOS == null || materialBaseInfoPOS.isEmpty()) {
errorList.add("出库单号【" + orderNumber + "】物料【" + materialName + "】未找到对应物料,将仅以名称导入");
} else {
materialBaseInfoPO = materialBaseInfoPOS.get(0);
materialCache.put(materialName, materialBaseInfoPO);
}
}
ReserveOutMaterialDetailDO materialDetail = new ReserveOutMaterialDetailDO();
if (materialBaseInfoPO != null) {
materialDetail.setMaterialBaseInfoId(materialBaseInfoPO.getMaterialBaseInfoId());
materialDetail.setMaterialCode(materialBaseInfoPO.getMaterialCode());
materialDetail.setUnitCode(materialBaseInfoPO.getUnitCode());
materialDetail.setUnitName(materialBaseInfoPO.getUnitName());
}
materialDetail.setMaterialName(materialName);
materialDetail.setReserveMaterialName(materialName);
materialDetail.setQuantity(detailRow.getQuantity());
materialDetail.setOutboundQuantity(detailRow.getQuantity());
materialDetail.setTotalNetWeight(detailRow.getWeight());
materialDetail.setTotalGrossWeight(detailRow.getWeight());
// 保留老系统关联的入库单号到备注
if (StringUtils.isNotBlank(detailRow.getInOrderNumber())) {
// materialDetail.setRemark("老系统入库单号:" + detailRow.getInOrderNumber());
materialDetail.setInOrderNumber(detailRow.getInOrderNumber());
}
materialDetail.setContractFee(BigDecimal.ZERO);
materialDetail.setLotNo(generateDateSerialNumber() + "-" + lotIndex);
lotIndex++;
// 组织字段硬编码与入库导入保持一致
materialDetail.setOrganizationId(2841L);
materialDetail.setOrganizationName("仓码");
materialDetail.setTopOrganizationId(2827L);
// 创建人/修改人名称取老系统Excel中的值不使用当前登录人
materialDetail.setCreateTime(detailRow.getCreateTime() != null ? detailRow.getCreateTime() : new Date());
materialDetail.setCreateByName(detailRow.getCreateByName());
materialDetail.setUpdateTime(detailRow.getUpdateTime());
materialDetail.setUpdateByName(detailRow.getUpdateByName());
materialDetail.setUniqueId(idGenerator.snowflakeId(SnowFlakeConstants.wmsId));
materialDetailList.add(materialDetail);
}
// 组装出库预约单
ReserveStockOutOrderDO stockOutOrderDO = new ReserveStockOutOrderDO();
stockOutOrderDO.setOutOrderNumber(orderNumber);
stockOutOrderDO.setBusinessOrderNo(orderNumber);
// 老系统历史数据状态直接置为最终状态已出库审核通过
stockOutOrderDO.setStatus(9);
stockOutOrderDO.setAuditStatus(3);
stockOutOrderDO.setIssueStatus(3);
stockOutOrderDO.setOutboundDate(orderRow.getOutboundDate());
stockOutOrderDO.setNeedTransportFlag("0");
stockOutOrderDO.setNeedDeclareFlag("0");
stockOutOrderDO.setExpectTime(orderRow.getOutboundDate() != null ? orderRow.getOutboundDate() : new Date());
stockOutOrderDO.setDocumentDate(orderRow.getDocumentDate() != null ? orderRow.getDocumentDate() : new Date());
stockOutOrderDO.setDocumentCreator(orderRow.getDocumentCreator());
stockOutOrderDO.setRemark(orderRow.getRemark());
if (shipper != null) {
stockOutOrderDO.setShipperId(shipper.getUserId());
stockOutOrderDO.setShipperName(shipper.getUserName());
stockOutOrderDO.setCustomerId(shipper.getUserId());
stockOutOrderDO.setCustomerName(shipper.getUserName());
stockOutOrderDO.setSalesmanId(String.valueOf(shipper.getUserId()));
stockOutOrderDO.setSalesmanName(shipper.getUserName());
stockOutOrderDO.setCustomerCode(reserveStockInOrderMapper.getCustomerNcCodeByUserId(shipper.getUserId()));
} else {
// 货主未匹配到仅以Excel中的名称作为名称字段id留空
stockOutOrderDO.setShipperName(shipperName);
stockOutOrderDO.setCustomerName(shipperName);
stockOutOrderDO.setSalesmanName(shipperName);
}
// 组织字段硬编码与入库导入保持一致
stockOutOrderDO.setOrganizationId(2841L);
stockOutOrderDO.setOrganizationName("仓码");
stockOutOrderDO.setTopOrganizationId(2827L);
if (warehouse != null) {
stockOutOrderDO.setWarehouseId(warehouse.getWarehouseId());
stockOutOrderDO.setWarehouseCode(warehouse.getWarehouseCode());
stockOutOrderDO.setWarehouseName(warehouse.getWarehouseName());
} else if (StringUtils.isNotBlank(warehouseType)) {
// 仓库未匹配到仅以仓库类型名作为仓库名称id/编码留空
String fallbackName = "1".equals(warehouseType) ? "干仓" : ("2".equals(warehouseType) ? "冻仓" : "");
if (StringUtils.isNotBlank(fallbackName)) {
stockOutOrderDO.setWarehouseName(fallbackName);
}
}
// 创建人/修改人名称取老系统Excel中的值不使用当前登录人
stockOutOrderDO.setCreateTime(orderRow.getCreateTime() != null ? orderRow.getCreateTime() : new Date());
stockOutOrderDO.setCreateByName(orderRow.getCreateByName());
stockOutOrderDO.setUpdateTime(orderRow.getUpdateTime());
stockOutOrderDO.setUpdateByName(orderRow.getUpdateByName());
stockOutOrderDO.setMaterialDetailList(materialDetailList);
stockOutOrderList.add(stockOutOrderDO);
}
// 明细文件中存在但主表文件中不存在的单号
for (String detailOrderNumber : detailGroupMap.keySet()) {
if (!orderNumberSet.contains(detailOrderNumber)) {
errorList.add("明细文件中出库单号【" + detailOrderNumber + "】在主表文件中不存在");
}
}
// 逐单入库即使有未匹配到基础数据的警告也不阻断错误信息随结果返回
// 直接走 MyBatis-Plus 入库绕过领域服务/应用服务层的参数补全逻辑
int detailCount = 0;
for (ReserveStockOutOrderDO stockOutOrderDO : stockOutOrderList) {
// 主表DO -> 实体 -> save
ReserveStockOutOrder stockOutOrder = new ReserveStockOutOrder();
BeanUtils.copyProperties(stockOutOrderDO, stockOutOrder);
stockOutOrder.setMaterialQuantity(stockOutOrderDO.getMaterialDetailList().size());
BigDecimal totalQuantity = stockOutOrderDO.getMaterialDetailList().stream()
.map(ReserveOutMaterialDetailDO::getQuantity).filter(Objects::nonNull)
.reduce(BigDecimal.ZERO, BigDecimal::add);
stockOutOrder.setQuantity(totalQuantity);
stockOutOrderService.save(stockOutOrder);
// 明细DO -> 实体 -> saveBatch
List<ReserveOutMaterialDetail> detailEntities = new ArrayList<>();
for (ReserveOutMaterialDetailDO detailDO : stockOutOrderDO.getMaterialDetailList()) {
ReserveOutMaterialDetail detail = new ReserveOutMaterialDetail();
BeanUtils.copyProperties(detailDO, detail);
detail.setOutOrderNumber(stockOutOrderDO.getOutOrderNumber());
detailEntities.add(detail);
}
if (!detailEntities.isEmpty()) {
outMaterialDetailService.saveBatch(detailEntities);
}
detailCount += detailEntities.size();
}
Map<String, Object> result = new HashMap<>();
result.put("orderCount", stockOutOrderList.size());
result.put("detailCount", detailCount);
if (!errorList.isEmpty()) {
result.put("warnings", errorList);
}
return result;
}
public void importInData(List<ReservedInventoryOut> dataList) { public void importInData(List<ReservedInventoryOut> dataList) {
LoginUser loginUser = SecurityUtils.getLoginUser(); LoginUser loginUser = SecurityUtils.getLoginUser();
ReserveStockOutOrderDO reserveStockOutOrder = new ReserveStockOutOrderDO(); ReserveStockOutOrderDO reserveStockOutOrder = new ReserveStockOutOrderDO();
@@ -1217,4 +1460,8 @@ public class ReserveStockOutOrderApplicationService {
// 3. 拼接结果 // 3. 拼接结果
return datePart + randomPart; return datePart + randomPart;
} }
public String generateReserveOrderNumber() {
return stockOutOrderDomainService.generateReserveOrderNumber();
}
} }
@@ -16,6 +16,7 @@ import com.mhd.oms.domain.reservationStockInOrder.entity.ReservationStockInOrder
import com.mhd.oms.domain.reservationStockInOrder.repository.po.MaterialBaseInfoPO; import com.mhd.oms.domain.reservationStockInOrder.repository.po.MaterialBaseInfoPO;
import com.mhd.oms.domain.reservationStockOutOrder.entity.ReservationStockOutOrder; import com.mhd.oms.domain.reservationStockOutOrder.entity.ReservationStockOutOrder;
import com.mhd.oms.domain.reservationStockOutOrder.repository.facade.IReservationStockOutOrderService; import com.mhd.oms.domain.reservationStockOutOrder.repository.facade.IReservationStockOutOrderService;
import com.mhd.oms.domain.reservationStockOutOrder.service.ReservationStockOutOrderDomainService;
import com.mhd.oms.domain.reserveInMaterialDetail.entity.ReserveInMaterialDetail; import com.mhd.oms.domain.reserveInMaterialDetail.entity.ReserveInMaterialDetail;
import com.mhd.oms.domain.reserveOutMaterialDetail.entity.ReserveOutMaterialDetail; import com.mhd.oms.domain.reserveOutMaterialDetail.entity.ReserveOutMaterialDetail;
import com.mhd.oms.domain.reserveOutMaterialDetail.repository.facade.IReserveOutMaterialDetailService; import com.mhd.oms.domain.reserveOutMaterialDetail.repository.facade.IReserveOutMaterialDetailService;
@@ -28,6 +29,7 @@ import com.mhd.oms.domain.reserveStockInOrder.repository.mapper.ReserveStockInOr
import com.mhd.oms.domain.reserveStockInOrder.repository.todo.ReserveStockInOrderDO; import com.mhd.oms.domain.reserveStockInOrder.repository.todo.ReserveStockInOrderDO;
import com.mhd.oms.domain.reserveStockOutOrder.entity.ReserveStockOutOrder; import com.mhd.oms.domain.reserveStockOutOrder.entity.ReserveStockOutOrder;
import com.mhd.oms.domain.reserveStockOutOrder.repository.facade.IReserveStockOutOrderService; import com.mhd.oms.domain.reserveStockOutOrder.repository.facade.IReserveStockOutOrderService;
import com.mhd.oms.domain.reserveStockOutOrder.repository.mapper.ReserveStockOutOrderMapper;
import com.mhd.oms.domain.reserveStockOutOrder.repository.po.ReserveStockOutOrderPO; import com.mhd.oms.domain.reserveStockOutOrder.repository.po.ReserveStockOutOrderPO;
import com.mhd.oms.domain.reserveStockOutOrder.repository.todo.ReserveStockOutOrderDO; import com.mhd.oms.domain.reserveStockOutOrder.repository.todo.ReserveStockOutOrderDO;
import com.mhd.system.api.SystemServiceFeign; import com.mhd.system.api.SystemServiceFeign;
@@ -71,6 +73,12 @@ public class ReserveStockOutOrderDomainService {
@Autowired @Autowired
private ReserveStockInOrderMapper reservationStockInOrderMapper; private ReserveStockInOrderMapper reservationStockInOrderMapper;
@Autowired
private ReserveStockOutOrderMapper stockOutOrderMapper;
@Autowired
private ReservationStockOutOrderDomainService reservationStockOutOrderDomainService;
/** /**
* 分页查询出库单列表 * 分页查询出库单列表
*/ */
@@ -89,7 +97,7 @@ public class ReserveStockOutOrderDomainService {
@Transactional(rollbackFor = Exception.class) @Transactional(rollbackFor = Exception.class)
public Boolean insert(ReserveStockOutOrderDO stockOutOrderDO) { public Boolean insert(ReserveStockOutOrderDO stockOutOrderDO) {
if (stockOutOrderDO.getOutOrderNumber() == null) { if (stockOutOrderDO.getOutOrderNumber() == null) {
stockOutOrderDO.setOutOrderNumber(OrderSequence.getOrderCode("CK")); stockOutOrderDO.setOutOrderNumber(generateReserveOrderNumber());
} }
// update / batchInsert 一致前端传计划数量为 quantity outboundQuantity // update / batchInsert 一致前端传计划数量为 quantity outboundQuantity
setMaterialDetailInfo(stockOutOrderDO); setMaterialDetailInfo(stockOutOrderDO);
@@ -119,7 +127,7 @@ public class ReserveStockOutOrderDomainService {
public Boolean batchInsert(List<ReserveStockOutOrderDO> stockOutOrderDOList) { public Boolean batchInsert(List<ReserveStockOutOrderDO> stockOutOrderDOList) {
for (ReserveStockOutOrderDO stockOutOrderDO : stockOutOrderDOList){ for (ReserveStockOutOrderDO stockOutOrderDO : stockOutOrderDOList){
if (StringUtils.isBlank(stockOutOrderDO.getOutOrderNumber())){ if (StringUtils.isBlank(stockOutOrderDO.getOutOrderNumber())){
stockOutOrderDO.setOutOrderNumber(OrderSequence.getOrderCode("CK")); stockOutOrderDO.setOutOrderNumber(generateReserveOrderNumber());
} }
//设置物料信息 //设置物料信息
setMaterialDetailInfo(stockOutOrderDO); setMaterialDetailInfo(stockOutOrderDO);
@@ -298,14 +306,20 @@ public class ReserveStockOutOrderDomainService {
Long shipperId = reservationStockOutOrder.getShipperId(); Long shipperId = reservationStockOutOrder.getShipperId();
String jsbz = reservationStockInOrderMapper.getJsbz(shipperId); String jsbz = reservationStockInOrderMapper.getJsbz(shipperId);
reservationStockOutOrder.setSettlementCurrency(jsbz); reservationStockOutOrder.setSettlementCurrency(jsbz);
// 保留旧单号用于查询源明细数据
String oldOutOrderNumber = reservationStockOutOrder.getOutOrderNumber();
// 生成出库业务单号防止与已生成的出库业务单号重复
String newOrderNumber = reservationStockOutOrderDomainService.generateReserveOrderNumber();
reservationStockOutOrder.setOutOrderNumber(newOrderNumber);
reservationStockOutOrder.setBusinessOrderNo(newOrderNumber);
reservationStockOutOrderService.save(reservationStockOutOrder); reservationStockOutOrderService.save(reservationStockOutOrder);
String outOrderNumber = reservationStockOutOrder.getOutOrderNumber(); List<ReserveOutMaterialDetail> materialDetailList = outMaterialDetailService.list(new QueryWrapper<ReserveOutMaterialDetail>().lambda().eq(ReserveOutMaterialDetail::getOutOrderNumber, oldOutOrderNumber));
List<ReserveOutMaterialDetail> materialDetailList = outMaterialDetailService.list(new QueryWrapper<ReserveOutMaterialDetail>().lambda().eq(ReserveOutMaterialDetail::getOutOrderNumber, outOrderNumber));
List<ReservationOutMaterialDetail> inMaterialDetailList = new ArrayList<>(); List<ReservationOutMaterialDetail> inMaterialDetailList = new ArrayList<>();
int index = 1; int index = 1;
for (ReserveOutMaterialDetail reserveOutMaterialDetail : materialDetailList) { for (ReserveOutMaterialDetail reserveOutMaterialDetail : materialDetailList) {
ReservationOutMaterialDetail reservationOutMaterialDetail = new ReservationOutMaterialDetail(); ReservationOutMaterialDetail reservationOutMaterialDetail = new ReservationOutMaterialDetail();
BeanUtils.copyProperties(reserveOutMaterialDetail, reservationOutMaterialDetail,"materialDetailId"); BeanUtils.copyProperties(reserveOutMaterialDetail, reservationOutMaterialDetail,"materialDetailId");
reservationOutMaterialDetail.setOutOrderNumber(newOrderNumber); // 使用新单号保持与主表关联
String lot = generateDateSerialNumber(); String lot = generateDateSerialNumber();
lot = lot+"-"+index; lot = lot+"-"+index;
index++; index++;
@@ -751,4 +765,17 @@ public class ReserveStockOutOrderDomainService {
return stockOutOrderService.queryOutStockNoticePrintDetail(stockOutOrderDO); return stockOutOrderService.queryOutStockNoticePrintDetail(stockOutOrderDO);
} }
/**
* 生成出库预约单号C + YYMMDD + 当日累加序号3位不足补零
* 当日累加 = 今日已有单数 + 1
*/
public String generateReserveOrderNumber() {
SimpleDateFormat sdf = new SimpleDateFormat("yyMMdd");
String datePart = sdf.format(new Date());
String prefix = "C" + datePart;
int todayCount = stockOutOrderMapper.countByOrderNumberPrefix(prefix);
String seq = String.format("%03d", todayCount + 1);
return prefix + seq;
}
} }
@@ -246,4 +246,16 @@ public class ReservationStockOutOrderApi extends BaseController {
return getDataTable(list); return getDataTable(list);
} }
@ApiOperation("生成出库预约单号")
@GetMapping("/generateOrderNumber")
public AjaxResult generateOrderNumber() {
return AjaxResult.success(stockOutOrderApplicationService.generateReserveOrderNumber());
}
@ApiOperation("生成出库预约单号/出库业务单号")
@GetMapping("/generateOrderNumber1")
public AjaxResult generateOrderNumber1() {
return AjaxResult.success(stockOutOrderApplicationService.generateReserveOrderNumber1());
}
} }
@@ -15,6 +15,8 @@ import com.mhd.oms.domain.reserveStockOutOrder.repository.facade.IReserveStockOu
import com.mhd.oms.domain.reserveStockOutOrder.repository.po.ReserveStockOutOrderPO; import com.mhd.oms.domain.reserveStockOutOrder.repository.po.ReserveStockOutOrderPO;
import com.mhd.oms.domain.reserveStockOutOrder.repository.todo.ReserveStockOutOrderDO; import com.mhd.oms.domain.reserveStockOutOrder.repository.todo.ReserveStockOutOrderDO;
import com.mhd.oms.domain.reserveStockOutOrder.repository.todo.ReserveStockOutOrderDTO; import com.mhd.oms.domain.reserveStockOutOrder.repository.todo.ReserveStockOutOrderDTO;
import com.mhd.oms.domain.reserveStockOutOrder.repository.vo.LegacyReserveOutDetailVO;
import com.mhd.oms.domain.reserveStockOutOrder.repository.vo.LegacyReserveOutOrderVO;
import com.mhd.oms.domain.reserveStockOutOrder.repository.vo.ReservedInventoryOut; import com.mhd.oms.domain.reserveStockOutOrder.repository.vo.ReservedInventoryOut;
import com.mhd.oms.domain.reserveStockOutOrder.service.ReserveStockOutOrderApplicationService; import com.mhd.oms.domain.reserveStockOutOrder.service.ReserveStockOutOrderApplicationService;
import com.mhd.oms.domain.reserveStockOutOrder.service.ReserveStockOutOrderAssembler; import com.mhd.oms.domain.reserveStockOutOrder.service.ReserveStockOutOrderAssembler;
@@ -294,4 +296,68 @@ public class ReserveStockOutOrderApi extends BaseController {
} }
} }
/**
* 生成出库预约单号
*/
@ApiOperation("生成出库单号")
@GetMapping("/generateOrderNumber")
public AjaxResult generateOrderNumber() {
return AjaxResult.success(stockOutOrderApplicationService.generateReserveOrderNumber());
}
/**
* 老系统出库预约单数据导入两个文件主表+明细
* 通过货主名称仓库类型物料名称等匹配基础数据id类字段不使用
* 仓库类型1=干仓 2=冬仓
* 明细物料名称取物料名称1和物料名称2中有值的那一个
*/
@ApiOperation("老系统出库预约单数据导入")
@PostMapping("/importLegacy")
public ResponseEntity<Map<String, Object>> importLegacyData(
@RequestParam("orderFile") MultipartFile orderFile,
@RequestParam("detailFile") MultipartFile detailFile) {
try {
// 1. 解析两个Excel文件
List<LegacyReserveOutOrderVO> orderList = ExcelParseUtil.parseLegacyOrderExcel(orderFile);
List<LegacyReserveOutDetailVO> detailList = ExcelParseUtil.parseLegacyDetailExcel(detailFile);
// 2. 调用应用服务执行导入
Map<String, Object> result = stockOutOrderApplicationService.importLegacyData(orderList, detailList);
Map<String, Object> successResponse = new HashMap<>();
successResponse.put("code", 200);
successResponse.put("message", "老系统出库预约单数据导入成功");
successResponse.put("orderCount", result.get("orderCount"));
successResponse.put("detailCount", result.get("detailCount"));
if (result.containsKey("warnings")) {
successResponse.put("warnings", result.get("warnings"));
}
return ResponseEntity.ok(successResponse);
} catch (ValidationException e) {
log.error("老系统出库预约单数据验证失败: {}", e.getMessage(), e);
Map<String, Object> errorResponse = new HashMap<>();
errorResponse.put("code", 400);
errorResponse.put("message", "数据验证失败");
errorResponse.put("errorDetails", e.getMessage());
return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(errorResponse);
} catch (IOException e) {
log.error("老系统出库预约单文件处理失败: {}", e.getMessage(), e);
Map<String, Object> errorResponse = new HashMap<>();
errorResponse.put("code", 500);
errorResponse.put("message", "文件处理失败");
errorResponse.put("errorDetails", e.getMessage());
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(errorResponse);
} catch (Exception e) {
log.error("老系统出库预约单导入失败: {}", e.getMessage(), e);
Map<String, Object> errorResponse = new HashMap<>();
errorResponse.put("code", 500);
errorResponse.put("message", "导入失败");
errorResponse.put("errorDetails", e.getMessage());
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(errorResponse);
}
}
} }
@@ -50,7 +50,9 @@ public class ReservationMaterialInventoryApi extends BaseController {
@ApiOperation("查询物料库存列表") @ApiOperation("查询物料库存列表")
@GetMapping("/list") @GetMapping("/list")
public TableDataInfo list(ReservationMaterialInventoryDTO materialInventoryDTO, public TableDataInfo list(ReservationMaterialInventoryDTO materialInventoryDTO,
@RequestParam(value = "customerName", required = false) String customerName) @RequestParam(value = "customerName", required = false) String customerName,
@RequestParam(value = "expiryDateStart", required = false) String expiryDateStart,
@RequestParam(value = "expiryDateEnd", required = false) String expiryDateEnd)
{ {
// 出库分配前端传的是客户名称 customerName这里通过名称查询货主ID使用精确匹配不模糊匹配 // 出库分配前端传的是客户名称 customerName这里通过名称查询货主ID使用精确匹配不模糊匹配
String shipperName = null; // 保存查询到的货主名称 String shipperName = null; // 保存查询到的货主名称
@@ -78,6 +80,8 @@ public class ReservationMaterialInventoryApi extends BaseController {
ReservationMaterialInventoryDO materialInventoryDO = materialInventoryAssembler.toDO(materialInventoryDTO); ReservationMaterialInventoryDO materialInventoryDO = materialInventoryAssembler.toDO(materialInventoryDTO);
materialInventoryDO.setExpiryDateStr(materialInventoryDTO.getExpiryDate()); materialInventoryDO.setExpiryDateStr(materialInventoryDTO.getExpiryDate());
materialInventoryDO.setProductionDateStr(materialInventoryDTO.getProductionDate()); materialInventoryDO.setProductionDateStr(materialInventoryDTO.getProductionDate());
materialInventoryDO.setExpiryDateStart(expiryDateStart);
materialInventoryDO.setExpiryDateEnd(expiryDateEnd);
startPage(); startPage();
// 使用带批次属性的查询方法批次属性值从库存表中获取 // 使用带批次属性的查询方法批次属性值从库存表中获取
List<ReservationMaterialInventoryPO> list = materialInventoryApplicationService.queryListWithBatchAttributes(materialInventoryDO); List<ReservationMaterialInventoryPO> list = materialInventoryApplicationService.queryListWithBatchAttributes(materialInventoryDO);
@@ -281,4 +281,16 @@ public class ReservationStockInOrderApi extends BaseController {
return getDataTable(list); return getDataTable(list);
} }
@ApiOperation("生成入库预约单号")
@GetMapping("/generateOrderNumber")
public AjaxResult generateOrderNumber() {
return AjaxResult.success(stockInOrderApplicationService.generateReserveOrderNumber());
}
@ApiOperation("生成入库预约单号/入库业务单号")
@GetMapping("/generateOrderNumber1")
public AjaxResult generateOrderNumber1() {
return AjaxResult.success(stockInOrderApplicationService.generateReserveOrderNumber1());
}
} }
@@ -10,12 +10,15 @@ import com.mhd.oms.domain.reserveStockInOrder.repository.todo.ReserveStockInOrde
import com.mhd.oms.domain.reserveStockInOrder.repository.todo.ReserveStockInOrderDTO; import com.mhd.oms.domain.reserveStockInOrder.repository.todo.ReserveStockInOrderDTO;
import com.mhd.oms.domain.reserveStockInOrder.repository.util.ExcelParseUtil; import com.mhd.oms.domain.reserveStockInOrder.repository.util.ExcelParseUtil;
import com.mhd.oms.domain.reserveStockInOrder.repository.vo.InAndOutListVo; import com.mhd.oms.domain.reserveStockInOrder.repository.vo.InAndOutListVo;
import com.mhd.oms.domain.reserveStockInOrder.repository.vo.LegacyReserveInDetailVO;
import com.mhd.oms.domain.reserveStockInOrder.repository.vo.LegacyReserveInOrderVO;
import com.mhd.oms.domain.reserveStockInOrder.repository.vo.ReservedInventory; import com.mhd.oms.domain.reserveStockInOrder.repository.vo.ReservedInventory;
import com.mhd.oms.domain.reserveStockInOrder.service.ReserveStockInOrderApplicationService; import com.mhd.oms.domain.reserveStockInOrder.service.ReserveStockInOrderApplicationService;
import com.mhd.oms.domain.reserveStockInOrder.service.ReserveStockInOrderAssembler; import com.mhd.oms.domain.reserveStockInOrder.service.ReserveStockInOrderAssembler;
import com.mhd.system.api.domain.InMaterialDetailTZPD; import com.mhd.system.api.domain.InMaterialDetailTZPD;
import com.mhd.system.api.domain.StockInOrderTZPD; import com.mhd.system.api.domain.StockInOrderTZPD;
import io.swagger.annotations.ApiOperation; import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus; import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity; import org.springframework.http.ResponseEntity;
@@ -34,6 +37,7 @@ import java.util.Map;
* @author gen * @author gen
* @date 2024-05-21 * @date 2024-05-21
*/ */
@Slf4j
@RestController @RestController
@RequestMapping("/reserveStockInOrderApi") @RequestMapping("/reserveStockInOrderApi")
public class ReserveStockInOrderApi extends BaseController { public class ReserveStockInOrderApi extends BaseController {
@@ -256,4 +260,75 @@ public class ReserveStockInOrderApi extends BaseController {
} }
} }
/**
* 老系统入库预约单数据导入主表+明细两个Excel文件批量导入按名称匹配基础数据
*/
@ApiOperation("老系统入库预约单数据导入")
@PostMapping("/importLegacy")
public ResponseEntity<Map<String, Object>> importLegacyExcel(
@RequestParam("orderFile") MultipartFile orderFile,
@RequestParam("detailFile") MultipartFile detailFile) {
try {
List<LegacyReserveInOrderVO> orderList = ExcelParseUtil.parseLegacyOrderExcel(orderFile);
List<LegacyReserveInDetailVO> detailList = ExcelParseUtil.parseLegacyDetailExcel(detailFile);
Map<String, Object> importResult = stockInOrderApplicationService.importLegacyData(orderList, detailList);
Map<String, Object> successResponse = new HashMap<>();
successResponse.put("code", 200);
successResponse.put("message", "老系统数据导入成功");
successResponse.put("orderCount", importResult.get("orderCount"));
successResponse.put("detailCount", importResult.get("detailCount"));
if (importResult.containsKey("warnings")) {
successResponse.put("warnings", importResult.get("warnings"));
}
return ResponseEntity.ok(successResponse);
} catch (ValidationException e) {
// 数据验证失败响应
log.warn("老系统数据导入校验失败: {}", e.getMessage());
Map<String, Object> errorResponse = new HashMap<>();
errorResponse.put("code", 400);
errorResponse.put("message", "数据验证失败");
errorResponse.put("errorDetails", e.getMessage());
return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(errorResponse);
} catch (IOException e) {
// 文件处理失败响应
log.error("老系统数据导入文件处理失败", e);
Map<String, Object> errorResponse = new HashMap<>();
errorResponse.put("code", 500);
errorResponse.put("message", "文件处理失败");
errorResponse.put("errorDetails", e.getClass().getSimpleName() + ": " + e.getMessage());
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(errorResponse);
} catch (Exception e) {
// 其他未知错误响应打印完整堆栈把真正的报错信息报出来
log.error("老系统数据导入发生未知异常", e);
String errorType = e.getClass().getSimpleName();
String errorMsg = e.getMessage() != null ? e.getMessage() : "无详细信息";
// 如果异常带有 cause则再追加 cause 信息方便定位根因
Throwable cause = e.getCause();
StringBuilder detail = new StringBuilder();
detail.append(errorType).append(": ").append(errorMsg);
if (cause != null && cause != e) {
detail.append(" | 根因: ").append(cause.getClass().getSimpleName()).append(": ").append(cause.getMessage());
}
Map<String, Object> errorResponse = new HashMap<>();
errorResponse.put("code", 500);
errorResponse.put("message", detail.toString());
errorResponse.put("errorDetails", detail.toString());
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(errorResponse);
}
}
/**
* 生成入库预约单号
*/
@ApiOperation("生成入库单号")
@GetMapping("/generateOrderNumber")
public AjaxResult generateOrderNumber() {
return AjaxResult.success(stockInOrderApplicationService.generateReserveOrderNumber());
}
} }
+5 -5
View File
@@ -17,16 +17,16 @@ spring:
nacos: nacos:
discovery: discovery:
# server-addr: 127.0.0.1:8848 # server-addr: 127.0.0.1:8848
# 线上测试环境配置 容器名+端口号 # 线上测试环境配置 容器名+端口号
server-addr: 10.33.0.129:6010 # server-addr: 10.33.0.129:6010
# server-addr: 10.102.192.30:6848 server-addr: 10.102.192.30:6848
username: nacos username: nacos
password: manhuoda@2023 password: manhuoda@2023
config: config:
# server-addr: 127.0.0.1:8848 # server-addr: 127.0.0.1:8848
# 线上测试环境配置 容器名+端口号 # 线上测试环境配置 容器名+端口号
server-addr: 10.33.0.129:6010 # server-addr: 10.33.0.129:6010
# server-addr: 10.102.192.30:6848 server-addr: 10.102.192.30:6848
username: nacos username: nacos
password: manhuoda@2023 password: manhuoda@2023
#线上正式环境 #线上正式环境
@@ -650,4 +650,10 @@
<update id="delWShOrderDetail"> <update id="delWShOrderDetail">
update "NGWL_TEST_WMS".RECEIPT_MATERIAL_DETAIL set DEL_FLAG = 2 where DEL_FLAG = 1 and RECEIPT_ORDER_NUMBER = #{receiptOrderNumber} update "NGWL_TEST_WMS".RECEIPT_MATERIAL_DETAIL set DEL_FLAG = 2 where DEL_FLAG = 1 and RECEIPT_ORDER_NUMBER = #{receiptOrderNumber}
</update> </update>
<select id="countByOrderNumberPrefix" resultType="java.lang.Integer" parameterType="java.lang.String">
SELECT COUNT(1)
FROM execution_stock_in_order
WHERE in_order_number LIKE concat(#{prefix}, '%')
</select>
</mapper> </mapper>
@@ -475,4 +475,9 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
update "NGWL_TEST_WMS".out_material_detail set DEL_FLAG = 2 where DEL_FLAG = 1 and out_order_number = #{outOrderNumber} update "NGWL_TEST_WMS".out_material_detail set DEL_FLAG = 2 where DEL_FLAG = 1 and out_order_number = #{outOrderNumber}
</update> </update>
<select id="countByOrderNumberPrefix" resultType="java.lang.Integer" parameterType="java.lang.String">
SELECT COUNT(1)
FROM execution_stock_out_order
WHERE out_order_number LIKE concat(#{prefix}, '%')
</select>
</mapper> </mapper>
@@ -276,6 +276,12 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<if test="productionDateStr != null and productionDateStr != ''"> <if test="productionDateStr != null and productionDateStr != ''">
AND TO_CHAR(a.production_date, 'yyyy-MM-dd') = #{productionDateStr} AND TO_CHAR(a.production_date, 'yyyy-MM-dd') = #{productionDateStr}
</if> </if>
<if test="expiryDateStart != null and expiryDateStart != ''">
and a.expiry_date >= #{expiryDateStart}
</if>
<if test="expiryDateEnd != null and expiryDateEnd != ''">
and a.expiry_date <![CDATA[ < ]]> DATEADD(DAY, 1, #{expiryDateEnd})
</if>
</sql> </sql>
<select id="queryList" parameterType="com.mhd.oms.domain.reservationMaterialInventory.repository.todo.ReservationMaterialInventoryDO" resultMap="MaterialInventoryResult"> <select id="queryList" parameterType="com.mhd.oms.domain.reservationMaterialInventory.repository.todo.ReservationMaterialInventoryDO" resultMap="MaterialInventoryResult">
@@ -330,6 +336,44 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
GROUP BY a.MATERIAL_BASE_INFO_ID GROUP BY a.MATERIAL_BASE_INFO_ID
</select> </select>
<!-- 按物料+过期日期汇总 -->
<select id="queryListByWlExpiry" parameterType="com.mhd.oms.domain.reservationMaterialInventory.repository.todo.ReservationMaterialInventoryDO" resultMap="MaterialInventoryResult">
select
a.material_base_info_id, a.expiry_date, a.shipper_id, a.shipper_code, a.shipper_name,
a.organization_id, a.organization_name, a.top_organization_id,
MAX(a.warehouse_id) AS warehouse_id, MAX(a.warehouse_code) AS warehouse_code, MAX(a.warehouse_name) AS warehouse_name,
MAX(a.storage_section_id) AS storage_section_id, MAX(a.storage_code) AS storage_code, MAX(a.storage_name) AS storage_name,
MAX(a.storage_location_id) AS storage_location_id, MAX(a.storage_location_code) AS storage_location_code, MAX(a.storage_location_name) AS storage_location_name,
MAX(a.batch_number) AS batch_number, MAX(a.material_status_code) AS material_status_code, MAX(a.material_status_name) AS material_status_name,
MAX(a.container_id) AS container_id, MAX(a.container_code) AS container_code, MAX(a.container_type) AS container_type, MAX(a.container_type_name) AS container_type_name,
IFNULL(SUM(a.freeze_quantity), 0) AS freeze_quantity, a.is_able,
IFNULL(SUM(a.inventory_quantity), 0) AS inventory_quantity,
IFNULL(SUM(a.allocation_quantity), 0) AS allocation_quantity,
IFNULL(SUM(a.area), 0) AS area,
IFNULL(SUM(a.NET_WEIGHT), 0) AS NET_WEIGHT,
IFNULL(SUM(a.GROSS_WEIGHT), 0) AS GROSS_WEIGHT,
IFNULL(SUM(a.VOLUME), 0) AS VOLUME,
MAX(a.unit) AS unit,
MAX(a.unit_name) AS unit_name,
MAX(a.production_date) AS production_date,
MAX(a.inventory_date) AS inventory_date,
MAX(a.batch_ref_no) AS batch_ref_no, MAX(a.sheet_ref_no) AS sheet_ref_no, MAX(a.box_pallet_no) AS box_pallet_no,
MAX(a.bar_code) AS inv_bar_code,
MAX(a.in_order_number) AS in_order_number, MAX(a.lot_number) AS lot_number,
b.material_code, b.material_name,
CASE WHEN IFNULL(SUM(a.inventory_quantity), 0) = 0 THEN 1 ELSE 0 END AS sort_order
from reservation_material_inventory a
left join NGWL_TEST_WMS.material_base_info b on a.material_base_info_id = b.material_base_info_id
<where>
<include refid="selectMaterialInventoryPo1"/>
<include refid="JoinMaterialBaseInfoPoWhere"/>
</where>
GROUP BY a.MATERIAL_BASE_INFO_ID, a.EXPIRY_DATE, a.shipper_id, a.shipper_code, a.shipper_name,
a.organization_id, a.organization_name, a.top_organization_id,
b.material_code, b.material_name
order by sort_order, MAX(a.update_time) desc
</select>
<select id="queryListByHz" parameterType="com.mhd.oms.domain.reservationMaterialInventory.repository.todo.ReservationMaterialInventoryDO" resultMap="MaterialInventoryResult"> <select id="queryListByHz" parameterType="com.mhd.oms.domain.reservationMaterialInventory.repository.todo.ReservationMaterialInventoryDO" resultMap="MaterialInventoryResult">
select select
<include refid="selectMaterialInventoryPo"/> <include refid="selectMaterialInventoryPo"/>
@@ -519,21 +519,27 @@
<select id="getByName" parameterType="java.lang.String" resultType="com.mhd.oms.domain.reservationStockInOrder.repository.po.MaterialBaseInfoPO"> <select id="getByName" parameterType="java.lang.String" resultType="com.mhd.oms.domain.reservationStockInOrder.repository.po.MaterialBaseInfoPO">
select * from "NGWL_TEST_WMS".MATERIAL_BASE_INFO where 1 = 1 and DEL_FLAG = 1 and MATERIAL_NAME = #{name} select * from "NGWL_TEST_WMS".MATERIAL_BASE_INFO where 1 = 1 and DEL_FLAG = 1 and MATERIAL_NAME = #{name}
</select> </select>
<select id="getByCode" parameterType="java.lang.String" resultType="com.mhd.oms.domain.reservationStockInOrder.repository.po.MaterialBaseInfoPO"> <select id="getByCode" resultType="com.mhd.oms.domain.reservationStockInOrder.repository.po.MaterialBaseInfoPO">
select * from "NGWL_TEST_WMS".MATERIAL_BASE_INFO where 1 = 1 and DEL_FLAG = 1 and MATERIAL_CODE = #{code} select * from "NGWL_TEST_WMS".MATERIAL_BASE_INFO where 1 = 1 and DEL_FLAG = 1 and MATERIAL_CODE = #{code} and ORGANIZATION_ID = #{orgId}
</select> </select>
<select id="getMaterialBaseInfoList" parameterType="java.lang.String" resultType="com.mhd.oms.domain.reservationStockInOrder.repository.po.MaterialBaseInfoPO"> <select id="getMaterialBaseInfoList" parameterType="java.lang.String" resultType="com.mhd.oms.domain.reservationStockInOrder.repository.po.MaterialBaseInfoPO">
select * from "NGWL_TEST_WMS".MATERIAL_BASE_INFO where 1 = 1 and DEL_FLAG = 1 and material_code = #{id} select * from "NGWL_TEST_WMS".MATERIAL_BASE_INFO where 1 = 1 and DEL_FLAG = 1 and material_code = #{id}
</select> </select>
<select id="getInfoByMaterialBaseInfoIds" parameterType="java.lang.Long" resultType="com.mhd.oms.domain.reservationStockInOrder.repository.po.MaterialWarehouseControlPO"> <!-- <select id="getkcId" resultType="com.mhd.oms.domain.reservationMaterialInventory.repository.po.ReservationMaterialInventoryPO">-->
<!-- select * from "NGWL_TEST_WMS".MATERIAL_INVENTORY where 1 = 1 and DEL_FLAG = 1 and MATERIAL_BASE_INFO_ID = #{id} and ALLOCATION_QUANTITY >= #{q}-->
<!-- </select>-->
<select id="getInfoByMaterialBaseInfoIds" resultType="com.mhd.oms.domain.reservationStockInOrder.repository.po.MaterialWarehouseControlPO">
select * from "NGWL_TEST_WMS".MATERIAL_WAREHOUSE_CONTROL where 1 = 1 and DEL_FLAG = 1 and MATERIAL_BASE_INFO_ID = #{id} select * from "NGWL_TEST_WMS".MATERIAL_WAREHOUSE_CONTROL where 1 = 1 and DEL_FLAG = 1 and MATERIAL_BASE_INFO_ID = #{id}
</select> </select>
<select id="getGoodsInfoByMaterialBaseInfoIds" parameterType="java.lang.Long" resultType="com.mhd.oms.domain.reservationStockInOrder.repository.po.MaterialGoodsRulePO"> <select id="getGoodsInfoByMaterialBaseInfoIds" parameterType="java.lang.Long" resultType="com.mhd.oms.domain.reservationStockInOrder.repository.po.MaterialGoodsRulePO">
select * from "NGWL_TEST_WMS".MATERIAL_GOODS_RULE where 1 = 1 and DEL_FLAG = 1 and MATERIAL_BASE_INFO_ID = #{id} select * from "NGWL_TEST_WMS".MATERIAL_GOODS_RULE where 1 = 1 and DEL_FLAG = 1 and MATERIAL_BASE_INFO_ID = #{id}
</select> </select>
<select id="getkcId" resultType="com.mhd.oms.domain.reservationMaterialInventory.repository.po.ReservationMaterialInventoryPO">
select * from "NGWL_TEST_WMS".MATERIAL_INVENTORY where 1 = 1 and DEL_FLAG = 1 and MATERIAL_BASE_INFO_ID = #{id} and ALLOCATION_QUANTITY >= #{q}
</select>
<select id="getUserNcCode" parameterType="java.lang.Long" resultType="java.lang.String"> <select id="getUserNcCode" parameterType="java.lang.Long" resultType="java.lang.String">
select CUSTOMER_NC_CODE from "NGWL_TEST_USER".USER_SHIPPER where 1 = 1 and DEL_FLAG = 1 and USER_ID = #{id} limit 1 select CUSTOMER_NC_CODE from "NGWL_TEST_USER".USER_SHIPPER where 1 = 1 and DEL_FLAG = 1 and USER_ID = #{id} limit 1
</select> </select>
@@ -649,4 +655,16 @@
<select id="getCustomerOrgCode" resultType="java.lang.String"> <select id="getCustomerOrgCode" resultType="java.lang.String">
select ORG_CODE from "NGWL_TEST_USER".USER_SHIPPER where 1 = 1 and DEL_FLAG = 1 and USER_ID = #{id} select ORG_CODE from "NGWL_TEST_USER".USER_SHIPPER where 1 = 1 and DEL_FLAG = 1 and USER_ID = #{id}
</select> </select>
<select id="countByOrderNumberPrefix" resultType="java.lang.Integer" parameterType="java.lang.String">
SELECT COUNT(1)
FROM reservation_stock_in_order
WHERE in_order_number LIKE concat(#{prefix}, '%')
</select>
<select id="generateReserveOrderNumber1" resultType="java.lang.String">
select in_order_number
FROM reservation_stock_in_order
WHERE in_order_number LIKE concat(#{prefix}, '%')
</select>
</mapper> </mapper>
@@ -470,4 +470,14 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
select max(user_id) as user_id from NGWL_TEST_USER."USER" where ORGANIZATION_ID = #{organizationId} and USER_MEMBER_CODE = #{userMemberCode} and DEL_FLAG = 1 select max(user_id) as user_id from NGWL_TEST_USER."USER" where ORGANIZATION_ID = #{organizationId} and USER_MEMBER_CODE = #{userMemberCode} and DEL_FLAG = 1
</select> </select>
<select id="countByOrderNumberPrefix" resultType="java.lang.Integer" parameterType="java.lang.String">
SELECT COUNT(1)
FROM reservation_stock_out_order
WHERE out_order_number LIKE concat(#{prefix}, '%')
</select>
<select id="generateReserveOrderNumber1" resultType="java.lang.String">
SELECT out_order_number
FROM reservation_stock_out_order
WHERE out_order_number LIKE concat(#{prefix}, '%')
</select>
</mapper> </mapper>
@@ -777,4 +777,58 @@
AND USER_ID = #{id} limit 1 AND USER_ID = #{id} limit 1
</select> </select>
<select id="countByOrderNumberPrefix" resultType="java.lang.Integer" parameterType="java.lang.String">
SELECT COUNT(1)
FROM reserve_stock_in_order
WHERE in_order_number LIKE concat(#{prefix}, '%')
</select>
<select id="generateReserveOrderNumber1" resultType="java.lang.String">
SELECT in_order_number
FROM reserve_stock_in_order
WHERE in_order_number LIKE concat(#{prefix}, '%')
</select>
<!-- 老系统数据导入:根据货主名称查询用户 -->
<select id="getShipperByName" parameterType="java.lang.String" resultType="com.mhd.common.core.domain.po.UserPo">
select USER_ID, USER_NAME, ORGANIZATION_ID, ORGANIZATION_NAME, TOP_ORGANIZATION_ID
from NGWL_TEST_USER."USER"
where DEL_FLAG = 1 and USER_NAME = #{name}
</select>
<!-- 老系统数据导入:根据仓库名称查询仓库(支持模糊匹配,如Excel中"凍倉-陳美玲"匹配系统中"凍倉" -->
<select id="getWarehouseByName" parameterType="java.lang.String" resultType="com.mhd.common.core.domain.po.WarehousePO">
select WAREHOUSE_ID, WAREHOUSE_CODE, WAREHOUSE_NAME
from "NGWL_TEST_SYSTEM".WAREHOUSE
where DEL_FLAG = 1
and (
WAREHOUSE_NAME = #{name}
or #{name} LIKE ('%' || WAREHOUSE_NAME || '%')
)
order by case when WAREHOUSE_NAME = #{name} then 0 else 1 end,
length(WAREHOUSE_NAME) asc
</select>
<!-- 老系统数据导入:根据仓库类型查询仓库(1=干仓 2=冬仓) -->
<select id="getWarehouseByType" parameterType="java.lang.String" resultType="com.mhd.common.core.domain.po.WarehousePO">
select WAREHOUSE_ID, WAREHOUSE_CODE, WAREHOUSE_NAME
from "NGWL_TEST_SYSTEM".WAREHOUSE
where DEL_FLAG = 1
and (
WAREHOUSE_TYPE = #{warehouseType}
or WAREHOUSE_TYPE_NAME = case when #{warehouseType} = '1' then '干仓' when #{warehouseType} = '2' then '冻仓' else null end
)
</select>
<!-- 老系统数据导入:根据货主用户ID查询NC客户编码 -->
<select id="getCustomerNcCodeByUserId" parameterType="java.lang.Long" resultType="java.lang.String">
select CUSTOMER_NC_CODE from "NGWL_TEST_USER".USER_SHIPPER where DEL_FLAG = 1 and USER_ID = #{id} limit 1
</select>
<!-- 老系统数据导入:根据入库单号精确统计(防重) -->
<select id="countByInOrderNumber" resultType="java.lang.Integer" parameterType="java.lang.String">
SELECT COUNT(1)
FROM reserve_stock_in_order
WHERE in_order_number = #{inOrderNumber}
</select>
</mapper> </mapper>
@@ -517,4 +517,35 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<result property="boxPalletNo" column="box_pallet_no"/> <result property="boxPalletNo" column="box_pallet_no"/>
</resultMap> </resultMap>
<select id="countByOrderNumberPrefix" resultType="java.lang.Integer" parameterType="java.lang.String">
SELECT COUNT(1)
FROM reserve_stock_out_order
WHERE out_order_number LIKE concat(#{prefix}, '%')
</select>
<select id="generateReserveOrderNumber1" resultType="java.lang.String">
SELECT out_order_number
FROM reserve_stock_out_order
WHERE out_order_number LIKE concat(#{prefix}, '%')
</select>
<!-- 老系统数据导入:根据出库单号精确统计(防重) -->
<select id="countByOutOrderNumber" resultType="java.lang.Integer" parameterType="java.lang.String">
SELECT COUNT(1)
FROM reserve_stock_out_order
WHERE out_order_number = #{outOrderNumber}
</select>
<!-- 老系统数据导入:根据仓库类型查询仓库
老系统仓库类型 1=干仓 2=冬仓;新系统 WAREHOUSE_TYPE 为数据字典编码
同时尝试匹配 WAREHOUSE_TYPE 编码和 WAREHOUSE_TYPE_NAME 名称,兼容字典值与老系统编码一致或不一致两种情况 -->
<select id="getWarehouseByType" parameterType="java.lang.String" resultType="com.mhd.common.core.domain.po.WarehousePO">
select WAREHOUSE_ID, WAREHOUSE_CODE, WAREHOUSE_NAME
from "NGWL_TEST_SYSTEM".WAREHOUSE
where DEL_FLAG = 1
and (
WAREHOUSE_TYPE = #{warehouseType}
or WAREHOUSE_TYPE_NAME = case when #{warehouseType} = '1' then '干仓' when #{warehouseType} = '2' then '冻仓' else null end
)
</select>
</mapper> </mapper>
@@ -7,12 +7,14 @@ import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient; import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.ComponentScan;
import org.springframework.scheduling.annotation.EnableAsync;
@SpringBootApplication @SpringBootApplication
@EnableRyFeignClients @EnableRyFeignClients
@EnableDiscoveryClient @EnableDiscoveryClient
@MapperScan("com.mhd.wms.domain.**.mapper") @MapperScan("com.mhd.wms.domain.**.mapper")
@EnableMethodCache(basePackages = "com.mhd.platform.domain.**.cache") @EnableMethodCache(basePackages = "com.mhd.platform.domain.**.cache")
@EnableAsync
@ComponentScan(basePackages = { @ComponentScan(basePackages = {
"com.mhd.wms", "com.mhd.wms",
"com.mhd.system.api.factory" "com.mhd.system.api.factory"
@@ -49,12 +49,15 @@ import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils; import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils; import org.springframework.util.CollectionUtils;
import org.springframework.web.multipart.MultipartFile; import org.springframework.web.multipart.MultipartFile;
import javax.annotation.Resource; import javax.annotation.Resource;
import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream; import java.io.InputStream;
import java.util.*; import java.util.*;
import java.util.stream.Collectors; import java.util.stream.Collectors;
@@ -100,6 +103,10 @@ public class MaterialBaseInfoApplicationService {
@Resource @Resource
private MaterialBaseInfoMapper materialBaseInfoMapper; private MaterialBaseInfoMapper materialBaseInfoMapper;
@Autowired
private MaterialBaseInfoAsyncService materialBaseInfoAsyncService;
/** /**
* 分页查询物料基础信息列表 * 分页查询物料基础信息列表
*/ */
@@ -250,7 +257,10 @@ public class MaterialBaseInfoApplicationService {
} }
} }
Long shipperId = materialBaseInfoDO.getShipperId(); Long shipperId = materialBaseInfoDO.getShipperId();
String customerCodeNcJson = materialBaseInfoMapper.getCustomerCodeNcJson(shipperId.toString()); String customerCodeNcJson = null;
if (shipperId != null) {
customerCodeNcJson = materialBaseInfoMapper.getCustomerCodeNcJson(shipperId.toString());
}
if (customerCodeNcJson != null && !customerCodeNcJson.isEmpty()) { if (customerCodeNcJson != null && !customerCodeNcJson.isEmpty()) {
ObjectMapper objectMapper = new ObjectMapper(); ObjectMapper objectMapper = new ObjectMapper();
List<Map<String, Object>> listNc = null; List<Map<String, Object>> listNc = null;
@@ -433,8 +443,47 @@ public class MaterialBaseInfoApplicationService {
return materialBaseInfoDomainService.getInfoByNoOrderReceipt(materialBaseInfoDO); return materialBaseInfoDomainService.getInfoByNoOrderReceipt(materialBaseInfoDO);
} }
/** /**
* 导入物料主数据仅导入主表字段 * 导入物料主数据异步入口
*
* <p>接口层调用此方法将文件保存到临时目录后立即返回"异步处理中"
* 实际导入由 {@link #doImportData(File, String, LoginUser)} 异步执行
* 避免大数据量时接口超时</p>
*/
public AjaxResult importDataAsync(MultipartFile file) {
if (file == null || file.isEmpty()) {
throw new ServiceException("上传文件不能为空");
}
String fileName = file.getOriginalFilename();
if (org.apache.commons.lang3.StringUtils.isBlank(fileName)
|| (!fileName.endsWith(".xls") && !fileName.endsWith(".xlsx"))) {
throw new ServiceException("请上传xls或xlsx格式文件");
}
// 流式写入临时文件避免大文件 getBytes() 导致内存溢出和接口超时
String tmpDir = System.getProperty("java.io.tmpdir") + File.separator + "material_import";
File dir = new File(tmpDir);
if (!dir.exists()) {
dir.mkdirs();
}
String tmpFileName = System.currentTimeMillis() + "_" + fileName;
File tmpFile = new File(dir, tmpFileName);
try {
file.transferTo(tmpFile);
} catch (Exception e) {
throw new ServiceException("文件保存失败:" + e.getMessage());
}
LoginUser loginUser = SecurityUtils.getLoginUser();
// 通过独立的异步 Service 执行导入避免类内部 self-invocation 导致 @Async 失效
materialBaseInfoAsyncService.doImportData(tmpFile, fileName, loginUser);
return AjaxResult.success("导入任务已提交,正在后台异步处理,请稍后查看导入结果日志");
}
/**
* 导入物料主数据仅导入主表字段- 原同步方法保留供其他场景调用
*/ */
@Transactional(rollbackFor = Exception.class) @Transactional(rollbackFor = Exception.class)
public AjaxResult importData(MultipartFile file) { public AjaxResult importData(MultipartFile file) {
@@ -493,7 +542,6 @@ public class MaterialBaseInfoApplicationService {
row.setHsCode(row.getHsCodeImport().trim()); row.setHsCode(row.getHsCodeImport().trim());
} }
normalizeImportBarCodeWhenDuplicateOfHs(row); normalizeImportBarCodeWhenDuplicateOfHs(row);
// 客户模板通常只有货主名称货主id须先按名称解析货主再回填组织勿提前写入登录组织以免组织校验拦截货主匹配
fillIdsFromExistingMasterData(row); fillIdsFromExistingMasterData(row);
fillOrganizationFromShipperIfNeeded(row); fillOrganizationFromShipperIfNeeded(row);
if (!isValidOrgId(row.getOrganizationId()) && isValidOrgId(loginOrgId)) { if (!isValidOrgId(row.getOrganizationId()) && isValidOrgId(loginOrgId)) {
@@ -564,25 +612,20 @@ public class MaterialBaseInfoApplicationService {
materialBaseInfoDO.setMaterialCommon(null); materialBaseInfoDO.setMaterialCommon(null);
materialBaseInfoDO.setMaterialWarehouseControl(null); materialBaseInfoDO.setMaterialWarehouseControl(null);
materialBaseInfoDO.setMaterialBarCodeList(buildImportBarCodeList(row)); materialBaseInfoDO.setMaterialBarCodeList(buildImportBarCodeList(row));
// 商品规则由 buildImportMaterialGoodsRule + insert() 统一写入勿再单独 insert避免 MATERIAL_GOODS_RULE 重复
insert(materialBaseInfoDO); insert(materialBaseInfoDO);
Long materialBaseInfoId = materialBaseInfoDO.getMaterialBaseInfoId(); Long materialBaseInfoId = materialBaseInfoDO.getMaterialBaseInfoId();
//公共信息
MaterialCommonDO materialCommonDO = materialBaseInfoDO.getMaterialCommon(); MaterialCommonDO materialCommonDO = materialBaseInfoDO.getMaterialCommon();
if (materialCommonDO != null) { if (materialCommonDO != null) {
materialCommonDO.setMaterialBaseInfoId(materialBaseInfoId); materialCommonDO.setMaterialBaseInfoId(materialBaseInfoId);
materialCommonDomainService.insert(materialCommonDO); materialCommonDomainService.insert(materialCommonDO);
} }
//仓库控制信息
MaterialWarehouseControlDO materialWarehouseControlDO = materialBaseInfoDO.getMaterialWarehouseControl(); MaterialWarehouseControlDO materialWarehouseControlDO = materialBaseInfoDO.getMaterialWarehouseControl();
if (materialWarehouseControlDO != null) { if (materialWarehouseControlDO != null) {
materialWarehouseControlDO.setMaterialBaseInfoId(materialBaseInfoId); materialWarehouseControlDO.setMaterialBaseInfoId(materialBaseInfoId);
materialWarehouseControlDomainService.insert(materialWarehouseControlDO); materialWarehouseControlDomainService.insert(materialWarehouseControlDO);
} }
//库存预警
materialInventoryWarningDomainService.batchInsertOrUpdate(materialBaseInfoDO); materialInventoryWarningDomainService.batchInsertOrUpdate(materialBaseInfoDO);
//条码信息
materialBarCodeDomainService.batchInsertOrUpdate(materialBaseInfoDO); materialBarCodeDomainService.batchInsertOrUpdate(materialBaseInfoDO);
successCount++; successCount++;
} }
@@ -593,10 +636,11 @@ public class MaterialBaseInfoApplicationService {
return AjaxResult.success("导入成功,共" + successCount + ""); return AjaxResult.success("导入成功,共" + successCount + "");
} }
/** /**
* 使用已存在主数据按名称/编码反查并回填ID * 使用已存在主数据按名称/编码反查并回填ID
*/ */
private void fillIdsFromExistingMasterData(MaterialBaseInfoDTO row) { public void fillIdsFromExistingMasterData(MaterialBaseInfoDTO row) {
if (StringUtils.isBlank(row.getPackName()) && StringUtils.isNotBlank(row.getPackImport())) { if (StringUtils.isBlank(row.getPackName()) && StringUtils.isNotBlank(row.getPackImport())) {
row.setPackName(row.getPackImport().trim()); row.setPackName(row.getPackImport().trim());
} }
@@ -815,10 +859,14 @@ public class MaterialBaseInfoApplicationService {
Object userCode = shipper.get("userCode"); Object userCode = shipper.get("userCode");
Object userMemberCode = shipper.get("userMemberCode"); Object userMemberCode = shipper.get("userMemberCode");
Object entName = shipper.get("shipperEnterpriseName"); Object entName = shipper.get("shipperEnterpriseName");
if (userName == null) { // userName 可能为空字符串而非 null需同时判断空字符串
if (userName == null || String.valueOf(userName).trim().isEmpty()) {
userName = shipper.get("userNameShipper");
}
if (userName == null || String.valueOf(userName).trim().isEmpty()) {
userName = shipper.get("name"); userName = shipper.get("name");
} }
if (userName == null) { if (userName == null || String.valueOf(userName).trim().isEmpty()) {
userName = shipper.get("shipperName"); userName = shipper.get("shipperName");
} }
String normalizedName = StringUtils.isNotBlank(shipperName) ? shipperName : ""; String normalizedName = StringUtils.isNotBlank(shipperName) ? shipperName : "";
@@ -916,7 +964,7 @@ public class MaterialBaseInfoApplicationService {
/** /**
* Excel 已填货主 ID但未填组织时从货主用户补全组织信息 * Excel 已填货主 ID但未填组织时从货主用户补全组织信息
*/ */
private void fillOrganizationFromShipperIfNeeded(MaterialBaseInfoDTO row) { public void fillOrganizationFromShipperIfNeeded(MaterialBaseInfoDTO row) {
if (isValidOrgId(row.getOrganizationId()) || row.getShipperId() == null) { if (isValidOrgId(row.getOrganizationId()) || row.getShipperId() == null) {
return; return;
} }
@@ -975,7 +1023,7 @@ public class MaterialBaseInfoApplicationService {
} }
} }
private void fillOrganizationName(MaterialBaseInfoDTO row, LoginUser loginUser) { public void fillOrganizationName(MaterialBaseInfoDTO row, LoginUser loginUser) {
if (StringUtils.isNotBlank(row.getOrganizationName())) { if (StringUtils.isNotBlank(row.getOrganizationName())) {
return; return;
} }
@@ -995,7 +1043,7 @@ public class MaterialBaseInfoApplicationService {
} }
} }
private void fillClassifyTypeAndUnit(MaterialBaseInfoDTO row) { public void fillClassifyTypeAndUnit(MaterialBaseInfoDTO row) {
normalizeMaterialClassifyImportFields(row); normalizeMaterialClassifyImportFields(row);
// 按组织从 system 主数据反查分类编码与名称列表对齐 // 按组织从 system 主数据反查分类编码与名称列表对齐
fillMaterialClassifyCodesFromSystem(row); fillMaterialClassifyCodesFromSystem(row);
@@ -1176,7 +1224,7 @@ public class MaterialBaseInfoApplicationService {
* 导入约定HS码/HS编码物料条形码为不同列模板表头错位或两列误填相同 HS * 导入约定HS码/HS编码物料条形码为不同列模板表头错位或两列误填相同 HS
* barCode 会与 hsCode 相同此时保留 hsCode清空主表/子表条码避免 HS 写入 bar_code * barCode 会与 hsCode 相同此时保留 hsCode清空主表/子表条码避免 HS 写入 bar_code
*/ */
private void normalizeImportBarCodeWhenDuplicateOfHs(MaterialBaseInfoDTO row) { public void normalizeImportBarCodeWhenDuplicateOfHs(MaterialBaseInfoDTO row) {
if (row == null) { if (row == null) {
return; return;
} }
@@ -1191,7 +1239,7 @@ public class MaterialBaseInfoApplicationService {
} }
} }
private List<MaterialBarCodeDO> buildImportBarCodeList(MaterialBaseInfoDTO row) { public List<MaterialBarCodeDO> buildImportBarCodeList(MaterialBaseInfoDTO row) {
if (StringUtils.isBlank(row.getBarCode())) { if (StringUtils.isBlank(row.getBarCode())) {
return null; return null;
} }
@@ -1231,7 +1279,7 @@ public class MaterialBaseInfoApplicationService {
return idObj == null ? null : Long.valueOf(String.valueOf(idObj)); return idObj == null ? null : Long.valueOf(String.valueOf(idObj));
} }
private MaterialGoodsRuleDO buildImportMaterialGoodsRule(MaterialBaseInfoDTO row) { public MaterialGoodsRuleDO buildImportMaterialGoodsRule(MaterialBaseInfoDTO row) {
String batchName = StringUtils.isNotBlank(row.getBatchRuleNameImport()) String batchName = StringUtils.isNotBlank(row.getBatchRuleNameImport())
? row.getBatchRuleNameImport().trim() ? row.getBatchRuleNameImport().trim()
: (StringUtils.isNotBlank(row.getBatchName()) : (StringUtils.isNotBlank(row.getBatchName())
@@ -1306,7 +1354,7 @@ public class MaterialBaseInfoApplicationService {
.trim(); .trim();
} }
private List<Map<String, Object>> extractTableDataRows(Map<String, Object> resultMap) { public List<Map<String, Object>> extractTableDataRows(Map<String, Object> resultMap) {
if (resultMap == null) { if (resultMap == null) {
return new ArrayList<>(); return new ArrayList<>();
} }
@@ -0,0 +1,274 @@
package com.mhd.wms.application.service.materialBaseInfo;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.TypeReference;
import com.alibaba.fastjson2.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.mhd.common.core.domain.po.UserPo;
import com.mhd.common.core.web.domain.AjaxResult;
import com.mhd.system.api.SystemServiceFeign;
import com.mhd.system.api.UserServiceFeign;
import com.mhd.system.api.model.LoginUser;
import com.mhd.wms.domain.materialBarCode.service.MaterialBarCodeDomainService;
import com.mhd.wms.domain.materialBaseInfo.entity.MaterialBaseInfo;
import com.mhd.wms.domain.materialBaseInfo.repository.facade.IMaterialBaseInfoService;
import com.mhd.wms.domain.materialBaseInfo.repository.mapper.MaterialBaseInfoMapper;
import com.mhd.wms.domain.materialBaseInfo.repository.todo.MaterialBaseInfoDO;
import com.mhd.wms.domain.materialBaseInfo.service.MaterialBaseInfoDomainService;
import com.mhd.wms.domain.materialGoodsRule.service.MaterialGoodsRuleDomainService;
import com.mhd.wms.domain.materialCommon.service.MaterialCommonDomainService;
import com.mhd.wms.domain.materialCommon.repository.todo.MaterialCommonDO;
import com.mhd.wms.domain.materialInventoryWarning.service.MaterialInventoryWarningDomainService;
import com.mhd.wms.domain.materialWarehouseControl.service.MaterialWarehouseControlDomainService;
import com.mhd.wms.domain.materialWarehouseControl.repository.todo.MaterialWarehouseControlDO;
import com.mhd.wms.interfaces.dto.materialBaseInfo.MaterialBaseInfoDTO;
import com.mhd.wms.util.MaterialBaseInfoImportExcelUtil;
import com.mhd.wms.util.ZhTextNormalizeUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.util.*;
import java.util.stream.Collectors;
/**
* 物料主数据异步导入服务
*/
@Slf4j
@Service
public class MaterialBaseInfoAsyncService {
@Autowired
private IMaterialBaseInfoService materialBaseInfoService;
@Autowired
private MaterialBaseInfoMapper materialBaseInfoMapper;
@Autowired
private SystemServiceFeign systemServiceFeign;
@Autowired
private UserServiceFeign userServiceFeign;
@Autowired
private MaterialCommonDomainService materialCommonDomainService;
@Autowired
private MaterialWarehouseControlDomainService materialWarehouseControlDomainService;
@Autowired
private MaterialInventoryWarningDomainService materialInventoryWarningDomainService;
@Autowired
private MaterialBarCodeDomainService materialBarCodeDomainService;
@Autowired
private MaterialBaseInfoDomainService materialBaseInfoDomainService;
@Autowired
private com.mhd.wms.domain.materialGoodsRule.service.MaterialGoodsRuleDomainService materialGoodsRuleDomainService;
@org.springframework.context.annotation.Lazy
@Autowired
private MaterialBaseInfoApplicationService materialBaseInfoApplicationService;
@Async
public void doImportData(File tmpFile, String fileName, LoginUser loginUser) {
long startTime = System.currentTimeMillis();
log.info("=== 物料主数据异步导入开始,文件:{},大小:{}KB ===", fileName, tmpFile.length() / 1024);
try {
List<MaterialBaseInfoDTO> rows;
try (InputStream is = new FileInputStream(tmpFile)) {
rows = MaterialBaseInfoImportExcelUtil.importRows(is);
} catch (Exception e) {
log.error("物料主数据异步导入失败 - 文件解析异常:{}", e.getMessage(), e);
return;
}
if (CollectionUtils.isEmpty(rows)) {
log.warn("物料主数据异步导入结束 - 导入数据为空");
return;
}
Long loginOrgId = null;
Long loginTopOrgId = null;
if (loginUser != null && loginUser.getUserPo() != null) {
loginOrgId = loginUser.getUserPo().getOrganizationId();
loginTopOrgId = loginUser.getUserPo().getTopOrganizationId();
}
StringBuilder errors = new StringBuilder();
Set<String> duplicateInFile = new HashSet<>();
int successCount = 0;
int totalCount = rows.size();
Map<String, Map<String, Object>> packCache = new HashMap<>();
for (int i = 0; i < rows.size(); i++) {
MaterialBaseInfoDTO row = rows.get(i);
int rowNum = i + 2;
if (row == null) {
continue;
}
try {
if (StringUtils.isBlank(row.getMaterialCode())) {
errors.append("").append(rowNum).append("行:物料编码不能为空;");
continue;
}
if (StringUtils.isBlank(row.getMaterialName())) {
errors.append("").append(rowNum).append("行:物料名称不能为空;");
continue;
}
if (row.getNullify() == null) {
row.setNullify(2);
}
if (row.getCommon() == null) {
row.setCommon(2);
}
if (StringUtils.isBlank(row.getHsCode()) && StringUtils.isNotBlank(row.getHsCodeImport())) {
row.setHsCode(row.getHsCodeImport().trim());
}
materialBaseInfoApplicationService.normalizeImportBarCodeWhenDuplicateOfHs(row);
materialBaseInfoApplicationService.fillIdsFromExistingMasterData(row);
materialBaseInfoApplicationService.fillOrganizationFromShipperIfNeeded(row);
if (!isValidOrgId(row.getOrganizationId()) && isValidOrgId(loginOrgId)) {
row.setOrganizationId(loginOrgId);
}
if (row.getTopOrganizationId() == null && isValidOrgId(loginTopOrgId)) {
row.setTopOrganizationId(loginTopOrgId);
}
materialBaseInfoApplicationService.fillOrganizationName(row, loginUser);
String shipperCode = StringUtils.defaultString(row.getShipperCode(), "");
String duplicateKey = row.getOrganizationId() + "|" + shipperCode + "|" + row.getMaterialCode();
if (!duplicateInFile.add(duplicateKey)) {
errors.append("").append(rowNum).append("行:文件内存在重复物料;");
continue;
}
LambdaQueryWrapper<MaterialBaseInfo> wrapper = new LambdaQueryWrapper<MaterialBaseInfo>()
.eq(MaterialBaseInfo::getDelFlag, 1)
.eq(MaterialBaseInfo::getOrganizationId, row.getOrganizationId())
.eq(MaterialBaseInfo::getMaterialCode, row.getMaterialCode());
if (StringUtils.isBlank(row.getShipperCode())) {
wrapper.and(w -> w.isNull(MaterialBaseInfo::getShipperCode).or().eq(MaterialBaseInfo::getShipperCode, ""));
} else {
wrapper.eq(MaterialBaseInfo::getShipperCode, row.getShipperCode());
}
if (materialBaseInfoService.count(wrapper) > 0) {
errors.append("").append(rowNum).append("行:物料已存在;");
continue;
}
materialBaseInfoApplicationService.fillClassifyTypeAndUnit(row);
// 包装规格查询带缓存
String packCacheKey = row.getOrganizationId() + "|" + StringUtils.defaultString(row.getPackName());
Map<String, Object> cachedPack = packCache.get(packCacheKey);
if (cachedPack == null) {
Object result = systemServiceFeign.getPackList(null, row.getPackName(), row.getOrganizationId());
if (result == null) {
packCache.put(packCacheKey, Collections.emptyMap());
errors.append("").append(rowNum).append("行:包装规格查询无返回;");
continue;
}
Map<String, Object> resultMap = JSON.parseObject(JSONObject.toJSONString(result), new TypeReference<Map<String, Object>>() {});
List<Map<String, Object>> rowsPack = extractTableDataRows(resultMap);
if (CollectionUtils.isEmpty(rowsPack)) {
packCache.put(packCacheKey, Collections.emptyMap());
errors.append("").append(rowNum).append("行:包装规格不存在;");
continue;
}
cachedPack = rowsPack.get(0);
packCache.put(packCacheKey, cachedPack);
}
if (cachedPack.isEmpty()) {
errors.append("").append(rowNum).append("行:包装规格不存在(缓存);");
continue;
}
String packCode = cachedPack.get("packCode") == null ? "" : String.valueOf(cachedPack.get("packCode"));
row.setPackCode(packCode);
String packId = cachedPack.get("packId") == null ? "" : String.valueOf(cachedPack.get("packId"));
if (StringUtils.isBlank(packId) || !StringUtils.isNumeric(packId)) {
errors.append("").append(rowNum).append("行:包装规格数据异常;");
continue;
}
row.setPackId(Long.valueOf(packId));
String unitName = cachedPack.get("unitName") == null ? "" : String.valueOf(cachedPack.get("unitName"));
row.setUnitCode("EA");
row.setUnitName(unitName);
MaterialBaseInfoDO materialBaseInfoDO = new MaterialBaseInfoDO();
BeanUtils.copyProperties(row, materialBaseInfoDO);
materialBaseInfoDO.setMaterialGoodsRule(materialBaseInfoApplicationService.buildImportMaterialGoodsRule(row));
materialBaseInfoDO.setMaterialCommon(null);
materialBaseInfoDO.setMaterialWarehouseControl(null);
materialBaseInfoDO.setMaterialBarCodeList(materialBaseInfoApplicationService.buildImportBarCodeList(row));
// 补全创建人信息异步线程没有 SecurityContext loginUser
if (loginUser != null) {
materialBaseInfoDO.setCreateBy(loginUser.getUserid());
materialBaseInfoDO.setCreateByName(loginUser.getUsername());
}
materialBaseInfoDO.setCreateTime(new Date());
// 调用原 ApplicationService insert走完整的插入逻辑含商品规则公共信息NC编码等
materialBaseInfoApplicationService.insert(materialBaseInfoDO);
successCount++;
} catch (Exception e) {
log.error("物料主数据异步导入 - 第{}行处理异常", rowNum, e);
errors.append("").append(rowNum).append("行:处理异常-").append(e.getMessage()).append("");
}
}
long costTime = System.currentTimeMillis() - startTime;
if (errors.length() > 0) {
log.warn("=== 物料主数据异步导入完成,文件:{},总数:{},成功:{},失败:{},耗时:{}ms,失败原因:{} ===",
fileName, totalCount, successCount, totalCount - successCount, costTime, errors);
} else {
log.info("=== 物料主数据异步导入完成,文件:{},总数:{},成功:{},耗时:{}ms ===",
fileName, totalCount, successCount, costTime);
}
} finally {
try {
if (tmpFile.exists()) {
tmpFile.delete();
}
} catch (Exception e) {
log.warn("物料主数据异步导入 - 临时文件清理失败:{}", e.getMessage());
}
}
}
// ====== 以下工具方法 ======
private List<Map<String, Object>> extractTableDataRows(Map<String, Object> resultMap) {
if (resultMap == null) {
return Collections.emptyList();
}
Object data = resultMap.get("data");
if (data == null) {
data = resultMap.get("rows");
}
if (data instanceof List) {
@SuppressWarnings("unchecked")
List<Map<String, Object>> list = (List<Map<String, Object>>) data;
return list;
}
if (data instanceof Map) {
@SuppressWarnings("unchecked")
Map<String, Object> dataMap = (Map<String, Object>) data;
Object innerData = dataMap.get("data");
if (innerData instanceof List) {
@SuppressWarnings("unchecked")
List<Map<String, Object>> list = (List<Map<String, Object>>) innerData;
return list;
}
Object rows = dataMap.get("rows");
if (rows instanceof List) {
@SuppressWarnings("unchecked")
List<Map<String, Object>> list = (List<Map<String, Object>>) rows;
return list;
}
}
return Collections.emptyList();
}
private boolean isValidOrgId(Long id) {
return id != null && id > 0;
}
}
@@ -18,6 +18,7 @@ import com.mhd.wms.domain.materialInventory.repository.po.MaterialInventoryQuery
import com.mhd.wms.domain.materialInventory.repository.todo.MaterialInventoryDO; import com.mhd.wms.domain.materialInventory.repository.todo.MaterialInventoryDO;
import com.mhd.wms.domain.materialInventory.repository.todo.MaterialInventoryQueryListDO; import com.mhd.wms.domain.materialInventory.repository.todo.MaterialInventoryQueryListDO;
import com.mhd.wms.domain.materialInventory.service.MaterialInventoryDomainService; import com.mhd.wms.domain.materialInventory.service.MaterialInventoryDomainService;
import com.mhd.wms.interfaces.dto.materialInventory.MaterialInventoryDTO;
import com.mhd.wms.domain.materialBarCode.repository.facade.IMaterialBarCodeService; import com.mhd.wms.domain.materialBarCode.repository.facade.IMaterialBarCodeService;
import com.mhd.wms.domain.materialBarCode.repository.po.MaterialBarCodePO; import com.mhd.wms.domain.materialBarCode.repository.po.MaterialBarCodePO;
import com.mhd.wms.domain.materialMoreDetail.repository.po.MaterialMoreDetailPO; import com.mhd.wms.domain.materialMoreDetail.repository.po.MaterialMoreDetailPO;
@@ -290,6 +290,17 @@ public class ShiftManageApplicationService {
return shiftManageDomainService.taskDistribution(shiftManageDO); return shiftManageDomainService.taskDistribution(shiftManageDO);
} }
/**
* @description 撤回审核
* @author gen
* @date 2026/7/17
* @param shiftManageDO
* @return Boolean
*/
public Boolean revokeAudit(ShiftManageDO shiftManageDO) {
return shiftManageDomainService.revokeAudit(shiftManageDO);
}
/** /**
* 物料移位PDA与收货上架一致支持 getInfoByApp parent_copy 结构及分批移位 * 物料移位PDA与收货上架一致支持 getInfoByApp parent_copy 结构及分批移位
* 按单移位PDA 仅传 shiftManageIdupdateTime 自动从库中带出该单下所有待移位明细默认 shiftQuantity=quantity * 按单移位PDA 仅传 shiftManageIdupdateTime 自动从库中带出该单下所有待移位明细默认 shiftQuantity=quantity
@@ -545,9 +545,71 @@ public class StockInOrderApplicationService {
info.setKhdm(userNcCode); info.setKhdm(userNcCode);
List<InMaterialDetailPO> materialDetailList = info.getMaterialDetailList(); List<InMaterialDetailPO> materialDetailList = info.getMaterialDetailList();
if (materialDetailList != null && !materialDetailList.isEmpty()) { if (materialDetailList != null && !materialDetailList.isEmpty()) {
for (InMaterialDetailPO inMaterialDetailPO : materialDetailList) { // 收集所有有效的物料基础信息ID
// TODO: 设置物料详情信息 Set<Long> materialBaseInfoIdSet = new HashSet<>();
inMaterialDetailPO.setKhdm(userNcCode); for (InMaterialDetailPO detail : materialDetailList) {
if (detail.getMaterialBaseInfoId() != null && detail.getMaterialBaseInfoId() > 0) {
materialBaseInfoIdSet.add(detail.getMaterialBaseInfoId());
}
}
// 批量查询物料基础信息try-catch保护防止没有ID时NPE
Map<Long, MaterialBaseInfoPO> materialBaseInfoMap = new HashMap<>();
for (Long materialBaseInfoId : materialBaseInfoIdSet) {
try {
MaterialBaseInfoPO materialBaseInfoPO = materialBaseInfoService.getInfo(materialBaseInfoId);
if (materialBaseInfoPO != null) {
materialBaseInfoMap.put(materialBaseInfoId, materialBaseInfoPO);
}
} catch (Exception e) {
log.warn("获取物料基础信息失败,物料基础信息ID:{},错误:{}", materialBaseInfoId, e.getMessage());
}
}
// 填充明细的物料字段物料编码抄码条码单位等
Long shipperId = info.getShipperId();
for (InMaterialDetailPO detail : materialDetailList) {
detail.setKhdm(userNcCode);
Long materialBaseInfoId = detail.getMaterialBaseInfoId();
MaterialBaseInfoPO materialBaseInfoPO = null;
if (materialBaseInfoId != null && materialBaseInfoId > 0) {
materialBaseInfoPO = materialBaseInfoMap.get(materialBaseInfoId);
}
// 兜底ID=0时用物料名称反查
if (materialBaseInfoPO == null && StringUtils.isNotBlank(detail.getMaterialName())) {
try {
MaterialBaseInfoDO queryDO = new MaterialBaseInfoDO();
queryDO.setMaterialName(detail.getMaterialName().trim());
if (shipperId != null && shipperId > 0) {
queryDO.setShipperId(shipperId);
}
List<MaterialBaseInfoPO> list = materialBaseInfoService.queryList(queryDO);
if (list != null && !list.isEmpty()) {
materialBaseInfoPO = list.get(0);
}
} catch (Exception e) {
log.warn("兜底反查物料失败,物料名:{}", detail.getMaterialName());
}
}
if (materialBaseInfoPO != null) {
if (StringUtils.isBlank(detail.getMaterialCode())) {
detail.setMaterialCode(materialBaseInfoPO.getMaterialCode());
}
if (StringUtils.isBlank(detail.getBarCode())) {
detail.setBarCode(materialBaseInfoPO.getBarCode());
}
if (StringUtils.isBlank(detail.getUnitCode())) {
detail.setUnitCode(materialBaseInfoPO.getUnitCode());
}
if (StringUtils.isBlank(detail.getUnitName())) {
detail.setUnitName(materialBaseInfoPO.getUnitName());
}
detail.setPackId(materialBaseInfoPO.getPackId());
detail.setPackCode(materialBaseInfoPO.getPackCode());
detail.setPackName(materialBaseInfoPO.getPackName());
}
} }
info.setMaterialDetailList(materialDetailList); info.setMaterialDetailList(materialDetailList);
} }
@@ -282,9 +282,6 @@ public class StockOutOrderApplicationService {
stockOutOrderPO.setMaterialQuantity(cnt); stockOutOrderPO.setMaterialQuantity(cnt);
} }
BigDecimal checkSum = (mag != null && mag.getCheckQuantitySum() != null)
? mag.getCheckQuantitySum() : BigDecimal.ZERO;
stockOutOrderPO.setCheckQuantity(checkSum);
stockOutOrderPO.setReceiptOrderAccountList( stockOutOrderPO.setReceiptOrderAccountList(
accountByOrderId.getOrDefault(stockOutOrderPO.getOutOrderId(), Collections.emptyList())); accountByOrderId.getOrDefault(stockOutOrderPO.getOutOrderId(), Collections.emptyList()));
} }
@@ -233,7 +233,9 @@ public class StockReceiptOrderApplicationService {
} }
for (ReceiptMaterialDetailPO receiptMaterialDetailPO : receiptMaterialDetailPOList) { for (ReceiptMaterialDetailPO receiptMaterialDetailPO : receiptMaterialDetailPOList) {
MaterialBaseInfoPO materialBaseInfoPO = materialBaseInfoMap.get(receiptMaterialDetailPO.getMaterialBaseInfoId()); MaterialBaseInfoPO materialBaseInfoPO = materialBaseInfoMap.get(receiptMaterialDetailPO.getMaterialBaseInfoId());
receiptMaterialDetailPO.setCopyCode(materialBaseInfoPO.getCopyCode()); if (materialBaseInfoPO != null) {
receiptMaterialDetailPO.setCopyCode(materialBaseInfoPO.getCopyCode());
}
} }
// 4.2 批量查询包装规格信息单位代码为EA的单位名称 // 4.2 批量查询包装规格信息单位代码为EA的单位名称
@@ -32,6 +32,8 @@ public interface MaterialInventoryMapper extends BaseMapper<MaterialInventory>
public List<MaterialInventoryPO> queryListByKw(MaterialInventoryDO materialInventoryDO); public List<MaterialInventoryPO> queryListByKw(MaterialInventoryDO materialInventoryDO);
//查物料库存列表-物料 //查物料库存列表-物料
public List<MaterialInventoryPO> queryListByWl(MaterialInventoryDO materialInventoryDO); public List<MaterialInventoryPO> queryListByWl(MaterialInventoryDO materialInventoryDO);
//查物料库存列表-物料+过期日期
public List<MaterialInventoryPO> queryListByWlExpiry(MaterialInventoryDO materialInventoryDO);
//查物料库存列表-货主 //查物料库存列表-货主
public List<MaterialInventoryPO> queryListByHz(MaterialInventoryDO materialInventoryDO); public List<MaterialInventoryPO> queryListByHz(MaterialInventoryDO materialInventoryDO);
//查物料库存列表-货主+物料同一物料在不同货主下各一行 //查物料库存列表-货主+物料同一物料在不同货主下各一行
@@ -85,6 +85,8 @@ public class MaterialInventoryImpl extends ServiceImpl<MaterialInventoryMapper,
return materialInventoryMapper.queryListByKw(materialInventoryDO); return materialInventoryMapper.queryListByKw(materialInventoryDO);
} else if ("wlkw".equals(queryRule)) { } else if ("wlkw".equals(queryRule)) {
return materialInventoryMapper.queryListByWlKw(materialInventoryDO); return materialInventoryMapper.queryListByWlKw(materialInventoryDO);
} else if ("wlExpiry".equals(queryRule)) {
return materialInventoryMapper.queryListByWlExpiry(materialInventoryDO);
} else if ("all".equals(queryRule)) { } else if ("all".equals(queryRule)) {
return materialInventoryMapper.queryList(materialInventoryDO); return materialInventoryMapper.queryList(materialInventoryDO);
} else { } else {
@@ -817,7 +819,12 @@ public class MaterialInventoryImpl extends ServiceImpl<MaterialInventoryMapper,
materialInventory.setNetWeight(netWeight); materialInventory.setNetWeight(netWeight);
materialInventory.setMaterialBaseInfoId(materialInventoryParamDO.getMaterialBaseInfoId()); materialInventory.setMaterialBaseInfoId(materialInventoryParamDO.getMaterialBaseInfoId());
materialInventory.setInOrderNumber(materialInventoryParamDO.getInOrderNumber()); materialInventory.setInOrderNumber(materialInventoryParamDO.getInOrderNumber());
if (materialBaseInfo != null) { // 优先使用上游传入的货主信息如来自上架单否则再从物料基础信息兜底
if (materialInventoryParamDO.getShipperId() != null) {
materialInventory.setShipperId(materialInventoryParamDO.getShipperId());
materialInventory.setShipperName(materialInventoryParamDO.getShipperName());
materialInventory.setShipperCode(materialInventoryParamDO.getShipperCode());
} else if (materialBaseInfo != null) {
materialInventory.setShipperId(materialBaseInfo.getShipperId()); materialInventory.setShipperId(materialBaseInfo.getShipperId());
materialInventory.setShipperName(materialBaseInfo.getShipperName()); materialInventory.setShipperName(materialBaseInfo.getShipperName());
materialInventory.setShipperCode(materialBaseInfo.getShipperCode()); materialInventory.setShipperCode(materialBaseInfo.getShipperCode());
@@ -2,6 +2,8 @@ package com.mhd.wms.domain.reviewOrder.repository.po;
import com.mhd.common.core.web.domain.BaseVOEntity; import com.mhd.common.core.web.domain.BaseVOEntity;
import com.fasterxml.jackson.annotation.JsonFormat; import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty; import io.swagger.annotations.ApiModelProperty;
import lombok.Data; import lombok.Data;
@@ -18,24 +20,28 @@ import java.util.List;
@ApiModel(value = "复核单主表", description = "复核单主表展示") @ApiModel(value = "复核单主表", description = "复核单主表展示")
public class ReviewOrderPO extends BaseVOEntity { public class ReviewOrderPO extends BaseVOEntity {
@JsonSerialize(using = ToStringSerializer.class)
@ApiModelProperty("复核单主键") @ApiModelProperty("复核单主键")
private Long reviewOrderId; private Long reviewOrderId;
@ApiModelProperty("复核单号") @ApiModelProperty("复核单号")
private String reviewOrderNumber; private String reviewOrderNumber;
@JsonSerialize(using = ToStringSerializer.class)
@ApiModelProperty("出库单ID") @ApiModelProperty("出库单ID")
private Long outOrderId; private Long outOrderId;
@ApiModelProperty("出库单号") @ApiModelProperty("出库单号")
private String outOrderNumber; private String outOrderNumber;
@JsonSerialize(using = ToStringSerializer.class)
@ApiModelProperty("组织ID") @ApiModelProperty("组织ID")
private Long organizationId; private Long organizationId;
@ApiModelProperty("组织名称") @ApiModelProperty("组织名称")
private String organizationName; private String organizationName;
@JsonSerialize(using = ToStringSerializer.class)
@ApiModelProperty("一级组织ID") @ApiModelProperty("一级组织ID")
private Long topOrganizationId; private Long topOrganizationId;
@@ -50,6 +56,7 @@ public class ReviewOrderPO extends BaseVOEntity {
@ApiModelProperty("复核下发时间") @ApiModelProperty("复核下发时间")
private Date issuedTime; private Date issuedTime;
@JsonSerialize(using = ToStringSerializer.class)
@ApiModelProperty("仓库ID") @ApiModelProperty("仓库ID")
private Long warehouseId; private Long warehouseId;
@@ -59,6 +66,7 @@ public class ReviewOrderPO extends BaseVOEntity {
@ApiModelProperty("仓库名称") @ApiModelProperty("仓库名称")
private String warehouseName; private String warehouseName;
@JsonSerialize(using = ToStringSerializer.class)
@ApiModelProperty("客户ID") @ApiModelProperty("客户ID")
private Long customerId; private Long customerId;
@@ -68,6 +76,7 @@ public class ReviewOrderPO extends BaseVOEntity {
@ApiModelProperty("客户名称") @ApiModelProperty("客户名称")
private String customerName; private String customerName;
@JsonSerialize(using = ToStringSerializer.class)
@ApiModelProperty("货主ID") @ApiModelProperty("货主ID")
private Long shipperId; private Long shipperId;
@@ -3,6 +3,7 @@ package com.mhd.wms.domain.shiftManage.service;
import cn.hutool.core.util.ObjectUtil; import cn.hutool.core.util.ObjectUtil;
import cn.hutool.json.JSONUtil; import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper; import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.mhd.common.core.domain.po.UserPo; import com.mhd.common.core.domain.po.UserPo;
import com.mhd.common.core.exception.ServiceException; import com.mhd.common.core.exception.ServiceException;
@@ -14,6 +15,7 @@ import com.mhd.system.api.domain.MaterialInventoryOmsParamDO;
import com.mhd.system.api.domain.cache.AssociationWarehouseCacheDO; import com.mhd.system.api.domain.cache.AssociationWarehouseCacheDO;
import com.mhd.system.api.domain.cache.SystemServiceCacheUtil; import com.mhd.system.api.domain.cache.SystemServiceCacheUtil;
import com.mhd.system.api.model.LoginUser; import com.mhd.system.api.model.LoginUser;
import com.mhd.wms.domain.deliveTask.entity.DeliveTask;
import com.mhd.wms.domain.deliveTask.repository.facade.IDeliveTaskService; import com.mhd.wms.domain.deliveTask.repository.facade.IDeliveTaskService;
import com.mhd.wms.domain.deliveTask.repository.todo.DeliveTaskDO; import com.mhd.wms.domain.deliveTask.repository.todo.DeliveTaskDO;
import com.mhd.wms.domain.inventoryStandingDetail.repository.facade.IInventoryStandingDetailService; import com.mhd.wms.domain.inventoryStandingDetail.repository.facade.IInventoryStandingDetailService;
@@ -484,6 +486,43 @@ public class ShiftManageDomainService {
return shiftManageService.taskDistribution(shiftManageDO); return shiftManageService.taskDistribution(shiftManageDO);
} }
/**
* @description 撤回移位待移位 已创建
* @author gen
* @date 2026/7/17
* @param shiftManageDO
* @return Boolean
*/
@Transactional(rollbackFor = Exception.class)
public Boolean revokeAudit(ShiftManageDO shiftManageDO) {
LoginUser loginUser = SecurityUtils.getLoginUser();
Long shiftManageId = shiftManageDO.getShiftManageId();
if (shiftManageId == null) {
throw new ServiceException("移位单id不能为空");
}
ShiftManage shiftManage = shiftManageService.getById(shiftManageId);
if (shiftManage == null) {
throw new ServiceException("移位单不存在");
}
if (!Integer.valueOf(2).equals(shiftManage.getShiftStatus())) {
throw new ServiceException("移位单【" + shiftManage.getShiftNumber() + "】状态不为待移位,不可撤回");
}
// 删除生成的配送任务taskType=5trackingNumber=shiftNumber
deliveTaskService.remove(new QueryWrapper<DeliveTask>().lambda()
.eq(DeliveTask::getTrackingNumber, shiftManage.getShiftNumber())
.eq(DeliveTask::getTaskType, 5));
// 回退shiftStatus=1已创建taskDistribution=2未下发auditStatus=1未审核
shiftManageService.update(null, new UpdateWrapper<ShiftManage>().lambda()
.set(ShiftManage::getShiftStatus, 1)
.set(ShiftManage::getTaskDistribution, 2)
.set(ShiftManage::getAuditStatus, 1)
.set(ShiftManage::getUpdateBy, loginUser.getUserid())
.set(ShiftManage::getUpdateByName, loginUser.getUsername())
.set(ShiftManage::getUpdateTime, new Date())
.eq(ShiftManage::getShiftManageId, shiftManageId));
return true;
}
/** /**
* 物料移位 * 物料移位
*/ */
@@ -106,12 +106,16 @@ public class MaterialBaseInfoApi extends BaseController {
} }
/** /**
* 导入物料主数据 * 导入物料主数据异步执行
*
* <p>数据量大时同步导入会导致接口超时改为异步模式
* 接口立即返回"已提交异步处理"后台线程执行实际导入
* 导入结果通过日志输出</p>
*/ */
@ApiOperation("导入物料主数据") @ApiOperation("导入物料主数据(异步)")
@PostMapping("/importData") @PostMapping("/importData")
public AjaxResult importData(@RequestParam("file") MultipartFile file) { public AjaxResult importData(@RequestParam("file") MultipartFile file) {
return materialBaseInfoApplicationService.importData(file); return materialBaseInfoApplicationService.importDataAsync(file);
} }
@ApiOperation("物料管理更新推送信息") @ApiOperation("物料管理更新推送信息")
@@ -55,7 +55,9 @@ public class MaterialInventoryApi extends BaseController {
@GetMapping("/list") @GetMapping("/list")
public TableDataInfo list(MaterialInventoryDTO materialInventoryDTO, public TableDataInfo list(MaterialInventoryDTO materialInventoryDTO,
@RequestParam(value = "customerName", required = false) String customerName, @RequestParam(value = "customerName", required = false) String customerName,
@RequestParam(value = "excludeZeroInventoryQuantity", required = false) Boolean excludeZeroInventoryQuantity) @RequestParam(value = "excludeZeroInventoryQuantity", required = false) Boolean excludeZeroInventoryQuantity,
@RequestParam(value = "expiryDateStart", required = false) String expiryDateStart,
@RequestParam(value = "expiryDateEnd", required = false) String expiryDateEnd)
{ {
if (Boolean.TRUE.equals(excludeZeroInventoryQuantity)) { if (Boolean.TRUE.equals(excludeZeroInventoryQuantity)) {
materialInventoryDTO.setExcludeZeroInventoryQuantity(true); materialInventoryDTO.setExcludeZeroInventoryQuantity(true);
@@ -86,6 +88,8 @@ public class MaterialInventoryApi extends BaseController {
MaterialInventoryDO materialInventoryDO = materialInventoryAssembler.toDO(materialInventoryDTO); MaterialInventoryDO materialInventoryDO = materialInventoryAssembler.toDO(materialInventoryDTO);
materialInventoryDO.setExpiryDateStr(materialInventoryDTO.getExpiryDate()); materialInventoryDO.setExpiryDateStr(materialInventoryDTO.getExpiryDate());
materialInventoryDO.setProductionDateStr(materialInventoryDTO.getProductionDate()); materialInventoryDO.setProductionDateStr(materialInventoryDTO.getProductionDate());
materialInventoryDO.setExpiryDateStart(expiryDateStart);
materialInventoryDO.setExpiryDateEnd(expiryDateEnd);
Date updateTime = materialInventoryDTO.getUpdateTime(); Date updateTime = materialInventoryDTO.getUpdateTime();
if (updateTime != null) { if (updateTime != null) {
LocalDateTime localDateTime = updateTime.toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime(); LocalDateTime localDateTime = updateTime.toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime();
@@ -120,4 +120,14 @@ public class ShiftManageApi extends BaseController {
return AjaxResult.success(shiftManageApplicationService.taskDistribution(shiftManageDO)); return AjaxResult.success(shiftManageApplicationService.taskDistribution(shiftManageDO));
} }
/**
* 撤回审核
*/
@ApiOperation("撤回审核")
@PostMapping(value = "/revokeAudit")
public AjaxResult revokeAudit(@RequestBody ShiftManageDTO shiftManageDTO) {
ShiftManageDO shiftManageDO = shiftManageAssembler.toDO(shiftManageDTO);
return AjaxResult.success(shiftManageApplicationService.revokeAudit(shiftManageDO));
}
} }
@@ -36,6 +36,11 @@ public final class MaterialBaseInfoImportExcelUtil {
HEADER_ALIASES.put("淨重(kg)", "净重 单位:千克"); HEADER_ALIASES.put("淨重(kg)", "净重 单位:千克");
HEADER_ALIASES.put("体积(m³)", "体积 单位:立方米"); HEADER_ALIASES.put("体积(m³)", "体积 单位:立方米");
HEADER_ALIASES.put("體積(m³)", "体积 单位:立方米"); HEADER_ALIASES.put("體積(m³)", "体积 单位:立方米");
HEADER_ALIASES.put("", "物料大小-长 单位:米");
HEADER_ALIASES.put("", "物料大小-宽 单位:米");
HEADER_ALIASES.put("", "物料大小-高 单位:米");
HEADER_ALIASES.put("公司名称", "货主名称");
HEADER_ALIASES.put("公司名稱", "货主名称");
} }
public static List<MaterialBaseInfoDTO> importRows(InputStream is) throws Exception { public static List<MaterialBaseInfoDTO> importRows(InputStream is) throws Exception {
+4 -4
View File
@@ -14,18 +14,18 @@ spring:
nacos: nacos:
discovery: discovery:
# server-addr: 127.0.0.1:8848 # server-addr: 127.0.0.1:8848
server-addr: 10.33.0.129:6010 # server-addr: 10.33.0.129:6010
# 线上测试环境配置 容器名+端口号 # 线上测试环境配置 容器名+端口号
# server-addr: 10.102.192.31:6848 server-addr: 10.102.192.31:6848
username: nacos username: nacos
password: manhuoda@2023 password: manhuoda@2023
#线上正式环境 #线上正式环境
# server-addr: 10.102.192.105:6848 # server-addr: 10.102.192.105:6848
config: config:
# server-addr: 127.0.0.1:8848 # server-addr: 127.0.0.1:8848
server-addr: 10.33.0.129:6010 # server-addr: 10.33.0.129:6010
# 线上测试环境配置 容器名+端口号 # 线上测试环境配置 容器名+端口号
# server-addr: 10.102.192.31:6848 server-addr: 10.102.192.31:6848
username: nacos username: nacos
password: manhuoda@2023 password: manhuoda@2023
#线上正式环境 #线上正式环境
@@ -455,6 +455,45 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
loc.storage_location_id, loc.storage_location_code, loc.storage_location_name order by sort_order, a.update_time desc loc.storage_location_id, loc.storage_location_code, loc.storage_location_name order by sort_order, a.update_time desc
</select> </select>
<!-- 按物料+过期日期汇总:相同物料+相同过期日期合并,不同过期日期分开 -->
<select id="queryListByWlExpiry" parameterType="com.mhd.wms.domain.materialInventory.repository.todo.MaterialInventoryDO" resultMap="MaterialInventoryResult">
select
a.material_base_info_id, a.expiry_date, a.shipper_id, a.shipper_code, a.shipper_name,
a.organization_id, a.organization_name, a.top_organization_id,
MAX(a.warehouse_id) AS warehouse_id, MAX(a.warehouse_code) AS warehouse_code, MAX(a.warehouse_name) AS warehouse_name,
MAX(a.storage_section_id) AS storage_section_id, MAX(a.storage_code) AS storage_code, MAX(a.storage_name) AS storage_name,
MAX(a.storage_location_id) AS storage_location_id, MAX(a.storage_location_code) AS storage_location_code, MAX(a.storage_location_name) AS storage_location_name,
MAX(a.batch_number) AS batch_number, MAX(a.material_status_code) AS material_status_code, MAX(a.material_status_name) AS material_status_name,
MAX(a.container_id) AS container_id, MAX(a.container_code) AS container_code, MAX(a.container_type) AS container_type, MAX(a.container_type_name) AS container_type_name,
IFNULL(SUM(a.freeze_quantity), 0) AS freeze_quantity, a.is_able,
IFNULL(SUM(a.inventory_quantity), 0) AS inventory_quantity,
IFNULL(SUM(a.allocation_quantity), 0) AS allocation_quantity,
IFNULL(SUM(a.area), 0) AS area,
IFNULL(SUM(a.NET_WEIGHT), 0) AS NET_WEIGHT,
IFNULL(SUM(a.GROSS_WEIGHT), 0) AS GROSS_WEIGHT,
IFNULL(SUM(a.VOLUME), 0) AS VOLUME,
MAX(a.unit) AS unit,
MAX(a.unit_name) AS unit_name,
MAX(a.production_date) AS production_date,
MAX(a.inventory_date) AS inventory_date,
MAX(a.batch_ref_no) AS batch_ref_no, MAX(a.sheet_ref_no) AS sheet_ref_no, MAX(a.box_pallet_no) AS box_pallet_no,
MAX(a.bar_code) AS inv_bar_code,
MAX(a.in_order_number) AS in_order_number, MAX(a.lot_number) AS lot_number,
b.specification_model,
b.material_code, b.material_name,
CASE WHEN IFNULL(SUM(a.inventory_quantity), 0) = 0 THEN 1 ELSE 0 END AS sort_order
from material_inventory a
left join material_base_info b on a.material_base_info_id = b.material_base_info_id
<where>
<include refid="selectMaterialInventoryPo1"/>
<include refid="com.mhd.wms.domain.materialBaseInfo.repository.mapper.MaterialBaseInfoMapper.JoinMaterialBaseInfoPoWhere"/>
</where>
GROUP BY a.MATERIAL_BASE_INFO_ID, a.EXPIRY_DATE, a.shipper_id, a.shipper_code, a.shipper_name,
a.organization_id, a.organization_name, a.top_organization_id,
b.material_code, b.material_name, b.specification_model
order by sort_order, MAX(a.update_time) desc
</select>
<!-- 按货主+物料汇总:A货主物料1、A货主物料2、B货主物料1、B货主物料2 为 4 行;库位取该货主+该物料下创建时间最新的一条明细 --> <!-- 按货主+物料汇总:A货主物料1、A货主物料2、B货主物料1、B货主物料2 为 4 行;库位取该货主+该物料下创建时间最新的一条明细 -->
<select id="queryListByHzWl" parameterType="com.mhd.wms.domain.materialInventory.repository.todo.MaterialInventoryDO" resultMap="MaterialInventoryResult"> <select id="queryListByHzWl" parameterType="com.mhd.wms.domain.materialInventory.repository.todo.MaterialInventoryDO" resultMap="MaterialInventoryResult">
select select
@@ -580,6 +619,10 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
group by b.material_base_info_id, a.shipper_id, a.batch_number group by b.material_base_info_id, a.shipper_id, a.batch_number
order by max(b.material_name), max(a.shipper_name), a.batch_number order by max(b.material_name), max(a.shipper_name), a.batch_number
</when> </when>
<when test="queryType != null and queryType == 7">
group by b.material_base_info_id, a.shipper_id, a.expiry_date
order by max(b.material_name), max(a.shipper_name), a.expiry_date
</when>
<when test="queryType != null and queryType == 4"> <when test="queryType != null and queryType == 4">
group by a.storage_location_id group by a.storage_location_id
order by max(a.storage_location_code) order by max(a.storage_location_code)
@@ -4,7 +4,7 @@
<mapper namespace="com.mhd.wms.domain.reviewOrder.repository.mapper.ReviewOrderMapper"> <mapper namespace="com.mhd.wms.domain.reviewOrder.repository.mapper.ReviewOrderMapper">
<resultMap type="com.mhd.wms.domain.reviewOrder.repository.po.ReviewOrderPO" id="ReviewOrderResult"> <resultMap type="com.mhd.wms.domain.reviewOrder.repository.po.ReviewOrderPO" id="ReviewOrderResult">
<result property="reviewOrderId" column="review_order_id"/> <id property="reviewOrderId" column="review_order_id"/>
<result property="reviewOrderNumber" column="review_order_number"/> <result property="reviewOrderNumber" column="review_order_number"/>
<result property="outOrderId" column="out_order_id"/> <result property="outOrderId" column="out_order_id"/>
<result property="outOrderNumber" column="out_order_number"/> <result property="outOrderNumber" column="out_order_number"/>
@@ -84,7 +84,7 @@
</resultMap> </resultMap>
<sql id="reviewOrderSelectColumns"> <sql id="reviewOrderSelectColumns">
a.review_order_id, a.review_order_id AS review_order_id,
a.review_order_number, a.review_order_number,
a.out_order_id, a.out_order_id,
a.out_order_number, a.out_order_number,
@@ -154,6 +154,9 @@
<if test="shipperName != null and shipperName != ''"> <if test="shipperName != null and shipperName != ''">
and a.shipper_name like concat('%', #{shipperName}, '%') and a.shipper_name like concat('%', #{shipperName}, '%')
</if> </if>
<if test="shipperId != null and shipperId != ''">
and a.shipper_id like concat('%', #{shipperId}, '%')
</if>
<if test="createTimeStart != null and createTimeStart != ''"> <if test="createTimeStart != null and createTimeStart != ''">
and date_format(a.create_time, '%Y-%m-%d') &gt;= #{createTimeStart} and date_format(a.create_time, '%Y-%m-%d') &gt;= #{createTimeStart}
</if> </if>
+6
View File
@@ -0,0 +1,6 @@
ALTER TABLE NGWL_TEST_SYSTEM.CONTRACT_MANAGE_DETAIL
ADD (SERVICE_ITEMS_CODE VARCHAR(100),
SERVICE_ITEMS_NAME VARCHAR(200));
COMMENT ON COLUMN NGWL_TEST_SYSTEM.CONTRACT_MANAGE_DETAIL.SERVICE_ITEMS_CODE IS '费用类别编码(服务项编码)';
COMMENT ON COLUMN NGWL_TEST_SYSTEM.CONTRACT_MANAGE_DETAIL.SERVICE_ITEMS_NAME IS '费用类别名称(服务项名称)';