Merge branch 'dev' into feature/dev-0729

# Conflicts:
#	mhd_bms/src/main/resources/bootstrap.yml
This commit is contained in:
王奎兴
2026-08-08 11:39:21 +08:00
52 changed files with 2552 additions and 963 deletions
@@ -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"},
@@ -14,6 +14,12 @@ import lombok.NoArgsConstructor;
@ApiModel("月台监测-作业车辆")
public class PlatformVehicleItemVO {
@ApiModelProperty("预约申请时间")
private String appointmentTime;
@ApiModelProperty("作业楼层")
private String workFloor;
@ApiModelProperty("车牌号码")
private String plateNumber;
+4 -4
View File
@@ -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
# 线上测试环境配置 容器名+端口号
@@ -33,4 +33,6 @@ public class WarehousePO implements Serializable {
@Excel(name = "仓库名称")
private String warehouseName;
@Excel(name = "是否启用: 1-否 2-是")
private Integer isEnable;
}
@@ -1124,4 +1124,51 @@ public class ContractManageApplicationService {
public ContractManagePO getGeneralContract() {
return contractManageDomainService.getGeneralContract();
}
/**
* 合同导出(合同头字段 + 明细拍平成一行一条明细)
*/
public List<ContractManageExportVO> buildExportList(ContractManageDO contractManageDO) {
List<ContractManagePO> contractList = this.queryList(contractManageDO);
List<ContractManageExportVO> exportList = new ArrayList<>();
if (contractList == null || contractList.isEmpty()) {
return exportList;
}
List<Long> contractManageIds = contractList.stream()
.map(ContractManagePO::getContractManageId)
.collect(Collectors.toList());
Map<Long, List<ContractManageDetailPO>> detailMap = contractManageDetailDomainService
.queryListByManageIds(contractManageIds).stream()
.collect(Collectors.groupingBy(ContractManageDetailPO::getContractManageId));
for (ContractManagePO contract : contractList) {
List<ContractManageDetailPO> details = detailMap.get(contract.getContractManageId());
if (details != null && !details.isEmpty()) {
for (ContractManageDetailPO detail : details) {
ContractManageExportVO vo = new ContractManageExportVO();
// 合同头字段整体复制
BeanUtils.copyProperties(contract, vo);
// 明细字段显式赋值(合同头/明细存在同名字段,避免互相覆盖)
vo.setSubjectType(detail.getSubjectType());
vo.setFirstSubjectCode(detail.getFirstSubjectCode());
vo.setFirstSubjectName(detail.getFirstSubjectName());
vo.setSecondSubjectCode(detail.getSecondSubjectCode());
vo.setSecondSubjectName(detail.getSecondSubjectName());
vo.setAccountingStrategy(detail.getAccountingStrategy());
vo.setBillingAttributes(detail.getBillingAttributes());
vo.setSubjectEffectiveDate(detail.getSubjectEffectiveDate());
vo.setSubjectExpirationDate(detail.getSubjectExpirationDate());
vo.setDocumentType(detail.getDocumentType());
vo.setServiceItemsName(detail.getServiceItemsName());
exportList.add(vo);
}
} else {
// 无明细的合同也保留一行头字段
ContractManageExportVO vo = new ContractManageExportVO();
BeanUtils.copyProperties(contract, vo);
exportList.add(vo);
}
}
return exportList;
}
}
@@ -98,4 +98,10 @@ public class ContractManageDetail extends BaseVOEntity{
@ApiModelProperty("单据类型")
private String documentType;
@ApiModelProperty("费用类别编码")
private String serviceItemsCode;
@ApiModelProperty("费用类别名称")
private String serviceItemsName;
}
@@ -97,4 +97,10 @@ public class ContractManageDetailPO extends BaseVOEntity{
@ApiModelProperty("单据类型")
private String documentType;
@ApiModelProperty("费用类别编码")
private String serviceItemsCode;
@ApiModelProperty("费用类别名称")
private String serviceItemsName;
}
@@ -102,4 +102,10 @@ public class ContractManageDetailDO extends BaseVOEntity{
@ApiModelProperty("单据类型")
private String documentType;
@ApiModelProperty("费用类别编码")
private String serviceItemsCode;
@ApiModelProperty("费用类别名称")
private String serviceItemsName;
}
@@ -11,6 +11,7 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
/**
* 合同管理详情
@@ -95,5 +96,29 @@ public class ContractManageDetailDomainService {
return resultList;
}
/**
* 根据多个合同管理id批量查询合同科目详情一次SQL查询避免逐合同N+1
* @param contractManageIds 合同管理id集合
* @return 合同科目详情列表
*/
public List<ContractManageDetailPO> queryListByManageIds(Collection<Long> contractManageIds) {
List<ContractManageDetailPO> resultList = new ArrayList<>();
if (contractManageIds == null || contractManageIds.isEmpty()) {
return resultList;
}
LambdaQueryWrapper<ContractManageDetail> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.in(ContractManageDetail::getContractManageId, contractManageIds);
queryWrapper.eq(ContractManageDetail::getDelFlag, 1);
List<ContractManageDetail> contractManageDetails = contractManageDetailService.list(queryWrapper);
if (contractManageDetails != null && contractManageDetails.size() > 0) {
for (ContractManageDetail contractManageDetail : contractManageDetails) {
ContractManageDetailPO contractManageDetailPO = new ContractManageDetailPO();
BeanUtils.copyProperties(contractManageDetail, contractManageDetailPO);
resultList.add(contractManageDetailPO);
}
}
return resultList;
}
}
@@ -0,0 +1,102 @@
package com.mhd.basic.interfaces.dto.contractManage;
import com.mhd.common.core.annotation.Excel;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.util.Date;
/**
* 合同管理导出对象合同头字段 + 科目明细字段拍平为一行一条明细
*
* @author gen
* @date 2024-06-07
*/
@Data
@ApiModel(value = "合同管理导出对象", description = "合同管理导出对象(含明细)")
public class ContractManageExportVO {
/** ====== 合同头字段(与 ContractManagePO 的 @Excel 一致) ====== */
@Excel(name = "合同编号")
private String contractNumber;
@Excel(name = "合同名称")
private String contractName;
@Excel(name = "是否通用合同", readConverterExp = "1=是,2=否")
private Integer commonContractFlag;
@Excel(name = "合同类型", readConverterExp = "1=仓储,2=运输,3=其他")
private Integer contractType;
@Excel(name = "合同状态", readConverterExp = "1=未生效,2=使用中,3=已过期,4=已作废")
private Integer contractState;
@Excel(name = "签订单位")
private String signingUnit;
@Excel(name = "结算主体")
private String settlementCustomers;
@Excel(name = "我司身份", readConverterExp = "1=甲方,2=乙方")
private Integer ourIdentity;
@Excel(name = "账期", readConverterExp = "1=每月,2=双月,3=季度")
private Integer accountingPeriod;
@Excel(name = "合同签订日期", width = 30, dateFormat = "yyyy-MM-dd")
private Date signingDate;
@Excel(name = "合同生效日期", width = 30, dateFormat = "yyyy-MM-dd")
private Date effectiveDate;
@Excel(name = "合同到期日期", width = 30, dateFormat = "yyyy-MM-dd")
private Date expirationDate;
@Excel(name = "组织名称")
private String organizationName;
@Excel(name = "客户类型")
private String customerType;
@Excel(name = "是否自动出账", readConverterExp = "1=是,2=否")
private Integer automaticFlag;
@Excel(name = "备注")
private String remark;
/** ====== 明细字段(来源于 contract_manage_detail ====== */
@Excel(name = "结算科目类型", readConverterExp = "1=通用,2=临时")
private Integer subjectType;
@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 String accountingStrategy;
@Excel(name = "计费周期")
private String billingAttributes;
@Excel(name = "科目生效日期", width = 30, dateFormat = "yyyy-MM-dd")
private Date subjectEffectiveDate;
@Excel(name = "科目到期日期", width = 30, dateFormat = "yyyy-MM-dd")
private Date subjectExpirationDate;
@Excel(name = "单据类型")
private String documentType;
@Excel(name = "费用类别")
private String serviceItemsName;
}
@@ -102,4 +102,10 @@ public class ContractManageDetailDTO extends BaseVOEntity{
@ApiModelProperty("单据类型")
private String documentType;
@ApiModelProperty("费用类别编码")
private String serviceItemsCode;
@ApiModelProperty("费用类别名称")
private String serviceItemsName;
}
@@ -1,8 +1,11 @@
package com.mhd.basic.interfaces.facade.contractManage;
import java.io.IOException;
import java.net.URLEncoder;
import java.util.List;
import com.mhd.basic.interfaces.assember.contractManage.ContractManageAssembler;
import com.mhd.basic.interfaces.dto.contractManage.ContractManageExportVO;
import com.mhd.basic.interfaces.dto.contractManage.SubjectAndPriceDTO;
import com.mhd.basic.interfaces.dto.contractManage.SubjectAndPriceReturn;
import io.swagger.annotations.ApiOperation;
@@ -14,9 +17,11 @@ import com.mhd.basic.domain.contractManage.repository.todo.ContractManageDO;
import com.mhd.basic.domain.contractManage.repository.po.ContractManagePO;
import com.mhd.basic.application.service.contractManage.ContractManageApplicationService;
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;
import com.mhd.common.core.utils.poi.ExcelUtil;
/**
* 合同管理Api
@@ -205,7 +210,24 @@ public class ContractManageApi extends BaseController{
return AjaxResult.success(list);
}
@ApiOperation("导出合同(含明细)")
@GetMapping(value = "/export", produces = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet")
public void export(ContractManageDTO contractManageDTO, HttpServletResponse response) throws IOException
{
//转换实体
ContractManageDO contractManageDO = new ContractManageDO();
BeanUtils.copyProperties(contractManageDTO, contractManageDO);
//查询全量不分页并拍平明细
List<ContractManageExportVO> list = contractManageApplicationService.buildExportList(contractManageDO);
//设置下载头防止浏览器乱码
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<ContractManageExportVO> util = new ExcelUtil<>(ContractManageExportVO.class);
util.exportExcel(response, list, "合同导出");
}
}
@@ -14,18 +14,18 @@ spring:
nacos:
discovery:
# server-addr: 127.0.0.1:8848
# server-addr: 10.33.0.129:6010
server-addr: 10.33.0.129:6010
# 线上测试环境配置 容器名+端口号
server-addr: 10.102.192.30:6848
# server-addr: 10.102.192.31:6848
username: nacos
password: manhuoda@2023
#线上正式环境
# server-addr: 10.102.192.105:6848
config:
# server-addr: 127.0.0.1:8848
# server-addr: 10.33.0.129:6010
server-addr: 10.33.0.129:6010
# 线上测试环境配置 容器名+端口号
server-addr: 10.102.192.30:6848
# server-addr: 10.102.192.31:6848
username: nacos
password: manhuoda@2023
#线上正式环境
@@ -148,6 +148,7 @@
AND a.top_organization_id = #{expenseAccountDO.topOrganizationId}
AND a.subject_code = #{expenseAccountDO.subjectCode}
AND a.status = 1
LIMIT 1
</select>
@@ -782,10 +782,6 @@
<if test="organizationId !=null">
AND (
u.organization_id = #{organizationId}
OR b.org_code LIKE concat('%"code":"', #{organizationId}, '"%')
OR b.org_code LIKE concat('%code:', #{organizationId}, '%')
OR b.org_code LIKE concat('%code: ', #{organizationId}, '%')
OR b.org_code LIKE concat('%"code":', #{organizationId}, '%')
)
AND u.organization_name IS NOT NULL
</if>
@@ -381,10 +381,6 @@
<if test="organizationId !=null">
AND (
a.organization_id = #{organizationId}
OR b.org_code LIKE concat('%"code":"', #{organizationId}, '"%')
OR b.org_code LIKE concat('%code:', #{organizationId}, '%')
OR b.org_code LIKE concat('%code: ', #{organizationId}, '%')
OR b.org_code LIKE concat('%"code":', #{organizationId}, '%')
)
</if>
/*组织名称*/
@@ -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;
@@ -78,6 +79,8 @@ public class BillManageApplicationService {
private BillDetailMapper billDetailMapper;
@Autowired
private NcLogMapper ncLogMapper;
@Autowired
private IBillManageService billManageService;
/**
@@ -133,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;
}
@@ -360,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);
//更新账单金额
@@ -428,6 +448,7 @@ public class BillManageApplicationService {
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());
@@ -449,6 +470,16 @@ public class BillManageApplicationService {
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);
@@ -464,7 +495,47 @@ public class BillManageApplicationService {
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);
item.setBillManageId(billManageDO.getBillManageId());
item.setBillNumber(billManageDO.getBillNumber());
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();
@@ -476,105 +547,51 @@ public class BillManageApplicationService {
}
/**
* 复制账单
* 复制账单-获取原账单数据供前端回显
* 前端拿到数据后跳转到类似修改/新增账单的页面用户修改后通过addBill接口提交新增
*/
@Transactional
public Boolean copyBill(BillManageDTO billManageDTO) {
LoginUser loginUser = SecurityUtils.getLoginUser();
if (ObjectUtil.isNull(loginUser)) {
throw new DigitalLogisticsException(UserError.TIMEOUT);
}
public BillManagePO copyBill(BillManageDTO billManageDTO) {
if (billManageDTO.getBillManageId() == null) {
throw new ServiceException("原账单id不能为空");
}
// 1. 获取原账单信息
// 获取原账单信息
BillManagePO originalBill = billManageDomainService.getInfo(billManageDTO.getBillManageId());
if (null == originalBill) {
throw new ServiceException("原账单信息未找到");
}
// 2. 获取原账单明细
// 获取原账单明细
List<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;
}
/**
@@ -585,6 +585,8 @@ public class BillingStatementApplicationService {
此方法只进行实体返回并不进行数据保存
*/
LoginUser loginUser = SecurityUtils.getLoginUser();
billingStatementDO.setAccountExpenseType(billingStatementDO.getAccountExpenseType());
if (ObjectUtil.isNull(loginUser)) {
throw new DigitalLogisticsException(UserError.TIMEOUT);
}
@@ -594,7 +596,10 @@ public class BillingStatementApplicationService {
BeanUtils.copyProperties(billingStatementDO,billingStatementPO);
billingStatementPO.setBillingTotalAmount(billingStatementDO.getBillingAmount());
billingStatementPO.setDataSources(2);
billingStatementPO.setBillingFlow(OrderSequence.getOrderCode("JFLS"));
// 若传入了计费流水号则直接使用否则自动生成
if (StringUtils.isEmpty(billingStatementPO.getBillingFlow())) {
billingStatementPO.setBillingFlow(OrderSequence.getOrderCode("JFLS"));
}
billingStatementPO.setTopOrganizationId(loginUser.getUserPo().getTopOrganizationId());
billingStatementPO.setOrganizationId(loginUser.getUserPo().getOrganizationId());
billingStatementPO.setOrganizationName(loginUser.getUserPo().getOrganizationName());
@@ -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);
}
@@ -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);
}
@@ -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);
}
@@ -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);
}
}
@@ -264,4 +264,6 @@ public class BillManageDO extends BaseVOEntity{
private String paymentAccountId;
@ApiModelProperty("收款帐户名称")
private String paymentAccountName;
@ApiModelProperty("业务员ID")
private String salesmanId;
}
@@ -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;
@@ -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;
@@ -0,0 +1,145 @@
package com.mhd.bms.interfaces.dto.billManage;
import com.mhd.common.core.annotation.Excel;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.math.BigDecimal;
import java.util.Date;
@Data
@ApiModel(value = "应收账单导出对象")
public class BillManageExportVO {
/** ====== 原有账单头字段(与 BillManagePO 的 @Excel 一致) ====== */
@Excel(name = "一级组织表ID")
private Long topOrganizationId;
@Excel(name = "组织表ID")
private Long organizationId;
@Excel(name = "组织名称")
private String organizationName;
@Excel(name = "账单编号")
private String billNumber;
@Excel(name = "账单类型", readConverterExp = "1=-应收,2-应付")
private Integer billType;
@Excel(name = "账单状态", readConverterExp = "1=-未确认,2-对账中,3-未收款/付款,4-部分收款/付款,5-已收款/付款,6-已作废,7-已退款")
private Integer billState;
@Excel(name = "账单流程节点", readConverterExp = "1=-发起对账,2-客户确认,3-财务审核,4-收款/付款")
private Integer billStep;
@Excel(name = "系统来源")
private String belongModule;
@Excel(name = "系统来源code")
private String belongModuleCode;
@Excel(name = "结算对象id")
private Long settlementCustomersId;
@Excel(name = "结算对象code")
private String settlementCustomersCode;
@Excel(name = "结算对象")
private String settlementEntity;
@Excel(name = "账单总金额")
private BigDecimal billTotalAmount;
@Excel(name = "优惠金额")
private BigDecimal billDiscountAmount;
@Excel(name = "账单金额")
private BigDecimal billAmount;
@Excel(name = "已收/付金额")
private BigDecimal billAmountSettlement;
@Excel(name = "未收/付金额")
private BigDecimal billAmountUnsettled;
@Excel(name = "期望金额")
private BigDecimal billExpectedAmount;
@Excel(name = "对账状态", readConverterExp = "1=-暂未确认,2-申请调账,3-财务调账,4-核对无误")
private Integer reconciliationStatus;
@Excel(name = "对账意见描述")
private String reconciliationOpinion;
@Excel(name = "客户凭证地址")
private String voucherAddress;
@Excel(name = "财务审核结果(1-同意,2-拒绝)")
private Integer financialReviewFlag;
@Excel(name = "审核意见描述")
private String financialReviewOpinion;
@Excel(name = "周期开始时间", width = 30, dateFormat = "yyyy-MM-dd")
private Date cycleBeginTime;
@Excel(name = "周期结束时间", width = 30, dateFormat = "yyyy-MM-dd")
private Date cycleEndTime;
@Excel(name = "收款/付款时间", width = 30, dateFormat = "yyyy-MM-dd")
private Date settlementTime;
@Excel(name = "备注")
private String billRemark;
@Excel(name = "折扣百分比")
private BigDecimal billDiscount;
@Excel(name = "折扣上限金额")
private BigDecimal billDiscountLimit;
@Excel(name = "费用计算精度code")
private String costAccuracyCode;
@Excel(name = "费用计算精度name")
private String costAccuracyName;
@Excel(name = "尾数计算code")
private String tailCalculationCode;
@Excel(name = "尾数计算name")
private String tailCalculationName;
@Excel(name = "账单金额精度code")
private String amountAccuracyCode;
@Excel(name = "账单金额精度name")
private String amountAccuracyName;
/** ====== 新增明细字段(来源于 bill_detail + billing_statement ====== */
@Excel(name = "费用类别")
private String feeType;
@Excel(name = "费用类型code")
private String serviceItemsCode;
@Excel(name = "费用类型")
private String serviceItemsName;
@Excel(name = "一级费用科目code")
private String firstSubjectCode;
@Excel(name = "一级费用科目")
private String firstSubjectName;
@Excel(name = "二级费用科目code")
private String secondSubjectCode;
@Excel(name = "二级费用科目")
private String secondSubjectName;
@Excel(name = "明细金额")
private BigDecimal billingAmount;
}
@@ -102,6 +102,10 @@ public class BillingStatementDTO extends BaseVOEntity{
@Excel(name = "收支类型", readConverterExp = "1=-应收,2-应付")
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)
@@ -258,7 +312,7 @@ public class BillManageApi extends BaseController{
}
@ApiOperation("复制账单")
@ApiOperation("复制账单-获取原账单数据用于回显")
@PostMapping("/copyBill")
public AjaxResult copyBill(@RequestBody BillManageDTO billManageDTO)
{
@@ -266,8 +320,8 @@ public class BillManageApi extends BaseController{
throw new ServiceException("原账单id不能为空");
}
try {
Boolean result = billManageApplicationService.copyBill(billManageDTO);
return toAjax(result);
BillManagePO result = billManageApplicationService.copyBill(billManageDTO);
return AjaxResult.success(result);
}catch (Exception e){
return AjaxResult.error("复制账单失败:"+e.getMessage());
}
@@ -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>
@@ -89,6 +89,21 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<if test="billingRulesDO.serviceItemsCode != null and billingRulesDO.serviceItemsCode != ''">
and service_items_code = #{billingRulesDO.serviceItemsCode}
</if>
<if test="billingRulesDO.serviceItemsName != null and billingRulesDO.serviceItemsName != ''">
and service_items_name like concat('%',#{billingRulesDO.serviceItemsName},'%')
</if>
<if test="billingRulesDO.firstSubjectCode != null and billingRulesDO.firstSubjectCode != ''">
and first_subject_code = #{billingRulesDO.firstSubjectCode}
</if>
<if test="billingRulesDO.firstSubjectName != null and billingRulesDO.firstSubjectName != ''">
and first_subject_name like concat('%',#{billingRulesDO.firstSubjectName},'%')
</if>
<if test="billingRulesDO.secondSubjectCode != null and billingRulesDO.secondSubjectCode != ''">
and second_subject_code = #{billingRulesDO.secondSubjectCode}
</if>
<if test="billingRulesDO.secondSubjectName != null and billingRulesDO.secondSubjectName != ''">
and second_subject_name like concat('%',#{billingRulesDO.secondSubjectName},'%')
</if>
<if test="billingRulesDO.billingRulesState != null">
and billing_rules_state = #{billingRulesDO.billingRulesState}
</if>
@@ -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>
@@ -181,17 +181,9 @@ public class ReservationStockInOrderApplicationService {
* 新增入库单
*/
public Boolean insert(ReservationStockInOrderDO stockInOrderDO) {
// 如果仓库ID为空从当前登录用户的关联仓库中获取
// 仓库为必填项前端必须选择入库仓库
if (stockInOrderDO.getWarehouseId() == null) {
LoginUser loginUser = SecurityUtils.getLoginUser();
if (loginUser == null) {
throw new ServiceException("登录已失效,请重新登录");
}
AssociationWarehouseCacheDO associationWarehouseCacheDO = SystemServiceCacheUtil.getAssociationWarehouseCache(loginUser.getUserid());
if (associationWarehouseCacheDO == null || associationWarehouseCacheDO.getWarehouseId() == null) {
throw new ServiceException("当前用户未配置关联仓库,请先配置仓库");
}
stockInOrderDO.setWarehouseId(associationWarehouseCacheDO.getWarehouseId());
throw new ServiceException("请选择入库仓库");
}
//设置仓库
setWarehouseInfo(stockInOrderDO);
@@ -25,6 +25,7 @@ import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import java.lang.reflect.Field;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;
@@ -127,6 +128,7 @@ public class StatementStatisticsService {
}
}
List<ImmediateInventoryPO> immediateInventoryPOS = materialInventoryDomainService.queryImmediateInventoryList(immediateInventoryDO);
// 性能优化批量获取批次属性避免N+1查询问题
// 1. 收集所有唯一的materialBaseInfoId
Set<Long> materialBaseInfoIdSet = immediateInventoryPOS.stream()
@@ -161,6 +163,19 @@ public class StatementStatisticsService {
return immediateInventoryPOS;
}
/**
* 获取库存数量合计
* @param immediateInventoryDO 查询参数
* @return 库存数量合计
*/
public BigDecimal sumImmediateInventoryQuantity(ImmediateInventoryDO immediateInventoryDO) {
BigDecimal totalInventoryQuantity = materialInventoryDomainService.sumImmediateInventoryQuantity(immediateInventoryDO);
if (totalInventoryQuantity == null) {
totalInventoryQuantity = BigDecimal.ZERO;
}
return totalInventoryQuantity;
}
/**
* 为物料库存设置更多属性从库存表中获取值
* @param materialInventoryPOList 物料库存列表
@@ -2222,24 +2222,31 @@ public class StockReceiptOrderApplicationService {
}
/**
* PDA 抄码收货不采集毛重体积面积在装配前将对应请求字段置 0避免 getInfo 带回的累计展示值被当作本次增量
* PDA 抄码收货不采集毛重体积面积在装配前将对应请求字段置 null
* 利用 MyBatis-Plus NOT_NULL 策略跳过这些字段避免覆盖已有累计数据
* @param lines 收货明细列表
*/
private static void normalizePdaCopyReceiptGrossVolumeAreaToZero(List<ReceiptMaterialDetailDO> lines) {
// 没有明细时直接返回
if (CollectionUtils.isEmpty(lines)) {
return;
}
// 有明细时遍历
for (ReceiptMaterialDetailDO line : lines) {
// 跳过 line null
if (line == null) {
continue;
}
// 在装配之前将字段置为 null
if (isPdaCopyReceiptLine(line)) {
line.setReceiptGrossWeight(BigDecimal.ZERO);
line.setTotalGrossWeight(BigDecimal.ZERO);
line.setReceiptVolume(BigDecimal.ZERO);
line.setTotalVolume(BigDecimal.ZERO);
line.setReceiptArea(BigDecimal.ZERO);
line.setTotalArea(BigDecimal.ZERO);
line.setReceiptGrossWeight(null);
line.setTotalGrossWeight(null);
line.setReceiptVolume(null);
line.setTotalVolume(null);
line.setReceiptArea(null);
line.setTotalArea(null);
}
// 递归确保每一个子行都会独立通过 isPdaCopyReceiptLine 判断是否需要清字段
normalizePdaCopyReceiptGrossVolumeAreaToZero(line.getChildren());
}
}
@@ -1,15 +1,21 @@
package com.mhd.wms.domain.inventoryAdjustmentRecord.service;
import cn.hutool.core.util.ObjectUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.aliyun.oss.ServiceException;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
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.utils.OrderSequence;
import com.mhd.common.core.utils.uuid.IdGenerator;
import com.mhd.common.core.utils.StringUtils;
import com.mhd.common.core.web.domain.AjaxResult;
import com.mhd.common.core.web.domain.BaseVOEntity;
import com.mhd.common.security.utils.SecurityUtils;
import com.mhd.system.api.OmsServiceFeign;
import com.mhd.system.api.SystemServiceFeign;
import com.mhd.system.api.domain.*;
import com.mhd.system.api.model.LoginUser;
import com.mhd.wms.domain.inventoryAdjustmentRecord.repository.facade.IInventoryAdjustmentRecordService;
@@ -56,6 +62,8 @@ public class InventoryAdjustmentRecordDomainService {
private IdGenerator idGenerator;
@Autowired
private OmsServiceFeign omsServiceFeign;
@Autowired
private SystemServiceFeign systemServiceFeign;
@@ -106,6 +114,15 @@ public class InventoryAdjustmentRecordDomainService {
*/
@Transactional
public Boolean inventoryAdjust(InventoryAdjustmentRecordDO inventoryAdjustmentRecordDO) {
// 根据仓库ID获取仓库信息用于后续库存调整的仓库判断
AjaxResult warehouseInfoByWarehouseId = systemServiceFeign.getWarehouseInfoByWarehouseId(inventoryAdjustmentRecordDO.getWarehouseId());
if (warehouseInfoByWarehouseId == null) {
throw new ServiceException("仓库不存在");
} else if (!warehouseInfoByWarehouseId.get("code").equals(200)) {
throw new ServiceException("网络错误请重试 --- " + warehouseInfoByWarehouseId.get("msg"));
}
// 获取仓库信息
WarehousePO warehousePO = JSON.parseObject(JSONObject.toJSONString(warehouseInfoByWarehouseId.get("data")), WarehousePO.class);
InventoryAdjustmentRecordDO inventoryAdjustmentRecord = new InventoryAdjustmentRecordDO();
inventoryAdjustmentRecord.setAdjustAction("库存调整");
LoginUser loginUser = SecurityUtils.getLoginUser();
@@ -115,6 +132,17 @@ public class InventoryAdjustmentRecordDomainService {
inventoryAdjustmentRecord.setCreateBy(loginUser.getUserid());
inventoryAdjustmentRecord.setCreateByName(loginUser.getUsername());
inventoryAdjustmentRecord.setCreateTime(new Date());
if (inventoryAdjustmentRecordDO.getAdjustType() == null) {
throw new ServiceException("调整类型不能为空");
}
if (inventoryAdjustmentRecordDO.getAdjustType() == 1
&& inventoryAdjustmentRecordDO.getMaterialInventoryId() == null) {
throw new ServiceException("请选择要调整的库存");
}
if (inventoryAdjustmentRecordDO.getAdjustQuantity() == null
|| inventoryAdjustmentRecordDO.getAdjustQuantity().compareTo(BigDecimal.ZERO) == 0) {
throw new ServiceException("调整数量不能为空且不能为0");
}
MaterialInventory materialInventory = null;
//根据调整类型判断,数量调整只调整当前库存记录数量状态调整减少当前原物料状态库存数量和可用数量增加到现状态库存数量和可用数量
if (inventoryAdjustmentRecordDO.getAdjustType() != null && inventoryAdjustmentRecordDO.getAdjustType() == 1) {
@@ -180,8 +208,8 @@ public class InventoryAdjustmentRecordDomainService {
.eq(MaterialInventory::getStorageSectionId,inventoryAdjustmentRecordDO.getStorageSectionId())
.eq(MaterialInventory::getStorageLocationId,inventoryAdjustmentRecordDO.getStorageLocationId())
.eq(MaterialInventory::getMaterialStatusCode,inventoryAdjustmentRecordDO.getAdjustBeforeStatusCode())
.eq(MaterialInventory::getBatchNumber,inventoryAdjustmentRecordDO.getBatchNumber())
.eq(MaterialInventory::getContainerId,inventoryAdjustmentRecordDO.getContainerId())
.eq(StringUtils.isNotBlank(inventoryAdjustmentRecordDO.getBatchNumber()),MaterialInventory::getBatchNumber,inventoryAdjustmentRecordDO.getBatchNumber())
.eq(inventoryAdjustmentRecordDO.getContainerId() != null, MaterialInventory::getContainerId, inventoryAdjustmentRecordDO.getContainerId())
.eq(BaseVOEntity::getDelFlag, 1));
if (ObjectUtil.isNotNull(materialInventory)) {
BeanUtils.copyProperties(materialInventory, inventoryAdjustmentRecord);
@@ -218,6 +246,8 @@ public class InventoryAdjustmentRecordDomainService {
inventoryAdjustmentRecord.setAdjustedGrossWeight(materialInventory.getGrossWeight());
inventoryAdjustmentRecord.setAdjustedVolume(materialInventory.getVolume());
inventoryAdjustmentRecord.setAdjustedArea(materialInventory.getArea());
// ===== 新增原状态库存扣减后立即落库避免依赖末尾统一更新 =====
materialInventoryService.updateById(materialInventory);
} else {
throw new ServiceException("根据原物料状态查询不到物料库存信息!");
}
@@ -228,8 +258,8 @@ public class InventoryAdjustmentRecordDomainService {
.eq(MaterialInventory::getStorageSectionId,inventoryAdjustmentRecordDO.getStorageSectionId())
.eq(MaterialInventory::getStorageLocationId,inventoryAdjustmentRecordDO.getStorageLocationId())
.eq(MaterialInventory::getMaterialStatusCode,inventoryAdjustmentRecordDO.getAdjustAfterStatusCode())
.eq(MaterialInventory::getBatchNumber,inventoryAdjustmentRecordDO.getBatchNumber())
.eq(MaterialInventory::getContainerId,inventoryAdjustmentRecordDO.getContainerId())
.eq(StringUtils.isNotBlank(inventoryAdjustmentRecordDO.getBatchNumber()),MaterialInventory::getBatchNumber,inventoryAdjustmentRecordDO.getBatchNumber())
.eq(inventoryAdjustmentRecordDO.getContainerId() != null,MaterialInventory::getContainerId,inventoryAdjustmentRecordDO.getContainerId())
.eq(BaseVOEntity::getDelFlag, 1));
if (ObjectUtil.isNotNull(materialInventory1)) {
materialInventory1.setInventoryQuantity(materialInventory1.getInventoryQuantity().add(inventoryAdjustmentRecordDO.getAdjustQuantity()));
@@ -245,21 +275,49 @@ public class InventoryAdjustmentRecordDomainService {
inventoryAdjustmentRecord.setAdjustAfterStatusCode(inventoryAdjustmentRecordDO.getAdjustAfterStatusCode());
inventoryAdjustmentRecord.setAdjustAfterStatusName(inventoryAdjustmentRecordDO.getAdjustAfterStatusName());
}
// ===== 新增adjustType 合法性兜底避免异常类型导致 materialInventory null 静默走完流程 =====
if (ObjectUtil.isNull(materialInventory)) {
throw new ServiceException("不支持的调整类型:" + inventoryAdjustmentRecordDO.getAdjustType());
}
//生成库存调整追溯记录
if (ObjectUtil.isNotNull(materialInventory)){
genInventoryStandingDetail(materialInventory, inventoryAdjustmentRecordDO.getAdjustQuantity());
}
materialInventoryService.updateById(materialInventory);
// ===== 修复末尾更新加 null 保护 =====
if (ObjectUtil.isNotNull(materialInventory)) {
materialInventoryService.updateById(materialInventory);
}
Boolean insert = inventoryAdjustmentRecordService.insert(inventoryAdjustmentRecord);
//推送oms库存调整记录
pushOms(materialInventory, inventoryAdjustmentRecordDO);
try{
// 当仓库启用 oms 才进行推送
if (warehousePO.getIsEnable() == 1) {
Boolean pushSuccess = pushOms(materialInventory, inventoryAdjustmentRecordDO);
if (!pushSuccess) {
throw new ServiceException("库存调整推送OMS失败,请稍后重试");
}
}
}catch (Exception e){
log.error("推送OMS库存调整记录异常,materialBaseInfoId={}, adjustDirection={}",
inventoryAdjustmentRecordDO.getMaterialBaseInfoId(),
inventoryAdjustmentRecordDO.getAdjustDirection());
throw new ServiceException("库存调整推送OMS失败,请稍后重试");
}
System.out.println("库存调整时间结束 ----" + System.currentTimeMillis());
return insert;
}
private void pushOms(MaterialInventory materialInventory,InventoryAdjustmentRecordDO inventoryAdjustmentRecordDO) {
/**
* 推送库存调整信息至OMS系统
* <p>
* 根据调整方向1=增加库存2=减少库存分别构造入库调整单或出库调整单
* 并通过Feign接口推送至OMS系统同时推送对应的物料明细信息
*
* @param materialInventory 调整涉及的物料库存信息包含仓库库区库位货主等上下文数据
* @param inventoryAdjustmentRecordDO 库存调整记录包含调整方向调整数量物料编码等数据
*/
private Boolean pushOms(MaterialInventory materialInventory,InventoryAdjustmentRecordDO inventoryAdjustmentRecordDO) {
LoginUser loginUser = SecurityUtils.getLoginUser();
UserPo userPo = loginUser.getUserPo();
MaterialBaseInfo materialBaseInfo = materialBaseInfoService.getById(materialInventory.getMaterialBaseInfoId());
@@ -327,8 +385,16 @@ public class InventoryAdjustmentRecordDomainService {
inMaterialDetail.setStorageLocationCode(materialInventory.getStorageLocationCode());
inMaterialDetail.setStorageLocationName(materialInventory.getStorageLocationName());
inMaterialDetail.setSingleGrossWeight(materialBaseInfo.getWeightLimit());
omsServiceFeign.pushInOrder(stockInOrder);
omsServiceFeign.pushInOrderDetail(inMaterialDetail);
AjaxResult inOrderResult = omsServiceFeign.pushInOrder(stockInOrder);
AjaxResult inOrderDetailResult = omsServiceFeign.pushInOrderDetail(inMaterialDetail);
if (inOrderResult == null || inOrderDetailResult == null
|| !"200".equals(String.valueOf(inOrderResult.get("code")))
|| !"200".equals(String.valueOf(inOrderDetailResult.get("code")))
) {
log.error("推送OMS入库调整单失败,pushInOrder={}, pushInOrderDetail={}",
inOrderResult, inOrderDetailResult);
return false;
}
} else {
StockOutOrderTZPD stockOutOrder = new StockOutOrderTZPD();
stockOutOrder.setOrganizationId(loginUser.getUserPo().getOrganizationId());
@@ -391,9 +457,18 @@ public class InventoryAdjustmentRecordDomainService {
outMaterialDetail.setStorageLocationCode(materialInventory.getStorageLocationCode());
outMaterialDetail.setStorageLocationName(materialInventory.getStorageLocationName());
outMaterialDetail.setSingleGrossWeight(materialBaseInfo.getWeightLimit());
omsServiceFeign.pushOutOrder(stockOutOrder);
omsServiceFeign.pushOutOrderDetail(outMaterialDetail);
AjaxResult inOrderResult = omsServiceFeign.pushOutOrder(stockOutOrder);
AjaxResult inOrderDetailResult = omsServiceFeign.pushOutOrderDetail(outMaterialDetail);
if (inOrderResult == null || inOrderDetailResult == null
|| !"200".equals(String.valueOf(inOrderResult.get("code")))
|| !"200".equals(String.valueOf(inOrderDetailResult.get("code")))
) {
log.error("推送OMS入库调整单失败,pushInOrder={}, pushInOrderDetail={}",
inOrderResult, inOrderDetailResult);
return false;
}
}
return true;
}
/**
@@ -71,6 +71,12 @@ public interface IMaterialInventoryService extends IService<MaterialInventory>
*/
public List<ImmediateInventoryPO> queryImmediateInventoryList(ImmediateInventoryDO immediateInventoryDO);
/**
* 查询即时库存合计数量
*/
public BigDecimal sumImmediateInventoryQuantity(ImmediateInventoryDO immediateInventoryDO);
/**
* @description 增加指定库存
* @author ZhouGY
@@ -38,6 +38,8 @@ public interface MaterialInventoryMapper extends BaseMapper<MaterialInventory>
public List<MaterialInventoryPO> queryListByHz(MaterialInventoryDO materialInventoryDO);
//查物料库存列表-货主+物料同一物料在不同货主下各一行
public List<MaterialInventoryPO> queryListByHzWl(MaterialInventoryDO materialInventoryDO);
//查物料库存列表-按货主+物料+仓库库存查询第三个页签update_time 取合并后最大值
public List<MaterialInventoryPO> queryListByHzWlUnit(MaterialInventoryDO materialInventoryDO);
/**
* @description 批量增加库存
@@ -91,6 +93,12 @@ public interface MaterialInventoryMapper extends BaseMapper<MaterialInventory>
*/
public List<ImmediateInventoryPO> queryImmediateInventoryList(ImmediateInventoryDO immediateInventoryDO);
/**
* 查询即时库存合计数量与列表相同筛选条件返回库存数量总和
*/
public BigDecimal sumImmediateInventoryQuantity(ImmediateInventoryDO immediateInventoryDO);
@Select("SELECT SUM(inventory_quantity) FROM material_inventory a LEFT JOIN material_base_info b ON a.material_base_info_id = b.material_base_info_id WHERE a.del_flag = 1 AND b.shipper_id = #{shipperId} AND b.material_base_info_id = #{materialBaseInfoId}")
public BigDecimal sumInventoryQuantityByShipperAndMaterialCode(@Param("shipperId") Long shipperId, @Param("materialBaseInfoId") Long materialBaseInfoId);
@@ -77,17 +77,19 @@ public class MaterialInventoryImpl extends ServiceImpl<MaterialInventoryMapper,
String queryRule = materialInventoryDO.getQueryRule();
if ("hz".equals(queryRule)) {
return materialInventoryMapper.queryListByHz(materialInventoryDO);
} else if ("hzwl".equals(queryRule)) {
} else if ("hzwl".equals(queryRule)) { // 货主查询
return materialInventoryMapper.queryListByHzWl(materialInventoryDO);
} else if ("wl".equals(queryRule)) {
} else if ("wl".equals(queryRule)) { // 物料查询
return materialInventoryMapper.queryListByWl(materialInventoryDO);
} else if ("kw".equals(queryRule)) {
return materialInventoryMapper.queryListByKw(materialInventoryDO);
} else if ("wlkw".equals(queryRule)) {
} else if ("wlkw".equals(queryRule)) { // 物料/库位查询
return materialInventoryMapper.queryListByWlKw(materialInventoryDO);
} else if ("wlExpiry".equals(queryRule)) {
} else if ("wlExpiry".equals(queryRule)) { // 物料/过期日期查询
return materialInventoryMapper.queryListByWlExpiry(materialInventoryDO);
} else if ("all".equals(queryRule)) {
} else if("hzwlunit".equals(queryRule)){ // 货主/物料查询
return materialInventoryMapper.queryListByHzWlUnit(materialInventoryDO);
}else if ("all".equals(queryRule)) { // 全部查询
return materialInventoryMapper.queryList(materialInventoryDO);
} else {
//不传返回全部
@@ -464,11 +466,29 @@ public class MaterialInventoryImpl extends ServiceImpl<MaterialInventoryMapper,
}
}
/**
* 分页查询即时库存列表
*
* @param immediateInventoryDO 即时库存查询条件含组织权限货主物料仓库数量区间等筛选条件
* @return 即时库存列表
*/
@Override
public List<ImmediateInventoryPO> queryImmediateInventoryList(ImmediateInventoryDO immediateInventoryDO) {
return materialInventoryMapper.queryImmediateInventoryList(immediateInventoryDO);
}
/**
* 查询即时库存合计数量
* <p>与列表查询使用相同筛选条件但不分页统计筛选条件下所有库存数量之和</p>
*
* @param immediateInventoryDO 即时库存查询条件与列表查询保持一致保证合计口径一致
* @return 库存数量合计值无数据时为 0
*/
@Override
public BigDecimal sumImmediateInventoryQuantity(ImmediateInventoryDO immediateInventoryDO) {
return materialInventoryMapper.sumImmediateInventoryQuantity(immediateInventoryDO);
}
/**
* @description 增加指定库存
* @author ZhouGY
@@ -103,6 +103,20 @@ public class MaterialInventoryDomainService {
return materialInventoryService.queryImmediateInventoryList(immediateInventoryDO);
}
/**
* 查询即时库存合计数量
*/
public BigDecimal sumImmediateInventoryQuantity(ImmediateInventoryDO immediateInventoryDO) {
return materialInventoryService.sumImmediateInventoryQuantity(immediateInventoryDO);
}
/**
* 根据查询条件获取物料库存信息
* <p>按货主组织物料仓库库位等条件查询返回汇总后的库存信息含库存数量合计</p>
*
* @param materialInventoryDO 物料库存查询条件含货主顶级组织物料基础信息仓库库位等
* @return 匹配条件的物料库存信息无匹配数据时返回 null
*/
public MaterialInventoryPO selectOneByWhere(MaterialInventoryDO materialInventoryDO) {
return materialInventoryService.selectOneByWhere(materialInventoryDO);
}
@@ -459,6 +459,7 @@ public class ReceiptMaterialDetailImpl extends ServiceImpl<ReceiptMaterialDetail
ReceiptMaterialDetail receiptMaterialDetailChild = new ReceiptMaterialDetail();
BeanUtils.copyProperties(receiptMaterialDetailDOChild, receiptMaterialDetailChild);
alignPersistedReceiptQuantityToCumulative(receiptMaterialDetailDOChild, receiptMaterialDetailChild);
normalizeZeroMetricsToNull(receiptMaterialDetailChild);
receiptMaterialDetailChild.setCreateBy(loginUser.getUserid());
receiptMaterialDetailChild.setCreateByName(loginUser.getUsername());
receiptMaterialDetailChild.setCreateTime(new Date());
@@ -474,9 +475,12 @@ public class ReceiptMaterialDetailImpl extends ServiceImpl<ReceiptMaterialDetail
}
}
}
ReceiptMaterialDetail receiptMaterialDetail = new ReceiptMaterialDetail();
BeanUtils.copyProperties(receiptMaterialDetailDO, receiptMaterialDetail);
alignPersistedReceiptQuantityToCumulative(receiptMaterialDetailDO, receiptMaterialDetail);
// total* 字段为 0 或空字符串时置为 null避免 MyBatis-Plus NOT_NULL 策略下覆盖已有数据
normalizeZeroMetricsToNull(receiptMaterialDetail);
receiptMaterialDetail.setUpdateBy(loginUser.getUserid());
receiptMaterialDetail.setUpdateByName(loginUser.getUsername());
receiptMaterialDetail.setUpdateTime(new Date());
@@ -488,23 +492,25 @@ public class ReceiptMaterialDetailImpl extends ServiceImpl<ReceiptMaterialDetail
}
//保存物料明细信息
saveOrUpdateBatch(receiptMaterialDetailList);
//批量新增/更新物料更多属性保留已有值仅更新有值的属性不再先删后插
mergeMaterialMoreDetail(materialMoreDetailList, stockReceiptOrderDO, receiptMaterialDetailDOList);
//批量新增/更新物料更多属性先删除该收货单下所有明细的旧批次属性再插入新值避免重复插入导致更新失效
if (!CollectionUtils.isEmpty(materialMoreDetailList)){
String receiptOrderNumber = stockReceiptOrderDO.getReceiptOrderNumber();
if (StringUtils.isBlank(receiptOrderNumber) && !CollectionUtils.isEmpty(receiptMaterialDetailDOList)) {
receiptOrderNumber = receiptMaterialDetailDOList.get(0).getReceiptOrderNumber();
}
if (StringUtils.isNotBlank(receiptOrderNumber)) {
java.util.Set<Long> uniqueIds = collectReceiptDetailUniqueIds(receiptMaterialDetailDOList);
if (!uniqueIds.isEmpty()) {
IMaterialMoreDetailService.remove(new QueryWrapper<MaterialMoreDetail>()
.eq("order_number", receiptOrderNumber)
.in("material_detail_unique_id", uniqueIds)
.eq("del_flag", 1));
}
}
IMaterialMoreDetailService.saveBatch(materialMoreDetailList);
}
// if (!CollectionUtils.isEmpty(materialMoreDetailList)){
// String receiptOrderNumber = stockReceiptOrderDO.getReceiptOrderNumber();
// if (StringUtils.isBlank(receiptOrderNumber) && !CollectionUtils.isEmpty(receiptMaterialDetailDOList)) {
// receiptOrderNumber = receiptMaterialDetailDOList.get(0).getReceiptOrderNumber();
// }
// if (StringUtils.isNotBlank(receiptOrderNumber)) {
// java.util.Set<Long> uniqueIds = collectReceiptDetailUniqueIds(receiptMaterialDetailDOList);
// if (!uniqueIds.isEmpty()) {
// IMaterialMoreDetailService.remove(new QueryWrapper<MaterialMoreDetail>()
// .eq("order_number", receiptOrderNumber)
// .in("material_detail_unique_id", uniqueIds)
// .eq("del_flag", 1));
// }
// }
// IMaterialMoreDetailService.saveBatch(materialMoreDetailList);
// }
//批量新增序列号
if (!CollectionUtils.isEmpty(materialDetailSerialNumberList)){
inMaterialDetailSerialNumberService.saveBatch(materialDetailSerialNumberList);
@@ -513,6 +519,144 @@ public class ReceiptMaterialDetailImpl extends ServiceImpl<ReceiptMaterialDetail
updateInMaterialDetailFromAttributeOption(receiptMaterialDetailDOList);
}
/**
* 批量合并物料更多属性有值则更新无值跳过保留旧值不存在则新增
* 替代原先 DELETE 全部再 INSERT的策略避免未填写字段丢失已有数据
* @param materialMoreDetailList 本次收货提交的批次属性列表
* @param stockReceiptOrderDO 收货单信息用于获取收货单号
* @param receiptMaterialDetailDOList 收货明细列表用于提取 uniqueId 集合
*/
private void mergeMaterialMoreDetail(List<MaterialMoreDetail> materialMoreDetailList,
StockReceiptOrderDO stockReceiptOrderDO,
List<ReceiptMaterialDetailDO> receiptMaterialDetailDOList) {
// 无批次属性则直接返回
if (CollectionUtils.isEmpty(materialMoreDetailList)) {
return;
}
// 无收货单号无法做增量更新退回全量插入
String receiptOrderNumber = stockReceiptOrderDO.getReceiptOrderNumber();
if (StringUtils.isBlank(receiptOrderNumber) && !CollectionUtils.isEmpty(receiptMaterialDetailDOList)) {
receiptOrderNumber = receiptMaterialDetailDOList.get(0).getReceiptOrderNumber();
}
// 无收货单号无法做增量更新退回全量插入
if (StringUtils.isBlank(receiptOrderNumber)) {
IMaterialMoreDetailService.saveBatch(materialMoreDetailList);
return;
}
// 无明细唯一ID无法做增量更新退回全量插入
java.util.Set<Long> uniqueIds = collectReceiptDetailUniqueIds(receiptMaterialDetailDOList);
if (uniqueIds.isEmpty()) {
IMaterialMoreDetailService.saveBatch(materialMoreDetailList);
return;
}
// 查询已存在的批次属性记录
List<MaterialMoreDetail> existingList = IMaterialMoreDetailService.list(
new QueryWrapper<MaterialMoreDetail>()
.eq("order_number", receiptOrderNumber) // 收货单号
.in("material_detail_unique_id", uniqueIds) // 明细唯一ID
.eq("del_flag", 1)); // 删除标志
// materialDetailUniqueId + batchDetailId 构建索引
Map<String, MaterialMoreDetail> existingMap = new HashMap<>();
for (MaterialMoreDetail existing : existingList) {
String key = buildMaterialMoreDetailKey(existing.getMaterialDetailUniqueId(), existing.getBatchDetailId());
existingMap.put(key, existing);
}
// 分离需要更新的 以及 需要新增的跳过空值保留旧数据
List<MaterialMoreDetail> toUpdate = new ArrayList<>();
List<MaterialMoreDetail> toInsert = new ArrayList<>();
for (MaterialMoreDetail incoming : materialMoreDetailList) {
// attributeValue 为空/空白时跳过不覆盖已有数据
if (StringUtils.isBlank(incoming.getAttributeValue())) {
continue;
}
// materialDetailUniqueId + batchDetailId 构建索引
String key = buildMaterialMoreDetailKey(incoming.getMaterialDetailUniqueId(), incoming.getBatchDetailId());
// 已存在的批次属性记录
MaterialMoreDetail existing = existingMap.get(key);
// 存在则更新 不存在则新增
if (existing != null) {
// 设置主键走 update保留已有记录的 id
incoming.setMaterialMoreDetailId(existing.getMaterialMoreDetailId());
// 更新现有记录
toUpdate.add(incoming);
} else {
// 插入新的记录
toInsert.add(incoming);
}
}
// 判断需更新的记录是否存在存在则更新
if (!toUpdate.isEmpty()) {
IMaterialMoreDetailService.updateBatchById(toUpdate);
}
// 判断是否存在需新增的记录存在则批量插入
if (!toInsert.isEmpty()) {
IMaterialMoreDetailService.saveBatch(toInsert);
}
}
/**
* 构建批次属性索引
* @param materialDetailUniqueId 明细唯一ID
* @param batchDetailId 批次属性ID
* @return 批次属性索引
*/
private static String buildMaterialMoreDetailKey(Long materialDetailUniqueId, Long batchDetailId) {
return (materialDetailUniqueId != null ? materialDetailUniqueId : "null") + "_"
+ (batchDetailId != null ? batchDetailId : "null");
}
/**
* total* 指标字段中值为 0 的置为 null
* MyBatis-Plus 默认 NOT_NULL 策略下null 不参与 SET 子句已有数据得以保留
* 注意仅对未填写场景生效用户确实需要填 0 的极端场景不受影响因前端通常传 null 表示未填
* @param receiptMaterialDetail 收货明细
* 需保证 total* 字段已赋值
* 需保证 alreadyReceipt* 字段已赋值
* 静态方法修改 receiptMaterialDetail 参数
**/
private static void normalizeZeroMetricsToNull(ReceiptMaterialDetail receiptMaterialDetail) {
// entity null 时直接返回
if (receiptMaterialDetail == null) {
return;
}
// receiptMaterialDetail totalNetWeight 字段为 0 时置为 null
if (isZeroBigDecimal(receiptMaterialDetail.getTotalNetWeight())) {
receiptMaterialDetail.setTotalNetWeight(null);
}
// receiptMaterialDetail totalGrossWeight 字段为 0 时置为 null
if (isZeroBigDecimal(receiptMaterialDetail.getTotalGrossWeight())) {
receiptMaterialDetail.setTotalGrossWeight(null);
}
// receiptMaterialDetail totalVolume 字段为 0 时置为 null
if (isZeroBigDecimal(receiptMaterialDetail.getTotalVolume())) {
receiptMaterialDetail.setTotalVolume(null);
}
// receiptMaterialDetail totalArea 字段为 0 时置为 null
if (isZeroBigDecimal(receiptMaterialDetail.getTotalArea())) {
receiptMaterialDetail.setTotalArea(null);
}
// receiptMaterialDetail alreadyReceiptNetWeight 字段为 0 时置为 null
if (isZeroBigDecimal(receiptMaterialDetail.getAlreadyReceiptNetWeight())) {
receiptMaterialDetail.setAlreadyReceiptNetWeight(null);
}
// receiptMaterialDetail alreadyReceiptGrossWeight 字段为 0 时置为 null
if (isZeroBigDecimal(receiptMaterialDetail.getAlreadyReceiptGrossWeight())) {
receiptMaterialDetail.setAlreadyReceiptGrossWeight(null);
}
// receiptMaterialDetail alreadyReceiptVolume 字段为 0 时置为 null
if (isZeroBigDecimal(receiptMaterialDetail.getAlreadyReceiptVolume())) {
receiptMaterialDetail.setAlreadyReceiptVolume(null);
}
// receiptMaterialDetail alreadyReceiptArea 字段为 0 时置为 null
if (isZeroBigDecimal(receiptMaterialDetail.getAlreadyReceiptArea())) {
receiptMaterialDetail.setAlreadyReceiptArea(null);
}
}
private static boolean isZeroBigDecimal(BigDecimal val) {
return val != null && val.compareTo(BigDecimal.ZERO) == 0;
}
private void setMore(ReceiptMaterialDetailDO receiptMaterialDetailDO) {
List<MaterialMoreDetailDO> materialMoreDetailList = receiptMaterialDetailDO.getMaterialMoreDetailList();
if (!CollectionUtils.isEmpty(materialMoreDetailList)) {
@@ -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;
@@ -42,6 +42,10 @@ public class ImmediateInventoryPO {
@Excel(name = "物料条形码")
private String barCode;
@ApiModelProperty("规格型号")
@Excel(name = "规格型号")
private String specificationModel;
@ApiModelProperty("库存数量")
@Excel(name = "库存数量")
private BigDecimal inventoryQuantity;
@@ -44,6 +44,10 @@ public class ImmediateInventoryDO extends BaseVOEntity {
@Excel(name = "物料条形码")
private String barCode;
@ApiModelProperty("规格型号")
@Excel(name = "规格型号")
private String specificationModel;
@ApiModelProperty("仓库id")
@Excel(name = "仓库id")
private Long warehouseId;
@@ -45,6 +45,10 @@ public class ImmediateInventoryDTO {
@Excel(name = "物料条形码")
private String barCode;
@ApiModelProperty("规格型号")
@Excel(name = "规格型号")
private String specificationModel;
@ApiModelProperty("仓库id")
@Excel(name = "仓库id")
private Long warehouseId;
@@ -23,6 +23,8 @@ import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.HashMap;
import java.util.List;
/**
@@ -48,13 +50,14 @@ public class StatementStatisticsApi {
*/
@ApiOperation("查询即时库存列表")
@GetMapping("/queryImmediateInventoryList")
public TableDataInfo queryImmediateInventoryList(ImmediateInventoryDTO immediateInventoryDTO)
public HashMap<String, Object> queryImmediateInventoryList(ImmediateInventoryDTO immediateInventoryDTO)
{
//转换实体
ImmediateInventoryDO immediateInventoryDO = immediateInventoryAssembler.toDO(immediateInventoryDTO);
startPage();
List<ImmediateInventoryPO> list = statementStatisticsService.queryImmediateInventoryList(immediateInventoryDO);
return getDataTable(list);
BigDecimal bigDecimal = statementStatisticsService.sumImmediateInventoryQuantity(immediateInventoryDO);
return getDataTableWarehouse(list,bigDecimal);
}
/**
* 分页查询入库日报表列表
@@ -129,4 +132,18 @@ public class StatementStatisticsApi {
rspData.setTotal(new PageInfo(list).getTotal());
return rspData;
}
/**
* 响应请求分页仓库数量 数据
*/
protected HashMap<String, Object> getDataTableWarehouse(List<?> list,BigDecimal bigDecimal)
{
HashMap<String, Object> stringObjectHashMap = new HashMap<>();
stringObjectHashMap.put("data",list);
stringObjectHashMap.put("total",new PageInfo(list).getTotal());
stringObjectHashMap.put("code",HttpStatus.SUCCESS);
stringObjectHashMap.put("msg","查询成功");
stringObjectHashMap.put("totalInventoryQuantity",bigDecimal);
return stringObjectHashMap;
}
}
@@ -5,7 +5,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<mapper namespace="com.mhd.wms.domain.handoverTaskOrder.repository.mapper.HandoverTaskOrderMapper">
<resultMap type="com.mhd.wms.domain.handoverTaskOrder.repository.po.HandoverTaskOrderPO" id="HandoverTaskOrderResult">
<result property="handoverTaskOrderId" column="handover_task_order_id" />
<id property="handoverTaskOrderId" column="handover_task_order_id" />
<result property="organizationId" column="organization_id" />
<result property="organizationName" column="organization_name" />
<result property="topOrganizationId" column="top_organization_id" />
@@ -45,7 +45,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<sql id="selectHandoverTaskOrderPo">
a.handover_task_order_id, a.organization_id, a.organization_name, a.top_organization_id, a.serial_number, a.task_number, a.status, a.platform_id,
a.handover_task_order_id AS handover_task_order_id, a.organization_id, a.organization_name, a.top_organization_id, a.serial_number, a.task_number, a.status, a.platform_id,
a.platform_code, a.platform_name, a.platform_use_time_id, a.platform_use_start_time, a.platform_use_end_time, a.platform_use_status,
a.order_type_code, a.order_type_name, a.expect_time, a.warehouse_id, a.warehouse_code, a.warehouse_name, a.shipper_id,
a.shipper_name, a.order_number, a.picking_order_number, a.remark, a.task_distribution, a.task_distribution_time, a.create_time, a.create_by, a.create_by_name, a.update_time,
@@ -162,7 +162,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
and a.material_base_info_id = #{materialBaseInfoId}
</if>
<if test="materialDetailId != null ">
and a.material_detail_id, = #{materialDetailId}
and a.material_detail_id = #{materialDetailId}
</if>
<!-- 容器号或批次号:containerOrBatch 优先;若 batchNumber 与 containerCode 相同则按 OR 查(PDA 单输入框传两个相同值) -->
<choose>
@@ -313,7 +313,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
and mi.material_base_info_id = #{materialBaseInfoId}
</if>
<if test="materialDetailId != null ">
and mi.material_detail_id, = #{materialDetailId}
and mi.material_detail_id = #{materialDetailId}
</if>
<choose>
<when test="containerOrBatch != null and containerOrBatch != ''">
@@ -528,6 +528,55 @@ 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 列:需求字段,全部聚合;包装单位优先库存表,回退物料基础信息表 -->
<sql id="selectMaterialInventoryPoByHzWlUnit">
a.shipper_id, a.shipper_code, a.shipper_name,
b.material_base_info_id, b.material_code, b.material_name, b.SPECIFICATION_MODEL,
a.warehouse_id, a.warehouse_code, a.warehouse_name,
a.organization_id, a.organization_name, a.top_organization_id,
MAX(b.material_type) AS material_type,
MAX(b.material_type_name) AS material_type_name,
MAX(b.bar_code) AS bar_code,
MAX(nvl(a.unit_name, b.unit_name)) AS unit_name,
MAX(b.pack_id) AS pack_id,
MAX(b.pack_code) AS pack_code,
MAX(b.pack_name) AS pack_name,
MAX(a.unit) AS unit,
IFNULL(SUM(a.freeze_quantity), 0) AS freeze_quantity,
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,
MIN(a.create_time) AS create_time, -- 新增:首次入库时间
MAX(a.update_time) AS update_time,
CASE WHEN IFNULL(SUM(a.inventory_quantity), 0) = 0 THEN 1 ELSE 0 END AS sort_order
</sql>
<select id="queryListByHzWlUnit"
parameterType="com.mhd.wms.domain.materialInventory.repository.todo.MaterialInventoryDO"
resultMap="MaterialInventoryResult">
select
<include refid="selectMaterialInventoryPoByHzWlUnit"/>
from material_inventory a
left join material_base_info b on a.material_base_info_id = b.material_base_info_id
<where>
a.del_flag = 1
<include refid="selectMaterialInventoryPo1"/>
<include refid="com.mhd.wms.domain.materialBaseInfo.repository.mapper.MaterialBaseInfoMapper.JoinMaterialBaseInfoPoWhere"/>
<if test="excludeZeroInventoryQuantity != null and excludeZeroInventoryQuantity == true">
and IFNULL(a.inventory_quantity, 0) &gt; 0
</if>
</where>
GROUP BY a.shipper_id, a.shipper_code, a.shipper_name,
b.material_base_info_id, b.material_code, b.material_name, b.SPECIFICATION_MODEL,
a.warehouse_id, a.warehouse_code, a.warehouse_name,
a.organization_id, a.organization_name, a.top_organization_id
ORDER BY sort_order, MAX(a.update_time) DESC
</select>
<select id="queryListByHz" parameterType="com.mhd.wms.domain.materialInventory.repository.todo.MaterialInventoryDO" resultMap="MaterialInventoryResult">
select
<include refid="selectMaterialInventoryPo"/>
@@ -781,12 +830,279 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
and container_id = #{containerId}
</update>
<sql id="immediateInventoryQueryWhere">
<if test="organizationId != null ">
and a.organization_id = #{organizationId}
</if>
<if test="topOrganizationId != null ">
and a.top_organization_id = #{topOrganizationId}
</if>
<if test="shipperName != null and shipperName != ''">
and (a.shipper_name = #{shipperName} OR b.shipper_name = #{shipperName})
</if>
<if test="shipperId != null and shipperId != '' ">
and a.shipper_id = #{shipperId}
</if>
<if test="warehouseId != null and warehouseId != '' ">
and a.warehouse_id = #{warehouseId}
</if>
<if test="warehouseCode != null and warehouseCode != '' ">
and a.warehouse_code = #{warehouseCode}
</if>
<if test="warehouseName != null and warehouseName != '' ">
and a.warehouse_name like concat('%', #{warehouseName}, '%')
</if>
<if test="materialName != null and materialName != '' ">
and b.material_name = #{materialName}
</if>
<if test="materialCode != null and materialCode != '' ">
and b.material_code = #{materialCode}
</if>
<if test="barCode != null and barCode != '' ">
and b.bar_code = #{barCode}
</if>
<if test="specificationModel != null and specificationModel != ''">
and b.specification_model = #{specificationModel}
</if>
<if test="batchNumber != null and batchNumber != ''">
and a.batch_number = #{batchNumber}
</if>
<if test="receivedQuantityStart != null ">
and ifnull(
(
SELECT
sum( c.receipt_quantity )
FROM
receipt_material_detail c
LEFT JOIN stock_receipt_order d ON c.receipt_order_number = d.receipt_order_number
AND d.del_flag = 1
LEFT JOIN stock_in_order e ON d.in_order_number = e.in_order_number and e.DEL_FLAG = 1 and d.DEL_FLAG = 1
WHERE
c.del_flag = 1 and d.STATUS = 3
AND e.warehouse_id = a.warehouse_id
AND (a.shipper_id IS NULL OR e.shipper_id = a.shipper_id)
AND c.material_base_info_id = a.material_base_info_id
and (c.BATCH_REF_NO = a.batch_ref_no or (c.BATCH_REF_NO is null and a.BATCH_REF_NO is null))
and (c.SHEET_REF_NO = a.sheet_ref_no or (c.SHEET_REF_NO is null and a.SHEET_REF_NO is null))
and (c.BOX_PALLET_NO = a.BOX_PALLET_NO or (c.BOX_PALLET_NO is null and a.BOX_PALLET_NO is null))
and (c.EXT_ATTR_1 = a.EXT_ATTR_1 or (c.EXT_ATTR_1 is null and a.EXT_ATTR_1 is null))
and (c.EXT_ATTR_2 = a.EXT_ATTR_2 or (c.EXT_ATTR_2 is null and a.EXT_ATTR_2 is null))
and (c.EXT_ATTR_3 = a.EXT_ATTR_3 or (c.EXT_ATTR_3 is null and a.EXT_ATTR_3 is null))
and (c.EXT_ATTR_4 = a.EXT_ATTR_4 or (c.EXT_ATTR_4 is null and a.EXT_ATTR_4 is null))
and (c.PRODUCTION_DATE = a.PRODUCTION_DATE or (c.PRODUCTION_DATE is null and a.PRODUCTION_DATE is null))
and (c.EXPIRY_DATE = a.EXPIRY_DATE or (c.EXPIRY_DATE is null and a.EXPIRY_DATE is null))
and (c.INVENTORY_DATE = a.INVENTORY_DATE or (c.INVENTORY_DATE is null and a.INVENTORY_DATE is null))
),
0
)> #{receivedQuantityStart}
</if>
<if test="receivedQuantityEnd != null ">
and ifnull(
(
SELECT
sum( c.receipt_quantity )
FROM
receipt_material_detail c
LEFT JOIN stock_receipt_order d ON c.receipt_order_number = d.receipt_order_number
AND d.del_flag = 1
LEFT JOIN stock_in_order e ON d.in_order_number = e.in_order_number and e.DEL_FLAG = 1 and d.DEL_FLAG = 1
WHERE
c.del_flag = 1 and d.STATUS = 3
AND e.warehouse_id = a.warehouse_id
AND (a.shipper_id IS NULL OR e.shipper_id = a.shipper_id)
AND c.material_base_info_id = a.material_base_info_id
and (c.BATCH_REF_NO = a.batch_ref_no or (c.BATCH_REF_NO is null and a.BATCH_REF_NO is null))
and (c.SHEET_REF_NO = a.sheet_ref_no or (c.SHEET_REF_NO is null and a.SHEET_REF_NO is null))
and (c.BOX_PALLET_NO = a.BOX_PALLET_NO or (c.BOX_PALLET_NO is null and a.BOX_PALLET_NO is null))
and (c.EXT_ATTR_1 = a.EXT_ATTR_1 or (c.EXT_ATTR_1 is null and a.EXT_ATTR_1 is null))
and (c.EXT_ATTR_2 = a.EXT_ATTR_2 or (c.EXT_ATTR_2 is null and a.EXT_ATTR_2 is null))
and (c.EXT_ATTR_3 = a.EXT_ATTR_3 or (c.EXT_ATTR_3 is null and a.EXT_ATTR_3 is null))
and (c.EXT_ATTR_4 = a.EXT_ATTR_4 or (c.EXT_ATTR_4 is null and a.EXT_ATTR_4 is null))
and (c.PRODUCTION_DATE = a.PRODUCTION_DATE or (c.PRODUCTION_DATE is null and a.PRODUCTION_DATE is null))
and (c.EXPIRY_DATE = a.EXPIRY_DATE or (c.EXPIRY_DATE is null and a.EXPIRY_DATE is null))
and (c.INVENTORY_DATE = a.INVENTORY_DATE or (c.INVENTORY_DATE is null and a.INVENTORY_DATE is null))
),
0
) &lt; #{receivedQuantityEnd}
</if>
<if test="shelvesQuantityStart != null ">
and ifnull(
(
SELECT
sum( c.shelves_quantity )
FROM
shelf_material_detail c
LEFT JOIN stock_shelf_order d ON c.shelf_order_number = d.shelf_order_number
AND d.del_flag = 1
LEFT JOIN stock_in_order e ON d.in_order_number = e.in_order_number and e.DEL_FLAG = 1 and d.DEL_FLAG = 1
WHERE
c.del_flag = 1
AND e.warehouse_id = a.warehouse_id
AND (a.shipper_id IS NULL OR e.shipper_id = a.shipper_id)
AND c.material_base_info_id = a.material_base_info_id
),
0
) > #{shelvesQuantityStart}
</if>
<if test="shelvesQuantityEnd != null ">
and ifnull(
(
SELECT
sum( c.shelves_quantity )
FROM
shelf_material_detail c
LEFT JOIN stock_shelf_order d ON c.shelf_order_number = d.shelf_order_number
AND d.del_flag = 1
LEFT JOIN stock_in_order e ON d.in_order_number = e.in_order_number and e.DEL_FLAG = 1 and d.DEL_FLAG = 1
WHERE
c.del_flag = 1
AND e.warehouse_id = a.warehouse_id
AND (a.shipper_id IS NULL OR e.shipper_id = a.shipper_id)
AND c.material_base_info_id = a.material_base_info_id
),
0
) &lt; #{shelvesQuantityEnd}
</if>
<if test="pickQuantityStart != null ">
and ifnull(
(
SELECT
sum( c.picking_quantity )
FROM
picking_material_detail c
LEFT JOIN picking_order d ON c.picking_order_number = d.PICKING_ORDER_NUMBER and c.del_flag = 1 and d.del_flag=1
left join STOCK_OUT_ORDER e ON d.ORDER_NUMBER = e.OUT_ORDER_NUMBER and e.del_flag = 1
WHERE
c.del_flag = 1 and d.STATUS = 3 and e.STATUS = 7
AND d.warehouse_id = a.warehouse_id
AND (a.shipper_id IS NULL OR d.shipper_id = a.shipper_id)
AND c.material_base_info_id = a.material_base_info_id
AND c.MATERIAL_INVENTORY_ID = a.MATERIAL_INVENTORY_ID
),
0
) > #{pickQuantityStart}
</if>
<if test="pickQuantityEnd != null ">
and ifnull(
(
SELECT
sum( c.picking_quantity )
FROM
picking_material_detail c
LEFT JOIN picking_order d ON c.picking_order_number = d.PICKING_ORDER_NUMBER and c.del_flag = 1 and d.del_flag=1
left join STOCK_OUT_ORDER e ON d.ORDER_NUMBER = e.OUT_ORDER_NUMBER and e.del_flag = 1
WHERE
c.del_flag = 1 and d.STATUS = 3 and e.STATUS = 7
AND d.warehouse_id = a.warehouse_id
AND (a.shipper_id IS NULL OR d.shipper_id = a.shipper_id)
AND c.material_base_info_id = a.material_base_info_id
AND c.MATERIAL_INVENTORY_ID = a.MATERIAL_INVENTORY_ID
),
0
) &lt; #{pickQuantityEnd}
</if>
<if test="checkQuantityBegin != null ">
and
ifnull(
(
SELECT
SUM(c.CHECK_QUANTITY) AS CHECK_QUANTITY
FROM
OUT_MATERIAL_DETAIL c
LEFT JOIN STOCK_OUT_ORDER d ON c.OUT_ORDER_NUMBER = d.OUT_ORDER_NUMBER and c.del_flag = 1 and d.del_flag = 1
LEFT JOIN HANDOVER_TASK_ORDER e ON d.OUT_ORDER_NUMBER = e.ORDER_NUMBER
WHERE
d.CHECK_STATUS in (2,3) and e.STATUS = 1 and d.STATUS in (8,12)
AND d.DEL_FLAG = 1
AND c.DEL_FLAG = 1
and e.del_flag = 1
AND d.warehouse_id = a.warehouse_id
AND (a.shipper_id IS NULL OR d.shipper_id = a.shipper_id)
AND c.material_base_info_id = a.material_base_info_id
AND c.MATERIAL_INVENTORY_ID = a.MATERIAL_INVENTORY_ID
),
0
) > #{checkQuantityBegin}
</if>
<if test="checkQuantityEnd != null ">
and
ifnull(
(
SELECT
SUM(c.CHECK_QUANTITY) AS CHECK_QUANTITY
FROM
OUT_MATERIAL_DETAIL c
LEFT JOIN STOCK_OUT_ORDER d ON c.OUT_ORDER_NUMBER = d.OUT_ORDER_NUMBER and c.del_flag = 1 and d.del_flag = 1
LEFT JOIN HANDOVER_TASK_ORDER e ON d.OUT_ORDER_NUMBER = e.ORDER_NUMBER
WHERE
d.CHECK_STATUS in (2,3) and e.STATUS = 1 and d.STATUS in (8,12)
AND d.DEL_FLAG = 1
AND c.DEL_FLAG = 1
and e.del_flag = 1
AND d.warehouse_id = a.warehouse_id
AND (a.shipper_id IS NULL OR d.shipper_id = a.shipper_id)
AND c.material_base_info_id = a.material_base_info_id
AND c.MATERIAL_INVENTORY_ID = a.MATERIAL_INVENTORY_ID
),
0
) &lt; #{checkQuantityEnd}
</if>
<if test="inventoryQuantity != null ">
and a.inventory_quantity = #{inventoryQuantity}
</if>
<if test="inventoryQuantityStart != null ">
and a.inventory_quantity > #{inventoryQuantityStart}
</if>
<if test="inventoryQuantityEnd != null ">
and a.inventory_quantity &lt; #{inventoryQuantityEnd}
</if>
<if test="allocationQuantityStart != null ">
and a.allocation_quantity > #{allocationQuantityStart}
</if>
<if test="allocationQuantityEnd != null ">
and a.allocation_quantity &lt; #{allocationQuantityEnd}
</if>
<if test="freezeQuantityStart != null ">
and a.freeze_quantity > #{freezeQuantityStart}
</if>
<if test="freezeQuantityEnd != null ">
and a.freeze_quantity &lt; #{freezeQuantityEnd}
</if>
</sql>
<resultMap type="com.mhd.wms.domain.statementStatistics.po.ImmediateInventoryPO" id="queryImmediateInventoryListResult">
<result property="shipperName" column="shipper_name" />
<result property="materialCode" column="material_code" />
<result property="materialName" column="material_name" />
<result property="barCode" column="bar_code" />
<result property="specificationModel" column="specification_model" />
<result property="warehouseName" column="warehouse_name" />
<result property="inventoryQuantity" column="inventory_quantity" />
<result property="allocationQuantity" column="allocation_quantity" />
@@ -826,6 +1142,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
b.material_name,
b.material_code,
b.bar_code,
b.specification_model,
<!-- sum(a.inventory_quantity) inventory_quantity,
sum(a.allocation_quantity) allocation_quantity,
sum(a.freeze_quantity) freeze_quantity,-->
@@ -995,271 +1312,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
WHERE
a.del_flag = 1
<if test="organizationId != null ">
and a.organization_id = #{organizationId}
</if>
<if test="topOrganizationId != null ">
and a.top_organization_id = #{topOrganizationId}
</if>
<if test="shipperName != null and shipperName != ''">
and (a.shipper_name = #{shipperName} OR b.shipper_name = #{shipperName})
</if>
<if test="shipperId != null and shipperId != '' ">
and a.shipper_id = #{shipperId}
</if>
<if test="warehouseId != null and warehouseId != '' ">
and a.warehouse_id = #{warehouseId}
</if>
<if test="warehouseCode != null and warehouseCode != '' ">
and a.warehouse_code = #{warehouseCode}
</if>
<if test="warehouseName != null and warehouseName != '' ">
and a.warehouse_name like concat('%', #{warehouseName}, '%')
</if>
<if test="materialName != null and materialName != '' ">
and b.material_name = #{materialName}
</if>
<if test="materialCode != null and materialCode != '' ">
and b.material_code = #{materialCode}
</if>
<if test="barCode != null and barCode != '' ">
and b.bar_code = #{barCode}
</if>
<if test="batchNumber != null and batchNumber != ''">
and a.batch_number = #{batchNumber}
</if>
<if test="receivedQuantityStart != null ">
and ifnull(
(
SELECT
sum( c.receipt_quantity )
FROM
receipt_material_detail c
LEFT JOIN stock_receipt_order d ON c.receipt_order_number = d.receipt_order_number
AND d.del_flag = 1
LEFT JOIN stock_in_order e ON d.in_order_number = e.in_order_number and e.DEL_FLAG = 1 and d.DEL_FLAG = 1
WHERE
c.del_flag = 1 and d.STATUS = 3
AND e.warehouse_id = a.warehouse_id
AND (a.shipper_id IS NULL OR e.shipper_id = a.shipper_id)
AND c.material_base_info_id = a.material_base_info_id
and (c.BATCH_REF_NO = a.batch_ref_no or (c.BATCH_REF_NO is null and a.BATCH_REF_NO is null))
and (c.SHEET_REF_NO = a.sheet_ref_no or (c.SHEET_REF_NO is null and a.SHEET_REF_NO is null))
and (c.BOX_PALLET_NO = a.BOX_PALLET_NO or (c.BOX_PALLET_NO is null and a.BOX_PALLET_NO is null))
and (c.EXT_ATTR_1 = a.EXT_ATTR_1 or (c.EXT_ATTR_1 is null and a.EXT_ATTR_1 is null))
and (c.EXT_ATTR_2 = a.EXT_ATTR_2 or (c.EXT_ATTR_2 is null and a.EXT_ATTR_2 is null))
and (c.EXT_ATTR_3 = a.EXT_ATTR_3 or (c.EXT_ATTR_3 is null and a.EXT_ATTR_3 is null))
and (c.EXT_ATTR_4 = a.EXT_ATTR_4 or (c.EXT_ATTR_4 is null and a.EXT_ATTR_4 is null))
and (c.PRODUCTION_DATE = a.PRODUCTION_DATE or (c.PRODUCTION_DATE is null and a.PRODUCTION_DATE is null))
and (c.EXPIRY_DATE = a.EXPIRY_DATE or (c.EXPIRY_DATE is null and a.EXPIRY_DATE is null))
and (c.INVENTORY_DATE = a.INVENTORY_DATE or (c.INVENTORY_DATE is null and a.INVENTORY_DATE is null))
),
0
)> #{receivedQuantityStart}
</if>
<if test="receivedQuantityEnd != null ">
and ifnull(
(
SELECT
sum( c.receipt_quantity )
FROM
receipt_material_detail c
LEFT JOIN stock_receipt_order d ON c.receipt_order_number = d.receipt_order_number
AND d.del_flag = 1
LEFT JOIN stock_in_order e ON d.in_order_number = e.in_order_number and e.DEL_FLAG = 1 and d.DEL_FLAG = 1
WHERE
c.del_flag = 1 and d.STATUS = 3
AND e.warehouse_id = a.warehouse_id
AND (a.shipper_id IS NULL OR e.shipper_id = a.shipper_id)
AND c.material_base_info_id = a.material_base_info_id
and (c.BATCH_REF_NO = a.batch_ref_no or (c.BATCH_REF_NO is null and a.BATCH_REF_NO is null))
and (c.SHEET_REF_NO = a.sheet_ref_no or (c.SHEET_REF_NO is null and a.SHEET_REF_NO is null))
and (c.BOX_PALLET_NO = a.BOX_PALLET_NO or (c.BOX_PALLET_NO is null and a.BOX_PALLET_NO is null))
and (c.EXT_ATTR_1 = a.EXT_ATTR_1 or (c.EXT_ATTR_1 is null and a.EXT_ATTR_1 is null))
and (c.EXT_ATTR_2 = a.EXT_ATTR_2 or (c.EXT_ATTR_2 is null and a.EXT_ATTR_2 is null))
and (c.EXT_ATTR_3 = a.EXT_ATTR_3 or (c.EXT_ATTR_3 is null and a.EXT_ATTR_3 is null))
and (c.EXT_ATTR_4 = a.EXT_ATTR_4 or (c.EXT_ATTR_4 is null and a.EXT_ATTR_4 is null))
and (c.PRODUCTION_DATE = a.PRODUCTION_DATE or (c.PRODUCTION_DATE is null and a.PRODUCTION_DATE is null))
and (c.EXPIRY_DATE = a.EXPIRY_DATE or (c.EXPIRY_DATE is null and a.EXPIRY_DATE is null))
and (c.INVENTORY_DATE = a.INVENTORY_DATE or (c.INVENTORY_DATE is null and a.INVENTORY_DATE is null))
),
0
) &lt; #{receivedQuantityEnd}
</if>
<if test="shelvesQuantityStart != null ">
and ifnull(
(
SELECT
sum( c.shelves_quantity )
FROM
shelf_material_detail c
LEFT JOIN stock_shelf_order d ON c.shelf_order_number = d.shelf_order_number
AND d.del_flag = 1
LEFT JOIN stock_in_order e ON d.in_order_number = e.in_order_number and e.DEL_FLAG = 1 and d.DEL_FLAG = 1
WHERE
c.del_flag = 1
AND e.warehouse_id = a.warehouse_id
AND (a.shipper_id IS NULL OR e.shipper_id = a.shipper_id)
AND c.material_base_info_id = a.material_base_info_id
),
0
) > #{shelvesQuantityStart}
</if>
<if test="shelvesQuantityEnd != null ">
and ifnull(
(
SELECT
sum( c.shelves_quantity )
FROM
shelf_material_detail c
LEFT JOIN stock_shelf_order d ON c.shelf_order_number = d.shelf_order_number
AND d.del_flag = 1
LEFT JOIN stock_in_order e ON d.in_order_number = e.in_order_number and e.DEL_FLAG = 1 and d.DEL_FLAG = 1
WHERE
c.del_flag = 1
AND e.warehouse_id = a.warehouse_id
AND (a.shipper_id IS NULL OR e.shipper_id = a.shipper_id)
AND c.material_base_info_id = a.material_base_info_id
),
0
) &lt; #{shelvesQuantityEnd}
</if>
<if test="pickQuantityStart != null ">
and ifnull(
(
SELECT
sum( c.picking_quantity )
FROM
picking_material_detail c
LEFT JOIN picking_order d ON c.picking_order_number = d.PICKING_ORDER_NUMBER and c.del_flag = 1 and d.del_flag=1
left join STOCK_OUT_ORDER e ON d.ORDER_NUMBER = e.OUT_ORDER_NUMBER and e.del_flag = 1
WHERE
c.del_flag = 1 and d.STATUS = 3 and e.STATUS = 7
AND d.warehouse_id = a.warehouse_id
AND (a.shipper_id IS NULL OR d.shipper_id = a.shipper_id)
AND c.material_base_info_id = a.material_base_info_id
AND c.MATERIAL_INVENTORY_ID = a.MATERIAL_INVENTORY_ID
),
0
) > #{pickQuantityStart}
</if>
<if test="pickQuantityEnd != null ">
and ifnull(
(
SELECT
sum( c.picking_quantity )
FROM
picking_material_detail c
LEFT JOIN picking_order d ON c.picking_order_number = d.PICKING_ORDER_NUMBER and c.del_flag = 1 and d.del_flag=1
left join STOCK_OUT_ORDER e ON d.ORDER_NUMBER = e.OUT_ORDER_NUMBER and e.del_flag = 1
WHERE
c.del_flag = 1 and d.STATUS = 3 and e.STATUS = 7
AND d.warehouse_id = a.warehouse_id
AND (a.shipper_id IS NULL OR d.shipper_id = a.shipper_id)
AND c.material_base_info_id = a.material_base_info_id
AND c.MATERIAL_INVENTORY_ID = a.MATERIAL_INVENTORY_ID
),
0
) &lt; #{pickQuantityEnd}
</if>
<!--
GROUP BY
a.warehouse_id,
a.material_base_info_id,
a.shipper_id
HAVING 1=1-->
<if test="checkQuantityBegin != null ">
and
ifnull(
(
SELECT
SUM(c.CHECK_QUANTITY) AS CHECK_QUANTITY
FROM
OUT_MATERIAL_DETAIL c
LEFT JOIN STOCK_OUT_ORDER d ON c.OUT_ORDER_NUMBER = d.OUT_ORDER_NUMBER and c.del_flag = 1 and d.del_flag = 1
LEFT JOIN HANDOVER_TASK_ORDER e ON d.OUT_ORDER_NUMBER = e.ORDER_NUMBER
WHERE
d.CHECK_STATUS in (2,3) and e.STATUS = 1 and d.STATUS in (8,12)
AND d.DEL_FLAG = 1
AND c.DEL_FLAG = 1
and e.del_flag = 1
AND d.warehouse_id = a.warehouse_id
AND (a.shipper_id IS NULL OR d.shipper_id = a.shipper_id)
AND c.material_base_info_id = a.material_base_info_id
AND c.MATERIAL_INVENTORY_ID = a.MATERIAL_INVENTORY_ID
),
0
) > #{checkQuantityBegin}
</if>
<if test="checkQuantityEnd != null ">
and
ifnull(
(
SELECT
SUM(c.CHECK_QUANTITY) AS CHECK_QUANTITY
FROM
OUT_MATERIAL_DETAIL c
LEFT JOIN STOCK_OUT_ORDER d ON c.OUT_ORDER_NUMBER = d.OUT_ORDER_NUMBER and c.del_flag = 1 and d.del_flag = 1
LEFT JOIN HANDOVER_TASK_ORDER e ON d.OUT_ORDER_NUMBER = e.ORDER_NUMBER
WHERE
d.CHECK_STATUS in (2,3) and e.STATUS = 1 and d.STATUS in (8,12)
AND d.DEL_FLAG = 1
AND c.DEL_FLAG = 1
and e.del_flag = 1
AND d.warehouse_id = a.warehouse_id
AND (a.shipper_id IS NULL OR d.shipper_id = a.shipper_id)
AND c.material_base_info_id = a.material_base_info_id
AND c.MATERIAL_INVENTORY_ID = a.MATERIAL_INVENTORY_ID
),
0
) &lt; #{checkQuantityEnd}
</if>
<if test="inventoryQuantity != null ">
and a.inventory_quantity = #{inventoryQuantity}
</if>
<if test="inventoryQuantityStart != null ">
and a.inventory_quantity > #{inventoryQuantityStart}
</if>
<if test="inventoryQuantityEnd != null ">
and a.inventory_quantity &lt; #{inventoryQuantityEnd}
</if>
<if test="allocationQuantityStart != null ">
and a.allocation_quantity > #{allocationQuantityStart}
</if>
<if test="allocationQuantityEnd != null ">
and a.allocation_quantity &lt; #{allocationQuantityEnd}
</if>
<if test="freezeQuantityStart != null ">
and a.freeze_quantity > #{freezeQuantityStart}
</if>
<if test="freezeQuantityEnd != null ">
and a.freeze_quantity &lt; #{freezeQuantityEnd}
</if>
<include refid="immediateInventoryQueryWhere"/>
ORDER BY GREATEST(
IFNULL(a.update_time, '1970-01-01 00:00:00'),
IFNULL((
@@ -1330,6 +1383,15 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
</select>
<select id="sumImmediateInventoryQuantity" parameterType="com.mhd.wms.domain.statementStatistics.todo.ImmediateInventoryDO"
resultType="java.math.BigDecimal">
SELECT IFNULL(SUM(a.inventory_quantity), 0)
FROM material_inventory a
left join material_base_info b on a.material_base_info_id = b.material_base_info_id
WHERE a.del_flag = 1
<include refid="immediateInventoryQueryWhere"/>
</select>
<select id="selectListByWhere" parameterType="com.mhd.wms.domain.materialInventory.entity.MaterialInventory"
resultMap="MaterialInventoryResult">
@@ -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,
+6
View File
@@ -0,0 +1,6 @@
ALTER TABLE NGWL_TEST_SYSTEM.CONTRACT_MANAGE_DETAIL
ADD (SERVICE_ITEMS_CODE VARCHAR(100),
SERVICE_ITEMS_NAME VARCHAR(200));
COMMENT ON COLUMN NGWL_TEST_SYSTEM.CONTRACT_MANAGE_DETAIL.SERVICE_ITEMS_CODE IS '费用类别编码(服务项编码)';
COMMENT ON COLUMN NGWL_TEST_SYSTEM.CONTRACT_MANAGE_DETAIL.SERVICE_ITEMS_NAME IS '费用类别名称(服务项名称)';