Merge branch 'dev' into feature/dev-0729
This commit is contained in:
+2
-2
@@ -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());
|
||||
|
||||
+182
-20
@@ -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;
|
||||
@@ -361,7 +364,7 @@ public class UserShipperApplicationService {
|
||||
|
||||
/**
|
||||
* 从 Excel 导入委托方
|
||||
* 模版列:登录账号、公司名称、联系人、联系电话、地址、详细地址、备注、结算币种
|
||||
* 模版列:登录账号、公司名称、联系人、联系电话、地址、详细地址、备注、结算币种、NC客户编码
|
||||
*/
|
||||
public com.mhd.common.core.web.domain.AjaxResult importShipperFromExcel(org.springframework.web.multipart.MultipartFile file) {
|
||||
if (file == null || file.isEmpty()) {
|
||||
@@ -372,6 +375,12 @@ public class UserShipperApplicationService {
|
||||
org.apache.poi.ss.usermodel.Sheet sheet = workbook.getSheetAt(0);
|
||||
int total = 0, success = 0, failed = 0;
|
||||
java.util.List<String> errors = new java.util.ArrayList<>();
|
||||
LoginUser loginUser = SecurityUtils.getLoginUser();
|
||||
if (loginUser == null || loginUser.getUserPo() == null) {
|
||||
return com.mhd.common.core.web.domain.AjaxResult.error("登录信息失效");
|
||||
}
|
||||
Long currentOrgId = loginUser.getUserPo().getOrganizationId();
|
||||
String currentOrgName = loginUser.getUserPo().getOrganizationName();
|
||||
for (int i = 1; i <= sheet.getLastRowNum(); i++) {
|
||||
org.apache.poi.ss.usermodel.Row row = sheet.getRow(i);
|
||||
if (row == null) continue;
|
||||
@@ -380,14 +389,21 @@ public class UserShipperApplicationService {
|
||||
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) {
|
||||
// 已存在:只更新NC客户编码和org_code
|
||||
appendOrganizationToExistingShipper(existingShipper,
|
||||
SecurityUtils.getLoginUser().getUserPo().getOrganizationId(),
|
||||
SecurityUtils.getLoginUser().getUserPo().getOrganizationName(),
|
||||
userAccount, SecurityUtils.getLoginUser());
|
||||
// 已存在:按模板更新指定字段
|
||||
updateShipperFromExcel(existingShipper, userAccount, companyName,
|
||||
contactName, contactPhone, address, detailedAddress,
|
||||
remark, settlementCurrency, ncCustomerCode, loginUser, currentOrgId);
|
||||
success++;
|
||||
} else {
|
||||
UserShipperDO shipperDO = new UserShipperDO();
|
||||
@@ -395,31 +411,34 @@ public class UserShipperApplicationService {
|
||||
shipperDO.setDataSource(2);
|
||||
shipperDO.setUserAccount(userAccount);
|
||||
shipperDO.setShipperEnterpriseName(companyName);
|
||||
// 登录账号同时作为NC客户编码
|
||||
shipperDO.setCustomerNcCode(userAccount);
|
||||
String contactName = getCellStr(row.getCell(2));
|
||||
String contactPhone = getCellStr(row.getCell(3));
|
||||
// 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(getCellStr(row.getCell(4)));
|
||||
shipperDO.setUserAreaAddress(getCellStr(row.getCell(5)));
|
||||
shipperDO.setRemark(getCellStr(row.getCell(6)));
|
||||
shipperDO.setSettlementCurrency(getCellStr(row.getCell(7)));
|
||||
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();
|
||||
LoginUser loginUser = SecurityUtils.getLoginUser();
|
||||
orgItem.put("name", loginUser.getUserPo().getOrganizationName());
|
||||
orgItem.put("code", loginUser.getUserPo().getOrganizationId());
|
||||
orgItem.put("ncCustomer", userAccount);
|
||||
orgItem.put("names", loginUser.getUserPo().getOrganizationId());
|
||||
orgItem.put("name", currentOrgName);
|
||||
orgItem.put("code", currentOrgId);
|
||||
orgItem.put("ncCustomer", ncCustomerCode);
|
||||
orgItem.put("names", currentOrgId);
|
||||
orgCodeArray.add(orgItem);
|
||||
shipperDO.setOrgCode(orgCodeArray.toJSONString());
|
||||
addShipper(shipperDO);
|
||||
Map<String, Object> addResult = addShipper(shipperDO);
|
||||
Object newUserIdObj = addResult.get("userId");
|
||||
if (newUserIdObj instanceof Long) {
|
||||
assignCompanyRoleIfMissing((Long) newUserIdObj, currentOrgId);
|
||||
}
|
||||
success++;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
@@ -441,6 +460,149 @@ public class UserShipperApplicationService {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 导入时若账号没有任何角色,则补分配企业货主角色
|
||||
*/
|
||||
private void assignCompanyRoleIfMissing(Long userId, Long organizationId) {
|
||||
if (userId == null || organizationId == null) {
|
||||
return;
|
||||
}
|
||||
List<UserRoleMenuPO> existingRoles = userRoleDomainService.selectRolesByUserId(userId);
|
||||
if (CollUtil.isNotEmpty(existingRoles)) {
|
||||
return;
|
||||
}
|
||||
// 按 role_code + organization_id 精确匹配角色(selectByOrganizationIdAndRoleCode 的 common_where 不含 roleCode 过滤,不适用)
|
||||
RolePO rolePO = roleDomainService.selectByRoleCodeAndOrganizationId(RoleEnum.COMPANY.getCode(), organizationId);
|
||||
if (rolePO == null) {
|
||||
log.warn("组织{}下未找到{}角色,无法为导入用户{}分配角色", organizationId, RoleEnum.COMPANY.getCode(), userId);
|
||||
return;
|
||||
}
|
||||
// 1. 写入 user_role 表
|
||||
UserRoleDo userRoleDo = new UserRoleDo();
|
||||
userRoleDo.setUserId(userId);
|
||||
userRoleDo.setRoleId(rolePO.getRoleId());
|
||||
userRoleDomainService.addUserRole(userRoleDo);
|
||||
// 2. 同步更新 user 表的 role_code / role_name
|
||||
UserDO userDO = new UserDO();
|
||||
userDO.setUserId(userId);
|
||||
userDO.setRoleCode(RoleEnum.COMPANY.getCode());
|
||||
userDO.setRoleName(RoleEnum.COMPANY.getName());
|
||||
userDomainService.updateUser(userDO);
|
||||
}
|
||||
|
||||
/**
|
||||
* 按Excel模板更新已存在的委托方(只更新模板中的字段)
|
||||
*/
|
||||
private void updateShipperFromExcel(UserShipperEntity existingShipper, String userAccount,
|
||||
String companyName, String contactName, String contactPhone,
|
||||
String address, String detailedAddress, String remark,
|
||||
String settlementCurrency, String ncCustomerCode,
|
||||
LoginUser loginUser, Long currentOrgId) {
|
||||
Long userId = existingShipper.getUserId();
|
||||
// 从 user 主表读取当前登录账号(user_shipper 表无 user_account 字段)
|
||||
UserPo existingUser = null;
|
||||
String existingUserAccount = null;
|
||||
if (userId != null) {
|
||||
existingUser = userDomainService.selectByUserId(userId);
|
||||
if (existingUser != null) {
|
||||
existingUserAccount = existingUser.getUserAccount();
|
||||
}
|
||||
}
|
||||
if (StringUtils.isBlank(existingUserAccount) && StringUtils.isBlank(userAccount)) {
|
||||
throw new ServiceException("登录账号不能为空");
|
||||
}
|
||||
// 登录账号变更时校验唯一性
|
||||
if (StringUtils.isNotBlank(userAccount) && !userAccount.equals(existingUserAccount)) {
|
||||
UserDO checkDO = new UserDO();
|
||||
checkDO.setUserAccount(userAccount);
|
||||
checkDO.setTopOrganizationId(existingShipper.getTopOrganizationId());
|
||||
UserPo existedUser = userDomainService.findByTopOrganizationIdAndUserAccount(checkDO);
|
||||
if (existedUser != null && !existedUser.getUserId().equals(userId)) {
|
||||
throw new ServiceException("登录账号已存在:" + userAccount);
|
||||
}
|
||||
}
|
||||
Date now = new Date();
|
||||
Long updateBy = loginUser.getUserPo().getUserId();
|
||||
String updateByName = loginUser.getUserPo().getUserName();
|
||||
|
||||
// 1. 更新 user_shipper 表指定字段
|
||||
// 注意:user_shipper 表没有 user_account 字段,登录账号在 user 主表维护
|
||||
UserShipperEntity shipperUpdate = new UserShipperEntity();
|
||||
shipperUpdate.setShipperId(existingShipper.getShipperId());
|
||||
shipperUpdate.setShipperEnterpriseName(companyName);
|
||||
shipperUpdate.setUserNameShipper(contactName);
|
||||
shipperUpdate.setUserAreaName(address);
|
||||
shipperUpdate.setUserAreaAddress(detailedAddress);
|
||||
shipperUpdate.setRemark(remark);
|
||||
shipperUpdate.setSettlementCurrency(settlementCurrency);
|
||||
shipperUpdate.setCustomerNcCode(ncCustomerCode);
|
||||
shipperUpdate.setUpdateBy(updateBy);
|
||||
shipperUpdate.setUpdateByName(updateByName);
|
||||
shipperUpdate.setUpdateTime(now);
|
||||
userShipperMapper.updateById(shipperUpdate);
|
||||
|
||||
// 2. 同步更新 user 表指定字段
|
||||
if (userId != null) {
|
||||
UserDO userDO = new UserDO();
|
||||
userDO.setUserId(userId);
|
||||
if (StringUtils.isNotBlank(userAccount)) {
|
||||
userDO.setUserAccount(userAccount);
|
||||
}
|
||||
userDO.setUserName(contactName);
|
||||
userDO.setUserPhone(contactPhone);
|
||||
userDO.setUserAreaName(address);
|
||||
userDO.setUserAreaAddress(detailedAddress);
|
||||
userDO.setUpdateBy(updateBy);
|
||||
userDO.setUpdateByName(updateByName);
|
||||
userDO.setUpdateTime(now);
|
||||
// 如果现有账号没有密码,设置默认密码 Aa123456(与 addUserInfoShipper 一致的加密流程)
|
||||
if (existingUser != null && StringUtils.isBlank(existingUser.getUserPassword())) {
|
||||
String finalAccount = StringUtils.isNotBlank(userAccount) ? userAccount : existingUser.getUserAccount();
|
||||
String salt = OConvertUtils.randomGen(8);
|
||||
String passwordEncode = PasswordUtil.encrypt(finalAccount, "Aa123456", salt);
|
||||
userDO.setUserPassword(passwordEncode);
|
||||
userDO.setUserSalt(salt);
|
||||
}
|
||||
userDomainService.updateUser(userDO);
|
||||
// 如果该账号没有任何角色,补分配企业货主角色,避免登录报“账号未授权角色信息”
|
||||
assignCompanyRoleIfMissing(userId, existingShipper.getOrganizationId());
|
||||
}
|
||||
|
||||
// 3. 更新 orgCode 中当前组织的 ncCustomer
|
||||
String existingOrgCode = existingShipper.getOrgCode();
|
||||
com.alibaba.fastjson.JSONArray orgCodeArray = new com.alibaba.fastjson.JSONArray();
|
||||
boolean hasOrg = false;
|
||||
if (StringUtils.isNotEmpty(existingOrgCode)) {
|
||||
try {
|
||||
orgCodeArray = com.alibaba.fastjson.JSONArray.parseArray(existingOrgCode);
|
||||
for (int i = 0; i < orgCodeArray.size(); i++) {
|
||||
com.alibaba.fastjson.JSONObject orgItem = orgCodeArray.getJSONObject(i);
|
||||
if (currentOrgId != null && currentOrgId.equals(orgItem.getLong("code"))) {
|
||||
orgItem.put("ncCustomer", ncCustomerCode);
|
||||
hasOrg = true;
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error("解析orgCode失败,shipperId={}", existingShipper.getShipperId(), e);
|
||||
}
|
||||
}
|
||||
if (!hasOrg) {
|
||||
com.alibaba.fastjson.JSONObject newOrgItem = new com.alibaba.fastjson.JSONObject();
|
||||
newOrgItem.put("name", loginUser.getUserPo().getOrganizationName());
|
||||
newOrgItem.put("code", currentOrgId);
|
||||
newOrgItem.put("ncCustomer", ncCustomerCode);
|
||||
newOrgItem.put("names", currentOrgId);
|
||||
orgCodeArray.add(newOrgItem);
|
||||
}
|
||||
UserShipperEntity orgCodeUpdate = new UserShipperEntity();
|
||||
orgCodeUpdate.setShipperId(existingShipper.getShipperId());
|
||||
orgCodeUpdate.setOrgCode(orgCodeArray.toJSONString());
|
||||
orgCodeUpdate.setUpdateBy(updateBy);
|
||||
orgCodeUpdate.setUpdateByName(updateByName);
|
||||
orgCodeUpdate.setUpdateTime(now);
|
||||
userShipperMapper.updateById(orgCodeUpdate);
|
||||
}
|
||||
|
||||
private String getCellStr(org.apache.poi.ss.usermodel.Cell cell) {
|
||||
if (cell == null) return null;
|
||||
cell.setCellType(org.apache.poi.ss.usermodel.CellType.STRING);
|
||||
|
||||
@@ -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.31:6848
|
||||
server-addr: 10.33.0.129:6010
|
||||
# server-addr: 10.102.192.30:6848
|
||||
username: nacos
|
||||
password: manhuoda@2023
|
||||
config:
|
||||
# server-addr: 127.0.0.1:8848
|
||||
# 线上测试环境配置 容器名+端口号
|
||||
# server-addr: 10.33.0.129:6010
|
||||
server-addr: 10.102.192.31:6848
|
||||
server-addr: 10.33.0.129:6010
|
||||
# server-addr: 10.102.192.30:6848
|
||||
username: nacos
|
||||
password: manhuoda@2023
|
||||
group: DEFAULT_GROUP # 默认分组就是DEFAULT_GROUP,如果使用默认分组可以不配置
|
||||
|
||||
+27
@@ -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;
|
||||
@@ -50,4 +52,29 @@ public interface ReserveStockInOrderMapper extends BaseMapper<ReserveStockInOrde
|
||||
int countByOrderNumberPrefix(@Param("prefix") String prefix);
|
||||
|
||||
List<String> generateReserveOrderNumber1(@Param("prefix") String prefix);
|
||||
|
||||
/**
|
||||
* 根据货主名称查询用户(老系统数据导入用)
|
||||
*/
|
||||
List<UserPo> getShipperByName(@Param("name") String name);
|
||||
|
||||
/**
|
||||
* 根据仓库名称查询仓库(老系统数据导入用)
|
||||
*/
|
||||
List<WarehousePO> getWarehouseByName(@Param("name") String name);
|
||||
|
||||
/**
|
||||
* 根据仓库类型查询仓库(老系统数据导入用,1=干仓 2=冬仓)
|
||||
*/
|
||||
List<WarehousePO> getWarehouseByType(@Param("warehouseType") String warehouseType);
|
||||
|
||||
/**
|
||||
* 根据货主用户ID查询NC客户编码
|
||||
*/
|
||||
String getCustomerNcCodeByUserId(@Param("id") Long id);
|
||||
|
||||
/**
|
||||
* 根据入库单号精确统计(导入防重用)
|
||||
*/
|
||||
int countByInOrderNumber(@Param("inOrderNumber") String inOrderNumber);
|
||||
}
|
||||
+48
@@ -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<LegacyReserveInOrderVO> parseLegacyOrderExcel(MultipartFile file) throws IOException {
|
||||
validateFile(file);
|
||||
List<LegacyReserveInOrderVO> dataList;
|
||||
try (InputStream inputStream = file.getInputStream()) {
|
||||
dataList = EasyExcel.read(inputStream)
|
||||
.head(LegacyReserveInOrderVO.class)
|
||||
.sheet(0)
|
||||
.headRowNumber(1)
|
||||
.doReadSync();
|
||||
}
|
||||
// 过滤入库单号为空的无效行
|
||||
return dataList.stream()
|
||||
.filter(row -> row != null && StringUtils.isNotBlank(row.getInOrderNumber()))
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
/**
|
||||
* 解析老系统《入库预约单明细列表》Excel(表头第1行,数据从第2行开始)
|
||||
* @param file 上传的Excel文件
|
||||
* @return 老系统入库预约单明细行列表
|
||||
* @throws IOException 文件处理异常
|
||||
*/
|
||||
public static List<LegacyReserveInDetailVO> parseLegacyDetailExcel(MultipartFile file) throws IOException {
|
||||
validateFile(file);
|
||||
List<LegacyReserveInDetailVO> dataList;
|
||||
try (InputStream inputStream = file.getInputStream()) {
|
||||
dataList = EasyExcel.read(inputStream)
|
||||
.head(LegacyReserveInDetailVO.class)
|
||||
.sheet(0)
|
||||
.headRowNumber(1)
|
||||
.doReadSync();
|
||||
}
|
||||
// 过滤入库单号为空的无效行
|
||||
return dataList.stream()
|
||||
.filter(row -> row != null && StringUtils.isNotBlank(row.getInOrderNumber()))
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
/**
|
||||
* 验证Excel文件合法性
|
||||
*/
|
||||
|
||||
+77
@@ -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;
|
||||
}
|
||||
+93
@@ -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;
|
||||
}
|
||||
+249
@@ -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<String, Object> importLegacyData(List<LegacyReserveInOrderVO> orderList, List<LegacyReserveInDetailVO> detailList) {
|
||||
if (orderList == null || orderList.isEmpty()) {
|
||||
throw new ValidationException("入库预约单列表文件中没有有效数据");
|
||||
}
|
||||
if (detailList == null || detailList.isEmpty()) {
|
||||
throw new ValidationException("入库预约单明细列表文件中没有有效数据");
|
||||
}
|
||||
|
||||
// 明细按入库单号分组
|
||||
Map<String, List<LegacyReserveInDetailVO>> detailGroupMap = new LinkedHashMap<>();
|
||||
for (LegacyReserveInDetailVO detailRow : detailList) {
|
||||
detailGroupMap.computeIfAbsent(detailRow.getInOrderNumber().trim(), k -> new ArrayList<>()).add(detailRow);
|
||||
}
|
||||
|
||||
List<String> errorList = new ArrayList<>();
|
||||
// 名称匹配结果缓存,避免重复查库
|
||||
Map<String, UserPo> shipperCache = new HashMap<>();
|
||||
Map<String, WarehousePO> warehouseCache = new HashMap<>();
|
||||
// 仓库类型 -> 仓库 缓存(用于名称匹配失败时的兜底)
|
||||
Map<String, WarehousePO> warehouseTypeCache = new HashMap<>();
|
||||
Map<String, MaterialBaseInfoPO> materialCache = new HashMap<>();
|
||||
|
||||
Set<String> orderNumberSet = new HashSet<>();
|
||||
List<ReserveStockInOrderDO> stockInOrderList = new ArrayList<>();
|
||||
int lotIndex = 1;
|
||||
for (LegacyReserveInOrderVO orderRow : orderList) {
|
||||
String orderNumber = orderRow.getInOrderNumber().trim();
|
||||
if (!orderNumberSet.add(orderNumber)) {
|
||||
errorList.add("入库单号【" + orderNumber + "】在主表文件中重复");
|
||||
continue;
|
||||
}
|
||||
if (reserveStockInOrderMapper.countByInOrderNumber(orderNumber) > 0) {
|
||||
errorList.add("入库单号【" + orderNumber + "】在系统中已存在,请勿重复导入");
|
||||
continue;
|
||||
}
|
||||
// 按货主名称匹配用户(查不到则用Excel中的名称兜底,不阻断导入)
|
||||
UserPo shipper = null;
|
||||
String shipperName = StringUtils.trimToEmpty(orderRow.getShipperName());
|
||||
if (StringUtils.isBlank(shipperName)) {
|
||||
errorList.add("入库单号【" + orderNumber + "】货主名称为空");
|
||||
} else {
|
||||
shipper = shipperCache.get(shipperName);
|
||||
if (shipper == null) {
|
||||
List<UserPo> userPoList = reserveStockInOrderMapper.getShipperByName(shipperName);
|
||||
if (userPoList == null || userPoList.isEmpty()) {
|
||||
errorList.add("入库单号【" + orderNumber + "】货主【" + shipperName + "】未找到对应用户,将仅以名称导入");
|
||||
} else {
|
||||
shipper = userPoList.get(0);
|
||||
shipperCache.put(shipperName, shipper);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 按仓库类型匹配仓库(老系统仓库类型 1=干仓 2=冬仓,查不到则用类型名兜底)
|
||||
String warehouseName = "";
|
||||
WarehousePO warehouse = null;
|
||||
String warehouseType = StringUtils.trimToEmpty(orderRow.getWarehouseType());
|
||||
if (StringUtils.isNotBlank(warehouseType)) {
|
||||
warehouse = warehouseTypeCache.get(warehouseType);
|
||||
if (warehouse == null) {
|
||||
List<WarehousePO> warehousePOList = reserveStockOutOrderMapper.getWarehouseByType(warehouseType);
|
||||
if (warehousePOList == null || warehousePOList.isEmpty()) {
|
||||
warehouseName = "1".equals(warehouseType) ? "干仓" : ("2".equals(warehouseType) ? "冻仓" : "");
|
||||
errorList.add("出库单号【" + orderNumber + "】仓库类型【" + warehouseType + "】未找到对应仓库,将仅以名称导入");
|
||||
warehouseTypeCache.put(warehouseType, null);
|
||||
warehouse = null;
|
||||
} else {
|
||||
warehouse = warehousePOList.get(0);
|
||||
warehouseName = warehouse.getWarehouseName();
|
||||
warehouseTypeCache.put(warehouseType, warehouse);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 明细匹配
|
||||
List<LegacyReserveInDetailVO> detailRows = detailGroupMap.get(orderNumber);
|
||||
if (detailRows == null || detailRows.isEmpty()) {
|
||||
errorList.add("入库单号【" + orderNumber + "】在明细文件中没有明细数据");
|
||||
continue;
|
||||
}
|
||||
List<ReserveInMaterialDetailDO> materialDetailList = new ArrayList<>();
|
||||
for (LegacyReserveInDetailVO detailRow : detailRows) {
|
||||
String materialName = StringUtils.trimToEmpty(detailRow.getMaterialName());
|
||||
if (StringUtils.isBlank(materialName)) {
|
||||
errorList.add("入库单号【" + orderNumber + "】存在物料名称为空的明细行");
|
||||
continue;
|
||||
}
|
||||
// 按物料名称匹配物料基础信息(查不到则用Excel中的名称兜底,不阻断导入)
|
||||
MaterialBaseInfoPO materialBaseInfoPO = materialCache.get(materialName);
|
||||
if (materialBaseInfoPO == null) {
|
||||
List<MaterialBaseInfoPO> materialBaseInfoPOS = reserveStockInOrderMapper.getByName(materialName);
|
||||
if (materialBaseInfoPOS == null || materialBaseInfoPOS.isEmpty()) {
|
||||
errorList.add("入库单号【" + orderNumber + "】物料【" + materialName + "】未找到对应物料,将仅以名称导入");
|
||||
} else {
|
||||
materialBaseInfoPO = materialBaseInfoPOS.get(0);
|
||||
materialCache.put(materialName, materialBaseInfoPO);
|
||||
}
|
||||
}
|
||||
ReserveInMaterialDetailDO materialDetail = new ReserveInMaterialDetailDO();
|
||||
if (materialBaseInfoPO != null) {
|
||||
materialDetail.setMaterialBaseInfoId(materialBaseInfoPO.getMaterialBaseInfoId());
|
||||
materialDetail.setMaterialCode(materialBaseInfoPO.getMaterialCode());
|
||||
materialDetail.setUnitCode(materialBaseInfoPO.getUnitCode());
|
||||
materialDetail.setUnitName(StringUtils.isNotBlank(materialBaseInfoPO.getUnitName()) ? materialBaseInfoPO.getUnitName() : detailRow.getUnitName());
|
||||
} else {
|
||||
// 未匹配到物料基础信息,仅以Excel中的名称作为物料名称
|
||||
materialDetail.setUnitName(detailRow.getUnitName());
|
||||
}
|
||||
materialDetail.setMaterialName(materialName);
|
||||
materialDetail.setReserveMaterialName(materialName);
|
||||
materialDetail.setQuantity(detailRow.getQuantity());
|
||||
materialDetail.setReserveQuantity(detailRow.getQuantity());
|
||||
materialDetail.setTotalNetWeight(detailRow.getTotalNetWeight());
|
||||
materialDetail.setTotalGrossWeight(detailRow.getTotalNetWeight());
|
||||
materialDetail.setRemark(detailRow.getRemark());
|
||||
materialDetail.setContractFee(BigDecimal.ZERO);
|
||||
materialDetail.setLotNo(generateDateSerialNumber() + "-" + lotIndex);
|
||||
lotIndex++;
|
||||
// if (shipper != null) {
|
||||
materialDetail.setOrganizationId(2841L);
|
||||
materialDetail.setOrganizationName("仓码");
|
||||
materialDetail.setTopOrganizationId(2827L);
|
||||
// }
|
||||
// 创建人/修改人名称取老系统Excel中的值,不使用当前登录人
|
||||
materialDetail.setCreateTime(detailRow.getCreateTime() != null ? detailRow.getCreateTime() : new Date());
|
||||
materialDetail.setCreateByName(detailRow.getCreateByName());
|
||||
materialDetail.setUpdateTime(detailRow.getUpdateTime());
|
||||
materialDetail.setUpdateByName(detailRow.getUpdateByName());
|
||||
materialDetailList.add(materialDetail);
|
||||
}
|
||||
|
||||
// 组装入库预约单
|
||||
ReserveStockInOrderDO stockInOrderDO = new ReserveStockInOrderDO();
|
||||
stockInOrderDO.setInOrderNumber(orderNumber);
|
||||
stockInOrderDO.setBusinessOrderNo(orderNumber);
|
||||
// 老系统历史数据,状态直接置为最终状态:已入库、审核通过、已完成
|
||||
stockInOrderDO.setStatus(5);
|
||||
stockInOrderDO.setAuditStatus(3);
|
||||
stockInOrderDO.setIssueStatus(3);
|
||||
stockInOrderDO.setOrderStatus("已确认");
|
||||
stockInOrderDO.setStorageTime(orderRow.getWarehouseDate());
|
||||
stockInOrderDO.setNeedTransport(0);
|
||||
stockInOrderDO.setNeedCustomsDeclaration(0);
|
||||
stockInOrderDO.setWarehouseDate(orderRow.getWarehouseDate());
|
||||
stockInOrderDO.setExpectTime(orderRow.getWarehouseDate() != null ? orderRow.getWarehouseDate() : new Date());
|
||||
stockInOrderDO.setDocumentDate(orderRow.getDocumentDate() != null ? orderRow.getDocumentDate() : new Date());
|
||||
stockInOrderDO.setDocumentCreator(orderRow.getDocumentCreator());
|
||||
stockInOrderDO.setRemark(orderRow.getRemark());
|
||||
if (shipper != null) {
|
||||
stockInOrderDO.setShipperId(shipper.getUserId());
|
||||
stockInOrderDO.setShipperName(shipper.getUserName());
|
||||
stockInOrderDO.setCustomerId(shipper.getUserId());
|
||||
stockInOrderDO.setCustomerName(shipper.getUserName());
|
||||
stockInOrderDO.setSalesmanId(String.valueOf(shipper.getUserId()));
|
||||
stockInOrderDO.setSalesmanName(shipper.getUserName());
|
||||
stockInOrderDO.setCustomerCode(reserveStockInOrderMapper.getCustomerNcCodeByUserId(shipper.getUserId()));
|
||||
// stockInOrderDO.setOrganizationId(shipper.getOrganizationId());
|
||||
// stockInOrderDO.setOrganizationName(shipper.getOrganizationName());
|
||||
// stockInOrderDO.setTopOrganizationId(shipper.getTopOrganizationId());
|
||||
} else {
|
||||
// 货主未匹配到,仅以Excel中的名称作为名称字段,id/组织留空
|
||||
stockInOrderDO.setShipperName(shipperName);
|
||||
stockInOrderDO.setCustomerName(shipperName);
|
||||
stockInOrderDO.setSalesmanName(shipperName);
|
||||
}
|
||||
stockInOrderDO.setOrganizationId(2841L);
|
||||
stockInOrderDO.setOrganizationName("仓码");
|
||||
stockInOrderDO.setTopOrganizationId(2827L);
|
||||
if (warehouse != null) {
|
||||
stockInOrderDO.setWarehouseId(warehouse.getWarehouseId());
|
||||
stockInOrderDO.setWarehouseCode(warehouse.getWarehouseCode());
|
||||
stockInOrderDO.setWarehouseName(warehouse.getWarehouseName());
|
||||
} else if (StringUtils.isNotBlank(warehouseName)) {
|
||||
// 仓库未匹配到,仅以Excel中的名称作为仓库名称,id/编码留空
|
||||
stockInOrderDO.setWarehouseName(warehouseName);
|
||||
}
|
||||
// 创建人/修改人名称取老系统Excel中的值,不使用当前登录人
|
||||
stockInOrderDO.setCreateTime(orderRow.getCreateTime() != null ? orderRow.getCreateTime() : new Date());
|
||||
stockInOrderDO.setCreateByName(orderRow.getCreateByName());
|
||||
stockInOrderDO.setUpdateTime(orderRow.getUpdateTime());
|
||||
stockInOrderDO.setUpdateByName(orderRow.getUpdateByName());
|
||||
stockInOrderDO.setMaterialDetailList(materialDetailList);
|
||||
stockInOrderList.add(stockInOrderDO);
|
||||
}
|
||||
|
||||
// 明细文件中存在但主表文件中不存在的单号
|
||||
for (String detailOrderNumber : detailGroupMap.keySet()) {
|
||||
if (!orderNumberSet.contains(detailOrderNumber)) {
|
||||
errorList.add("明细文件中入库单号【" + detailOrderNumber + "】在主表文件中不存在");
|
||||
}
|
||||
}
|
||||
|
||||
// 逐单入库(即使有未匹配到基础数据的警告也不阻断,错误信息随结果返回)
|
||||
// 直接走 MyBatis-Plus 入库,绕过领域服务/应用服务层的参数补全逻辑,避免货主/物料未匹配等场景报错
|
||||
int detailCount = 0;
|
||||
for (ReserveStockInOrderDO stockInOrderDO : stockInOrderList) {
|
||||
// 主表:DO -> 实体 -> save
|
||||
ReserveStockInOrder stockInOrder = new ReserveStockInOrder();
|
||||
BeanUtils.copyProperties(stockInOrderDO, stockInOrder);
|
||||
stockInOrder.setMaterialQuantity(stockInOrderDO.getMaterialDetailList().size());
|
||||
BigDecimal totalQuantity = stockInOrderDO.getMaterialDetailList().stream()
|
||||
.map(ReserveInMaterialDetailDO::getQuantity).filter(Objects::nonNull)
|
||||
.reduce(BigDecimal.ZERO, BigDecimal::add);
|
||||
stockInOrder.setQuantity(totalQuantity);
|
||||
stockInOrder.setReserveQuantity(totalQuantity);
|
||||
stockInOrderService.save(stockInOrder);
|
||||
|
||||
// 明细:DO -> 实体 -> saveBatch
|
||||
List<ReserveInMaterialDetail> detailEntities = new ArrayList<>();
|
||||
for (ReserveInMaterialDetailDO detailDO : stockInOrderDO.getMaterialDetailList()) {
|
||||
ReserveInMaterialDetail detail = new ReserveInMaterialDetail();
|
||||
BeanUtils.copyProperties(detailDO, detail);
|
||||
detail.setInOrderNumber(stockInOrderDO.getInOrderNumber());
|
||||
detail.setLevel(1);
|
||||
detailEntities.add(detail);
|
||||
}
|
||||
if (!detailEntities.isEmpty()) {
|
||||
materialDetailService.saveBatch(detailEntities);
|
||||
}
|
||||
detailCount += detailEntities.size();
|
||||
}
|
||||
Map<String, Object> result = new HashMap<>();
|
||||
result.put("orderCount", stockInOrderList.size());
|
||||
result.put("detailCount", detailCount);
|
||||
if (!errorList.isEmpty()) {
|
||||
result.put("warnings", errorList);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public static String generateDateTimeWithRandom() {
|
||||
// 1. 获取当前时间,格式化:yyMMddHHmmss
|
||||
LocalDateTime now = LocalDateTime.now();
|
||||
|
||||
+12
@@ -2,6 +2,7 @@ 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;
|
||||
@@ -38,4 +39,15 @@ public interface ReserveStockOutOrderMapper extends BaseMapper<ReserveStockOutOr
|
||||
int countByOrderNumberPrefix(@Param("prefix") String prefix);
|
||||
|
||||
List<String> generateReserveOrderNumber1(@Param("prefix") String prefix);
|
||||
|
||||
/**
|
||||
* 老系统数据导入:根据出库单号精确统计(防重)
|
||||
*/
|
||||
int countByOutOrderNumber(@Param("outOrderNumber") String outOrderNumber);
|
||||
|
||||
/**
|
||||
* 老系统数据导入:根据仓库类型查询仓库
|
||||
* @param warehouseType 仓库类型编码(如 "1"/"2")
|
||||
*/
|
||||
List<WarehousePO> getWarehouseByType(@Param("warehouseType") String warehouseType);
|
||||
}
|
||||
+52
@@ -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<LegacyReserveOutOrderVO> parseLegacyOrderExcel(MultipartFile file) throws IOException {
|
||||
validateFile(file);
|
||||
List<LegacyReserveOutOrderVO> dataList;
|
||||
try (InputStream inputStream = file.getInputStream()) {
|
||||
dataList = EasyExcel.read(inputStream)
|
||||
.head(LegacyReserveOutOrderVO.class)
|
||||
.sheet(0)
|
||||
.headRowNumber(1)
|
||||
.doReadSync();
|
||||
}
|
||||
// 过滤出库单号为空的无效行
|
||||
return dataList.stream()
|
||||
.filter(row -> row != null && StringUtils.isNotBlank(row.getOutOrderNumber()))
|
||||
.collect(java.util.stream.Collectors.toList());
|
||||
}
|
||||
|
||||
/**
|
||||
* 解析老系统《出库预约单明细列表》Excel(表头第1行,数据从第2行开始)
|
||||
* 物料名称取物料名称1和物料名称2中有值的那一个
|
||||
*/
|
||||
public static List<LegacyReserveOutDetailVO> parseLegacyDetailExcel(MultipartFile file) throws IOException {
|
||||
validateFile(file);
|
||||
List<LegacyReserveOutDetailVO> dataList;
|
||||
try (InputStream inputStream = file.getInputStream()) {
|
||||
dataList = EasyExcel.read(inputStream)
|
||||
.head(LegacyReserveOutDetailVO.class)
|
||||
.sheet(0)
|
||||
.headRowNumber(1)
|
||||
.doReadSync();
|
||||
}
|
||||
// 过滤出库单号为空的无效行,同时把 materialName1/materialName2 中有值的赋给 materialName
|
||||
return dataList.stream()
|
||||
.filter(row -> row != null && StringUtils.isNotBlank(row.getOutOrderNumber()))
|
||||
.map(row -> {
|
||||
if (StringUtils.isBlank(row.getMaterialName())) {
|
||||
if (StringUtils.isNotBlank(row.getMaterialName1())) {
|
||||
row.setMaterialName(row.getMaterialName1());
|
||||
} else if (StringUtils.isNotBlank(row.getMaterialName2())) {
|
||||
row.setMaterialName(row.getMaterialName2());
|
||||
}
|
||||
}
|
||||
return row;
|
||||
})
|
||||
.collect(java.util.stream.Collectors.toList());
|
||||
}
|
||||
|
||||
/**
|
||||
* 验证Excel文件合法性
|
||||
*/
|
||||
|
||||
+91
@@ -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;
|
||||
}
|
||||
+82
@@ -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;
|
||||
}
|
||||
+243
@@ -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<String, Object> importLegacyData(List<LegacyReserveOutOrderVO> orderList, List<LegacyReserveOutDetailVO> detailList) {
|
||||
if (orderList == null || orderList.isEmpty()) {
|
||||
throw new ValidationException("出库预约单列表文件中没有有效数据");
|
||||
}
|
||||
if (detailList == null || detailList.isEmpty()) {
|
||||
throw new ValidationException("出库预约单明细列表文件中没有有效数据");
|
||||
}
|
||||
|
||||
// 明细按出库单号分组
|
||||
Map<String, List<LegacyReserveOutDetailVO>> detailGroupMap = new LinkedHashMap<>();
|
||||
for (LegacyReserveOutDetailVO detailRow : detailList) {
|
||||
detailGroupMap.computeIfAbsent(detailRow.getOutOrderNumber().trim(), k -> new ArrayList<>()).add(detailRow);
|
||||
}
|
||||
|
||||
List<String> errorList = new ArrayList<>();
|
||||
// 名称匹配结果缓存,避免重复查库
|
||||
Map<String, UserPo> shipperCache = new HashMap<>();
|
||||
// 仓库类型 -> 仓库 缓存(老系统只有仓库类型,没有仓库名称)
|
||||
Map<String, WarehousePO> warehouseTypeCache = new HashMap<>();
|
||||
Map<String, MaterialBaseInfoPO> materialCache = new HashMap<>();
|
||||
|
||||
Set<String> orderNumberSet = new HashSet<>();
|
||||
List<ReserveStockOutOrderDO> stockOutOrderList = new ArrayList<>();
|
||||
int lotIndex = 1;
|
||||
for (LegacyReserveOutOrderVO orderRow : orderList) {
|
||||
String orderNumber = orderRow.getOutOrderNumber().trim();
|
||||
if (!orderNumberSet.add(orderNumber)) {
|
||||
errorList.add("出库单号【" + orderNumber + "】在主表文件中重复");
|
||||
continue;
|
||||
}
|
||||
if (reserveStockOutOrderMapper.countByOutOrderNumber(orderNumber) > 0) {
|
||||
errorList.add("出库单号【" + orderNumber + "】在系统中已存在,请勿重复导入");
|
||||
continue;
|
||||
}
|
||||
|
||||
// 按货主名称匹配用户(查不到则用Excel中的名称兜底,不阻断导入)
|
||||
UserPo shipper = null;
|
||||
String shipperName = StringUtils.trimToEmpty(orderRow.getShipperName());
|
||||
if (StringUtils.isBlank(shipperName)) {
|
||||
errorList.add("出库单号【" + orderNumber + "】货主名称为空");
|
||||
} else {
|
||||
shipper = shipperCache.get(shipperName);
|
||||
if (shipper == null) {
|
||||
List<UserPo> userPoList = reserveStockInOrderMapper.getShipperByName(shipperName);
|
||||
if (userPoList == null || userPoList.isEmpty()) {
|
||||
errorList.add("出库单号【" + orderNumber + "】货主【" + shipperName + "】未找到对应用户,将仅以名称导入");
|
||||
} else {
|
||||
shipper = userPoList.get(0);
|
||||
shipperCache.put(shipperName, shipper);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 按仓库类型匹配仓库(老系统仓库类型 1=干仓 2=冬仓,查不到则用类型名兜底)
|
||||
WarehousePO warehouse = null;
|
||||
String warehouseType = StringUtils.trimToEmpty(orderRow.getWarehouseType());
|
||||
if (StringUtils.isNotBlank(warehouseType)) {
|
||||
warehouse = warehouseTypeCache.get(warehouseType);
|
||||
if (warehouse == null) {
|
||||
List<WarehousePO> warehousePOList = reserveStockOutOrderMapper.getWarehouseByType(warehouseType);
|
||||
if (warehousePOList == null || warehousePOList.isEmpty()) {
|
||||
String fallbackName = "1".equals(warehouseType) ? "干仓" : ("2".equals(warehouseType) ? "冻仓" : "");
|
||||
errorList.add("出库单号【" + orderNumber + "】仓库类型【" + warehouseType + "】未找到对应仓库,将仅以名称导入");
|
||||
warehouseTypeCache.put(warehouseType, null);
|
||||
warehouse = null;
|
||||
} else {
|
||||
warehouse = warehousePOList.get(0);
|
||||
warehouseTypeCache.put(warehouseType, warehouse);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 明细匹配
|
||||
List<LegacyReserveOutDetailVO> detailRows = detailGroupMap.get(orderNumber);
|
||||
if (detailRows == null || detailRows.isEmpty()) {
|
||||
errorList.add("出库单号【" + orderNumber + "】在明细文件中没有明细数据");
|
||||
continue;
|
||||
}
|
||||
List<ReserveOutMaterialDetailDO> materialDetailList = new ArrayList<>();
|
||||
for (LegacyReserveOutDetailVO detailRow : detailRows) {
|
||||
String materialName = StringUtils.trimToEmpty(detailRow.getMaterialName());
|
||||
if (StringUtils.isBlank(materialName)) {
|
||||
errorList.add("出库单号【" + orderNumber + "】存在物料名称为空的明细行");
|
||||
continue;
|
||||
}
|
||||
// 按物料名称匹配物料基础信息(查不到则用Excel中的名称兜底,不阻断导入)
|
||||
MaterialBaseInfoPO materialBaseInfoPO = materialCache.get(materialName);
|
||||
if (materialBaseInfoPO == null) {
|
||||
List<MaterialBaseInfoPO> materialBaseInfoPOS = reserveStockInOrderMapper.getByName(materialName);
|
||||
if (materialBaseInfoPOS == null || materialBaseInfoPOS.isEmpty()) {
|
||||
errorList.add("出库单号【" + orderNumber + "】物料【" + materialName + "】未找到对应物料,将仅以名称导入");
|
||||
} else {
|
||||
materialBaseInfoPO = materialBaseInfoPOS.get(0);
|
||||
materialCache.put(materialName, materialBaseInfoPO);
|
||||
}
|
||||
}
|
||||
ReserveOutMaterialDetailDO materialDetail = new ReserveOutMaterialDetailDO();
|
||||
if (materialBaseInfoPO != null) {
|
||||
materialDetail.setMaterialBaseInfoId(materialBaseInfoPO.getMaterialBaseInfoId());
|
||||
materialDetail.setMaterialCode(materialBaseInfoPO.getMaterialCode());
|
||||
materialDetail.setUnitCode(materialBaseInfoPO.getUnitCode());
|
||||
materialDetail.setUnitName(materialBaseInfoPO.getUnitName());
|
||||
}
|
||||
materialDetail.setMaterialName(materialName);
|
||||
materialDetail.setReserveMaterialName(materialName);
|
||||
materialDetail.setQuantity(detailRow.getQuantity());
|
||||
materialDetail.setOutboundQuantity(detailRow.getQuantity());
|
||||
materialDetail.setTotalNetWeight(detailRow.getWeight());
|
||||
materialDetail.setTotalGrossWeight(detailRow.getWeight());
|
||||
// 保留老系统关联的入库单号到备注
|
||||
if (StringUtils.isNotBlank(detailRow.getInOrderNumber())) {
|
||||
// materialDetail.setRemark("老系统入库单号:" + detailRow.getInOrderNumber());
|
||||
materialDetail.setInOrderNumber(detailRow.getInOrderNumber());
|
||||
}
|
||||
materialDetail.setContractFee(BigDecimal.ZERO);
|
||||
materialDetail.setLotNo(generateDateSerialNumber() + "-" + lotIndex);
|
||||
lotIndex++;
|
||||
// 组织字段硬编码(与入库导入保持一致)
|
||||
materialDetail.setOrganizationId(2841L);
|
||||
materialDetail.setOrganizationName("仓码");
|
||||
materialDetail.setTopOrganizationId(2827L);
|
||||
// 创建人/修改人名称取老系统Excel中的值,不使用当前登录人
|
||||
materialDetail.setCreateTime(detailRow.getCreateTime() != null ? detailRow.getCreateTime() : new Date());
|
||||
materialDetail.setCreateByName(detailRow.getCreateByName());
|
||||
materialDetail.setUpdateTime(detailRow.getUpdateTime());
|
||||
materialDetail.setUpdateByName(detailRow.getUpdateByName());
|
||||
materialDetail.setUniqueId(idGenerator.snowflakeId(SnowFlakeConstants.wmsId));
|
||||
materialDetailList.add(materialDetail);
|
||||
}
|
||||
|
||||
// 组装出库预约单
|
||||
ReserveStockOutOrderDO stockOutOrderDO = new ReserveStockOutOrderDO();
|
||||
stockOutOrderDO.setOutOrderNumber(orderNumber);
|
||||
stockOutOrderDO.setBusinessOrderNo(orderNumber);
|
||||
// 老系统历史数据,状态直接置为最终状态:已出库、审核通过
|
||||
stockOutOrderDO.setStatus(9);
|
||||
stockOutOrderDO.setAuditStatus(3);
|
||||
stockOutOrderDO.setIssueStatus(3);
|
||||
stockOutOrderDO.setOutboundDate(orderRow.getOutboundDate());
|
||||
stockOutOrderDO.setNeedTransportFlag("0");
|
||||
stockOutOrderDO.setNeedDeclareFlag("0");
|
||||
stockOutOrderDO.setExpectTime(orderRow.getOutboundDate() != null ? orderRow.getOutboundDate() : new Date());
|
||||
stockOutOrderDO.setDocumentDate(orderRow.getDocumentDate() != null ? orderRow.getDocumentDate() : new Date());
|
||||
stockOutOrderDO.setDocumentCreator(orderRow.getDocumentCreator());
|
||||
stockOutOrderDO.setRemark(orderRow.getRemark());
|
||||
if (shipper != null) {
|
||||
stockOutOrderDO.setShipperId(shipper.getUserId());
|
||||
stockOutOrderDO.setShipperName(shipper.getUserName());
|
||||
stockOutOrderDO.setCustomerId(shipper.getUserId());
|
||||
stockOutOrderDO.setCustomerName(shipper.getUserName());
|
||||
stockOutOrderDO.setSalesmanId(String.valueOf(shipper.getUserId()));
|
||||
stockOutOrderDO.setSalesmanName(shipper.getUserName());
|
||||
stockOutOrderDO.setCustomerCode(reserveStockInOrderMapper.getCustomerNcCodeByUserId(shipper.getUserId()));
|
||||
} else {
|
||||
// 货主未匹配到,仅以Excel中的名称作为名称字段,id留空
|
||||
stockOutOrderDO.setShipperName(shipperName);
|
||||
stockOutOrderDO.setCustomerName(shipperName);
|
||||
stockOutOrderDO.setSalesmanName(shipperName);
|
||||
}
|
||||
// 组织字段硬编码(与入库导入保持一致)
|
||||
stockOutOrderDO.setOrganizationId(2841L);
|
||||
stockOutOrderDO.setOrganizationName("仓码");
|
||||
stockOutOrderDO.setTopOrganizationId(2827L);
|
||||
if (warehouse != null) {
|
||||
stockOutOrderDO.setWarehouseId(warehouse.getWarehouseId());
|
||||
stockOutOrderDO.setWarehouseCode(warehouse.getWarehouseCode());
|
||||
stockOutOrderDO.setWarehouseName(warehouse.getWarehouseName());
|
||||
} else if (StringUtils.isNotBlank(warehouseType)) {
|
||||
// 仓库未匹配到,仅以仓库类型名作为仓库名称,id/编码留空
|
||||
String fallbackName = "1".equals(warehouseType) ? "干仓" : ("2".equals(warehouseType) ? "冻仓" : "");
|
||||
if (StringUtils.isNotBlank(fallbackName)) {
|
||||
stockOutOrderDO.setWarehouseName(fallbackName);
|
||||
}
|
||||
}
|
||||
// 创建人/修改人名称取老系统Excel中的值,不使用当前登录人
|
||||
stockOutOrderDO.setCreateTime(orderRow.getCreateTime() != null ? orderRow.getCreateTime() : new Date());
|
||||
stockOutOrderDO.setCreateByName(orderRow.getCreateByName());
|
||||
stockOutOrderDO.setUpdateTime(orderRow.getUpdateTime());
|
||||
stockOutOrderDO.setUpdateByName(orderRow.getUpdateByName());
|
||||
stockOutOrderDO.setMaterialDetailList(materialDetailList);
|
||||
stockOutOrderList.add(stockOutOrderDO);
|
||||
}
|
||||
|
||||
// 明细文件中存在但主表文件中不存在的单号
|
||||
for (String detailOrderNumber : detailGroupMap.keySet()) {
|
||||
if (!orderNumberSet.contains(detailOrderNumber)) {
|
||||
errorList.add("明细文件中出库单号【" + detailOrderNumber + "】在主表文件中不存在");
|
||||
}
|
||||
}
|
||||
|
||||
// 逐单入库(即使有未匹配到基础数据的警告也不阻断,错误信息随结果返回)
|
||||
// 直接走 MyBatis-Plus 入库,绕过领域服务/应用服务层的参数补全逻辑
|
||||
int detailCount = 0;
|
||||
for (ReserveStockOutOrderDO stockOutOrderDO : stockOutOrderList) {
|
||||
// 主表:DO -> 实体 -> save
|
||||
ReserveStockOutOrder stockOutOrder = new ReserveStockOutOrder();
|
||||
BeanUtils.copyProperties(stockOutOrderDO, stockOutOrder);
|
||||
stockOutOrder.setMaterialQuantity(stockOutOrderDO.getMaterialDetailList().size());
|
||||
BigDecimal totalQuantity = stockOutOrderDO.getMaterialDetailList().stream()
|
||||
.map(ReserveOutMaterialDetailDO::getQuantity).filter(Objects::nonNull)
|
||||
.reduce(BigDecimal.ZERO, BigDecimal::add);
|
||||
stockOutOrder.setQuantity(totalQuantity);
|
||||
stockOutOrderService.save(stockOutOrder);
|
||||
|
||||
// 明细:DO -> 实体 -> saveBatch
|
||||
List<ReserveOutMaterialDetail> detailEntities = new ArrayList<>();
|
||||
for (ReserveOutMaterialDetailDO detailDO : stockOutOrderDO.getMaterialDetailList()) {
|
||||
ReserveOutMaterialDetail detail = new ReserveOutMaterialDetail();
|
||||
BeanUtils.copyProperties(detailDO, detail);
|
||||
detail.setOutOrderNumber(stockOutOrderDO.getOutOrderNumber());
|
||||
detailEntities.add(detail);
|
||||
}
|
||||
if (!detailEntities.isEmpty()) {
|
||||
outMaterialDetailService.saveBatch(detailEntities);
|
||||
}
|
||||
detailCount += detailEntities.size();
|
||||
}
|
||||
Map<String, Object> result = new HashMap<>();
|
||||
result.put("orderCount", stockOutOrderList.size());
|
||||
result.put("detailCount", detailCount);
|
||||
if (!errorList.isEmpty()) {
|
||||
result.put("warnings", errorList);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public void importInData(List<ReservedInventoryOut> dataList) {
|
||||
LoginUser loginUser = SecurityUtils.getLoginUser();
|
||||
ReserveStockOutOrderDO reserveStockOutOrder = new ReserveStockOutOrderDO();
|
||||
|
||||
+57
@@ -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;
|
||||
@@ -303,4 +305,59 @@ public class ReserveStockOutOrderApi extends BaseController {
|
||||
return AjaxResult.success(stockOutOrderApplicationService.generateReserveOrderNumber());
|
||||
}
|
||||
|
||||
/**
|
||||
* 老系统出库预约单数据导入(两个文件:主表+明细)
|
||||
* 通过货主名称、仓库类型、物料名称等匹配基础数据,id类字段不使用
|
||||
* 仓库类型:1=干仓 2=冬仓
|
||||
* 明细物料名称:取物料名称1和物料名称2中有值的那一个
|
||||
*/
|
||||
@ApiOperation("老系统出库预约单数据导入")
|
||||
@PostMapping("/importLegacy")
|
||||
public ResponseEntity<Map<String, Object>> importLegacyData(
|
||||
@RequestParam("orderFile") MultipartFile orderFile,
|
||||
@RequestParam("detailFile") MultipartFile detailFile) {
|
||||
try {
|
||||
// 1. 解析两个Excel文件
|
||||
List<LegacyReserveOutOrderVO> orderList = ExcelParseUtil.parseLegacyOrderExcel(orderFile);
|
||||
List<LegacyReserveOutDetailVO> detailList = ExcelParseUtil.parseLegacyDetailExcel(detailFile);
|
||||
|
||||
// 2. 调用应用服务执行导入
|
||||
Map<String, Object> result = stockOutOrderApplicationService.importLegacyData(orderList, detailList);
|
||||
|
||||
Map<String, Object> successResponse = new HashMap<>();
|
||||
successResponse.put("code", 200);
|
||||
successResponse.put("message", "老系统出库预约单数据导入成功");
|
||||
successResponse.put("orderCount", result.get("orderCount"));
|
||||
successResponse.put("detailCount", result.get("detailCount"));
|
||||
if (result.containsKey("warnings")) {
|
||||
successResponse.put("warnings", result.get("warnings"));
|
||||
}
|
||||
return ResponseEntity.ok(successResponse);
|
||||
|
||||
} catch (ValidationException e) {
|
||||
log.error("老系统出库预约单数据验证失败: {}", e.getMessage(), e);
|
||||
Map<String, Object> errorResponse = new HashMap<>();
|
||||
errorResponse.put("code", 400);
|
||||
errorResponse.put("message", "数据验证失败");
|
||||
errorResponse.put("errorDetails", e.getMessage());
|
||||
return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(errorResponse);
|
||||
|
||||
} catch (IOException e) {
|
||||
log.error("老系统出库预约单文件处理失败: {}", e.getMessage(), e);
|
||||
Map<String, Object> errorResponse = new HashMap<>();
|
||||
errorResponse.put("code", 500);
|
||||
errorResponse.put("message", "文件处理失败");
|
||||
errorResponse.put("errorDetails", e.getMessage());
|
||||
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(errorResponse);
|
||||
|
||||
} catch (Exception e) {
|
||||
log.error("老系统出库预约单导入失败: {}", e.getMessage(), e);
|
||||
Map<String, Object> errorResponse = new HashMap<>();
|
||||
errorResponse.put("code", 500);
|
||||
errorResponse.put("message", "导入失败");
|
||||
errorResponse.put("errorDetails", e.getMessage());
|
||||
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(errorResponse);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
+66
@@ -10,12 +10,15 @@ import com.mhd.oms.domain.reserveStockInOrder.repository.todo.ReserveStockInOrde
|
||||
import com.mhd.oms.domain.reserveStockInOrder.repository.todo.ReserveStockInOrderDTO;
|
||||
import com.mhd.oms.domain.reserveStockInOrder.repository.util.ExcelParseUtil;
|
||||
import com.mhd.oms.domain.reserveStockInOrder.repository.vo.InAndOutListVo;
|
||||
import com.mhd.oms.domain.reserveStockInOrder.repository.vo.LegacyReserveInDetailVO;
|
||||
import com.mhd.oms.domain.reserveStockInOrder.repository.vo.LegacyReserveInOrderVO;
|
||||
import com.mhd.oms.domain.reserveStockInOrder.repository.vo.ReservedInventory;
|
||||
import com.mhd.oms.domain.reserveStockInOrder.service.ReserveStockInOrderApplicationService;
|
||||
import com.mhd.oms.domain.reserveStockInOrder.service.ReserveStockInOrderAssembler;
|
||||
import com.mhd.system.api.domain.InMaterialDetailTZPD;
|
||||
import com.mhd.system.api.domain.StockInOrderTZPD;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
@@ -34,6 +37,7 @@ import java.util.Map;
|
||||
* @author gen
|
||||
* @date 2024-05-21
|
||||
*/
|
||||
@Slf4j
|
||||
@RestController
|
||||
@RequestMapping("/reserveStockInOrderApi")
|
||||
public class ReserveStockInOrderApi extends BaseController {
|
||||
@@ -256,6 +260,68 @@ public class ReserveStockInOrderApi extends BaseController {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 老系统入库预约单数据导入(主表+明细两个Excel文件批量导入,按名称匹配基础数据)
|
||||
*/
|
||||
@ApiOperation("老系统入库预约单数据导入")
|
||||
@PostMapping("/importLegacy")
|
||||
public ResponseEntity<Map<String, Object>> importLegacyExcel(
|
||||
@RequestParam("orderFile") MultipartFile orderFile,
|
||||
@RequestParam("detailFile") MultipartFile detailFile) {
|
||||
try {
|
||||
List<LegacyReserveInOrderVO> orderList = ExcelParseUtil.parseLegacyOrderExcel(orderFile);
|
||||
List<LegacyReserveInDetailVO> detailList = ExcelParseUtil.parseLegacyDetailExcel(detailFile);
|
||||
|
||||
Map<String, Object> importResult = stockInOrderApplicationService.importLegacyData(orderList, detailList);
|
||||
|
||||
Map<String, Object> successResponse = new HashMap<>();
|
||||
successResponse.put("code", 200);
|
||||
successResponse.put("message", "老系统数据导入成功");
|
||||
successResponse.put("orderCount", importResult.get("orderCount"));
|
||||
successResponse.put("detailCount", importResult.get("detailCount"));
|
||||
if (importResult.containsKey("warnings")) {
|
||||
successResponse.put("warnings", importResult.get("warnings"));
|
||||
}
|
||||
return ResponseEntity.ok(successResponse);
|
||||
|
||||
} catch (ValidationException e) {
|
||||
// 数据验证失败响应
|
||||
log.warn("老系统数据导入校验失败: {}", e.getMessage());
|
||||
Map<String, Object> errorResponse = new HashMap<>();
|
||||
errorResponse.put("code", 400);
|
||||
errorResponse.put("message", "数据验证失败");
|
||||
errorResponse.put("errorDetails", e.getMessage());
|
||||
return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(errorResponse);
|
||||
|
||||
} catch (IOException e) {
|
||||
// 文件处理失败响应
|
||||
log.error("老系统数据导入文件处理失败", e);
|
||||
Map<String, Object> errorResponse = new HashMap<>();
|
||||
errorResponse.put("code", 500);
|
||||
errorResponse.put("message", "文件处理失败");
|
||||
errorResponse.put("errorDetails", e.getClass().getSimpleName() + ": " + e.getMessage());
|
||||
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(errorResponse);
|
||||
|
||||
} catch (Exception e) {
|
||||
// 其他未知错误响应:打印完整堆栈,把真正的报错信息报出来
|
||||
log.error("老系统数据导入发生未知异常", e);
|
||||
String errorType = e.getClass().getSimpleName();
|
||||
String errorMsg = e.getMessage() != null ? e.getMessage() : "无详细信息";
|
||||
// 如果异常带有 cause,则再追加 cause 信息,方便定位根因
|
||||
Throwable cause = e.getCause();
|
||||
StringBuilder detail = new StringBuilder();
|
||||
detail.append(errorType).append(": ").append(errorMsg);
|
||||
if (cause != null && cause != e) {
|
||||
detail.append(" | 根因: ").append(cause.getClass().getSimpleName()).append(": ").append(cause.getMessage());
|
||||
}
|
||||
Map<String, Object> errorResponse = new HashMap<>();
|
||||
errorResponse.put("code", 500);
|
||||
errorResponse.put("message", detail.toString());
|
||||
errorResponse.put("errorDetails", detail.toString());
|
||||
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(errorResponse);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成入库预约单号
|
||||
*/
|
||||
|
||||
@@ -788,4 +788,47 @@
|
||||
WHERE in_order_number LIKE concat(#{prefix}, '%')
|
||||
</select>
|
||||
|
||||
<!-- 老系统数据导入:根据货主名称查询用户 -->
|
||||
<select id="getShipperByName" parameterType="java.lang.String" resultType="com.mhd.common.core.domain.po.UserPo">
|
||||
select USER_ID, USER_NAME, ORGANIZATION_ID, ORGANIZATION_NAME, TOP_ORGANIZATION_ID
|
||||
from NGWL_TEST_USER."USER"
|
||||
where DEL_FLAG = 1 and USER_NAME = #{name}
|
||||
</select>
|
||||
|
||||
<!-- 老系统数据导入:根据仓库名称查询仓库(支持模糊匹配,如Excel中"凍倉-陳美玲"匹配系统中"凍倉") -->
|
||||
<select id="getWarehouseByName" parameterType="java.lang.String" resultType="com.mhd.common.core.domain.po.WarehousePO">
|
||||
select WAREHOUSE_ID, WAREHOUSE_CODE, WAREHOUSE_NAME
|
||||
from "NGWL_TEST_SYSTEM".WAREHOUSE
|
||||
where DEL_FLAG = 1
|
||||
and (
|
||||
WAREHOUSE_NAME = #{name}
|
||||
or #{name} LIKE ('%' || WAREHOUSE_NAME || '%')
|
||||
)
|
||||
order by case when WAREHOUSE_NAME = #{name} then 0 else 1 end,
|
||||
length(WAREHOUSE_NAME) asc
|
||||
</select>
|
||||
|
||||
<!-- 老系统数据导入:根据仓库类型查询仓库(1=干仓 2=冬仓) -->
|
||||
<select id="getWarehouseByType" parameterType="java.lang.String" resultType="com.mhd.common.core.domain.po.WarehousePO">
|
||||
select WAREHOUSE_ID, WAREHOUSE_CODE, WAREHOUSE_NAME
|
||||
from "NGWL_TEST_SYSTEM".WAREHOUSE
|
||||
where DEL_FLAG = 1
|
||||
and (
|
||||
WAREHOUSE_TYPE = #{warehouseType}
|
||||
or WAREHOUSE_TYPE_NAME = case when #{warehouseType} = '1' then '干仓' when #{warehouseType} = '2' then '冻仓' else null end
|
||||
)
|
||||
</select>
|
||||
|
||||
<!-- 老系统数据导入:根据货主用户ID查询NC客户编码 -->
|
||||
<select id="getCustomerNcCodeByUserId" parameterType="java.lang.Long" resultType="java.lang.String">
|
||||
select CUSTOMER_NC_CODE from "NGWL_TEST_USER".USER_SHIPPER where DEL_FLAG = 1 and USER_ID = #{id} limit 1
|
||||
</select>
|
||||
|
||||
<!-- 老系统数据导入:根据入库单号精确统计(防重) -->
|
||||
<select id="countByInOrderNumber" resultType="java.lang.Integer" parameterType="java.lang.String">
|
||||
SELECT COUNT(1)
|
||||
FROM reserve_stock_in_order
|
||||
WHERE in_order_number = #{inOrderNumber}
|
||||
</select>
|
||||
|
||||
</mapper>
|
||||
@@ -528,4 +528,24 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
WHERE out_order_number LIKE concat(#{prefix}, '%')
|
||||
</select>
|
||||
|
||||
<!-- 老系统数据导入:根据出库单号精确统计(防重) -->
|
||||
<select id="countByOutOrderNumber" resultType="java.lang.Integer" parameterType="java.lang.String">
|
||||
SELECT COUNT(1)
|
||||
FROM reserve_stock_out_order
|
||||
WHERE out_order_number = #{outOrderNumber}
|
||||
</select>
|
||||
|
||||
<!-- 老系统数据导入:根据仓库类型查询仓库
|
||||
老系统仓库类型 1=干仓 2=冬仓;新系统 WAREHOUSE_TYPE 为数据字典编码
|
||||
同时尝试匹配 WAREHOUSE_TYPE 编码和 WAREHOUSE_TYPE_NAME 名称,兼容字典值与老系统编码一致或不一致两种情况 -->
|
||||
<select id="getWarehouseByType" parameterType="java.lang.String" resultType="com.mhd.common.core.domain.po.WarehousePO">
|
||||
select WAREHOUSE_ID, WAREHOUSE_CODE, WAREHOUSE_NAME
|
||||
from "NGWL_TEST_SYSTEM".WAREHOUSE
|
||||
where DEL_FLAG = 1
|
||||
and (
|
||||
WAREHOUSE_TYPE = #{warehouseType}
|
||||
or WAREHOUSE_TYPE_NAME = case when #{warehouseType} = '1' then '干仓' when #{warehouseType} = '2' then '冻仓' else null end
|
||||
)
|
||||
</select>
|
||||
|
||||
</mapper>
|
||||
+65
-3
@@ -630,9 +630,71 @@ public class StockInOrderApplicationService {
|
||||
info.setKhdm(userNcCode);
|
||||
List<InMaterialDetailPO> materialDetailList = info.getMaterialDetailList();
|
||||
if (materialDetailList != null && !materialDetailList.isEmpty()) {
|
||||
for (InMaterialDetailPO inMaterialDetailPO : materialDetailList) {
|
||||
// TODO: 设置物料详情信息
|
||||
inMaterialDetailPO.setKhdm(userNcCode);
|
||||
// 收集所有有效的物料基础信息ID
|
||||
Set<Long> materialBaseInfoIdSet = new HashSet<>();
|
||||
for (InMaterialDetailPO detail : materialDetailList) {
|
||||
if (detail.getMaterialBaseInfoId() != null && detail.getMaterialBaseInfoId() > 0) {
|
||||
materialBaseInfoIdSet.add(detail.getMaterialBaseInfoId());
|
||||
}
|
||||
}
|
||||
|
||||
// 批量查询物料基础信息,try-catch保护,防止没有ID时NPE
|
||||
Map<Long, MaterialBaseInfoPO> materialBaseInfoMap = new HashMap<>();
|
||||
for (Long materialBaseInfoId : materialBaseInfoIdSet) {
|
||||
try {
|
||||
MaterialBaseInfoPO materialBaseInfoPO = materialBaseInfoService.getInfo(materialBaseInfoId);
|
||||
if (materialBaseInfoPO != null) {
|
||||
materialBaseInfoMap.put(materialBaseInfoId, materialBaseInfoPO);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.warn("获取物料基础信息失败,物料基础信息ID:{},错误:{}", materialBaseInfoId, e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
// 填充明细的物料字段(物料编码、抄码、条码、单位等)
|
||||
Long shipperId = info.getShipperId();
|
||||
for (InMaterialDetailPO detail : materialDetailList) {
|
||||
detail.setKhdm(userNcCode);
|
||||
Long materialBaseInfoId = detail.getMaterialBaseInfoId();
|
||||
MaterialBaseInfoPO materialBaseInfoPO = null;
|
||||
|
||||
if (materialBaseInfoId != null && materialBaseInfoId > 0) {
|
||||
materialBaseInfoPO = materialBaseInfoMap.get(materialBaseInfoId);
|
||||
}
|
||||
// 兜底:ID=0时用物料名称反查
|
||||
if (materialBaseInfoPO == null && StringUtils.isNotBlank(detail.getMaterialName())) {
|
||||
try {
|
||||
MaterialBaseInfoDO queryDO = new MaterialBaseInfoDO();
|
||||
queryDO.setMaterialName(detail.getMaterialName().trim());
|
||||
if (shipperId != null && shipperId > 0) {
|
||||
queryDO.setShipperId(shipperId);
|
||||
}
|
||||
List<MaterialBaseInfoPO> list = materialBaseInfoService.queryList(queryDO);
|
||||
if (list != null && !list.isEmpty()) {
|
||||
materialBaseInfoPO = list.get(0);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.warn("兜底反查物料失败,物料名:{}", detail.getMaterialName());
|
||||
}
|
||||
}
|
||||
|
||||
if (materialBaseInfoPO != null) {
|
||||
if (StringUtils.isBlank(detail.getMaterialCode())) {
|
||||
detail.setMaterialCode(materialBaseInfoPO.getMaterialCode());
|
||||
}
|
||||
if (StringUtils.isBlank(detail.getBarCode())) {
|
||||
detail.setBarCode(materialBaseInfoPO.getBarCode());
|
||||
}
|
||||
if (StringUtils.isBlank(detail.getUnitCode())) {
|
||||
detail.setUnitCode(materialBaseInfoPO.getUnitCode());
|
||||
}
|
||||
if (StringUtils.isBlank(detail.getUnitName())) {
|
||||
detail.setUnitName(materialBaseInfoPO.getUnitName());
|
||||
}
|
||||
detail.setPackId(materialBaseInfoPO.getPackId());
|
||||
detail.setPackCode(materialBaseInfoPO.getPackCode());
|
||||
detail.setPackName(materialBaseInfoPO.getPackName());
|
||||
}
|
||||
}
|
||||
info.setMaterialDetailList(materialDetailList);
|
||||
}
|
||||
|
||||
+3
-1
@@ -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的单位名称)
|
||||
|
||||
@@ -14,18 +14,18 @@ spring:
|
||||
nacos:
|
||||
discovery:
|
||||
# server-addr: 127.0.0.1:8848
|
||||
# server-addr: 10.33.0.129:6010
|
||||
server-addr: 10.33.0.129:6010
|
||||
# 线上测试环境配置 容器名+端口号
|
||||
server-addr: 10.102.192.30:6848
|
||||
# server-addr: 10.102.192.30:6848
|
||||
username: nacos
|
||||
password: manhuoda@2023
|
||||
#线上正式环境
|
||||
# server-addr: 10.102.192.105:6848
|
||||
config:
|
||||
# server-addr: 127.0.0.1:8848
|
||||
# server-addr: 10.33.0.129:6010
|
||||
server-addr: 10.33.0.129:6010
|
||||
# 线上测试环境配置 容器名+端口号
|
||||
server-addr: 10.102.192.30:6848
|
||||
# server-addr: 10.102.192.30:6848
|
||||
username: nacos
|
||||
password: manhuoda@2023
|
||||
#线上正式环境
|
||||
|
||||
Reference in New Issue
Block a user