feat(wms,oms):出库排名统计改造为仓单×货品明细列表,按出库数量降序排名

- 字段:种类/仓单编号/入库单号/客户编号/收货人/货名/线路/件数/毛重(吨)/体积(CBM)/退保总额(占位null,数据来源待确认)/出仓日期

- 商品/线路各一套接口,路径名不变;商品接口忽略线路筛选参数,线路接口忽略商品筛选参数;含合计行(件数/毛重吨/体积/仓单数)与Excel导出

- 统计口径不变:出库单创建时间区间+已出库状态(9,12,13)+明细level=1主行;排序按出库数量(销售量)降序,件数/出仓日期/单号次之

- 数据源:WMS查本库出库表;OMS跨库查NGWL_TEST_WMS同名表(OMS库出库单状态不流转,跨库与WMS端数字一致)

- 删除原按商品/线路聚合的排名接口(销售量/交易数/金额字段)
This commit is contained in:
rcx
2026-09-02 15:25:51 +08:00
parent e821619a96
commit 3af78d5d7b
28 changed files with 554 additions and 684 deletions
@@ -3,27 +3,38 @@ package com.mhd.wms.interfaces.dto.outboundRank;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.io.Serializable;
/**
* 出库排名统计入参DTO
* 出库排名统计(明细)入参DTO
*
* <p>按日期区间统计商品/线路出库量排名,统计口径:出库单创建时间 + 已出库及之后状态(9,12,13)</p>
* <p>按日期区间筛选出库明细列表,一行 = 仓单×货品(件数/毛重/体积按行汇总,件数降序),
* 统计口径:出库单创建时间 + 已出库及之后状态(9,12,13) + 明细仅取 level=1 主行</p>
*
* @author rcx
* @date 2026-08-31
*/
@Data
public class OutboundRankDTO {
public class OutboundRankDTO implements Serializable {
@ApiModelProperty("出库日期-开始 yyyy-MM-dd(必填,按出库单创建时间统计)")
private static final long serialVersionUID = 1L;
@ApiModelProperty("出库日期-开始 yyyy-MM-dd(必填,按出库单创建时间筛选)")
private String createTimeStart;
@ApiModelProperty("出库日期-结束 yyyy-MM-dd(必填,按出库单创建时间统计")
@ApiModelProperty("出库日期-结束 yyyy-MM-dd(必填,按出库单创建时间筛选")
private String createTimeEnd;
@ApiModelProperty("仓单编号/出库单号(模糊)")
private String outOrderNumber;
@ApiModelProperty("入库单号(模糊)")
private String inOrderNumber;
@ApiModelProperty("商品货号(模糊)")
private String materialCode;
@ApiModelProperty("商品名称(模糊)")
@ApiModelProperty("货名/商品名称(模糊)")
private String materialName;
@ApiModelProperty("线路编码(模糊)")
@@ -5,9 +5,8 @@ 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.po.OutboundDetailRankPO;
import com.mhd.wms.domain.outboundRank.repository.po.OutboundDetailRankTotalPO;
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;
@@ -26,8 +25,10 @@ import java.util.List;
/**
* 出库排名统计Api
*
* <p>按日期区间筛选,统计商品/线路出库量排名。统计口径:出库单创建时间 + 已出库及之后状态(9,12,13)
* 明细仅取 level=1 主行;销售量=SUM(出库数量)、交易数=COUNT(DISTINCT 出库单号)、金额=SUM(明细总价)</p>
* <p>按日期区间筛选出库明细列表(一行 = 仓单×货品,件数/毛重/体积按行汇总,按出库数量(销售量)降序,件数/出仓日期/单号次之)。
* 统计口径:出库单创建时间 + 已出库及之后状态(9,12,13),明细仅取 level=1 主行。
* 商品/线路两个 tab 各自独立接口,内部为同一份明细查询:商品接口忽略线路筛选参数,线路接口忽略商品筛选参数。
* 字段:种类/仓单编号/入库单号/客户编号/收货人/货名/线路/件数/毛重(吨)/体积(CBM)/退保总额(占位null)/出仓日期</p>
*
* @author rcx
* @date 2026-08-31
@@ -43,84 +44,97 @@ public class OutboundRankApi {
private OutboundRankApplicationService outboundRankApplicationService;
/**
* 分页查询商品出库排名列表(含合计行)
* 分页查询商品出库排名列表(含合计行,商品tab;忽略线路筛选参数
*/
@ApiOperation("分页查询商品出库排名列表")
@GetMapping("/queryMaterialRankList")
public HashMap<String, Object> queryMaterialRankList(OutboundRankDTO outboundRankDTO) {
//转换实体
OutboundRankDO outboundRankDO = outboundRankAssembler.toDO(outboundRankDTO);
//商品tab:忽略线路筛选参数
outboundRankDO.setLineCode(null);
outboundRankDO.setLineName(null);
startPage();
List<OutboundMaterialRankPO> list = outboundRankApplicationService.queryMaterialRankList(outboundRankDO);
OutboundRankTotalPO total = outboundRankApplicationService.queryMaterialRankTotal(outboundRankDO);
List<OutboundDetailRankPO> list = outboundRankApplicationService.queryDetailList(outboundRankDO);
OutboundDetailRankTotalPO total = outboundRankApplicationService.queryDetailTotal(outboundRankDO);
return getDataTableWithTotal(list, total);
}
/**
* 分页查询线路出库排名列表(含合计行)
* 分页查询线路出库排名列表(含合计行,线路tab;忽略商品筛选参数
*/
@ApiOperation("分页查询线路出库排名列表")
@GetMapping("/queryLineRankList")
public HashMap<String, Object> queryLineRankList(OutboundRankDTO outboundRankDTO) {
//转换实体
OutboundRankDO outboundRankDO = outboundRankAssembler.toDO(outboundRankDTO);
//线路tab:忽略商品筛选参数
outboundRankDO.setMaterialCode(null);
outboundRankDO.setMaterialName(null);
startPage();
List<OutboundLineRankPO> list = outboundRankApplicationService.queryLineRankList(outboundRankDO);
OutboundRankTotalPO total = outboundRankApplicationService.queryLineRankTotal(outboundRankDO);
List<OutboundDetailRankPO> list = outboundRankApplicationService.queryDetailList(outboundRankDO);
OutboundDetailRankTotalPO total = outboundRankApplicationService.queryDetailTotal(outboundRankDO);
return getDataTableWithTotal(list, total);
}
/**
* 导出商品出库排名Excel
* 导出商品出库排名Excel(商品tab;忽略线路筛选参数)
*/
@ApiOperation("导出商品出库排名Excel")
@GetMapping("/exportMaterialRank")
public void exportMaterialRank(HttpServletResponse response, OutboundRankDTO outboundRankDTO) throws Exception {
//转换实体(不分页,导出全量)
OutboundRankDO outboundRankDO = outboundRankAssembler.toDO(outboundRankDTO);
List<OutboundMaterialRankPO> list = outboundRankApplicationService.exportMaterialRankList(outboundRankDO);
//商品tab:忽略线路筛选参数
outboundRankDO.setLineCode(null);
outboundRankDO.setLineName(null);
List<OutboundDetailRankPO> list = outboundRankApplicationService.exportDetailList(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);
ExcelUtil<OutboundDetailRankPO> util = new ExcelUtil<>(OutboundDetailRankPO.class);
util.exportExcel(response, list, "商品出库排名");
}
/**
* 导出线路出库排名Excel
* 导出线路出库排名Excel(线路tab;忽略商品筛选参数)
*/
@ApiOperation("导出线路出库排名Excel")
@GetMapping("/exportLineRank")
public void exportLineRank(HttpServletResponse response, OutboundRankDTO outboundRankDTO) throws Exception {
//转换实体(不分页,导出全量)
OutboundRankDO outboundRankDO = outboundRankAssembler.toDO(outboundRankDTO);
List<OutboundLineRankPO> list = outboundRankApplicationService.exportLineRankList(outboundRankDO);
//线路tab:忽略商品筛选参数
outboundRankDO.setMaterialCode(null);
outboundRankDO.setMaterialName(null);
List<OutboundDetailRankPO> list = outboundRankApplicationService.exportDetailList(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);
ExcelUtil<OutboundDetailRankPO> util = new ExcelUtil<>(OutboundDetailRankPO.class);
util.exportExcel(response, list, "线路出库排名");
}
/**
* 分页结果 + 合计行:data/total/code/msg 之外追加 totalSalesQuantity/totalTradeCount/totalAmount
* 分页结果 + 合计行:data/total/code/msg 之外追加 totalPieceCount/totalGrossWeightTon/totalVolume/totalOrderCount
*/
private HashMap<String, Object> getDataTableWithTotal(List<?> list, OutboundRankTotalPO total) {
private HashMap<String, Object> getDataTableWithTotal(List<?> list, OutboundDetailRankTotalPO 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());
result.put("totalPieceCount", total.getTotalPieceCount());
result.put("totalGrossWeightTon", total.getTotalGrossWeightTon());
result.put("totalVolume", total.getTotalVolume());
result.put("totalOrderCount", total.getTotalOrderCount());
}
return result;
}