Commit f7cd8573fda670e8d4241ed595b659cbcc5c2487
1 parent
a9464080
feat(wms):增加首页的 review
Showing
11 changed files
with
640 additions
and
0 deletions
yudao-module-wms/src/main/java/cn/iocoder/yudao/module/wms/controller/admin/home/WmsHomeStatisticsController.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.wms.controller.admin.home; | |
| 2 | + | |
| 3 | +import cn.iocoder.yudao.framework.common.pojo.CommonResult; | |
| 4 | +import cn.iocoder.yudao.module.wms.controller.admin.home.vo.WmsHomeInventorySummaryRespVO; | |
| 5 | +import cn.iocoder.yudao.module.wms.controller.admin.home.vo.WmsHomeOrderSummaryRespVO; | |
| 6 | +import cn.iocoder.yudao.module.wms.controller.admin.home.vo.WmsHomeOrderTrendRespVO; | |
| 7 | +import cn.iocoder.yudao.module.wms.service.home.WmsHomeStatisticsService; | |
| 8 | +import io.swagger.v3.oas.annotations.Operation; | |
| 9 | +import io.swagger.v3.oas.annotations.Parameter; | |
| 10 | +import io.swagger.v3.oas.annotations.tags.Tag; | |
| 11 | +import jakarta.annotation.Resource; | |
| 12 | +import jakarta.validation.constraints.Max; | |
| 13 | +import jakarta.validation.constraints.Min; | |
| 14 | +import org.springframework.security.access.prepost.PreAuthorize; | |
| 15 | +import org.springframework.validation.annotation.Validated; | |
| 16 | +import org.springframework.web.bind.annotation.GetMapping; | |
| 17 | +import org.springframework.web.bind.annotation.RequestMapping; | |
| 18 | +import org.springframework.web.bind.annotation.RequestParam; | |
| 19 | +import org.springframework.web.bind.annotation.RestController; | |
| 20 | + | |
| 21 | +import java.util.List; | |
| 22 | + | |
| 23 | +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; | |
| 24 | + | |
| 25 | +@Tag(name = "管理后台 - WMS 首页统计") | |
| 26 | +@RestController | |
| 27 | +@RequestMapping("/wms/home-statistics") | |
| 28 | +@Validated | |
| 29 | +public class WmsHomeStatisticsController { | |
| 30 | + | |
| 31 | + @Resource | |
| 32 | + private WmsHomeStatisticsService homeStatisticsService; | |
| 33 | + | |
| 34 | + @GetMapping("/order-summary") | |
| 35 | + @Operation(summary = "获得首页单据汇总统计") | |
| 36 | + @Parameter(name = "warehouseId", description = "仓库编号", example = "1024") | |
| 37 | + @PreAuthorize("@ss.hasPermission('wms:home:query')") | |
| 38 | + public CommonResult<List<WmsHomeOrderSummaryRespVO>> getOrderSummary( | |
| 39 | + @RequestParam(value = "warehouseId", required = false) Long warehouseId) { | |
| 40 | + return success(homeStatisticsService.getOrderSummary(warehouseId)); | |
| 41 | + } | |
| 42 | + | |
| 43 | + @GetMapping("/order-trend") | |
| 44 | + @Operation(summary = "获得首页单据趋势") | |
| 45 | + @Parameter(name = "days", description = "天数", example = "7") | |
| 46 | + @PreAuthorize("@ss.hasPermission('wms:home:query')") | |
| 47 | + public CommonResult<List<WmsHomeOrderTrendRespVO>> getOrderTrend( | |
| 48 | + @RequestParam(value = "days", defaultValue = "7") @Min(1) @Max(90) Integer days, | |
| 49 | + @RequestParam(value = "warehouseId", required = false) Long warehouseId) { | |
| 50 | + return success(homeStatisticsService.getOrderTrend(days, warehouseId)); | |
| 51 | + } | |
| 52 | + | |
| 53 | + @GetMapping("/inventory-summary") | |
| 54 | + @Operation(summary = "获得首页库存汇总统计") | |
| 55 | + @Parameter(name = "warehouseId", description = "仓库编号", example = "1024") | |
| 56 | + @PreAuthorize("@ss.hasPermission('wms:home:query')") | |
| 57 | + public CommonResult<WmsHomeInventorySummaryRespVO> getInventorySummary( | |
| 58 | + @RequestParam(value = "warehouseId", required = false) Long warehouseId) { | |
| 59 | + return success(homeStatisticsService.getInventorySummary(warehouseId)); | |
| 60 | + } | |
| 61 | + | |
| 62 | +} | ... | ... |
yudao-module-wms/src/main/java/cn/iocoder/yudao/module/wms/controller/admin/home/vo/WmsHomeInventoryItemRankRespVO.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.wms.controller.admin.home.vo; | |
| 2 | + | |
| 3 | +import io.swagger.v3.oas.annotations.media.Schema; | |
| 4 | +import lombok.Data; | |
| 5 | + | |
| 6 | +import java.math.BigDecimal; | |
| 7 | + | |
| 8 | +@Schema(description = "管理后台 - WMS 首页商品库存排行 Response VO") | |
| 9 | +@Data | |
| 10 | +public class WmsHomeInventoryItemRankRespVO { | |
| 11 | + | |
| 12 | + // TODO @AI:改成 id、name 会不会更好? | |
| 13 | + | |
| 14 | + @Schema(description = "商品编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") | |
| 15 | + private Long itemId; | |
| 16 | + | |
| 17 | + @Schema(description = "商品名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "A4 复印纸") | |
| 18 | + private String itemName; | |
| 19 | + | |
| 20 | + @Schema(description = "库存数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "100.00") | |
| 21 | + private BigDecimal quantity; | |
| 22 | + | |
| 23 | +} | ... | ... |
yudao-module-wms/src/main/java/cn/iocoder/yudao/module/wms/controller/admin/home/vo/WmsHomeInventorySummaryRespVO.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.wms.controller.admin.home.vo; | |
| 2 | + | |
| 3 | +import io.swagger.v3.oas.annotations.media.Schema; | |
| 4 | +import lombok.Data; | |
| 5 | + | |
| 6 | +import java.math.BigDecimal; | |
| 7 | +import java.util.List; | |
| 8 | + | |
| 9 | +@Schema(description = "管理后台 - WMS 首页库存汇总统计 Response VO") | |
| 10 | +@Data | |
| 11 | +public class WmsHomeInventorySummaryRespVO { | |
| 12 | + | |
| 13 | + // TODO @AI:一次性的 VO ,要不合并到 WmsHomeInventorySummaryRespVO 里?一个叫 ItemRank,一个叫 WarehouseRank? | |
| 14 | + | |
| 15 | + @Schema(description = "总库存数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "1000.00") | |
| 16 | + private BigDecimal totalQuantity; | |
| 17 | + | |
| 18 | + @Schema(description = "商品库存占比列表") | |
| 19 | + private List<WmsHomeInventoryItemRankRespVO> goodsShareList; | |
| 20 | + | |
| 21 | + @Schema(description = "仓库库存分布列表") | |
| 22 | + private List<WmsHomeInventoryWarehouseRankRespVO> warehouseDistributionList; | |
| 23 | + | |
| 24 | +} | ... | ... |
yudao-module-wms/src/main/java/cn/iocoder/yudao/module/wms/controller/admin/home/vo/WmsHomeInventoryWarehouseRankRespVO.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.wms.controller.admin.home.vo; | |
| 2 | + | |
| 3 | +import io.swagger.v3.oas.annotations.media.Schema; | |
| 4 | +import lombok.Data; | |
| 5 | + | |
| 6 | +import java.math.BigDecimal; | |
| 7 | + | |
| 8 | +@Schema(description = "管理后台 - WMS 首页仓库库存排行 Response VO") | |
| 9 | +@Data | |
| 10 | +public class WmsHomeInventoryWarehouseRankRespVO { | |
| 11 | + | |
| 12 | + // TODO @AI:改成 id、name 会不会更好? | |
| 13 | + | |
| 14 | + @Schema(description = "仓库编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") | |
| 15 | + private Long warehouseId; | |
| 16 | + | |
| 17 | + @Schema(description = "仓库名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "上海仓") | |
| 18 | + private String warehouseName; | |
| 19 | + | |
| 20 | + @Schema(description = "库存数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "100.00") | |
| 21 | + private BigDecimal quantity; | |
| 22 | + | |
| 23 | +} | ... | ... |
yudao-module-wms/src/main/java/cn/iocoder/yudao/module/wms/controller/admin/home/vo/WmsHomeOrderStatusRespVO.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.wms.controller.admin.home.vo; | |
| 2 | + | |
| 3 | +import io.swagger.v3.oas.annotations.media.Schema; | |
| 4 | +import lombok.AllArgsConstructor; | |
| 5 | +import lombok.Data; | |
| 6 | +import lombok.NoArgsConstructor; | |
| 7 | + | |
| 8 | +@Schema(description = "管理后台 - WMS 首页单据状态统计 Response VO") | |
| 9 | +@Data | |
| 10 | +@NoArgsConstructor | |
| 11 | +@AllArgsConstructor | |
| 12 | +public class WmsHomeOrderStatusRespVO { | |
| 13 | + | |
| 14 | + @Schema(description = "状态值", requiredMode = Schema.RequiredMode.REQUIRED, example = "0") | |
| 15 | + private Integer status; | |
| 16 | + | |
| 17 | + // TODO @AI:statusName 前端字段就翻译点? | |
| 18 | + @Schema(description = "状态名", requiredMode = Schema.RequiredMode.REQUIRED, example = "草稿") | |
| 19 | + private String statusName; | |
| 20 | + | |
| 21 | + @Schema(description = "单据数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "12") | |
| 22 | + private Long count; | |
| 23 | + | |
| 24 | +} | ... | ... |
yudao-module-wms/src/main/java/cn/iocoder/yudao/module/wms/controller/admin/home/vo/WmsHomeOrderSummaryRespVO.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.wms.controller.admin.home.vo; | |
| 2 | + | |
| 3 | +import io.swagger.v3.oas.annotations.media.Schema; | |
| 4 | +import lombok.Data; | |
| 5 | + | |
| 6 | +import java.util.List; | |
| 7 | + | |
| 8 | +@Schema(description = "管理后台 - WMS 首页单据汇总统计 Response VO") | |
| 9 | +@Data | |
| 10 | +public class WmsHomeOrderSummaryRespVO { | |
| 11 | + | |
| 12 | + // TODO @AI:orderType 缩写成 type? | |
| 13 | + | |
| 14 | + @Schema(description = "单据类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") | |
| 15 | + private Integer orderType; | |
| 16 | + | |
| 17 | + // TODO @AI:type 改成 dict tag 去翻译?或者字典工具类? | |
| 18 | + @Schema(description = "单据类型名", requiredMode = Schema.RequiredMode.REQUIRED, example = "入库单") | |
| 19 | + private String orderTypeName; | |
| 20 | + | |
| 21 | + @Schema(description = "单据总数", requiredMode = Schema.RequiredMode.REQUIRED, example = "12") | |
| 22 | + private Long total; | |
| 23 | + | |
| 24 | + // TODO @AI:statuses;状态分布; | |
| 25 | + @Schema(description = "状态分布") | |
| 26 | + private List<WmsHomeOrderStatusRespVO> statusList; | |
| 27 | + | |
| 28 | +} | ... | ... |
yudao-module-wms/src/main/java/cn/iocoder/yudao/module/wms/controller/admin/home/vo/WmsHomeOrderTrendRespVO.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.wms.controller.admin.home.vo; | |
| 2 | + | |
| 3 | +import io.swagger.v3.oas.annotations.media.Schema; | |
| 4 | +import lombok.Data; | |
| 5 | + | |
| 6 | +@Schema(description = "管理后台 - WMS 首页单据趋势 Response VO") | |
| 7 | +@Data | |
| 8 | +public class WmsHomeOrderTrendRespVO { | |
| 9 | + | |
| 10 | + // TODO @AI:可以使用 localdatetime?前端按需翻译?无非是 time 是 00 00 00 这样。灵活性更大。 | |
| 11 | + @Schema(description = "日期", requiredMode = Schema.RequiredMode.REQUIRED, example = "2026-05-14") | |
| 12 | + private String date; | |
| 13 | + | |
| 14 | + @Schema(description = "入库单数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "12") | |
| 15 | + private Long receiptCount; | |
| 16 | + | |
| 17 | + @Schema(description = "出库单数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "8") | |
| 18 | + private Long shipmentCount; | |
| 19 | + | |
| 20 | + @Schema(description = "移库单数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "3") | |
| 21 | + private Long movementCount; | |
| 22 | + | |
| 23 | + @Schema(description = "盘库单数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "2") | |
| 24 | + private Long checkCount; | |
| 25 | + | |
| 26 | +} | ... | ... |
yudao-module-wms/src/main/java/cn/iocoder/yudao/module/wms/dal/mysql/home/WmsHomeStatisticsMapper.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.wms.dal.mysql.home; | |
| 2 | + | |
| 3 | +import org.apache.ibatis.annotations.Mapper; | |
| 4 | +import org.apache.ibatis.annotations.Param; | |
| 5 | + | |
| 6 | +import java.math.BigDecimal; | |
| 7 | +import java.time.LocalDateTime; | |
| 8 | +import java.util.List; | |
| 9 | +import java.util.Map; | |
| 10 | + | |
| 11 | +/** | |
| 12 | + * WMS 首页统计 Mapper | |
| 13 | + * | |
| 14 | + * @author 芋道源码 | |
| 15 | + */ | |
| 16 | +@Mapper | |
| 17 | +public interface WmsHomeStatisticsMapper { | |
| 18 | + | |
| 19 | + /** | |
| 20 | + * 按单据类型和状态统计单据数量 | |
| 21 | + * | |
| 22 | + * @param warehouseId 仓库编号 | |
| 23 | + * @return [{ "orderType": 1, "status": 0, "count": 5 }, ...] | |
| 24 | + */ | |
| 25 | + List<Map<String, Object>> selectOrderCountGroupByTypeAndStatus(@Param("warehouseId") Long warehouseId); | |
| 26 | + | |
| 27 | + /** | |
| 28 | + * 按天聚合单据数量 | |
| 29 | + * | |
| 30 | + * @param beginTime >= 开始时间 | |
| 31 | + * @param endTime < 结束时间 | |
| 32 | + * @param warehouseId 仓库编号 | |
| 33 | + * @return [{ "date": "2026-05-14", "orderType": 1, "count": 5 }, ...] | |
| 34 | + */ | |
| 35 | + List<Map<String, Object>> selectDailyOrderTrend(@Param("beginTime") LocalDateTime beginTime, | |
| 36 | + @Param("endTime") LocalDateTime endTime, | |
| 37 | + @Param("warehouseId") Long warehouseId); | |
| 38 | + | |
| 39 | + /** | |
| 40 | + * 统计库存总数量 | |
| 41 | + * | |
| 42 | + * @param warehouseId 仓库编号 | |
| 43 | + * @return 库存总数量 | |
| 44 | + */ | |
| 45 | + BigDecimal selectInventoryTotalQuantity(@Param("warehouseId") Long warehouseId); | |
| 46 | + | |
| 47 | + /** | |
| 48 | + * 按商品统计库存数量排行 | |
| 49 | + * | |
| 50 | + * @param warehouseId 仓库编号 | |
| 51 | + * @param limit 数量限制 | |
| 52 | + * @return [{ "itemId": 1, "itemName": "A4 复印纸", "quantity": 100 }, ...] | |
| 53 | + */ | |
| 54 | + List<Map<String, Object>> selectInventoryItemRank(@Param("warehouseId") Long warehouseId, | |
| 55 | + @Param("limit") Integer limit); | |
| 56 | + | |
| 57 | + /** | |
| 58 | + * 按仓库统计库存数量排行 | |
| 59 | + * | |
| 60 | + * @param warehouseId 仓库编号 | |
| 61 | + * @param limit 数量限制 | |
| 62 | + * @return [{ "warehouseId": 1, "warehouseName": "上海仓", "quantity": 100 }, ...] | |
| 63 | + */ | |
| 64 | + List<Map<String, Object>> selectInventoryWarehouseRank(@Param("warehouseId") Long warehouseId, | |
| 65 | + @Param("limit") Integer limit); | |
| 66 | + | |
| 67 | +} | ... | ... |
yudao-module-wms/src/main/java/cn/iocoder/yudao/module/wms/service/home/WmsHomeStatisticsService.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.wms.service.home; | |
| 2 | + | |
| 3 | +import cn.iocoder.yudao.module.wms.controller.admin.home.vo.WmsHomeInventorySummaryRespVO; | |
| 4 | +import cn.iocoder.yudao.module.wms.controller.admin.home.vo.WmsHomeOrderSummaryRespVO; | |
| 5 | +import cn.iocoder.yudao.module.wms.controller.admin.home.vo.WmsHomeOrderTrendRespVO; | |
| 6 | + | |
| 7 | +import java.util.List; | |
| 8 | + | |
| 9 | +/** | |
| 10 | + * WMS 首页统计 Service 接口 | |
| 11 | + * | |
| 12 | + * @author 芋道源码 | |
| 13 | + */ | |
| 14 | +public interface WmsHomeStatisticsService { | |
| 15 | + | |
| 16 | + /** | |
| 17 | + * 获得单据汇总统计 | |
| 18 | + * | |
| 19 | + * @param warehouseId 仓库编号 | |
| 20 | + * @return 单据汇总统计 | |
| 21 | + */ | |
| 22 | + List<WmsHomeOrderSummaryRespVO> getOrderSummary(Long warehouseId); | |
| 23 | + | |
| 24 | + /** | |
| 25 | + * 获得单据趋势 | |
| 26 | + * | |
| 27 | + * @param days 天数 | |
| 28 | + * @param warehouseId 仓库编号 | |
| 29 | + * @return 单据趋势 | |
| 30 | + */ | |
| 31 | + List<WmsHomeOrderTrendRespVO> getOrderTrend(Integer days, Long warehouseId); | |
| 32 | + | |
| 33 | + /** | |
| 34 | + * 获得库存汇总统计 | |
| 35 | + * | |
| 36 | + * @param warehouseId 仓库编号 | |
| 37 | + * @return 库存汇总统计 | |
| 38 | + */ | |
| 39 | + WmsHomeInventorySummaryRespVO getInventorySummary(Long warehouseId); | |
| 40 | + | |
| 41 | +} | ... | ... |
yudao-module-wms/src/main/java/cn/iocoder/yudao/module/wms/service/home/WmsHomeStatisticsServiceImpl.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.wms.service.home; | |
| 2 | + | |
| 3 | +import cn.hutool.core.util.ObjectUtil; | |
| 4 | +import cn.iocoder.yudao.module.wms.controller.admin.home.vo.WmsHomeInventoryItemRankRespVO; | |
| 5 | +import cn.iocoder.yudao.module.wms.controller.admin.home.vo.WmsHomeInventorySummaryRespVO; | |
| 6 | +import cn.iocoder.yudao.module.wms.controller.admin.home.vo.WmsHomeInventoryWarehouseRankRespVO; | |
| 7 | +import cn.iocoder.yudao.module.wms.controller.admin.home.vo.WmsHomeOrderStatusRespVO; | |
| 8 | +import cn.iocoder.yudao.module.wms.controller.admin.home.vo.WmsHomeOrderSummaryRespVO; | |
| 9 | +import cn.iocoder.yudao.module.wms.controller.admin.home.vo.WmsHomeOrderTrendRespVO; | |
| 10 | +import cn.iocoder.yudao.module.wms.dal.mysql.home.WmsHomeStatisticsMapper; | |
| 11 | +import cn.iocoder.yudao.module.wms.enums.order.WmsOrderStatusEnum; | |
| 12 | +import cn.iocoder.yudao.module.wms.enums.order.WmsOrderTypeEnum; | |
| 13 | +import jakarta.annotation.Resource; | |
| 14 | +import org.springframework.stereotype.Service; | |
| 15 | + | |
| 16 | +import java.math.BigDecimal; | |
| 17 | +import java.time.LocalDate; | |
| 18 | +import java.time.LocalDateTime; | |
| 19 | +import java.time.format.DateTimeFormatter; | |
| 20 | +import java.util.ArrayList; | |
| 21 | +import java.util.Collections; | |
| 22 | +import java.util.HashMap; | |
| 23 | +import java.util.LinkedHashMap; | |
| 24 | +import java.util.List; | |
| 25 | +import java.util.Map; | |
| 26 | + | |
| 27 | +/** | |
| 28 | + * WMS 首页统计 Service 实现类 | |
| 29 | + * | |
| 30 | + * @author 芋道源码 | |
| 31 | + */ | |
| 32 | +@Service | |
| 33 | +public class WmsHomeStatisticsServiceImpl implements WmsHomeStatisticsService { | |
| 34 | + | |
| 35 | + // TODO @AI:8、5、交给前端传递; | |
| 36 | + private static final int GOODS_SHARE_LIMIT = 5; | |
| 37 | + private static final int WAREHOUSE_DISTRIBUTION_LIMIT = 8; | |
| 38 | + | |
| 39 | + @Resource | |
| 40 | + private WmsHomeStatisticsMapper homeStatisticsMapper; | |
| 41 | + | |
| 42 | + @Override | |
| 43 | + public List<WmsHomeOrderSummaryRespVO> getOrderSummary(Long warehouseId) { | |
| 44 | + List<Map<String, Object>> stats = homeStatisticsMapper.selectOrderCountGroupByTypeAndStatus(warehouseId); | |
| 45 | + // TODO @AI:convertList 链式调用。 | |
| 46 | + List<WmsHomeOrderSummaryRespVO> result = new ArrayList<>(); | |
| 47 | + for (WmsOrderTypeEnum orderTypeEnum : WmsOrderTypeEnum.values()) { | |
| 48 | + WmsHomeOrderSummaryRespVO vo = new WmsHomeOrderSummaryRespVO() | |
| 49 | + .setOrderType(orderTypeEnum.getType()).setOrderTypeName(orderTypeEnum.getName()); | |
| 50 | + // TODO @AI:collutils sum 是不是可以? | |
| 51 | + long total = 0L; | |
| 52 | + List<WmsHomeOrderStatusRespVO> statusList = new ArrayList<>(); | |
| 53 | + for (WmsOrderStatusEnum statusEnum : WmsOrderStatusEnum.values()) { | |
| 54 | + long count = getOrderCount(stats, orderTypeEnum.getType(), statusEnum.getStatus()); | |
| 55 | + total += count; | |
| 56 | + statusList.add(new WmsHomeOrderStatusRespVO(statusEnum.getStatus(), statusEnum.getName(), count)); | |
| 57 | + } | |
| 58 | + vo.setTotal(total).setStatusList(statusList); | |
| 59 | + result.add(vo); | |
| 60 | + } | |
| 61 | + return result; | |
| 62 | + } | |
| 63 | + | |
| 64 | + @Override | |
| 65 | + public List<WmsHomeOrderTrendRespVO> getOrderTrend(Integer days, Long warehouseId) { | |
| 66 | + // TODO @AI:同上? | |
| 67 | + LocalDate endDate = LocalDate.now().plusDays(1); | |
| 68 | + LocalDate startDate = endDate.minusDays(days); | |
| 69 | + LocalDateTime beginTime = startDate.atStartOfDay(); | |
| 70 | + LocalDateTime endTime = endDate.atStartOfDay(); | |
| 71 | + | |
| 72 | + List<Map<String, Object>> dbData = homeStatisticsMapper.selectDailyOrderTrend(beginTime, endTime, warehouseId); | |
| 73 | + Map<String, Map<Integer, Long>> dateMap = new LinkedHashMap<>(); | |
| 74 | + for (Map<String, Object> row : dbData) { | |
| 75 | + String date = (String) row.get("date"); | |
| 76 | + Integer orderType = getInteger(row, "orderType"); | |
| 77 | + Long count = getLong(row, "count"); | |
| 78 | + dateMap.computeIfAbsent(date, key -> new HashMap<>()).put(orderType, count); | |
| 79 | + } | |
| 80 | + // TODO @AI:链式调用; | |
| 81 | + DateTimeFormatter fmt = DateTimeFormatter.ofPattern("yyyy-MM-dd"); | |
| 82 | + List<WmsHomeOrderTrendRespVO> result = new ArrayList<>(); | |
| 83 | + for (LocalDate d = startDate; d.isBefore(endDate); d = d.plusDays(1)) { | |
| 84 | + String dateStr = d.format(fmt); | |
| 85 | + Map<Integer, Long> row = dateMap.getOrDefault(dateStr, Collections.emptyMap()); | |
| 86 | + WmsHomeOrderTrendRespVO vo = new WmsHomeOrderTrendRespVO(); | |
| 87 | + vo.setDate(dateStr); | |
| 88 | + vo.setReceiptCount(row.getOrDefault(WmsOrderTypeEnum.RECEIPT.getType(), 0L)); | |
| 89 | + vo.setShipmentCount(row.getOrDefault(WmsOrderTypeEnum.SHIPMENT.getType(), 0L)); | |
| 90 | + vo.setMovementCount(row.getOrDefault(WmsOrderTypeEnum.MOVEMENT.getType(), 0L)); | |
| 91 | + vo.setCheckCount(row.getOrDefault(WmsOrderTypeEnum.CHECK.getType(), 0L)); | |
| 92 | + result.add(vo); | |
| 93 | + } | |
| 94 | + return result; | |
| 95 | + } | |
| 96 | + | |
| 97 | + @Override | |
| 98 | + public WmsHomeInventorySummaryRespVO getInventorySummary(Long warehouseId) { | |
| 99 | + // TODO @AI:要不都先查询;然后 set 设置值; | |
| 100 | + return new WmsHomeInventorySummaryRespVO() | |
| 101 | + .setTotalQuantity(getDecimal(homeStatisticsMapper.selectInventoryTotalQuantity(warehouseId))) | |
| 102 | + .setGoodsShareList(buildInventoryItemRankList(homeStatisticsMapper.selectInventoryItemRank(warehouseId, GOODS_SHARE_LIMIT))) | |
| 103 | + .setWarehouseDistributionList(buildInventoryWarehouseRankList(homeStatisticsMapper.selectInventoryWarehouseRank(warehouseId, WAREHOUSE_DISTRIBUTION_LIMIT))); | |
| 104 | + } | |
| 105 | + | |
| 106 | + // TODO @AI:这个 ===== 太短了,加长! | |
| 107 | + // ========== 工具方法 ========== | |
| 108 | + | |
| 109 | + private long getOrderCount(List<Map<String, Object>> stats, Integer orderType, Integer status) { | |
| 110 | + for (Map<String, Object> stat : stats) { | |
| 111 | + if (ObjectUtil.equal(getInteger(stat, "orderType"), orderType) | |
| 112 | + && ObjectUtil.equal(getInteger(stat, "status"), status)) { | |
| 113 | + return getLong(stat, "count"); | |
| 114 | + } | |
| 115 | + } | |
| 116 | + return 0L; | |
| 117 | + } | |
| 118 | + | |
| 119 | + // TODO @AI:convertList;然后链式调用; | |
| 120 | + private List<WmsHomeInventoryItemRankRespVO> buildInventoryItemRankList(List<Map<String, Object>> rows) { | |
| 121 | + List<WmsHomeInventoryItemRankRespVO> result = new ArrayList<>(rows.size()); | |
| 122 | + for (Map<String, Object> row : rows) { | |
| 123 | + WmsHomeInventoryItemRankRespVO vo = new WmsHomeInventoryItemRankRespVO(); | |
| 124 | + vo.setItemId(getLong(row, "itemId")); | |
| 125 | + vo.setItemName((String) row.get("itemName")); | |
| 126 | + vo.setQuantity(getDecimal(row.get("quantity"))); | |
| 127 | + result.add(vo); | |
| 128 | + } | |
| 129 | + return result; | |
| 130 | + } | |
| 131 | + | |
| 132 | + // TODO @AI:convertList;然后链式调用; | |
| 133 | + private List<WmsHomeInventoryWarehouseRankRespVO> buildInventoryWarehouseRankList(List<Map<String, Object>> rows) { | |
| 134 | + List<WmsHomeInventoryWarehouseRankRespVO> result = new ArrayList<>(rows.size()); | |
| 135 | + for (Map<String, Object> row : rows) { | |
| 136 | + WmsHomeInventoryWarehouseRankRespVO vo = new WmsHomeInventoryWarehouseRankRespVO(); | |
| 137 | + vo.setWarehouseId(getLong(row, "warehouseId")); | |
| 138 | + vo.setWarehouseName((String) row.get("warehouseName")); | |
| 139 | + vo.setQuantity(getDecimal(row.get("quantity"))); | |
| 140 | + result.add(vo); | |
| 141 | + } | |
| 142 | + return result; | |
| 143 | + } | |
| 144 | + | |
| 145 | + // TODO @AI:maputil 直接使用 | |
| 146 | + private Integer getInteger(Map<String, Object> map, String key) { | |
| 147 | + Object value = map.get(key); | |
| 148 | + return value == null ? null : ((Number) value).intValue(); | |
| 149 | + } | |
| 150 | + | |
| 151 | + // TODO @AI:maputil 直接使用 | |
| 152 | + private Long getLong(Map<String, Object> map, String key) { | |
| 153 | + Object value = map.get(key); | |
| 154 | + return value == null ? 0L : ((Number) value).longValue(); | |
| 155 | + } | |
| 156 | + | |
| 157 | + // TODO @AI:maputil 直接使用 | |
| 158 | + private BigDecimal getDecimal(Object value) { | |
| 159 | + if (value == null) { | |
| 160 | + return BigDecimal.ZERO; | |
| 161 | + } | |
| 162 | + if (value instanceof BigDecimal) { | |
| 163 | + return (BigDecimal) value; | |
| 164 | + } | |
| 165 | + return new BigDecimal(value.toString()); | |
| 166 | + } | |
| 167 | + | |
| 168 | +} | ... | ... |
yudao-module-wms/src/main/resources/mapper/home/WmsHomeStatisticsMapper.xml
0 → 100644
| 1 | +<?xml version="1.0" encoding="UTF-8"?> | |
| 2 | +<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> | |
| 3 | +<mapper namespace="cn.iocoder.yudao.module.wms.dal.mysql.home.WmsHomeStatisticsMapper"> | |
| 4 | + | |
| 5 | + <!-- 按单据类型和状态统计单据数量 --> | |
| 6 | + <select id="selectOrderCountGroupByTypeAndStatus" resultType="java.util.Map"> | |
| 7 | + SELECT orderType, status, SUM(count) AS count | |
| 8 | + FROM ( | |
| 9 | + SELECT ${@cn.iocoder.yudao.module.wms.enums.order.WmsOrderTypeEnum@RECEIPT.type} AS orderType, | |
| 10 | + status, | |
| 11 | + COUNT(*) AS count | |
| 12 | + FROM wms_receipt_order | |
| 13 | + WHERE deleted = 0 | |
| 14 | + <if test="warehouseId != null"> | |
| 15 | + AND warehouse_id = #{warehouseId} | |
| 16 | + </if> | |
| 17 | + GROUP BY status | |
| 18 | + UNION ALL | |
| 19 | + SELECT ${@cn.iocoder.yudao.module.wms.enums.order.WmsOrderTypeEnum@SHIPMENT.type} AS orderType, | |
| 20 | + status, | |
| 21 | + COUNT(*) AS count | |
| 22 | + FROM wms_shipment_order | |
| 23 | + WHERE deleted = 0 | |
| 24 | + <if test="warehouseId != null"> | |
| 25 | + AND warehouse_id = #{warehouseId} | |
| 26 | + </if> | |
| 27 | + GROUP BY status | |
| 28 | + UNION ALL | |
| 29 | + SELECT ${@cn.iocoder.yudao.module.wms.enums.order.WmsOrderTypeEnum@MOVEMENT.type} AS orderType, | |
| 30 | + status, | |
| 31 | + COUNT(*) AS count | |
| 32 | + FROM wms_movement_order | |
| 33 | + WHERE deleted = 0 | |
| 34 | + <if test="warehouseId != null"> | |
| 35 | + AND (source_warehouse_id = #{warehouseId} OR target_warehouse_id = #{warehouseId}) | |
| 36 | + </if> | |
| 37 | + GROUP BY status | |
| 38 | + UNION ALL | |
| 39 | + SELECT ${@cn.iocoder.yudao.module.wms.enums.order.WmsOrderTypeEnum@CHECK.type} AS orderType, | |
| 40 | + status, | |
| 41 | + COUNT(*) AS count | |
| 42 | + FROM wms_check_order | |
| 43 | + WHERE deleted = 0 | |
| 44 | + <if test="warehouseId != null"> | |
| 45 | + AND warehouse_id = #{warehouseId} | |
| 46 | + </if> | |
| 47 | + GROUP BY status | |
| 48 | + ) t | |
| 49 | + GROUP BY orderType, status | |
| 50 | + ORDER BY orderType, status | |
| 51 | + </select> | |
| 52 | + | |
| 53 | + <!-- 按天聚合单据数量 --> | |
| 54 | + <select id="selectDailyOrderTrend" resultType="java.util.Map"> | |
| 55 | + SELECT date, orderType, SUM(count) AS count | |
| 56 | + FROM ( | |
| 57 | + SELECT DATE_FORMAT(order_time, '%Y-%m-%d') AS date, | |
| 58 | + ${@cn.iocoder.yudao.module.wms.enums.order.WmsOrderTypeEnum@RECEIPT.type} AS orderType, | |
| 59 | + COUNT(*) AS count | |
| 60 | + FROM wms_receipt_order | |
| 61 | + WHERE deleted = 0 | |
| 62 | + AND order_time >= #{beginTime} | |
| 63 | + AND order_time < #{endTime} | |
| 64 | + <if test="warehouseId != null"> | |
| 65 | + AND warehouse_id = #{warehouseId} | |
| 66 | + </if> | |
| 67 | + GROUP BY DATE_FORMAT(order_time, '%Y-%m-%d') | |
| 68 | + UNION ALL | |
| 69 | + SELECT DATE_FORMAT(order_time, '%Y-%m-%d') AS date, | |
| 70 | + ${@cn.iocoder.yudao.module.wms.enums.order.WmsOrderTypeEnum@SHIPMENT.type} AS orderType, | |
| 71 | + COUNT(*) AS count | |
| 72 | + FROM wms_shipment_order | |
| 73 | + WHERE deleted = 0 | |
| 74 | + AND order_time >= #{beginTime} | |
| 75 | + AND order_time < #{endTime} | |
| 76 | + <if test="warehouseId != null"> | |
| 77 | + AND warehouse_id = #{warehouseId} | |
| 78 | + </if> | |
| 79 | + GROUP BY DATE_FORMAT(order_time, '%Y-%m-%d') | |
| 80 | + UNION ALL | |
| 81 | + SELECT DATE_FORMAT(order_time, '%Y-%m-%d') AS date, | |
| 82 | + ${@cn.iocoder.yudao.module.wms.enums.order.WmsOrderTypeEnum@MOVEMENT.type} AS orderType, | |
| 83 | + COUNT(*) AS count | |
| 84 | + FROM wms_movement_order | |
| 85 | + WHERE deleted = 0 | |
| 86 | + AND order_time >= #{beginTime} | |
| 87 | + AND order_time < #{endTime} | |
| 88 | + <if test="warehouseId != null"> | |
| 89 | + AND (source_warehouse_id = #{warehouseId} OR target_warehouse_id = #{warehouseId}) | |
| 90 | + </if> | |
| 91 | + GROUP BY DATE_FORMAT(order_time, '%Y-%m-%d') | |
| 92 | + UNION ALL | |
| 93 | + SELECT DATE_FORMAT(order_time, '%Y-%m-%d') AS date, | |
| 94 | + ${@cn.iocoder.yudao.module.wms.enums.order.WmsOrderTypeEnum@CHECK.type} AS orderType, | |
| 95 | + COUNT(*) AS count | |
| 96 | + FROM wms_check_order | |
| 97 | + WHERE deleted = 0 | |
| 98 | + AND order_time >= #{beginTime} | |
| 99 | + AND order_time < #{endTime} | |
| 100 | + <if test="warehouseId != null"> | |
| 101 | + AND warehouse_id = #{warehouseId} | |
| 102 | + </if> | |
| 103 | + GROUP BY DATE_FORMAT(order_time, '%Y-%m-%d') | |
| 104 | + ) t | |
| 105 | + GROUP BY date, orderType | |
| 106 | + ORDER BY date, orderType | |
| 107 | + </select> | |
| 108 | + | |
| 109 | + <!-- 统计库存总数量 --> | |
| 110 | + <select id="selectInventoryTotalQuantity" resultType="java.math.BigDecimal"> | |
| 111 | + SELECT IFNULL(SUM(quantity), 0) | |
| 112 | + FROM wms_inventory | |
| 113 | + WHERE deleted = 0 | |
| 114 | + <if test="warehouseId != null"> | |
| 115 | + AND warehouse_id = #{warehouseId} | |
| 116 | + </if> | |
| 117 | + </select> | |
| 118 | + | |
| 119 | + <!-- 按商品统计库存数量排行 --> | |
| 120 | + <select id="selectInventoryItemRank" resultType="java.util.Map"> | |
| 121 | + SELECT item.id AS itemId, | |
| 122 | + item.name AS itemName, | |
| 123 | + IFNULL(SUM(inventory.quantity), 0) AS quantity | |
| 124 | + FROM wms_inventory inventory | |
| 125 | + INNER JOIN wms_item_sku sku ON sku.id = inventory.sku_id AND sku.deleted = 0 | |
| 126 | + INNER JOIN wms_item item ON item.id = sku.item_id AND item.deleted = 0 | |
| 127 | + WHERE inventory.deleted = 0 | |
| 128 | + AND inventory.quantity > 0 | |
| 129 | + <if test="warehouseId != null"> | |
| 130 | + AND inventory.warehouse_id = #{warehouseId} | |
| 131 | + </if> | |
| 132 | + GROUP BY item.id, item.name | |
| 133 | + ORDER BY quantity DESC, item.id ASC | |
| 134 | + LIMIT #{limit} | |
| 135 | + </select> | |
| 136 | + | |
| 137 | + <!-- 按仓库统计库存数量排行 --> | |
| 138 | + <select id="selectInventoryWarehouseRank" resultType="java.util.Map"> | |
| 139 | + SELECT warehouse.id AS warehouseId, | |
| 140 | + warehouse.name AS warehouseName, | |
| 141 | + IFNULL(SUM(inventory.quantity), 0) AS quantity | |
| 142 | + FROM wms_inventory inventory | |
| 143 | + INNER JOIN wms_warehouse warehouse ON warehouse.id = inventory.warehouse_id AND warehouse.deleted = 0 | |
| 144 | + WHERE inventory.deleted = 0 | |
| 145 | + AND inventory.quantity > 0 | |
| 146 | + <if test="warehouseId != null"> | |
| 147 | + AND inventory.warehouse_id = #{warehouseId} | |
| 148 | + </if> | |
| 149 | + GROUP BY warehouse.id, warehouse.name | |
| 150 | + ORDER BY quantity DESC, warehouse.id ASC | |
| 151 | + LIMIT #{limit} | |
| 152 | + </select> | |
| 153 | + | |
| 154 | +</mapper> | ... | ... |