Compare commits
143
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
568ce3f96d | ||
|
|
0ee27d796f | ||
|
|
7842ceaf71 | ||
|
|
987a7c564d | ||
|
|
18c8c4d18d | ||
|
|
0f4da97358 | ||
|
|
2787f7651e | ||
|
|
b9fe4bc4d2 | ||
|
|
7a6c570a88 | ||
|
|
f1567eb81e | ||
|
|
885d38565c | ||
|
|
476d7c8b0e | ||
|
|
93dd653ca9 | ||
|
|
f84c7b0843 | ||
|
|
3feb3851e4 | ||
|
|
38a04d6d30 | ||
|
|
c58112a719 | ||
|
|
a4a29c7c8e | ||
|
|
9283cc9df8 | ||
|
|
076c915a4c | ||
|
|
55c958bde5 | ||
|
|
c5babe103e | ||
|
|
287ae8f22b | ||
|
|
1779bc2b23 | ||
|
|
2a56ce433f | ||
|
|
2dd8e7f0a2 | ||
|
|
b8605c6b43 | ||
|
|
5fec54ac63 | ||
|
|
564b8ff8aa | ||
|
|
76a5c987b2 | ||
|
|
f6ee1a3eee | ||
|
|
1297f920be | ||
|
|
d4ba4f0c0b | ||
|
|
0ed45fee69 | ||
|
|
69412f7293 | ||
|
|
2bd4d5bb63 | ||
|
|
8b9b29dbf1 | ||
|
|
5890660fe4 | ||
|
|
fa6ccad965 | ||
|
|
e12beb1e0c | ||
|
|
8c722deac6 | ||
|
|
a1494846db | ||
|
|
0d70450997 | ||
|
|
6c6649368c | ||
|
|
92d53ad90d | ||
|
|
8b9cd8c749 | ||
|
|
c200645a15 | ||
|
|
674f56b2c2 | ||
|
|
44e7581b2c | ||
|
|
01b2723e1f | ||
|
|
489515f865 | ||
|
|
d8aa1e9490 | ||
|
|
07d9dacded | ||
|
|
538a3b42bd | ||
|
|
55dfb6f4a1 | ||
|
|
1f84ad71d8 | ||
|
|
4d0eb901c9 | ||
|
|
23984e69d6 | ||
|
|
a1f4953fb5 | ||
|
|
25ed516000 | ||
|
|
9f2e8f1855 | ||
|
|
1488405397 | ||
|
|
ad55d49d6b | ||
|
|
7aa7576799 | ||
|
|
96c95dabc6 | ||
|
|
f3fc2b3093 | ||
|
|
a112aa1163 | ||
|
|
57cce338b1 | ||
|
|
33a6e875ce | ||
|
|
cdc098fdd3 | ||
|
|
e544b76db6 | ||
|
|
4f727fadc1 | ||
|
|
5b98ae9435 | ||
|
|
82909efe6b | ||
|
|
d268718f9b | ||
|
|
895c8d6a4b | ||
|
|
914a751d96 | ||
|
|
fc16c1edf2 | ||
|
|
4bd655e4da | ||
|
|
a96b03a060 | ||
|
|
8681042a32 | ||
|
|
44c9953875 | ||
|
|
c48b8aa39a | ||
|
|
36b31e5d52 | ||
|
|
f5c096fe39 | ||
|
|
75e77c0476 | ||
|
|
709b151e3f | ||
|
|
fa731e1fa5 | ||
|
|
d1448b2746 | ||
|
|
32d38b7721 | ||
|
|
ebc7bee5be | ||
|
|
19ca4bbe6c | ||
|
|
2f6988abac | ||
|
|
e322e28d05 | ||
|
|
9f70b236a0 | ||
|
|
7dcedab498 | ||
|
|
e2f5896be2 | ||
|
|
effa681709 | ||
|
|
8ea6a82acd | ||
|
|
e7f2a79dee | ||
|
|
8a78122fcb | ||
|
|
49b3722328 | ||
|
|
cb96a3700d | ||
|
|
9250d03ab1 | ||
|
|
494f49ee1b | ||
|
|
be597775d9 | ||
|
|
9eff15e483 | ||
|
|
496548558b | ||
|
|
7bd2e0b87c | ||
|
|
266d416912 | ||
|
|
f2216adb06 | ||
|
|
b825f1a789 | ||
|
|
6177b70b34 | ||
|
|
30dd4abe43 | ||
|
|
5dd23e9f42 | ||
|
|
f91a2248af | ||
|
|
b4db0a8cdb | ||
|
|
65fd1e6a19 | ||
|
|
bab7f048eb | ||
|
|
f543c4a00f | ||
|
|
98004ba989 | ||
|
|
76c8b1f5aa | ||
|
|
8542a25238 | ||
|
|
22590abbb8 | ||
|
|
bb68e118fa | ||
|
|
1d28170d46 | ||
|
|
1b85098063 | ||
|
|
d6d9ee1d5e | ||
|
|
2d9a4eaad2 | ||
|
|
1423d5d140 | ||
|
|
80e1639b83 | ||
|
|
07862301e6 | ||
|
|
d6fae412cd | ||
|
|
7ee70dd06c | ||
|
|
6f33fc3b64 | ||
|
|
a9e3d6cb6b | ||
|
|
5fe5ce7e82 | ||
|
|
5cc987c2c4 | ||
|
|
9ed1797b59 | ||
|
|
2373be59e6 | ||
|
|
587550025d | ||
|
|
9dfcf4ef5a | ||
|
|
914957e683 |
@@ -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) {
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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"
|
||||
|
||||
+4
@@ -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"},
|
||||
|
||||
+6
@@ -14,6 +14,12 @@ import lombok.NoArgsConstructor;
|
||||
@ApiModel("月台监测-作业车辆")
|
||||
public class PlatformVehicleItemVO {
|
||||
|
||||
@ApiModelProperty("预约申请时间")
|
||||
private String appointmentTime;
|
||||
|
||||
@ApiModelProperty("作业楼层")
|
||||
private String workFloor;
|
||||
|
||||
@ApiModelProperty("车牌号码")
|
||||
private String plateNumber;
|
||||
|
||||
|
||||
@@ -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
|
||||
# 线上测试环境配置 容器名+端口号
|
||||
|
||||
@@ -13,24 +13,24 @@ spring:
|
||||
cloud:
|
||||
nacos:
|
||||
discovery:
|
||||
# server-addr: 127.0.0.1:8848
|
||||
server-addr: 127.0.0.1:8848
|
||||
# 线上测试环境配置 容器名+端口号
|
||||
# server-addr: 10.102.192.31:6848
|
||||
server-addr: 10.33.0.129:6010
|
||||
# server-addr: 10.33.0.129:6010
|
||||
#线上正式环境
|
||||
# server-addr: 127.0.0.1:8848
|
||||
# server-addr: 10.102.192.31:6848
|
||||
username: nacos
|
||||
password: manhuoda@2023
|
||||
# username: nacos
|
||||
# password: manhuoda@2023
|
||||
config:
|
||||
# server-addr: 127.0.0.1:8848
|
||||
server-addr: 127.0.0.1:8848
|
||||
# 线上测试环境配置 容器名+端口号
|
||||
server-addr: 10.33.0.129:6010
|
||||
# server-addr: 10.33.0.129:6010
|
||||
#线上正式环境
|
||||
# server-addr: 127.0.0.1:8848
|
||||
# server-addr: 10.102.192.31:6848
|
||||
username: nacos
|
||||
password: manhuoda@2023
|
||||
# username: nacos
|
||||
# password: manhuoda@2023
|
||||
group: DEFAULT_GROUP # 默认分组就是DEFAULT_GROUP,如果使用默认分组可以不配置
|
||||
file-extension: yml #默认properties
|
||||
# 共享配置
|
||||
|
||||
+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());
|
||||
|
||||
+6
@@ -98,4 +98,10 @@ public class ContractManageDetail extends BaseVOEntity{
|
||||
@ApiModelProperty("单据类型")
|
||||
private String documentType;
|
||||
|
||||
@ApiModelProperty("费用类别编码")
|
||||
private String serviceItemsCode;
|
||||
|
||||
@ApiModelProperty("费用类别名称")
|
||||
private String serviceItemsName;
|
||||
|
||||
}
|
||||
+6
@@ -97,4 +97,10 @@ public class ContractManageDetailPO extends BaseVOEntity{
|
||||
@ApiModelProperty("单据类型")
|
||||
private String documentType;
|
||||
|
||||
@ApiModelProperty("费用类别编码")
|
||||
private String serviceItemsCode;
|
||||
|
||||
@ApiModelProperty("费用类别名称")
|
||||
private String serviceItemsName;
|
||||
|
||||
}
|
||||
+6
@@ -102,4 +102,10 @@ public class ContractManageDetailDO extends BaseVOEntity{
|
||||
|
||||
@ApiModelProperty("单据类型")
|
||||
private String documentType;
|
||||
|
||||
@ApiModelProperty("费用类别编码")
|
||||
private String serviceItemsCode;
|
||||
|
||||
@ApiModelProperty("费用类别名称")
|
||||
private String serviceItemsName;
|
||||
}
|
||||
+4
-20
@@ -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<StorageSection> codelist = storageSectionService.list(new QueryWrapper<StorageSection>().lambda()
|
||||
.eq(StorageSection::getStorageCode, storageCode)
|
||||
.eq(StorageSection::getWarehouseId, warehouseId)
|
||||
.ne(StorageSection::getStorageSectionId, storageSectionDO.getStorageSectionId())
|
||||
.eq(StorageSection::getDelFlag, 1));
|
||||
List<StorageSection> namelist = storageSectionService.list(new QueryWrapper<StorageSection>().lambda()
|
||||
.eq(StorageSection::getStorageName, storageName)
|
||||
.eq(StorageSection::getWarehouseId, warehouseId)
|
||||
.ne(StorageSection::getStorageSectionId, storageSectionDO.getStorageSectionId())
|
||||
.eq(StorageSection::getDelFlag, 1));
|
||||
if ((codelist != null && codelist.size() > 0) || (namelist != null && namelist.size() > 0)) {
|
||||
throw new ServiceException("库区编码或名称已存在");
|
||||
}
|
||||
return storageSectionService.update(storageSectionDO);
|
||||
}
|
||||
|
||||
|
||||
+6
@@ -102,4 +102,10 @@ public class ContractManageDetailDTO extends BaseVOEntity{
|
||||
|
||||
@ApiModelProperty("单据类型")
|
||||
private String documentType;
|
||||
|
||||
@ApiModelProperty("费用类别编码")
|
||||
private String serviceItemsCode;
|
||||
|
||||
@ApiModelProperty("费用类别名称")
|
||||
private String serviceItemsName;
|
||||
}
|
||||
@@ -107,7 +107,10 @@
|
||||
<select id="selectCostSubject" parameterType="com.mhd.basic.domain.expenseAccount.repository.todo.ExpenseAccountDO"
|
||||
resultType="com.mhd.basic.domain.expenseAccount.repository.po.ExpenseAccountPO">
|
||||
select
|
||||
a.*
|
||||
a.* ,
|
||||
b.tax_rate,
|
||||
b.service_items_name,
|
||||
b.service_items_code
|
||||
from expense_account a left join service_items_manage b ON a.service_items_manage_id = b.service_items_manage_id
|
||||
where
|
||||
a.del_flag = 1
|
||||
@@ -118,13 +121,17 @@
|
||||
<select id="selectAllCostSubject"
|
||||
resultType="com.mhd.basic.domain.expenseAccount.repository.po.ExpenseAccountPO">
|
||||
select
|
||||
*
|
||||
from expense_account
|
||||
a.* ,
|
||||
b.tax_rate,
|
||||
b.service_items_name,
|
||||
b.service_items_code
|
||||
from expense_account a
|
||||
left join service_items_manage b ON a.service_items_manage_id = b.service_items_manage_id
|
||||
where
|
||||
del_flag = 1
|
||||
and status = 1
|
||||
and first_subject_flag = 2
|
||||
and upper_subject_code = #{subjectCode}
|
||||
a.del_flag = 1
|
||||
and a.status = 1
|
||||
and a.first_subject_flag = 2
|
||||
and a.upper_subject_code = #{subjectCode}
|
||||
</select>
|
||||
|
||||
<select id="getInfoByCode" resultType="com.mhd.basic.domain.expenseAccount.repository.po.ExpenseAccountPO" parameterType="com.mhd.basic.domain.expenseAccount.repository.todo.ExpenseAccountDO">
|
||||
@@ -141,6 +148,7 @@
|
||||
AND a.top_organization_id = #{expenseAccountDO.topOrganizationId}
|
||||
AND a.subject_code = #{expenseAccountDO.subjectCode}
|
||||
AND a.status = 1
|
||||
LIMIT 1
|
||||
</select>
|
||||
|
||||
|
||||
|
||||
+86
-7
@@ -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<AgreementDetails> listByShipperId(Long shipperId) {
|
||||
return agreementDetailsMapper.selectList(
|
||||
new LambdaQueryWrapper<AgreementDetails>()
|
||||
.eq(AgreementDetails::getShipperId, shipperId)
|
||||
.orderByDesc(AgreementDetails::getCreateTime)
|
||||
);
|
||||
public List<AgreementDetailsPo> 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<AgreementDetailsPo> result = new ArrayList<>();
|
||||
for (int i = 0; i < agreedaydatas.size(); i++) {
|
||||
JSONObject item = agreedaydatas.getJSONObject(i);
|
||||
AgreementDetailsPo po = new AgreementDetailsPo();
|
||||
po.setCode(item.getString("code"));
|
||||
po.setOrgcode(item.getString("orgcode"));
|
||||
po.setPtypename(item.getString("ptypename"));
|
||||
po.setPtype(item.getString("ptype"));
|
||||
po.setPcode(item.getString("pcode"));
|
||||
po.setPname(item.getString("pname"));
|
||||
po.setPday(item.getString("pday"));
|
||||
result.add(po);
|
||||
}
|
||||
|
||||
log.info("查询协议明细成功,shipperId={},organizationId={},共{}条", shipperId, organizationId, result.size());
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+251
@@ -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<String> errors = new java.util.ArrayList<>();
|
||||
LoginUser loginUser = SecurityUtils.getLoginUser();
|
||||
if (loginUser == null || loginUser.getUserPo() == null) {
|
||||
return com.mhd.common.core.web.domain.AjaxResult.error("登录信息失效");
|
||||
}
|
||||
Long currentOrgId = loginUser.getUserPo().getOrganizationId();
|
||||
String currentOrgName = loginUser.getUserPo().getOrganizationName();
|
||||
for (int i = 1; i <= sheet.getLastRowNum(); i++) {
|
||||
org.apache.poi.ss.usermodel.Row row = sheet.getRow(i);
|
||||
if (row == null) continue;
|
||||
String userAccount = getCellStr(row.getCell(0));
|
||||
String companyName = getCellStr(row.getCell(1));
|
||||
if (org.springframework.util.StringUtils.isEmpty(companyName)) continue;
|
||||
total++;
|
||||
try {
|
||||
String contactName = getCellStr(row.getCell(2));
|
||||
String contactPhone = getCellStr(row.getCell(3));
|
||||
String address = getCellStr(row.getCell(4));
|
||||
String detailedAddress = getCellStr(row.getCell(5));
|
||||
String remark = getCellStr(row.getCell(6));
|
||||
String settlementCurrency = getCellStr(row.getCell(7));
|
||||
String ncCustomerCode = getCellStr(row.getCell(8));
|
||||
|
||||
// 先按公司名称查是否已存在委托方
|
||||
UserShipperEntity existingShipper = findFirstByShipperEnterpriseNameAcrossOrgs(companyName);
|
||||
if (existingShipper != null && existingShipper.getShipperId() != null) {
|
||||
// 已存在:按模板更新指定字段
|
||||
updateShipperFromExcel(existingShipper, userAccount, companyName,
|
||||
contactName, contactPhone, address, detailedAddress,
|
||||
remark, settlementCurrency, ncCustomerCode, loginUser, currentOrgId);
|
||||
success++;
|
||||
} else {
|
||||
UserShipperDO shipperDO = new UserShipperDO();
|
||||
shipperDO.setShipperType(2);
|
||||
shipperDO.setDataSource(2);
|
||||
shipperDO.setUserAccount(userAccount);
|
||||
shipperDO.setShipperEnterpriseName(companyName);
|
||||
// NC客户编码使用模板中的独立字段,不再复用登录账号
|
||||
shipperDO.setCustomerNcCode(ncCustomerCode);
|
||||
// 联系人 -> user表 user_name + user_shipper表 user_name_shipper
|
||||
shipperDO.setUserName(contactName);
|
||||
shipperDO.setUserNameShipper(contactName);
|
||||
// 联系电话 -> user表 user_phone
|
||||
shipperDO.setUserPhone(contactPhone);
|
||||
// 地址 -> user表 user_area_name,详细地址 -> user表 user_area_address
|
||||
shipperDO.setUserAreaName(address);
|
||||
shipperDO.setUserAreaAddress(detailedAddress);
|
||||
shipperDO.setRemark(remark);
|
||||
shipperDO.setSettlementCurrency(settlementCurrency);
|
||||
// 新导入账号默认密码 Aa123456(按前端加密约定先 AES 加密)
|
||||
shipperDO.setUserPassword(AESUtil.encrypt("Aa123456"));
|
||||
// 初始化 orgCode:记录当前组织信息和NC客户编码
|
||||
com.alibaba.fastjson.JSONArray orgCodeArray = new com.alibaba.fastjson.JSONArray();
|
||||
com.alibaba.fastjson.JSONObject orgItem = new com.alibaba.fastjson.JSONObject();
|
||||
orgItem.put("name", currentOrgName);
|
||||
orgItem.put("code", currentOrgId);
|
||||
orgItem.put("ncCustomer", ncCustomerCode);
|
||||
orgItem.put("names", currentOrgId);
|
||||
orgCodeArray.add(orgItem);
|
||||
shipperDO.setOrgCode(orgCodeArray.toJSONString());
|
||||
Map<String, Object> addResult = addShipper(shipperDO);
|
||||
Object newUserIdObj = addResult.get("userId");
|
||||
if (newUserIdObj instanceof Long) {
|
||||
assignCompanyRoleIfMissing((Long) newUserIdObj, currentOrgId);
|
||||
}
|
||||
success++;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
failed++;
|
||||
errors.add("第" + (i + 1) + "行[" + companyName + "]导入失败:" + e.getMessage());
|
||||
log.error("导入委托方第{}行失败", i + 1, e);
|
||||
}
|
||||
}
|
||||
workbook.close();
|
||||
java.util.Map<String, Object> result = new java.util.HashMap<>();
|
||||
result.put("total", total);
|
||||
result.put("success", success);
|
||||
result.put("failed", failed);
|
||||
result.put("errorMessages", errors);
|
||||
return com.mhd.common.core.web.domain.AjaxResult.success("导入完成", result);
|
||||
} catch (Exception e) {
|
||||
log.error("解析Excel失败", e);
|
||||
return com.mhd.common.core.web.domain.AjaxResult.error("解析Excel失败:" + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 导入时若账号没有任何角色,则补分配企业货主角色
|
||||
*/
|
||||
private void assignCompanyRoleIfMissing(Long userId, Long organizationId) {
|
||||
if (userId == null || organizationId == null) {
|
||||
return;
|
||||
}
|
||||
List<UserRoleMenuPO> existingRoles = userRoleDomainService.selectRolesByUserId(userId);
|
||||
if (CollUtil.isNotEmpty(existingRoles)) {
|
||||
return;
|
||||
}
|
||||
// 按 role_code + organization_id 精确匹配角色(selectByOrganizationIdAndRoleCode 的 common_where 不含 roleCode 过滤,不适用)
|
||||
RolePO rolePO = roleDomainService.selectByRoleCodeAndOrganizationId(RoleEnum.COMPANY.getCode(), organizationId);
|
||||
if (rolePO == null) {
|
||||
log.warn("组织{}下未找到{}角色,无法为导入用户{}分配角色", organizationId, RoleEnum.COMPANY.getCode(), userId);
|
||||
return;
|
||||
}
|
||||
// 1. 写入 user_role 表
|
||||
UserRoleDo userRoleDo = new UserRoleDo();
|
||||
userRoleDo.setUserId(userId);
|
||||
userRoleDo.setRoleId(rolePO.getRoleId());
|
||||
userRoleDomainService.addUserRole(userRoleDo);
|
||||
// 2. 同步更新 user 表的 role_code / role_name
|
||||
UserDO userDO = new UserDO();
|
||||
userDO.setUserId(userId);
|
||||
userDO.setRoleCode(RoleEnum.COMPANY.getCode());
|
||||
userDO.setRoleName(RoleEnum.COMPANY.getName());
|
||||
userDomainService.updateUser(userDO);
|
||||
}
|
||||
|
||||
/**
|
||||
* 按Excel模板更新已存在的委托方(只更新模板中的字段)
|
||||
*/
|
||||
private void updateShipperFromExcel(UserShipperEntity existingShipper, String userAccount,
|
||||
String companyName, String contactName, String contactPhone,
|
||||
String address, String detailedAddress, String remark,
|
||||
String settlementCurrency, String ncCustomerCode,
|
||||
LoginUser loginUser, Long currentOrgId) {
|
||||
Long userId = existingShipper.getUserId();
|
||||
// 从 user 主表读取当前登录账号(user_shipper 表无 user_account 字段)
|
||||
UserPo existingUser = null;
|
||||
String existingUserAccount = null;
|
||||
if (userId != null) {
|
||||
existingUser = userDomainService.selectByUserId(userId);
|
||||
if (existingUser != null) {
|
||||
existingUserAccount = existingUser.getUserAccount();
|
||||
}
|
||||
}
|
||||
if (StringUtils.isBlank(existingUserAccount) && StringUtils.isBlank(userAccount)) {
|
||||
throw new ServiceException("登录账号不能为空");
|
||||
}
|
||||
// 登录账号变更时校验唯一性
|
||||
if (StringUtils.isNotBlank(userAccount) && !userAccount.equals(existingUserAccount)) {
|
||||
UserDO checkDO = new UserDO();
|
||||
checkDO.setUserAccount(userAccount);
|
||||
checkDO.setTopOrganizationId(existingShipper.getTopOrganizationId());
|
||||
UserPo existedUser = userDomainService.findByTopOrganizationIdAndUserAccount(checkDO);
|
||||
if (existedUser != null && !existedUser.getUserId().equals(userId)) {
|
||||
throw new ServiceException("登录账号已存在:" + userAccount);
|
||||
}
|
||||
}
|
||||
Date now = new Date();
|
||||
Long updateBy = loginUser.getUserPo().getUserId();
|
||||
String updateByName = loginUser.getUserPo().getUserName();
|
||||
|
||||
// 1. 更新 user_shipper 表指定字段
|
||||
// 注意:user_shipper 表没有 user_account 字段,登录账号在 user 主表维护
|
||||
UserShipperEntity shipperUpdate = new UserShipperEntity();
|
||||
shipperUpdate.setShipperId(existingShipper.getShipperId());
|
||||
shipperUpdate.setShipperEnterpriseName(companyName);
|
||||
shipperUpdate.setUserNameShipper(contactName);
|
||||
shipperUpdate.setUserAreaName(address);
|
||||
shipperUpdate.setUserAreaAddress(detailedAddress);
|
||||
shipperUpdate.setRemark(remark);
|
||||
shipperUpdate.setSettlementCurrency(settlementCurrency);
|
||||
shipperUpdate.setCustomerNcCode(ncCustomerCode);
|
||||
shipperUpdate.setUpdateBy(updateBy);
|
||||
shipperUpdate.setUpdateByName(updateByName);
|
||||
shipperUpdate.setUpdateTime(now);
|
||||
userShipperMapper.updateById(shipperUpdate);
|
||||
|
||||
// 2. 同步更新 user 表指定字段
|
||||
if (userId != null) {
|
||||
UserDO userDO = new UserDO();
|
||||
userDO.setUserId(userId);
|
||||
if (StringUtils.isNotBlank(userAccount)) {
|
||||
userDO.setUserAccount(userAccount);
|
||||
}
|
||||
userDO.setUserName(contactName);
|
||||
userDO.setUserPhone(contactPhone);
|
||||
userDO.setUserAreaName(address);
|
||||
userDO.setUserAreaAddress(detailedAddress);
|
||||
userDO.setUpdateBy(updateBy);
|
||||
userDO.setUpdateByName(updateByName);
|
||||
userDO.setUpdateTime(now);
|
||||
// 如果现有账号没有密码,设置默认密码 Aa123456(与 addUserInfoShipper 一致的加密流程)
|
||||
if (existingUser != null && StringUtils.isBlank(existingUser.getUserPassword())) {
|
||||
String finalAccount = StringUtils.isNotBlank(userAccount) ? userAccount : existingUser.getUserAccount();
|
||||
String salt = OConvertUtils.randomGen(8);
|
||||
String passwordEncode = PasswordUtil.encrypt(finalAccount, "Aa123456", salt);
|
||||
userDO.setUserPassword(passwordEncode);
|
||||
userDO.setUserSalt(salt);
|
||||
}
|
||||
userDomainService.updateUser(userDO);
|
||||
// 如果该账号没有任何角色,补分配企业货主角色,避免登录报“账号未授权角色信息”
|
||||
assignCompanyRoleIfMissing(userId, existingShipper.getOrganizationId());
|
||||
}
|
||||
|
||||
// 3. 更新 orgCode 中当前组织的 ncCustomer
|
||||
String existingOrgCode = existingShipper.getOrgCode();
|
||||
com.alibaba.fastjson.JSONArray orgCodeArray = new com.alibaba.fastjson.JSONArray();
|
||||
boolean hasOrg = false;
|
||||
if (StringUtils.isNotEmpty(existingOrgCode)) {
|
||||
try {
|
||||
orgCodeArray = com.alibaba.fastjson.JSONArray.parseArray(existingOrgCode);
|
||||
for (int i = 0; i < orgCodeArray.size(); i++) {
|
||||
com.alibaba.fastjson.JSONObject orgItem = orgCodeArray.getJSONObject(i);
|
||||
if (currentOrgId != null && currentOrgId.equals(orgItem.getLong("code"))) {
|
||||
orgItem.put("ncCustomer", ncCustomerCode);
|
||||
hasOrg = true;
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error("解析orgCode失败,shipperId={}", existingShipper.getShipperId(), e);
|
||||
}
|
||||
}
|
||||
if (!hasOrg) {
|
||||
com.alibaba.fastjson.JSONObject newOrgItem = new com.alibaba.fastjson.JSONObject();
|
||||
newOrgItem.put("name", loginUser.getUserPo().getOrganizationName());
|
||||
newOrgItem.put("code", currentOrgId);
|
||||
newOrgItem.put("ncCustomer", ncCustomerCode);
|
||||
newOrgItem.put("names", currentOrgId);
|
||||
orgCodeArray.add(newOrgItem);
|
||||
}
|
||||
UserShipperEntity orgCodeUpdate = new UserShipperEntity();
|
||||
orgCodeUpdate.setShipperId(existingShipper.getShipperId());
|
||||
orgCodeUpdate.setOrgCode(orgCodeArray.toJSONString());
|
||||
orgCodeUpdate.setUpdateBy(updateBy);
|
||||
orgCodeUpdate.setUpdateByName(updateByName);
|
||||
orgCodeUpdate.setUpdateTime(now);
|
||||
userShipperMapper.updateById(orgCodeUpdate);
|
||||
}
|
||||
|
||||
private String getCellStr(org.apache.poi.ss.usermodel.Cell cell) {
|
||||
if (cell == null) return null;
|
||||
cell.setCellType(org.apache.poi.ss.usermodel.CellType.STRING);
|
||||
String v = cell.getStringCellValue();
|
||||
return v == null ? null : v.trim();
|
||||
}
|
||||
|
||||
/**
|
||||
* 个人货主认证
|
||||
*
|
||||
|
||||
+32
@@ -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;
|
||||
}
|
||||
+6
@@ -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;
|
||||
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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,如果使用默认分组可以不配置
|
||||
|
||||
@@ -75,7 +75,9 @@
|
||||
AND b.del_flag = 1
|
||||
</sql>
|
||||
<sql id="selectShipperVo1">
|
||||
SELECT b.shipper_id,
|
||||
SELECT b.area,
|
||||
b.detail_address,
|
||||
b.shipper_id,
|
||||
a.user_id,
|
||||
b.parent_shipper_id,
|
||||
b.shipper_type,
|
||||
|
||||
+257
-82
@@ -7,6 +7,7 @@ import com.mhd.bms.application.server.receiptManage.ReceiptManageApplicationServ
|
||||
import com.mhd.bms.domain.billManage.entity.BillDetail;
|
||||
import com.mhd.bms.domain.billManage.entity.BillManage;
|
||||
import com.mhd.bms.domain.billManage.repository.facade.IBillDetailService;
|
||||
import com.mhd.bms.domain.billManage.repository.facade.IBillManageService;
|
||||
import com.mhd.bms.domain.billManage.repository.mapper.BillDetailMapper;
|
||||
import com.mhd.bms.domain.billManage.repository.po.BillDetailPO;
|
||||
import com.mhd.bms.domain.billManage.repository.po.BillManagePO;
|
||||
@@ -18,6 +19,7 @@ import com.mhd.bms.domain.billOperationLog.repository.todo.BillOperationLogDO;
|
||||
import com.mhd.bms.domain.billOperationLog.service.BillOperationLogDomainService;
|
||||
import com.mhd.bms.domain.billingStatement.entity.BillingStatement;
|
||||
import com.mhd.bms.domain.billingStatement.repository.po.BillingStatementPO;
|
||||
import com.mhd.bms.domain.billingStatement.repository.todo.BillingStatementDO;
|
||||
import com.mhd.bms.domain.billingStatement.service.BillingStatementDomainService;
|
||||
import com.mhd.bms.domain.ncLog.entity.NcLog;
|
||||
import com.mhd.bms.domain.ncLog.repository.mapper.NcLogMapper;
|
||||
@@ -77,6 +79,8 @@ public class BillManageApplicationService {
|
||||
private BillDetailMapper billDetailMapper;
|
||||
@Autowired
|
||||
private NcLogMapper ncLogMapper;
|
||||
@Autowired
|
||||
private IBillManageService billManageService;
|
||||
|
||||
|
||||
/**
|
||||
@@ -132,8 +136,12 @@ public class BillManageApplicationService {
|
||||
List<BillManagePO> billManagePOS = billManageDomainService.queryList(billManageDO);
|
||||
for (BillManagePO billManagePO : billManagePOS) {
|
||||
String billNumber = billManagePO.getBillNumber(); // 获取账单编号
|
||||
// 原有 - 前端列表用,不变
|
||||
List<BillDetail> billDetails = billDetailMapper.selectList(new LambdaQueryWrapper<BillDetail>().eq(BillDetail::getBillNumber, billNumber));
|
||||
billManagePO.setBillDetailList(billDetails);
|
||||
// 新增 - 导出用,LEFT JOIN billing_statement 拿到费用科目
|
||||
List<BillDetailPO> billDetailPOs = billDetailMapper.getDetailsByBillManageId(billManagePO.getBillManageId());
|
||||
billManagePO.setBillDetailPOList(billDetailPOs);
|
||||
}
|
||||
return billManagePOS;
|
||||
}
|
||||
@@ -333,7 +341,10 @@ public class BillManageApplicationService {
|
||||
BigDecimal billingDiscountAmount = billDetailDTOList.stream().map(BillDetailDTO::getBillingDiscountAmount).reduce(BigDecimal.ZERO, BigDecimal::add);
|
||||
//比较传来的账单总额、账单金额、账单优惠金额与计算的是否一致,不一致则报错
|
||||
if(billingTotalAmount.compareTo(billManageDTO.getBillTotalAmount())!=0 || billingAmount.compareTo(billManageDTO.getBillAmount())!=0 || billingDiscountAmount.compareTo(billManageDTO.getBillDiscountAmount())!=0){
|
||||
throw new ServiceException("账单金额不一致,调整失败,请重试");
|
||||
// 金额不一致时,用明细累加值覆盖前端传值,不再抛异常
|
||||
billManageDTO.setBillTotalAmount(billingTotalAmount);
|
||||
billManageDTO.setBillAmount(billingAmount);
|
||||
billManageDTO.setBillDiscountAmount(billingDiscountAmount);
|
||||
}
|
||||
//将集合中没有计费流水id的过滤到另一个集合,将添加费用的集合保存到计费流水并返回计费流水id
|
||||
List<BillDetailDTO> billDetailDTOListNoBillingStatementId = billDetailDTOList.stream().filter(billDetailDTO -> billDetailDTO.getBillingStatementId()==null).collect(Collectors.toList());
|
||||
@@ -356,6 +367,19 @@ public class BillManageApplicationService {
|
||||
billDetailDTO1.setFeeType(billDetailDTO1.getServiceItemsName());
|
||||
});
|
||||
}
|
||||
//同步更新已有计费流水(调整账单时可修改已有费用)
|
||||
List<BillDetailDTO> billDetailDTOListHasBillingStatementId = billDetailDTOList.stream()
|
||||
.filter(billDetailDTO -> billDetailDTO.getBillingStatementId() != null)
|
||||
.collect(Collectors.toList());
|
||||
for (BillDetailDTO billDetailDTO : billDetailDTOListHasBillingStatementId) {
|
||||
BillingStatementDO billingStatementDO = new BillingStatementDO();
|
||||
BeanUtils.copyProperties(billDetailDTO, billingStatementDO);
|
||||
billingStatementDO.setBillingStatementId(billDetailDTO.getBillingStatementId());
|
||||
billingStatementDO.setBillManageId(billManagePO.getBillManageId());
|
||||
billingStatementDO.setBillingState(3);
|
||||
billingStatementDO.setAccountExpenseType(billDetailDTO.getBillType());
|
||||
billingStatementApplicationService.update(billingStatementDO);
|
||||
}
|
||||
//保存账单明细
|
||||
Boolean flag = billDetailDomainService.saveBatch(billDetailDTOList);
|
||||
//更新账单金额
|
||||
@@ -369,7 +393,10 @@ public class BillManageApplicationService {
|
||||
billManageDO.setTailCalculationCode(billManageDTO.getTailCalculationCode());
|
||||
billManageDO.setAmountAccuracyCode(billManageDTO.getAmountAccuracyCode());
|
||||
billManageDO.setBillDiscount(billManageDTO.getBillDiscount());
|
||||
billManageDO.setBillRemark(billManageDTO.getBillRemark());
|
||||
billManageDO.setBillDiscountLimit(billManageDTO.getBillDiscountLimit());
|
||||
billManageDO.setCycleBeginTime(billManageDTO.getCycleBeginTime());
|
||||
billManageDO.setCycleEndTime(billManageDTO.getCycleEndTime());
|
||||
billManageDO.setCreateTime(billManageDTO.getCreateTime());
|
||||
billManageDO.setUpdateTime(new Date());
|
||||
billManageDO.setUpdateBy(loginUser.getUserid());
|
||||
@@ -386,105 +413,183 @@ public class BillManageApplicationService {
|
||||
}
|
||||
|
||||
/**
|
||||
* 复制账单
|
||||
* 新增账单
|
||||
*/
|
||||
@Transactional
|
||||
public Boolean copyBill(BillManageDTO billManageDTO) {
|
||||
public Boolean addBill(BillManageDTO billManageDTO) {
|
||||
LoginUser loginUser = SecurityUtils.getLoginUser();
|
||||
if (ObjectUtil.isNull(loginUser)) {
|
||||
throw new DigitalLogisticsException(UserError.TIMEOUT);
|
||||
}
|
||||
if (billManageDTO.getBillDetailDTOList() == null || billManageDTO.getBillDetailDTOList().size() == 0) {
|
||||
throw new ServiceException("账单明细不能为空");
|
||||
}
|
||||
List<BillDetailDTO> billDetailDTOList = billManageDTO.getBillDetailDTOList();
|
||||
//计算集合中所有账单总额、账单金额、账单优惠金额
|
||||
BigDecimal billingTotalAmount = billDetailDTOList.stream().map(BillDetailDTO::getBillingTotalAmount).reduce(BigDecimal.ZERO, BigDecimal::add);
|
||||
BigDecimal billingAmount = billDetailDTOList.stream().map(BillDetailDTO::getBillingAmount).reduce(BigDecimal.ZERO, BigDecimal::add);
|
||||
BigDecimal billingDiscountAmount = billDetailDTOList.stream().map(BillDetailDTO::getBillingDiscountAmount).reduce(BigDecimal.ZERO, BigDecimal::add);
|
||||
//生成账单编号
|
||||
String billNumber = OrderSequence.getOrderCode("ZD");
|
||||
//创建账单主记录
|
||||
BillManageDO billManageDO = new BillManageDO();
|
||||
BeanUtils.copyProperties(billManageDTO, billManageDO);
|
||||
billManageDO.setBillNumber(billNumber);
|
||||
billManageDO.setTopOrganizationId(loginUser.getUserPo().getTopOrganizationId());
|
||||
billManageDO.setOrganizationId(loginUser.getUserPo().getOrganizationId());
|
||||
billManageDO.setOrganizationName(loginUser.getUserPo().getOrganizationName());
|
||||
billManageDO.setBillAmount(billingAmount);
|
||||
billManageDO.setBillAmountUnsettled(billingAmount);
|
||||
billManageDO.setBillAmountSettlement(BigDecimal.ZERO);
|
||||
billManageDO.setBillDiscountAmount(billingDiscountAmount);
|
||||
billManageDO.setBillTotalAmount(billingTotalAmount);
|
||||
billManageDO.setBillState(1);
|
||||
billManageDO.setBillStep(1);
|
||||
billManageDO.setReconciliationStatus(1);
|
||||
billManageDO.setCreateTime(new Date());
|
||||
billManageDO.setCreateBy(loginUser.getUserid());
|
||||
billManageDO.setSalesmanId(String.valueOf(loginUser.getUserid()));
|
||||
billManageDO.setCreateByName(loginUser.getUserPo().getUserName());
|
||||
billManageDO.setUpdateTime(new Date());
|
||||
billManageDO.setUpdateBy(loginUser.getUserid());
|
||||
billManageDO.setUpdateByName(loginUser.getUserPo().getUserName());
|
||||
billManageDomainService.handlData(billManageDO);
|
||||
Boolean flag = billManageDomainService.insert(billManageDO);
|
||||
if (!flag) {
|
||||
throw new ServiceException("新增账单失败");
|
||||
}
|
||||
// insert后按账单编号重新查一次拿自增ID
|
||||
List<BillManage> insertedList = billManageDomainService.queryListLambda(
|
||||
new LambdaQueryWrapper<BillManage>().eq(BillManage::getBillNumber, billNumber));
|
||||
if (insertedList != null && !insertedList.isEmpty()) {
|
||||
billManageDO.setBillManageId(insertedList.get(0).getBillManageId());
|
||||
}
|
||||
//将集合中没有计费流水id的过滤到另一个集合,将添加费用的集合保存到计费流水并返回计费流水id
|
||||
List<BillDetailDTO> billDetailDTOListNoBillingStatementId = billDetailDTOList.stream().filter(item -> item.getBillingStatementId() == null).collect(Collectors.toList());
|
||||
//遍历集合并保存流水
|
||||
for (BillDetailDTO billDetailDTO : billDetailDTOListNoBillingStatementId) {
|
||||
BillingStatementDTO billingStatementDTO = new BillingStatementDTO();
|
||||
BeanUtils.copyProperties(billDetailDTO, billingStatementDTO);
|
||||
|
||||
String firstSubjectCode = billDetailDTO.getFirstSubjectCode();
|
||||
Double taxRate = billDetailMapper.getTaxRate(firstSubjectCode);
|
||||
BigDecimal amount = billingStatementDTO.getBillingAmount();
|
||||
BigDecimal taxAmount = amount.divide(BigDecimal.ONE.add(new BigDecimal(taxRate).divide(BigDecimal.valueOf(100))),10, BigDecimal.ROUND_HALF_UP).multiply(new BigDecimal(taxRate).divide(BigDecimal.valueOf(100))).setScale(2, BigDecimal.ROUND_HALF_UP);
|
||||
BigDecimal taxFreeFee = amount.subtract(taxAmount);
|
||||
billingStatementDTO.setTaxAmount(taxAmount);
|
||||
billingStatementDTO.setTaxFreeFee(taxFreeFee);
|
||||
billingStatementDTO.setTaxRate(taxRate);
|
||||
billingStatementDTO.setBillingAmount(amount);
|
||||
billingStatementDTO.setAccountExpenseType(billDetailDTO.getBillType());
|
||||
billingStatementDTO.setBillManageId(billManageDO.getBillManageId());
|
||||
billingStatementDTO.setBillingState(3);
|
||||
Long billingStatementId = billingStatementApplicationService.insertAndReturnId(billingStatementDTO);
|
||||
//遍历billDetailDTOList集合,将计费流水号相同的,赋值计费流水id
|
||||
billDetailDTOList.stream().filter(item -> item.getBillingFlow().equals(billDetailDTO.getBillingFlow())).forEach(item -> {
|
||||
item.setBillingStatementId(billingStatementId);
|
||||
item.setBillType(billManageDTO.getBillType());
|
||||
item.setBillManageId(billManageDO.getBillManageId());
|
||||
item.setBillNumber(billNumber);
|
||||
item.setInvoiceItem(item.getFirstSubjectCode());
|
||||
item.setInvoiceItemName(item.getFirstSubjectName());
|
||||
item.setFeeType(item.getServiceItemsName());
|
||||
});
|
||||
}
|
||||
//同步更新已有计费流水(新增账单时可修改已有费用)
|
||||
List<BillDetailDTO> billDetailDTOListHasBillingStatementId = billDetailDTOList.stream()
|
||||
.filter(item -> item.getBillingStatementId() != null)
|
||||
.collect(Collectors.toList());
|
||||
for (BillDetailDTO billDetailDTO : billDetailDTOListHasBillingStatementId) {
|
||||
BillingStatementDO billingStatementDO = new BillingStatementDO();
|
||||
BeanUtils.copyProperties(billDetailDTO, billingStatementDO);
|
||||
billingStatementDO.setBillingStatementId(billDetailDTO.getBillingStatementId());
|
||||
billingStatementDO.setBillManageId(billManageDO.getBillManageId());
|
||||
billingStatementDO.setBillingState(3);
|
||||
billingStatementDO.setAccountExpenseType(billDetailDTO.getBillType());
|
||||
billingStatementApplicationService.update(billingStatementDO);
|
||||
}
|
||||
//保存账单明细
|
||||
double allTaxRate = 0.0d;
|
||||
BigDecimal allTaxAmount = BigDecimal.ZERO;
|
||||
BigDecimal allTaxFreeFee = BigDecimal.ZERO;
|
||||
for (BillDetailDTO item : billDetailDTOList) {
|
||||
String firstSubjectCode = item.getFirstSubjectCode();
|
||||
Double taxRate = billDetailMapper.getTaxRate(firstSubjectCode);
|
||||
BigDecimal amount = item.getBillingAmount();
|
||||
BigDecimal taxAmount = amount.divide(BigDecimal.ONE.add(new BigDecimal(taxRate).divide(BigDecimal.valueOf(100))),10, BigDecimal.ROUND_HALF_UP).multiply(new BigDecimal(taxRate).divide(BigDecimal.valueOf(100))).setScale(2, BigDecimal.ROUND_HALF_UP);
|
||||
BigDecimal taxFreeFee = amount.subtract(taxAmount);
|
||||
item.setTaxAmount(taxAmount);
|
||||
item.setTaxFreeFee(taxFreeFee);
|
||||
item.setTaxRate(taxRate);
|
||||
allTaxRate += taxRate;
|
||||
allTaxAmount = allTaxAmount.add(taxAmount);
|
||||
allTaxFreeFee = allTaxFreeFee.add(taxFreeFee);
|
||||
}
|
||||
|
||||
BillManage billManage = billManageService.getById(billManageDO.getBillManageId());
|
||||
if (billManage != null) {
|
||||
billManage.setTaxRate(allTaxRate);
|
||||
billManage.setTaxAmount(allTaxAmount);
|
||||
billManage.setTaxFreeFee(allTaxFreeFee);
|
||||
billManage.setSalesmanId(String.valueOf(loginUser.getUserid()));
|
||||
billManageService.updateById(billManage);
|
||||
}
|
||||
Boolean flagTwo = billDetailDomainService.saveBatch(billDetailDTOList);
|
||||
//保存操作记录
|
||||
BillOperationLogDO billOperationLogDO = new BillOperationLogDO();
|
||||
billOperationLogDO.setBillManageId(billManageDO.getBillManageId());
|
||||
billOperationLogDO.setOperationInfo(StringUtils.format(BillLogsConstants.create_bill_text, billNumber, billingAmount));
|
||||
billOperationLogDO.setOperationType(1);
|
||||
boolean flagThree = billOperationLogDomainService.saveBillOperationLog(billOperationLogDO);
|
||||
return flag && flagTwo && flagThree;
|
||||
}
|
||||
|
||||
/**
|
||||
* 复制账单-获取原账单数据供前端回显
|
||||
* 前端拿到数据后跳转到类似修改/新增账单的页面,用户修改后通过addBill接口提交新增
|
||||
*/
|
||||
public BillManagePO copyBill(BillManageDTO billManageDTO) {
|
||||
if (billManageDTO.getBillManageId() == null) {
|
||||
throw new ServiceException("原账单id不能为空");
|
||||
}
|
||||
// 1. 获取原账单信息
|
||||
// 获取原账单信息
|
||||
BillManagePO originalBill = billManageDomainService.getInfo(billManageDTO.getBillManageId());
|
||||
if (null == originalBill) {
|
||||
throw new ServiceException("原账单信息未找到");
|
||||
}
|
||||
// 2. 获取原账单明细
|
||||
// 获取原账单明细
|
||||
List<BillDetailPO> 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<BillDetail> 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<BillingStatementPO> originalStatements = billingStatementDomainService.getDetailsByManageId(billManageDTO.getBillManageId());
|
||||
boolean flagThree = true;
|
||||
if (originalStatements != null && !originalStatements.isEmpty()) {
|
||||
List<BillingStatement> newStatementList = new ArrayList<>();
|
||||
for (BillingStatementPO originalStatement : originalStatements) {
|
||||
BillingStatement newStatement = new BillingStatement();
|
||||
BeanUtils.copyProperties(originalStatement, newStatement);
|
||||
newStatement.setBillingStatementId(null);
|
||||
newStatement.setBillManageId(newBill.getBillManageId());
|
||||
newStatement.setCreateBy(loginUser.getUserPo().getUserId());
|
||||
newStatement.setCreateByName(loginUser.getUserPo().getUserName());
|
||||
newStatement.setCreateTime(new Date());
|
||||
newStatementList.add(newStatement);
|
||||
}
|
||||
flagThree = billingStatementDomainService.saveEntityBatch(newStatementList);
|
||||
}
|
||||
// 6. 保存操作日志
|
||||
BillOperationLogDO billOperationLogDO = new BillOperationLogDO();
|
||||
billOperationLogDO.setBillManageId(newBill.getBillManageId());
|
||||
billOperationLogDO.setOperationInfo(StringUtils.format(BillLogsConstants.copy_bill_text, originalBill.getBillNumber(), newBillNumber));
|
||||
billOperationLogDO.setOperationType(1);
|
||||
boolean three = billOperationLogDomainService.saveBillOperationLog(billOperationLogDO);
|
||||
return flag && flagTwo && flagThree && three;
|
||||
originalBill.setBillDetailPOList(originalDetails);
|
||||
return originalBill;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -666,6 +771,76 @@ public class BillManageApplicationService {
|
||||
return billManageDomainService.synchronousNcSK(businessDocumentDetaliIds);
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改账单明细
|
||||
*/
|
||||
@Transactional
|
||||
public Boolean updateBillDetail(BillManageDTO billManageDTO) {
|
||||
LoginUser loginUser = SecurityUtils.getLoginUser();
|
||||
if (ObjectUtil.isNull(loginUser)) {
|
||||
throw new DigitalLogisticsException(UserError.TIMEOUT);
|
||||
}
|
||||
BillDetailDTO detailDTO = billManageDTO.getBillDetailDTOList() != null && !billManageDTO.getBillDetailDTOList().isEmpty()
|
||||
? billManageDTO.getBillDetailDTOList().get(0) : null;
|
||||
if (detailDTO == null || detailDTO.getBillDetailId() == null) {
|
||||
throw new ServiceException("明细id不能为空");
|
||||
}
|
||||
BillDetailPO billDetailPO = billDetailDomainService.getInfo(detailDTO.getBillDetailId());
|
||||
if (billDetailPO == null) {
|
||||
throw new ServiceException("明细不存在");
|
||||
}
|
||||
BillManagePO billManagePO = billManageDomainService.getInfo(billDetailPO.getBillManageId());
|
||||
if (billManagePO == null || billManagePO.getBillState() != 1) {
|
||||
throw new ServiceException("账单状态不为未确认,不可修改明细");
|
||||
}
|
||||
BillDetailDO billDetailDO = new BillDetailDO();
|
||||
BeanUtils.copyProperties(detailDTO, billDetailDO);
|
||||
billDetailDO.setBillDetailId(detailDTO.getBillDetailId());
|
||||
billDetailDO.setInvoiceItem(detailDTO.getFirstSubjectCode());
|
||||
billDetailDO.setInvoiceItemName(detailDTO.getFirstSubjectName());
|
||||
billDetailDO.setFeeType(detailDTO.getServiceItemsName());
|
||||
billDetailDO.setUpdateBy(loginUser.getUserid());
|
||||
billDetailDO.setUpdateByName(loginUser.getUserPo().getUserName());
|
||||
billDetailDO.setUpdateTime(new Date());
|
||||
// 同步更新计费流水的费用科目、服务项(因为这些字段在 billing_statement 表,不在 bill_detail 表)
|
||||
if (billDetailPO.getBillingStatementId() != null) {
|
||||
BillingStatementDO billingStatementDO = new BillingStatementDO();
|
||||
billingStatementDO.setBillingStatementId(billDetailPO.getBillingStatementId());
|
||||
billingStatementDO.setFirstSubjectCode(detailDTO.getFirstSubjectCode());
|
||||
billingStatementDO.setFirstSubjectName(detailDTO.getFirstSubjectName());
|
||||
billingStatementDO.setServiceItemsCode(detailDTO.getServiceItemsCode());
|
||||
billingStatementDO.setServiceItemsName(detailDTO.getServiceItemsName());
|
||||
billingStatementDO.setUpdateBy(loginUser.getUserid());
|
||||
billingStatementDO.setUpdateByName(loginUser.getUserPo().getUserName());
|
||||
billingStatementDO.setUpdateTime(new Date());
|
||||
billingStatementApplicationService.update(billingStatementDO);
|
||||
}
|
||||
Boolean flag = billDetailDomainService.update(billDetailDO);
|
||||
// 重新计算账单总金额并更新主表
|
||||
List<BillDetailPO> allDetails = billDetailDomainService.getDetailsByBillManageId(billManagePO.getBillManageId());
|
||||
allDetails = allDetails.stream().map(item -> {
|
||||
if (item.getBillDetailId().equals(detailDTO.getBillDetailId())) {
|
||||
item.setBillingTotalAmount(detailDTO.getBillingTotalAmount());
|
||||
item.setBillingAmount(detailDTO.getBillingAmount());
|
||||
item.setBillingDiscountAmount(detailDTO.getBillingDiscountAmount());
|
||||
}
|
||||
return item;
|
||||
}).collect(Collectors.toList());
|
||||
BigDecimal totalAmount = allDetails.stream().map(BillDetailPO::getBillingTotalAmount).reduce(BigDecimal.ZERO, BigDecimal::add);
|
||||
BigDecimal amount = allDetails.stream().map(BillDetailPO::getBillingAmount).reduce(BigDecimal.ZERO, BigDecimal::add);
|
||||
BigDecimal discountAmount = allDetails.stream().map(BillDetailPO::getBillingDiscountAmount).reduce(BigDecimal.ZERO, BigDecimal::add);
|
||||
BillManageDO billManageDO = new BillManageDO();
|
||||
billManageDO.setBillManageId(billManagePO.getBillManageId());
|
||||
billManageDO.setBillTotalAmount(totalAmount);
|
||||
billManageDO.setBillAmount(amount);
|
||||
billManageDO.setBillAmountUnsettled(amount);
|
||||
billManageDO.setBillDiscountAmount(discountAmount);
|
||||
billManageDO.setUpdateBy(loginUser.getUserid());
|
||||
billManageDO.setUpdateByName(loginUser.getUserPo().getUserName());
|
||||
billManageDO.setUpdateTime(new Date());
|
||||
Boolean flagTwo = billManageDomainService.update(billManageDO);
|
||||
return flag && flagTwo;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
+5
@@ -585,6 +585,8 @@ public class BillingStatementApplicationService {
|
||||
此方法只进行实体返回,并不进行数据保存
|
||||
*/
|
||||
LoginUser loginUser = SecurityUtils.getLoginUser();
|
||||
|
||||
billingStatementDO.setAccountExpenseType(billingStatementDO.getAccountExpenseType());
|
||||
if (ObjectUtil.isNull(loginUser)) {
|
||||
throw new DigitalLogisticsException(UserError.TIMEOUT);
|
||||
}
|
||||
@@ -598,6 +600,9 @@ public class BillingStatementApplicationService {
|
||||
billingStatementPO.setTopOrganizationId(loginUser.getUserPo().getTopOrganizationId());
|
||||
billingStatementPO.setOrganizationId(loginUser.getUserPo().getOrganizationId());
|
||||
billingStatementPO.setOrganizationName(loginUser.getUserPo().getOrganizationName());
|
||||
// 默认填充当前登录人为业务员
|
||||
billingStatementPO.setSalesmanId(String.valueOf(loginUser.getUserid()));
|
||||
billingStatementPO.setSalesmanName(loginUser.getUserPo().getUserName());
|
||||
return billingStatementPO;
|
||||
}
|
||||
|
||||
|
||||
+3
-1
@@ -38,4 +38,6 @@ public interface IBillDetailService extends IService<BillDetail>
|
||||
public BillDetailPO getInfo(Long billDetailId);
|
||||
|
||||
List<BillDetailPO> getDetailsByBillManageId(Long billManageId);
|
||||
}
|
||||
|
||||
List<BillDetail> getDetailsByBillManageIdAndGroup(Long billManageId);
|
||||
}
|
||||
+6
-1
@@ -5,6 +5,7 @@ import com.mhd.bms.domain.billManage.entity.BillDetail;
|
||||
import com.mhd.bms.domain.billManage.repository.po.BillDetailPO;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
@@ -17,4 +18,8 @@ public interface BillDetailMapper extends BaseMapper<BillDetail>
|
||||
{
|
||||
|
||||
List<BillDetailPO> getDetailsByBillManageId(@Param("billManageId") Long billManageId);
|
||||
}
|
||||
|
||||
List<BillDetail> getDetailsByBillManageIdAndGroup(@Param("billManageId") Long billManageId);
|
||||
|
||||
Double getTaxRate(@Param("code") String code);
|
||||
}
|
||||
+2
@@ -44,4 +44,6 @@ public interface BillManageMapper extends BaseMapper<BillManage>
|
||||
String getDeptName(@Param("dictCode") String dictCode);
|
||||
|
||||
String getOrgCodeNc(@Param("organizationId") Long organizationId);
|
||||
|
||||
Long getShipperId(@Param("userId") Long userId, @Param("organizationId") Long organizationId);
|
||||
}
|
||||
+6
-1
@@ -75,4 +75,9 @@ public class BillDetailImpl extends ServiceImpl<BillDetailMapper, BillDetail> im
|
||||
public List<BillDetailPO> getDetailsByBillManageId(Long billManageId) {
|
||||
return billDetailMapper.getDetailsByBillManageId(billManageId);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<BillDetail> getDetailsByBillManageIdAndGroup(Long billManageId) {
|
||||
return billDetailMapper.getDetailsByBillManageIdAndGroup(billManageId);
|
||||
}
|
||||
}
|
||||
+1188
-522
File diff suppressed because it is too large
Load Diff
@@ -264,4 +264,6 @@ public class BillManageDO extends BaseVOEntity{
|
||||
private String paymentAccountId;
|
||||
@ApiModelProperty("收款帐户名称")
|
||||
private String paymentAccountName;
|
||||
@ApiModelProperty("业务员ID")
|
||||
private String salesmanId;
|
||||
}
|
||||
+4
@@ -100,6 +100,10 @@ public class BillingStatementPO extends BaseVOEntity{
|
||||
@Excel(name = "收支类型", readConverterExp = "1=-应收,2-应付")
|
||||
private Integer accountExpenseType;
|
||||
|
||||
@ApiModelProperty("收支类型(1-应收,2-应付)")
|
||||
@Excel(name = "收支类型", readConverterExp = "1=-应收,2-应付")
|
||||
private Integer billType;
|
||||
|
||||
@ApiModelProperty("流水备注")
|
||||
@Excel(name = "流水备注")
|
||||
private String billingRemark;
|
||||
|
||||
+4
@@ -101,6 +101,10 @@ public class BillingStatementDO extends BaseVOEntity{
|
||||
@Excel(name = "收支类型", readConverterExp = "1=-应收,2-应付")
|
||||
private Integer accountExpenseType;
|
||||
|
||||
@ApiModelProperty("收支类型(1-应收,2-应付)")
|
||||
@Excel(name = "收支类型", readConverterExp = "1=-应收,2-应付")
|
||||
private Integer billType;
|
||||
|
||||
@ApiModelProperty("流水备注")
|
||||
@Excel(name = "流水备注")
|
||||
private String billingRemark;
|
||||
|
||||
+3
@@ -675,6 +675,9 @@ public class BillingStatementDomainService {
|
||||
*/
|
||||
public List<BillingStatementPO> getBillDetailsList(BillingStatementDO billingStatementDO) {
|
||||
//查询当前账单的五大信息:组织信息、结算对象、来源系统、收支类型、账单周期
|
||||
if (billingStatementDO.getBillManageId() == null || billingStatementDO.getBillManageId() <= 0) {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
BillManagePO billManagePO = billManageDomainService.getInfo(billingStatementDO.getBillManageId());
|
||||
if(null == billManagePO){
|
||||
throw new ServiceException("账单信息未找到");
|
||||
|
||||
+21
-1
@@ -8,6 +8,7 @@ import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import com.mhd.bms.domain.billManage.entity.BillManage;
|
||||
import com.mhd.bms.domain.billManage.repository.mapper.BillManageMapper;
|
||||
import com.mhd.common.core.web.domain.AjaxResult;
|
||||
import com.mhd.bms.domain.bmsInvoiceList.entity.BmsInvoiceList;
|
||||
import com.mhd.bms.domain.bmsInvoiceList.entity.BmsSettlementPartyInvoice;
|
||||
import com.mhd.bms.domain.bmsInvoiceList.repository.facade.IBmsInvoiceListService;
|
||||
@@ -56,6 +57,8 @@ public class BmsInvoiceListServiceImpl extends ServiceImpl<BmsInvoiceListMapper,
|
||||
private BmsMakeOutInvoiceItemMapper bmsMakeOutInvoiceItemMapper;
|
||||
@Resource
|
||||
private BillManageMapper billManageMapper;
|
||||
@Resource
|
||||
private com.mhd.system.api.SystemServiceFeign systemServiceFeign;
|
||||
/*@Resource
|
||||
private BmsSettlementPartyInvoiceMapper bmsSettlementPartyInvoiceMapper;*/
|
||||
|
||||
@@ -327,7 +330,7 @@ public class BmsInvoiceListServiceImpl extends ServiceImpl<BmsInvoiceListMapper,
|
||||
/**
|
||||
* 发票详情
|
||||
*
|
||||
* @param id
|
||||
* @param
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
@@ -415,6 +418,23 @@ public class BmsInvoiceListServiceImpl extends ServiceImpl<BmsInvoiceListMapper,
|
||||
bmsMakeOutInvoiceItem.setMakeId(bmsMakeOutInvoice.getId());
|
||||
//bmsMakeOutInvoiceItem.setCreateBy(sysUser.getId());
|
||||
bmsMakeOutInvoiceItem.setCreateTime(date);
|
||||
// 如果前端没传 invoiceItemName,按 invoiceItem(编码)从费用科目反查名称补齐
|
||||
if (StringUtils.isEmpty(bmsMakeOutInvoiceItem.getInvoiceItemName())
|
||||
&& StringUtils.isNotEmpty(bmsMakeOutInvoiceItem.getInvoiceItem())) {
|
||||
try {
|
||||
AjaxResult ajaxResult = systemServiceFeign.getSubInfoByCode(bmsMakeOutInvoiceItem.getInvoiceItem());
|
||||
if ("200".equals(String.valueOf(ajaxResult.get("code"))) && ajaxResult.get("data") != null) {
|
||||
com.alibaba.fastjson.JSONObject dataObj = com.alibaba.fastjson.JSON.parseObject(
|
||||
com.alibaba.fastjson.JSON.toJSONString(ajaxResult.get("data")));
|
||||
String subjectName = dataObj.getString("subjectName");
|
||||
if (StringUtils.isNotEmpty(subjectName)) {
|
||||
bmsMakeOutInvoiceItem.setInvoiceItemName(subjectName);
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.warn("开票项目名称反查失败 invoiceItem=" + bmsMakeOutInvoiceItem.getInvoiceItem() + " " + e.getMessage());
|
||||
}
|
||||
}
|
||||
bmsMakeOutInvoiceItemMapper.insert(bmsMakeOutInvoiceItem);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
+4
@@ -102,6 +102,10 @@ public class BillingStatementDTO extends BaseVOEntity{
|
||||
@Excel(name = "收支类型", readConverterExp = "1=-应收,2-应付")
|
||||
private Integer accountExpenseType;
|
||||
|
||||
@ApiModelProperty("收支类型(1-应收,2-应付)")
|
||||
@Excel(name = "收支类型", readConverterExp = "1=-应收,2-应付")
|
||||
private Integer billType;
|
||||
|
||||
@ApiModelProperty("流水备注")
|
||||
@Excel(name = "流水备注")
|
||||
private String billingRemark;
|
||||
|
||||
@@ -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<BillManagePO> list = billManageApplicationService.queryList(billManageDO);
|
||||
|
||||
//扁平化处理:一条明细生成一行
|
||||
List<BillManageExportVO> exportList = new ArrayList<>();
|
||||
for (BillManagePO bill : list) {
|
||||
List<BillDetailPO> details = bill.getBillDetailPOList();
|
||||
if (details != null && !details.isEmpty()) {
|
||||
for (BillDetailPO detail : details) {
|
||||
BillManageExportVO vo = new BillManageExportVO();
|
||||
//复制全部账单头字段
|
||||
BeanUtils.copyProperties(bill, vo);
|
||||
//覆盖明细字段
|
||||
vo.setFeeType(detail.getFeeType());
|
||||
vo.setServiceItemsCode(detail.getServiceItemsCode());
|
||||
vo.setServiceItemsName(detail.getServiceItemsName());
|
||||
vo.setFirstSubjectCode(detail.getFirstSubjectCode());
|
||||
vo.setFirstSubjectName(detail.getFirstSubjectName());
|
||||
vo.setSecondSubjectCode(detail.getSecondSubjectCode());
|
||||
vo.setSecondSubjectName(detail.getSecondSubjectName());
|
||||
vo.setBillingAmount(detail.getBillingAmount());
|
||||
exportList.add(vo);
|
||||
}
|
||||
} else {
|
||||
//没有明细也要有一行
|
||||
BillManageExportVO vo = new BillManageExportVO();
|
||||
BeanUtils.copyProperties(bill, vo);
|
||||
exportList.add(vo);
|
||||
}
|
||||
}
|
||||
|
||||
//设置下载头,防止浏览器乱码
|
||||
String fileName = URLEncoder.encode("应收账单", "UTF-8").replaceAll("\\+", "%20");
|
||||
response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
|
||||
response.setCharacterEncoding("utf-8");
|
||||
response.setHeader("Content-disposition", "attachment;filename=" + fileName + ".xlsx");
|
||||
|
||||
ExcelUtil<BillManageExportVO> util = new ExcelUtil<>(BillManageExportVO.class);
|
||||
util.exportExcel(response, exportList, "应收账单");
|
||||
}
|
||||
|
||||
@ApiOperation("获取nc推送日志")
|
||||
@GetMapping(value = "/getNcLog")
|
||||
public AjaxResult getNcLog(@RequestParam(name = "billManageId") Long billManageId, @RequestParam(name = "type") Long type)
|
||||
@@ -229,7 +283,36 @@ public class BillManageApi extends BaseController{
|
||||
}
|
||||
|
||||
|
||||
@ApiOperation("复制账单")
|
||||
@ApiOperation("修改账单明细")
|
||||
@PostMapping("/updateBillDetail")
|
||||
public AjaxResult updateBillDetail(@RequestBody BillManageDTO billManageDTO)
|
||||
{
|
||||
try {
|
||||
billManageApplicationService.updateBillDetail(billManageDTO);
|
||||
return AjaxResult.success("操作成功");
|
||||
}catch (Exception e){
|
||||
return AjaxResult.error("修改明细失败:"+e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ApiOperation("新增账单")
|
||||
@PostMapping("/addBill")
|
||||
public AjaxResult addBill(@RequestBody BillManageDTO billManageDTO)
|
||||
{
|
||||
if(billManageDTO.getBillDetailDTOList() == null || billManageDTO.getBillDetailDTOList().size() == 0){
|
||||
throw new ServiceException("账单明细不能为空");
|
||||
}
|
||||
try {
|
||||
billManageApplicationService.addBill(billManageDTO);
|
||||
return AjaxResult.success("操作成功");
|
||||
}catch (Exception e){
|
||||
return AjaxResult.error("新增账单失败:"+e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ApiOperation("复制账单-获取原账单数据用于回显")
|
||||
@PostMapping("/copyBill")
|
||||
public AjaxResult copyBill(@RequestBody BillManageDTO billManageDTO)
|
||||
{
|
||||
@@ -237,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());
|
||||
}
|
||||
|
||||
@@ -18,15 +18,15 @@ spring:
|
||||
discovery:
|
||||
# server-addr: 127.0.0.1:8848
|
||||
# 线上测试环境配置 容器名+端口号
|
||||
# server-addr: 10.33.0.129:6010
|
||||
server-addr: 10.102.192.30:6848
|
||||
server-addr: 10.33.0.129:6010
|
||||
# server-addr: 10.102.192.31:6848
|
||||
username: nacos
|
||||
password: manhuoda@2023
|
||||
config:
|
||||
# server-addr: 127.0.0.1:8848
|
||||
# 线上测试环境配置 容器名+端口号
|
||||
# server-addr: 10.33.0.129:6010
|
||||
server-addr: 10.102.192.30:6848
|
||||
server-addr: 10.33.0.129:6010
|
||||
# server-addr: 10.102.192.31:6848
|
||||
username: nacos
|
||||
password: manhuoda@2023
|
||||
group: DEFAULT_GROUP # 默认分组就是DEFAULT_GROUP,如果使用默认分组可以不配置
|
||||
|
||||
@@ -27,5 +27,35 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
AND bd.bill_manage_id = #{billManageId}
|
||||
</select>
|
||||
|
||||
<select id="getDetailsByBillManageIdAndGroup" resultType="com.mhd.bms.domain.billManage.entity.BillDetail" parameterType="java.lang.Long">
|
||||
SELECT
|
||||
SUM(BILLING_AMOUNT) as BILLING_AMOUNT,
|
||||
SUM(TAX_AMOUNT) as TAX_AMOUNT,
|
||||
SUM(TAX_FREE_FEE) as TAX_FREE_FEE,
|
||||
AVG(TAX_RATE) as TAX_RATE,
|
||||
BILL_MANAGE_ID as BILL_MANAGE_ID,
|
||||
TOP_ORGANIZATION_ID as TOP_ORGANIZATION_ID,
|
||||
ORGANIZATION_NAME,
|
||||
INVOICE_ITEM,
|
||||
INVOICE_ITEM_NAME,
|
||||
FEE_TYPE,
|
||||
BILL_NUMBER
|
||||
FROM
|
||||
bill_detail
|
||||
WHERE
|
||||
del_flag = 1
|
||||
AND bill_manage_id = #{billManageId} GROUP BY INVOICE_ITEM,INVOICE_ITEM_NAME,FEE_TYPE
|
||||
</select>
|
||||
|
||||
</mapper>
|
||||
<select id="getTaxRate" resultType="java.lang.Double" parameterType="java.lang.String">
|
||||
SELECT
|
||||
rate
|
||||
FROM
|
||||
NGWL_TEST_SYSTEM.EXPENSE_ACCOUNT
|
||||
WHERE
|
||||
del_flag = 1
|
||||
AND SUBJECT_CODE = #{code}
|
||||
</select>
|
||||
|
||||
|
||||
</mapper>
|
||||
@@ -162,4 +162,8 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
SELECT NC_CODE FROM NGWL_TEST_PRODUCT."SYS_ORGANIZATION" where DEL_FLAG = 1 and organization_id = #{organizationId} limit 1
|
||||
</select>
|
||||
|
||||
<select id="getShipperId" resultType="java.lang.Long">
|
||||
SELECT SHIPPER_ID FROM NGWL_TEST_USER."USER_SHIPPER" where DEL_FLAG = '1' and user_id = #{userId} and organization_id = #{organizationId} limit 1
|
||||
</select>
|
||||
|
||||
</mapper>
|
||||
@@ -166,12 +166,18 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
<if test="businessDocumentDO.contractName != null and businessDocumentDO.contractName != ''">
|
||||
AND contract_name like concat('%', #{businessDocumentDO.contractName}, '%')
|
||||
</if>
|
||||
<!-- <if test="businessDocumentDO.billAmount != null and businessDocumentDO.billAmount != ''">-->
|
||||
<!-- AND bill_amount like concat('%', #{businessDocumentDO.billAmount}, '%')-->
|
||||
<!-- </if>-->
|
||||
<if test="businessDocumentDO.billAmount != null and businessDocumentDO.billAmount != ''">
|
||||
AND bill_amount like concat('%', #{businessDocumentDO.billAmount}, '%')
|
||||
and bill_amount = #{businessDocumentDO.billAmount}
|
||||
</if>
|
||||
<if test="businessDocumentDO.estimatedCost != null and businessDocumentDO.estimatedCost != ''">
|
||||
AND estimated_cost like concat('%', #{businessDocumentDO.estimatedCost}, '%')
|
||||
AND estimated_cost = #{businessDocumentDO.estimatedCost}
|
||||
</if>
|
||||
<!-- <if test="businessDocumentDO.estimatedCost != null and businessDocumentDO.estimatedCost != ''">-->
|
||||
<!-- AND estimated_cost like concat('%', #{businessDocumentDO.estimatedCost}, '%')-->
|
||||
<!-- </if>-->
|
||||
<if test="businessDocumentDO.firstSubjectName != null and businessDocumentDO.firstSubjectName != ''">
|
||||
AND first_subject_name like concat('%', #{businessDocumentDO.firstSubjectName}, '%')
|
||||
</if>
|
||||
@@ -193,6 +199,9 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
<if test="businessDocumentDO.documentTypeCode != null and businessDocumentDO.documentTypeCode != ''">
|
||||
AND document_type_code = #{businessDocumentDO.documentTypeCode}
|
||||
</if>
|
||||
<if test="businessDocumentDO.salesmanId != null and businessDocumentDO.salesmanId != ''">
|
||||
AND document_type_code = #{businessDocumentDO.salesmanId}
|
||||
</if>
|
||||
<if test="businessDocumentDO.businessDocumentIdSet != null">
|
||||
and business_document_id in
|
||||
<foreach item="id" collection="businessDocumentDO.businessDocumentIdSet" open="(" separator="," close=")">
|
||||
|
||||
@@ -200,10 +200,6 @@
|
||||
<if test="settlementCustomersDO.organizationId != null">
|
||||
AND (
|
||||
a.organization_id = #{settlementCustomersDO.organizationId}
|
||||
OR b.org_code LIKE concat('%"code":"', #{settlementCustomersDO.organizationId}, '"%')
|
||||
OR b.org_code LIKE concat('%code:', #{settlementCustomersDO.organizationId}, '%')
|
||||
OR b.org_code LIKE concat('%code: ', #{settlementCustomersDO.organizationId}, '%')
|
||||
OR b.org_code LIKE concat('%"code":', #{settlementCustomersDO.organizationId}, '%')
|
||||
)
|
||||
</if>
|
||||
<if test="settlementCustomersDO.topOrganizationId != null and settlementCustomersDO.topOrganizationId != ''">
|
||||
@@ -216,4 +212,4 @@
|
||||
and a.customer_type_code = #{settlementCustomersDO.customerTypeCode}
|
||||
</if>
|
||||
</sql>
|
||||
</mapper>
|
||||
</mapper>
|
||||
+1
@@ -68,4 +68,5 @@ public interface ExecutionStockInOrderMapper extends BaseMapper<ExecutionStockIn
|
||||
|
||||
String getNcUrl(@Param("interfaceType") String interfaceType,@Param("organizationName") String organizationName,@Param("organizationId") Long organizationId);
|
||||
|
||||
int countByOrderNumberPrefix(@Param("prefix") String prefix);
|
||||
}
|
||||
+1
@@ -37,4 +37,5 @@ public interface ExecutionStockOutOrderMapper extends BaseMapper<ExecutionStockO
|
||||
|
||||
public void delWOrderDetail(@Param("outOrderNumber") String outOrderNumber);
|
||||
|
||||
int countByOrderNumberPrefix(@Param("prefix") String prefix);
|
||||
}
|
||||
+2
@@ -29,6 +29,8 @@ public interface ReservationMaterialInventoryMapper extends BaseMapper<Reservati
|
||||
public List<ReservationMaterialInventoryPO> queryListByWl(ReservationMaterialInventoryDO materialInventoryDO);
|
||||
//查物料库存列表-货主
|
||||
public List<ReservationMaterialInventoryPO> queryListByHz(ReservationMaterialInventoryDO materialInventoryDO);
|
||||
//查物料库存列表-物料+过期日期
|
||||
public List<ReservationMaterialInventoryPO> queryListByWlExpiry(ReservationMaterialInventoryDO materialInventoryDO);
|
||||
|
||||
|
||||
public MaterialBaseInfo getByInfoId(@Param("id") Long id);
|
||||
|
||||
+2
@@ -64,6 +64,8 @@ public class ReservationMaterialInventoryImpl extends ServiceImpl<ReservationMat
|
||||
return materialInventoryMapper.queryListByKw(materialInventoryDO);
|
||||
} else if ("wlkw".equals(queryRule)) {
|
||||
return materialInventoryMapper.queryListByWlKw(materialInventoryDO);
|
||||
} else if ("wlExpiry".equals(queryRule)) {
|
||||
return materialInventoryMapper.queryListByWlExpiry(materialInventoryDO);
|
||||
} else if ("all".equals(queryRule)) {
|
||||
return materialInventoryMapper.queryList(materialInventoryDO);
|
||||
} else {
|
||||
|
||||
+2
@@ -253,4 +253,6 @@ public class ReservationMaterialInventoryDO extends MaterialBaseDO {
|
||||
private String createTimeEnd;
|
||||
private String expiryDateStr;
|
||||
private String productionDateStr;
|
||||
private String expiryDateStart;
|
||||
private String expiryDateEnd;
|
||||
}
|
||||
+9
-1
@@ -2,6 +2,7 @@ package com.mhd.oms.domain.reservationStockInOrder.repository.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.mhd.oms.domain.reservationInMaterialDetail.repository.po.ReservationInMaterialDetailPO;
|
||||
import com.mhd.oms.domain.reservationMaterialInventory.repository.po.ReservationMaterialInventoryPO;
|
||||
import com.mhd.oms.domain.reservationStockInOrder.entity.ReservationStockInOrder;
|
||||
import com.mhd.oms.domain.reservationStockInOrder.repository.po.MaterialBaseInfoPO;
|
||||
import com.mhd.oms.domain.reservationStockInOrder.repository.po.MaterialGoodsRulePO;
|
||||
@@ -30,13 +31,16 @@ public interface ReservationStockInOrderMapper extends BaseMapper<ReservationSto
|
||||
|
||||
public MaterialBaseInfoPO getByName(@Param("name") String name);
|
||||
|
||||
public MaterialBaseInfoPO getByCode(@Param("code") String code);
|
||||
public MaterialBaseInfoPO getByCode(@Param("code") String code,@Param("orgId") Long orgId);
|
||||
|
||||
public List<MaterialBaseInfoPO> getMaterialBaseInfoList(@Param("id") String id);
|
||||
|
||||
public List<ReservationMaterialInventoryPO> 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<ReservationMaterialInventoryPO> getkcId(@Param("id") Long id, @Param("q") BigDecimal q);
|
||||
|
||||
public String getUserNcCode(@Param("id") Long id);
|
||||
|
||||
@@ -67,4 +71,8 @@ public interface ReservationStockInOrderMapper extends BaseMapper<ReservationSto
|
||||
String getNcUrl(@Param("interfaceType") String interfaceType,@Param("organizationName") String organizationName,@Param("organizationId") Long organizationId);
|
||||
|
||||
String getCustomerOrgCode(@Param("id") Long id);
|
||||
|
||||
int countByOrderNumberPrefix(@Param("prefix") String prefix);
|
||||
|
||||
List<String> generateReserveOrderNumber1(@Param("prefix") String prefix);
|
||||
}
|
||||
+47
-8
@@ -20,6 +20,7 @@ import com.mhd.oms.domain.reservationDeliveryDetailsLink.repository.facade.IRese
|
||||
import com.mhd.oms.domain.reservationInMaterialDetail.repository.facade.IReservationInMaterialDetailService;
|
||||
import com.mhd.oms.domain.reservationInMaterialDetail.repository.po.ReservationInMaterialDetailPO;
|
||||
import com.mhd.oms.domain.reservationInMaterialDetail.repository.todo.ReservationInMaterialDetailDO;
|
||||
import com.mhd.oms.domain.reservationMaterialInventory.repository.po.ReservationMaterialInventoryPO;
|
||||
import com.mhd.oms.domain.reservationOutMaterialDetail.repository.facade.IReservationOutMaterialDetailService;
|
||||
import com.mhd.oms.domain.reservationOutMaterialDetail.repository.todo.ReservationOutMaterialDetailDO;
|
||||
import com.mhd.oms.domain.reservationStockInOrder.entity.ReservationStockInOrder;
|
||||
@@ -32,6 +33,7 @@ import com.mhd.oms.domain.reservationStockInOrder.repository.po.MaterialBaseInfo
|
||||
import com.mhd.oms.domain.reservationStockInOrder.repository.po.ReservationStockInOrderPO;
|
||||
import com.mhd.oms.domain.reservationStockInOrder.repository.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;
|
||||
@@ -83,6 +85,8 @@ public class ReservationStockInOrderImpl extends ServiceImpl<ReservationStockInO
|
||||
private SystemServiceFeign systemServiceFeign;
|
||||
@Autowired
|
||||
private IReservationInMaterialDetailService materialDetailService;
|
||||
@Autowired
|
||||
private ReservationStockInOrderDomainService reservationStockInOrderDomainService;
|
||||
|
||||
/**
|
||||
* 查询入库单列表
|
||||
@@ -192,7 +196,7 @@ public class ReservationStockInOrderImpl extends ServiceImpl<ReservationStockInO
|
||||
List<Map<String,Object>> shipperIds = new ArrayList<>();
|
||||
Set<Long> processedShipperIds = new HashSet<>();
|
||||
for (ProductDetail productDetail : productDetailList) {
|
||||
MaterialBaseInfoPO materialBaseInfoPO = stockInOrderMapper.getByCode(productDetail.getProductCode());
|
||||
MaterialBaseInfoPO materialBaseInfoPO = stockInOrderMapper.getByCode(productDetail.getProductCode(),loginUser.getUserPo().getOrganizationId());
|
||||
if (materialBaseInfoPO != null && materialBaseInfoPO.getShipperId() != null) {
|
||||
Long shipperId = materialBaseInfoPO.getShipperId();
|
||||
if (processedShipperIds.add(shipperId)) {
|
||||
@@ -216,7 +220,10 @@ public class ReservationStockInOrderImpl extends ServiceImpl<ReservationStockInO
|
||||
}
|
||||
|
||||
ReservationStockOutOrderDO reservationStockOutOrderDO = new ReservationStockOutOrderDO();
|
||||
reservationStockOutOrderDO.setOutOrderNumber(OrderSequence.getOrderCode("CK"));
|
||||
// 生成出库业务单号
|
||||
String orderNumber = reservationStockOutOrderApplicationService.generateReserveOrderNumber();
|
||||
reservationStockOutOrderDO.setOutOrderNumber(orderNumber);
|
||||
reservationStockOutOrderDO.setBusinessOrderNo(orderNumber);
|
||||
// 货主信息:有货品明细时从解析结果取,无货品明细时从登录用户取
|
||||
if (!shipperIds.isEmpty()) {
|
||||
reservationStockOutOrderDO.setShipperId((Long) shipperIds.get(0).get("shipperId"));
|
||||
@@ -254,9 +261,38 @@ public class ReservationStockInOrderImpl extends ServiceImpl<ReservationStockInO
|
||||
for (ProductDetail productDetail : productDetailList) {
|
||||
ReservationOutMaterialDetailDO reservationOutMaterialDetailDO = new ReservationOutMaterialDetailDO();
|
||||
reservationOutMaterialDetailDO.setOutOrderNumber(reservationStockOutOrderDO.getOutOrderNumber());
|
||||
MaterialBaseInfoPO materialBaseInfoPO = stockInOrderMapper.getByCode(productDetail.getProductCode());
|
||||
MaterialBaseInfoPO materialBaseInfoPO = stockInOrderMapper.getByCode(productDetail.getProductCode(),loginUser.getUserPo().getOrganizationId());
|
||||
reservationOutMaterialDetailDO.setQuantity(new BigDecimal(productDetail.getPieceCount()).setScale(2, BigDecimal.ROUND_HALF_UP));
|
||||
if (materialBaseInfoPO != null) {
|
||||
Long materialBaseInfoId = materialBaseInfoPO.getMaterialBaseInfoId();
|
||||
List<ReservationMaterialInventoryPO> reservationMaterialInventoryPOS = stockInOrderMapper.getkcId(materialBaseInfoId, new BigDecimal(productDetail.getPieceCount()).setScale(2, BigDecimal.ROUND_HALF_UP));
|
||||
if (reservationMaterialInventoryPOS != null&&reservationMaterialInventoryPOS.size() > 0) {
|
||||
ReservationMaterialInventoryPO reservationMaterialInventoryPO = reservationMaterialInventoryPOS.get(0);
|
||||
Long materialInventoryId = reservationMaterialInventoryPO.getMaterialInventoryId();
|
||||
String batchNumber = reservationMaterialInventoryPO.getBatchNumber();
|
||||
String lotNumber = reservationMaterialInventoryPO.getLotNumber();
|
||||
Long warehouseId = reservationMaterialInventoryPO.getWarehouseId();
|
||||
String warehouseCode = reservationMaterialInventoryPO.getWarehouseCode();
|
||||
String warehouseName = reservationMaterialInventoryPO.getWarehouseName();
|
||||
String inOrderNumber = reservationMaterialInventoryPO.getInOrderNumber();
|
||||
BigDecimal inventoryQuantity = reservationMaterialInventoryPO.getInventoryQuantity();
|
||||
String unit = reservationMaterialInventoryPO.getUnit();
|
||||
String unitName = reservationMaterialInventoryPO.getUnitName();
|
||||
reservationOutMaterialDetailDO.setMaterialInventoryId(materialInventoryId);
|
||||
reservationOutMaterialDetailDO.setBatchNumber(batchNumber);
|
||||
reservationOutMaterialDetailDO.setLotNo(lotNumber);
|
||||
reservationOutMaterialDetailDO.setWarehouseId(warehouseId);
|
||||
reservationOutMaterialDetailDO.setWarehouseCode(warehouseCode);
|
||||
reservationOutMaterialDetailDO.setWarehouseName(warehouseName);
|
||||
reservationOutMaterialDetailDO.setInOrderNumber(inOrderNumber);
|
||||
reservationOutMaterialDetailDO.setStockQuantity(inventoryQuantity);
|
||||
reservationOutMaterialDetailDO.setUnit(unit);
|
||||
reservationOutMaterialDetailDO.setStockUnit(unitName);
|
||||
reservationOutMaterialDetailDO.setInventoryQuantity(inventoryQuantity);
|
||||
reservationOutMaterialDetailDO.setUnitName(unitName);
|
||||
} else {
|
||||
throw new RuntimeException("物料批次库存数量少于出库数量!");
|
||||
}
|
||||
reservationOutMaterialDetailDO.setMaterialBaseInfoId(materialBaseInfoPO.getMaterialBaseInfoId());
|
||||
reservationOutMaterialDetailDO.setMaterialCode(materialBaseInfoPO.getMaterialCode());
|
||||
reservationOutMaterialDetailDO.setMaterialName(materialBaseInfoPO.getMaterialName());
|
||||
@@ -360,7 +396,7 @@ public class ReservationStockInOrderImpl extends ServiceImpl<ReservationStockInO
|
||||
List<Map<String,Object>> shipperIds = new ArrayList<>();
|
||||
Set<Long> processedShipperIds = new HashSet<>();
|
||||
for (StockInProductDetail productDetail : productDetailList) {
|
||||
MaterialBaseInfoPO materialBaseInfoPO = stockInOrderMapper.getByCode(productDetail.getProductCode());
|
||||
MaterialBaseInfoPO materialBaseInfoPO = stockInOrderMapper.getByCode(productDetail.getProductCode(),loginUser.getUserPo().getOrganizationId());
|
||||
if (materialBaseInfoPO != null && materialBaseInfoPO.getShipperId() != null) {
|
||||
Long shipperId = materialBaseInfoPO.getShipperId();
|
||||
if (processedShipperIds.add(shipperId)) {
|
||||
@@ -373,7 +409,10 @@ public class ReservationStockInOrderImpl extends ServiceImpl<ReservationStockInO
|
||||
}
|
||||
}
|
||||
ReservationStockInOrderDO reservationStockInOrderDO = new ReservationStockInOrderDO();
|
||||
reservationStockInOrderDO.setInOrderNumber(OrderSequence.getOrderCode("RK"));
|
||||
// 生成业务单号
|
||||
String orderNumber = reservationStockInOrderDomainService.generateReserveOrderNumber();
|
||||
reservationStockInOrderDO.setInOrderNumber(orderNumber);
|
||||
reservationStockInOrderDO.setBusinessOrderNo(orderNumber);
|
||||
reservationStockInOrderDO.setOrganizationId(loginUser.getUserPo().getOrganizationId());
|
||||
reservationStockInOrderDO.setOrganizationName(loginUser.getUserPo().getOrganizationName());
|
||||
reservationStockInOrderDO.setTopOrganizationId(loginUser.getUserPo().getTopOrganizationId());
|
||||
@@ -399,7 +438,6 @@ public class ReservationStockInOrderImpl extends ServiceImpl<ReservationStockInO
|
||||
reservationStockInOrderDO.setWarehouseDate(stockInHeader.getStockInDate());
|
||||
reservationStockInOrderDO.setStorageTime(stockInHeader.getStockInDate());
|
||||
reservationStockInOrderDO.setExpectTime(stockInHeader.getStockInDate());
|
||||
reservationStockInOrderDO.setBusinessOrderNo(stockInHeader.getOrderNo());
|
||||
reservationStockInOrderDO.setReservationOrderSource("数据导入");
|
||||
List<ReservationInMaterialDetailDO> reservationInMaterialDetailDOList = new ArrayList<>();
|
||||
int index = 1;
|
||||
@@ -412,7 +450,7 @@ public class ReservationStockInOrderImpl extends ServiceImpl<ReservationStockInO
|
||||
reservationInMaterialDetailDO.setCreateBy(loginUser.getUserPo().getUserId());
|
||||
reservationInMaterialDetailDO.setCreateByName(loginUser.getUserPo().getUserName());
|
||||
reservationInMaterialDetailDO.setCreateTime(new Date());
|
||||
MaterialBaseInfoPO materialBaseInfoPO = stockInOrderMapper.getByCode(stockInProductDetail.getProductCode());
|
||||
MaterialBaseInfoPO materialBaseInfoPO = stockInOrderMapper.getByCode(stockInProductDetail.getProductCode(),loginUser.getUserPo().getOrganizationId());
|
||||
reservationInMaterialDetailDO.setQuantity(new BigDecimal(stockInProductDetail.getBoxCount()).setScale(2, BigDecimal.ROUND_HALF_UP));
|
||||
if (materialBaseInfoPO != null) {
|
||||
reservationInMaterialDetailDO.setMaterialBaseInfoId(materialBaseInfoPO.getMaterialBaseInfoId());
|
||||
@@ -469,7 +507,8 @@ public class ReservationStockInOrderImpl extends ServiceImpl<ReservationStockInO
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public Boolean insertDomain(ReservationStockInOrderDO stockInOrderDO) {
|
||||
if (stockInOrderDO.getInOrderNumber() == null) {
|
||||
stockInOrderDO.setInOrderNumber(OrderSequence.getOrderCode("RK"));
|
||||
stockInOrderDO.setInOrderNumber(reservationStockInOrderDomainService.generateReserveOrderNumber());
|
||||
stockInOrderDO.setBusinessOrderNo(stockInOrderDO.getInOrderNumber());
|
||||
}
|
||||
// //统计总计划数
|
||||
BigDecimal quantity = stockInOrderDO.getMaterialDetailList().stream().map(ReservationInMaterialDetailDO::getQuantity).filter(Objects::nonNull).reduce(BigDecimal.ZERO, BigDecimal::add);
|
||||
|
||||
+7
@@ -2286,4 +2286,11 @@ public class ReservationStockInOrderApplicationService {
|
||||
return filteredList;
|
||||
}
|
||||
|
||||
public String generateReserveOrderNumber() {
|
||||
return stockInOrderDomainService.generateReserveOrderNumber();
|
||||
}
|
||||
|
||||
public String generateReserveOrderNumber1() {
|
||||
return stockInOrderDomainService.generateReserveOrderNumber1();
|
||||
}
|
||||
}
|
||||
+55
-11
@@ -17,6 +17,7 @@ import com.mhd.oms.domain.executionInMaterialDetail.entity.ExecutionInMaterialDe
|
||||
import com.mhd.oms.domain.executionInMaterialDetail.repository.facade.IExecutionInMaterialDetailService;
|
||||
import com.mhd.oms.domain.executionStockInOrder.entity.ExecutionStockInOrder;
|
||||
import com.mhd.oms.domain.executionStockInOrder.repository.facade.IExecutionStockInOrderService;
|
||||
import com.mhd.oms.domain.executionStockInOrder.repository.mapper.ExecutionStockInOrderMapper;
|
||||
import com.mhd.oms.domain.executionStockInOrder.repository.todo.ExecutionStockInOrderDO;
|
||||
import com.mhd.oms.domain.executionStockInOrder.service.ExecutionStockInOrderApplicationService;
|
||||
import com.mhd.oms.domain.reservationInMaterialDetail.entity.ReservationInMaterialDetail;
|
||||
@@ -37,6 +38,7 @@ import com.mhd.oms.domain.reservationStockOutOrder.entity.ReservationStockOutOrd
|
||||
import com.mhd.oms.domain.reservationStockOutOrder.repository.facade.IReservationStockOutOrderService;
|
||||
import com.mhd.oms.domain.reserveInMaterialDetail.entity.ReserveInMaterialDetail;
|
||||
import com.mhd.oms.domain.reserveStockInOrder.entity.ReserveStockInOrder;
|
||||
import com.mhd.oms.domain.reserveStockInOrder.repository.mapper.ReserveStockInOrderMapper;
|
||||
import com.mhd.system.api.SystemServiceFeign;
|
||||
import com.mhd.system.api.WmsServiceFeign;
|
||||
import com.mhd.system.api.domain.*;
|
||||
@@ -85,6 +87,10 @@ public class ReservationStockInOrderDomainService {
|
||||
private ExecutionStockInOrderApplicationService stockInOrderApplicationService;
|
||||
@Autowired
|
||||
private BusinessDocumentOrderMapper businessDocumentOrderMapper;
|
||||
@Autowired
|
||||
private ExecutionStockInOrderMapper executionStockInOrderMapper;
|
||||
@Autowired
|
||||
private ReserveStockInOrderMapper reserveStockInOrderMapper;
|
||||
|
||||
/**
|
||||
* 分页查询入库单列表
|
||||
@@ -100,7 +106,8 @@ public class ReservationStockInOrderDomainService {
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public Boolean insert(ReservationStockInOrderDO stockInOrderDO) {
|
||||
if (stockInOrderDO.getInOrderNumber() == null) {
|
||||
stockInOrderDO.setInOrderNumber(OrderSequence.getOrderCode("RK"));
|
||||
stockInOrderDO.setInOrderNumber(generateReserveOrderNumber());
|
||||
stockInOrderDO.setBusinessOrderNo(stockInOrderDO.getInOrderNumber());
|
||||
}
|
||||
// //设置默认值
|
||||
// setDefaultValues(stockInOrderDO);
|
||||
@@ -534,11 +541,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<ExecutionInMaterialDetail> 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<ExecutionInMaterialDetail> 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<String> orderNumber1 = reservationStockInOrderMapper.generateReserveOrderNumber1(prefix);
|
||||
List<String> orderNumber2 = reserveStockInOrderMapper.generateReserveOrderNumber1(prefix);
|
||||
List<String> allOrders = new ArrayList<>();
|
||||
allOrders.addAll(orderNumber1);
|
||||
allOrders.addAll(orderNumber2);
|
||||
int maxseq = 0;
|
||||
for(String order:allOrders)
|
||||
{
|
||||
String numStr = order.substring(prefix.length());
|
||||
int num = Integer.parseInt(numStr);
|
||||
if(num > maxseq){
|
||||
maxseq = num;
|
||||
}
|
||||
}
|
||||
String seq = String.format("%03d", maxseq + 1);
|
||||
return prefix + seq;
|
||||
}
|
||||
}
|
||||
+4
@@ -37,4 +37,8 @@ public interface ReservationStockOutOrderMapper extends BaseMapper<ReservationSt
|
||||
List<ReservationOutMaterialDetailPO> queryOutStockNoticePrintDetail(ReservationStockOutOrderDO stockOutOrderDO);
|
||||
|
||||
Long queryShipperId(@Param("userMemberCode") String userMemberCode,@Param("organizationId") Long organizationId);
|
||||
|
||||
int countByOrderNumberPrefix(@Param("prefix") String prefix);
|
||||
|
||||
List<String> generateReserveOrderNumber1(@Param("prefix") String prefix);
|
||||
}
|
||||
+7
@@ -1743,4 +1743,11 @@ public class ReservationStockOutOrderApplicationService {
|
||||
return filteredList;
|
||||
}
|
||||
|
||||
public String generateReserveOrderNumber() {
|
||||
return stockOutOrderDomainService.generateReserveOrderNumber();
|
||||
}
|
||||
|
||||
public String generateReserveOrderNumber1() {
|
||||
return stockOutOrderDomainService.generateReserveOrderNumber1();
|
||||
}
|
||||
}
|
||||
+60
-11
@@ -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<ExecutionOutMaterialDetail> 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<ExecutionOutMaterialDetail> 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<String> orderNumber1 = reservationStockOutOrderMapper.generateReserveOrderNumber1(prefix);
|
||||
List<String> orderNumber2 = reserveStockOutOrderMapper.generateReserveOrderNumber1(prefix);
|
||||
List<String> allOrders = new ArrayList<>();
|
||||
allOrders.addAll(orderNumber1);
|
||||
allOrders.addAll(orderNumber2);
|
||||
int maxseq = 0;
|
||||
for(String order:allOrders)
|
||||
{
|
||||
String numStr = order.substring(prefix.length());
|
||||
int num = Integer.parseInt(numStr);
|
||||
if(num > maxseq){
|
||||
maxseq = num;
|
||||
}
|
||||
}
|
||||
String seq = String.format("%03d", maxseq + 1);
|
||||
return prefix + seq;
|
||||
}
|
||||
}
|
||||
+31
@@ -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<ReserveStockInOrde
|
||||
List<ReserveInMaterialDetailPO> queryNoticePrintDetail(ReserveStockInOrderDO stockInOrderDO);
|
||||
|
||||
public String getJsbz(@Param("id") Long id);
|
||||
|
||||
int countByOrderNumberPrefix(@Param("prefix") String prefix);
|
||||
|
||||
List<String> generateReserveOrderNumber1(@Param("prefix") String prefix);
|
||||
|
||||
/**
|
||||
* 根据货主名称查询用户(老系统数据导入用)
|
||||
*/
|
||||
List<UserPo> getShipperByName(@Param("name") String name);
|
||||
|
||||
/**
|
||||
* 根据仓库名称查询仓库(老系统数据导入用)
|
||||
*/
|
||||
List<WarehousePO> getWarehouseByName(@Param("name") String name);
|
||||
|
||||
/**
|
||||
* 根据仓库类型查询仓库(老系统数据导入用,1=干仓 2=冬仓)
|
||||
*/
|
||||
List<WarehousePO> getWarehouseByType(@Param("warehouseType") String warehouseType);
|
||||
|
||||
/**
|
||||
* 根据货主用户ID查询NC客户编码
|
||||
*/
|
||||
String getCustomerNcCodeByUserId(@Param("id") Long id);
|
||||
|
||||
/**
|
||||
* 根据入库单号精确统计(导入防重用)
|
||||
*/
|
||||
int countByInOrderNumber(@Param("inOrderNumber") String inOrderNumber);
|
||||
}
|
||||
+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;
|
||||
}
|
||||
+253
@@ -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();
|
||||
@@ -2066,4 +2315,8 @@ public class ReserveStockInOrderApplicationService {
|
||||
// 3. 拼接结果
|
||||
return datePart + randomPart;
|
||||
}
|
||||
|
||||
public String generateReserveOrderNumber() {
|
||||
return stockInOrderDomainService.generateReserveOrderNumber();
|
||||
}
|
||||
}
|
||||
+28
-4
@@ -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<ReserveStockInOrderDO> stockInOrderDOList) {
|
||||
for (ReserveStockInOrderDO stockInOrderDO : stockInOrderDOList){
|
||||
if (StringUtils.isBlank(stockInOrderDO.getInOrderNumber())){
|
||||
stockInOrderDO.setInOrderNumber(OrderSequence.getOrderCode("RK"));
|
||||
stockInOrderDO.setInOrderNumber(generateReserveOrderNumber());
|
||||
}
|
||||
// //设置物料信息
|
||||
// setMaterialDetailInfo(stockInOrderDO);
|
||||
@@ -176,6 +179,10 @@ public class ReserveStockInOrderDomainService {
|
||||
BigDecimal quantity = stockInOrderDO.getMaterialDetailList().stream().map(ReserveInMaterialDetailDO::getQuantity).filter(Objects::nonNull).reduce(BigDecimal.ZERO, BigDecimal::add);
|
||||
stockInOrderPO.setQuantity(quantity);
|
||||
stockInOrderDO.setQuantity(quantity);
|
||||
//统计预约数量
|
||||
BigDecimal reserceQuantity = stockInOrderDO.getMaterialDetailList().stream().map(ReserveInMaterialDetailDO::getReserveQuantity).filter(Objects::nonNull).reduce(BigDecimal.ZERO, BigDecimal::add);
|
||||
stockInOrderPO.setReserveQuantity(reserceQuantity);
|
||||
stockInOrderDO.setReserveQuantity(reserceQuantity);
|
||||
//统计总重量
|
||||
BigDecimal weightLimit = stockInOrderDO.getMaterialDetailList().stream().map(ReserveInMaterialDetailDO::getWeightLimit).filter(Objects::nonNull).reduce(BigDecimal.ZERO, BigDecimal::add);
|
||||
stockInOrderDO.setWeightLimit(weightLimit);
|
||||
@@ -467,13 +474,18 @@ public class ReserveStockInOrderDomainService {
|
||||
Long shipperId = reservationStockInOrder.getShipperId();
|
||||
String jsbz = reservationStockInOrderMapper.getJsbz(shipperId);
|
||||
reservationStockInOrder.setSettlementCurrency(jsbz);
|
||||
String inOrderNumber = reservationStockInOrder.getInOrderNumber();
|
||||
List<ReserveInMaterialDetail> materialDetailList = materialDetailService.list(new QueryWrapper<ReserveInMaterialDetail>().lambda().eq(ReserveInMaterialDetail::getInOrderNumber, inOrderNumber));
|
||||
String oldInOrderNumber = reservationStockInOrder.getInOrderNumber();
|
||||
// 生成新业务单号,防止与已生成的入库业务单号重复
|
||||
String newOrderNumber = reservationStockInOrderDomainService.generateReserveOrderNumber();
|
||||
reservationStockInOrder.setInOrderNumber(newOrderNumber);
|
||||
reservationStockInOrder.setBusinessOrderNo(newOrderNumber);
|
||||
List<ReserveInMaterialDetail> materialDetailList = materialDetailService.list(new QueryWrapper<ReserveInMaterialDetail>().lambda().eq(ReserveInMaterialDetail::getInOrderNumber, oldInOrderNumber));
|
||||
List<ReservationInMaterialDetail> inMaterialDetailList = new ArrayList<>();
|
||||
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;
|
||||
@@ -969,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;
|
||||
}
|
||||
|
||||
}
|
||||
+17
@@ -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<ReserveStockOutOr
|
||||
* 出库单提货单打印-明细
|
||||
*/
|
||||
List<ReserveOutMaterialDetailPO> queryOutStockNoticePrintDetail(ReserveStockOutOrderDO stockOutOrderDO);
|
||||
|
||||
int countByOrderNumberPrefix(@Param("prefix") String prefix);
|
||||
|
||||
List<String> generateReserveOrderNumber1(@Param("prefix") String prefix);
|
||||
|
||||
/**
|
||||
* 老系统数据导入:根据出库单号精确统计(防重)
|
||||
*/
|
||||
int countByOutOrderNumber(@Param("outOrderNumber") String outOrderNumber);
|
||||
|
||||
/**
|
||||
* 老系统数据导入:根据仓库类型查询仓库
|
||||
* @param warehouseType 仓库类型编码(如 "1"/"2")
|
||||
*/
|
||||
List<WarehousePO> getWarehouseByType(@Param("warehouseType") String warehouseType);
|
||||
}
|
||||
+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;
|
||||
}
|
||||
+247
@@ -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();
|
||||
@@ -1217,4 +1460,8 @@ public class ReserveStockOutOrderApplicationService {
|
||||
// 3. 拼接结果
|
||||
return datePart + randomPart;
|
||||
}
|
||||
|
||||
public String generateReserveOrderNumber() {
|
||||
return stockOutOrderDomainService.generateReserveOrderNumber();
|
||||
}
|
||||
}
|
||||
+31
-4
@@ -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<ReserveStockOutOrderDO> 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<ReserveOutMaterialDetail> materialDetailList = outMaterialDetailService.list(new QueryWrapper<ReserveOutMaterialDetail>().lambda().eq(ReserveOutMaterialDetail::getOutOrderNumber, outOrderNumber));
|
||||
List<ReserveOutMaterialDetail> materialDetailList = outMaterialDetailService.list(new QueryWrapper<ReserveOutMaterialDetail>().lambda().eq(ReserveOutMaterialDetail::getOutOrderNumber, oldOutOrderNumber));
|
||||
List<ReservationOutMaterialDetail> 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;
|
||||
}
|
||||
|
||||
}
|
||||
+12
@@ -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());
|
||||
}
|
||||
}
|
||||
+66
@@ -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<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);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
+5
-1
@@ -50,7 +50,9 @@ public class ReservationMaterialInventoryApi extends BaseController {
|
||||
@ApiOperation("查询物料库存列表")
|
||||
@GetMapping("/list")
|
||||
public TableDataInfo list(ReservationMaterialInventoryDTO materialInventoryDTO,
|
||||
@RequestParam(value = "customerName", required = false) String customerName)
|
||||
@RequestParam(value = "customerName", required = false) String customerName,
|
||||
@RequestParam(value = "expiryDateStart", required = false) String expiryDateStart,
|
||||
@RequestParam(value = "expiryDateEnd", required = false) String expiryDateEnd)
|
||||
{
|
||||
// 出库分配前端传的是客户名称 customerName,这里通过名称查询货主ID,使用精确匹配(不模糊匹配)
|
||||
String shipperName = null; // 保存查询到的货主名称
|
||||
@@ -78,6 +80,8 @@ public class ReservationMaterialInventoryApi extends BaseController {
|
||||
ReservationMaterialInventoryDO materialInventoryDO = materialInventoryAssembler.toDO(materialInventoryDTO);
|
||||
materialInventoryDO.setExpiryDateStr(materialInventoryDTO.getExpiryDate());
|
||||
materialInventoryDO.setProductionDateStr(materialInventoryDTO.getProductionDate());
|
||||
materialInventoryDO.setExpiryDateStart(expiryDateStart);
|
||||
materialInventoryDO.setExpiryDateEnd(expiryDateEnd);
|
||||
startPage();
|
||||
// 使用带批次属性的查询方法,批次属性值从库存表中获取
|
||||
List<ReservationMaterialInventoryPO> list = materialInventoryApplicationService.queryListWithBatchAttributes(materialInventoryDO);
|
||||
|
||||
+12
@@ -281,4 +281,16 @@ public class ReservationStockInOrderApi extends BaseController {
|
||||
return getDataTable(list);
|
||||
}
|
||||
|
||||
@ApiOperation("生成入库预约单号")
|
||||
@GetMapping("/generateOrderNumber")
|
||||
public AjaxResult generateOrderNumber() {
|
||||
return AjaxResult.success(stockInOrderApplicationService.generateReserveOrderNumber());
|
||||
}
|
||||
|
||||
@ApiOperation("生成入库预约单号/入库业务单号")
|
||||
@GetMapping("/generateOrderNumber1")
|
||||
public AjaxResult generateOrderNumber1() {
|
||||
return AjaxResult.success(stockInOrderApplicationService.generateReserveOrderNumber1());
|
||||
}
|
||||
|
||||
}
|
||||
+75
@@ -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,4 +260,75 @@ public class ReserveStockInOrderApi extends BaseController {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 老系统入库预约单数据导入(主表+明细两个Excel文件批量导入,按名称匹配基础数据)
|
||||
*/
|
||||
@ApiOperation("老系统入库预约单数据导入")
|
||||
@PostMapping("/importLegacy")
|
||||
public ResponseEntity<Map<String, Object>> importLegacyExcel(
|
||||
@RequestParam("orderFile") MultipartFile orderFile,
|
||||
@RequestParam("detailFile") MultipartFile detailFile) {
|
||||
try {
|
||||
List<LegacyReserveInOrderVO> orderList = ExcelParseUtil.parseLegacyOrderExcel(orderFile);
|
||||
List<LegacyReserveInDetailVO> detailList = ExcelParseUtil.parseLegacyDetailExcel(detailFile);
|
||||
|
||||
Map<String, Object> importResult = stockInOrderApplicationService.importLegacyData(orderList, detailList);
|
||||
|
||||
Map<String, Object> successResponse = new HashMap<>();
|
||||
successResponse.put("code", 200);
|
||||
successResponse.put("message", "老系统数据导入成功");
|
||||
successResponse.put("orderCount", importResult.get("orderCount"));
|
||||
successResponse.put("detailCount", importResult.get("detailCount"));
|
||||
if (importResult.containsKey("warnings")) {
|
||||
successResponse.put("warnings", importResult.get("warnings"));
|
||||
}
|
||||
return ResponseEntity.ok(successResponse);
|
||||
|
||||
} catch (ValidationException e) {
|
||||
// 数据验证失败响应
|
||||
log.warn("老系统数据导入校验失败: {}", e.getMessage());
|
||||
Map<String, Object> errorResponse = new HashMap<>();
|
||||
errorResponse.put("code", 400);
|
||||
errorResponse.put("message", "数据验证失败");
|
||||
errorResponse.put("errorDetails", e.getMessage());
|
||||
return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(errorResponse);
|
||||
|
||||
} catch (IOException e) {
|
||||
// 文件处理失败响应
|
||||
log.error("老系统数据导入文件处理失败", e);
|
||||
Map<String, Object> errorResponse = new HashMap<>();
|
||||
errorResponse.put("code", 500);
|
||||
errorResponse.put("message", "文件处理失败");
|
||||
errorResponse.put("errorDetails", e.getClass().getSimpleName() + ": " + e.getMessage());
|
||||
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(errorResponse);
|
||||
|
||||
} catch (Exception e) {
|
||||
// 其他未知错误响应:打印完整堆栈,把真正的报错信息报出来
|
||||
log.error("老系统数据导入发生未知异常", e);
|
||||
String errorType = e.getClass().getSimpleName();
|
||||
String errorMsg = e.getMessage() != null ? e.getMessage() : "无详细信息";
|
||||
// 如果异常带有 cause,则再追加 cause 信息,方便定位根因
|
||||
Throwable cause = e.getCause();
|
||||
StringBuilder detail = new StringBuilder();
|
||||
detail.append(errorType).append(": ").append(errorMsg);
|
||||
if (cause != null && cause != e) {
|
||||
detail.append(" | 根因: ").append(cause.getClass().getSimpleName()).append(": ").append(cause.getMessage());
|
||||
}
|
||||
Map<String, Object> errorResponse = new HashMap<>();
|
||||
errorResponse.put("code", 500);
|
||||
errorResponse.put("message", detail.toString());
|
||||
errorResponse.put("errorDetails", detail.toString());
|
||||
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(errorResponse);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成入库预约单号
|
||||
*/
|
||||
@ApiOperation("生成入库单号")
|
||||
@GetMapping("/generateOrderNumber")
|
||||
public AjaxResult generateOrderNumber() {
|
||||
return AjaxResult.success(stockInOrderApplicationService.generateReserveOrderNumber());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -17,16 +17,16 @@ spring:
|
||||
nacos:
|
||||
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.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.30:6848
|
||||
# server-addr: 10.33.0.129:6010
|
||||
server-addr: 10.102.192.30:6848
|
||||
username: nacos
|
||||
password: manhuoda@2023
|
||||
#线上正式环境
|
||||
|
||||
+6
@@ -650,4 +650,10 @@
|
||||
<update id="delWShOrderDetail">
|
||||
update "NGWL_TEST_WMS".RECEIPT_MATERIAL_DETAIL set DEL_FLAG = 2 where DEL_FLAG = 1 and RECEIPT_ORDER_NUMBER = #{receiptOrderNumber}
|
||||
</update>
|
||||
|
||||
<select id="countByOrderNumberPrefix" resultType="java.lang.Integer" parameterType="java.lang.String">
|
||||
SELECT COUNT(1)
|
||||
FROM execution_stock_in_order
|
||||
WHERE in_order_number LIKE concat(#{prefix}, '%')
|
||||
</select>
|
||||
</mapper>
|
||||
+5
@@ -475,4 +475,9 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
update "NGWL_TEST_WMS".out_material_detail set DEL_FLAG = 2 where DEL_FLAG = 1 and out_order_number = #{outOrderNumber}
|
||||
</update>
|
||||
|
||||
<select id="countByOrderNumberPrefix" resultType="java.lang.Integer" parameterType="java.lang.String">
|
||||
SELECT COUNT(1)
|
||||
FROM execution_stock_out_order
|
||||
WHERE out_order_number LIKE concat(#{prefix}, '%')
|
||||
</select>
|
||||
</mapper>
|
||||
+44
@@ -276,6 +276,12 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
<if test="productionDateStr != null and productionDateStr != ''">
|
||||
AND TO_CHAR(a.production_date, 'yyyy-MM-dd') = #{productionDateStr}
|
||||
</if>
|
||||
<if test="expiryDateStart != null and expiryDateStart != ''">
|
||||
and a.expiry_date >= #{expiryDateStart}
|
||||
</if>
|
||||
<if test="expiryDateEnd != null and expiryDateEnd != ''">
|
||||
and a.expiry_date <![CDATA[ < ]]> DATEADD(DAY, 1, #{expiryDateEnd})
|
||||
</if>
|
||||
</sql>
|
||||
|
||||
<select id="queryList" parameterType="com.mhd.oms.domain.reservationMaterialInventory.repository.todo.ReservationMaterialInventoryDO" resultMap="MaterialInventoryResult">
|
||||
@@ -330,6 +336,44 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
GROUP BY a.MATERIAL_BASE_INFO_ID
|
||||
</select>
|
||||
|
||||
<!-- 按物料+过期日期汇总 -->
|
||||
<select id="queryListByWlExpiry" parameterType="com.mhd.oms.domain.reservationMaterialInventory.repository.todo.ReservationMaterialInventoryDO" resultMap="MaterialInventoryResult">
|
||||
select
|
||||
a.material_base_info_id, a.expiry_date, a.shipper_id, a.shipper_code, a.shipper_name,
|
||||
a.organization_id, a.organization_name, a.top_organization_id,
|
||||
MAX(a.warehouse_id) AS warehouse_id, MAX(a.warehouse_code) AS warehouse_code, MAX(a.warehouse_name) AS warehouse_name,
|
||||
MAX(a.storage_section_id) AS storage_section_id, MAX(a.storage_code) AS storage_code, MAX(a.storage_name) AS storage_name,
|
||||
MAX(a.storage_location_id) AS storage_location_id, MAX(a.storage_location_code) AS storage_location_code, MAX(a.storage_location_name) AS storage_location_name,
|
||||
MAX(a.batch_number) AS batch_number, MAX(a.material_status_code) AS material_status_code, MAX(a.material_status_name) AS material_status_name,
|
||||
MAX(a.container_id) AS container_id, MAX(a.container_code) AS container_code, MAX(a.container_type) AS container_type, MAX(a.container_type_name) AS container_type_name,
|
||||
IFNULL(SUM(a.freeze_quantity), 0) AS freeze_quantity, a.is_able,
|
||||
IFNULL(SUM(a.inventory_quantity), 0) AS inventory_quantity,
|
||||
IFNULL(SUM(a.allocation_quantity), 0) AS allocation_quantity,
|
||||
IFNULL(SUM(a.area), 0) AS area,
|
||||
IFNULL(SUM(a.NET_WEIGHT), 0) AS NET_WEIGHT,
|
||||
IFNULL(SUM(a.GROSS_WEIGHT), 0) AS GROSS_WEIGHT,
|
||||
IFNULL(SUM(a.VOLUME), 0) AS VOLUME,
|
||||
MAX(a.unit) AS unit,
|
||||
MAX(a.unit_name) AS unit_name,
|
||||
MAX(a.production_date) AS production_date,
|
||||
MAX(a.inventory_date) AS inventory_date,
|
||||
MAX(a.batch_ref_no) AS batch_ref_no, MAX(a.sheet_ref_no) AS sheet_ref_no, MAX(a.box_pallet_no) AS box_pallet_no,
|
||||
MAX(a.bar_code) AS inv_bar_code,
|
||||
MAX(a.in_order_number) AS in_order_number, MAX(a.lot_number) AS lot_number,
|
||||
b.material_code, b.material_name,
|
||||
CASE WHEN IFNULL(SUM(a.inventory_quantity), 0) = 0 THEN 1 ELSE 0 END AS sort_order
|
||||
from reservation_material_inventory a
|
||||
left join NGWL_TEST_WMS.material_base_info b on a.material_base_info_id = b.material_base_info_id
|
||||
<where>
|
||||
<include refid="selectMaterialInventoryPo1"/>
|
||||
<include refid="JoinMaterialBaseInfoPoWhere"/>
|
||||
</where>
|
||||
GROUP BY a.MATERIAL_BASE_INFO_ID, a.EXPIRY_DATE, a.shipper_id, a.shipper_code, a.shipper_name,
|
||||
a.organization_id, a.organization_name, a.top_organization_id,
|
||||
b.material_code, b.material_name
|
||||
order by sort_order, MAX(a.update_time) desc
|
||||
</select>
|
||||
|
||||
<select id="queryListByHz" parameterType="com.mhd.oms.domain.reservationMaterialInventory.repository.todo.ReservationMaterialInventoryDO" resultMap="MaterialInventoryResult">
|
||||
select
|
||||
<include refid="selectMaterialInventoryPo"/>
|
||||
|
||||
+22
-4
@@ -519,21 +519,27 @@
|
||||
<select id="getByName" parameterType="java.lang.String" resultType="com.mhd.oms.domain.reservationStockInOrder.repository.po.MaterialBaseInfoPO">
|
||||
select * from "NGWL_TEST_WMS".MATERIAL_BASE_INFO where 1 = 1 and DEL_FLAG = 1 and MATERIAL_NAME = #{name}
|
||||
</select>
|
||||
<select id="getByCode" parameterType="java.lang.String" resultType="com.mhd.oms.domain.reservationStockInOrder.repository.po.MaterialBaseInfoPO">
|
||||
select * from "NGWL_TEST_WMS".MATERIAL_BASE_INFO where 1 = 1 and DEL_FLAG = 1 and MATERIAL_CODE = #{code}
|
||||
<select id="getByCode" resultType="com.mhd.oms.domain.reservationStockInOrder.repository.po.MaterialBaseInfoPO">
|
||||
select * from "NGWL_TEST_WMS".MATERIAL_BASE_INFO where 1 = 1 and DEL_FLAG = 1 and MATERIAL_CODE = #{code} and ORGANIZATION_ID = #{orgId}
|
||||
</select>
|
||||
<select id="getMaterialBaseInfoList" parameterType="java.lang.String" resultType="com.mhd.oms.domain.reservationStockInOrder.repository.po.MaterialBaseInfoPO">
|
||||
select * from "NGWL_TEST_WMS".MATERIAL_BASE_INFO where 1 = 1 and DEL_FLAG = 1 and material_code = #{id}
|
||||
</select>
|
||||
|
||||
<select id="getInfoByMaterialBaseInfoIds" parameterType="java.lang.Long" resultType="com.mhd.oms.domain.reservationStockInOrder.repository.po.MaterialWarehouseControlPO">
|
||||
<!-- <select id="getkcId" resultType="com.mhd.oms.domain.reservationMaterialInventory.repository.po.ReservationMaterialInventoryPO">-->
|
||||
<!-- select * from "NGWL_TEST_WMS".MATERIAL_INVENTORY where 1 = 1 and DEL_FLAG = 1 and MATERIAL_BASE_INFO_ID = #{id} and ALLOCATION_QUANTITY >= #{q}-->
|
||||
<!-- </select>-->
|
||||
|
||||
<select id="getInfoByMaterialBaseInfoIds" resultType="com.mhd.oms.domain.reservationStockInOrder.repository.po.MaterialWarehouseControlPO">
|
||||
select * from "NGWL_TEST_WMS".MATERIAL_WAREHOUSE_CONTROL where 1 = 1 and DEL_FLAG = 1 and MATERIAL_BASE_INFO_ID = #{id}
|
||||
</select>
|
||||
|
||||
<select id="getGoodsInfoByMaterialBaseInfoIds" parameterType="java.lang.Long" resultType="com.mhd.oms.domain.reservationStockInOrder.repository.po.MaterialGoodsRulePO">
|
||||
select * from "NGWL_TEST_WMS".MATERIAL_GOODS_RULE where 1 = 1 and DEL_FLAG = 1 and MATERIAL_BASE_INFO_ID = #{id}
|
||||
</select>
|
||||
|
||||
<select id="getkcId" resultType="com.mhd.oms.domain.reservationMaterialInventory.repository.po.ReservationMaterialInventoryPO">
|
||||
select * from "NGWL_TEST_WMS".MATERIAL_INVENTORY where 1 = 1 and DEL_FLAG = 1 and MATERIAL_BASE_INFO_ID = #{id} and ALLOCATION_QUANTITY >= #{q}
|
||||
</select>
|
||||
<select id="getUserNcCode" parameterType="java.lang.Long" resultType="java.lang.String">
|
||||
select CUSTOMER_NC_CODE from "NGWL_TEST_USER".USER_SHIPPER where 1 = 1 and DEL_FLAG = 1 and USER_ID = #{id} limit 1
|
||||
</select>
|
||||
@@ -649,4 +655,16 @@
|
||||
<select id="getCustomerOrgCode" resultType="java.lang.String">
|
||||
select ORG_CODE from "NGWL_TEST_USER".USER_SHIPPER where 1 = 1 and DEL_FLAG = 1 and USER_ID = #{id}
|
||||
</select>
|
||||
|
||||
<select id="countByOrderNumberPrefix" resultType="java.lang.Integer" parameterType="java.lang.String">
|
||||
SELECT COUNT(1)
|
||||
FROM reservation_stock_in_order
|
||||
WHERE in_order_number LIKE concat(#{prefix}, '%')
|
||||
</select>
|
||||
|
||||
<select id="generateReserveOrderNumber1" resultType="java.lang.String">
|
||||
select in_order_number
|
||||
FROM reservation_stock_in_order
|
||||
WHERE in_order_number LIKE concat(#{prefix}, '%')
|
||||
</select>
|
||||
</mapper>
|
||||
+10
@@ -470,4 +470,14 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
select max(user_id) as user_id from NGWL_TEST_USER."USER" where ORGANIZATION_ID = #{organizationId} and USER_MEMBER_CODE = #{userMemberCode} and DEL_FLAG = 1
|
||||
</select>
|
||||
|
||||
<select id="countByOrderNumberPrefix" resultType="java.lang.Integer" parameterType="java.lang.String">
|
||||
SELECT COUNT(1)
|
||||
FROM reservation_stock_out_order
|
||||
WHERE out_order_number LIKE concat(#{prefix}, '%')
|
||||
</select>
|
||||
<select id="generateReserveOrderNumber1" resultType="java.lang.String">
|
||||
SELECT out_order_number
|
||||
FROM reservation_stock_out_order
|
||||
WHERE out_order_number LIKE concat(#{prefix}, '%')
|
||||
</select>
|
||||
</mapper>
|
||||
@@ -777,4 +777,58 @@
|
||||
AND USER_ID = #{id} limit 1
|
||||
</select>
|
||||
|
||||
<select id="countByOrderNumberPrefix" resultType="java.lang.Integer" parameterType="java.lang.String">
|
||||
SELECT COUNT(1)
|
||||
FROM reserve_stock_in_order
|
||||
WHERE in_order_number LIKE concat(#{prefix}, '%')
|
||||
</select>
|
||||
<select id="generateReserveOrderNumber1" resultType="java.lang.String">
|
||||
SELECT in_order_number
|
||||
FROM reserve_stock_in_order
|
||||
WHERE in_order_number LIKE concat(#{prefix}, '%')
|
||||
</select>
|
||||
|
||||
<!-- 老系统数据导入:根据货主名称查询用户 -->
|
||||
<select id="getShipperByName" parameterType="java.lang.String" resultType="com.mhd.common.core.domain.po.UserPo">
|
||||
select USER_ID, USER_NAME, ORGANIZATION_ID, ORGANIZATION_NAME, TOP_ORGANIZATION_ID
|
||||
from NGWL_TEST_USER."USER"
|
||||
where DEL_FLAG = 1 and USER_NAME = #{name}
|
||||
</select>
|
||||
|
||||
<!-- 老系统数据导入:根据仓库名称查询仓库(支持模糊匹配,如Excel中"凍倉-陳美玲"匹配系统中"凍倉") -->
|
||||
<select id="getWarehouseByName" parameterType="java.lang.String" resultType="com.mhd.common.core.domain.po.WarehousePO">
|
||||
select WAREHOUSE_ID, WAREHOUSE_CODE, WAREHOUSE_NAME
|
||||
from "NGWL_TEST_SYSTEM".WAREHOUSE
|
||||
where DEL_FLAG = 1
|
||||
and (
|
||||
WAREHOUSE_NAME = #{name}
|
||||
or #{name} LIKE ('%' || WAREHOUSE_NAME || '%')
|
||||
)
|
||||
order by case when WAREHOUSE_NAME = #{name} then 0 else 1 end,
|
||||
length(WAREHOUSE_NAME) asc
|
||||
</select>
|
||||
|
||||
<!-- 老系统数据导入:根据仓库类型查询仓库(1=干仓 2=冬仓) -->
|
||||
<select id="getWarehouseByType" parameterType="java.lang.String" resultType="com.mhd.common.core.domain.po.WarehousePO">
|
||||
select WAREHOUSE_ID, WAREHOUSE_CODE, WAREHOUSE_NAME
|
||||
from "NGWL_TEST_SYSTEM".WAREHOUSE
|
||||
where DEL_FLAG = 1
|
||||
and (
|
||||
WAREHOUSE_TYPE = #{warehouseType}
|
||||
or WAREHOUSE_TYPE_NAME = case when #{warehouseType} = '1' then '干仓' when #{warehouseType} = '2' then '冻仓' else null end
|
||||
)
|
||||
</select>
|
||||
|
||||
<!-- 老系统数据导入:根据货主用户ID查询NC客户编码 -->
|
||||
<select id="getCustomerNcCodeByUserId" parameterType="java.lang.Long" resultType="java.lang.String">
|
||||
select CUSTOMER_NC_CODE from "NGWL_TEST_USER".USER_SHIPPER where DEL_FLAG = 1 and USER_ID = #{id} limit 1
|
||||
</select>
|
||||
|
||||
<!-- 老系统数据导入:根据入库单号精确统计(防重) -->
|
||||
<select id="countByInOrderNumber" resultType="java.lang.Integer" parameterType="java.lang.String">
|
||||
SELECT COUNT(1)
|
||||
FROM reserve_stock_in_order
|
||||
WHERE in_order_number = #{inOrderNumber}
|
||||
</select>
|
||||
|
||||
</mapper>
|
||||
@@ -517,4 +517,35 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
<result property="boxPalletNo" column="box_pallet_no"/>
|
||||
</resultMap>
|
||||
|
||||
<select id="countByOrderNumberPrefix" resultType="java.lang.Integer" parameterType="java.lang.String">
|
||||
SELECT COUNT(1)
|
||||
FROM reserve_stock_out_order
|
||||
WHERE out_order_number LIKE concat(#{prefix}, '%')
|
||||
</select>
|
||||
<select id="generateReserveOrderNumber1" resultType="java.lang.String">
|
||||
SELECT out_order_number
|
||||
FROM reserve_stock_out_order
|
||||
WHERE out_order_number LIKE concat(#{prefix}, '%')
|
||||
</select>
|
||||
|
||||
<!-- 老系统数据导入:根据出库单号精确统计(防重) -->
|
||||
<select id="countByOutOrderNumber" resultType="java.lang.Integer" parameterType="java.lang.String">
|
||||
SELECT COUNT(1)
|
||||
FROM reserve_stock_out_order
|
||||
WHERE out_order_number = #{outOrderNumber}
|
||||
</select>
|
||||
|
||||
<!-- 老系统数据导入:根据仓库类型查询仓库
|
||||
老系统仓库类型 1=干仓 2=冬仓;新系统 WAREHOUSE_TYPE 为数据字典编码
|
||||
同时尝试匹配 WAREHOUSE_TYPE 编码和 WAREHOUSE_TYPE_NAME 名称,兼容字典值与老系统编码一致或不一致两种情况 -->
|
||||
<select id="getWarehouseByType" parameterType="java.lang.String" resultType="com.mhd.common.core.domain.po.WarehousePO">
|
||||
select WAREHOUSE_ID, WAREHOUSE_CODE, WAREHOUSE_NAME
|
||||
from "NGWL_TEST_SYSTEM".WAREHOUSE
|
||||
where DEL_FLAG = 1
|
||||
and (
|
||||
WAREHOUSE_TYPE = #{warehouseType}
|
||||
or WAREHOUSE_TYPE_NAME = case when #{warehouseType} = '1' then '干仓' when #{warehouseType} = '2' then '冻仓' else null end
|
||||
)
|
||||
</select>
|
||||
|
||||
</mapper>
|
||||
@@ -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"
|
||||
|
||||
+66
-18
@@ -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<Map<String, Object>> listNc = null;
|
||||
@@ -433,8 +443,47 @@ public class MaterialBaseInfoApplicationService {
|
||||
return materialBaseInfoDomainService.getInfoByNoOrderReceipt(materialBaseInfoDO);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 导入物料主数据(仅导入主表字段)
|
||||
* 导入物料主数据(异步入口)
|
||||
*
|
||||
* <p>接口层调用此方法,将文件保存到临时目录后立即返回"异步处理中",
|
||||
* 实际导入由 {@link #doImportData(File, String, LoginUser)} 异步执行,
|
||||
* 避免大数据量时接口超时。</p>
|
||||
*/
|
||||
public AjaxResult importDataAsync(MultipartFile file) {
|
||||
if (file == null || file.isEmpty()) {
|
||||
throw new ServiceException("上传文件不能为空");
|
||||
}
|
||||
String fileName = file.getOriginalFilename();
|
||||
if (org.apache.commons.lang3.StringUtils.isBlank(fileName)
|
||||
|| (!fileName.endsWith(".xls") && !fileName.endsWith(".xlsx"))) {
|
||||
throw new ServiceException("请上传xls或xlsx格式文件");
|
||||
}
|
||||
|
||||
// 流式写入临时文件,避免大文件 getBytes() 导致内存溢出和接口超时
|
||||
String tmpDir = System.getProperty("java.io.tmpdir") + File.separator + "material_import";
|
||||
File dir = new File(tmpDir);
|
||||
if (!dir.exists()) {
|
||||
dir.mkdirs();
|
||||
}
|
||||
String tmpFileName = System.currentTimeMillis() + "_" + fileName;
|
||||
File tmpFile = new File(dir, tmpFileName);
|
||||
try {
|
||||
file.transferTo(tmpFile);
|
||||
} catch (Exception e) {
|
||||
throw new ServiceException("文件保存失败:" + e.getMessage());
|
||||
}
|
||||
|
||||
LoginUser loginUser = SecurityUtils.getLoginUser();
|
||||
// 通过独立的异步 Service 执行导入(避免类内部 self-invocation 导致 @Async 失效)
|
||||
materialBaseInfoAsyncService.doImportData(tmpFile, fileName, loginUser);
|
||||
|
||||
return AjaxResult.success("导入任务已提交,正在后台异步处理,请稍后查看导入结果日志");
|
||||
}
|
||||
|
||||
/**
|
||||
* 导入物料主数据(仅导入主表字段)- 原同步方法保留,供其他场景调用
|
||||
*/
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
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<MaterialBarCodeDO> buildImportBarCodeList(MaterialBaseInfoDTO row) {
|
||||
public List<MaterialBarCodeDO> 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<Map<String, Object>> extractTableDataRows(Map<String, Object> resultMap) {
|
||||
public List<Map<String, Object>> extractTableDataRows(Map<String, Object> resultMap) {
|
||||
if (resultMap == null) {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
|
||||
+274
@@ -0,0 +1,274 @@
|
||||
package com.mhd.wms.application.service.materialBaseInfo;
|
||||
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.alibaba.fastjson.TypeReference;
|
||||
import com.alibaba.fastjson2.JSONObject;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.mhd.common.core.domain.po.UserPo;
|
||||
import com.mhd.common.core.web.domain.AjaxResult;
|
||||
import com.mhd.system.api.SystemServiceFeign;
|
||||
import com.mhd.system.api.UserServiceFeign;
|
||||
import com.mhd.system.api.model.LoginUser;
|
||||
import com.mhd.wms.domain.materialBarCode.service.MaterialBarCodeDomainService;
|
||||
import com.mhd.wms.domain.materialBaseInfo.entity.MaterialBaseInfo;
|
||||
import com.mhd.wms.domain.materialBaseInfo.repository.facade.IMaterialBaseInfoService;
|
||||
import com.mhd.wms.domain.materialBaseInfo.repository.mapper.MaterialBaseInfoMapper;
|
||||
import com.mhd.wms.domain.materialBaseInfo.repository.todo.MaterialBaseInfoDO;
|
||||
import com.mhd.wms.domain.materialBaseInfo.service.MaterialBaseInfoDomainService;
|
||||
import com.mhd.wms.domain.materialGoodsRule.service.MaterialGoodsRuleDomainService;
|
||||
import com.mhd.wms.domain.materialCommon.service.MaterialCommonDomainService;
|
||||
import com.mhd.wms.domain.materialCommon.repository.todo.MaterialCommonDO;
|
||||
import com.mhd.wms.domain.materialInventoryWarning.service.MaterialInventoryWarningDomainService;
|
||||
import com.mhd.wms.domain.materialWarehouseControl.service.MaterialWarehouseControlDomainService;
|
||||
import com.mhd.wms.domain.materialWarehouseControl.repository.todo.MaterialWarehouseControlDO;
|
||||
import com.mhd.wms.interfaces.dto.materialBaseInfo.MaterialBaseInfoDTO;
|
||||
import com.mhd.wms.util.MaterialBaseInfoImportExcelUtil;
|
||||
import com.mhd.wms.util.ZhTextNormalizeUtil;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.beans.BeanUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.scheduling.annotation.Async;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.InputStream;
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* 物料主数据异步导入服务
|
||||
*/
|
||||
@Slf4j
|
||||
@Service
|
||||
public class MaterialBaseInfoAsyncService {
|
||||
|
||||
@Autowired
|
||||
private IMaterialBaseInfoService materialBaseInfoService;
|
||||
@Autowired
|
||||
private MaterialBaseInfoMapper materialBaseInfoMapper;
|
||||
@Autowired
|
||||
private SystemServiceFeign systemServiceFeign;
|
||||
@Autowired
|
||||
private UserServiceFeign userServiceFeign;
|
||||
@Autowired
|
||||
private MaterialCommonDomainService materialCommonDomainService;
|
||||
@Autowired
|
||||
private MaterialWarehouseControlDomainService materialWarehouseControlDomainService;
|
||||
@Autowired
|
||||
private MaterialInventoryWarningDomainService materialInventoryWarningDomainService;
|
||||
@Autowired
|
||||
private MaterialBarCodeDomainService materialBarCodeDomainService;
|
||||
@Autowired
|
||||
private MaterialBaseInfoDomainService materialBaseInfoDomainService;
|
||||
@Autowired
|
||||
private com.mhd.wms.domain.materialGoodsRule.service.MaterialGoodsRuleDomainService materialGoodsRuleDomainService;
|
||||
@org.springframework.context.annotation.Lazy
|
||||
@Autowired
|
||||
private MaterialBaseInfoApplicationService materialBaseInfoApplicationService;
|
||||
|
||||
@Async
|
||||
public void doImportData(File tmpFile, String fileName, LoginUser loginUser) {
|
||||
long startTime = System.currentTimeMillis();
|
||||
log.info("=== 物料主数据异步导入开始,文件:{},大小:{}KB ===", fileName, tmpFile.length() / 1024);
|
||||
try {
|
||||
List<MaterialBaseInfoDTO> rows;
|
||||
try (InputStream is = new FileInputStream(tmpFile)) {
|
||||
rows = MaterialBaseInfoImportExcelUtil.importRows(is);
|
||||
} catch (Exception e) {
|
||||
log.error("物料主数据异步导入失败 - 文件解析异常:{}", e.getMessage(), e);
|
||||
return;
|
||||
}
|
||||
if (CollectionUtils.isEmpty(rows)) {
|
||||
log.warn("物料主数据异步导入结束 - 导入数据为空");
|
||||
return;
|
||||
}
|
||||
|
||||
Long loginOrgId = null;
|
||||
Long loginTopOrgId = null;
|
||||
if (loginUser != null && loginUser.getUserPo() != null) {
|
||||
loginOrgId = loginUser.getUserPo().getOrganizationId();
|
||||
loginTopOrgId = loginUser.getUserPo().getTopOrganizationId();
|
||||
}
|
||||
|
||||
StringBuilder errors = new StringBuilder();
|
||||
Set<String> duplicateInFile = new HashSet<>();
|
||||
int successCount = 0;
|
||||
int totalCount = rows.size();
|
||||
Map<String, Map<String, Object>> packCache = new HashMap<>();
|
||||
|
||||
for (int i = 0; i < rows.size(); i++) {
|
||||
MaterialBaseInfoDTO row = rows.get(i);
|
||||
int rowNum = i + 2;
|
||||
if (row == null) {
|
||||
continue;
|
||||
}
|
||||
try {
|
||||
if (StringUtils.isBlank(row.getMaterialCode())) {
|
||||
errors.append("第").append(rowNum).append("行:物料编码不能为空;");
|
||||
continue;
|
||||
}
|
||||
if (StringUtils.isBlank(row.getMaterialName())) {
|
||||
errors.append("第").append(rowNum).append("行:物料名称不能为空;");
|
||||
continue;
|
||||
}
|
||||
if (row.getNullify() == null) {
|
||||
row.setNullify(2);
|
||||
}
|
||||
if (row.getCommon() == null) {
|
||||
row.setCommon(2);
|
||||
}
|
||||
if (StringUtils.isBlank(row.getHsCode()) && StringUtils.isNotBlank(row.getHsCodeImport())) {
|
||||
row.setHsCode(row.getHsCodeImport().trim());
|
||||
}
|
||||
materialBaseInfoApplicationService.normalizeImportBarCodeWhenDuplicateOfHs(row);
|
||||
materialBaseInfoApplicationService.fillIdsFromExistingMasterData(row);
|
||||
materialBaseInfoApplicationService.fillOrganizationFromShipperIfNeeded(row);
|
||||
if (!isValidOrgId(row.getOrganizationId()) && isValidOrgId(loginOrgId)) {
|
||||
row.setOrganizationId(loginOrgId);
|
||||
}
|
||||
if (row.getTopOrganizationId() == null && isValidOrgId(loginTopOrgId)) {
|
||||
row.setTopOrganizationId(loginTopOrgId);
|
||||
}
|
||||
materialBaseInfoApplicationService.fillOrganizationName(row, loginUser);
|
||||
|
||||
String shipperCode = StringUtils.defaultString(row.getShipperCode(), "");
|
||||
String duplicateKey = row.getOrganizationId() + "|" + shipperCode + "|" + row.getMaterialCode();
|
||||
if (!duplicateInFile.add(duplicateKey)) {
|
||||
errors.append("第").append(rowNum).append("行:文件内存在重复物料;");
|
||||
continue;
|
||||
}
|
||||
|
||||
LambdaQueryWrapper<MaterialBaseInfo> wrapper = new LambdaQueryWrapper<MaterialBaseInfo>()
|
||||
.eq(MaterialBaseInfo::getDelFlag, 1)
|
||||
.eq(MaterialBaseInfo::getOrganizationId, row.getOrganizationId())
|
||||
.eq(MaterialBaseInfo::getMaterialCode, row.getMaterialCode());
|
||||
if (StringUtils.isBlank(row.getShipperCode())) {
|
||||
wrapper.and(w -> w.isNull(MaterialBaseInfo::getShipperCode).or().eq(MaterialBaseInfo::getShipperCode, ""));
|
||||
} else {
|
||||
wrapper.eq(MaterialBaseInfo::getShipperCode, row.getShipperCode());
|
||||
}
|
||||
if (materialBaseInfoService.count(wrapper) > 0) {
|
||||
errors.append("第").append(rowNum).append("行:物料已存在;");
|
||||
continue;
|
||||
}
|
||||
materialBaseInfoApplicationService.fillClassifyTypeAndUnit(row);
|
||||
|
||||
// 包装规格查询(带缓存)
|
||||
String packCacheKey = row.getOrganizationId() + "|" + StringUtils.defaultString(row.getPackName());
|
||||
Map<String, Object> cachedPack = packCache.get(packCacheKey);
|
||||
if (cachedPack == null) {
|
||||
Object result = systemServiceFeign.getPackList(null, row.getPackName(), row.getOrganizationId());
|
||||
if (result == null) {
|
||||
packCache.put(packCacheKey, Collections.emptyMap());
|
||||
errors.append("第").append(rowNum).append("行:包装规格查询无返回;");
|
||||
continue;
|
||||
}
|
||||
Map<String, Object> resultMap = JSON.parseObject(JSONObject.toJSONString(result), new TypeReference<Map<String, Object>>() {});
|
||||
List<Map<String, Object>> rowsPack = extractTableDataRows(resultMap);
|
||||
if (CollectionUtils.isEmpty(rowsPack)) {
|
||||
packCache.put(packCacheKey, Collections.emptyMap());
|
||||
errors.append("第").append(rowNum).append("行:包装规格不存在;");
|
||||
continue;
|
||||
}
|
||||
cachedPack = rowsPack.get(0);
|
||||
packCache.put(packCacheKey, cachedPack);
|
||||
}
|
||||
if (cachedPack.isEmpty()) {
|
||||
errors.append("第").append(rowNum).append("行:包装规格不存在(缓存);");
|
||||
continue;
|
||||
}
|
||||
String packCode = cachedPack.get("packCode") == null ? "" : String.valueOf(cachedPack.get("packCode"));
|
||||
row.setPackCode(packCode);
|
||||
String packId = cachedPack.get("packId") == null ? "" : String.valueOf(cachedPack.get("packId"));
|
||||
if (StringUtils.isBlank(packId) || !StringUtils.isNumeric(packId)) {
|
||||
errors.append("第").append(rowNum).append("行:包装规格数据异常;");
|
||||
continue;
|
||||
}
|
||||
row.setPackId(Long.valueOf(packId));
|
||||
String unitName = cachedPack.get("unitName") == null ? "" : String.valueOf(cachedPack.get("unitName"));
|
||||
row.setUnitCode("EA");
|
||||
row.setUnitName(unitName);
|
||||
|
||||
MaterialBaseInfoDO materialBaseInfoDO = new MaterialBaseInfoDO();
|
||||
BeanUtils.copyProperties(row, materialBaseInfoDO);
|
||||
materialBaseInfoDO.setMaterialGoodsRule(materialBaseInfoApplicationService.buildImportMaterialGoodsRule(row));
|
||||
materialBaseInfoDO.setMaterialCommon(null);
|
||||
materialBaseInfoDO.setMaterialWarehouseControl(null);
|
||||
materialBaseInfoDO.setMaterialBarCodeList(materialBaseInfoApplicationService.buildImportBarCodeList(row));
|
||||
// 补全创建人信息(异步线程没有 SecurityContext,用 loginUser)
|
||||
if (loginUser != null) {
|
||||
materialBaseInfoDO.setCreateBy(loginUser.getUserid());
|
||||
materialBaseInfoDO.setCreateByName(loginUser.getUsername());
|
||||
}
|
||||
materialBaseInfoDO.setCreateTime(new Date());
|
||||
// 调用原 ApplicationService 的 insert,走完整的插入逻辑(含商品规则、公共信息、NC编码等)
|
||||
materialBaseInfoApplicationService.insert(materialBaseInfoDO);
|
||||
successCount++;
|
||||
} catch (Exception e) {
|
||||
log.error("物料主数据异步导入 - 第{}行处理异常", rowNum, e);
|
||||
errors.append("第").append(rowNum).append("行:处理异常-").append(e.getMessage()).append(";");
|
||||
}
|
||||
}
|
||||
|
||||
long costTime = System.currentTimeMillis() - startTime;
|
||||
if (errors.length() > 0) {
|
||||
log.warn("=== 物料主数据异步导入完成,文件:{},总数:{},成功:{},失败:{},耗时:{}ms,失败原因:{} ===",
|
||||
fileName, totalCount, successCount, totalCount - successCount, costTime, errors);
|
||||
} else {
|
||||
log.info("=== 物料主数据异步导入完成,文件:{},总数:{},成功:{},耗时:{}ms ===",
|
||||
fileName, totalCount, successCount, costTime);
|
||||
}
|
||||
} finally {
|
||||
try {
|
||||
if (tmpFile.exists()) {
|
||||
tmpFile.delete();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.warn("物料主数据异步导入 - 临时文件清理失败:{}", e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ====== 以下工具方法 ======
|
||||
|
||||
private List<Map<String, Object>> extractTableDataRows(Map<String, Object> resultMap) {
|
||||
if (resultMap == null) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
Object data = resultMap.get("data");
|
||||
if (data == null) {
|
||||
data = resultMap.get("rows");
|
||||
}
|
||||
if (data instanceof List) {
|
||||
@SuppressWarnings("unchecked")
|
||||
List<Map<String, Object>> list = (List<Map<String, Object>>) data;
|
||||
return list;
|
||||
}
|
||||
if (data instanceof Map) {
|
||||
@SuppressWarnings("unchecked")
|
||||
Map<String, Object> dataMap = (Map<String, Object>) data;
|
||||
Object innerData = dataMap.get("data");
|
||||
if (innerData instanceof List) {
|
||||
@SuppressWarnings("unchecked")
|
||||
List<Map<String, Object>> list = (List<Map<String, Object>>) innerData;
|
||||
return list;
|
||||
}
|
||||
Object rows = dataMap.get("rows");
|
||||
if (rows instanceof List) {
|
||||
@SuppressWarnings("unchecked")
|
||||
List<Map<String, Object>> list = (List<Map<String, Object>>) rows;
|
||||
return list;
|
||||
}
|
||||
}
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
private boolean isValidOrgId(Long id) {
|
||||
return id != null && id > 0;
|
||||
}
|
||||
}
|
||||
+1
@@ -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;
|
||||
|
||||
+11
@@ -290,6 +290,17 @@ public class ShiftManageApplicationService {
|
||||
return shiftManageDomainService.taskDistribution(shiftManageDO);
|
||||
}
|
||||
|
||||
/**
|
||||
* @description 撤回审核
|
||||
* @author gen
|
||||
* @date 2026/7/17
|
||||
* @param shiftManageDO
|
||||
* @return Boolean
|
||||
*/
|
||||
public Boolean revokeAudit(ShiftManageDO shiftManageDO) {
|
||||
return shiftManageDomainService.revokeAudit(shiftManageDO);
|
||||
}
|
||||
|
||||
/**
|
||||
* 物料移位(PDA),与收货、上架一致:支持 getInfoByApp 的 parent_copy 结构及分批移位
|
||||
* 按单移位:PDA 仅传 shiftManageId、updateTime 时,自动从库中带出该单下所有待移位明细,默认 shiftQuantity=quantity
|
||||
|
||||
+65
-3
@@ -545,9 +545,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
@@ -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()));
|
||||
}
|
||||
|
||||
+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的单位名称)
|
||||
|
||||
+2
@@ -32,6 +32,8 @@ public interface MaterialInventoryMapper extends BaseMapper<MaterialInventory>
|
||||
public List<MaterialInventoryPO> queryListByKw(MaterialInventoryDO materialInventoryDO);
|
||||
//查物料库存列表-物料
|
||||
public List<MaterialInventoryPO> queryListByWl(MaterialInventoryDO materialInventoryDO);
|
||||
//查物料库存列表-物料+过期日期
|
||||
public List<MaterialInventoryPO> queryListByWlExpiry(MaterialInventoryDO materialInventoryDO);
|
||||
//查物料库存列表-货主
|
||||
public List<MaterialInventoryPO> queryListByHz(MaterialInventoryDO materialInventoryDO);
|
||||
//查物料库存列表-货主+物料(同一物料在不同货主下各一行)
|
||||
|
||||
+8
-1
@@ -85,6 +85,8 @@ public class MaterialInventoryImpl extends ServiceImpl<MaterialInventoryMapper,
|
||||
return materialInventoryMapper.queryListByKw(materialInventoryDO);
|
||||
} else if ("wlkw".equals(queryRule)) {
|
||||
return materialInventoryMapper.queryListByWlKw(materialInventoryDO);
|
||||
} else if ("wlExpiry".equals(queryRule)) {
|
||||
return materialInventoryMapper.queryListByWlExpiry(materialInventoryDO);
|
||||
} else if ("all".equals(queryRule)) {
|
||||
return materialInventoryMapper.queryList(materialInventoryDO);
|
||||
} else {
|
||||
@@ -817,7 +819,12 @@ public class MaterialInventoryImpl extends ServiceImpl<MaterialInventoryMapper,
|
||||
materialInventory.setNetWeight(netWeight);
|
||||
materialInventory.setMaterialBaseInfoId(materialInventoryParamDO.getMaterialBaseInfoId());
|
||||
materialInventory.setInOrderNumber(materialInventoryParamDO.getInOrderNumber());
|
||||
if (materialBaseInfo != null) {
|
||||
// 优先使用上游传入的货主信息(如来自上架单),否则再从物料基础信息兜底
|
||||
if (materialInventoryParamDO.getShipperId() != null) {
|
||||
materialInventory.setShipperId(materialInventoryParamDO.getShipperId());
|
||||
materialInventory.setShipperName(materialInventoryParamDO.getShipperName());
|
||||
materialInventory.setShipperCode(materialInventoryParamDO.getShipperCode());
|
||||
} else if (materialBaseInfo != null) {
|
||||
materialInventory.setShipperId(materialBaseInfo.getShipperId());
|
||||
materialInventory.setShipperName(materialBaseInfo.getShipperName());
|
||||
materialInventory.setShipperCode(materialBaseInfo.getShipperCode());
|
||||
|
||||
@@ -2,6 +2,8 @@ package com.mhd.wms.domain.reviewOrder.repository.po;
|
||||
|
||||
import com.mhd.common.core.web.domain.BaseVOEntity;
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
|
||||
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
@@ -18,24 +20,28 @@ import java.util.List;
|
||||
@ApiModel(value = "复核单主表", description = "复核单主表展示")
|
||||
public class ReviewOrderPO extends BaseVOEntity {
|
||||
|
||||
@JsonSerialize(using = ToStringSerializer.class)
|
||||
@ApiModelProperty("复核单主键")
|
||||
private Long reviewOrderId;
|
||||
|
||||
@ApiModelProperty("复核单号")
|
||||
private String reviewOrderNumber;
|
||||
|
||||
@JsonSerialize(using = ToStringSerializer.class)
|
||||
@ApiModelProperty("出库单ID")
|
||||
private Long outOrderId;
|
||||
|
||||
@ApiModelProperty("出库单号")
|
||||
private String outOrderNumber;
|
||||
|
||||
@JsonSerialize(using = ToStringSerializer.class)
|
||||
@ApiModelProperty("组织ID")
|
||||
private Long organizationId;
|
||||
|
||||
@ApiModelProperty("组织名称")
|
||||
private String organizationName;
|
||||
|
||||
@JsonSerialize(using = ToStringSerializer.class)
|
||||
@ApiModelProperty("一级组织ID")
|
||||
private Long topOrganizationId;
|
||||
|
||||
@@ -50,6 +56,7 @@ public class ReviewOrderPO extends BaseVOEntity {
|
||||
@ApiModelProperty("复核下发时间")
|
||||
private Date issuedTime;
|
||||
|
||||
@JsonSerialize(using = ToStringSerializer.class)
|
||||
@ApiModelProperty("仓库ID")
|
||||
private Long warehouseId;
|
||||
|
||||
@@ -59,6 +66,7 @@ public class ReviewOrderPO extends BaseVOEntity {
|
||||
@ApiModelProperty("仓库名称")
|
||||
private String warehouseName;
|
||||
|
||||
@JsonSerialize(using = ToStringSerializer.class)
|
||||
@ApiModelProperty("客户ID")
|
||||
private Long customerId;
|
||||
|
||||
@@ -68,6 +76,7 @@ public class ReviewOrderPO extends BaseVOEntity {
|
||||
@ApiModelProperty("客户名称")
|
||||
private String customerName;
|
||||
|
||||
@JsonSerialize(using = ToStringSerializer.class)
|
||||
@ApiModelProperty("货主ID")
|
||||
private Long shipperId;
|
||||
|
||||
|
||||
+39
@@ -3,6 +3,7 @@ package com.mhd.wms.domain.shiftManage.service;
|
||||
import cn.hutool.core.util.ObjectUtil;
|
||||
import cn.hutool.json.JSONUtil;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
|
||||
import com.mhd.common.core.domain.po.UserPo;
|
||||
import com.mhd.common.core.exception.ServiceException;
|
||||
@@ -14,6 +15,7 @@ import com.mhd.system.api.domain.MaterialInventoryOmsParamDO;
|
||||
import com.mhd.system.api.domain.cache.AssociationWarehouseCacheDO;
|
||||
import com.mhd.system.api.domain.cache.SystemServiceCacheUtil;
|
||||
import com.mhd.system.api.model.LoginUser;
|
||||
import com.mhd.wms.domain.deliveTask.entity.DeliveTask;
|
||||
import com.mhd.wms.domain.deliveTask.repository.facade.IDeliveTaskService;
|
||||
import com.mhd.wms.domain.deliveTask.repository.todo.DeliveTaskDO;
|
||||
import com.mhd.wms.domain.inventoryStandingDetail.repository.facade.IInventoryStandingDetailService;
|
||||
@@ -484,6 +486,43 @@ public class ShiftManageDomainService {
|
||||
return shiftManageService.taskDistribution(shiftManageDO);
|
||||
}
|
||||
|
||||
/**
|
||||
* @description 撤回移位(待移位 → 已创建)
|
||||
* @author gen
|
||||
* @date 2026/7/17
|
||||
* @param shiftManageDO
|
||||
* @return Boolean
|
||||
*/
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public Boolean revokeAudit(ShiftManageDO shiftManageDO) {
|
||||
LoginUser loginUser = SecurityUtils.getLoginUser();
|
||||
Long shiftManageId = shiftManageDO.getShiftManageId();
|
||||
if (shiftManageId == null) {
|
||||
throw new ServiceException("移位单id不能为空");
|
||||
}
|
||||
ShiftManage shiftManage = shiftManageService.getById(shiftManageId);
|
||||
if (shiftManage == null) {
|
||||
throw new ServiceException("移位单不存在");
|
||||
}
|
||||
if (!Integer.valueOf(2).equals(shiftManage.getShiftStatus())) {
|
||||
throw new ServiceException("移位单【" + shiftManage.getShiftNumber() + "】状态不为待移位,不可撤回");
|
||||
}
|
||||
// 删除生成的配送任务(taskType=5,trackingNumber=shiftNumber)
|
||||
deliveTaskService.remove(new QueryWrapper<DeliveTask>().lambda()
|
||||
.eq(DeliveTask::getTrackingNumber, shiftManage.getShiftNumber())
|
||||
.eq(DeliveTask::getTaskType, 5));
|
||||
// 回退:shiftStatus=1(已创建),taskDistribution=2(未下发),auditStatus=1(未审核)
|
||||
shiftManageService.update(null, new UpdateWrapper<ShiftManage>().lambda()
|
||||
.set(ShiftManage::getShiftStatus, 1)
|
||||
.set(ShiftManage::getTaskDistribution, 2)
|
||||
.set(ShiftManage::getAuditStatus, 1)
|
||||
.set(ShiftManage::getUpdateBy, loginUser.getUserid())
|
||||
.set(ShiftManage::getUpdateByName, loginUser.getUsername())
|
||||
.set(ShiftManage::getUpdateTime, new Date())
|
||||
.eq(ShiftManage::getShiftManageId, shiftManageId));
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 物料移位
|
||||
*/
|
||||
|
||||
+7
-3
@@ -106,12 +106,16 @@ public class MaterialBaseInfoApi extends BaseController {
|
||||
}
|
||||
|
||||
/**
|
||||
* 导入物料主数据
|
||||
* 导入物料主数据(异步执行)
|
||||
*
|
||||
* <p>数据量大时同步导入会导致接口超时,改为异步模式:
|
||||
* 接口立即返回"已提交异步处理",后台线程执行实际导入,
|
||||
* 导入结果通过日志输出。</p>
|
||||
*/
|
||||
@ApiOperation("导入物料主数据")
|
||||
@ApiOperation("导入物料主数据(异步)")
|
||||
@PostMapping("/importData")
|
||||
public AjaxResult importData(@RequestParam("file") MultipartFile file) {
|
||||
return materialBaseInfoApplicationService.importData(file);
|
||||
return materialBaseInfoApplicationService.importDataAsync(file);
|
||||
}
|
||||
|
||||
@ApiOperation("物料管理更新推送信息")
|
||||
|
||||
+5
-1
@@ -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();
|
||||
|
||||
+10
@@ -120,4 +120,14 @@ public class ShiftManageApi extends BaseController {
|
||||
return AjaxResult.success(shiftManageApplicationService.taskDistribution(shiftManageDO));
|
||||
}
|
||||
|
||||
/**
|
||||
* 撤回审核
|
||||
*/
|
||||
@ApiOperation("撤回审核")
|
||||
@PostMapping(value = "/revokeAudit")
|
||||
public AjaxResult revokeAudit(@RequestBody ShiftManageDTO shiftManageDTO) {
|
||||
ShiftManageDO shiftManageDO = shiftManageAssembler.toDO(shiftManageDTO);
|
||||
return AjaxResult.success(shiftManageApplicationService.revokeAudit(shiftManageDO));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -36,6 +36,11 @@ public final class MaterialBaseInfoImportExcelUtil {
|
||||
HEADER_ALIASES.put("淨重(kg)", "净重 单位:千克");
|
||||
HEADER_ALIASES.put("体积(m³)", "体积 单位:立方米");
|
||||
HEADER_ALIASES.put("體積(m³)", "体积 单位:立方米");
|
||||
HEADER_ALIASES.put("长", "物料大小-长 单位:米");
|
||||
HEADER_ALIASES.put("宽", "物料大小-宽 单位:米");
|
||||
HEADER_ALIASES.put("高", "物料大小-高 单位:米");
|
||||
HEADER_ALIASES.put("公司名称", "货主名称");
|
||||
HEADER_ALIASES.put("公司名稱", "货主名称");
|
||||
}
|
||||
|
||||
public static List<MaterialBaseInfoDTO> importRows(InputStream is) throws Exception {
|
||||
|
||||
@@ -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.31:6848
|
||||
server-addr: 10.102.192.31:6848
|
||||
username: nacos
|
||||
password: manhuoda@2023
|
||||
#线上正式环境
|
||||
# server-addr: 10.102.192.105:6848
|
||||
config:
|
||||
# server-addr: 127.0.0.1:8848
|
||||
server-addr: 10.33.0.129:6010
|
||||
# server-addr: 10.33.0.129:6010
|
||||
# 线上测试环境配置 容器名+端口号
|
||||
# server-addr: 10.102.192.31:6848
|
||||
server-addr: 10.102.192.31:6848
|
||||
username: nacos
|
||||
password: manhuoda@2023
|
||||
#线上正式环境
|
||||
|
||||
@@ -455,6 +455,45 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
loc.storage_location_id, loc.storage_location_code, loc.storage_location_name order by sort_order, a.update_time desc
|
||||
</select>
|
||||
|
||||
<!-- 按物料+过期日期汇总:相同物料+相同过期日期合并,不同过期日期分开 -->
|
||||
<select id="queryListByWlExpiry" parameterType="com.mhd.wms.domain.materialInventory.repository.todo.MaterialInventoryDO" resultMap="MaterialInventoryResult">
|
||||
select
|
||||
a.material_base_info_id, a.expiry_date, a.shipper_id, a.shipper_code, a.shipper_name,
|
||||
a.organization_id, a.organization_name, a.top_organization_id,
|
||||
MAX(a.warehouse_id) AS warehouse_id, MAX(a.warehouse_code) AS warehouse_code, MAX(a.warehouse_name) AS warehouse_name,
|
||||
MAX(a.storage_section_id) AS storage_section_id, MAX(a.storage_code) AS storage_code, MAX(a.storage_name) AS storage_name,
|
||||
MAX(a.storage_location_id) AS storage_location_id, MAX(a.storage_location_code) AS storage_location_code, MAX(a.storage_location_name) AS storage_location_name,
|
||||
MAX(a.batch_number) AS batch_number, MAX(a.material_status_code) AS material_status_code, MAX(a.material_status_name) AS material_status_name,
|
||||
MAX(a.container_id) AS container_id, MAX(a.container_code) AS container_code, MAX(a.container_type) AS container_type, MAX(a.container_type_name) AS container_type_name,
|
||||
IFNULL(SUM(a.freeze_quantity), 0) AS freeze_quantity, a.is_able,
|
||||
IFNULL(SUM(a.inventory_quantity), 0) AS inventory_quantity,
|
||||
IFNULL(SUM(a.allocation_quantity), 0) AS allocation_quantity,
|
||||
IFNULL(SUM(a.area), 0) AS area,
|
||||
IFNULL(SUM(a.NET_WEIGHT), 0) AS NET_WEIGHT,
|
||||
IFNULL(SUM(a.GROSS_WEIGHT), 0) AS GROSS_WEIGHT,
|
||||
IFNULL(SUM(a.VOLUME), 0) AS VOLUME,
|
||||
MAX(a.unit) AS unit,
|
||||
MAX(a.unit_name) AS unit_name,
|
||||
MAX(a.production_date) AS production_date,
|
||||
MAX(a.inventory_date) AS inventory_date,
|
||||
MAX(a.batch_ref_no) AS batch_ref_no, MAX(a.sheet_ref_no) AS sheet_ref_no, MAX(a.box_pallet_no) AS box_pallet_no,
|
||||
MAX(a.bar_code) AS inv_bar_code,
|
||||
MAX(a.in_order_number) AS in_order_number, MAX(a.lot_number) AS lot_number,
|
||||
b.specification_model,
|
||||
b.material_code, b.material_name,
|
||||
CASE WHEN IFNULL(SUM(a.inventory_quantity), 0) = 0 THEN 1 ELSE 0 END AS sort_order
|
||||
from material_inventory a
|
||||
left join material_base_info b on a.material_base_info_id = b.material_base_info_id
|
||||
<where>
|
||||
<include refid="selectMaterialInventoryPo1"/>
|
||||
<include refid="com.mhd.wms.domain.materialBaseInfo.repository.mapper.MaterialBaseInfoMapper.JoinMaterialBaseInfoPoWhere"/>
|
||||
</where>
|
||||
GROUP BY a.MATERIAL_BASE_INFO_ID, a.EXPIRY_DATE, a.shipper_id, a.shipper_code, a.shipper_name,
|
||||
a.organization_id, a.organization_name, a.top_organization_id,
|
||||
b.material_code, b.material_name, b.specification_model
|
||||
order by sort_order, MAX(a.update_time) desc
|
||||
</select>
|
||||
|
||||
<!-- 按货主+物料汇总:A货主物料1、A货主物料2、B货主物料1、B货主物料2 为 4 行;库位取该货主+该物料下创建时间最新的一条明细 -->
|
||||
<select id="queryListByHzWl" parameterType="com.mhd.wms.domain.materialInventory.repository.todo.MaterialInventoryDO" resultMap="MaterialInventoryResult">
|
||||
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
|
||||
</when>
|
||||
<when test="queryType != null and queryType == 7">
|
||||
group by b.material_base_info_id, a.shipper_id, a.expiry_date
|
||||
order by max(b.material_name), max(a.shipper_name), a.expiry_date
|
||||
</when>
|
||||
<when test="queryType != null and queryType == 4">
|
||||
group by a.storage_location_id
|
||||
order by max(a.storage_location_code)
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<mapper namespace="com.mhd.wms.domain.reviewOrder.repository.mapper.ReviewOrderMapper">
|
||||
|
||||
<resultMap type="com.mhd.wms.domain.reviewOrder.repository.po.ReviewOrderPO" id="ReviewOrderResult">
|
||||
<result property="reviewOrderId" column="review_order_id"/>
|
||||
<id property="reviewOrderId" column="review_order_id"/>
|
||||
<result property="reviewOrderNumber" column="review_order_number"/>
|
||||
<result property="outOrderId" column="out_order_id"/>
|
||||
<result property="outOrderNumber" column="out_order_number"/>
|
||||
@@ -84,7 +84,7 @@
|
||||
</resultMap>
|
||||
|
||||
<sql id="reviewOrderSelectColumns">
|
||||
a.review_order_id,
|
||||
a.review_order_id AS review_order_id,
|
||||
a.review_order_number,
|
||||
a.out_order_id,
|
||||
a.out_order_number,
|
||||
@@ -154,6 +154,9 @@
|
||||
<if test="shipperName != null and shipperName != ''">
|
||||
and a.shipper_name like concat('%', #{shipperName}, '%')
|
||||
</if>
|
||||
<if test="shipperId != null and shipperId != ''">
|
||||
and a.shipper_id like concat('%', #{shipperId}, '%')
|
||||
</if>
|
||||
<if test="createTimeStart != null and createTimeStart != ''">
|
||||
and date_format(a.create_time, '%Y-%m-%d') >= #{createTimeStart}
|
||||
</if>
|
||||
|
||||
@@ -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 '费用类别名称(服务项名称)';
|
||||
Reference in New Issue
Block a user