diff --git a/mhd-auth/src/main/java/com/mhd/auth/system/controller/SsoAuthorizeController.java b/mhd-auth/src/main/java/com/mhd/auth/system/controller/SsoAuthorizeController.java
index 4891fb10e..024cb8c3f 100644
--- a/mhd-auth/src/main/java/com/mhd/auth/system/controller/SsoAuthorizeController.java
+++ b/mhd-auth/src/main/java/com/mhd/auth/system/controller/SsoAuthorizeController.java
@@ -79,6 +79,7 @@ public class SsoAuthorizeController {
// 5. 重定向到前端页面,token通过URL参数传递
// 前端页面需读取URL中的token参数并存入localStorage
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()));
} catch (Exception e) {
diff --git a/mhd-auth/src/main/java/com/mhd/auth/system/service/SsoAuthorizeService.java b/mhd-auth/src/main/java/com/mhd/auth/system/service/SsoAuthorizeService.java
index e3e6040d6..ee2613ecd 100644
--- a/mhd-auth/src/main/java/com/mhd/auth/system/service/SsoAuthorizeService.java
+++ b/mhd-auth/src/main/java/com/mhd/auth/system/service/SsoAuthorizeService.java
@@ -50,7 +50,7 @@ public class SsoAuthorizeService {
@Value("${sso.public-key}")
private String publicKeyStr;
- @Value("https://diglog.namkwong.com.mo/main_app/sso")
+ @Value("${sso.redirect-url}")
private String redirectUrl;
@Resource
diff --git a/mhd-auth/src/main/java/com/mhd/auth/system/service/SysLoginService.java b/mhd-auth/src/main/java/com/mhd/auth/system/service/SysLoginService.java
index dbf6b5e80..09112dcc3 100644
--- a/mhd-auth/src/main/java/com/mhd/auth/system/service/SysLoginService.java
+++ b/mhd-auth/src/main/java/com/mhd/auth/system/service/SysLoginService.java
@@ -550,11 +550,11 @@ public class SysLoginService {
throw new ServiceException("请输入手机号和短信验证码");
}
- //调用工具类校验,校验手机号格式错误
- if (!RegexUtil.isPhoneLegal(userPhone)) {
- recordLogininfor(userPhone, Constants.LOGIN_FAIL, UserError.USER_PHONE_REG_ERROR.errmsg(), 1);
- throw new DigitalLogisticsException(UserError.USER_PHONE_REG_ERROR);
- }
+// //调用工具类校验,校验手机号格式错误
+// if (!RegexUtil.isPhoneLegal(userPhone)) {
+// recordLogininfor(userPhone, Constants.LOGIN_FAIL, UserError.USER_PHONE_REG_ERROR.errmsg(), 1);
+// throw new DigitalLogisticsException(UserError.USER_PHONE_REG_ERROR);
+// }
//根据域名获取一级组织ID
AjaxResult topOrganizationIdR = organizationServiceFeign.getOrganizationByPath(path, SecurityConstants.INNER);
diff --git a/mhd-auth/src/main/resources/bootstrap.yml b/mhd-auth/src/main/resources/bootstrap.yml
index 0f7b839c1..828fff329 100644
--- a/mhd-auth/src/main/resources/bootstrap.yml
+++ b/mhd-auth/src/main/resources/bootstrap.yml
@@ -15,7 +15,7 @@ spring:
# server-addr: 127.0.0.1:8848
# 线上测试环境配置 容器名+端口号
# server-addr: 10.33.0.129:6010
- server-addr: 10.102.192.30:6848
+ server-addr: 10.102.192.31:6848
username: nacos
password: manhuoda@2023
#线上正式环境
@@ -24,7 +24,7 @@ spring:
# password: manhuoda@2023
config:
# 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
# 线上测试环境配置 容器名+端口号
@@ -52,4 +52,4 @@ sso:
AwIDAQAB
-----END PUBLIC KEY-----
# SSO登录成功后跳转的前端页面地址
- redirect-url: "/"
+ redirect-url: "https://diglog.namkwong.com.mo/main_app/sso"
diff --git a/mhd-bi/src/main/java/com/mhd/bi/domain/biSnapshotSync/support/BiSnapshotWeeklyRandomDataBuilder.java b/mhd-bi/src/main/java/com/mhd/bi/domain/biSnapshotSync/support/BiSnapshotWeeklyRandomDataBuilder.java
index cb72d7b6a..e34d40d82 100644
--- a/mhd-bi/src/main/java/com/mhd/bi/domain/biSnapshotSync/support/BiSnapshotWeeklyRandomDataBuilder.java
+++ b/mhd-bi/src/main/java/com/mhd/bi/domain/biSnapshotSync/support/BiSnapshotWeeklyRandomDataBuilder.java
@@ -127,6 +127,8 @@ public final class BiSnapshotWeeklyRandomDataBuilder {
for (String[] row : Baseline.P_PLATES) {
int dur = jitterInt(Integer.parseInt(row[3]), r);
vehicles.add(PlatformVehicleItemVO.builder()
+ .appointmentTime(Baseline.P_APPOINTMENT_TIME)
+ .workFloor(Baseline.P_WORK_FLOOR)
.plateNumber(row[0])
.status(row[1])
.platformId(row[2])
@@ -394,6 +396,8 @@ public final class BiSnapshotWeeklyRandomDataBuilder {
static final String[] W_CUST_NAMES = {"华东冷链", "华南汽配", "西南快消", "华北家电", "跨境达"};
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 = {
{"粤A12345", "待入场", "#12", "88"},
{"闽D99887", "作业中", "#07", "142"},
diff --git a/mhd-bi/src/main/java/com/mhd/bi/interfaces/facadeApi/biReport/vo/platform/PlatformVehicleItemVO.java b/mhd-bi/src/main/java/com/mhd/bi/interfaces/facadeApi/biReport/vo/platform/PlatformVehicleItemVO.java
index 8ec4ebc49..f98561c13 100644
--- a/mhd-bi/src/main/java/com/mhd/bi/interfaces/facadeApi/biReport/vo/platform/PlatformVehicleItemVO.java
+++ b/mhd-bi/src/main/java/com/mhd/bi/interfaces/facadeApi/biReport/vo/platform/PlatformVehicleItemVO.java
@@ -14,6 +14,12 @@ import lombok.NoArgsConstructor;
@ApiModel("月台监测-作业车辆")
public class PlatformVehicleItemVO {
+ @ApiModelProperty("预约申请时间")
+ private String appointmentTime;
+
+ @ApiModelProperty("作业楼层")
+ private String workFloor;
+
@ApiModelProperty("车牌号码")
private String plateNumber;
diff --git a/mhd-bi/src/main/resources/bootstrap.yml b/mhd-bi/src/main/resources/bootstrap.yml
index fa1d95e1a..b949b746f 100644
--- a/mhd-bi/src/main/resources/bootstrap.yml
+++ b/mhd-bi/src/main/resources/bootstrap.yml
@@ -16,12 +16,12 @@ spring:
# 线上测试环境配置 容器名+端口号
# server-addr: 10.33.0.129:6010
# server-addr: 10.102.192.5:6848
-# username: nacos
-# password: manhuoda@2023
- #线上正式环境
- server-addr: 10.102.192.31:6848
username: nacos
password: manhuoda@2023
+ #线上正式环境
+ server-addr: 10.102.192.31:6848
+# username: nacos
+# password: manhuoda@2023
config:
# server-addr: 127.0.0.1:8848
# 线上测试环境配置 容器名+端口号
diff --git a/mhd-modules/mhd-system/src/main/java/com/mhd/basic/application/service/Lease/LeaseApplicationService.java b/mhd-modules/mhd-system/src/main/java/com/mhd/basic/application/service/Lease/LeaseApplicationService.java
index 8b1631346..611298729 100644
--- a/mhd-modules/mhd-system/src/main/java/com/mhd/basic/application/service/Lease/LeaseApplicationService.java
+++ b/mhd-modules/mhd-system/src/main/java/com/mhd/basic/application/service/Lease/LeaseApplicationService.java
@@ -270,7 +270,7 @@ public class LeaseApplicationService {
* 货主租赁明细
* 定时任务:每天凌晨1点执行,计算前一天的货主租赁明细
*/
- @Scheduled(cron = "0 0 1 * * ?")
+// @Scheduled(cron = "0 0 1 * * ?")
public void shipperLeaseDetails() {
log.info("开始执行货主租赁明细定时任务");
// 计算前一天的日期,将时间设置为当天的0点0分0秒,只保留日期部分
@@ -537,7 +537,7 @@ public class LeaseApplicationService {
/**
* 定时任务散租推送到bms
*/
- @Scheduled(cron = "0 0 0 * * ?")
+// @Scheduled(cron = "0 0 0 * * ?")
public void ScatteredRentalSynchronization() {
LeaseDO leaseDO = new LeaseDO();
leaseDO.setTime(new Date());
diff --git a/mhd-modules/mhd-system/src/main/java/com/mhd/basic/domain/contractManageDetail/entity/ContractManageDetail.java b/mhd-modules/mhd-system/src/main/java/com/mhd/basic/domain/contractManageDetail/entity/ContractManageDetail.java
index 8af878e6e..aafb47a9e 100644
--- a/mhd-modules/mhd-system/src/main/java/com/mhd/basic/domain/contractManageDetail/entity/ContractManageDetail.java
+++ b/mhd-modules/mhd-system/src/main/java/com/mhd/basic/domain/contractManageDetail/entity/ContractManageDetail.java
@@ -98,4 +98,10 @@ public class ContractManageDetail extends BaseVOEntity{
@ApiModelProperty("单据类型")
private String documentType;
+ @ApiModelProperty("费用类别编码")
+ private String serviceItemsCode;
+
+ @ApiModelProperty("费用类别名称")
+ private String serviceItemsName;
+
}
\ No newline at end of file
diff --git a/mhd-modules/mhd-system/src/main/java/com/mhd/basic/domain/contractManageDetail/repository/po/ContractManageDetailPO.java b/mhd-modules/mhd-system/src/main/java/com/mhd/basic/domain/contractManageDetail/repository/po/ContractManageDetailPO.java
index a67500951..14f9c68fc 100644
--- a/mhd-modules/mhd-system/src/main/java/com/mhd/basic/domain/contractManageDetail/repository/po/ContractManageDetailPO.java
+++ b/mhd-modules/mhd-system/src/main/java/com/mhd/basic/domain/contractManageDetail/repository/po/ContractManageDetailPO.java
@@ -97,4 +97,10 @@ public class ContractManageDetailPO extends BaseVOEntity{
@ApiModelProperty("单据类型")
private String documentType;
+ @ApiModelProperty("费用类别编码")
+ private String serviceItemsCode;
+
+ @ApiModelProperty("费用类别名称")
+ private String serviceItemsName;
+
}
\ No newline at end of file
diff --git a/mhd-modules/mhd-system/src/main/java/com/mhd/basic/domain/contractManageDetail/repository/todo/ContractManageDetailDO.java b/mhd-modules/mhd-system/src/main/java/com/mhd/basic/domain/contractManageDetail/repository/todo/ContractManageDetailDO.java
index 0691d5915..57e2b6ac6 100644
--- a/mhd-modules/mhd-system/src/main/java/com/mhd/basic/domain/contractManageDetail/repository/todo/ContractManageDetailDO.java
+++ b/mhd-modules/mhd-system/src/main/java/com/mhd/basic/domain/contractManageDetail/repository/todo/ContractManageDetailDO.java
@@ -102,4 +102,10 @@ public class ContractManageDetailDO extends BaseVOEntity{
@ApiModelProperty("单据类型")
private String documentType;
+
+ @ApiModelProperty("费用类别编码")
+ private String serviceItemsCode;
+
+ @ApiModelProperty("费用类别名称")
+ private String serviceItemsName;
}
\ No newline at end of file
diff --git a/mhd-modules/mhd-system/src/main/java/com/mhd/basic/domain/storageSection/service/StorageSectionDomainService.java b/mhd-modules/mhd-system/src/main/java/com/mhd/basic/domain/storageSection/service/StorageSectionDomainService.java
index db2ba5435..5fbe57933 100644
--- a/mhd-modules/mhd-system/src/main/java/com/mhd/basic/domain/storageSection/service/StorageSectionDomainService.java
+++ b/mhd-modules/mhd-system/src/main/java/com/mhd/basic/domain/storageSection/service/StorageSectionDomainService.java
@@ -91,31 +91,15 @@ public class StorageSectionDomainService {
public Boolean update(StorageSectionDO storageSectionDO) {
LoginUser loginUser = SecurityUtils.getLoginUser();
Long topOrganizationId = loginUser.getUserPo().getTopOrganizationId();
- AssociationWarehouseCacheDO associationWarehouseCacheDO = SystemServiceCacheUtil.getAssociationWarehouseCache(loginUser.getUserid());
- if (topOrganizationId == null || topOrganizationId == 0 || associationWarehouseCacheDO == null) {
- throw new ServiceException("获取当前登陆人组织与登陆仓库失败!");
+ if (topOrganizationId == null || topOrganizationId == 0) {
+ throw new ServiceException("获取当前登陆人组织失败!");
}
- checkStorageSectionDuplicate(topOrganizationId, associationWarehouseCacheDO.getWarehouseId(),
+ // 直接用记录自身的 warehouseId 做唯一校验,不再依赖缓存仓库
+ checkStorageSectionDuplicate(topOrganizationId, storageSectionDO.getWarehouseId(),
storageSectionDO.getStorageCode(), storageSectionDO.getStorageName(),
storageSectionDO.getStorageSectionId());
//设置仓库
setWarehouseInfo(storageSectionDO);
- String storageCode = storageSectionDO.getStorageCode();
- String storageName = storageSectionDO.getStorageName();
- Long warehouseId = storageSectionDO.getWarehouseId();
- List codelist = storageSectionService.list(new QueryWrapper().lambda()
- .eq(StorageSection::getStorageCode, storageCode)
- .eq(StorageSection::getWarehouseId, warehouseId)
- .ne(StorageSection::getStorageSectionId, storageSectionDO.getStorageSectionId())
- .eq(StorageSection::getDelFlag, 1));
- List namelist = storageSectionService.list(new QueryWrapper().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);
}
diff --git a/mhd-modules/mhd-system/src/main/java/com/mhd/basic/interfaces/dto/contractManageDetail/ContractManageDetailDTO.java b/mhd-modules/mhd-system/src/main/java/com/mhd/basic/interfaces/dto/contractManageDetail/ContractManageDetailDTO.java
index 92d2b4400..53ba7b99d 100644
--- a/mhd-modules/mhd-system/src/main/java/com/mhd/basic/interfaces/dto/contractManageDetail/ContractManageDetailDTO.java
+++ b/mhd-modules/mhd-system/src/main/java/com/mhd/basic/interfaces/dto/contractManageDetail/ContractManageDetailDTO.java
@@ -102,4 +102,10 @@ public class ContractManageDetailDTO extends BaseVOEntity{
@ApiModelProperty("单据类型")
private String documentType;
+
+ @ApiModelProperty("费用类别编码")
+ private String serviceItemsCode;
+
+ @ApiModelProperty("费用类别名称")
+ private String serviceItemsName;
}
\ No newline at end of file
diff --git a/mhd-modules/mhd-system/src/main/resources/bootstrap.yml b/mhd-modules/mhd-system/src/main/resources/bootstrap.yml
index 79f1a3df7..aa660b126 100644
--- a/mhd-modules/mhd-system/src/main/resources/bootstrap.yml
+++ b/mhd-modules/mhd-system/src/main/resources/bootstrap.yml
@@ -16,7 +16,7 @@ spring:
# server-addr: 127.0.0.1:8848
# server-addr: 10.33.0.129:6010
# 线上测试环境配置 容器名+端口号
- server-addr: 10.102.192.31:6848
+ server-addr: 10.102.192.30:6848
username: nacos
password: manhuoda@2023
#线上正式环境
@@ -25,7 +25,7 @@ spring:
# server-addr: 127.0.0.1:8848
# server-addr: 10.33.0.129:6010
# 线上测试环境配置 容器名+端口号
- server-addr: 10.102.192.31:6848
+ server-addr: 10.102.192.30:6848
username: nacos
password: manhuoda@2023
#线上正式环境
diff --git a/mhd-modules/mhd-system/src/main/resources/mapper/basic/ExpenseAccountMapper.xml b/mhd-modules/mhd-system/src/main/resources/mapper/basic/ExpenseAccountMapper.xml
index 5b9d6288e..d34d5d030 100644
--- a/mhd-modules/mhd-system/src/main/resources/mapper/basic/ExpenseAccountMapper.xml
+++ b/mhd-modules/mhd-system/src/main/resources/mapper/basic/ExpenseAccountMapper.xml
@@ -148,6 +148,7 @@
AND a.top_organization_id = #{expenseAccountDO.topOrganizationId}
AND a.subject_code = #{expenseAccountDO.subjectCode}
AND a.status = 1
+ LIMIT 1
diff --git a/mhd-user-center/src/main/java/com/mhd/user/application/service/AgreementDetailsApplicationService.java b/mhd-user-center/src/main/java/com/mhd/user/application/service/AgreementDetailsApplicationService.java
index 4b9703459..99d56c911 100644
--- a/mhd-user-center/src/main/java/com/mhd/user/application/service/AgreementDetailsApplicationService.java
+++ b/mhd-user-center/src/main/java/com/mhd/user/application/service/AgreementDetailsApplicationService.java
@@ -1,12 +1,22 @@
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.mhd.common.security.utils.SecurityUtils;
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.UserShipperMapper;
+import com.mhd.user.domain.userAggregate.repository.po.AgreementDetailsPo;
+import com.mhd.system.api.model.LoginUser;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
+import java.util.ArrayList;
+import java.util.Collections;
import java.util.List;
/**
@@ -19,18 +29,87 @@ public class AgreementDetailsApplicationService {
@Resource
private AgreementDetailsMapper agreementDetailsMapper;
+ @Resource
+ private UserShipperMapper userShipperMapper;
+
/**
- * 根据货主ID查询所有协议明细
+ * 根据货主ID查询当前登录用户组织下的协议明细
+ * 从user_shipper表的orgCode字段解析JSON,匹配当前登录用户组织code,
+ * 返回该组织下的agreedaydatas列表
*
* @param shipperId 货主ID
* @return 协议明细列表
*/
- public List listByShipperId(Long shipperId) {
- return agreementDetailsMapper.selectList(
- new LambdaQueryWrapper()
- .eq(AgreementDetails::getShipperId, shipperId)
- .orderByDesc(AgreementDetails::getCreateTime)
- );
+ public List listByShipperId(Long shipperId) {
+ // 1. 获取当前登录用户组织ID
+ LoginUser loginUser = SecurityUtils.getLoginUser();
+ if (ObjectUtil.isNull(loginUser) || ObjectUtil.isNull(loginUser.getUserPo())) {
+ 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 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;
}
/**
diff --git a/mhd-user-center/src/main/java/com/mhd/user/application/service/UserShipperApplicationService.java b/mhd-user-center/src/main/java/com/mhd/user/application/service/UserShipperApplicationService.java
index f70783dd3..a73ad76d5 100644
--- a/mhd-user-center/src/main/java/com/mhd/user/application/service/UserShipperApplicationService.java
+++ b/mhd-user-center/src/main/java/com/mhd/user/application/service/UserShipperApplicationService.java
@@ -23,7 +23,10 @@ import com.mhd.common.core.enums.MessageTypeEnum;
import com.mhd.common.core.enums.WebsocketTypeEnum;
import com.mhd.common.core.feign.ThirdPartyServiceFeign;
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.security.utils.password.PasswordUtil;
import com.mhd.system.api.FinanceServiceFeign;
import com.mhd.system.api.WlhyServiceFeign;
import com.mhd.system.api.domain.UserShipperEntityFeign;
@@ -359,6 +362,254 @@ public class UserShipperApplicationService {
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 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 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 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 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();
+ }
+
/**
* 个人货主认证
*
diff --git a/mhd-user-center/src/main/java/com/mhd/user/domain/userAggregate/repository/po/AgreementDetailsPo.java b/mhd-user-center/src/main/java/com/mhd/user/domain/userAggregate/repository/po/AgreementDetailsPo.java
new file mode 100644
index 000000000..a01334043
--- /dev/null
+++ b/mhd-user-center/src/main/java/com/mhd/user/domain/userAggregate/repository/po/AgreementDetailsPo.java
@@ -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;
+}
diff --git a/mhd-user-center/src/main/java/com/mhd/user/domain/userAggregate/repository/todo/UserShipperDO.java b/mhd-user-center/src/main/java/com/mhd/user/domain/userAggregate/repository/todo/UserShipperDO.java
index e96c43d8c..6fb1d1727 100644
--- a/mhd-user-center/src/main/java/com/mhd/user/domain/userAggregate/repository/todo/UserShipperDO.java
+++ b/mhd-user-center/src/main/java/com/mhd/user/domain/userAggregate/repository/todo/UserShipperDO.java
@@ -244,6 +244,12 @@ public class UserShipperDO extends UserDO {
@ApiModelProperty("货主/供应商/客户名称")
private String userNameShipper;
+ @ApiModelProperty("用户名称")
+ private String userName;
+
+ @ApiModelProperty("用户电话")
+ private String userPhone;
+
@ApiModelProperty("联系人")
private String emergencyContactName;
diff --git a/mhd-user-center/src/main/java/com/mhd/user/interfaces/facade/UserShipperAPI.java b/mhd-user-center/src/main/java/com/mhd/user/interfaces/facade/UserShipperAPI.java
index f070f084b..39144e917 100644
--- a/mhd-user-center/src/main/java/com/mhd/user/interfaces/facade/UserShipperAPI.java
+++ b/mhd-user-center/src/main/java/com/mhd/user/interfaces/facade/UserShipperAPI.java
@@ -352,8 +352,20 @@ public class UserShipperAPI extends BaseController {
@PostMapping("/wxGetPhoneNumber")
public AjaxResult wxGetPhoneNumber(@RequestBody com.mhd.user.interfaces.dto.wechat.WxPhoneNumberDTO dto) {
LoginUser loginUser = SecurityUtils.getLoginUser();
- Long organizationId = (loginUser != null && loginUser.getUserPo() != null)
+ Long organizationId = (loginUser != null && loginUser.getUserPo() != null)
? loginUser.getUserPo().getOrganizationId() : null;
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());
+ }
+ }
}
\ No newline at end of file
diff --git a/mhd-user-center/src/main/resources/bootstrap.yml b/mhd-user-center/src/main/resources/bootstrap.yml
index 7b6baaea4..dd13bfba5 100644
--- a/mhd-user-center/src/main/resources/bootstrap.yml
+++ b/mhd-user-center/src/main/resources/bootstrap.yml
@@ -20,15 +20,15 @@ spring:
discovery:
# server-addr: 127.0.0.1:8848
# 线上测试环境配置 容器名+端口号
- server-addr: 10.33.0.129:6010
-# server-addr: 10.102.192.30:6848
+# server-addr: 10.33.0.129:6010
+ server-addr: 10.102.192.31:6848
username: nacos
password: manhuoda@2023
config:
# server-addr: 127.0.0.1:8848
# 线上测试环境配置 容器名+端口号
- server-addr: 10.33.0.129:6010
-# server-addr: 10.102.192.30:6848
+# server-addr: 10.33.0.129:6010
+ server-addr: 10.102.192.31:6848
username: nacos
password: manhuoda@2023
group: DEFAULT_GROUP # 默认分组就是DEFAULT_GROUP,如果使用默认分组可以不配置
diff --git a/mhd-user-center/src/main/resources/mapper/UserShipperMapper.xml b/mhd-user-center/src/main/resources/mapper/UserShipperMapper.xml
index f9bffc4e9..38524dcd0 100644
--- a/mhd-user-center/src/main/resources/mapper/UserShipperMapper.xml
+++ b/mhd-user-center/src/main/resources/mapper/UserShipperMapper.xml
@@ -75,7 +75,9 @@
AND b.del_flag = 1
- SELECT b.shipper_id,
+ SELECT b.area,
+ b.detail_address,
+ b.shipper_id,
a.user_id,
b.parent_shipper_id,
b.shipper_type,
diff --git a/mhd_bms/src/main/java/com/mhd/bms/application/server/billManage/BillManageApplicationService.java b/mhd_bms/src/main/java/com/mhd/bms/application/server/billManage/BillManageApplicationService.java
index 50f706d8d..3de55f4d1 100644
--- a/mhd_bms/src/main/java/com/mhd/bms/application/server/billManage/BillManageApplicationService.java
+++ b/mhd_bms/src/main/java/com/mhd/bms/application/server/billManage/BillManageApplicationService.java
@@ -136,8 +136,12 @@ public class BillManageApplicationService {
List billManagePOS = billManageDomainService.queryList(billManageDO);
for (BillManagePO billManagePO : billManagePOS) {
String billNumber = billManagePO.getBillNumber(); // 获取账单编号
+ // 原有 - 前端列表用,不变
List billDetails = billDetailMapper.selectList(new LambdaQueryWrapper().eq(BillDetail::getBillNumber, billNumber));
billManagePO.setBillDetailList(billDetails);
+ // 新增 - 导出用,LEFT JOIN billing_statement 拿到费用科目
+ List billDetailPOs = billDetailMapper.getDetailsByBillManageId(billManagePO.getBillManageId());
+ billManagePO.setBillDetailPOList(billDetailPOs);
}
return billManagePOS;
}
@@ -363,6 +367,19 @@ public class BillManageApplicationService {
billDetailDTO1.setFeeType(billDetailDTO1.getServiceItemsName());
});
}
+ //同步更新已有计费流水(调整账单时可修改已有费用)
+ List 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);
//更新账单金额
@@ -478,6 +495,19 @@ public class BillManageApplicationService {
item.setFeeType(item.getServiceItemsName());
});
}
+ //同步更新已有计费流水(新增账单时可修改已有费用)
+ List 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;
@@ -515,105 +545,51 @@ public class BillManageApplicationService {
}
/**
- * 复制账单
+ * 复制账单-获取原账单数据供前端回显
+ * 前端拿到数据后跳转到类似修改/新增账单的页面,用户修改后通过addBill接口提交新增
*/
- @Transactional
- public Boolean copyBill(BillManageDTO billManageDTO) {
- LoginUser loginUser = SecurityUtils.getLoginUser();
- if (ObjectUtil.isNull(loginUser)) {
- throw new DigitalLogisticsException(UserError.TIMEOUT);
- }
+ public BillManagePO copyBill(BillManageDTO billManageDTO) {
if (billManageDTO.getBillManageId() == null) {
throw new ServiceException("原账单id不能为空");
}
- // 1. 获取原账单信息
+ // 获取原账单信息
BillManagePO originalBill = billManageDomainService.getInfo(billManageDTO.getBillManageId());
if (null == originalBill) {
throw new ServiceException("原账单信息未找到");
}
- // 2. 获取原账单明细
+ // 获取原账单明细
List originalDetails = billDetailDomainService.getDetailsByBillManageId(billManageDTO.getBillManageId());
if (originalDetails == null || originalDetails.isEmpty()) {
throw new ServiceException("原账单明细为空,无法复制");
}
- // 3. 创建新账单,除账单编号外完全复制原账单
- String newBillNumber = OrderSequence.getOrderCode("ZD");
- BillManage newBill = new BillManage();
- BeanUtils.copyProperties(originalBill, newBill);
- newBill.setBillManageId(null);
- newBill.setBillNumber(newBillNumber);
- newBill.setCreateBy(loginUser.getUserPo().getUserId());
- newBill.setCreateByName(loginUser.getUserPo().getUserName());
- newBill.setCreateTime(new Date());
- newBill.setUpdateBy(loginUser.getUserPo().getUserId());
- newBill.setUpdateByName(loginUser.getUserPo().getUserName());
- newBill.setUpdateTime(new Date());
- newBill.setDelFlag(1);
- // 复制后重置状态字段为初始值
- // 账单状态、对账状态、发票状态重置
- newBill.setBillState(1); // 1-未确认
- newBill.setBillStep(1); // 1-发起对账
- newBill.setReconciliationStatus(0); // 1-暂未确认
- newBill.setIsInvoice(0); // 0-未索取
- // 实收=0,未收=账单金额
- newBill.setActualReceivedAmount(BigDecimal.ZERO);
- newBill.setBillAmountUnsettled(newBill.getBillAmount());
- newBill.setBillAmountSettlement(BigDecimal.ZERO);
- // NC同步状态重置
- newBill.setSynchronousStatus(0); // 0-未同步
- 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("复制账单失败,请重试");
+ // 重置关键字段为初始值,清空id等,方便前端回显后直接提交新增
+ originalBill.setBillManageId(null);
+ originalBill.setBillNumber(null);
+ originalBill.setBillState(1);
+ originalBill.setBillStep(1);
+ originalBill.setReconciliationStatus(0);
+ originalBill.setIsInvoice(0);
+ originalBill.setActualReceivedAmount(BigDecimal.ZERO);
+ originalBill.setBillAmountUnsettled(originalBill.getBillAmount());
+ originalBill.setBillAmountSettlement(BigDecimal.ZERO);
+ originalBill.setSynchronousStatus(0);
+ originalBill.setSkSynchronousStatus(0);
+ originalBill.setApplyNumber(null);
+ originalBill.setSettlementTime(null);
+ originalBill.setSynchronousTime(null);
+ originalBill.setSkSynchronousTime(null);
+ originalBill.setInvoiceId(null);
+ originalBill.setInvoiceMakeTime(null);
+ originalBill.setNcId(null);
+ originalBill.setSkNcId(null);
+ // 明细也清空id
+ for (BillDetailPO detail : originalDetails) {
+ detail.setBillDetailId(null);
+ detail.setBillManageId(null);
+ detail.setBillNumber(null);
}
- // 4. 复制账单明细
- List newDetailList = new ArrayList<>();
- 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 originalStatements = billingStatementDomainService.getDetailsByManageId(billManageDTO.getBillManageId());
- boolean flagThree = true;
- if (originalStatements != null && !originalStatements.isEmpty()) {
- List 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;
+ originalBill.setBillDetailPOList(originalDetails);
+ return originalBill;
}
/**
diff --git a/mhd_bms/src/main/java/com/mhd/bms/interfaces/dto/billManage/BillManageExportVO.java b/mhd_bms/src/main/java/com/mhd/bms/interfaces/dto/billManage/BillManageExportVO.java
new file mode 100644
index 000000000..e7ce56b74
--- /dev/null
+++ b/mhd_bms/src/main/java/com/mhd/bms/interfaces/dto/billManage/BillManageExportVO.java
@@ -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;
+}
diff --git a/mhd_bms/src/main/java/com/mhd/bms/interfaces/facadeApi/BillManageApi.java b/mhd_bms/src/main/java/com/mhd/bms/interfaces/facadeApi/BillManageApi.java
index bef4396b4..f2816b63e 100644
--- a/mhd_bms/src/main/java/com/mhd/bms/interfaces/facadeApi/BillManageApi.java
+++ b/mhd_bms/src/main/java/com/mhd/bms/interfaces/facadeApi/BillManageApi.java
@@ -6,6 +6,8 @@ import java.util.Set;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
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.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.infrastructure.utils.UniqueKeyUtil;
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.utils.poi.ExcelUtil;
import com.mhd.common.log.annotation.Log;
import com.mhd.common.log.enums.BusinessType;
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.interfaces.assembler.billManage.BillManageAssembler;
import javax.annotation.Resource;
+import javax.servlet.http.HttpServletResponse;
import com.mhd.common.core.web.controller.BaseController;
import com.mhd.common.core.web.domain.AjaxResult;
import com.mhd.common.core.web.page.TableDataInfo;
@@ -79,6 +84,55 @@ public class BillManageApi extends BaseController{
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 list = billManageApplicationService.queryList(billManageDO);
+
+ //扁平化处理:一条明细生成一行
+ List exportList = new ArrayList<>();
+ for (BillManagePO bill : list) {
+ List 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 util = new ExcelUtil<>(BillManageExportVO.class);
+ util.exportExcel(response, exportList, "应收账单");
+ }
+
@ApiOperation("获取nc推送日志")
@GetMapping(value = "/getNcLog")
public AjaxResult getNcLog(@RequestParam(name = "billManageId") Long billManageId, @RequestParam(name = "type") Long type)
@@ -258,7 +312,7 @@ public class BillManageApi extends BaseController{
}
- @ApiOperation("复制账单")
+ @ApiOperation("复制账单-获取原账单数据用于回显")
@PostMapping("/copyBill")
public AjaxResult copyBill(@RequestBody BillManageDTO billManageDTO)
{
@@ -266,8 +320,8 @@ public class BillManageApi extends BaseController{
throw new ServiceException("原账单id不能为空");
}
try {
- Boolean result = billManageApplicationService.copyBill(billManageDTO);
- return toAjax(result);
+ BillManagePO result = billManageApplicationService.copyBill(billManageDTO);
+ return AjaxResult.success(result);
}catch (Exception e){
return AjaxResult.error("复制账单失败:"+e.getMessage());
}
diff --git a/mhd_bms/src/main/resources/mapper/BusinessDocumentMapper.xml b/mhd_bms/src/main/resources/mapper/BusinessDocumentMapper.xml
index 9c6f2ffcc..7e6608fe0 100644
--- a/mhd_bms/src/main/resources/mapper/BusinessDocumentMapper.xml
+++ b/mhd_bms/src/main/resources/mapper/BusinessDocumentMapper.xml
@@ -166,12 +166,18 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
AND contract_name like concat('%', #{businessDocumentDO.contractName}, '%')
+
+
+
- AND bill_amount like concat('%', #{businessDocumentDO.billAmount}, '%')
+ and bill_amount = #{businessDocumentDO.billAmount}
- AND estimated_cost like concat('%', #{businessDocumentDO.estimatedCost}, '%')
+ AND estimated_cost = #{businessDocumentDO.estimatedCost}
+
+
+
AND first_subject_name like concat('%', #{businessDocumentDO.firstSubjectName}, '%')
@@ -193,6 +199,9 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
AND document_type_code = #{businessDocumentDO.documentTypeCode}
+
+ AND document_type_code = #{businessDocumentDO.salesmanId}
+
and business_document_id in
diff --git a/mhd_oms/src/main/java/com/mhd/oms/domain/executionStockInOrder/repository/mapper/ExecutionStockInOrderMapper.java b/mhd_oms/src/main/java/com/mhd/oms/domain/executionStockInOrder/repository/mapper/ExecutionStockInOrderMapper.java
index a83ad2a97..e2621b868 100644
--- a/mhd_oms/src/main/java/com/mhd/oms/domain/executionStockInOrder/repository/mapper/ExecutionStockInOrderMapper.java
+++ b/mhd_oms/src/main/java/com/mhd/oms/domain/executionStockInOrder/repository/mapper/ExecutionStockInOrderMapper.java
@@ -68,4 +68,5 @@ public interface ExecutionStockInOrderMapper extends BaseMapper queryListByWl(ReservationMaterialInventoryDO materialInventoryDO);
//查物料库存列表-货主
public List queryListByHz(ReservationMaterialInventoryDO materialInventoryDO);
+ //查物料库存列表-物料+过期日期
+ public List queryListByWlExpiry(ReservationMaterialInventoryDO materialInventoryDO);
public MaterialBaseInfo getByInfoId(@Param("id") Long id);
diff --git a/mhd_oms/src/main/java/com/mhd/oms/domain/reservationMaterialInventory/repository/persistence/ReservationMaterialInventoryImpl.java b/mhd_oms/src/main/java/com/mhd/oms/domain/reservationMaterialInventory/repository/persistence/ReservationMaterialInventoryImpl.java
index edf99e0ec..508bf043b 100644
--- a/mhd_oms/src/main/java/com/mhd/oms/domain/reservationMaterialInventory/repository/persistence/ReservationMaterialInventoryImpl.java
+++ b/mhd_oms/src/main/java/com/mhd/oms/domain/reservationMaterialInventory/repository/persistence/ReservationMaterialInventoryImpl.java
@@ -64,6 +64,8 @@ public class ReservationMaterialInventoryImpl extends ServiceImpl getMaterialBaseInfoList(@Param("id") String id);
+ public List getkcId(@Param("id") Long id,@Param("q") BigDecimal q);
+
public MaterialWarehouseControlPO getInfoByMaterialBaseInfoIds(@Param("id") Long id);
public MaterialGoodsRulePO getGoodsInfoByMaterialBaseInfoIds(@Param("id") Long id);
- public List getkcId(@Param("id") Long id, @Param("q") BigDecimal q);
+// public List getkcId(@Param("id") Long id, @Param("q") BigDecimal q);
public String getUserNcCode(@Param("id") Long id);
@@ -69,4 +71,8 @@ public interface ReservationStockInOrderMapper extends BaseMapper generateReserveOrderNumber1(@Param("prefix") String prefix);
}
\ No newline at end of file
diff --git a/mhd_oms/src/main/java/com/mhd/oms/domain/reservationStockInOrder/repository/persistence/ReservationStockInOrderImpl.java b/mhd_oms/src/main/java/com/mhd/oms/domain/reservationStockInOrder/repository/persistence/ReservationStockInOrderImpl.java
index 0584639a8..93070d2f4 100644
--- a/mhd_oms/src/main/java/com/mhd/oms/domain/reservationStockInOrder/repository/persistence/ReservationStockInOrderImpl.java
+++ b/mhd_oms/src/main/java/com/mhd/oms/domain/reservationStockInOrder/repository/persistence/ReservationStockInOrderImpl.java
@@ -33,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.todo.ReservationStockInOrderDO;
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.repository.facade.IReservationStockOutOrderService;
import com.mhd.oms.domain.reservationStockOutOrder.repository.mapper.ReservationStockOutOrderMapper;
@@ -84,6 +85,8 @@ public class ReservationStockInOrderImpl extends ServiceImpl reservationMaterialInventoryPOS = stockInOrderMapper.getkcId(materialBaseInfoId, new BigDecimal(productDetail.getPieceCount()).setScale(2, BigDecimal.ROUND_HALF_UP));
if (reservationMaterialInventoryPOS != null&&reservationMaterialInventoryPOS.size() > 0) {
@@ -266,9 +271,25 @@ public class ReservationStockInOrderImpl extends ServiceImpl reservationInMaterialDetailDOList = new ArrayList<>();
int index = 1;
@@ -484,7 +507,8 @@ public class ReservationStockInOrderImpl extends ServiceImpl1) {
- reservationStockInOrder.setInOrderNumber(OrderSequence.getOrderCode("RK"));
- } else {
- reservationStockInOrder.setInOrderNumber(inOrderNumber);
- }
+ reservationStockInOrder.setInOrderNumber(generateExecutionOrderNumber(warehouseCode));
List inMaterialDetailList = new ArrayList<>();
int index = 1;
@@ -691,11 +694,7 @@ public class ReservationStockInOrderDomainService {
reservationStockInOrder.setWarehouseCode(warehouseCode);
reservationStockInOrder.setWarehouseName(warehouseName);
reservationStockInOrder.setBusinessInOrderNumber(inOrderNumber);
- if (materialDetailGroupByWarehouse!=null&&materialDetailGroupByWarehouse.size()>1) {
- reservationStockInOrder.setInOrderNumber(OrderSequence.getOrderCode("RK"));
- } else {
- reservationStockInOrder.setInOrderNumber(inOrderNumber);
- }
+ reservationStockInOrder.setInOrderNumber(generateExecutionOrderNumber(warehouseCode));
List inMaterialDetailList = new ArrayList<>();
int index = 1;
@@ -1212,4 +1211,49 @@ public class ReservationStockInOrderDomainService {
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 orderNumber1 = reservationStockInOrderMapper.generateReserveOrderNumber1(prefix);
+ List orderNumber2 = reserveStockInOrderMapper.generateReserveOrderNumber1(prefix);
+ List 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;
+ }
}
\ No newline at end of file
diff --git a/mhd_oms/src/main/java/com/mhd/oms/domain/reservationStockOutOrder/repository/mapper/ReservationStockOutOrderMapper.java b/mhd_oms/src/main/java/com/mhd/oms/domain/reservationStockOutOrder/repository/mapper/ReservationStockOutOrderMapper.java
index b22548db1..89487e570 100644
--- a/mhd_oms/src/main/java/com/mhd/oms/domain/reservationStockOutOrder/repository/mapper/ReservationStockOutOrderMapper.java
+++ b/mhd_oms/src/main/java/com/mhd/oms/domain/reservationStockOutOrder/repository/mapper/ReservationStockOutOrderMapper.java
@@ -37,4 +37,8 @@ public interface ReservationStockOutOrderMapper extends BaseMapper queryOutStockNoticePrintDetail(ReservationStockOutOrderDO stockOutOrderDO);
Long queryShipperId(@Param("userMemberCode") String userMemberCode,@Param("organizationId") Long organizationId);
+
+ int countByOrderNumberPrefix(@Param("prefix") String prefix);
+
+ List generateReserveOrderNumber1(@Param("prefix") String prefix);
}
\ No newline at end of file
diff --git a/mhd_oms/src/main/java/com/mhd/oms/domain/reservationStockOutOrder/service/ReservationStockOutOrderApplicationService.java b/mhd_oms/src/main/java/com/mhd/oms/domain/reservationStockOutOrder/service/ReservationStockOutOrderApplicationService.java
index a51006cb8..877149037 100644
--- a/mhd_oms/src/main/java/com/mhd/oms/domain/reservationStockOutOrder/service/ReservationStockOutOrderApplicationService.java
+++ b/mhd_oms/src/main/java/com/mhd/oms/domain/reservationStockOutOrder/service/ReservationStockOutOrderApplicationService.java
@@ -1743,4 +1743,11 @@ public class ReservationStockOutOrderApplicationService {
return filteredList;
}
+ public String generateReserveOrderNumber() {
+ return stockOutOrderDomainService.generateReserveOrderNumber();
+ }
+
+ public String generateReserveOrderNumber1() {
+ return stockOutOrderDomainService.generateReserveOrderNumber1();
+ }
}
\ No newline at end of file
diff --git a/mhd_oms/src/main/java/com/mhd/oms/domain/reservationStockOutOrder/service/ReservationStockOutOrderDomainService.java b/mhd_oms/src/main/java/com/mhd/oms/domain/reservationStockOutOrder/service/ReservationStockOutOrderDomainService.java
index 9807ea098..bf7018944 100644
--- a/mhd_oms/src/main/java/com/mhd/oms/domain/reservationStockOutOrder/service/ReservationStockOutOrderDomainService.java
+++ b/mhd_oms/src/main/java/com/mhd/oms/domain/reservationStockOutOrder/service/ReservationStockOutOrderDomainService.java
@@ -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.executionStockOutOrder.entity.ExecutionStockOutOrder;
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.service.ExecutionStockOutOrderApplicationService;
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.reservationStockOutOrder.entity.ReservationStockOutOrder;
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.todo.ReservationStockOutOrderDO;
+import com.mhd.oms.domain.reserveStockOutOrder.repository.mapper.ReserveStockOutOrderMapper;
import com.mhd.system.api.SystemServiceFeign;
import com.mhd.system.api.WmsServiceFeign;
import com.mhd.system.api.domain.*;
@@ -62,6 +65,7 @@ import org.springframework.util.CollectionUtils;
import javax.annotation.Resource;
import java.math.BigDecimal;
+import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;
@@ -95,6 +99,8 @@ public class ReservationStockOutOrderDomainService {
private ExecuteOrderMapper executeOrderMapper;
@Autowired
private ExecutionStockOutOrderApplicationService stockOutOrderApplicationService;
+ @Autowired
+ private ExecutionStockOutOrderMapper executionStockOutOrderMapper;
@Resource
private SystemServiceFeign systemServiceFeign;
@Resource
@@ -105,6 +111,10 @@ public class ReservationStockOutOrderDomainService {
private IBusinessDeliveryDetailsLinkService businessDeliveryDetailsLinkService;
@Autowired
private BusinessDeliveryDetailsLinkMapper businessDeliveryDetailsLinkMapper;
+ @Autowired
+ private ReservationStockOutOrderMapper reservationStockOutOrderMapper;
+ @Autowired
+ private ReserveStockOutOrderMapper reserveStockOutOrderMapper;
/**
* 分页查询出库单列表
@@ -120,7 +130,8 @@ public class ReservationStockOutOrderDomainService {
@Transactional(rollbackFor = Exception.class)
public Boolean insert(ReservationStockOutOrderDO stockOutOrderDO) {
if (stockOutOrderDO.getOutOrderNumber() == null) {
- stockOutOrderDO.setOutOrderNumber(OrderSequence.getOrderCode("CK"));
+ stockOutOrderDO.setOutOrderNumber(generateReserveOrderNumber());
+ stockOutOrderDO.setBusinessOrderNo(stockOutOrderDO.getOutOrderNumber());
}
// 与 update / batchInsert 一致:前端传计划数量为 quantity,非 outboundQuantity
setMaterialDetailInfo(stockOutOrderDO);
@@ -385,11 +396,8 @@ public class ReservationStockOutOrderDomainService {
// reservationStockInOrder.setTopOrganizationId(topOrgId);
reservationStockInOrder.setBusinessOutOrderNumber(inOrderNumber);
- if (materialDetailGroupByWarehouse!=null&&materialDetailGroupByWarehouse.size()>1) {
- reservationStockInOrder.setOutOrderNumber(OrderSequence.getOrderCode("CK"));
- } else {
- reservationStockInOrder.setOutOrderNumber(inOrderNumber);
- }
+ reservationStockInOrder.setOutOrderNumber(generateExecutionOrderNumber(warehouseCode));
+
List inMaterialDetailList = new ArrayList<>();
for (ReservationOutMaterialDetail reservationOutMaterialDetail : details) {
@@ -513,11 +521,7 @@ public class ReservationStockOutOrderDomainService {
reservationStockInOrder.setWarehouseCode(warehouseCode);
reservationStockInOrder.setWarehouseName(warehouseName);
reservationStockInOrder.setBusinessOutOrderNumber(inOrderNumber);
- if (materialDetailGroupByWarehouse!=null&&materialDetailGroupByWarehouse.size()>1) {
- reservationStockInOrder.setOutOrderNumber(OrderSequence.getOrderCode("CK"));
- } else {
- reservationStockInOrder.setOutOrderNumber(inOrderNumber);
- }
+ reservationStockInOrder.setOutOrderNumber(generateExecutionOrderNumber(warehouseCode));
List inMaterialDetailList = new ArrayList<>();
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 orderNumber1 = reservationStockOutOrderMapper.generateReserveOrderNumber1(prefix);
+ List orderNumber2 = reserveStockOutOrderMapper.generateReserveOrderNumber1(prefix);
+ List 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;
+ }
}
\ No newline at end of file
diff --git a/mhd_oms/src/main/java/com/mhd/oms/domain/reserveStockInOrder/repository/mapper/ReserveStockInOrderMapper.java b/mhd_oms/src/main/java/com/mhd/oms/domain/reserveStockInOrder/repository/mapper/ReserveStockInOrderMapper.java
index 92e0c7292..9bbc47a3d 100644
--- a/mhd_oms/src/main/java/com/mhd/oms/domain/reserveStockInOrder/repository/mapper/ReserveStockInOrderMapper.java
+++ b/mhd_oms/src/main/java/com/mhd/oms/domain/reserveStockInOrder/repository/mapper/ReserveStockInOrderMapper.java
@@ -2,6 +2,8 @@ package com.mhd.oms.domain.reserveStockInOrder.repository.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
//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.MaterialGoodsRulePO;
import com.mhd.oms.domain.reservationStockInOrder.repository.po.MaterialWarehouseControlPO;
@@ -46,4 +48,33 @@ public interface ReserveStockInOrderMapper extends BaseMapper queryNoticePrintDetail(ReserveStockInOrderDO stockInOrderDO);
public String getJsbz(@Param("id") Long id);
+
+ int countByOrderNumberPrefix(@Param("prefix") String prefix);
+
+ List generateReserveOrderNumber1(@Param("prefix") String prefix);
+
+ /**
+ * 根据货主名称查询用户(老系统数据导入用)
+ */
+ List getShipperByName(@Param("name") String name);
+
+ /**
+ * 根据仓库名称查询仓库(老系统数据导入用)
+ */
+ List getWarehouseByName(@Param("name") String name);
+
+ /**
+ * 根据仓库类型查询仓库(老系统数据导入用,1=干仓 2=冬仓)
+ */
+ List getWarehouseByType(@Param("warehouseType") String warehouseType);
+
+ /**
+ * 根据货主用户ID查询NC客户编码
+ */
+ String getCustomerNcCodeByUserId(@Param("id") Long id);
+
+ /**
+ * 根据入库单号精确统计(导入防重用)
+ */
+ int countByInOrderNumber(@Param("inOrderNumber") String inOrderNumber);
}
\ No newline at end of file
diff --git a/mhd_oms/src/main/java/com/mhd/oms/domain/reserveStockInOrder/repository/util/ExcelParseUtil.java b/mhd_oms/src/main/java/com/mhd/oms/domain/reserveStockInOrder/repository/util/ExcelParseUtil.java
index 3ae7db3e8..3d534da4f 100644
--- a/mhd_oms/src/main/java/com/mhd/oms/domain/reserveStockInOrder/repository/util/ExcelParseUtil.java
+++ b/mhd_oms/src/main/java/com/mhd/oms/domain/reserveStockInOrder/repository/util/ExcelParseUtil.java
@@ -1,12 +1,16 @@
package com.mhd.oms.domain.reserveStockInOrder.repository.util;
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.vo.LegacyReserveInDetailVO;
+import com.mhd.oms.domain.reserveStockInOrder.repository.vo.LegacyReserveInOrderVO;
import com.mhd.oms.domain.reserveStockInOrder.repository.vo.ReservedInventory;
import org.springframework.web.multipart.MultipartFile;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
+import java.util.stream.Collectors;
/**
* Excel解析工具类
@@ -56,6 +60,50 @@ public class ExcelParseUtil {
return dataList;
}
+ /**
+ * 解析老系统《入库预约单列表》Excel(表头第1行,数据从第2行开始)
+ * @param file 上传的Excel文件
+ * @return 老系统入库预约单主表行列表
+ * @throws IOException 文件处理异常
+ */
+ public static List parseLegacyOrderExcel(MultipartFile file) throws IOException {
+ validateFile(file);
+ List 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 parseLegacyDetailExcel(MultipartFile file) throws IOException {
+ validateFile(file);
+ List 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文件合法性
*/
diff --git a/mhd_oms/src/main/java/com/mhd/oms/domain/reserveStockInOrder/repository/vo/LegacyReserveInDetailVO.java b/mhd_oms/src/main/java/com/mhd/oms/domain/reserveStockInOrder/repository/vo/LegacyReserveInDetailVO.java
new file mode 100644
index 000000000..42ec1de99
--- /dev/null
+++ b/mhd_oms/src/main/java/com/mhd/oms/domain/reserveStockInOrder/repository/vo/LegacyReserveInDetailVO.java
@@ -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;
+}
diff --git a/mhd_oms/src/main/java/com/mhd/oms/domain/reserveStockInOrder/repository/vo/LegacyReserveInOrderVO.java b/mhd_oms/src/main/java/com/mhd/oms/domain/reserveStockInOrder/repository/vo/LegacyReserveInOrderVO.java
new file mode 100644
index 000000000..4bbbca38d
--- /dev/null
+++ b/mhd_oms/src/main/java/com/mhd/oms/domain/reserveStockInOrder/repository/vo/LegacyReserveInOrderVO.java
@@ -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;
+}
diff --git a/mhd_oms/src/main/java/com/mhd/oms/domain/reserveStockInOrder/service/ReserveStockInOrderApplicationService.java b/mhd_oms/src/main/java/com/mhd/oms/domain/reserveStockInOrder/service/ReserveStockInOrderApplicationService.java
index a31ca9db3..571dfa51c 100644
--- a/mhd_oms/src/main/java/com/mhd/oms/domain/reserveStockInOrder/service/ReserveStockInOrderApplicationService.java
+++ b/mhd_oms/src/main/java/com/mhd/oms/domain/reserveStockInOrder/service/ReserveStockInOrderApplicationService.java
@@ -5,6 +5,7 @@ import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson2.JSONObject;
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.exception.ServiceException;
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.po.MaterialBaseInfoPO;
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.todo.ReserveInMaterialDetailDO;
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.po.ReserveStockInOrderPO;
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.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.reserveStockOutOrder.repository.mapper.ReserveStockOutOrderMapper;
import com.mhd.system.api.SystemServiceFeign;
import com.mhd.system.api.UserServiceFeign;
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.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
import java.math.BigDecimal;
import java.text.ParseException;
@@ -61,6 +69,8 @@ public class ReserveStockInOrderApplicationService {
@Autowired
private ReserveStockInOrderMapper reserveStockInOrderMapper;
@Autowired
+ private ReserveStockOutOrderMapper reserveStockOutOrderMapper;
+ @Autowired
private ReservationMaterialInventoryMapper reservationMaterialInventoryMapper;
@Autowired
private UserServiceFeign userServiceFeign;
@@ -70,6 +80,10 @@ public class ReserveStockInOrderApplicationService {
private WmsServiceFeign wmsServiceFeign;
@Autowired
private ReservationStockInOrderMapper reservationStockInOrderMapper;
+ @Autowired
+ private IReserveStockInOrderService stockInOrderService;
+ @Autowired
+ private IReserveInMaterialDetailService materialDetailService;
// @Autowired
// private IMaterialBaseInfoService materialBaseInfoService;
@@ -2039,6 +2053,241 @@ public class ReserveStockInOrderApplicationService {
insert(reserveStockInOrder);
}
+ /**
+ * 老系统入库预约单数据导入(主表+明细两个Excel,多单批量导入)
+ * 老系统的id类字段不可用,货主、仓库、物料均按名称匹配新系统基础数据
+ */
+ @Transactional(rollbackFor = Exception.class)
+ public Map importLegacyData(List orderList, List detailList) {
+ if (orderList == null || orderList.isEmpty()) {
+ throw new ValidationException("入库预约单列表文件中没有有效数据");
+ }
+ if (detailList == null || detailList.isEmpty()) {
+ throw new ValidationException("入库预约单明细列表文件中没有有效数据");
+ }
+
+ // 明细按入库单号分组
+ Map> detailGroupMap = new LinkedHashMap<>();
+ for (LegacyReserveInDetailVO detailRow : detailList) {
+ detailGroupMap.computeIfAbsent(detailRow.getInOrderNumber().trim(), k -> new ArrayList<>()).add(detailRow);
+ }
+
+ List errorList = new ArrayList<>();
+ // 名称匹配结果缓存,避免重复查库
+ Map shipperCache = new HashMap<>();
+ Map warehouseCache = new HashMap<>();
+ // 仓库类型 -> 仓库 缓存(用于名称匹配失败时的兜底)
+ Map warehouseTypeCache = new HashMap<>();
+ Map materialCache = new HashMap<>();
+
+ Set orderNumberSet = new HashSet<>();
+ List 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 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 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 detailRows = detailGroupMap.get(orderNumber);
+ if (detailRows == null || detailRows.isEmpty()) {
+ errorList.add("入库单号【" + orderNumber + "】在明细文件中没有明细数据");
+ continue;
+ }
+ List 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 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 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 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() {
// 1. 获取当前时间,格式化:yyMMddHHmmss
LocalDateTime now = LocalDateTime.now();
@@ -2066,4 +2315,8 @@ public class ReserveStockInOrderApplicationService {
// 3. 拼接结果
return datePart + randomPart;
}
+
+ public String generateReserveOrderNumber() {
+ return stockInOrderDomainService.generateReserveOrderNumber();
+ }
}
\ No newline at end of file
diff --git a/mhd_oms/src/main/java/com/mhd/oms/domain/reserveStockInOrder/service/ReserveStockInOrderDomainService.java b/mhd_oms/src/main/java/com/mhd/oms/domain/reserveStockInOrder/service/ReserveStockInOrderDomainService.java
index d451559cf..c69b34725 100644
--- a/mhd_oms/src/main/java/com/mhd/oms/domain/reserveStockInOrder/service/ReserveStockInOrderDomainService.java
+++ b/mhd_oms/src/main/java/com/mhd/oms/domain/reserveStockInOrder/service/ReserveStockInOrderDomainService.java
@@ -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.reservationStockInOrder.entity.ReservationStockInOrder;
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.MaterialGoodsRulePO;
import com.mhd.oms.domain.reservationStockInOrder.repository.po.MaterialWarehouseControlPO;
@@ -78,6 +79,8 @@ public class ReserveStockInOrderDomainService {
private IReservationStockInOrderService reservationStockInOrderService;
@Autowired
private IReservationInMaterialDetailService reservationInMaterialDetailService;
+ @Autowired
+ private ReservationStockInOrderDomainService reservationStockInOrderDomainService;
/**
* 分页查询入库单列表
@@ -101,7 +104,7 @@ public class ReserveStockInOrderDomainService {
@Transactional(rollbackFor = Exception.class)
public Boolean insert(ReserveStockInOrderDO stockInOrderDO) {
if (stockInOrderDO.getInOrderNumber() == null) {
- stockInOrderDO.setInOrderNumber(OrderSequence.getOrderCode("RK"));
+ stockInOrderDO.setInOrderNumber(generateReserveOrderNumber());
}
// //设置默认值
// setDefaultValues(stockInOrderDO);
@@ -134,7 +137,7 @@ public class ReserveStockInOrderDomainService {
public Boolean batchInsert(List stockInOrderDOList) {
for (ReserveStockInOrderDO stockInOrderDO : stockInOrderDOList){
if (StringUtils.isBlank(stockInOrderDO.getInOrderNumber())){
- stockInOrderDO.setInOrderNumber(OrderSequence.getOrderCode("RK"));
+ stockInOrderDO.setInOrderNumber(generateReserveOrderNumber());
}
// //设置物料信息
// setMaterialDetailInfo(stockInOrderDO);
@@ -471,13 +474,18 @@ public class ReserveStockInOrderDomainService {
Long shipperId = reservationStockInOrder.getShipperId();
String jsbz = reservationStockInOrderMapper.getJsbz(shipperId);
reservationStockInOrder.setSettlementCurrency(jsbz);
- String inOrderNumber = reservationStockInOrder.getInOrderNumber();
- List materialDetailList = materialDetailService.list(new QueryWrapper().lambda().eq(ReserveInMaterialDetail::getInOrderNumber, inOrderNumber));
+ String oldInOrderNumber = reservationStockInOrder.getInOrderNumber();
+ // 生成新业务单号,防止与已生成的入库业务单号重复
+ String newOrderNumber = reservationStockInOrderDomainService.generateReserveOrderNumber();
+ reservationStockInOrder.setInOrderNumber(newOrderNumber);
+ reservationStockInOrder.setBusinessOrderNo(newOrderNumber);
+ List materialDetailList = materialDetailService.list(new QueryWrapper().lambda().eq(ReserveInMaterialDetail::getInOrderNumber, oldInOrderNumber));
List inMaterialDetailList = new ArrayList<>();
int index = 1;
for (ReserveInMaterialDetail reserveInMaterialDetail : materialDetailList) {
ReservationInMaterialDetail reservationInMaterialDetail = new ReservationInMaterialDetail();
BeanUtils.copyProperties(reserveInMaterialDetail, reservationInMaterialDetail,"materialDetailId");
+ reservationInMaterialDetail.setInOrderNumber(newOrderNumber); // 使用新单号保持与主表关联
reservationInMaterialDetail.setQuantity(reserveInMaterialDetail.getReserveQuantity());
String lot = generateDateSerialNumber();
lot = lot+"-"+index;
@@ -973,4 +981,16 @@ public class ReserveStockInOrderDomainService {
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;
+ }
+
}
\ No newline at end of file
diff --git a/mhd_oms/src/main/java/com/mhd/oms/domain/reserveStockOutOrder/repository/mapper/ReserveStockOutOrderMapper.java b/mhd_oms/src/main/java/com/mhd/oms/domain/reserveStockOutOrder/repository/mapper/ReserveStockOutOrderMapper.java
index e752dc596..128716b68 100644
--- a/mhd_oms/src/main/java/com/mhd/oms/domain/reserveStockOutOrder/repository/mapper/ReserveStockOutOrderMapper.java
+++ b/mhd_oms/src/main/java/com/mhd/oms/domain/reserveStockOutOrder/repository/mapper/ReserveStockOutOrderMapper.java
@@ -2,10 +2,12 @@ package com.mhd.oms.domain.reserveStockOutOrder.repository.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
//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.reserveStockOutOrder.entity.ReserveStockOutOrder;
import com.mhd.oms.domain.reserveStockOutOrder.repository.po.ReserveStockOutOrderPO;
import com.mhd.oms.domain.reserveStockOutOrder.repository.todo.ReserveStockOutOrderDO;
+import org.apache.ibatis.annotations.Param;
import java.util.List;
@@ -33,4 +35,19 @@ public interface ReserveStockOutOrderMapper extends BaseMapper queryOutStockNoticePrintDetail(ReserveStockOutOrderDO stockOutOrderDO);
+
+ int countByOrderNumberPrefix(@Param("prefix") String prefix);
+
+ List generateReserveOrderNumber1(@Param("prefix") String prefix);
+
+ /**
+ * 老系统数据导入:根据出库单号精确统计(防重)
+ */
+ int countByOutOrderNumber(@Param("outOrderNumber") String outOrderNumber);
+
+ /**
+ * 老系统数据导入:根据仓库类型查询仓库
+ * @param warehouseType 仓库类型编码(如 "1"/"2")
+ */
+ List getWarehouseByType(@Param("warehouseType") String warehouseType);
}
\ No newline at end of file
diff --git a/mhd_oms/src/main/java/com/mhd/oms/domain/reserveStockOutOrder/repository/util/ExcelParseUtil.java b/mhd_oms/src/main/java/com/mhd/oms/domain/reserveStockOutOrder/repository/util/ExcelParseUtil.java
index 693b30aba..7deeddc83 100644
--- a/mhd_oms/src/main/java/com/mhd/oms/domain/reserveStockOutOrder/repository/util/ExcelParseUtil.java
+++ b/mhd_oms/src/main/java/com/mhd/oms/domain/reserveStockOutOrder/repository/util/ExcelParseUtil.java
@@ -1,7 +1,10 @@
package com.mhd.oms.domain.reserveStockOutOrder.repository.util;
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.vo.LegacyReserveOutDetailVO;
+import com.mhd.oms.domain.reserveStockOutOrder.repository.vo.LegacyReserveOutOrderVO;
import com.mhd.oms.domain.reserveStockOutOrder.repository.vo.ReservedInventoryOut;
import org.springframework.web.multipart.MultipartFile;
@@ -55,6 +58,55 @@ public class ExcelParseUtil {
return dataList;
}
+ /**
+ * 解析老系统《出库预约单列表》Excel(表头第1行,数据从第2行开始)
+ */
+ public static List parseLegacyOrderExcel(MultipartFile file) throws IOException {
+ validateFile(file);
+ List 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 parseLegacyDetailExcel(MultipartFile file) throws IOException {
+ validateFile(file);
+ List 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文件合法性
*/
diff --git a/mhd_oms/src/main/java/com/mhd/oms/domain/reserveStockOutOrder/repository/vo/LegacyReserveOutDetailVO.java b/mhd_oms/src/main/java/com/mhd/oms/domain/reserveStockOutOrder/repository/vo/LegacyReserveOutDetailVO.java
new file mode 100644
index 000000000..84dc95dff
--- /dev/null
+++ b/mhd_oms/src/main/java/com/mhd/oms/domain/reserveStockOutOrder/repository/vo/LegacyReserveOutDetailVO.java
@@ -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;
+}
diff --git a/mhd_oms/src/main/java/com/mhd/oms/domain/reserveStockOutOrder/repository/vo/LegacyReserveOutOrderVO.java b/mhd_oms/src/main/java/com/mhd/oms/domain/reserveStockOutOrder/repository/vo/LegacyReserveOutOrderVO.java
new file mode 100644
index 000000000..59adf9bca
--- /dev/null
+++ b/mhd_oms/src/main/java/com/mhd/oms/domain/reserveStockOutOrder/repository/vo/LegacyReserveOutOrderVO.java
@@ -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;
+}
diff --git a/mhd_oms/src/main/java/com/mhd/oms/domain/reserveStockOutOrder/service/ReserveStockOutOrderApplicationService.java b/mhd_oms/src/main/java/com/mhd/oms/domain/reserveStockOutOrder/service/ReserveStockOutOrderApplicationService.java
index 95cdd6c2f..4dc2f9a89 100644
--- a/mhd_oms/src/main/java/com/mhd/oms/domain/reserveStockOutOrder/service/ReserveStockOutOrderApplicationService.java
+++ b/mhd_oms/src/main/java/com/mhd/oms/domain/reserveStockOutOrder/service/ReserveStockOutOrderApplicationService.java
@@ -5,7 +5,9 @@ import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson2.JSONObject;
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.WarehousePO;
import com.mhd.common.core.enums.DictCode;
import com.mhd.common.core.exception.ServiceException;
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.po.ReserveOutMaterialDetailPO;
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.todo.ReserveStockInOrderDO;
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.mapper.ReserveStockOutOrderMapper;
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.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.reserveOutMaterialDetail.entity.ReserveOutMaterialDetail;
import com.mhd.system.api.SystemServiceFeign;
import com.mhd.system.api.UserServiceFeign;
import com.mhd.system.api.domain.*;
@@ -38,6 +46,7 @@ import com.mhd.system.api.model.LoginUser;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import java.lang.reflect.Field;
@@ -68,6 +77,8 @@ public class ReserveStockOutOrderApplicationService {
@Autowired
private ReserveStockInOrderMapper reserveStockInOrderMapper;
@Autowired
+ private ReserveStockOutOrderMapper reserveStockOutOrderMapper;
+ @Autowired
private ReservationMaterialInventoryMapper reservationMaterialInventoryMapper;
@Autowired
private UserServiceFeign userServiceFeign;
@@ -1112,6 +1123,238 @@ public class ReserveStockOutOrderApplicationService {
return stockOutOrderDomainService.queryOutStockNoticePrintDetail(stockOutOrderDO);
}
+ /**
+ * 老系统出库预约单数据导入(主表+明细两个Excel,多单批量导入)
+ * 老系统的id类字段不可用,货主按名称匹配新系统用户,仓库按仓库类型(1=干仓 2=冬仓)匹配新系统仓库,物料按名称匹配
+ * 明细表物料名称取物料名称1和物料名称2中有值的那一个
+ */
+ @Transactional(rollbackFor = Exception.class)
+ public Map importLegacyData(List orderList, List detailList) {
+ if (orderList == null || orderList.isEmpty()) {
+ throw new ValidationException("出库预约单列表文件中没有有效数据");
+ }
+ if (detailList == null || detailList.isEmpty()) {
+ throw new ValidationException("出库预约单明细列表文件中没有有效数据");
+ }
+
+ // 明细按出库单号分组
+ Map> detailGroupMap = new LinkedHashMap<>();
+ for (LegacyReserveOutDetailVO detailRow : detailList) {
+ detailGroupMap.computeIfAbsent(detailRow.getOutOrderNumber().trim(), k -> new ArrayList<>()).add(detailRow);
+ }
+
+ List errorList = new ArrayList<>();
+ // 名称匹配结果缓存,避免重复查库
+ Map shipperCache = new HashMap<>();
+ // 仓库类型 -> 仓库 缓存(老系统只有仓库类型,没有仓库名称)
+ Map warehouseTypeCache = new HashMap<>();
+ Map materialCache = new HashMap<>();
+
+ Set orderNumberSet = new HashSet<>();
+ List 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 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 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 detailRows = detailGroupMap.get(orderNumber);
+ if (detailRows == null || detailRows.isEmpty()) {
+ errorList.add("出库单号【" + orderNumber + "】在明细文件中没有明细数据");
+ continue;
+ }
+ List 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 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 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 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 dataList) {
LoginUser loginUser = SecurityUtils.getLoginUser();
ReserveStockOutOrderDO reserveStockOutOrder = new ReserveStockOutOrderDO();
@@ -1217,4 +1460,8 @@ public class ReserveStockOutOrderApplicationService {
// 3. 拼接结果
return datePart + randomPart;
}
+
+ public String generateReserveOrderNumber() {
+ return stockOutOrderDomainService.generateReserveOrderNumber();
+ }
}
\ No newline at end of file
diff --git a/mhd_oms/src/main/java/com/mhd/oms/domain/reserveStockOutOrder/service/ReserveStockOutOrderDomainService.java b/mhd_oms/src/main/java/com/mhd/oms/domain/reserveStockOutOrder/service/ReserveStockOutOrderDomainService.java
index 6e66b54d2..cb75be175 100644
--- a/mhd_oms/src/main/java/com/mhd/oms/domain/reserveStockOutOrder/service/ReserveStockOutOrderDomainService.java
+++ b/mhd_oms/src/main/java/com/mhd/oms/domain/reserveStockOutOrder/service/ReserveStockOutOrderDomainService.java
@@ -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.reservationStockOutOrder.entity.ReservationStockOutOrder;
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.reserveOutMaterialDetail.entity.ReserveOutMaterialDetail;
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.reserveStockOutOrder.entity.ReserveStockOutOrder;
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.todo.ReserveStockOutOrderDO;
import com.mhd.system.api.SystemServiceFeign;
@@ -71,6 +73,12 @@ public class ReserveStockOutOrderDomainService {
@Autowired
private ReserveStockInOrderMapper reservationStockInOrderMapper;
+ @Autowired
+ private ReserveStockOutOrderMapper stockOutOrderMapper;
+
+ @Autowired
+ private ReservationStockOutOrderDomainService reservationStockOutOrderDomainService;
+
/**
* 分页查询出库单列表
*/
@@ -89,7 +97,7 @@ public class ReserveStockOutOrderDomainService {
@Transactional(rollbackFor = Exception.class)
public Boolean insert(ReserveStockOutOrderDO stockOutOrderDO) {
if (stockOutOrderDO.getOutOrderNumber() == null) {
- stockOutOrderDO.setOutOrderNumber(OrderSequence.getOrderCode("CK"));
+ stockOutOrderDO.setOutOrderNumber(generateReserveOrderNumber());
}
// 与 update / batchInsert 一致:前端传计划数量为 quantity,非 outboundQuantity
setMaterialDetailInfo(stockOutOrderDO);
@@ -119,7 +127,7 @@ public class ReserveStockOutOrderDomainService {
public Boolean batchInsert(List stockOutOrderDOList) {
for (ReserveStockOutOrderDO stockOutOrderDO : stockOutOrderDOList){
if (StringUtils.isBlank(stockOutOrderDO.getOutOrderNumber())){
- stockOutOrderDO.setOutOrderNumber(OrderSequence.getOrderCode("CK"));
+ stockOutOrderDO.setOutOrderNumber(generateReserveOrderNumber());
}
//设置物料信息
setMaterialDetailInfo(stockOutOrderDO);
@@ -298,14 +306,20 @@ public class ReserveStockOutOrderDomainService {
Long shipperId = reservationStockOutOrder.getShipperId();
String jsbz = reservationStockInOrderMapper.getJsbz(shipperId);
reservationStockOutOrder.setSettlementCurrency(jsbz);
+ // 保留旧单号,用于查询源明细数据
+ String oldOutOrderNumber = reservationStockOutOrder.getOutOrderNumber();
+ // 生成出库业务单号,防止与已生成的出库业务单号重复
+ String newOrderNumber = reservationStockOutOrderDomainService.generateReserveOrderNumber();
+ reservationStockOutOrder.setOutOrderNumber(newOrderNumber);
+ reservationStockOutOrder.setBusinessOrderNo(newOrderNumber);
reservationStockOutOrderService.save(reservationStockOutOrder);
- String outOrderNumber = reservationStockOutOrder.getOutOrderNumber();
- List materialDetailList = outMaterialDetailService.list(new QueryWrapper().lambda().eq(ReserveOutMaterialDetail::getOutOrderNumber, outOrderNumber));
+ List materialDetailList = outMaterialDetailService.list(new QueryWrapper().lambda().eq(ReserveOutMaterialDetail::getOutOrderNumber, oldOutOrderNumber));
List inMaterialDetailList = new ArrayList<>();
int index = 1;
for (ReserveOutMaterialDetail reserveOutMaterialDetail : materialDetailList) {
ReservationOutMaterialDetail reservationOutMaterialDetail = new ReservationOutMaterialDetail();
BeanUtils.copyProperties(reserveOutMaterialDetail, reservationOutMaterialDetail,"materialDetailId");
+ reservationOutMaterialDetail.setOutOrderNumber(newOrderNumber); // 使用新单号保持与主表关联
String lot = generateDateSerialNumber();
lot = lot+"-"+index;
index++;
@@ -751,4 +765,17 @@ public class ReserveStockOutOrderDomainService {
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;
+ }
+
}
\ No newline at end of file
diff --git a/mhd_oms/src/main/java/com/mhd/oms/interfaces/facade/ReservationStockOutOrder/ReservationStockOutOrderApi.java b/mhd_oms/src/main/java/com/mhd/oms/interfaces/facade/ReservationStockOutOrder/ReservationStockOutOrderApi.java
index 634649524..77dd5ebf6 100644
--- a/mhd_oms/src/main/java/com/mhd/oms/interfaces/facade/ReservationStockOutOrder/ReservationStockOutOrderApi.java
+++ b/mhd_oms/src/main/java/com/mhd/oms/interfaces/facade/ReservationStockOutOrder/ReservationStockOutOrderApi.java
@@ -246,4 +246,16 @@ public class ReservationStockOutOrderApi extends BaseController {
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());
+ }
}
\ No newline at end of file
diff --git a/mhd_oms/src/main/java/com/mhd/oms/interfaces/facade/ReserveStockOutOrder/ReserveStockOutOrderApi.java b/mhd_oms/src/main/java/com/mhd/oms/interfaces/facade/ReserveStockOutOrder/ReserveStockOutOrderApi.java
index 7a034b4de..14e6d1f9e 100644
--- a/mhd_oms/src/main/java/com/mhd/oms/interfaces/facade/ReserveStockOutOrder/ReserveStockOutOrderApi.java
+++ b/mhd_oms/src/main/java/com/mhd/oms/interfaces/facade/ReserveStockOutOrder/ReserveStockOutOrderApi.java
@@ -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.todo.ReserveStockOutOrderDO;
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.service.ReserveStockOutOrderApplicationService;
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
+
+
+
-
+
+ SELECT COUNT(1)
+ FROM reservation_stock_out_order
+ WHERE out_order_number LIKE concat(#{prefix}, '%')
+
+
+ SELECT out_order_number
+ FROM reservation_stock_out_order
+ WHERE out_order_number LIKE concat(#{prefix}, '%')
+
\ No newline at end of file
diff --git a/mhd_oms/src/main/resources/mapper/reserveStockInOrder/ReserveStockInOrderMapper.xml b/mhd_oms/src/main/resources/mapper/reserveStockInOrder/ReserveStockInOrderMapper.xml
index 7546d26e8..2272d6a7d 100644
--- a/mhd_oms/src/main/resources/mapper/reserveStockInOrder/ReserveStockInOrderMapper.xml
+++ b/mhd_oms/src/main/resources/mapper/reserveStockInOrder/ReserveStockInOrderMapper.xml
@@ -777,4 +777,58 @@
AND USER_ID = #{id} limit 1
+
+ SELECT COUNT(1)
+ FROM reserve_stock_in_order
+ WHERE in_order_number LIKE concat(#{prefix}, '%')
+
+
+ SELECT in_order_number
+ FROM reserve_stock_in_order
+ WHERE in_order_number LIKE concat(#{prefix}, '%')
+
+
+
+
+ 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 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 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 CUSTOMER_NC_CODE from "NGWL_TEST_USER".USER_SHIPPER where DEL_FLAG = 1 and USER_ID = #{id} limit 1
+
+
+
+
+ SELECT COUNT(1)
+ FROM reserve_stock_in_order
+ WHERE in_order_number = #{inOrderNumber}
+
+
\ No newline at end of file
diff --git a/mhd_oms/src/main/resources/mapper/reserveStockOutOrder/ReserveStockOutOrderMapper.xml b/mhd_oms/src/main/resources/mapper/reserveStockOutOrder/ReserveStockOutOrderMapper.xml
index 05fa3137e..1c4a103dd 100644
--- a/mhd_oms/src/main/resources/mapper/reserveStockOutOrder/ReserveStockOutOrderMapper.xml
+++ b/mhd_oms/src/main/resources/mapper/reserveStockOutOrder/ReserveStockOutOrderMapper.xml
@@ -517,4 +517,35 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
+
+ SELECT COUNT(1)
+ FROM reserve_stock_out_order
+ WHERE out_order_number LIKE concat(#{prefix}, '%')
+
+
+ SELECT out_order_number
+ FROM reserve_stock_out_order
+ WHERE out_order_number LIKE concat(#{prefix}, '%')
+
+
+
+
+ SELECT COUNT(1)
+ FROM reserve_stock_out_order
+ WHERE out_order_number = #{outOrderNumber}
+
+
+
+
+ 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
+ )
+
+
\ No newline at end of file
diff --git a/mhd_wms/src/main/java/com/mhd/wms/MhdWmsApplication.java b/mhd_wms/src/main/java/com/mhd/wms/MhdWmsApplication.java
index f8b3d4145..a848debd3 100644
--- a/mhd_wms/src/main/java/com/mhd/wms/MhdWmsApplication.java
+++ b/mhd_wms/src/main/java/com/mhd/wms/MhdWmsApplication.java
@@ -7,12 +7,14 @@ import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.context.annotation.ComponentScan;
+import org.springframework.scheduling.annotation.EnableAsync;
@SpringBootApplication
@EnableRyFeignClients
@EnableDiscoveryClient
@MapperScan("com.mhd.wms.domain.**.mapper")
@EnableMethodCache(basePackages = "com.mhd.platform.domain.**.cache")
+@EnableAsync
@ComponentScan(basePackages = {
"com.mhd.wms",
"com.mhd.system.api.factory"
diff --git a/mhd_wms/src/main/java/com/mhd/wms/application/service/materialBaseInfo/MaterialBaseInfoApplicationService.java b/mhd_wms/src/main/java/com/mhd/wms/application/service/materialBaseInfo/MaterialBaseInfoApplicationService.java
index c30840c5f..10b12490c 100644
--- a/mhd_wms/src/main/java/com/mhd/wms/application/service/materialBaseInfo/MaterialBaseInfoApplicationService.java
+++ b/mhd_wms/src/main/java/com/mhd/wms/application/service/materialBaseInfo/MaterialBaseInfoApplicationService.java
@@ -49,12 +49,15 @@ 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.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.web.multipart.MultipartFile;
import javax.annotation.Resource;
+import java.io.File;
+import java.io.FileOutputStream;
import java.io.InputStream;
import java.util.*;
import java.util.stream.Collectors;
@@ -100,6 +103,10 @@ public class MaterialBaseInfoApplicationService {
@Resource
private MaterialBaseInfoMapper materialBaseInfoMapper;
+
+ @Autowired
+ private MaterialBaseInfoAsyncService materialBaseInfoAsyncService;
+
/**
* 分页查询物料基础信息列表
*/
@@ -250,7 +257,10 @@ public class MaterialBaseInfoApplicationService {
}
}
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()) {
ObjectMapper objectMapper = new ObjectMapper();
List> listNc = null;
@@ -433,8 +443,47 @@ public class MaterialBaseInfoApplicationService {
return materialBaseInfoDomainService.getInfoByNoOrderReceipt(materialBaseInfoDO);
}
+
/**
- * 导入物料主数据(仅导入主表字段)
+ * 导入物料主数据(异步入口)
+ *
+ * 接口层调用此方法,将文件保存到临时目录后立即返回"异步处理中",
+ * 实际导入由 {@link #doImportData(File, String, LoginUser)} 异步执行,
+ * 避免大数据量时接口超时。
+ */
+ 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)
public AjaxResult importData(MultipartFile file) {
@@ -493,7 +542,6 @@ public class MaterialBaseInfoApplicationService {
row.setHsCode(row.getHsCodeImport().trim());
}
normalizeImportBarCodeWhenDuplicateOfHs(row);
- // 客户模板通常只有「货主名称」无「货主id」:须先按名称解析货主,再回填组织;勿提前写入登录组织以免组织校验拦截货主匹配
fillIdsFromExistingMasterData(row);
fillOrganizationFromShipperIfNeeded(row);
if (!isValidOrgId(row.getOrganizationId()) && isValidOrgId(loginOrgId)) {
@@ -564,25 +612,20 @@ public class MaterialBaseInfoApplicationService {
materialBaseInfoDO.setMaterialCommon(null);
materialBaseInfoDO.setMaterialWarehouseControl(null);
materialBaseInfoDO.setMaterialBarCodeList(buildImportBarCodeList(row));
- // 商品规则由 buildImportMaterialGoodsRule + insert() 统一写入,勿再单独 insert,避免 MATERIAL_GOODS_RULE 重复
insert(materialBaseInfoDO);
Long materialBaseInfoId = materialBaseInfoDO.getMaterialBaseInfoId();
- //公共信息
MaterialCommonDO materialCommonDO = materialBaseInfoDO.getMaterialCommon();
if (materialCommonDO != null) {
materialCommonDO.setMaterialBaseInfoId(materialBaseInfoId);
materialCommonDomainService.insert(materialCommonDO);
}
- //仓库控制信息
MaterialWarehouseControlDO materialWarehouseControlDO = materialBaseInfoDO.getMaterialWarehouseControl();
if (materialWarehouseControlDO != null) {
materialWarehouseControlDO.setMaterialBaseInfoId(materialBaseInfoId);
materialWarehouseControlDomainService.insert(materialWarehouseControlDO);
}
- //库存预警
materialInventoryWarningDomainService.batchInsertOrUpdate(materialBaseInfoDO);
- //条码信息
materialBarCodeDomainService.batchInsertOrUpdate(materialBaseInfoDO);
successCount++;
}
@@ -593,10 +636,11 @@ public class MaterialBaseInfoApplicationService {
return AjaxResult.success("导入成功,共" + successCount + "条");
}
+
/**
* 使用已存在主数据按名称/编码反查并回填ID
*/
- private void fillIdsFromExistingMasterData(MaterialBaseInfoDTO row) {
+ public void fillIdsFromExistingMasterData(MaterialBaseInfoDTO row) {
if (StringUtils.isBlank(row.getPackName()) && StringUtils.isNotBlank(row.getPackImport())) {
row.setPackName(row.getPackImport().trim());
}
@@ -815,10 +859,14 @@ public class MaterialBaseInfoApplicationService {
Object userCode = shipper.get("userCode");
Object userMemberCode = shipper.get("userMemberCode");
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");
}
- if (userName == null) {
+ if (userName == null || String.valueOf(userName).trim().isEmpty()) {
userName = shipper.get("shipperName");
}
String normalizedName = StringUtils.isNotBlank(shipperName) ? shipperName : "";
@@ -916,7 +964,7 @@ public class MaterialBaseInfoApplicationService {
/**
* Excel 已填货主 ID、但未填组织时,从货主用户补全组织信息。
*/
- private void fillOrganizationFromShipperIfNeeded(MaterialBaseInfoDTO row) {
+ public void fillOrganizationFromShipperIfNeeded(MaterialBaseInfoDTO row) {
if (isValidOrgId(row.getOrganizationId()) || row.getShipperId() == null) {
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())) {
return;
}
@@ -995,7 +1043,7 @@ public class MaterialBaseInfoApplicationService {
}
}
- private void fillClassifyTypeAndUnit(MaterialBaseInfoDTO row) {
+ public void fillClassifyTypeAndUnit(MaterialBaseInfoDTO row) {
normalizeMaterialClassifyImportFields(row);
// 按组织从 system 主数据反查分类编码,与名称列表对齐
fillMaterialClassifyCodesFromSystem(row);
@@ -1176,7 +1224,7 @@ public class MaterialBaseInfoApplicationService {
* 导入约定:「HS码/HS编码」与「物料条形码」为不同列。模板表头错位或两列误填相同 HS 时,
* barCode 会与 hsCode 相同;此时保留 hsCode,清空主表/子表条码,避免 HS 写入 bar_code。
*/
- private void normalizeImportBarCodeWhenDuplicateOfHs(MaterialBaseInfoDTO row) {
+ public void normalizeImportBarCodeWhenDuplicateOfHs(MaterialBaseInfoDTO row) {
if (row == null) {
return;
}
@@ -1191,7 +1239,7 @@ public class MaterialBaseInfoApplicationService {
}
}
- private List buildImportBarCodeList(MaterialBaseInfoDTO row) {
+ public List buildImportBarCodeList(MaterialBaseInfoDTO row) {
if (StringUtils.isBlank(row.getBarCode())) {
return null;
}
@@ -1231,7 +1279,7 @@ public class MaterialBaseInfoApplicationService {
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())
? row.getBatchRuleNameImport().trim()
: (StringUtils.isNotBlank(row.getBatchName())
@@ -1306,7 +1354,7 @@ public class MaterialBaseInfoApplicationService {
.trim();
}
- private List> extractTableDataRows(Map resultMap) {
+ public List> extractTableDataRows(Map resultMap) {
if (resultMap == null) {
return new ArrayList<>();
}
diff --git a/mhd_wms/src/main/java/com/mhd/wms/application/service/materialBaseInfo/MaterialBaseInfoAsyncService.java b/mhd_wms/src/main/java/com/mhd/wms/application/service/materialBaseInfo/MaterialBaseInfoAsyncService.java
new file mode 100644
index 000000000..5a3554478
--- /dev/null
+++ b/mhd_wms/src/main/java/com/mhd/wms/application/service/materialBaseInfo/MaterialBaseInfoAsyncService.java
@@ -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 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 duplicateInFile = new HashSet<>();
+ int successCount = 0;
+ int totalCount = rows.size();
+ Map> 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 wrapper = new LambdaQueryWrapper()
+ .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 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 resultMap = JSON.parseObject(JSONObject.toJSONString(result), new TypeReference>() {});
+ List> 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> extractTableDataRows(Map 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> list = (List>) data;
+ return list;
+ }
+ if (data instanceof Map) {
+ @SuppressWarnings("unchecked")
+ Map dataMap = (Map) data;
+ Object innerData = dataMap.get("data");
+ if (innerData instanceof List) {
+ @SuppressWarnings("unchecked")
+ List> list = (List>) innerData;
+ return list;
+ }
+ Object rows = dataMap.get("rows");
+ if (rows instanceof List) {
+ @SuppressWarnings("unchecked")
+ List> list = (List>) rows;
+ return list;
+ }
+ }
+ return Collections.emptyList();
+ }
+
+ private boolean isValidOrgId(Long id) {
+ return id != null && id > 0;
+ }
+}
diff --git a/mhd_wms/src/main/java/com/mhd/wms/application/service/materialInventory/MaterialInventoryApplicationService.java b/mhd_wms/src/main/java/com/mhd/wms/application/service/materialInventory/MaterialInventoryApplicationService.java
index 823313caa..1dbedb634 100644
--- a/mhd_wms/src/main/java/com/mhd/wms/application/service/materialInventory/MaterialInventoryApplicationService.java
+++ b/mhd_wms/src/main/java/com/mhd/wms/application/service/materialInventory/MaterialInventoryApplicationService.java
@@ -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.MaterialInventoryQueryListDO;
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.po.MaterialBarCodePO;
import com.mhd.wms.domain.materialMoreDetail.repository.po.MaterialMoreDetailPO;
diff --git a/mhd_wms/src/main/java/com/mhd/wms/application/service/stockInOrder/StockInOrderApplicationService.java b/mhd_wms/src/main/java/com/mhd/wms/application/service/stockInOrder/StockInOrderApplicationService.java
index 117efb435..f07aca537 100644
--- a/mhd_wms/src/main/java/com/mhd/wms/application/service/stockInOrder/StockInOrderApplicationService.java
+++ b/mhd_wms/src/main/java/com/mhd/wms/application/service/stockInOrder/StockInOrderApplicationService.java
@@ -545,9 +545,71 @@ public class StockInOrderApplicationService {
info.setKhdm(userNcCode);
List materialDetailList = info.getMaterialDetailList();
if (materialDetailList != null && !materialDetailList.isEmpty()) {
- for (InMaterialDetailPO inMaterialDetailPO : materialDetailList) {
- // TODO: 设置物料详情信息
- inMaterialDetailPO.setKhdm(userNcCode);
+ // 收集所有有效的物料基础信息ID
+ Set materialBaseInfoIdSet = new HashSet<>();
+ for (InMaterialDetailPO detail : materialDetailList) {
+ if (detail.getMaterialBaseInfoId() != null && detail.getMaterialBaseInfoId() > 0) {
+ materialBaseInfoIdSet.add(detail.getMaterialBaseInfoId());
+ }
+ }
+
+ // 批量查询物料基础信息,try-catch保护,防止没有ID时NPE
+ Map 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 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);
}
diff --git a/mhd_wms/src/main/java/com/mhd/wms/application/service/stockOutOrder/StockOutOrderApplicationService.java b/mhd_wms/src/main/java/com/mhd/wms/application/service/stockOutOrder/StockOutOrderApplicationService.java
index 8e6556798..26de7300b 100644
--- a/mhd_wms/src/main/java/com/mhd/wms/application/service/stockOutOrder/StockOutOrderApplicationService.java
+++ b/mhd_wms/src/main/java/com/mhd/wms/application/service/stockOutOrder/StockOutOrderApplicationService.java
@@ -282,9 +282,6 @@ public class StockOutOrderApplicationService {
stockOutOrderPO.setMaterialQuantity(cnt);
}
- BigDecimal checkSum = (mag != null && mag.getCheckQuantitySum() != null)
- ? mag.getCheckQuantitySum() : BigDecimal.ZERO;
- stockOutOrderPO.setCheckQuantity(checkSum);
stockOutOrderPO.setReceiptOrderAccountList(
accountByOrderId.getOrDefault(stockOutOrderPO.getOutOrderId(), Collections.emptyList()));
}
diff --git a/mhd_wms/src/main/java/com/mhd/wms/application/service/stockReceiptOrder/StockReceiptOrderApplicationService.java b/mhd_wms/src/main/java/com/mhd/wms/application/service/stockReceiptOrder/StockReceiptOrderApplicationService.java
index 355dc57d2..ea0c33038 100644
--- a/mhd_wms/src/main/java/com/mhd/wms/application/service/stockReceiptOrder/StockReceiptOrderApplicationService.java
+++ b/mhd_wms/src/main/java/com/mhd/wms/application/service/stockReceiptOrder/StockReceiptOrderApplicationService.java
@@ -233,7 +233,9 @@ public class StockReceiptOrderApplicationService {
}
for (ReceiptMaterialDetailPO receiptMaterialDetailPO : receiptMaterialDetailPOList) {
MaterialBaseInfoPO materialBaseInfoPO = materialBaseInfoMap.get(receiptMaterialDetailPO.getMaterialBaseInfoId());
- receiptMaterialDetailPO.setCopyCode(materialBaseInfoPO.getCopyCode());
+ if (materialBaseInfoPO != null) {
+ receiptMaterialDetailPO.setCopyCode(materialBaseInfoPO.getCopyCode());
+ }
}
// 4.2 批量查询包装规格信息(单位代码为EA的单位名称)
diff --git a/mhd_wms/src/main/java/com/mhd/wms/domain/materialInventory/repository/mapper/MaterialInventoryMapper.java b/mhd_wms/src/main/java/com/mhd/wms/domain/materialInventory/repository/mapper/MaterialInventoryMapper.java
index 013aca6f3..a609f19c0 100644
--- a/mhd_wms/src/main/java/com/mhd/wms/domain/materialInventory/repository/mapper/MaterialInventoryMapper.java
+++ b/mhd_wms/src/main/java/com/mhd/wms/domain/materialInventory/repository/mapper/MaterialInventoryMapper.java
@@ -32,6 +32,8 @@ public interface MaterialInventoryMapper extends BaseMapper
public List queryListByKw(MaterialInventoryDO materialInventoryDO);
//查物料库存列表-物料
public List queryListByWl(MaterialInventoryDO materialInventoryDO);
+ //查物料库存列表-物料+过期日期
+ public List queryListByWlExpiry(MaterialInventoryDO materialInventoryDO);
//查物料库存列表-货主
public List queryListByHz(MaterialInventoryDO materialInventoryDO);
//查物料库存列表-货主+物料(同一物料在不同货主下各一行)
diff --git a/mhd_wms/src/main/java/com/mhd/wms/domain/materialInventory/repository/persistence/MaterialInventoryImpl.java b/mhd_wms/src/main/java/com/mhd/wms/domain/materialInventory/repository/persistence/MaterialInventoryImpl.java
index 0c6076a39..8b25a0600 100644
--- a/mhd_wms/src/main/java/com/mhd/wms/domain/materialInventory/repository/persistence/MaterialInventoryImpl.java
+++ b/mhd_wms/src/main/java/com/mhd/wms/domain/materialInventory/repository/persistence/MaterialInventoryImpl.java
@@ -85,6 +85,8 @@ public class MaterialInventoryImpl extends ServiceImpl数据量大时同步导入会导致接口超时,改为异步模式:
+ * 接口立即返回"已提交异步处理",后台线程执行实际导入,
+ * 导入结果通过日志输出。
*/
- @ApiOperation("导入物料主数据")
+ @ApiOperation("导入物料主数据(异步)")
@PostMapping("/importData")
public AjaxResult importData(@RequestParam("file") MultipartFile file) {
- return materialBaseInfoApplicationService.importData(file);
+ return materialBaseInfoApplicationService.importDataAsync(file);
}
@ApiOperation("物料管理更新推送信息")
diff --git a/mhd_wms/src/main/java/com/mhd/wms/interfaces/facadeApi/materialInventory/MaterialInventoryApi.java b/mhd_wms/src/main/java/com/mhd/wms/interfaces/facadeApi/materialInventory/MaterialInventoryApi.java
index d2e88e3b6..1f3547b5d 100644
--- a/mhd_wms/src/main/java/com/mhd/wms/interfaces/facadeApi/materialInventory/MaterialInventoryApi.java
+++ b/mhd_wms/src/main/java/com/mhd/wms/interfaces/facadeApi/materialInventory/MaterialInventoryApi.java
@@ -55,7 +55,9 @@ public class MaterialInventoryApi extends BaseController {
@GetMapping("/list")
public TableDataInfo list(MaterialInventoryDTO materialInventoryDTO,
@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)) {
materialInventoryDTO.setExcludeZeroInventoryQuantity(true);
@@ -86,6 +88,8 @@ public class MaterialInventoryApi extends BaseController {
MaterialInventoryDO materialInventoryDO = materialInventoryAssembler.toDO(materialInventoryDTO);
materialInventoryDO.setExpiryDateStr(materialInventoryDTO.getExpiryDate());
materialInventoryDO.setProductionDateStr(materialInventoryDTO.getProductionDate());
+ materialInventoryDO.setExpiryDateStart(expiryDateStart);
+ materialInventoryDO.setExpiryDateEnd(expiryDateEnd);
Date updateTime = materialInventoryDTO.getUpdateTime();
if (updateTime != null) {
LocalDateTime localDateTime = updateTime.toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime();
diff --git a/mhd_wms/src/main/java/com/mhd/wms/util/MaterialBaseInfoImportExcelUtil.java b/mhd_wms/src/main/java/com/mhd/wms/util/MaterialBaseInfoImportExcelUtil.java
index 678a72e6d..206e35fb2 100644
--- a/mhd_wms/src/main/java/com/mhd/wms/util/MaterialBaseInfoImportExcelUtil.java
+++ b/mhd_wms/src/main/java/com/mhd/wms/util/MaterialBaseInfoImportExcelUtil.java
@@ -36,6 +36,11 @@ public final class MaterialBaseInfoImportExcelUtil {
HEADER_ALIASES.put("淨重(kg)", "净重 单位:千克");
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 importRows(InputStream is) throws Exception {
diff --git a/mhd_wms/src/main/resources/mapper/materialInventory/MaterialInventoryMapper.xml b/mhd_wms/src/main/resources/mapper/materialInventory/MaterialInventoryMapper.xml
index 30b20f9e5..484fcf602 100644
--- a/mhd_wms/src/main/resources/mapper/materialInventory/MaterialInventoryMapper.xml
+++ b/mhd_wms/src/main/resources/mapper/materialInventory/MaterialInventoryMapper.xml
@@ -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
+
+
+ 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
+
+
+
+
+ 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
@@ -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
order by max(b.material_name), max(a.shipper_name), a.batch_number
+
+ 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
+
group by a.storage_location_id
order by max(a.storage_location_code)
diff --git a/mhd_wms/src/main/resources/mapper/reviewOrder/ReviewOrderMapper.xml b/mhd_wms/src/main/resources/mapper/reviewOrder/ReviewOrderMapper.xml
index 86a8a0466..d03ce31fc 100644
--- a/mhd_wms/src/main/resources/mapper/reviewOrder/ReviewOrderMapper.xml
+++ b/mhd_wms/src/main/resources/mapper/reviewOrder/ReviewOrderMapper.xml
@@ -4,7 +4,7 @@
-
+
@@ -84,7 +84,7 @@
- a.review_order_id,
+ a.review_order_id AS review_order_id,
a.review_order_number,
a.out_order_id,
a.out_order_number,
diff --git a/sql/bms20260729.sql b/sql/bms20260729.sql
new file mode 100644
index 000000000..6d6613f12
--- /dev/null
+++ b/sql/bms20260729.sql
@@ -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 '费用类别名称(服务项名称)';
\ No newline at end of file