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> |