Merge branch 'refs/heads/dev-ty1.2' into dev

# Conflicts:
#	mhd-api/mhd-api-system/src/main/java/com/mhd/system/api/BmsServiceFeign.java
#	mhd-api/mhd-api-system/src/main/java/com/mhd/system/api/OmsServiceFeign.java
#	mhd-api/mhd-api-system/src/main/java/com/mhd/system/api/WlhyServiceFeign.java
#	mhd-api/mhd-api-system/src/main/java/com/mhd/system/api/WmsServiceFeign.java
#	mhd-api/mhd-api-system/src/main/java/com/mhd/system/api/YmsServiceFeign.java
#	mhd-common/mhd-common-core/src/main/java/com/mhd/common/core/feign/ThirdPartyServiceFeign.java
#	mhd_oms/src/main/java/com/mhd/oms/infrastructure/feign/ThirdPartyServiceFeign.java
#	mhd_oms/src/main/resources/bootstrap.yml
This commit is contained in:
rcx
2026-09-01 23:49:08 +08:00
111 changed files with 4773 additions and 320 deletions
@@ -0,0 +1,76 @@
package com.mhd.wms.application.service.inboundRank;
import com.mhd.common.core.exception.ServiceException;
import com.mhd.common.core.utils.StringUtils;
import com.mhd.common.security.utils.SecurityUtils;
import com.mhd.system.api.domain.cache.AssociationWarehouseCacheDO;
import com.mhd.system.api.domain.cache.SystemServiceCacheUtil;
import com.mhd.system.api.model.LoginUser;
import com.mhd.wms.domain.inboundRank.repository.po.InboundMaterialRankPO;
import com.mhd.wms.domain.inboundRank.repository.po.InboundRankTotalPO;
import com.mhd.wms.domain.inboundRank.repository.todo.InboundRankDO;
import com.mhd.wms.domain.inboundRank.service.InboundRankDomainService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
/**
* 入库排名统计应用服务
*
* <p>负责登录用户组织隔离注入、日期区间校验,查询逻辑在 InboundRankDomainService → InboundRankMapper.xml</p>
*
* @author rcx
* @date 2026-08-31
*/
@Service
@Slf4j
public class InboundRankApplicationService {
@Autowired
private InboundRankDomainService inboundRankDomainService;
/**
* 分页查询商品入库排名列表(仓单+货品汇总,按件数降序)
*/
public List<InboundMaterialRankPO> queryMaterialRankList(InboundRankDO inboundRankDO) {
fillLoginContext(inboundRankDO);
return inboundRankDomainService.queryMaterialRankList(inboundRankDO);
}
/**
* 商品入库排名合计(当前筛选条件全量,不分页)
*/
public InboundRankTotalPO queryMaterialRankTotal(InboundRankDO inboundRankDO) {
return inboundRankDomainService.queryMaterialRankTotal(inboundRankDO);
}
/**
* 导出商品入库排名(不分页全量)
*/
public List<InboundMaterialRankPO> exportMaterialRank(InboundRankDO inboundRankDO) {
fillLoginContext(inboundRankDO);
return inboundRankDomainService.queryMaterialRankList(inboundRankDO);
}
/**
* 注入登录用户组织隔离与关联仓库,并校验入仓日期区间必填
*/
private void fillLoginContext(InboundRankDO inboundRankDO) {
if (StringUtils.isEmpty(inboundRankDO.getWarehouseDateStart()) || StringUtils.isEmpty(inboundRankDO.getWarehouseDateEnd())) {
throw new ServiceException("请选择统计日期区间");
}
LoginUser loginUser = SecurityUtils.getLoginUser();
if (loginUser != null && loginUser.getUserPo() != null) {
Long topOrganizationId = loginUser.getUserPo().getTopOrganizationId();
if (topOrganizationId != null && topOrganizationId != 1) {
inboundRankDO.setTopOrganizationId(topOrganizationId);
}
AssociationWarehouseCacheDO associationWarehouseCacheDO = SystemServiceCacheUtil.getAssociationWarehouseCache(loginUser.getUserid());
if (associationWarehouseCacheDO != null && associationWarehouseCacheDO.getWarehouseId() != null) {
inboundRankDO.setWarehouseId(associationWarehouseCacheDO.getWarehouseId());
}
}
}
}
@@ -0,0 +1,100 @@
package com.mhd.wms.application.service.outboundRank;
import com.mhd.common.core.utils.StringUtils;
import com.mhd.common.core.exception.ServiceException;
import com.mhd.common.security.utils.SecurityUtils;
import com.mhd.system.api.domain.cache.AssociationWarehouseCacheDO;
import com.mhd.system.api.domain.cache.SystemServiceCacheUtil;
import com.mhd.system.api.model.LoginUser;
import com.mhd.wms.domain.outboundRank.repository.po.OutboundLineRankPO;
import com.mhd.wms.domain.outboundRank.repository.po.OutboundMaterialRankPO;
import com.mhd.wms.domain.outboundRank.repository.po.OutboundRankTotalPO;
import com.mhd.wms.domain.outboundRank.repository.todo.OutboundRankDO;
import com.mhd.wms.domain.outboundRank.service.OutboundRankDomainService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
/**
* 出库排名统计应用服务
*
* <p>负责登录用户组织隔离注入、日期区间校验,统计逻辑在 OutboundRankDomainService → OutboundRankMapper.xml</p>
*
* @author rcx
* @date 2026-08-31
*/
@Service
@Slf4j
public class OutboundRankApplicationService {
@Autowired
private OutboundRankDomainService outboundRankDomainService;
/**
* 分页查询商品出库排名列表
*/
public List<OutboundMaterialRankPO> queryMaterialRankList(OutboundRankDO outboundRankDO) {
fillLoginContext(outboundRankDO);
return outboundRankDomainService.queryMaterialRankList(outboundRankDO);
}
/**
* 分页查询线路出库排名列表
*/
public List<OutboundLineRankPO> queryLineRankList(OutboundRankDO outboundRankDO) {
fillLoginContext(outboundRankDO);
return outboundRankDomainService.queryLineRankList(outboundRankDO);
}
/**
* 商品出库排名合计(当前筛选条件全量,不分页)
*/
public OutboundRankTotalPO queryMaterialRankTotal(OutboundRankDO outboundRankDO) {
return outboundRankDomainService.queryMaterialRankTotal(outboundRankDO);
}
/**
* 线路出库排名合计(当前筛选条件全量,不分页)
*/
public OutboundRankTotalPO queryLineRankTotal(OutboundRankDO outboundRankDO) {
return outboundRankDomainService.queryLineRankTotal(outboundRankDO);
}
/**
* 导出商品出库排名(不分页全量)
*/
public List<OutboundMaterialRankPO> exportMaterialRankList(OutboundRankDO outboundRankDO) {
fillLoginContext(outboundRankDO);
return outboundRankDomainService.queryMaterialRankList(outboundRankDO);
}
/**
* 导出线路出库排名(不分页全量)
*/
public List<OutboundLineRankPO> exportLineRankList(OutboundRankDO outboundRankDO) {
fillLoginContext(outboundRankDO);
return outboundRankDomainService.queryLineRankList(outboundRankDO);
}
/**
* 注入登录用户组织隔离与关联仓库,并校验日期区间必填
*/
private void fillLoginContext(OutboundRankDO outboundRankDO) {
if (StringUtils.isEmpty(outboundRankDO.getCreateTimeStart()) || StringUtils.isEmpty(outboundRankDO.getCreateTimeEnd())) {
throw new ServiceException("请选择统计日期区间");
}
LoginUser loginUser = SecurityUtils.getLoginUser();
if (loginUser != null && loginUser.getUserPo() != null) {
Long topOrganizationId = loginUser.getUserPo().getTopOrganizationId();
if (topOrganizationId != null && topOrganizationId != 1) {
outboundRankDO.setTopOrganizationId(topOrganizationId);
}
AssociationWarehouseCacheDO associationWarehouseCacheDO = SystemServiceCacheUtil.getAssociationWarehouseCache(loginUser.getUserid());
if (associationWarehouseCacheDO != null && associationWarehouseCacheDO.getWarehouseId() != null) {
outboundRankDO.setWarehouseId(associationWarehouseCacheDO.getWarehouseId());
}
}
}
}
@@ -0,0 +1,26 @@
package com.mhd.wms.domain.inboundRank.repository.facade;
import com.mhd.wms.domain.inboundRank.repository.po.InboundMaterialRankPO;
import com.mhd.wms.domain.inboundRank.repository.po.InboundRankTotalPO;
import com.mhd.wms.domain.inboundRank.repository.todo.InboundRankDO;
import java.util.List;
/**
* 入库排名统计Service接口
*
* @author rcx
* @date 2026-08-31
*/
public interface IInboundRankService {
/**
* 商品入库排名列表(仓单+货品汇总,按件数降序)
*/
List<InboundMaterialRankPO> queryMaterialRankList(InboundRankDO inboundRankDO);
/**
* 商品入库排名合计(不分页)
*/
InboundRankTotalPO queryMaterialRankTotal(InboundRankDO inboundRankDO);
}
@@ -0,0 +1,26 @@
package com.mhd.wms.domain.inboundRank.repository.mapper;
import com.mhd.wms.domain.inboundRank.repository.po.InboundMaterialRankPO;
import com.mhd.wms.domain.inboundRank.repository.po.InboundRankTotalPO;
import com.mhd.wms.domain.inboundRank.repository.todo.InboundRankDO;
import java.util.List;
/**
* 入库排名统计Mapper接口
*
* @author rcx
* @date 2026-08-31
*/
public interface InboundRankMapper {
/**
* 商品入库排名列表(仓单+货品汇总,按件数降序)
*/
List<InboundMaterialRankPO> queryMaterialRankList(InboundRankDO inboundRankDO);
/**
* 商品入库排名合计(不分页,当前筛选条件全量合计)
*/
InboundRankTotalPO queryMaterialRankTotal(InboundRankDO inboundRankDO);
}
@@ -0,0 +1,34 @@
package com.mhd.wms.domain.inboundRank.repository.persistence;
import com.mhd.wms.domain.inboundRank.repository.facade.IInboundRankService;
import com.mhd.wms.domain.inboundRank.repository.mapper.InboundRankMapper;
import com.mhd.wms.domain.inboundRank.repository.po.InboundMaterialRankPO;
import com.mhd.wms.domain.inboundRank.repository.po.InboundRankTotalPO;
import com.mhd.wms.domain.inboundRank.repository.todo.InboundRankDO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
/**
* 入库排名统计Service业务层处理
*
* @author rcx
* @date 2026-08-31
*/
@Service
public class InboundRankImpl implements IInboundRankService {
@Autowired
private InboundRankMapper inboundRankMapper;
@Override
public List<InboundMaterialRankPO> queryMaterialRankList(InboundRankDO inboundRankDO) {
return inboundRankMapper.queryMaterialRankList(inboundRankDO);
}
@Override
public InboundRankTotalPO queryMaterialRankTotal(InboundRankDO inboundRankDO) {
return inboundRankMapper.queryMaterialRankTotal(inboundRankDO);
}
}
@@ -0,0 +1,79 @@
package com.mhd.wms.domain.inboundRank.repository.po;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.mhd.common.core.annotation.Excel;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import org.springframework.format.annotation.DateTimeFormat;
import java.io.Serializable;
import java.math.BigDecimal;
import java.util.Date;
/**
* 入库排名统计PO(一行 = 某仓单内某货品的合计,按件数降序排名)
*
* <p>字段口径:入仓日期=入仓单入仓日期(为空兜底建档时间);仓单编号=入库单号;客户编号/存货人=入仓单货主;
* 件数/毛重/体积=仓单内该货品明细合计(件数取实际上架量 SHELVES_QUANTITY);毛重(吨)=明细总毛重KG/1000
* 投保总额=货品档案保额(material_base_info.insure_amount,组内取MAX防多批次明细行重复累加)</p>
*
* @author rcx
* @date 2026-08-31
*/
@Data
@ApiModel(value = "入库排名统计对象", description = "入库排名统计响应对象")
public class InboundMaterialRankPO implements Serializable {
private static final long serialVersionUID = 1L;
@ApiModelProperty("入仓日期")
@JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8")
@DateTimeFormat(pattern = "yyyy-MM-dd")
@Excel(name = "入仓日期", width = 30, dateFormat = "yyyy-MM-dd")
private Date warehouseDate;
@ApiModelProperty("仓单编号(入库单号)")
@Excel(name = "仓单编号")
private String inOrderNumber;
@ApiModelProperty("客户编号")
@Excel(name = "客户编号")
private String shipperCode;
@ApiModelProperty("存货人(客户名称)")
@Excel(name = "存货人")
private String shipperName;
@ApiModelProperty("商品货号")
@Excel(name = "商品货号")
private String materialCode;
@ApiModelProperty("货名/商品名称")
@Excel(name = "货名")
private String materialName;
@ApiModelProperty("规格型号")
@Excel(name = "规格型号")
private String specificationModel;
@ApiModelProperty("单位")
@Excel(name = "单位")
private String unitName;
@ApiModelProperty("件数(仓单内该货品实际上架量合计 SHELVES_QUANTITY,排名依据)")
@Excel(name = "件数")
private BigDecimal pieceCount;
@ApiModelProperty("毛重(吨)(仓单内该货品合计,KG/1000)")
@Excel(name = "毛重(吨)")
private BigDecimal grossWeightTon;
@ApiModelProperty("投保总额(货品档案保额)")
@Excel(name = "投保总额")
private BigDecimal insureAmount;
@ApiModelProperty("体积(CBM)(仓单内该货品合计)")
@Excel(name = "体积(CBM)")
private BigDecimal totalVolume;
}
@@ -0,0 +1,39 @@
package com.mhd.wms.domain.inboundRank.repository.po;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.io.Serializable;
import java.math.BigDecimal;
/**
* 入库排名统计合计PO
*
* <p>当前筛选条件下不分页的全量合计,随分页列表一起返回
* totalPieceCount/totalGrossWeightTon/totalInsureAmount/totalVolume/totalOrderCount</p>
*
* @author rcx
* @date 2026-08-31
*/
@Data
@ApiModel(value = "入库排名统计合计对象", description = "入库排名统计合计响应对象")
public class InboundRankTotalPO implements Serializable {
private static final long serialVersionUID = 1L;
@ApiModelProperty("件数合计(实际上架量)")
private BigDecimal totalPieceCount;
@ApiModelProperty("毛重(吨)合计")
private BigDecimal totalGrossWeightTon;
@ApiModelProperty("投保总额合计(各仓单+货品行保额之和)")
private BigDecimal totalInsureAmount;
@ApiModelProperty("体积(CBM)合计")
private BigDecimal totalVolume;
@ApiModelProperty("仓单数合计")
private Long totalOrderCount;
}
@@ -0,0 +1,50 @@
package com.mhd.wms.domain.inboundRank.repository.todo;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.io.Serializable;
/**
* 入库排名统计查询DO
*
* <p>topOrganizationId / warehouseId 由服务端按登录用户注入,前端不传</p>
*
* @author rcx
* @date 2026-08-31
*/
@Data
public class InboundRankDO implements Serializable {
private static final long serialVersionUID = 1L;
@ApiModelProperty("入仓日期-开始 yyyy-MM-dd(必填)")
private String warehouseDateStart;
@ApiModelProperty("入仓日期-结束 yyyy-MM-dd(必填)")
private String warehouseDateEnd;
@ApiModelProperty("仓单编号/入库单号(模糊)")
private String inOrderNumber;
@ApiModelProperty("客户编号(模糊)")
private String shipperCode;
@ApiModelProperty("存货人/客户名称(模糊)")
private String shipperName;
@ApiModelProperty("商品货号(模糊)")
private String materialCode;
@ApiModelProperty("货名/商品名称(模糊)")
private String materialName;
@ApiModelProperty("仓库名称(模糊)")
private String warehouseName;
@ApiModelProperty("一级组织表ID(登录用户隔离,非1时注入)")
private Long topOrganizationId;
@ApiModelProperty("仓库id(按用户关联仓库注入)")
private Long warehouseId;
}
@@ -0,0 +1,39 @@
package com.mhd.wms.domain.inboundRank.service;
import com.mhd.wms.domain.inboundRank.repository.facade.IInboundRankService;
import com.mhd.wms.domain.inboundRank.repository.po.InboundMaterialRankPO;
import com.mhd.wms.domain.inboundRank.repository.po.InboundRankTotalPO;
import com.mhd.wms.domain.inboundRank.repository.todo.InboundRankDO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
/**
* 入库排名统计领域服务
*
* @author rcx
* @date 2026-08-31
*/
@Service
@Slf4j
public class InboundRankDomainService {
@Autowired
private IInboundRankService inboundRankService;
/**
* 商品入库排名列表(仓单+货品汇总,按件数降序)
*/
public List<InboundMaterialRankPO> queryMaterialRankList(InboundRankDO inboundRankDO) {
return inboundRankService.queryMaterialRankList(inboundRankDO);
}
/**
* 商品入库排名合计(不分页)
*/
public InboundRankTotalPO queryMaterialRankTotal(InboundRankDO inboundRankDO) {
return inboundRankService.queryMaterialRankTotal(inboundRankDO);
}
}
@@ -210,6 +210,12 @@ public class MaterialInventory extends BaseVOEntity {
@Excel(name = "存货日期", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss")
private Date inventoryDate;
@ApiModelProperty("进货日期")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@Excel(name = "进货日期", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss")
private Date purchaseDate;
@ApiModelProperty("ExtAttr3")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@@ -874,6 +874,7 @@ public class MaterialInventoryImpl extends ServiceImpl<MaterialInventoryMapper,
materialInventory.setExtAttr4(materialInventoryParamDO.getExtAttr4());
materialInventory.setExpiryDate(materialInventoryParamDO.getExpiryDate());
materialInventory.setInventoryDate(materialInventoryParamDO.getInventoryDate());
materialInventory.setPurchaseDate(materialInventoryParamDO.getPurchaseDate());
materialInventory.setBatchNumber(materialInventoryParamDO.getBatchNumber());
materialInventory.setUnit(materialBaseInfo.getUnitCode());
materialInventory.setUnitName(materialBaseInfo.getUnitName());
@@ -194,6 +194,12 @@ public class MaterialInventoryPO extends MaterialBasePO {
@Excel(name = "存货日期", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss")
private Date inventoryDate;
@ApiModelProperty("进货日期")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@Excel(name = "进货日期", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss")
private Date purchaseDate;
@ApiModelProperty("ExtAttr3")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@@ -218,6 +218,12 @@ public class MaterialInventoryDO extends MaterialBaseDO {
@Excel(name = "存货日期", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss")
private Date inventoryDate;
@ApiModelProperty("进货日期")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@Excel(name = "进货日期", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss")
private Date purchaseDate;
@ApiModelProperty("ExtAttr3")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@@ -253,6 +259,7 @@ public class MaterialInventoryDO extends MaterialBaseDO {
private String expiryDateStr;
private String productionDateStr;
private String updateTimeStr;
private String purchaseDateStr;
private String expiryDateStart;
private String expiryDateEnd;
@@ -263,6 +270,13 @@ public class MaterialInventoryDO extends MaterialBaseDO {
private String updateTimeStart;
private String updateTimeEnd;
private String purchaseDateStart;
private String purchaseDateEnd;
/** 入库日期(库存行创建时间)区间查询 */
private String createTimeStart;
private String createTimeEnd;
@ApiModelProperty("库存分配匹配:箱号/卡板号 token 列表(明细多值拆分后,OR 匹配;空则不参与匹配)")
private List<String> boxPalletNoList;
@@ -271,4 +285,7 @@ public class MaterialInventoryDO extends MaterialBaseDO {
@ApiModelProperty("库存分配匹配:Batch Ref NO's token 列表(默认不启用,仅显式赋值时参与匹配)")
private List<String> batchRefNoList;
@ApiModelProperty("导出标识:导出与查询共用 /list,true-本次为导出请求,启用导出融合排序(到期日倒序优先→同到期日按物料编码升序→0库存靠后→更新时间倒序);不传-保持原有排序")
private Boolean isExport;
}
@@ -88,6 +88,8 @@ public class MaterialInventoryParamDO extends MaterialBaseDO {
private Date expiryDate;
//库存日期
private Date inventoryDate;
//进货日期
private Date purchaseDate;
//扩展字段3
private Date extAttr3;
//扩展字段4
@@ -0,0 +1,37 @@
package com.mhd.wms.domain.outboundRank.repository.facade;
import com.mhd.wms.domain.outboundRank.repository.po.OutboundLineRankPO;
import com.mhd.wms.domain.outboundRank.repository.po.OutboundMaterialRankPO;
import com.mhd.wms.domain.outboundRank.repository.po.OutboundRankTotalPO;
import com.mhd.wms.domain.outboundRank.repository.todo.OutboundRankDO;
import java.util.List;
/**
* 出库排名统计Service接口
*
* @author rcx
* @date 2026-08-31
*/
public interface IOutboundRankService {
/**
* 商品出库排名列表
*/
List<OutboundMaterialRankPO> queryMaterialRankList(OutboundRankDO outboundRankDO);
/**
* 线路出库排名列表
*/
List<OutboundLineRankPO> queryLineRankList(OutboundRankDO outboundRankDO);
/**
* 商品出库排名合计(不分页)
*/
OutboundRankTotalPO queryMaterialRankTotal(OutboundRankDO outboundRankDO);
/**
* 线路出库排名合计(不分页)
*/
OutboundRankTotalPO queryLineRankTotal(OutboundRankDO outboundRankDO);
}
@@ -0,0 +1,37 @@
package com.mhd.wms.domain.outboundRank.repository.mapper;
import com.mhd.wms.domain.outboundRank.repository.po.OutboundLineRankPO;
import com.mhd.wms.domain.outboundRank.repository.po.OutboundMaterialRankPO;
import com.mhd.wms.domain.outboundRank.repository.po.OutboundRankTotalPO;
import com.mhd.wms.domain.outboundRank.repository.todo.OutboundRankDO;
import java.util.List;
/**
* 出库排名统计Mapper接口
*
* @author rcx
* @date 2026-08-31
*/
public interface OutboundRankMapper {
/**
* 商品出库排名列表(按销售量倒序)
*/
List<OutboundMaterialRankPO> queryMaterialRankList(OutboundRankDO outboundRankDO);
/**
* 线路出库排名列表(按销售量倒序)
*/
List<OutboundLineRankPO> queryLineRankList(OutboundRankDO outboundRankDO);
/**
* 商品出库排名合计(不分页,当前筛选条件全量合计)
*/
OutboundRankTotalPO queryMaterialRankTotal(OutboundRankDO outboundRankDO);
/**
* 线路出库排名合计(不分页,当前筛选条件全量合计)
*/
OutboundRankTotalPO queryLineRankTotal(OutboundRankDO outboundRankDO);
}
@@ -0,0 +1,45 @@
package com.mhd.wms.domain.outboundRank.repository.persistence;
import com.mhd.wms.domain.outboundRank.repository.facade.IOutboundRankService;
import com.mhd.wms.domain.outboundRank.repository.mapper.OutboundRankMapper;
import com.mhd.wms.domain.outboundRank.repository.po.OutboundLineRankPO;
import com.mhd.wms.domain.outboundRank.repository.po.OutboundMaterialRankPO;
import com.mhd.wms.domain.outboundRank.repository.po.OutboundRankTotalPO;
import com.mhd.wms.domain.outboundRank.repository.todo.OutboundRankDO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
/**
* 出库排名统计Service业务层处理
*
* @author rcx
* @date 2026-08-31
*/
@Service
public class OutboundRankImpl implements IOutboundRankService {
@Autowired
private OutboundRankMapper outboundRankMapper;
@Override
public List<OutboundMaterialRankPO> queryMaterialRankList(OutboundRankDO outboundRankDO) {
return outboundRankMapper.queryMaterialRankList(outboundRankDO);
}
@Override
public List<OutboundLineRankPO> queryLineRankList(OutboundRankDO outboundRankDO) {
return outboundRankMapper.queryLineRankList(outboundRankDO);
}
@Override
public OutboundRankTotalPO queryMaterialRankTotal(OutboundRankDO outboundRankDO) {
return outboundRankMapper.queryMaterialRankTotal(outboundRankDO);
}
@Override
public OutboundRankTotalPO queryLineRankTotal(OutboundRankDO outboundRankDO) {
return outboundRankMapper.queryLineRankTotal(outboundRankDO);
}
}
@@ -0,0 +1,45 @@
package com.mhd.wms.domain.outboundRank.repository.po;
import com.mhd.common.core.annotation.Excel;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.io.Serializable;
import java.math.BigDecimal;
/**
* 线路出库排名PO
*
* <p>按日期区间对出库单聚合:销售量=SUM(出库数量),交易数=COUNT(DISTINCT 出库单号),金额=SUM(明细总价);
* 仅统计带线路的出库单(line_code 为 2026-08-20 新增冗余字段,历史单为空)</p>
*
* @author rcx
* @date 2026-08-31
*/
@Data
@ApiModel(value = "线路出库排名对象", description = "线路出库排名响应对象")
public class OutboundLineRankPO implements Serializable {
private static final long serialVersionUID = 1L;
@ApiModelProperty("线路编码")
@Excel(name = "线路编码")
private String lineCode;
@ApiModelProperty("线路名称")
@Excel(name = "线路名称")
private String lineName;
@ApiModelProperty("销售量(出库数量合计)")
@Excel(name = "销售量")
private BigDecimal salesQuantity;
@ApiModelProperty("交易数(出库单据数)")
@Excel(name = "交易数")
private Long tradeCount;
@ApiModelProperty("金额")
@Excel(name = "金额")
private BigDecimal amount;
}
@@ -0,0 +1,52 @@
package com.mhd.wms.domain.outboundRank.repository.po;
import com.mhd.common.core.annotation.Excel;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.io.Serializable;
import java.math.BigDecimal;
/**
* 商品出库排名PO
*
* <p>按日期区间对出库明细聚合:销售量=SUM(出库数量),交易数=COUNT(DISTINCT 出库单号),金额=SUM(明细总价)</p>
*
* @author rcx
* @date 2026-08-31
*/
@Data
@ApiModel(value = "商品出库排名对象", description = "商品出库排名响应对象")
public class OutboundMaterialRankPO implements Serializable {
private static final long serialVersionUID = 1L;
@ApiModelProperty("商品货号")
@Excel(name = "商品货号")
private String materialCode;
@ApiModelProperty("商品名称")
@Excel(name = "商品名称")
private String materialName;
@ApiModelProperty("规格")
@Excel(name = "规格")
private String specificationModel;
@ApiModelProperty("单位")
@Excel(name = "单位")
private String unitName;
@ApiModelProperty("销售量(出库数量合计)")
@Excel(name = "销售量")
private BigDecimal salesQuantity;
@ApiModelProperty("交易数(出库单据数)")
@Excel(name = "交易数")
private Long tradeCount;
@ApiModelProperty("金额")
@Excel(name = "金额")
private BigDecimal amount;
}
@@ -0,0 +1,32 @@
package com.mhd.wms.domain.outboundRank.repository.po;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.io.Serializable;
import java.math.BigDecimal;
/**
* 出库排名合计PO
*
* <p>当前筛选条件下不分页的全量合计,随分页列表一起返回(totalSalesQuantity/totalTradeCount/totalAmount</p>
*
* @author rcx
* @date 2026-08-31
*/
@Data
@ApiModel(value = "出库排名合计对象", description = "出库排名合计响应对象")
public class OutboundRankTotalPO implements Serializable {
private static final long serialVersionUID = 1L;
@ApiModelProperty("销售量合计")
private BigDecimal totalSalesQuantity;
@ApiModelProperty("交易数合计(去重出库单数)")
private Long totalTradeCount;
@ApiModelProperty("金额合计")
private BigDecimal totalAmount;
}
@@ -0,0 +1,53 @@
package com.mhd.wms.domain.outboundRank.repository.todo;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.io.Serializable;
/**
* 出库排名统计查询DO
*
* <p>topOrganizationId / warehouseId 由服务端按登录用户注入,前端不传</p>
*
* @author rcx
* @date 2026-08-31
*/
@Data
public class OutboundRankDO implements Serializable {
private static final long serialVersionUID = 1L;
@ApiModelProperty("出库日期-开始 yyyy-MM-dd(必填)")
private String createTimeStart;
@ApiModelProperty("出库日期-结束 yyyy-MM-dd(必填)")
private String createTimeEnd;
@ApiModelProperty("商品货号(模糊)")
private String materialCode;
@ApiModelProperty("商品名称(模糊)")
private String materialName;
@ApiModelProperty("线路编码(模糊)")
private String lineCode;
@ApiModelProperty("线路名称(模糊)")
private String lineName;
@ApiModelProperty("仓库名称(模糊)")
private String warehouseName;
@ApiModelProperty("客户名称(模糊)")
private String customerName;
@ApiModelProperty("货主名称(模糊)")
private String shipperName;
@ApiModelProperty("一级组织表ID(登录用户隔离,非1时注入)")
private Long topOrganizationId;
@ApiModelProperty("仓库id(按用户关联仓库注入)")
private Long warehouseId;
}
@@ -0,0 +1,54 @@
package com.mhd.wms.domain.outboundRank.service;
import com.mhd.wms.domain.outboundRank.repository.facade.IOutboundRankService;
import com.mhd.wms.domain.outboundRank.repository.po.OutboundLineRankPO;
import com.mhd.wms.domain.outboundRank.repository.po.OutboundMaterialRankPO;
import com.mhd.wms.domain.outboundRank.repository.po.OutboundRankTotalPO;
import com.mhd.wms.domain.outboundRank.repository.todo.OutboundRankDO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
/**
* 出库排名统计领域服务
*
* @author rcx
* @date 2026-08-31
*/
@Service
@Slf4j
public class OutboundRankDomainService {
@Autowired
private IOutboundRankService outboundRankService;
/**
* 商品出库排名列表
*/
public List<OutboundMaterialRankPO> queryMaterialRankList(OutboundRankDO outboundRankDO) {
return outboundRankService.queryMaterialRankList(outboundRankDO);
}
/**
* 线路出库排名列表
*/
public List<OutboundLineRankPO> queryLineRankList(OutboundRankDO outboundRankDO) {
return outboundRankService.queryLineRankList(outboundRankDO);
}
/**
* 商品出库排名合计(不分页)
*/
public OutboundRankTotalPO queryMaterialRankTotal(OutboundRankDO outboundRankDO) {
return outboundRankService.queryMaterialRankTotal(outboundRankDO);
}
/**
* 线路出库排名合计(不分页)
*/
public OutboundRankTotalPO queryLineRankTotal(OutboundRankDO outboundRankDO) {
return outboundRankService.queryLineRankTotal(outboundRankDO);
}
}
@@ -286,6 +286,11 @@ public class ReceiptMaterialDetail extends BaseVOEntity {
@JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8")
private Date inventoryDate;
@ApiModelProperty("进货日期")
@Excel(name = "进货日期", width = 30, dateFormat = "yyyy-MM-dd")
@JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8")
private Date purchaseDate;
@ApiModelProperty("扩展属性1")
@Excel(name = "扩展属性1")
@TableField("ext_attr_1")
@@ -770,6 +770,15 @@ public class ReceiptMaterialDetailImpl extends ServiceImpl<ReceiptMaterialDetail
throw new RuntimeException(e);
}
receiptMaterialDetailDO.setInventoryDate(date);
} else if ("进货日期".equals(batchLabels)) {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
Date date = null;
try {
date = sdf.parse(attributeValue);
} catch (ParseException e) {
throw new RuntimeException(e);
}
receiptMaterialDetailDO.setPurchaseDate(date);
}
}
}
@@ -1274,6 +1283,15 @@ public class ReceiptMaterialDetailImpl extends ServiceImpl<ReceiptMaterialDetail
log.warn("库存日期格式转换失败,物料:{},原始值:{}", receiptMaterialDetailDO.getMaterialName(), attributeValue);
}
break;
case "进货日期":
try {
if (attributeValue.matches("\\d{4}-\\d{2}-\\d{2}.*")) {
receiptMaterialDetailDO.setPurchaseDate(DateUtils.parseDate(attributeValue));
}
} catch (Exception e) {
log.warn("进货日期格式转换失败,物料:{},原始值:{}", receiptMaterialDetailDO.getMaterialName(), attributeValue);
}
break;
case "总净重":
case "净重(KG)":
case "净重":
@@ -316,6 +316,11 @@ public class ReceiptMaterialDetailPO extends BaseVOEntity {
@JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8")
private Date inventoryDate;
@ApiModelProperty("进货日期")
@Excel(name = "进货日期", width = 30, dateFormat = "yyyy-MM-dd")
@JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8")
private Date purchaseDate;
@ApiModelProperty("扩展属性1")
@Excel(name = "扩展属性1")
private String extAttr1;
@@ -300,6 +300,11 @@ public class ReceiptMaterialDetailDO extends BaseVOEntity {
@JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8")
private Date inventoryDate;
@ApiModelProperty("进货日期")
@Excel(name = "进货日期", width = 30, dateFormat = "yyyy-MM-dd")
@JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8")
private Date purchaseDate;
@ApiModelProperty("扩展属性1")
@Excel(name = "扩展属性1")
private String extAttr1;
@@ -301,6 +301,13 @@ public class ShelfMaterialDetail extends BaseVOEntity {
@TableField("inventory_date")
private Date inventoryDate;
@ApiModelProperty("进货日期")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@Excel(name = "进货日期", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss")
@TableField("purchase_date")
private Date purchaseDate;
@ApiModelProperty("ExtAttr3")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@@ -313,6 +313,12 @@ public class ShelfMaterialDetailDO extends BaseVOEntity {
@Excel(name = "存货日期", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss")
private Date inventoryDate;
@ApiModelProperty("进货日期")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@Excel(name = "进货日期", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss")
private Date purchaseDate;
@ApiModelProperty("ExtAttr3")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@@ -1493,6 +1493,7 @@ public class StockReceiptOrderDomainService {
shelfMaterialDetailDO.setTotalGrossWeight(receiptMaterialDetailDO.getTotalGrossWeight());
shelfMaterialDetailDO.setExpiryDate(receiptMaterialDetailDO.getExpiryDate());
shelfMaterialDetailDO.setInventoryDate(receiptMaterialDetailDO.getInventoryDate());
shelfMaterialDetailDO.setPurchaseDate(receiptMaterialDetailDO.getPurchaseDate());
shelfMaterialDetailDO.setBatchRefNo(receiptMaterialDetailDO.getBatchRefNo());
shelfMaterialDetailDO.setSheetRefNo(receiptMaterialDetailDO.getSheetRefNo());
shelfMaterialDetailDO.setBoxPalletNo(receiptMaterialDetailDO.getBoxPalletNo());
@@ -1533,6 +1534,7 @@ public class StockReceiptOrderDomainService {
shelfMaterialDetailDOChildren.setProductionDate(receiptMaterialDetailDOChildren.getProductionDate());
shelfMaterialDetailDOChildren.setExpiryDate(receiptMaterialDetailDOChildren.getExpiryDate());
shelfMaterialDetailDOChildren.setInventoryDate(receiptMaterialDetailDOChildren.getInventoryDate());
shelfMaterialDetailDOChildren.setPurchaseDate(receiptMaterialDetailDOChildren.getPurchaseDate());
shelfMaterialDetailDOChildren.setBatchRefNo(receiptMaterialDetailDOChildren.getBatchRefNo());
shelfMaterialDetailDOChildren.setSheetRefNo(receiptMaterialDetailDOChildren.getSheetRefNo());
shelfMaterialDetailDOChildren.setBoxPalletNo(receiptMaterialDetailDOChildren.getBoxPalletNo());
@@ -1634,10 +1636,11 @@ public class StockReceiptOrderDomainService {
shelfMaterialDetailDO.setTotalVolume(receiptMaterialDetailPO.getTotalVolume());
shelfMaterialDetailDO.setTotalNetWeight(receiptMaterialDetailPO.getTotalNetWeight());
shelfMaterialDetailDO.setTotalGrossWeight(receiptMaterialDetailPO.getTotalGrossWeight());
// 传递生产日期过期日期存货日期Batch Ref NO'sSheet Ref NO's箱号/卡板号扩展属性1-4
// 传递生产日期过期日期存货日期进货日期Batch Ref NO'sSheet Ref NO's箱号/卡板号扩展属性1-4
shelfMaterialDetailDO.setProductionDate(receiptMaterialDetailPO.getProductionDate());
shelfMaterialDetailDO.setExpiryDate(receiptMaterialDetailPO.getExpiryDate());
shelfMaterialDetailDO.setInventoryDate(receiptMaterialDetailPO.getInventoryDate());
shelfMaterialDetailDO.setPurchaseDate(receiptMaterialDetailPO.getPurchaseDate());
shelfMaterialDetailDO.setBatchRefNo(receiptMaterialDetailPO.getBatchRefNo());
shelfMaterialDetailDO.setSheetRefNo(receiptMaterialDetailPO.getSheetRefNo());
shelfMaterialDetailDO.setBoxPalletNo(receiptMaterialDetailPO.getBoxPalletNo());
@@ -1686,6 +1689,7 @@ public class StockReceiptOrderDomainService {
shelfMaterialDetailDOChildren.setProductionDate(receiptMaterialDetailPOChildren.getProductionDate());
shelfMaterialDetailDOChildren.setExpiryDate(receiptMaterialDetailPOChildren.getExpiryDate());
shelfMaterialDetailDOChildren.setInventoryDate(receiptMaterialDetailPOChildren.getInventoryDate());
shelfMaterialDetailDOChildren.setPurchaseDate(receiptMaterialDetailPOChildren.getPurchaseDate());
shelfMaterialDetailDOChildren.setBatchRefNo(receiptMaterialDetailPOChildren.getBatchRefNo());
shelfMaterialDetailDOChildren.setSheetRefNo(receiptMaterialDetailPOChildren.getSheetRefNo());
shelfMaterialDetailDOChildren.setBoxPalletNo(receiptMaterialDetailPOChildren.getBoxPalletNo());
@@ -1767,10 +1771,11 @@ public class StockReceiptOrderDomainService {
shelfMaterialDetailDO.setQuantity(receiptMaterialDetailPO.getReceiptQuantity());
shelfMaterialDetailDO.setInUniqueId(receiptMaterialDetailPO.getInUniqueId());
shelfMaterialDetailDO.setReceiptUniqueId(receiptMaterialDetailPO.getUniqueId());
// 传递生产日期过期日期存货日期Batch Ref NO'sSheet Ref NO's箱号/卡板号扩展属性1-4
// 传递生产日期过期日期存货日期进货日期Batch Ref NO'sSheet Ref NO's箱号/卡板号扩展属性1-4
shelfMaterialDetailDO.setProductionDate(receiptMaterialDetailPO.getProductionDate());
shelfMaterialDetailDO.setExpiryDate(receiptMaterialDetailPO.getExpiryDate());
shelfMaterialDetailDO.setInventoryDate(receiptMaterialDetailPO.getInventoryDate());
shelfMaterialDetailDO.setPurchaseDate(receiptMaterialDetailPO.getPurchaseDate());
shelfMaterialDetailDO.setBatchRefNo(receiptMaterialDetailPO.getBatchRefNo());
shelfMaterialDetailDO.setSheetRefNo(receiptMaterialDetailPO.getSheetRefNo());
shelfMaterialDetailDO.setBoxPalletNo(receiptMaterialDetailPO.getBoxPalletNo());
@@ -1809,10 +1814,11 @@ public class StockReceiptOrderDomainService {
shelfMaterialDetailDOChildren.setInUniqueId(receiptMaterialDetailPO.getInUniqueId());
// 子项使用自身的 uniqueId 作为 receiptUniqueId以便正确关联 material_more_detail 中的扩展属性
shelfMaterialDetailDOChildren.setReceiptUniqueId(receiptMaterialDetailDOChildren.getUniqueId());
// 传递生产日期过期日期存货日期Batch Ref NO'sSheet Ref NO's箱号/卡板号扩展属性1-4
// 传递生产日期过期日期存货日期进货日期Batch Ref NO'sSheet Ref NO's箱号/卡板号扩展属性1-4
shelfMaterialDetailDOChildren.setProductionDate(receiptMaterialDetailDOChildren.getProductionDate());
shelfMaterialDetailDOChildren.setExpiryDate(receiptMaterialDetailDOChildren.getExpiryDate());
shelfMaterialDetailDOChildren.setInventoryDate(receiptMaterialDetailDOChildren.getInventoryDate());
shelfMaterialDetailDOChildren.setPurchaseDate(receiptMaterialDetailDOChildren.getPurchaseDate());
shelfMaterialDetailDOChildren.setBatchRefNo(receiptMaterialDetailDOChildren.getBatchRefNo());
shelfMaterialDetailDOChildren.setSheetRefNo(receiptMaterialDetailDOChildren.getSheetRefNo());
shelfMaterialDetailDOChildren.setBoxPalletNo(receiptMaterialDetailDOChildren.getBoxPalletNo());
@@ -1262,6 +1262,7 @@ public class StockShelfOrderDomainService {
inventoryParamDO.setInventoryDate(shelfMaterialDetail.getInventoryDate());
inventoryParamDO.setExpiryDate(shelfMaterialDetail.getExpiryDate());
inventoryParamDO.setProductionDate(shelfMaterialDetail.getProductionDate());
inventoryParamDO.setPurchaseDate(shelfMaterialDetail.getPurchaseDate());
inventoryParamDO.setBoxPalletNo(shelfMaterialDetail.getBoxPalletNo());
inventoryParamDO.setSheetRefNo(shelfMaterialDetail.getSheetRefNo());
inventoryParamDO.setBatchRefNo(shelfMaterialDetail.getBatchRefNo());
@@ -1348,6 +1349,7 @@ public class StockShelfOrderDomainService {
BeanUtils.copyProperties(inventoryParamDO, materialInventoryOmsParamDO);
materialInventoryOmsParamDO.setProductionDate(materialInventoryPO.getProductionDate());
materialInventoryOmsParamDO.setExpiryDate(materialInventoryPO.getExpiryDate());
materialInventoryOmsParamDO.setPurchaseDate(materialInventoryPO.getPurchaseDate());
materialInventoryOmsParamDO.setMaterialBaseInfoId(materialInventoryPO.getMaterialBaseInfoId());
materialInventoryOmsParamDO.setWarehouseId(materialInventoryPO.getWarehouseId());
materialInventoryOmsParamDO.setLotNumber(materialInventoryPO.getLotNumber());
@@ -1510,6 +1512,9 @@ public class StockShelfOrderDomainService {
case "production_date":
param.setProductionDate(shelfMaterialDetail.getProductionDate());
break;
case "purchase_date":
param.setPurchaseDate(shelfMaterialDetail.getPurchaseDate());
break;
}
}
} else {
@@ -0,0 +1,36 @@
package com.mhd.wms.interfaces.assember.inboundRank;
import cn.hutool.core.util.ObjectUtil;
import com.mhd.common.core.exception.digitalLogisticsException.DigitalLogisticsException;
import com.mhd.common.core.exception.digitalLogisticsException.UserError;
import com.mhd.common.core.utils.IgnoreNullUtil;
import com.mhd.common.core.utils.bean.BeanUtils;
import com.mhd.common.security.utils.SecurityUtils;
import com.mhd.system.api.model.LoginUser;
import com.mhd.wms.domain.inboundRank.repository.todo.InboundRankDO;
import com.mhd.wms.interfaces.dto.inboundRank.InboundRankDTO;
import org.springframework.stereotype.Component;
/**
* 入库排名统计Assembler
*
* @author rcx
* @date 2026-08-31
*/
@Component
public class InboundRankAssembler {
/**
* 转换实体
*/
public InboundRankDO toDO(InboundRankDTO inboundRankDTO) {
InboundRankDO inboundRankDO = new InboundRankDO();
// 拷贝
BeanUtils.copyProperties(inboundRankDTO, inboundRankDO, IgnoreNullUtil.getNullPropertyNames(inboundRankDTO));
LoginUser loginUser = SecurityUtils.getLoginUser();
if (ObjectUtil.isNull(loginUser)) {
throw new DigitalLogisticsException(UserError.TIMEOUT);
}
return inboundRankDO;
}
}
@@ -0,0 +1,36 @@
package com.mhd.wms.interfaces.assember.outboundRank;
import cn.hutool.core.util.ObjectUtil;
import com.mhd.common.core.exception.digitalLogisticsException.DigitalLogisticsException;
import com.mhd.common.core.exception.digitalLogisticsException.UserError;
import com.mhd.common.core.utils.IgnoreNullUtil;
import com.mhd.common.core.utils.bean.BeanUtils;
import com.mhd.common.security.utils.SecurityUtils;
import com.mhd.system.api.model.LoginUser;
import com.mhd.wms.domain.outboundRank.repository.todo.OutboundRankDO;
import com.mhd.wms.interfaces.dto.outboundRank.OutboundRankDTO;
import org.springframework.stereotype.Component;
/**
* 出库排名统计Assembler
*
* @author rcx
* @date 2026-08-31
*/
@Component
public class OutboundRankAssembler {
/**
* 转换实体
*/
public OutboundRankDO toDO(OutboundRankDTO outboundRankDTO) {
OutboundRankDO outboundRankDO = new OutboundRankDO();
// 拷贝
BeanUtils.copyProperties(outboundRankDTO, outboundRankDO, IgnoreNullUtil.getNullPropertyNames(outboundRankDTO));
LoginUser loginUser = SecurityUtils.getLoginUser();
if (ObjectUtil.isNull(loginUser)) {
throw new DigitalLogisticsException(UserError.TIMEOUT);
}
return outboundRankDO;
}
}
@@ -0,0 +1,45 @@
package com.mhd.wms.interfaces.dto.inboundRank;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.io.Serializable;
/**
* 入库排名统计入参DTO
*
* <p>按入仓日期区间筛选商品入库量统计排名统计口径入仓日期 + 仅已入库状态(5) + 明细仅取 level=1 主行
* 一行 = 某仓单内某货品的合计按件数降序排名</p>
*
* @author rcx
* @date 2026-08-31
*/
@Data
public class InboundRankDTO implements Serializable {
private static final long serialVersionUID = 1L;
@ApiModelProperty("入仓日期-开始 yyyy-MM-dd(必填,按入仓单入仓日期筛选)")
private String warehouseDateStart;
@ApiModelProperty("入仓日期-结束 yyyy-MM-dd(必填,按入仓单入仓日期筛选)")
private String warehouseDateEnd;
@ApiModelProperty("仓单编号/入库单号(模糊)")
private String inOrderNumber;
@ApiModelProperty("客户编号(模糊)")
private String shipperCode;
@ApiModelProperty("存货人/客户名称(模糊)")
private String shipperName;
@ApiModelProperty("商品货号(模糊)")
private String materialCode;
@ApiModelProperty("货名/商品名称(模糊)")
private String materialName;
@ApiModelProperty("仓库名称(模糊)")
private String warehouseName;
}
@@ -190,9 +190,12 @@ public class MaterialInventoryDTO extends MaterialBaseDTO {
private Boolean excludeZeroInventoryQuantity;
private String expiryDate;
private String productionDate;
/** 进货日期(yyyy-MM-dd,单日精确查询) */
private String purchaseDate;
private String expiryDateStr;
private String productionDateStr;
private String updateTimeStr;
private String purchaseDateStr;
private String expiryDateStart;
private String expiryDateEnd;
@@ -203,4 +206,11 @@ public class MaterialInventoryDTO extends MaterialBaseDTO {
private String updateTimeStart;
private String updateTimeEnd;
private String purchaseDateStart;
private String purchaseDateEnd;
/** 入库日期(库存行创建时间)区间查询 */
private String createTimeStart;
private String createTimeEnd;
}
@@ -0,0 +1,43 @@
package com.mhd.wms.interfaces.dto.outboundRank;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
/**
* 出库排名统计入参DTO
*
* <p>按日期区间统计商品/线路出库量排名统计口径出库单创建时间 + 已出库及之后状态(9,12,13)</p>
*
* @author rcx
* @date 2026-08-31
*/
@Data
public class OutboundRankDTO {
@ApiModelProperty("出库日期-开始 yyyy-MM-dd(必填,按出库单创建时间统计)")
private String createTimeStart;
@ApiModelProperty("出库日期-结束 yyyy-MM-dd(必填,按出库单创建时间统计)")
private String createTimeEnd;
@ApiModelProperty("商品货号(模糊)")
private String materialCode;
@ApiModelProperty("商品名称(模糊)")
private String materialName;
@ApiModelProperty("线路编码(模糊)")
private String lineCode;
@ApiModelProperty("线路名称(模糊)")
private String lineName;
@ApiModelProperty("仓库名称(模糊)")
private String warehouseName;
@ApiModelProperty("客户名称(模糊)")
private String customerName;
@ApiModelProperty("货主名称(模糊)")
private String shipperName;
}
@@ -311,6 +311,12 @@ public class ShelfMaterialDetailDTO extends BaseVOEntity {
@Excel(name = "存货日期", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss")
private Date inventoryDate;
@ApiModelProperty("进货日期")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@Excel(name = "进货日期", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss")
private Date purchaseDate;
@ApiModelProperty("ExtAttr3")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@@ -0,0 +1,105 @@
package com.mhd.wms.interfaces.facadeApi.inboundRank;
import com.github.pagehelper.PageInfo;
import com.mhd.common.core.constant.HttpStatus;
import com.mhd.common.core.utils.PageUtils;
import com.mhd.common.core.utils.poi.ExcelUtil;
import com.mhd.wms.application.service.inboundRank.InboundRankApplicationService;
import com.mhd.wms.domain.inboundRank.repository.po.InboundMaterialRankPO;
import com.mhd.wms.domain.inboundRank.repository.po.InboundRankTotalPO;
import com.mhd.wms.domain.inboundRank.repository.todo.InboundRankDO;
import com.mhd.wms.interfaces.assember.inboundRank.InboundRankAssembler;
import com.mhd.wms.interfaces.dto.inboundRank.InboundRankDTO;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.net.URLEncoder;
import java.util.HashMap;
import java.util.List;
/**
* 入库排名统计Api
*
* <p>按入仓日期区间筛选商品入库量统计排名统计口径入仓日期(为空的历史单按建档时间兜底) + 仅已入库状态(5)
* 明细仅取 level=1 主行一行 = 某仓单内某货品的合计按件数(实际上架量 SHELVES_QUANTITY)降序排名
* 字段入仓日期/仓单编号/客户编号/存货人/货名/件数/毛重()/投保总额/体积(CBM)
* 与出库排名(/outboundRankApi)配对前端用 tab 页区分</p>
*
* @author rcx
* @date 2026-08-31
*/
@RestController
@RequestMapping("/inboundRankApi")
public class InboundRankApi {
@Resource
private InboundRankAssembler inboundRankAssembler;
@Autowired
private InboundRankApplicationService inboundRankApplicationService;
/**
* 分页查询商品入库排名列表含合计行
*/
@ApiOperation("分页查询商品入库排名列表")
@GetMapping("/queryMaterialRankList")
public HashMap<String, Object> queryMaterialRankList(InboundRankDTO inboundRankDTO) {
//转换实体
InboundRankDO inboundRankDO = inboundRankAssembler.toDO(inboundRankDTO);
startPage();
List<InboundMaterialRankPO> list = inboundRankApplicationService.queryMaterialRankList(inboundRankDO);
InboundRankTotalPO total = inboundRankApplicationService.queryMaterialRankTotal(inboundRankDO);
return getDataTableWithTotal(list, total);
}
/**
* 导出商品入库排名Excel
*/
@ApiOperation("导出商品入库排名Excel")
@GetMapping("/exportMaterialRank")
public void exportMaterialRank(HttpServletResponse response, InboundRankDTO inboundRankDTO) throws Exception {
//转换实体不分页导出全量
InboundRankDO inboundRankDO = inboundRankAssembler.toDO(inboundRankDTO);
List<InboundMaterialRankPO> list = inboundRankApplicationService.exportMaterialRank(inboundRankDO);
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<InboundMaterialRankPO> util = new ExcelUtil<>(InboundMaterialRankPO.class);
util.exportExcel(response, list, "入库排名统计");
}
/**
* 分页结果 + 合计行data/total/code/msg 之外追加
* totalPieceCount/totalGrossWeightTon/totalInsureAmount/totalVolume/totalOrderCount
*/
private HashMap<String, Object> getDataTableWithTotal(List<?> list, InboundRankTotalPO total) {
HashMap<String, Object> result = new HashMap<>();
result.put("data", list);
result.put("total", new PageInfo<>(list).getTotal());
result.put("code", HttpStatus.SUCCESS);
result.put("msg", "查询成功");
if (total != null) {
result.put("totalPieceCount", total.getTotalPieceCount());
result.put("totalGrossWeightTon", total.getTotalGrossWeightTon());
result.put("totalInsureAmount", total.getTotalInsureAmount());
result.put("totalVolume", total.getTotalVolume());
result.put("totalOrderCount", total.getTotalOrderCount());
}
return result;
}
/**
* 设置请求分页数据
*/
protected void startPage() {
PageUtils.startPage();
}
}
@@ -53,14 +53,18 @@ public class MaterialInventoryApi extends BaseController {
/**
* 分页查询物料库存列表
*/
@ApiOperation(value = "查询物料库存列表", notes = "库存查询页不传 excludeZeroInventoryQuantity 可查出数量为0;出库分配页传 excludeZeroInventoryQuantity=true 排除库存数量为0")
@ApiOperation(value = "查询物料库存列表", notes = "库存查询页不传 excludeZeroInventoryQuantity 可查出数量为0;出库分配页传 excludeZeroInventoryQuantity=true 排除库存数量为0;导出复用本接口:传 isExport=true 标识导出请求(导出显示:商品饮用有效期expiryDate/物料分类materialClassifyName/进货日期purchaseDate,所有查询维度均返回)")
@GetMapping("/list")
public TableDataInfo list(MaterialInventoryDTO materialInventoryDTO,
@RequestParam(value = "customerName", required = false) String customerName,
@RequestParam(value = "excludeZeroInventoryQuantity", required = false) Boolean excludeZeroInventoryQuantity,
@RequestParam(value = "expiryDateStart", required = false) String expiryDateStart,
@RequestParam(value = "expiryDateEnd", required = false) String expiryDateEnd,
@RequestParam(value = "orderByExpiryDate", required = false) Boolean orderByExpiryDate)
@RequestParam(value = "purchaseDateStart", required = false) String purchaseDateStart,
@RequestParam(value = "purchaseDateEnd", required = false) String purchaseDateEnd,
@RequestParam(value = "orderByExpiryDate", required = false) Boolean orderByExpiryDate,
// 导出标识导出与查询共用本接口isExport=true 表示本次请求为导出导出专属排序等逻辑以此开关
@RequestParam(value = "isExport", required = false) Boolean isExport)
{
if (Boolean.TRUE.equals(excludeZeroInventoryQuantity)) {
materialInventoryDTO.setExcludeZeroInventoryQuantity(true);
@@ -91,10 +95,15 @@ public class MaterialInventoryApi extends BaseController {
MaterialInventoryDO materialInventoryDO = materialInventoryAssembler.toDO(materialInventoryDTO);
materialInventoryDO.setExpiryDateStr(materialInventoryDTO.getExpiryDate());
materialInventoryDO.setProductionDateStr(materialInventoryDTO.getProductionDate());
materialInventoryDO.setPurchaseDateStr(materialInventoryDTO.getPurchaseDate());
materialInventoryDO.setExpiryDateStart(expiryDateStart);
materialInventoryDO.setExpiryDateEnd(expiryDateEnd);
materialInventoryDO.setPurchaseDateStart(purchaseDateStart);
materialInventoryDO.setPurchaseDateEnd(purchaseDateEnd);
// 导出场景queryRule=wlExpiry + orderByExpiryDate=true SQL 按到期日倒序分组 OMS 库存查询导出一致
materialInventoryDO.setOrderByExpiryDate(orderByExpiryDate);
// 导出标识isExport=true 启用导出融合排序到期日倒序优先 同到期日按物料编码升序所有维度生效
materialInventoryDO.setIsExport(isExport);
Date updateTime = materialInventoryDTO.getUpdateTime();
if (updateTime != null) {
LocalDateTime localDateTime = updateTime.toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime();
@@ -167,7 +176,8 @@ public class MaterialInventoryApi extends BaseController {
// materialDetailId 是新接口专用参数出库单明细ID库存 DTO 的同名字段语义是上架单明细ID
// 泄入原查询会生成错误的 a.material_detail_id 条件导致查空进原查询前显式清除
materialInventoryDTO.setMaterialDetailId(null);
return list(materialInventoryDTO, customerName, excludeZeroInventoryQuantity, expiryDateStart, expiryDateEnd, orderByExpiryDate);
// assignableList 非导出场景isExport null
return list(materialInventoryDTO, customerName, excludeZeroInventoryQuantity, expiryDateStart, expiryDateEnd, null, null, orderByExpiryDate, null);
}
@ApiOperation("查询物料库存列表不分页;queryRule=hz 时按货主+物料分组(同一物料在不同货主各占一行)")
@@ -0,0 +1,134 @@
package com.mhd.wms.interfaces.facadeApi.outboundRank;
import com.github.pagehelper.PageInfo;
import com.mhd.common.core.constant.HttpStatus;
import com.mhd.common.core.utils.PageUtils;
import com.mhd.common.core.utils.poi.ExcelUtil;
import com.mhd.wms.application.service.outboundRank.OutboundRankApplicationService;
import com.mhd.wms.domain.outboundRank.repository.po.OutboundLineRankPO;
import com.mhd.wms.domain.outboundRank.repository.po.OutboundMaterialRankPO;
import com.mhd.wms.domain.outboundRank.repository.po.OutboundRankTotalPO;
import com.mhd.wms.domain.outboundRank.repository.todo.OutboundRankDO;
import com.mhd.wms.interfaces.assember.outboundRank.OutboundRankAssembler;
import com.mhd.wms.interfaces.dto.outboundRank.OutboundRankDTO;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.net.URLEncoder;
import java.util.HashMap;
import java.util.List;
/**
* 出库排名统计Api
*
* <p>按日期区间筛选统计商品/线路出库量排名统计口径出库单创建时间 + 已出库及之后状态(9,12,13)
* 明细仅取 level=1 主行销售量=SUM(出库数量)交易数=COUNT(DISTINCT 出库单号)金额=SUM(明细总价)</p>
*
* @author rcx
* @date 2026-08-31
*/
@RestController
@RequestMapping("/outboundRankApi")
public class OutboundRankApi {
@Resource
private OutboundRankAssembler outboundRankAssembler;
@Autowired
private OutboundRankApplicationService outboundRankApplicationService;
/**
* 分页查询商品出库排名列表含合计行
*/
@ApiOperation("分页查询商品出库排名列表")
@GetMapping("/queryMaterialRankList")
public HashMap<String, Object> queryMaterialRankList(OutboundRankDTO outboundRankDTO) {
//转换实体
OutboundRankDO outboundRankDO = outboundRankAssembler.toDO(outboundRankDTO);
startPage();
List<OutboundMaterialRankPO> list = outboundRankApplicationService.queryMaterialRankList(outboundRankDO);
OutboundRankTotalPO total = outboundRankApplicationService.queryMaterialRankTotal(outboundRankDO);
return getDataTableWithTotal(list, total);
}
/**
* 分页查询线路出库排名列表含合计行
*/
@ApiOperation("分页查询线路出库排名列表")
@GetMapping("/queryLineRankList")
public HashMap<String, Object> queryLineRankList(OutboundRankDTO outboundRankDTO) {
//转换实体
OutboundRankDO outboundRankDO = outboundRankAssembler.toDO(outboundRankDTO);
startPage();
List<OutboundLineRankPO> list = outboundRankApplicationService.queryLineRankList(outboundRankDO);
OutboundRankTotalPO total = outboundRankApplicationService.queryLineRankTotal(outboundRankDO);
return getDataTableWithTotal(list, total);
}
/**
* 导出商品出库排名Excel
*/
@ApiOperation("导出商品出库排名Excel")
@GetMapping("/exportMaterialRank")
public void exportMaterialRank(HttpServletResponse response, OutboundRankDTO outboundRankDTO) throws Exception {
//转换实体不分页导出全量
OutboundRankDO outboundRankDO = outboundRankAssembler.toDO(outboundRankDTO);
List<OutboundMaterialRankPO> list = outboundRankApplicationService.exportMaterialRankList(outboundRankDO);
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<OutboundMaterialRankPO> util = new ExcelUtil<>(OutboundMaterialRankPO.class);
util.exportExcel(response, list, "商品出库排名");
}
/**
* 导出线路出库排名Excel
*/
@ApiOperation("导出线路出库排名Excel")
@GetMapping("/exportLineRank")
public void exportLineRank(HttpServletResponse response, OutboundRankDTO outboundRankDTO) throws Exception {
//转换实体不分页导出全量
OutboundRankDO outboundRankDO = outboundRankAssembler.toDO(outboundRankDTO);
List<OutboundLineRankPO> list = outboundRankApplicationService.exportLineRankList(outboundRankDO);
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<OutboundLineRankPO> util = new ExcelUtil<>(OutboundLineRankPO.class);
util.exportExcel(response, list, "线路出库排名");
}
/**
* 分页结果 + 合计行data/total/code/msg 之外追加 totalSalesQuantity/totalTradeCount/totalAmount
*/
private HashMap<String, Object> getDataTableWithTotal(List<?> list, OutboundRankTotalPO total) {
HashMap<String, Object> result = new HashMap<>();
result.put("data", list);
result.put("total", new PageInfo<>(list).getTotal());
result.put("code", HttpStatus.SUCCESS);
result.put("msg", "查询成功");
if (total != null) {
result.put("totalSalesQuantity", total.getTotalSalesQuantity());
result.put("totalTradeCount", total.getTotalTradeCount());
result.put("totalAmount", total.getTotalAmount());
}
return result;
}
/**
* 设置请求分页数据
*/
protected void startPage() {
PageUtils.startPage();
}
}
+1 -23
View File
@@ -34,26 +34,4 @@ spring:
file-extension: yml
# 共享配置
shared-configs:
- application-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension}
# XXL-JOB 配置
#xxl:
# job:
# # 调度中心地址(填你部署的地址)
# admin:
# addresses: http://192.168.1.6:8020/xxl-job-admin
# # 执行器配置
# executor:
# # 执行器名称(自定义,后面调度中心要用到)
# appname: wms-service-executor
# # 执行器注册地址,默认0表示自动获取
# address:
# # 执行器IP,默认空自动获取
# ip:
# # 执行器端口号(每个微服务不能重复,建议9997/9998/9999
# port: 9997
# # 执行器日志存放路径
# logpath: /data/applogs/xxl-job/jobhandler
# # 日志保留天数
# logretentiondays: 30
# # 调度中心通讯令牌(默认空,安全可设置)
# accessToken: default_token
- application-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension}
@@ -0,0 +1,104 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.mhd.wms.domain.inboundRank.repository.mapper.InboundRankMapper">
<!--
入库排名统计公共查询条件
数据源:入库明细 in_material_detail(a,仅 level=1 主行防重复) join 入仓单 stock_in_order(b)
left join 货品档案 material_base_info(c,取保额作投保总额)
口径:b.status = 5已入库(排除已取消(6)/已关闭(7)及未完成单据);
日期筛选按入仓单入仓日期 b.warehouse_date(与列表"入仓日期"列同源,为空的历史单按建档时间兜底);
一行 = 某仓单(b.in_order_number)内某货品(a.material_code)的合计,按件数(实际上架量 SUM(a.SHELVES_QUANTITY))降序排名
-->
<sql id="inboundRankConditions">
a.del_flag = 1
and a.level = 1
and b.status = 5
<if test="topOrganizationId != null">
and b.top_organization_id = #{topOrganizationId}
</if>
<if test="warehouseId != null">
and b.warehouse_id = #{warehouseId}
</if>
<if test="warehouseName != null and warehouseName != ''">
and b.warehouse_name like concat('%', #{warehouseName}, '%')
</if>
<if test="inOrderNumber != null and inOrderNumber != ''">
and b.in_order_number like concat('%', #{inOrderNumber}, '%')
</if>
<if test="shipperCode != null and shipperCode != ''">
and b.shipper_code like concat('%', #{shipperCode}, '%')
</if>
<if test="shipperName != null and shipperName != ''">
and b.shipper_name like concat('%', #{shipperName}, '%')
</if>
<if test="materialCode != null and materialCode != ''">
and a.material_code like concat('%', #{materialCode}, '%')
</if>
<if test="materialName != null and materialName != ''">
and a.material_name like concat('%', #{materialName}, '%')
</if>
<if test="warehouseDateStart != null and warehouseDateStart != ''">
and date_format(IFNULL(b.warehouse_date, b.create_time),'%Y-%m-%d') &gt;= #{warehouseDateStart}
</if>
<if test="warehouseDateEnd != null and warehouseDateEnd != ''">
and date_format(IFNULL(b.warehouse_date, b.create_time),'%Y-%m-%d') &lt;= #{warehouseDateEnd}
</if>
</sql>
<sql id="inboundRankFrom">
from in_material_detail a
join stock_in_order b on a.in_order_number = b.in_order_number and b.del_flag = 1
left join material_base_info c on a.material_base_info_id = c.material_base_info_id
</sql>
<!-- 商品入库排名列表(仓单+货品汇总,按件数=实际上架量降序) -->
<select id="queryMaterialRankList" parameterType="com.mhd.wms.domain.inboundRank.repository.todo.InboundRankDO"
resultType="com.mhd.wms.domain.inboundRank.repository.po.InboundMaterialRankPO">
select
IFNULL(MAX(b.warehouse_date), MAX(b.create_time)) AS warehouseDate,
b.in_order_number AS inOrderNumber,
MAX(b.shipper_code) AS shipperCode,
MAX(b.shipper_name) AS shipperName,
a.material_code AS materialCode,
MAX(a.material_name) AS materialName,
MAX(a.SPECIFICATION_MODEL) AS specificationModel,
MAX(a.unit_name) AS unitName,
IFNULL(SUM(a.SHELVES_QUANTITY), 0) AS pieceCount,
ROUND(IFNULL(SUM(a.TOTAL_GROSS_WEIGHT), 0) / 1000, 3) AS grossWeightTon,
MAX(IFNULL(c.insure_amount, 0)) AS insureAmount,
IFNULL(SUM(a.TOTAL_VOLUME), 0) AS totalVolume
<include refid="inboundRankFrom"/>
<where>
<include refid="inboundRankConditions"/>
</where>
GROUP BY b.in_order_number, a.material_code
order by pieceCount desc, warehouseDate desc, inOrderNumber desc
</select>
<!-- 商品入库排名合计(当前筛选条件全量;外层对分组结果再汇总,保证投保总额合计=各行列值之和) -->
<select id="queryMaterialRankTotal" parameterType="com.mhd.wms.domain.inboundRank.repository.todo.InboundRankDO"
resultType="com.mhd.wms.domain.inboundRank.repository.po.InboundRankTotalPO">
select
IFNULL(SUM(t.pieceCount), 0) AS totalPieceCount,
ROUND(IFNULL(SUM(t.grossWeightKG), 0) / 1000, 3) AS totalGrossWeightTon,
IFNULL(SUM(t.insureAmount), 0) AS totalInsureAmount,
IFNULL(SUM(t.totalVolume), 0) AS totalVolume,
COUNT(DISTINCT t.inOrderNumber) AS totalOrderCount
from (
select
b.in_order_number AS inOrderNumber,
IFNULL(SUM(a.SHELVES_QUANTITY), 0) AS pieceCount,
IFNULL(SUM(a.TOTAL_GROSS_WEIGHT), 0) AS grossWeightKG,
MAX(IFNULL(c.insure_amount, 0)) AS insureAmount,
IFNULL(SUM(a.TOTAL_VOLUME), 0) AS totalVolume
<include refid="inboundRankFrom"/>
<where>
<include refid="inboundRankConditions"/>
</where>
GROUP BY b.in_order_number, a.material_code
) t
</select>
</mapper>
@@ -56,6 +56,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<result property="productionDate" column="production_date" />
<result property="expiryDate" column="expiry_date" />
<result property="inventoryDate" column="inventory_date" />
<result property="purchaseDate" column="purchase_date" />
<result property="batchRefNo" column="batch_ref_no" />
<result property="sheetRefNo" column="sheet_ref_no" />
<result property="boxPalletNo" column="box_pallet_no" />
@@ -65,6 +66,10 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<result property="inOrderNumber" column="in_order_number" />
<result property="lotNumber" column="lot_number" />
<result property="specificationModel" column="specification_model" />
<result property="materialClassifyCode" column="material_classify_code"
typeHandler="com.mhd.common.core.handler.ListTypeHandler" />
<result property="materialClassifyName" column="material_classify_name"
typeHandler="com.mhd.common.core.handler.ListTypeHandler" />
</resultMap>
@@ -84,7 +89,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
IFNULL (sum(a.GROSS_WEIGHT), 0) GROSS_WEIGHT,
IFNULL (sum(a.VOLUME), 0) VOLUME,
a.ext_attr_1, a.ext_attr_2, a.ext_attr_3, a.ext_attr_4,
a.production_date, a.expiry_date, a.inventory_date,
a.production_date, a.expiry_date, a.inventory_date, a.purchase_date,
a.BATCH_REF_NO, a.SHEET_REF_NO, a.BOX_PALLET_NO,nvl(a.unit_name,b.unit_name) as unit_name,
a.bar_code as inv_bar_code,
a.in_order_number,a.lot_number,
@@ -108,7 +113,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
IFNULL (sum(a.GROSS_WEIGHT), 0) GROSS_WEIGHT,
IFNULL (sum(a.VOLUME), 0) VOLUME,
a.ext_attr_1, a.ext_attr_2, a.ext_attr_3, a.ext_attr_4,
a.production_date, a.expiry_date, a.inventory_date,
a.production_date, a.expiry_date, a.inventory_date, a.purchase_date,
a.BATCH_REF_NO, a.SHEET_REF_NO, a.BOX_PALLET_NO,nvl(a.unit_name,b.unit_name) as unit_name,
a.bar_code as inv_bar_code,
a.in_order_number,a.lot_number,
@@ -263,6 +268,21 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<if test="expiryDateEnd != null and expiryDateEnd != ''">
and a.expiry_date <![CDATA[ < ]]> DATEADD(DAY, 1, #{expiryDateEnd})
</if>
<if test="purchaseDateStr != null and purchaseDateStr != ''">
AND TO_CHAR(a.purchase_date, 'yyyy-MM-dd') = #{purchaseDateStr}
</if>
<if test="purchaseDateStart != null and purchaseDateStart != ''">
and a.purchase_date >= #{purchaseDateStart}
</if>
<if test="purchaseDateEnd != null and purchaseDateEnd != ''">
and a.purchase_date <![CDATA[ < ]]> DATEADD(DAY, 1, #{purchaseDateEnd})
</if>
<if test="createTimeStart != null and createTimeStart != ''">
and date_format(a.create_time,'%Y-%m-%d') &gt;= #{createTimeStart}
</if>
<if test="createTimeEnd != null and createTimeEnd != ''">
and date_format(a.create_time,'%Y-%m-%d') &lt;= #{createTimeEnd}
</if>
</sql>
<!-- 与 selectMaterialInventoryPo1 相同条件,表别名为 mi(用于 queryListByWl 最新明细子查询) -->
@@ -383,6 +403,17 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
</if>
</sql>
<!-- 导出融合排序(isExport=true):保留"到期日优先"第一优先级(到期日倒序、空值最后),
融合新增"同到期日内按物料编码升序",再保留 0库存靠后、更新时间倒序 兜底,
末位以 MAX(物料库存ID) 保证分页序稳定;不传 isExport 各语句保持原有排序 -->
<sql id="exportOrderByMaterialCode">
order by CASE WHEN MAX(a.expiry_date) IS NULL THEN 1 ELSE 0 END ASC, MAX(a.expiry_date) DESC,
MAX(b.material_code) ASC,
CASE WHEN IFNULL(SUM(a.inventory_quantity), 0) = 0 THEN 1 ELSE 0 END ASC,
MAX(a.update_time) DESC,
MAX(a.material_inventory_id) DESC
</sql>
<select id="queryList" parameterType="com.mhd.wms.domain.materialInventory.repository.todo.MaterialInventoryDO" resultMap="MaterialInventoryResult">
select
<include refid="selectMaterialInventoryPo"/>
@@ -393,7 +424,26 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<include refid="selectMaterialInventoryPo1"/>
<include refid="com.mhd.wms.domain.materialBaseInfo.repository.mapper.MaterialBaseInfoMapper.JoinMaterialBaseInfoPoWhere"/>
</where>
group by a.MATERIAL_INVENTORY_ID order by sort_order, a.update_time desc
group by a.MATERIAL_INVENTORY_ID
<choose>
<when test="isExport != null and isExport == true">
<include refid="exportOrderByMaterialCode"/>
</when>
<otherwise> order by sort_order, a.update_time desc </otherwise>
</choose>
</select>
<!-- 库存数量合计:与 queryList 相同筛选条件,对全部命中明细行 SUM(库存数量);
不受 queryRule 分组展示影响(各分组行之和即全部明细之和) -->
<select id="sumInventoryQuantity" parameterType="com.mhd.wms.domain.materialInventory.repository.todo.MaterialInventoryDO"
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>
<include refid="selectMaterialInventoryPo1"/>
<include refid="com.mhd.wms.domain.materialBaseInfo.repository.mapper.MaterialBaseInfoMapper.JoinMaterialBaseInfoPoWhere"/>
</where>
</select>
<!-- ============ 出库单明细可分配库存(库存分配弹窗专用) ============
@@ -463,7 +513,13 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<include refid="selectMaterialInventoryPo1"/>
<include refid="com.mhd.wms.domain.materialBaseInfo.repository.mapper.MaterialBaseInfoMapper.JoinMaterialBaseInfoPoWhere"/>
</where>
GROUP BY a.SHIPPER_ID,a.MATERIAL_BASE_INFO_ID,a.WAREHOUSE_ID,a.STORAGE_SECTION_ID,a.STORAGE_LOCATION_ID order by sort_order, a.update_time desc
GROUP BY a.SHIPPER_ID,a.MATERIAL_BASE_INFO_ID,a.WAREHOUSE_ID,a.STORAGE_SECTION_ID,a.STORAGE_LOCATION_ID
<choose>
<when test="isExport != null and isExport == true">
<include refid="exportOrderByMaterialCode"/>
</when>
<otherwise> order by sort_order, a.update_time desc </otherwise>
</choose>
</select>
<select id="queryListByKw" parameterType="com.mhd.wms.domain.materialInventory.repository.todo.MaterialInventoryDO" resultMap="MaterialInventoryResult">
@@ -476,7 +532,13 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<include refid="selectMaterialInventoryPo1"/>
<include refid="com.mhd.wms.domain.materialBaseInfo.repository.mapper.MaterialBaseInfoMapper.JoinMaterialBaseInfoPoWhere"/>
</where>
GROUP BY a.WAREHOUSE_ID,a.STORAGE_SECTION_ID,a.STORAGE_LOCATION_ID order by sort_order, a.update_time desc
GROUP BY a.WAREHOUSE_ID,a.STORAGE_SECTION_ID,a.STORAGE_LOCATION_ID
<choose>
<when test="isExport != null and isExport == true">
<include refid="exportOrderByMaterialCode"/>
</when>
<otherwise> order by sort_order, a.update_time desc </otherwise>
</choose>
</select>
<select id="queryListByWl" parameterType="com.mhd.wms.domain.materialInventory.repository.todo.MaterialInventoryDO" resultMap="MaterialInventoryResult">
@@ -509,7 +571,13 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
GROUP BY a.MATERIAL_BASE_INFO_ID, a.WAREHOUSE_ID,
loc.warehouse_id, loc.warehouse_code, loc.warehouse_name,
loc.storage_section_id, loc.storage_code, loc.storage_name,
loc.storage_location_id, loc.storage_location_code, loc.storage_location_name order by sort_order, a.update_time desc
loc.storage_location_id, loc.storage_location_code, loc.storage_location_name
<choose>
<when test="isExport != null and isExport == true">
<include refid="exportOrderByMaterialCode"/>
</when>
<otherwise> order by sort_order, a.update_time desc </otherwise>
</choose>
</select>
<!-- 按物料+过期日期汇总:相同物料+相同过期日期合并,不同过期日期分开 -->
@@ -532,13 +600,18 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
IFNULL(SUM(a.VOLUME), 0) AS VOLUME,
MAX(a.unit) AS unit,
MAX(a.unit_name) AS unit_name,
MAX(a.create_time) AS create_time,
MAX(a.update_time) AS update_time,
MAX(a.production_date) AS production_date,
MAX(a.inventory_date) AS inventory_date,
MAX(a.purchase_date) AS purchase_date,
MAX(a.batch_ref_no) AS batch_ref_no, MAX(a.sheet_ref_no) AS sheet_ref_no, MAX(a.box_pallet_no) AS box_pallet_no,
MAX(a.bar_code) AS inv_bar_code,
MAX(a.in_order_number) AS in_order_number, MAX(a.lot_number) AS lot_number,
MAX(b.specification_model) AS specification_model,
MAX(b.material_code) AS material_code, MAX(b.material_name) AS material_name,
MAX(b.material_classify_code) AS material_classify_code,
MAX(b.material_classify_name) AS material_classify_name,
CASE WHEN IFNULL(SUM(a.inventory_quantity), 0) = 0 THEN 1 ELSE 0 END AS sort_order
from material_inventory a
left join material_base_info b on a.material_base_info_id = b.material_base_info_id
@@ -548,16 +621,25 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
</where>
GROUP BY a.MATERIAL_BASE_INFO_ID, a.EXPIRY_DATE, a.shipper_id,
a.organization_id, a.top_organization_id
<!-- 导出(queryRule=wlExpiry + orderByExpiryDate=true)按到期日分组归类:到期日倒序(日期近的在前)、
空值放最后、0库存靠后、同到期日按更新时间倒序;相同物料+相同到期日合并为一行,数量类字段SUM汇总。
不传 orderByExpiryDate 保持原有排序 -->
<!-- 导出排序两级开关:isExport=true 用融合排序(到期日优先→同到期日按物料编码升序,与 orderByExpiryDate 融合不取代)
否则保持原有 orderByExpiryDate 分支排序 -->
<choose>
<when test="orderByExpiryDate != null and orderByExpiryDate == true">
order by CASE WHEN a.expiry_date IS NULL THEN 1 ELSE 0 END ASC, a.expiry_date DESC,
sort_order, MAX(a.update_time) DESC
<when test="isExport != null and isExport == true">
<include refid="exportOrderByMaterialCode"/>
</when>
<otherwise>
order by sort_order, MAX(a.update_time) desc
<!-- 导出(queryRule=wlExpiry + orderByExpiryDate=true)按到期日分组归类:到期日倒序(日期近的在前)、
空值放最后、0库存靠后、同到期日按更新时间倒序;相同物料+相同到期日合并为一行,数量类字段SUM汇总。
不传 orderByExpiryDate 保持原有排序 -->
<choose>
<when test="orderByExpiryDate != null and orderByExpiryDate == true">
order by CASE WHEN a.expiry_date IS NULL THEN 1 ELSE 0 END ASC, a.expiry_date DESC,
sort_order, MAX(a.update_time) DESC
</when>
<otherwise>
order by sort_order, MAX(a.update_time) desc
</otherwise>
</choose>
</otherwise>
</choose>
</select>
@@ -593,7 +675,13 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
GROUP BY a.SHIPPER_ID, a.MATERIAL_BASE_INFO_ID,
loc.warehouse_id, loc.warehouse_code, loc.warehouse_name,
loc.storage_section_id, loc.storage_code, loc.storage_name,
loc.storage_location_id, loc.storage_location_code, loc.storage_location_name order by sort_order, a.update_time desc
loc.storage_location_id, loc.storage_location_code, loc.storage_location_name
<choose>
<when test="isExport != null and isExport == true">
<include refid="exportOrderByMaterialCode"/>
</when>
<otherwise> order by sort_order, a.update_time desc </otherwise>
</choose>
</select>
<!-- ============ 按货主+物料+仓库+单位 汇总(库存查询第三个页签) ============ -->
@@ -614,6 +702,8 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
a.top_organization_id,
MAX(b.material_type) AS material_type,
MAX(b.material_type_name) AS material_type_name,
MAX(b.material_classify_code) AS material_classify_code,
MAX(b.material_classify_name) AS material_classify_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,
@@ -651,7 +741,12 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
b.material_code,
a.warehouse_id,
a.organization_id, a.top_organization_id
ORDER BY sort_order, MAX(a.update_time) DESC
<choose>
<when test="isExport != null and isExport == true">
<include refid="exportOrderByMaterialCode"/>
</when>
<otherwise> ORDER BY sort_order, MAX(a.update_time) DESC </otherwise>
</choose>
</select>
<select id="queryListByHz" parameterType="com.mhd.wms.domain.materialInventory.repository.todo.MaterialInventoryDO" resultMap="MaterialInventoryResult">
@@ -664,7 +759,13 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<include refid="selectMaterialInventoryPo1"/>
<include refid="com.mhd.wms.domain.materialBaseInfo.repository.mapper.MaterialBaseInfoMapper.JoinMaterialBaseInfoPoWhere"/>
</where>
GROUP BY a.SHIPPER_ID, a.WAREHOUSE_ID order by sort_order, a.update_time desc
GROUP BY a.SHIPPER_ID, a.WAREHOUSE_ID
<choose>
<when test="isExport != null and isExport == true">
<include refid="exportOrderByMaterialCode"/>
</when>
<otherwise> order by sort_order, a.update_time desc </otherwise>
</choose>
</select>
<resultMap type="com.mhd.wms.domain.materialInventory.repository.po.MaterialInventoryQueryListPO" id="MaterialQueryListResult">
@@ -728,6 +829,10 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<result property="updateBy" column="update_by" />
<result property="updateByName" column="update_by_name" />
<result property="delFlag" column="del_flag" />
<result property="materialClassifyCode" column="material_classify_code"
typeHandler="com.mhd.common.core.handler.ListTypeHandler" />
<result property="materialClassifyName" column="material_classify_name"
typeHandler="com.mhd.common.core.handler.ListTypeHandler" />
</resultMap>
<!-- 1-按货主 2-按物料 3-按批次 4-按库位 5-按物料/库位 6-按容器 0-全部 -->
@@ -1195,6 +1300,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<result property="productionDate" column="production_date" />
<result property="expiryDate" column="expiry_date" />
<result property="inventoryDate" column="inventory_date" />
<result property="purchaseDate" column="purchase_date" />
<result property="batchRefNo" column="batch_ref_no" />
<result property="sheetRefNo" column="sheet_ref_no" />
<result property="boxPalletNo" column="box_pallet_no" />
@@ -1513,6 +1619,9 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<if test="productionDate != null">
AND TRUNC(a.PRODUCTION_DATE) = TRUNC(#{productionDate})
</if>
<if test="purchaseDate != null">
AND TRUNC(a.purchase_date) = TRUNC(#{purchaseDate})
</if>
<if test="extAttr2 != null and extAttr2 != ''">
AND a.EXT_ATTR_2 = #{extAttr2}
</if>
@@ -1544,6 +1653,9 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<if test="productionDate == null">
AND a.PRODUCTION_DATE is null
</if>
<if test="purchaseDate == null">
AND a.purchase_date is null
</if>
<if test="extAttr2 == ''">
AND a.EXT_ATTR_2 = #{extAttr2}
</if>
@@ -0,0 +1,126 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.mhd.wms.domain.outboundRank.repository.mapper.OutboundRankMapper">
<!--
出库排名统计公共查询条件
数据源:出库明细 out_material_detail(a,仅 level=1 主行防重复) join 出库单 stock_out_order(b)
口径:b.status in (9已出库,12已复核,13已交接),排除已取消(10)/已关闭(11);
日期按出库单创建时间 b.create_time(与出库单列表日期筛选一致)
-->
<sql id="outboundRankConditions">
a.del_flag = 1
and a.level = 1
and b.status in (9, 12, 13)
<if test="topOrganizationId != null">
and b.top_organization_id = #{topOrganizationId}
</if>
<if test="warehouseId != null">
and b.warehouse_id = #{warehouseId}
</if>
<if test="warehouseName != null and warehouseName != ''">
and b.warehouse_name like concat('%', #{warehouseName}, '%')
</if>
<if test="customerName != null and customerName != ''">
and b.customer_name like concat('%', #{customerName}, '%')
</if>
<if test="shipperName != null and shipperName != ''">
and b.shipper_name like concat('%', #{shipperName}, '%')
</if>
<if test="lineCode != null and lineCode != ''">
and b.line_code like concat('%', #{lineCode}, '%')
</if>
<if test="lineName != null and lineName != ''">
and b.line_name like concat('%', #{lineName}, '%')
</if>
<if test="createTimeStart != null and createTimeStart != ''">
and date_format(b.create_time,'%Y-%m-%d') &gt;= #{createTimeStart}
</if>
<if test="createTimeEnd != null and createTimeEnd != ''">
and date_format(b.create_time,'%Y-%m-%d') &lt;= #{createTimeEnd}
</if>
</sql>
<sql id="outboundRankFrom">
from out_material_detail a
join stock_out_order b on a.out_order_number = b.out_order_number and b.del_flag = 1
</sql>
<!-- 商品出库排名列表 -->
<select id="queryMaterialRankList" parameterType="com.mhd.wms.domain.outboundRank.repository.todo.OutboundRankDO"
resultType="com.mhd.wms.domain.outboundRank.repository.po.OutboundMaterialRankPO">
select
a.material_code AS materialCode,
MAX(a.material_name) AS materialName,
MAX(a.SPECIFICATION_MODEL) AS specificationModel,
MAX(a.unit_name) AS unitName,
IFNULL(SUM(a.outbound_quantity), 0) AS salesQuantity,
COUNT(DISTINCT a.out_order_number) AS tradeCount,
IFNULL(SUM(IFNULL(a.TOTAL_AMOUNT, 0)), 0) AS amount
<include refid="outboundRankFrom"/>
<where>
<include refid="outboundRankConditions"/>
<if test="materialCode != null and materialCode != ''">
and a.material_code like concat('%', #{materialCode}, '%')
</if>
<if test="materialName != null and materialName != ''">
and a.material_name like concat('%', #{materialName}, '%')
</if>
</where>
GROUP BY a.material_code
order by salesQuantity desc
</select>
<!-- 线路出库排名列表(线路为空的历史单不参与线路排名) -->
<select id="queryLineRankList" parameterType="com.mhd.wms.domain.outboundRank.repository.todo.OutboundRankDO"
resultType="com.mhd.wms.domain.outboundRank.repository.po.OutboundLineRankPO">
select
b.line_code AS lineCode,
MAX(b.line_name) AS lineName,
IFNULL(SUM(a.outbound_quantity), 0) AS salesQuantity,
COUNT(DISTINCT b.out_order_number) AS tradeCount,
IFNULL(SUM(IFNULL(a.TOTAL_AMOUNT, 0)), 0) AS amount
<include refid="outboundRankFrom"/>
<where>
<include refid="outboundRankConditions"/>
and b.line_code is not null and b.line_code != ''
</where>
GROUP BY b.line_code
order by salesQuantity desc
</select>
<!-- 商品出库排名合计(当前筛选条件全量) -->
<select id="queryMaterialRankTotal" parameterType="com.mhd.wms.domain.outboundRank.repository.todo.OutboundRankDO"
resultType="com.mhd.wms.domain.outboundRank.repository.po.OutboundRankTotalPO">
select
IFNULL(SUM(a.outbound_quantity), 0) AS totalSalesQuantity,
COUNT(DISTINCT a.out_order_number) AS totalTradeCount,
IFNULL(SUM(IFNULL(a.TOTAL_AMOUNT, 0)), 0) AS totalAmount
<include refid="outboundRankFrom"/>
<where>
<include refid="outboundRankConditions"/>
<if test="materialCode != null and materialCode != ''">
and a.material_code like concat('%', #{materialCode}, '%')
</if>
<if test="materialName != null and materialName != ''">
and a.material_name like concat('%', #{materialName}, '%')
</if>
</where>
</select>
<!-- 线路出库排名合计(当前筛选条件全量) -->
<select id="queryLineRankTotal" parameterType="com.mhd.wms.domain.outboundRank.repository.todo.OutboundRankDO"
resultType="com.mhd.wms.domain.outboundRank.repository.po.OutboundRankTotalPO">
select
IFNULL(SUM(a.outbound_quantity), 0) AS totalSalesQuantity,
COUNT(DISTINCT b.out_order_number) AS totalTradeCount,
IFNULL(SUM(IFNULL(a.TOTAL_AMOUNT, 0)), 0) AS totalAmount
<include refid="outboundRankFrom"/>
<where>
<include refid="outboundRankConditions"/>
and b.line_code is not null and b.line_code != ''
</where>
</select>
</mapper>