Ver Fonte

[update] 版本号, 鉴权, 仓库商品产品分析接口开发

miajio há 2 dias atrás
pai
commit
2765eb405b
49 ficheiros alterados com 3550 adições e 15 exclusões
  1. 12 12
      pom.xml
  2. 53 0
      warehouse-admin-data/src/main/java/com/yr/warehouse/admin/warehouse/bo/WarehouseProductDemandAnalysisEditorBo.java
  3. 61 0
      warehouse-admin-data/src/main/java/com/yr/warehouse/admin/warehouse/bo/WarehouseProductDemandAnalysisGeneratorBo.java
  4. 30 0
      warehouse-admin-data/src/main/java/com/yr/warehouse/admin/warehouse/bo/WarehouseProductDemandAnalysisHistoryBo.java
  5. 49 0
      warehouse-admin-data/src/main/java/com/yr/warehouse/admin/warehouse/bo/WarehouseProductDemandAnalysisHistoryPageBo.java
  6. 61 0
      warehouse-admin-data/src/main/java/com/yr/warehouse/admin/warehouse/bo/WarehouseProductDemandAnalysisPageBo.java
  7. 146 0
      warehouse-admin-data/src/main/java/com/yr/warehouse/admin/warehouse/data/WarehouseInfo.java
  8. 165 0
      warehouse-admin-data/src/main/java/com/yr/warehouse/admin/warehouse/data/WarehouseProduct.java
  9. 214 0
      warehouse-admin-data/src/main/java/com/yr/warehouse/admin/warehouse/data/WarehouseProductDemandAnalysisDetail.java
  10. 117 0
      warehouse-admin-data/src/main/java/com/yr/warehouse/admin/warehouse/data/WarehouseProductDemandAnalysisInfo.java
  11. 24 0
      warehouse-admin-data/src/main/java/com/yr/warehouse/admin/warehouse/mapper/WarehouseInfoMapper.java
  12. 39 0
      warehouse-admin-data/src/main/java/com/yr/warehouse/admin/warehouse/mapper/WarehouseProductDemandAnalysisDetailMapper.java
  13. 36 0
      warehouse-admin-data/src/main/java/com/yr/warehouse/admin/warehouse/mapper/WarehouseProductDemandAnalysisInfoMapper.java
  14. 50 0
      warehouse-admin-data/src/main/java/com/yr/warehouse/admin/warehouse/mapper/WarehouseProductDemandAnalysisMapper.java
  15. 27 0
      warehouse-admin-data/src/main/java/com/yr/warehouse/admin/warehouse/mapper/WarehouseProductMapper.java
  16. 96 0
      warehouse-admin-data/src/main/java/com/yr/warehouse/admin/warehouse/vo/WarehouseProductDemandAnalysisHistoryVo.java
  17. 233 0
      warehouse-admin-data/src/main/java/com/yr/warehouse/admin/warehouse/vo/WarehouseProductDemandAnalysisVo.java
  18. 145 0
      warehouse-admin-data/src/main/java/com/yr/warehouse/admin/warehouse/vo/WarehouseProductVo.java
  19. 27 0
      warehouse-admin-data/src/main/java/com/yr/warehouse/admin/warehouse/vo/WarehouseRequirementsVo.java
  20. 42 0
      warehouse-admin-data/src/main/resources/mapper/warehouse/WarehouseInfoMapper.xml
  21. 123 0
      warehouse-admin-data/src/main/resources/mapper/warehouse/WarehouseProductDemandAnalysisDetailMapper.xml
  22. 97 0
      warehouse-admin-data/src/main/resources/mapper/warehouse/WarehouseProductDemandAnalysisInfoMapper.xml
  23. 160 0
      warehouse-admin-data/src/main/resources/mapper/warehouse/WarehouseProductDemandAnalysisMapper.xml
  24. 75 0
      warehouse-admin-data/src/main/resources/mapper/warehouse/WarehouseProductMapper.xml
  25. 2 3
      warehouse-admin-data/src/main/test/com/supplychain/CodeGenerator.java
  26. 16 0
      warehouse-admin-server/src/main/java/com/yr/warehouse/admin/service/warehouse/service/WarehouseInfoService.java
  27. 16 0
      warehouse-admin-server/src/main/java/com/yr/warehouse/admin/service/warehouse/service/WarehouseProductDemandAnalysisDetailService.java
  28. 16 0
      warehouse-admin-server/src/main/java/com/yr/warehouse/admin/service/warehouse/service/WarehouseProductDemandAnalysisInfoService.java
  29. 61 0
      warehouse-admin-server/src/main/java/com/yr/warehouse/admin/service/warehouse/service/WarehouseProductDemandAnalysisService.java
  30. 27 0
      warehouse-admin-server/src/main/java/com/yr/warehouse/admin/service/warehouse/service/WarehouseProductService.java
  31. 20 0
      warehouse-admin-server/src/main/java/com/yr/warehouse/admin/service/warehouse/service/impl/WarehouseInfoServiceImpl.java
  32. 20 0
      warehouse-admin-server/src/main/java/com/yr/warehouse/admin/service/warehouse/service/impl/WarehouseProductDemandAnalysisDetailServiceImpl.java
  33. 20 0
      warehouse-admin-server/src/main/java/com/yr/warehouse/admin/service/warehouse/service/impl/WarehouseProductDemandAnalysisInfoServiceImpl.java
  34. 121 0
      warehouse-admin-server/src/main/java/com/yr/warehouse/admin/service/warehouse/service/impl/WarehouseProductDemandAnalysisServiceImpl.java
  35. 27 0
      warehouse-admin-server/src/main/java/com/yr/warehouse/admin/service/warehouse/service/impl/WarehouseProductServiceImpl.java
  36. 236 0
      warehouse-admin-web/src/main/java/com/yr/warehouse/admin/web/product/controller/WarehouseProductDemandAnalysisController.java
  37. 59 0
      warehouse-admin-web/src/main/java/com/yr/warehouse/admin/web/product/excel/WarehouseProductDemandAnalysisExcel.java
  38. 187 0
      warehouse-admin-web/src/main/java/com/yr/warehouse/admin/web/product/export/WarehouseProductDemandAnalysisExport.java
  39. 39 0
      warehouse-admin-web/src/main/java/com/yr/warehouse/admin/web/product/mapstruct/WarehouseProductMapStruct.java
  40. 26 0
      warehouse-admin-web/src/main/java/com/yr/warehouse/admin/web/product/request/WarehouseProductDemandAnalysisBatchImportRequest.java
  41. 49 0
      warehouse-admin-web/src/main/java/com/yr/warehouse/admin/web/product/request/WarehouseProductDemandAnalysisEditorRequest.java
  42. 39 0
      warehouse-admin-web/src/main/java/com/yr/warehouse/admin/web/product/request/WarehouseProductDemandAnalysisExportRequest.java
  43. 59 0
      warehouse-admin-web/src/main/java/com/yr/warehouse/admin/web/product/request/WarehouseProductDemandAnalysisGeneratorRequest.java
  44. 47 0
      warehouse-admin-web/src/main/java/com/yr/warehouse/admin/web/product/request/WarehouseProductDemandAnalysisHistoryExportRequest.java
  45. 53 0
      warehouse-admin-web/src/main/java/com/yr/warehouse/admin/web/product/request/WarehouseProductDemandAnalysisHistoryPageRequest.java
  46. 31 0
      warehouse-admin-web/src/main/java/com/yr/warehouse/admin/web/product/request/WarehouseProductDemandAnalysisHistoryRequest.java
  47. 62 0
      warehouse-admin-web/src/main/java/com/yr/warehouse/admin/web/product/request/WarehouseProductDemandAnalysisPageRequest.java
  48. 76 0
      warehouse-admin-web/src/main/java/com/yr/warehouse/admin/web/product/response/WarehouseProductDemandAnalysisHistoryResponse.java
  49. 159 0
      warehouse-admin-web/src/main/java/com/yr/warehouse/admin/web/product/response/WarehouseProductDemandAnalysisResponse.java

+ 12 - 12
pom.xml

@@ -30,9 +30,9 @@
         <springboot.version>3.1.5</springboot.version>
         <mapstruct.version>1.4.2.Final</mapstruct.version>
         <bluecat.common.version>1.1.2-SNAPSHOT</bluecat.common.version>
-        <prism-auth-core.version>1.9.0-SNAPSHOT</prism-auth-core.version>
-        <prism-auth-support.version>1.9.0-SNAPSHOT</prism-auth-support.version>
-        <yr-supply-chain-api.version>1.2.2-SNAPSHOT</yr-supply-chain-api.version>
+        <prism-auth-core.version>1.10.4-SNAPSHOT</prism-auth-core.version>
+        <prism-auth-support.version>1.10.4-SNAPSHOT</prism-auth-support.version>
+        <yr-supply-chain-api.version>1.2.5-SNAPSHOT</yr-supply-chain-api.version>
         <yr-shopping-admin.version>1.0.3-SNAPSHOT</yr-shopping-admin.version>
         <dubbo.version>3.2.9</dubbo.version>
         <nacos.version>2.2.4</nacos.version>
@@ -211,9 +211,9 @@
                 <!-- 开发环境固定1.0.2 -->
                 <revision>1.0.0-SNAPSHOT</revision>
                 <bluecat.common.version>1.1.2-SNAPSHOT</bluecat.common.version>
-                <prism-auth-support.version>1.9.0-SNAPSHOT</prism-auth-support.version>
-                <prism-auth-core.version>1.9.0-SNAPSHOT</prism-auth-core.version>
-                <yr-supply-chain-api.version>1.2.2-SNAPSHOT</yr-supply-chain-api.version>
+                <prism-auth-support.version>1.10.4-SNAPSHOT</prism-auth-support.version>
+                <prism-auth-core.version>1.10.4-SNAPSHOT</prism-auth-core.version>
+                <yr-supply-chain-api.version>1.2.5-SNAPSHOT</yr-supply-chain-api.version>
                 <yr-shopping-admin.version>1.0.3-SNAPSHOT</yr-shopping-admin.version>
             </properties>
             <distributionManagement>
@@ -230,9 +230,9 @@
             <properties>
                 <revision>1.0.0-SNAPSHOT</revision>
                 <bluecat.common.version>1.1.2-SNAPSHOT</bluecat.common.version>
-                <prism-auth-support.version>1.9.0-SNAPSHOT</prism-auth-support.version>
-                <prism-auth-core.version>1.9.0-SNAPSHOT</prism-auth-core.version>
-                <yr-supply-chain-api.version>1.2.2-SNAPSHOT</yr-supply-chain-api.version>
+                <prism-auth-support.version>1.10.4-SNAPSHOT</prism-auth-support.version>
+                <prism-auth-core.version>1.10.4-SNAPSHOT</prism-auth-core.version>
+                <yr-supply-chain-api.version>1.2.5-SNAPSHOT</yr-supply-chain-api.version>
                 <yr-shopping-admin.version>1.0.3-SNAPSHOT</yr-shopping-admin.version>
             </properties>
             <distributionManagement>
@@ -248,9 +248,9 @@
             <properties>
                 <revision>1.0.0-RELEASE</revision>
                 <bluecat.common.version>1.1.2-RELEASE</bluecat.common.version>
-                <prism-auth-support.version>1.9.0-RELEASE</prism-auth-support.version>
-                <prism-auth-core.version>1.9.0-RELEASE</prism-auth-core.version>
-                <yr-supply-chain-api.version>1.2.2-RELEASE</yr-supply-chain-api.version>
+                <prism-auth-support.version>1.10.4-RELEASE</prism-auth-support.version>
+                <prism-auth-core.version>1.10.4-RELEASE</prism-auth-core.version>
+                <yr-supply-chain-api.version>1.2.5-RELEASE</yr-supply-chain-api.version>
                 <yr-shopping-admin.version>1.0.3-RELEASE</yr-shopping-admin.version>
             </properties>
             <distributionManagement>

+ 53 - 0
warehouse-admin-data/src/main/java/com/yr/warehouse/admin/warehouse/bo/WarehouseProductDemandAnalysisEditorBo.java

@@ -0,0 +1,53 @@
+package com.yr.warehouse.admin.warehouse.bo;
+
+import com.yr.bluecat.common.entity.bo.BaseBo;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+import java.io.Serializable;
+import java.math.BigDecimal;
+
+/**
+ * 仓库商品需求分析编辑参数
+ */
+@EqualsAndHashCode(callSuper = true)
+@Data
+public class WarehouseProductDemandAnalysisEditorBo extends BaseBo implements Serializable {
+
+    /**
+     * 仓库商品id
+     */
+    private Long id;
+
+    /**
+     * 采购周期
+     * 人工填写 默认 7 天
+     */
+    private Long procurementCycle;
+
+    /**
+     * 起订量
+     * 人工填写 默认 0
+     */
+    private Long moq;
+
+    /**
+     * 安全库存数
+     * 人工填写 默认1
+     */
+    private Long inventoryWarningQuantity;
+
+    /**
+     * 预警系数
+     * 人工填写 默认1.0 - 预警系数必须大于等于: 1
+     */
+    private BigDecimal warningCoefficient;
+
+    public void build() {
+        this.procurementCycle = this.procurementCycle == null ? 7 : this.procurementCycle;
+        this.moq = this.moq == null ? 0 : this.moq;
+        this.inventoryWarningQuantity = this.inventoryWarningQuantity == null ? 1 : this.inventoryWarningQuantity;
+        this.warningCoefficient = this.warningCoefficient == null ? BigDecimal.ONE : this.warningCoefficient;
+    }
+
+}

+ 61 - 0
warehouse-admin-data/src/main/java/com/yr/warehouse/admin/warehouse/bo/WarehouseProductDemandAnalysisGeneratorBo.java

@@ -0,0 +1,61 @@
+package com.yr.warehouse.admin.warehouse.bo;
+
+import com.yr.bluecat.common.entity.bo.BaseBo;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+import java.io.Serial;
+import java.io.Serializable;
+import java.time.LocalDate;
+
+/**
+ * 仓库商品需求分析生成记录参数
+ */
+@EqualsAndHashCode(callSuper = true)
+@Data
+public class WarehouseProductDemandAnalysisGeneratorBo extends BaseBo implements Serializable {
+
+    @Serial
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * id
+     */
+    private Long id;
+
+    /**
+     * 运营商id
+     */
+    private Long operatorId;
+
+    /**
+     * 运营商链
+     */
+    private String operatorChain;
+
+    /**
+     * 运营商名称
+     */
+    private String operatorName;
+
+    /**
+     * 仓库id
+     */
+    private Long warehouseId;
+
+    /**
+     * 开始统计时间
+     */
+    private LocalDate beginStatisticsDate;
+
+    /**
+     * 结束统计时间
+     */
+    private LocalDate endStatisticsDate;
+
+    /**
+     * 备注
+     */
+    private String remark;
+
+}

+ 30 - 0
warehouse-admin-data/src/main/java/com/yr/warehouse/admin/warehouse/bo/WarehouseProductDemandAnalysisHistoryBo.java

@@ -0,0 +1,30 @@
+package com.yr.warehouse.admin.warehouse.bo;
+
+import com.yr.bluecat.common.entity.bo.BasePageBo;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+import java.io.Serial;
+import java.io.Serializable;
+
+/**
+ * 仓库商品需求分析生成记录列表查询参数
+ */
+@EqualsAndHashCode(callSuper = true)
+@Data
+public class WarehouseProductDemandAnalysisHistoryBo extends BasePageBo implements Serializable {
+
+    @Serial
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 运营商id
+     */
+    public Long operatorId;
+
+    /**
+     * 仓库id
+     */
+    private Long warehouseId;
+
+}

+ 49 - 0
warehouse-admin-data/src/main/java/com/yr/warehouse/admin/warehouse/bo/WarehouseProductDemandAnalysisHistoryPageBo.java

@@ -0,0 +1,49 @@
+package com.yr.warehouse.admin.warehouse.bo;
+
+import com.yr.bluecat.common.entity.bo.BasePageBo;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+import java.io.Serial;
+import java.io.Serializable;
+
+/**
+ * 仓库商品需求分析生成记录分页查询参数
+ */
+@EqualsAndHashCode(callSuper = true)
+@Data
+public class WarehouseProductDemandAnalysisHistoryPageBo extends BasePageBo implements Serializable {
+
+    @Serial
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 历史id
+     */
+    private Long historyId;
+
+    /**
+     * 商品名称
+     */
+    private String goodsName;
+
+    /**
+     * 状态: 安全: SAFETY 预警: WARNING 危险: DANGER
+     */
+    private String status;
+
+    /**
+     * 排序字段
+     * warehouseProductId 默认 warehouseProductId desc
+     * moq 起订量
+     * weeklySalesVolume 周销售量(个)
+     * weeklySalesVolumeUnits 周销售量(件)
+     * upShelfNum 上架数
+     */
+    private String sort;
+
+    /**
+     * 排序方式 asc: 升序 desc: 降序
+     */
+    private String sortType;
+}

+ 61 - 0
warehouse-admin-data/src/main/java/com/yr/warehouse/admin/warehouse/bo/WarehouseProductDemandAnalysisPageBo.java

@@ -0,0 +1,61 @@
+package com.yr.warehouse.admin.warehouse.bo;
+
+import com.yr.bluecat.common.entity.bo.BasePageBo;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+import java.io.Serial;
+import java.io.Serializable;
+import java.time.LocalDate;
+
+/**
+ * 仓库商品需求分析分页参数
+ */
+@EqualsAndHashCode(callSuper = true)
+@Data
+public class WarehouseProductDemandAnalysisPageBo extends BasePageBo implements Serializable {
+
+    @Serial
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 仓库id
+     */
+    private Long warehouseId;
+
+    /**
+     * 商品名称
+     */
+    private String goodsName;
+
+    /**
+     * 状态: 安全: SAFETY 预警: WARNING 危险: DANGER
+     */
+    private String status;
+
+    /**
+     * 开始统计时间
+     */
+    private LocalDate beginStatisticsDate;
+
+    /**
+     * 结束统计时间
+     */
+    private LocalDate endStatisticsDate;
+
+    /**
+     * 排序字段
+     * id 默认 id desc
+     * moq 起订量
+     * weeklySalesVolume 周销售量(个)
+     * weeklySalesVolumeUnits 周销售量(件)
+     * upShelfNum 上架数
+     *
+     */
+    private String sort;
+
+    /**
+     * 排序方式 asc: 升序 desc: 降序
+     */
+    private String sortType;
+}

+ 146 - 0
warehouse-admin-data/src/main/java/com/yr/warehouse/admin/warehouse/data/WarehouseInfo.java

@@ -0,0 +1,146 @@
+package com.yr.warehouse.admin.warehouse.data;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import java.io.Serializable;
+import java.time.LocalDateTime;
+import lombok.Getter;
+import lombok.Setter;
+
+/**
+ * <p>
+ * 仓库信息
+ * </p>
+ *
+ * @author 
+ * @since 2026-02-27 14:35:26
+ */
+@Getter
+@Setter
+@TableName("yr_warehouse_info")
+public class WarehouseInfo implements Serializable {
+
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 自增长id
+     */
+    @TableId(value = "id", type = IdType.AUTO)
+    private Long id;
+
+    /**
+     * 仓库编号
+     */
+    @TableField("code")
+    private String code;
+
+    /**
+     * 仓库名称
+     */
+    @TableField("name")
+    private String name;
+
+    /**
+     * 仓库负责人id
+     */
+    @TableField("managerId")
+    private Long managerId;
+
+    /**
+     * 仓库地址
+     */
+    @TableField("address")
+    private String address;
+
+    /**
+     * 总库存
+     */
+    @TableField("totalInventory")
+    private Long totalInventory;
+
+    /**
+     * 在途库存
+     */
+    @TableField("transportationInventory")
+    private Long transportationInventory;
+
+    /**
+     * 设备库存
+     */
+    @TableField("deviceInventory")
+    private Long deviceInventory;
+
+    /**
+     * 仓库库存
+     */
+    @TableField("inventory")
+    private Long inventory;
+
+    /**
+     * 出库锁
+     */
+    @TableField("deliveryLock")
+    private String deliveryLock;
+
+    /**
+     * 上次盘点时间
+     */
+    @TableField("lastStockTakingTime")
+    private LocalDateTime lastStockTakingTime;
+
+    /**
+     * 设备状态,默认启用: ENABLE 启用 DISABLED 禁用 DELETE 删除
+     */
+    @TableField("status")
+    private String status;
+
+    /**
+     * 运营商id
+     */
+    @TableField("operatorId")
+    private Long operatorId;
+
+    /**
+     * 运营商id链
+     */
+    @TableField("operatorChain")
+    private String operatorChain;
+
+    /**
+     * 创建用户名称
+     */
+    @TableField("createUserName")
+    private String createUserName;
+
+    /**
+     * 创建用户id
+     */
+    @TableField("createUserId")
+    private Long createUserId;
+
+    /**
+     * 创建时间
+     */
+    @TableField("createTime")
+    private LocalDateTime createTime;
+
+    /**
+     * 修改用户名称
+     */
+    @TableField("updateUserName")
+    private String updateUserName;
+
+    /**
+     * 修改用户id
+     */
+    @TableField("updateUserId")
+    private Long updateUserId;
+
+    /**
+     * 修改时间
+     */
+    @TableField("updateTime")
+    private LocalDateTime updateTime;
+}

+ 165 - 0
warehouse-admin-data/src/main/java/com/yr/warehouse/admin/warehouse/data/WarehouseProduct.java

@@ -0,0 +1,165 @@
+package com.yr.warehouse.admin.warehouse.data;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import java.io.Serializable;
+import java.math.BigDecimal;
+import java.time.LocalDateTime;
+import lombok.Getter;
+import lombok.Setter;
+
+/**
+ * <p>
+ * 仓库商品表
+ * </p>
+ *
+ * @author 
+ * @since 2026-02-27 10:48:39
+ */
+@Getter
+@Setter
+@TableName("yr_warehouse_product")
+public class WarehouseProduct implements Serializable {
+
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 自增长id
+     */
+    @TableId(value = "id", type = IdType.AUTO)
+    private Long id;
+
+    /**
+     * 仓库id
+     */
+    @TableField("warehouseInfoId")
+    private Long warehouseInfoId;
+
+    /**
+     * 商品id
+     */
+    @TableField("productSpecId")
+    private Integer productSpecId;
+
+    /**
+     * 安全库存数
+     */
+    @TableField("inventoryWarningQuantity")
+    private Long inventoryWarningQuantity;
+
+    /**
+     * 库存数
+     */
+    @TableField("inventory")
+    private Long inventory;
+
+    /**
+     * 库位
+     */
+    @TableField("warehouseLocation")
+    private String warehouseLocation;
+
+    /**
+     * 采购周期, 默认7天
+     */
+    @TableField("procurementCycle")
+    private Long procurementCycle;
+
+    /**
+     * 最小起订量
+     */
+    @TableField("moq")
+    private Long moq;
+
+    /**
+     * 预警系数
+     */
+    @TableField("warningCoefficient")
+    private BigDecimal warningCoefficient;
+
+    /**
+     * 拆箱优先级
+     */
+    @TableField("unboxingPriority")
+    private Integer unboxingPriority;
+
+    /**
+     * 入库时间
+     */
+    @TableField("countingTime")
+    private LocalDateTime countingTime;
+
+    /**
+     * 最近一次采购时间
+     */
+    @TableField("lastPurchaseTime")
+    private LocalDateTime lastPurchaseTime;
+
+    /**
+     * 预计售罄天数
+     */
+    @TableField("expectedSoldOutDays")
+    private Integer expectedSoldOutDays;
+
+    /**
+     * 商品在仓库状态: ONLINE 上架 OFFLINE 下架(可售卖,不可采购) FORBID_SALE 禁售(不可售卖,不可采购)
+     */
+    @TableField("status")
+    private String status;
+
+    /**
+     * 商品售卖状态 NORMAL 正常 STOP 停止
+     */
+    @TableField("salesStatus")
+    private String salesStatus;
+
+    /**
+     * 创建用户名称
+     */
+    @TableField("createUserName")
+    private String createUserName;
+
+    /**
+     * 创建用户id
+     */
+    @TableField("createUserId")
+    private Long createUserId;
+
+    /**
+     * 创建时间
+     */
+    @TableField("createTime")
+    private LocalDateTime createTime;
+
+    /**
+     * 修改用户名称
+     */
+    @TableField("updateUserName")
+    private String updateUserName;
+
+    /**
+     * 修改用户id
+     */
+    @TableField("updateUserId")
+    private Long updateUserId;
+
+    /**
+     * 修改时间
+     */
+    @TableField("updateTime")
+    private LocalDateTime updateTime;
+
+    /**
+     * 冻结库存数
+     */
+    @TableField("frozenInventory")
+    private Long frozenInventory;
+
+    /**
+     * 盘点前库存数
+     */
+    @TableField("takingBeforeInventory")
+    private Long takingBeforeInventory;
+}

+ 214 - 0
warehouse-admin-data/src/main/java/com/yr/warehouse/admin/warehouse/data/WarehouseProductDemandAnalysisDetail.java

@@ -0,0 +1,214 @@
+package com.yr.warehouse.admin.warehouse.data;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import java.io.Serializable;
+import java.math.BigDecimal;
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+import lombok.Getter;
+import lombok.Setter;
+
+/**
+ * <p>
+ * 仓库商品需求分析详情表
+ * </p>
+ *
+ * @author 
+ * @since 2026-02-27 11:20:46
+ */
+@Getter
+@Setter
+@TableName("yr_warehouse_product_demand_analysis_detail")
+public class WarehouseProductDemandAnalysisDetail implements Serializable {
+
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 自增长id
+     */
+    @TableId(value = "id", type = IdType.AUTO)
+    private Long id;
+
+    /**
+     * 仓库商品需求分析id
+     */
+    @TableField("infoId")
+    private Long infoId;
+
+    /**
+     * 仓库商品id
+     */
+    @TableField("warehouseProductId")
+    private Long warehouseProductId;
+
+    /**
+     * 商品编码
+     */
+    @TableField("goodsCode")
+    private String goodsCode;
+
+    /**
+     * 商品名称
+     */
+    @TableField("goodsName")
+    private String goodsName;
+
+    /**
+     * 拆箱优先级/规格
+     */
+    @TableField("unboxingPriority")
+    private Integer unboxingPriority;
+
+    /**
+     * 保质期(天)
+     */
+    @TableField("shelfLife")
+    private Integer shelfLife;
+
+    /**
+     * 采购周期, 默认7天
+     */
+    @TableField("procurementCycle")
+    private Long procurementCycle;
+
+    /**
+     * 起订量
+     */
+    @TableField("moq")
+    private Long moq;
+
+    /**
+     * 周销售量
+     */
+    @TableField("weeklySalesVolume")
+    private Long weeklySalesVolume;
+
+    /**
+     * 周销售量(件)
+     */
+    @TableField("weeklySalesVolumeUnits")
+    private BigDecimal weeklySalesVolumeUnits;
+
+    /**
+     * 安全库存数
+     */
+    @TableField("inventoryWarningQuantity")
+    private Long inventoryWarningQuantity;
+
+    /**
+     * 预警系数
+     */
+    @TableField("warningCoefficient")
+    private BigDecimal warningCoefficient;
+
+    /**
+     * 预警值
+     */
+    @TableField("warningQuantity")
+    private Long warningQuantity;
+
+    /**
+     * 上机库存
+     */
+    @TableField("machineInventory")
+    private Long machineInventory;
+
+    /**
+     * 分仓需求/件
+     */
+    @TableField("subWarehouseRequirements")
+    private BigDecimal subWarehouseRequirements;
+
+    /**
+     * 需求量
+     */
+    @TableField("warehouseRequirements")
+    private BigDecimal warehouseRequirements;
+
+    /**
+     * 结余库存/件
+     */
+    @TableField("surplusInventory")
+    private BigDecimal surplusInventory;
+
+    /**
+     * 状态: SAFETY 安全 | WARNING 预警 | DANGER 危险
+     */
+    @TableField("status")
+    private String status;
+
+    /**
+     * 预计消耗天数
+     */
+    @TableField("expectedConsumptionDays")
+    private BigDecimal expectedConsumptionDays;
+
+    /**
+     * 预计销售时间
+     */
+    @TableField("expectedSaleTime")
+    private LocalDate expectedSaleTime;
+
+    /**
+     * 期望到货时间
+     */
+    @TableField("expectedArrivalTime")
+    private LocalDate expectedArrivalTime;
+
+    /**
+     * 售卖天数
+     */
+    @TableField("saleDays")
+    private Long saleDays;
+
+    /**
+     * 上架数量
+     */
+    @TableField("upShelfNum")
+    private Long upShelfNum;
+
+    /**
+     * 采购需求
+     */
+    @TableField("procurementDemand")
+    private BigDecimal procurementDemand;
+
+    /**
+     * 创建用户名称
+     */
+    @TableField("createUserName")
+    private String createUserName;
+
+    /**
+     * 创建用户id
+     */
+    @TableField("createUserId")
+    private Long createUserId;
+
+    /**
+     * 创建时间
+     */
+    @TableField("createTime")
+    private LocalDateTime createTime;
+
+    /**
+     * 修改用户名称
+     */
+    @TableField("modifyUserName")
+    private String modifyUserName;
+
+    /**
+     * 修改用户id
+     */
+    @TableField("modifyUserId")
+    private Long modifyUserId;
+
+    /**
+     * 修改时间
+     */
+    @TableField("modifyTime")
+    private LocalDateTime modifyTime;
+}

+ 117 - 0
warehouse-admin-data/src/main/java/com/yr/warehouse/admin/warehouse/data/WarehouseProductDemandAnalysisInfo.java

@@ -0,0 +1,117 @@
+package com.yr.warehouse.admin.warehouse.data;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import java.io.Serializable;
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+import lombok.Getter;
+import lombok.Setter;
+
+/**
+ * <p>
+ * 仓库商品需求分析主表
+ * </p>
+ *
+ * @author 
+ * @since 2026-02-27 11:20:46
+ */
+@Getter
+@Setter
+@TableName("yr_warehouse_product_demand_analysis_info")
+public class WarehouseProductDemandAnalysisInfo implements Serializable {
+
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 自增长id
+     */
+    @TableId(value = "id", type = IdType.AUTO)
+    private Long id;
+
+    /**
+     * 运营商id
+     */
+    @TableField("operatorId")
+    private Long operatorId;
+
+    /**
+     * 运营商名称
+     */
+    @TableField("operatorName")
+    private String operatorName;
+
+    /**
+     * 仓库id
+     */
+    @TableField("warehouseId")
+    private Long warehouseId;
+
+    /**
+     * 仓库名称
+     */
+    @TableField("warehouseName")
+    private String warehouseName;
+
+    /**
+     * 开始统计时间
+     */
+    @TableField("beginStatisticsDate")
+    private LocalDate beginStatisticsDate;
+
+    /**
+     * 结束统计时间
+     */
+    @TableField("endStatisticsDate")
+    private LocalDate endStatisticsDate;
+
+    /**
+     * 备注
+     */
+    @TableField("remark")
+    private String remark;
+
+    /**
+     * 创建用户名称
+     */
+    @TableField("createUserName")
+    private String createUserName;
+
+    /**
+     * 创建用户id
+     */
+    @TableField("createUserId")
+    private Long createUserId;
+
+    /**
+     * 创建时间
+     */
+    @TableField("createTime")
+    private LocalDateTime createTime;
+
+    /**
+     * 修改用户名称
+     */
+    @TableField("modifyUserName")
+    private String modifyUserName;
+
+    /**
+     * 修改用户id
+     */
+    @TableField("modifyUserId")
+    private Long modifyUserId;
+
+    /**
+     * 修改时间
+     */
+    @TableField("modifyTime")
+    private LocalDateTime modifyTime;
+
+    /**
+     * 是否删除: NORMAL 正常 | DELETE 删除
+     */
+    @TableField("isDelete")
+    private String isDelete;
+}

+ 24 - 0
warehouse-admin-data/src/main/java/com/yr/warehouse/admin/warehouse/mapper/WarehouseInfoMapper.java

@@ -0,0 +1,24 @@
+package com.yr.warehouse.admin.warehouse.mapper;
+
+import com.yr.warehouse.admin.warehouse.data.WarehouseInfo;
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import org.apache.ibatis.annotations.Param;
+
+/**
+ * <p>
+ * 仓库信息 Mapper 接口
+ * </p>
+ *
+ * @author 
+ * @since 2026-02-27 14:35:26
+ */
+public interface WarehouseInfoMapper extends BaseMapper<WarehouseInfo> {
+
+    /**
+     * 根据id查询仓库信息
+     *
+     * @param id 仓库id
+     * @return 仓库信息
+     */
+    WarehouseInfo getById(@Param("id") Long id);
+}

+ 39 - 0
warehouse-admin-data/src/main/java/com/yr/warehouse/admin/warehouse/mapper/WarehouseProductDemandAnalysisDetailMapper.java

@@ -0,0 +1,39 @@
+package com.yr.warehouse.admin.warehouse.mapper;
+
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.yr.warehouse.admin.warehouse.bo.WarehouseProductDemandAnalysisGeneratorBo;
+import com.yr.warehouse.admin.warehouse.bo.WarehouseProductDemandAnalysisHistoryPageBo;
+import com.yr.warehouse.admin.warehouse.data.WarehouseProductDemandAnalysisDetail;
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.yr.warehouse.admin.warehouse.vo.WarehouseProductDemandAnalysisVo;
+import org.apache.ibatis.annotations.Param;
+
+import java.util.List;
+
+/**
+ * <p>
+ * 仓库商品需求分析详情表 Mapper 接口
+ * </p>
+ *
+ * @author 
+ * @since 2026-02-27 11:20:46
+ */
+public interface WarehouseProductDemandAnalysisDetailMapper extends BaseMapper<WarehouseProductDemandAnalysisDetail> {
+
+    /**
+     * 批量创建
+     *
+     * @param all 详情列表
+     * @param bo 创建参数
+     */
+    void create(@Param("all") List<WarehouseProductDemandAnalysisVo> all, @Param("bo") WarehouseProductDemandAnalysisGeneratorBo bo);
+
+    /**
+     * 仓库商品需求分析历史分页
+     *
+     * @param page 分页参数
+     * @param bo 仓库商品需求分析历史参数
+     * @return 仓库商品需求分析历史结果
+     */
+    Page<WarehouseProductDemandAnalysisVo> historyPage(@Param("page") Page<WarehouseProductDemandAnalysisVo> page, @Param("bo") WarehouseProductDemandAnalysisHistoryPageBo bo);
+}

+ 36 - 0
warehouse-admin-data/src/main/java/com/yr/warehouse/admin/warehouse/mapper/WarehouseProductDemandAnalysisInfoMapper.java

@@ -0,0 +1,36 @@
+package com.yr.warehouse.admin.warehouse.mapper;
+
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.yr.warehouse.admin.warehouse.bo.WarehouseProductDemandAnalysisGeneratorBo;
+import com.yr.warehouse.admin.warehouse.bo.WarehouseProductDemandAnalysisHistoryBo;
+import com.yr.warehouse.admin.warehouse.data.WarehouseProductDemandAnalysisInfo;
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.yr.warehouse.admin.warehouse.vo.WarehouseProductDemandAnalysisHistoryVo;
+import org.apache.ibatis.annotations.Param;
+
+/**
+ * <p>
+ * 仓库商品需求分析主表 Mapper 接口
+ * </p>
+ *
+ * @author 
+ * @since 2026-02-27 11:20:46
+ */
+public interface WarehouseProductDemandAnalysisInfoMapper extends BaseMapper<WarehouseProductDemandAnalysisInfo> {
+
+    /**
+     * 创建仓库商品需求分析
+     *
+     * @param bo 创建仓库商品需求分析参数
+     */
+    void create(@Param("bo") WarehouseProductDemandAnalysisGeneratorBo bo);
+
+    /**
+     * 查询仓库商品需求分析历史
+     *
+     * @param page 分页参数
+     * @param bo   查询仓库商品需求分析历史参数
+     * @return 仓库商品需求分析历史列表
+     */
+    Page<WarehouseProductDemandAnalysisHistoryVo> history(@Param("page") Page<WarehouseProductDemandAnalysisHistoryVo> page, @Param("bo") WarehouseProductDemandAnalysisHistoryBo bo);
+}

+ 50 - 0
warehouse-admin-data/src/main/java/com/yr/warehouse/admin/warehouse/mapper/WarehouseProductDemandAnalysisMapper.java

@@ -0,0 +1,50 @@
+package com.yr.warehouse.admin.warehouse.mapper;
+
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.yr.bluecat.common.entity.bo.BaseBo;
+import com.yr.warehouse.admin.warehouse.bo.WarehouseProductDemandAnalysisEditorBo;
+import com.yr.warehouse.admin.warehouse.bo.WarehouseProductDemandAnalysisPageBo;
+import com.yr.warehouse.admin.warehouse.vo.WarehouseProductDemandAnalysisVo;
+import com.yr.warehouse.admin.warehouse.vo.WarehouseRequirementsVo;
+import org.apache.ibatis.annotations.Mapper;
+import org.apache.ibatis.annotations.Param;
+
+import java.time.LocalDate;
+import java.util.List;
+
+/**
+ * 仓库商品需求分析 Mapper 接口
+ */
+@Mapper
+public interface WarehouseProductDemandAnalysisMapper {
+    /**
+     * 分页查询仓库商品需求分析
+     *
+     * @param page 分页参数
+     * @param bo   查询参数
+     * @return 分页结果
+     */
+    Page<WarehouseProductDemandAnalysisVo> page(@Param("page") Page<WarehouseProductDemandAnalysisVo> page, @Param("bo") WarehouseProductDemandAnalysisPageBo bo);
+
+    /**
+     * 查询仓库商品需求分析
+     *
+     * @return 结果
+     */
+    List<WarehouseRequirementsVo> searchSubWarehouseRequirements(@Param("goodsIds") List<Integer> goodsIds, @Param("warehouseId") Long warehouseId, @Param("beginStatisticsDate") LocalDate beginStatisticsDate, @Param("endStatisticsDate") LocalDate endStatisticsDate);
+
+    /**
+     * 仓库商品需求分析编辑
+     *
+     * @param bo 编辑参数
+     */
+    void editor(@Param("bo") WarehouseProductDemandAnalysisEditorBo bo);
+
+    /**
+     * 批量仓库商品需求分析编辑
+     *
+     * @param batchBos 编辑参数
+     * @param bo       基础参数
+     */
+    void batchEditor(@Param("batchBos") List<WarehouseProductDemandAnalysisEditorBo> batchBos, @Param("bo") BaseBo bo);
+}

+ 27 - 0
warehouse-admin-data/src/main/java/com/yr/warehouse/admin/warehouse/mapper/WarehouseProductMapper.java

@@ -0,0 +1,27 @@
+package com.yr.warehouse.admin.warehouse.mapper;
+
+import com.yr.warehouse.admin.warehouse.data.WarehouseProduct;
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.yr.warehouse.admin.warehouse.vo.WarehouseProductVo;
+import org.apache.ibatis.annotations.Param;
+
+import java.util.List;
+
+/**
+ * <p>
+ * 仓库商品表 Mapper 接口
+ * </p>
+ *
+ * @author 
+ * @since 2026-02-27 10:48:39
+ */
+public interface WarehouseProductMapper extends BaseMapper<WarehouseProduct> {
+
+    /**
+     * 根据商品编号查询仓库商品
+     * @param goodsCodes 商品编号
+     * @param warehouseId 仓库id
+     * @return 仓库商品
+     */
+    List<WarehouseProductVo> searchWarehouseProductByGoodsCodes(@Param("goodsCodes") List<String> goodsCodes, @Param("warehouseId") Long warehouseId);
+}

+ 96 - 0
warehouse-admin-data/src/main/java/com/yr/warehouse/admin/warehouse/vo/WarehouseProductDemandAnalysisHistoryVo.java

@@ -0,0 +1,96 @@
+package com.yr.warehouse.admin.warehouse.vo;
+
+import lombok.Data;
+
+import java.io.Serial;
+import java.io.Serializable;
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+
+/**
+ * 仓库商品需求分析生成记录列表查询参数
+ */
+@Data
+public class WarehouseProductDemandAnalysisHistoryVo implements Serializable {
+
+    @Serial
+    private static final long serialVersionUID = 1L;
+
+    private Long id;
+
+    /**
+     * 运营商id
+     */
+    private Long operatorId;
+
+    /**
+     * 运营商链
+     */
+    private String operatorChain;
+
+    /**
+     * 运营商名称
+     */
+    private String operatorName;
+
+    /**
+     * 仓库id
+     */
+    private Long warehouseId;
+
+    /**
+     * 仓库名称
+     */
+    private String warehouseName;
+
+    /**
+     * 开始统计时间
+     */
+    private LocalDate beginStatisticsDate;
+
+    /**
+     * 结束统计时间
+     */
+    private LocalDate endStatisticsDate;
+
+    /**
+     * 备注
+     */
+    private String remark;
+
+    /**
+     * 创建用户名称
+     */
+    private String createUserName;
+
+    /**
+     * 创建用户id
+     */
+    private Long createUserId;
+
+    /**
+     * 创建时间
+     */
+    private LocalDateTime createTime;
+
+    /**
+     * 修改用户名称
+     */
+    private String modifyUserName;
+
+    /**
+     * 修改用户id
+     */
+    private Long modifyUserId;
+
+    /**
+     * 修改时间
+     */
+    private LocalDateTime modifyTime;
+
+    /**
+     * 是否删除: NORMAL 正常 | DELETE 删除
+     */
+    private String isDelete;
+
+}

+ 233 - 0
warehouse-admin-data/src/main/java/com/yr/warehouse/admin/warehouse/vo/WarehouseProductDemandAnalysisVo.java

@@ -0,0 +1,233 @@
+package com.yr.warehouse.admin.warehouse.vo;
+
+import lombok.Data;
+
+import java.io.Serial;
+import java.io.Serializable;
+import java.math.BigDecimal;
+import java.math.RoundingMode;
+import java.time.LocalDate;
+
+/**
+ * 仓库商品需求分析视图参数
+ */
+@Data
+public class WarehouseProductDemandAnalysisVo implements Serializable {
+
+    @Serial
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 仓库商品id
+     */
+    private Long id;
+
+    /**
+     * 商品id
+     */
+    private Integer goodsId;
+
+    /**
+     * 商品编号
+     */
+    private String goodsCode;
+
+    /**
+     * 商品名称
+     */
+    private String goodsName;
+
+    /**
+     * 规格
+     */
+    private Integer unboxingPriority;
+
+    /**
+     * 保质期(天)
+     */
+    private Integer shelfLife;
+
+    /**
+     * 采购周期
+     * 人工填写 默认 7 天
+     */
+    private Long procurementCycle;
+
+    /**
+     * 起订量
+     * 人工填写 默认 0
+     */
+    private Long moq;
+
+    /**
+     * 周销售量(个)
+     */
+    private Long weeklySalesVolume;
+
+    /**
+     * 周销售量(件)
+     * 周销售量(个) / 规格, 保留两位小数
+     */
+    private BigDecimal weeklySalesVolumeUnits;
+
+    /**
+     * 安全库存数
+     * 人工填写 默认1
+     */
+    private Long inventoryWarningQuantity;
+
+    /**
+     * 预警系数
+     * 人工填写 默认1.0
+     */
+    private BigDecimal warningCoefficient;
+
+    /**
+     * 预警值
+     * 安全库存数 * 预警系数 整数 向上取整
+     */
+    private Long warningQuantity;
+
+    /**
+     * 上机库存
+     * 仓库绑定的所有设备在统计日期内该商品的所有数量 实时设备库存
+     */
+    private Long machineInventory;
+
+    /**
+     * 分仓需求
+     * 分仓批发数量(件) 出库管理的批发类型
+     */
+    private BigDecimal subWarehouseRequirements;
+
+    /**
+     * 需求量
+     * 周销售量(件) / 7 * (采购周期 + 7) * 预警系数 + 分仓需求 / 7 * (采购周期 + 7)
+     * 保留两位小数
+     */
+    private BigDecimal warehouseRequirements;
+
+    /**
+     * 结余库存
+     * 该商品在仓库里的库存数(件)
+     */
+    private BigDecimal surplusInventory;
+
+    /**
+     * 状态
+     * 安全(结余库存 >= 安全库存 && 结余库存 >= 预警值) SAFETY
+     * 预警(结余库存 >= 安全库存 && 预警值 > 结余库存) WARNING
+     * 危险(安全库存 > 结余库存 && 预警值 > 结余库存) DANGER
+     */
+    private String status;
+
+    /**
+     * 预计消耗天数
+     * (结余库存 + 上机库存) / 周销量(件) * 7 四舍五入取整
+     * 例如: (200 + 100) / 20 * 7 = 105
+     */
+    private BigDecimal expectedConsumptionDays;
+
+    /**
+     * 预计销售时间
+     * (结余库存 + 需求量) / 周销量(件) * 7 当前日期加上计算天数
+     * 例如: (200 + 300) / 20 * 7 = 175
+     * 2026-02-26 + 175 = 2026-08-20
+     */
+    private LocalDate expectedSaleTime;
+
+    /**
+     * 期望到货时间
+     * 当前日期 + 预计消耗天数
+     * 例如: 2026-02-26 + 105 = 2026-06-11
+     */
+    private LocalDate expectedArrivalTime;
+
+    /**
+     * 售卖天数
+     * (结余库存 - 分仓需求) / 周销量(件) * 7 四舍五入取整
+     */
+    private Long saleDays;
+
+    /**
+     * 上架数
+     * 该商品在设备里的上架设备数, 单台设备算1个上架数
+     * 只查询已上机的设备货道存在该商品的设备数
+     */
+    private Long upShelfNum;
+
+    /**
+     * 采购需求
+     * 需求量 (保留两位小数的原数据) - 结余库存
+     */
+    private BigDecimal procurementDemand;
+
+    /**
+     * 构建数据, 需先写入分仓需求数, 否则计算将存在问题
+     */
+    public void build() {
+        // 单位
+        BigDecimal uniting = BigDecimal.ONE;
+        // 如果拆箱优先级小于等于0, 默认为1
+        if (unboxingPriority > 0) {
+            uniting = BigDecimal.valueOf(unboxingPriority);
+        }
+
+        // 周销量件 = 周销量(个) / 规格, 保留两位小数
+        weeklySalesVolumeUnits = new BigDecimal(weeklySalesVolume).divide(uniting, 2, RoundingMode.HALF_UP);
+
+        BigDecimal seven = BigDecimal.valueOf(7);
+
+        // 销售需求量 = 周销售量(件) / 7 * (采购周期 + 7) * 预警系数
+        BigDecimal salesRequirements = weeklySalesVolumeUnits.divide(seven, 2, RoundingMode.HALF_UP)
+                .multiply(BigDecimal.valueOf(procurementCycle).add(seven))
+                .multiply(warningCoefficient);
+
+        // 分仓需求量 = 分仓需求 / 7 * (采购周期 + 7) (保留两位小数)
+        BigDecimal realSubWarehouseRequirements = BigDecimal.ZERO;
+        if (null != subWarehouseRequirements && subWarehouseRequirements.compareTo(BigDecimal.ZERO) > 0) {
+            realSubWarehouseRequirements = subWarehouseRequirements.divide(seven, 2, RoundingMode.HALF_UP)
+                    .multiply(BigDecimal.valueOf(procurementCycle).add(seven));
+        }
+
+        // 需求量 = 销售需求量 + 分仓需求量
+        warehouseRequirements = salesRequirements.add(realSubWarehouseRequirements);
+
+        if (0 == weeklySalesVolumeUnits.compareTo(BigDecimal.ZERO)) {
+            expectedConsumptionDays = BigDecimal.ZERO;
+            expectedSaleTime = LocalDate.now();
+            expectedArrivalTime = LocalDate.now();
+            saleDays = 0L;
+        } else {
+            // 预计消耗天数 = (结余库存 + 上机库存) / 周销量(件) * 7 四舍五入取整
+            if (0 > surplusInventory.add(BigDecimal.valueOf(machineInventory)).compareTo(BigDecimal.ZERO)) {
+                expectedConsumptionDays = BigDecimal.ZERO;
+            } else {
+                BigDecimal oldVal = surplusInventory.add(BigDecimal.valueOf(machineInventory));
+                expectedConsumptionDays = oldVal.divide(weeklySalesVolumeUnits, 2, RoundingMode.HALF_UP).multiply(seven).setScale(0, RoundingMode.HALF_UP);
+            }
+            // 预计销售时间 = (结余库存 + 需求量) / 周销量(件) * 7 四舍五入取整
+            BigDecimal expectedSaleDays = BigDecimal.ZERO;
+            if (0 > surplusInventory.add(warehouseRequirements).compareTo(BigDecimal.ZERO)) {
+                BigDecimal oldVal = surplusInventory.add(warehouseRequirements);
+                expectedSaleDays = oldVal.divide(weeklySalesVolumeUnits, 2, RoundingMode.HALF_UP).multiply(seven).setScale(0, RoundingMode.HALF_UP);
+            }
+            expectedSaleTime = LocalDate.now().plusDays(expectedSaleDays.longValue());
+
+            // 期望到货时间
+            expectedArrivalTime = LocalDate.now().plusDays(expectedConsumptionDays.longValue());
+
+            // 售卖天数 = (结余库存 - 分仓需求) / 周销量(件) * 7 四舍五入取整
+            if (0 == surplusInventory.subtract(subWarehouseRequirements).compareTo(BigDecimal.ZERO)) {
+                saleDays = 0L;
+            } else {
+                BigDecimal oldVal = surplusInventory.subtract(subWarehouseRequirements);
+                saleDays = oldVal.divide(weeklySalesVolumeUnits, 2, RoundingMode.HALF_UP).multiply(seven).setScale(0, RoundingMode.HALF_UP).longValue();
+            }
+        }
+
+        // 采购需求 = 需求量 (保留两位小数的原数据) - 结余库存
+        procurementDemand = warehouseRequirements.subtract(surplusInventory);
+    }
+
+}

+ 145 - 0
warehouse-admin-data/src/main/java/com/yr/warehouse/admin/warehouse/vo/WarehouseProductVo.java

@@ -0,0 +1,145 @@
+package com.yr.warehouse.admin.warehouse.vo;
+
+import lombok.Data;
+
+import java.io.Serial;
+import java.io.Serializable;
+import java.math.BigDecimal;
+import java.time.LocalDateTime;
+
+/**
+ * 仓库商品视图
+ */
+@Data
+public class WarehouseProductVo implements Serializable {
+
+    @Serial
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 自增长id
+     */
+    private Long id;
+
+    /**
+     * 仓库id
+     */
+    private Long warehouseInfoId;
+
+    /**
+     * 商品id
+     */
+    private Integer productSpecId;
+
+    /**
+     * 商品编号
+     */
+    private String goodsCode;
+
+    /**
+     * 商品名称
+     */
+    private String goodsName;
+
+    /**
+     * 安全库存数
+     */
+    private Long inventoryWarningQuantity;
+
+    /**
+     * 库存数
+     */
+    private Long inventory;
+
+    /**
+     * 库位
+     */
+    private String warehouseLocation;
+
+    /**
+     * 采购周期, 默认7天
+     */
+    private Long procurementCycle;
+
+    /**
+     * 最小起订量
+     */
+    private Long moq;
+
+    /**
+     * 预警系数
+     */
+    private BigDecimal warningCoefficient;
+
+    /**
+     * 拆箱优先级
+     */
+    private Integer unboxingPriority;
+
+    /**
+     * 入库时间
+     */
+    private LocalDateTime countingTime;
+
+    /**
+     * 最近一次采购时间
+     */
+    private LocalDateTime lastPurchaseTime;
+
+    /**
+     * 预计售罄天数
+     */
+    private Integer expectedSoldOutDays;
+
+    /**
+     * 商品在仓库状态: ONLINE 上架 OFFLINE 下架(可售卖,不可采购) FORBID_SALE 禁售(不可售卖,不可采购)
+     */
+    private String status;
+
+    /**
+     * 商品售卖状态 NORMAL 正常 STOP 停止
+     */
+    private String salesStatus;
+
+    /**
+     * 创建用户名称
+     */
+    private String createUserName;
+
+    /**
+     * 创建用户id
+     */
+    private Long createUserId;
+
+    /**
+     * 创建时间
+     */
+    private LocalDateTime createTime;
+
+    /**
+     * 修改用户名称
+     */
+    private String updateUserName;
+
+    /**
+     * 修改用户id
+     */
+    private Long updateUserId;
+
+    /**
+     * 修改时间
+     */
+    private LocalDateTime updateTime;
+
+    /**
+     * 冻结库存数
+     */
+    private Long frozenInventory;
+
+    /**
+     * 盘点前库存数
+     */
+    private Long takingBeforeInventory;
+
+
+}

+ 27 - 0
warehouse-admin-data/src/main/java/com/yr/warehouse/admin/warehouse/vo/WarehouseRequirementsVo.java

@@ -0,0 +1,27 @@
+package com.yr.warehouse.admin.warehouse.vo;
+
+import lombok.Data;
+
+import java.io.Serial;
+import java.io.Serializable;
+
+/**
+ * 仓库商品需求结果
+ */
+@Data
+public class WarehouseRequirementsVo implements Serializable {
+
+    @Serial
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 商品id
+     */
+    private Integer goodsId;
+
+    /**
+     * 出库数量(个)
+     */
+    private Long totalOutbound;
+
+}

+ 42 - 0
warehouse-admin-data/src/main/resources/mapper/warehouse/WarehouseInfoMapper.xml

@@ -0,0 +1,42 @@
+<?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.yr.warehouse.admin.warehouse.mapper.WarehouseInfoMapper">
+
+    <!-- 通用查询映射结果 -->
+    <resultMap id="BaseResultMap" type="com.yr.warehouse.admin.warehouse.data.WarehouseInfo">
+        <id column="id" property="id" />
+        <result column="code" property="code" />
+        <result column="name" property="name" />
+        <result column="managerId" property="managerId" />
+        <result column="address" property="address" />
+        <result column="totalInventory" property="totalInventory" />
+        <result column="transportationInventory" property="transportationInventory" />
+        <result column="deviceInventory" property="deviceInventory" />
+        <result column="inventory" property="inventory" />
+        <result column="deliveryLock" property="deliveryLock" />
+        <result column="lastStockTakingTime" property="lastStockTakingTime" />
+        <result column="status" property="status" />
+        <result column="operatorId" property="operatorId" />
+        <result column="operatorChain" property="operatorChain" />
+        <result column="createUserName" property="createUserName" />
+        <result column="createUserId" property="createUserId" />
+        <result column="createTime" property="createTime" />
+        <result column="updateUserName" property="updateUserName" />
+        <result column="updateUserId" property="updateUserId" />
+        <result column="updateTime" property="updateTime" />
+    </resultMap>
+
+    <!-- 通用查询结果列 -->
+    <sql id="Base_Column_List">
+        id, code, name, managerId, address, totalInventory, transportationInventory, deviceInventory, inventory, deliveryLock, lastStockTakingTime, status, operatorId, operatorChain, createUserName, createUserId, createTime, updateUserName, updateUserId, updateTime
+    </sql>
+    <select id="getById" resultType="com.yr.warehouse.admin.warehouse.data.WarehouseInfo"
+            parameterType="java.lang.Long">
+        select
+        <include refid="Base_Column_List"/>
+        from yr_warehouse_info
+        where id = #{id}
+        and status != 'DELETE'
+    </select>
+
+</mapper>

+ 123 - 0
warehouse-admin-data/src/main/resources/mapper/warehouse/WarehouseProductDemandAnalysisDetailMapper.xml

@@ -0,0 +1,123 @@
+<?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.yr.warehouse.admin.warehouse.mapper.WarehouseProductDemandAnalysisDetailMapper">
+
+    <!-- 通用查询映射结果 -->
+    <resultMap id="BaseResultMap" type="com.yr.warehouse.admin.warehouse.data.WarehouseProductDemandAnalysisDetail">
+        <id column="id" property="id"/>
+        <result column="infoId" property="infoId"/>
+        <result column="warehouseProductId" property="warehouseProductId"/>
+        <result column="goodsCode" property="goodsCode"/>
+        <result column="goodsName" property="goodsName"/>
+        <result column="unboxingPriority" property="unboxingPriority"/>
+        <result column="shelfLife" property="shelfLife"/>
+        <result column="procurementCycle" property="procurementCycle"/>
+        <result column="moq" property="moq"/>
+        <result column="weeklySalesVolume" property="weeklySalesVolume"/>
+        <result column="weeklySalesVolumeUnits" property="weeklySalesVolumeUnits"/>
+        <result column="inventoryWarningQuantity" property="inventoryWarningQuantity"/>
+        <result column="warningCoefficient" property="warningCoefficient"/>
+        <result column="warningQuantity" property="warningQuantity"/>
+        <result column="machineInventory" property="machineInventory"/>
+        <result column="subWarehouseRequirements" property="subWarehouseRequirements"/>
+        <result column="warehouseRequirements" property="warehouseRequirements"/>
+        <result column="surplusInventory" property="surplusInventory"/>
+        <result column="status" property="status"/>
+        <result column="expectedConsumptionDays" property="expectedConsumptionDays"/>
+        <result column="expectedSaleTime" property="expectedSaleTime"/>
+        <result column="expectedArrivalTime" property="expectedArrivalTime"/>
+        <result column="saleDays" property="saleDays"/>
+        <result column="upShelfNum" property="upShelfNum"/>
+        <result column="procurementDemand" property="procurementDemand"/>
+        <result column="createUserName" property="createUserName"/>
+        <result column="createUserId" property="createUserId"/>
+        <result column="createTime" property="createTime"/>
+        <result column="modifyUserName" property="modifyUserName"/>
+        <result column="modifyUserId" property="modifyUserId"/>
+        <result column="modifyTime" property="modifyTime"/>
+    </resultMap>
+
+    <!-- 通用查询结果列 -->
+    <sql id="Base_Column_List">
+        id, infoId, warehouseProductId, goodsCode, goodsName, unboxingPriority, shelfLife, procurementCycle, moq, weeklySalesVolume, weeklySalesVolumeUnits, inventoryWarningQuantity, warningCoefficient, warningQuantity, machineInventory, subWarehouseRequirements, warehouseRequirements, surplusInventory, status, expectedConsumptionDays, expectedSaleTime, expectedArrivalTime, saleDays, upShelfNum, procurementDemand, createUserName, createUserId, createTime, modifyUserName, modifyUserId, modifyTime
+    </sql>
+    <insert id="create">
+        insert into yr_warehouse_product_demand_analysis_detail
+        (infoId, warehouseProductId, goodsId, goodsCode, goodsName, unboxingPriority, shelfLife, procurementCycle, moq,
+        weeklySalesVolume, weeklySalesVolumeUnits, inventoryWarningQuantity, warningCoefficient, warningQuantity,
+        machineInventory, subWarehouseRequirements, warehouseRequirements, surplusInventory, status,
+        expectedConsumptionDays, expectedSaleTime, expectedArrivalTime, saleDays, upShelfNum, procurementDemand,
+        createUserName, createUserId)
+        VALUES
+        <foreach collection="all" item="item" separator=",">
+            (#{bo.id}, #{item.id}, #{item.goodsId}, #{item.goodsCode}, #{item.goodsName}, #{item.unboxingPriority},
+            #{item.shelfLife}, #{item.procurementCycle}, #{item.moq}, #{item.weeklySalesVolume},
+            #{item.weeklySalesVolumeUnits},
+            #{item.inventoryWarningQuantity}, #{item.warningCoefficient}, #{item.warningQuantity},
+            #{item.machineInventory}, #{item.subWarehouseRequirements},
+            #{item.warehouseRequirements},
+            #{item.surplusInventory},
+            #{item.status},
+            #{item.expectedConsumptionDays},
+            #{item.expectedSaleTime},
+            #{item.expectedArrivalTime},
+            #{item.saleDays},
+            #{item.upShelfNum},
+            #{item.procurementDemand},
+            #{bo.username}, #{bo.uid}
+            )
+        </foreach>
+    </insert>
+    <select id="historyPage" resultType="com.yr.warehouse.admin.warehouse.vo.WarehouseProductDemandAnalysisVo">
+        select wpdad.warehouseProductId as id,
+        wpdad.goodsId as goodsId,
+        wpdad.goodsCode as goodsCode,
+        wpdad.goodsName as goodsName,
+        wpdad.unboxingPriority as unboxingPriority,
+        wpdad.shelfLife as shelfLife,
+        wpdad.procurementCycle as procurementCycle,
+        wpdad.moq as moq,
+        wpdad.weeklySalesVolume as weeklySalesVolume,
+        wpdad.weeklySalesVolumeUnits as weeklySalesVolumeUnits,
+        wpdad.inventoryWarningQuantity as inventoryWarningQuantity,
+        wpdad.warningCoefficient as warningCoefficient,
+        wpdad.warningQuantity as warningQuantity,
+        wpdad.machineInventory as machineInventory,
+        wpdad.subWarehouseRequirements as subWarehouseRequirements,
+        wpdad.warehouseRequirements as warehouseRequirements,
+        wpdad.surplusInventory as surplusInventory,
+        wpdad.status as status,
+        wpdad.expectedConsumptionDays as expectedConsumptionDays,
+        wpdad.expectedSaleTime as expectedSaleTime,
+        wpdad.expectedArrivalTime as expectedArrivalTime,
+        wpdad.saleDays as saleDays,
+        wpdad.upShelfNum as upShelfNum,
+        wpdad.procurementDemand as procurementDemand
+        from yr_warehouse_product_demand_analysis_detail as wpdad
+        where
+        wpdad.infoId = #{bo.historyId}
+        <if test="bo.goodsName != null and bo.goodsName != ''">
+            and wpdad.goodsName like concat('%', #{bo.goodsName}, '%')
+        </if>
+        <if test="bo.status != null and bo.status != ''">
+            and wpdad.status = #{bo.status}
+        </if>
+        <choose>
+            <when test="bo.sort != null and bo.sort != ''">
+                order by wpdad.${bo.sort}
+            </when>
+            <otherwise>
+                order by wpdad.warehouseProductId
+            </otherwise>
+        </choose>
+        <choose>
+            <when test="bo.sortType != null and bo.sortType != ''">
+                ${bo.sortType}
+            </when>
+            <otherwise>
+                desc
+            </otherwise>
+        </choose>
+    </select>
+
+</mapper>

+ 97 - 0
warehouse-admin-data/src/main/resources/mapper/warehouse/WarehouseProductDemandAnalysisInfoMapper.xml

@@ -0,0 +1,97 @@
+<?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.yr.warehouse.admin.warehouse.mapper.WarehouseProductDemandAnalysisInfoMapper">
+
+    <!-- 通用查询映射结果 -->
+    <resultMap id="BaseResultMap" type="com.yr.warehouse.admin.warehouse.data.WarehouseProductDemandAnalysisInfo">
+        <id column="id" property="id"/>
+        <result column="operatorId" property="operatorId"/>
+        <result column="operatorName" property="operatorName"/>
+        <result column="warehouseId" property="warehouseId"/>
+        <result column="warehouseName" property="warehouseName"/>
+        <result column="beginStatisticsDate" property="beginStatisticsDate"/>
+        <result column="endStatisticsDate" property="endStatisticsDate"/>
+        <result column="remark" property="remark"/>
+        <result column="createUserName" property="createUserName"/>
+        <result column="createUserId" property="createUserId"/>
+        <result column="createTime" property="createTime"/>
+        <result column="modifyUserName" property="modifyUserName"/>
+        <result column="modifyUserId" property="modifyUserId"/>
+        <result column="modifyTime" property="modifyTime"/>
+        <result column="isDelete" property="isDelete"/>
+    </resultMap>
+
+    <!-- 通用查询结果列 -->
+    <sql id="Base_Column_List">
+        id, operatorId, operatorName, warehouseId, warehouseName, beginStatisticsDate, endStatisticsDate, remark, createUserName, createUserId, createTime, modifyUserName, modifyUserId, modifyTime, isDelete
+    </sql>
+    <!-- 别名查询结果列 -->
+    <sql id="BASE_SELECT_ALIAS">
+        select ${alias}.id                  as id,
+               ${alias}.operatorId          as operatorId,
+               ${alias}.operatorName        as operatorName,
+               ${alias}.warehouseId         as warehouseId,
+               ${alias}.warehouseName       as warehouseName,
+               ${alias}.beginStatisticsDate as beginStatisticsDate,
+               ${alias}.endStatisticsDate   as endStatisticsDate,
+               ${alias}.remark              as remark,
+               ${alias}.createUserName      as createUserName,
+               ${alias}.createUserId        as createUserId,
+               ${alias}.createTime          as createTime,
+               ${alias}.modifyUserName      as modifyUserName,
+               ${alias}.modifyUserId        as modifyUserId,
+               ${alias}.modifyTime          as modifyTime,
+               ${alias}.isDelete            as isDelete
+        from yr_warehouse_product_demand_analysis_info as ${alias}
+    </sql>
+    <sql id="WAREHOUSE_AUTH_WHERE">
+        AND (${alias}.operatorChain = #{bo.adminOperatorChain} or ${alias}.operatorChain like
+        CONCAT(#{bo.adminOperatorChain},'-%'))
+        <choose>
+            <when test="bo.operatorId != null and bo.operatorId != ''">
+                AND ${alias}.operatorId = #{bo.operatorId}
+            </when>
+            <otherwise>
+                AND ${alias}.operatorId = #{bo.adminOperatorId}
+            </otherwise>
+        </choose>
+        <if test="bo.userWarehouseList != null and bo.userWarehouseList.size > 0">
+            AND ${alias}.id in
+            <foreach collection="bo.userWarehouseList" item="warehouse" separator="," open="(" close=")">
+                #{warehouse.warehouseId}
+            </foreach>
+        </if>
+    </sql>
+    <insert id="create" useGeneratedKeys="true" keyProperty="id"
+            parameterType="com.yr.warehouse.admin.warehouse.bo.WarehouseProductDemandAnalysisGeneratorBo">
+        insert into yr_warehouse_product_demand_analysis_info
+        (operatorId, operatorChain, operatorName, warehouseId, warehouseName, beginStatisticsDate, endStatisticsDate,
+         remark,
+         createUserName, createUserId)
+        values (#{bo.operatorId},
+                #{bo.operatorChain},
+                #{bo.operatorName},
+                #{bo.warehouseId},
+                #{bo.warehouseName},
+                #{bo.beginStatisticsDate},
+                #{bo.endStatisticsDate},
+                #{bo.remark},
+                #{bo.username},
+                #{bo.uid})
+    </insert>
+    <select id="history"
+            resultType="com.yr.warehouse.admin.warehouse.vo.WarehouseProductDemandAnalysisHistoryVo">
+        <include refid="BASE_SELECT_ALIAS">
+            <property name="alias" value="info"/>
+        </include>
+        <where>
+            <include refid="WAREHOUSE_AUTH_WHERE">
+                <property name="alias" value="info"/>
+            </include>
+            <if test="bo.warehouseId != null and bo.warehouseId > 0">
+                AND info.warehouseId = #{bo.warehouseId}
+            </if>
+        </where>
+    </select>
+
+</mapper>

+ 160 - 0
warehouse-admin-data/src/main/resources/mapper/warehouse/WarehouseProductDemandAnalysisMapper.xml

@@ -0,0 +1,160 @@
+<?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.yr.warehouse.admin.warehouse.mapper.WarehouseProductDemandAnalysisMapper">
+    <select id="page" resultType="com.yr.warehouse.admin.warehouse.vo.WarehouseProductDemandAnalysisVo">
+        with warehouseProduct as (select wp.id                       as id,
+                                         pd.id                       as goodsId,
+                                         pd.code                     as goodsCode,
+                                         pd.display_name             as goodsName,
+                                         wp.unboxingPriority         as unboxingPriority,
+                                         pd.shelf_life               as shelfLife,
+                                         wp.procurementCycle         as procurementCycle,
+                                         wp.moq                      as moq,
+                                         wp.inventoryWarningQuantity as inventoryWarningQuantity,
+                                         wp.warningCoefficient       as warningCoefficient,
+                                         wp.inventory                as surplusInventory,
+                                         wp.warehouseInfoId          as warehouseId
+                                  from yr_warehouse_info as wi
+                                           left join yr_warehouse_product as wp on wi.id = wp.warehouseInfoId
+                                           left join yr_product_detail as pd on wp.productSpecId = pd.id
+                                  where wi.id = #{bo.warehouseId}
+                                    <if test="bo.goodsName != null and bo.goodsName != ''">
+                                        and pd.display_name like concat('%', #{bo.goodsName}, '%')
+                                    </if>
+                                    ),
+             goodsSales as (select svs.warehouseInfoId  as warehouseId,
+                                   svs.goodsId          as goodsId,
+                                   sum(svs.salesVolume) as salesVolume
+                            from yr_sales_volume_statistics as svs
+                                     inner join warehouseProduct as wp
+                                                on svs.goodsId = wp.goodsId and svs.warehouseInfoId = wp.warehouseId
+                            where svs.warehouseInfoId = #{bo.warehouseId}
+                              and svs.salesTime between #{bo.beginStatisticsDate} and #{bo.endStatisticsDate}
+                            group by svs.warehouseInfoId, svs.goodsId),
+             deviceGoods as (select wd.warehouseInfoId          as warehouseId,
+                                    odcw.goodsId                as goodsId,
+                                    SUM(odcw.stockNumber)       as machineInventory,
+                                    COUNT(distinct wd.deviceId) as upShelfNum
+                             from yr_warehouse_device as wd
+                                      inner join yr_operators_device as od on wd.deviceId = od.id and od.putStatus = 'USED'
+                                      inner join yr_operators_device_cargo_way as odcw on wd.deviceId = odcw.deviceId
+                                      inner join warehouseProduct wp
+                                                 on odcw.goodsId = wp.goodsId and wd.warehouseInfoId = wp.warehouseId
+                             where wd.warehouseInfoId = #{bo.warehouseId}
+                             group by wd.warehouseInfoId, odcw.goodsId),
+        tempDate as (select
+                         wp.id                                        as id,
+        wp.goodsId                                                    as goodsId,
+        wp.goodsCode                                                  as goodsCode,
+        wp.goodsName                                                  as goodsName,
+        wp.unboxingPriority                                           as unboxingPriority,
+        wp.shelfLife                                                  as shelfLife,
+        wp.procurementCycle                                           as procurementCycle,
+        wp.moq                                                        as moq,
+        ifnull(gs.salesVolume, 0)                                     as weeklySalesVolume,
+        wp.inventoryWarningQuantity                                   as inventoryWarningQuantity,
+        wp.warningCoefficient                                         as warningCoefficient,
+        round(wp.inventoryWarningQuantity * wp.warningCoefficient, 0) as warningQuantity,
+        ifnull(dg.machineInventory, 0)                                as machineInventory,
+        round(wp.surplusInventory / wp.unboxingPriority, 2)           as surplusInventory,
+        ifnull(dg.upShelfNum, 0)                                      as upShelfNum,
+        CASE
+        WHEN round(wp.surplusInventory / nullif(wp.unboxingPriority, 0), 2) >=
+        wp.inventoryWarningQuantity
+        AND round(wp.surplusInventory / nullif(wp.unboxingPriority, 0), 2) >=
+        round(wp.inventoryWarningQuantity * wp.warningCoefficient, 0)
+        THEN 'SAFETY'
+        WHEN round(wp.surplusInventory / nullif(wp.unboxingPriority, 0), 2) >=
+        wp.inventoryWarningQuantity
+        AND round(wp.inventoryWarningQuantity * wp.warningCoefficient, 0) >
+        round(wp.surplusInventory / nullif(wp.unboxingPriority, 0), 2)
+        THEN 'WARNING'
+        ELSE 'DANGER'
+        END                                                       as status
+        from warehouseProduct as wp
+        left join goodsSales as gs on wp.goodsId = gs.goodsId and wp.warehouseId = gs.warehouseId
+        left join deviceGoods as dg on wp.goodsId = dg.goodsId and wp.warehouseId = dg.warehouseId)
+        select
+        td.id as id,
+        td.goodsId as goodsId,
+        td.goodsCode as goodsCode,
+        td.goodsName as goodsName,
+        td.unboxingPriority as unboxingPriority,
+        td.shelfLife as shelfLife,
+        td.procurementCycle as procurementCycle,
+        td.moq as moq,
+        td.weeklySalesVolume as weeklySalesVolume,
+        td.inventoryWarningQuantity as inventoryWarningQuantity,
+        td.warningCoefficient as warningCoefficient,
+        td.warningQuantity as warningQuantity,
+        td.machineInventory as machineInventory,
+        td.surplusInventory as surplusInventory,
+        td.upShelfNum as upShelfNum,
+        td.status as status
+        from tempDate as td
+        <where>
+            <if test="bo.status != null and bo.status != ''">
+                and status = #{bo.status}
+            </if>
+        </where>
+        <choose>
+            <when test="bo.sort != null and bo.sort != ''">
+                order by #{bo.sort}
+            </when>
+            <otherwise>
+                order by id
+            </otherwise>
+        </choose>
+        <choose>
+            <when test="bo.sortType != null and bo.sortType != ''">
+                ${bo.sortType}
+            </when>
+            <otherwise>
+            DESC
+            </otherwise>
+        </choose>
+    </select>
+    <select id="searchSubWarehouseRequirements"
+            resultType="com.yr.warehouse.admin.warehouse.vo.WarehouseRequirementsVo">
+        select wdd.productSpecId as goodsId,
+        sum(wdd.actualOutboundPiecesQuantity * wdd.specificationQuantity + wdd.actualOutboundQuantity) as totalOutbound
+        from
+        yr_warehouse_delivery_info as wdi
+        left join yr_warehouse_delivery_detail as wdd on wdi.deliveryOrderNumber = wdd.deliveryOrderNumber
+        where wdi.warehouseInfoId = #{warehouseId}
+        <if test="goodsIds != null and goodsIds.size > 0">
+            <foreach collection="goodsIds" item="goodsId" open="and wdd.productSpecId in (" close=")" separator=",">
+                #{goodsId}
+            </foreach>
+        </if>
+        and wdi.outboundType in ('OTHER_OUT_OPERATOR', 'OTHER_OUT_MERCHANT')
+        and wdi.deliveryStatus = 'COMPLETED'
+        and wdi.updateTime between #{beginStatisticsDate} and #{endStatisticsDate}
+        group by wdd.productSpecId
+    </select>
+
+    <update id="editor"
+            parameterType="com.yr.warehouse.admin.warehouse.bo.WarehouseProductDemandAnalysisEditorBo">
+        update yr_warehouse_product
+        set procurementCycle         = #{bo.procurementCycle},
+            moq                      = #{bo.moq},
+            inventoryWarningQuantity = #{bo.inventoryWarningQuantity},
+            warningCoefficient       = #{bo.warningCoefficient},
+            updateUserName           = #{bo.username},
+            updateUserId             = #{bo.uid}
+        where id = #{bo.id}
+    </update>
+    <update id="batchEditor">
+        <foreach collection="batchBos" item="batchBo" index="index" separator=";">
+            update yr_warehouse_product
+            set
+            procurementCycle = #{batchBo.procurementCycle},
+            moq = #{batchBo.moq},
+            inventoryWarningQuantity = #{batchBo.inventoryWarningQuantity},
+            warningCoefficient = #{batchBo.warningCoefficient},
+            updateUserName = #{bo.username},
+            updateUserId = #{bo.uid}
+            where id = #{batchBo.id}
+        </foreach>
+    </update>
+</mapper>

+ 75 - 0
warehouse-admin-data/src/main/resources/mapper/warehouse/WarehouseProductMapper.xml

@@ -0,0 +1,75 @@
+<?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.yr.warehouse.admin.warehouse.mapper.WarehouseProductMapper">
+
+    <!-- 通用查询映射结果 -->
+    <resultMap id="BaseResultMap" type="com.yr.warehouse.admin.warehouse.data.WarehouseProduct">
+        <id column="id" property="id" />
+        <result column="warehouseInfoId" property="warehouseInfoId" />
+        <result column="productSpecId" property="productSpecId" />
+        <result column="inventoryWarningQuantity" property="inventoryWarningQuantity" />
+        <result column="inventory" property="inventory" />
+        <result column="warehouseLocation" property="warehouseLocation" />
+        <result column="procurementCycle" property="procurementCycle" />
+        <result column="moq" property="moq" />
+        <result column="warningCoefficient" property="warningCoefficient" />
+        <result column="unboxingPriority" property="unboxingPriority" />
+        <result column="countingTime" property="countingTime" />
+        <result column="lastPurchaseTime" property="lastPurchaseTime" />
+        <result column="expectedSoldOutDays" property="expectedSoldOutDays" />
+        <result column="status" property="status" />
+        <result column="salesStatus" property="salesStatus" />
+        <result column="createUserName" property="createUserName" />
+        <result column="createUserId" property="createUserId" />
+        <result column="createTime" property="createTime" />
+        <result column="updateUserName" property="updateUserName" />
+        <result column="updateUserId" property="updateUserId" />
+        <result column="updateTime" property="updateTime" />
+        <result column="frozenInventory" property="frozenInventory" />
+        <result column="takingBeforeInventory" property="takingBeforeInventory" />
+    </resultMap>
+
+    <!-- 通用查询结果列 -->
+    <sql id="Base_Column_List">
+        id, warehouseInfoId, productSpecId, inventoryWarningQuantity, inventory, warehouseLocation, procurementCycle, moq, warningCoefficient, unboxingPriority, countingTime, lastPurchaseTime, expectedSoldOutDays, status, salesStatus, createUserName, createUserId, createTime, updateUserName, updateUserId, updateTime, frozenInventory, takingBeforeInventory
+    </sql>
+    <select id="searchWarehouseProductByGoodsCodes"
+            resultType="com.yr.warehouse.admin.warehouse.vo.WarehouseProductVo">
+        select
+        wp.id as id,
+        wp.warehouseInfoId as warehouseInfoId,
+        wp.productSpecId as productSpecId,
+        pd.code as goodsCode,
+        pd.display_name as goodsName,
+        wp.inventoryWarningQuantity as inventoryWarningQuantity,
+        wp.inventory as inventory,
+        wp.warehouseLocation as warehouseLocation,
+        wp.procurementCycle as procurementCycle,
+        wp.moq as moq,
+        wp.warningCoefficient as warningCoefficient,
+        wp.unboxingPriority as unboxingPriority,
+        wp.countingTime as countingTime,
+        wp.lastPurchaseTime as lastPurchaseTime,
+        wp.expectedSoldOutDays as expectedSoldOutDays,
+        wp.status as status,
+        wp.salesStatus as salesStatus,
+        wp.createUserName as createUserName,
+        wp.createUserId as createUserId,
+        wp.createTime as createTime,
+        wp.updateUserName as updateUserName,
+        wp.updateUserId as updateUserId,
+        wp.updateTime as updateTime,
+        wp.frozenInventory as frozenInventory,
+        wp.takingBeforeInventory as takingBeforeInventory
+        from yr_warehouse_product as wp
+        left join yr_product_detail as pd on wp.productSpecId = pd.id
+        where
+        wp.warehouseInfoId = #{warehouseId}
+        and pd.code in
+        <foreach collection="goodsCodes" item="item" index="index"
+                 open="(" separator="," close=")">
+            #{item}
+        </foreach>
+    </select>
+
+</mapper>

+ 2 - 3
warehouse-admin-data/src/main/test/com/supplychain/CodeGenerator.java

@@ -52,14 +52,13 @@ public class CodeGenerator {
     /**
      * 模块名
      */
-    private static final String PACKAGE_BUSINESS = "driver";
+    private static final String PACKAGE_BUSINESS = "warehouse";
 
     /**
      * 需要生成的表名,必填
      */
     private static final List<String> TABLES = List.of(
-            "yr_driver_goods_loss_stat_un_replenish_snapshot",
-            "yr_driver_goods_loss_stat_profit_loss_detail"
+            "yr_warehouse_info"
     );
 
 

+ 16 - 0
warehouse-admin-server/src/main/java/com/yr/warehouse/admin/service/warehouse/service/WarehouseInfoService.java

@@ -0,0 +1,16 @@
+package com.yr.warehouse.admin.service.warehouse.service;
+
+import com.yr.warehouse.admin.warehouse.data.WarehouseInfo;
+import com.baomidou.mybatisplus.extension.service.IService;
+
+/**
+ * <p>
+ * 仓库信息 服务类
+ * </p>
+ *
+ * @author 
+ * @since 2026-02-27 14:35:26
+ */
+public interface WarehouseInfoService extends IService<WarehouseInfo> {
+
+}

+ 16 - 0
warehouse-admin-server/src/main/java/com/yr/warehouse/admin/service/warehouse/service/WarehouseProductDemandAnalysisDetailService.java

@@ -0,0 +1,16 @@
+package com.yr.warehouse.admin.service.warehouse.service;
+
+import com.yr.warehouse.admin.warehouse.data.WarehouseProductDemandAnalysisDetail;
+import com.baomidou.mybatisplus.extension.service.IService;
+
+/**
+ * <p>
+ * 仓库商品需求分析详情表 服务类
+ * </p>
+ *
+ * @author 
+ * @since 2026-02-27 11:20:46
+ */
+public interface WarehouseProductDemandAnalysisDetailService extends IService<WarehouseProductDemandAnalysisDetail> {
+
+}

+ 16 - 0
warehouse-admin-server/src/main/java/com/yr/warehouse/admin/service/warehouse/service/WarehouseProductDemandAnalysisInfoService.java

@@ -0,0 +1,16 @@
+package com.yr.warehouse.admin.service.warehouse.service;
+
+import com.yr.warehouse.admin.warehouse.data.WarehouseProductDemandAnalysisInfo;
+import com.baomidou.mybatisplus.extension.service.IService;
+
+/**
+ * <p>
+ * 仓库商品需求分析主表 服务类
+ * </p>
+ *
+ * @author 
+ * @since 2026-02-27 11:20:46
+ */
+public interface WarehouseProductDemandAnalysisInfoService extends IService<WarehouseProductDemandAnalysisInfo> {
+
+}

+ 61 - 0
warehouse-admin-server/src/main/java/com/yr/warehouse/admin/service/warehouse/service/WarehouseProductDemandAnalysisService.java

@@ -0,0 +1,61 @@
+package com.yr.warehouse.admin.service.warehouse.service;
+
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.yr.bluecat.common.entity.bo.BaseBo;
+import com.yr.warehouse.admin.warehouse.bo.*;
+import com.yr.warehouse.admin.warehouse.vo.WarehouseProductDemandAnalysisHistoryVo;
+import com.yr.warehouse.admin.warehouse.vo.WarehouseProductDemandAnalysisVo;
+
+import java.util.List;
+
+/**
+ * 仓库商品需求分析服务
+ */
+public interface WarehouseProductDemandAnalysisService {
+
+    /**
+     * 分页查询仓库商品需求分析
+     *
+     * @param bo 分页参数
+     * @return 仓库商品需求分析分页结果
+     */
+    Page<WarehouseProductDemandAnalysisVo> page(WarehouseProductDemandAnalysisPageBo bo);
+
+    /**
+     * 仓库商品需求分析编辑
+     *
+     * @param bo 仓库商品需求分析编辑参数
+     */
+    void editor(WarehouseProductDemandAnalysisEditorBo bo);
+
+    /**
+     * 批量仓库商品需求分析编辑
+     *
+     * @param batchBos 批量仓库商品需求分析编辑参数
+     * @param bo       基础参数
+     */
+    void batchEditor(List<WarehouseProductDemandAnalysisEditorBo> batchBos, BaseBo bo);
+
+    /**
+     * 仓库商品需求分析生成
+     *
+     * @param bo 仓库商品需求分析生成参数
+     */
+    void generator(WarehouseProductDemandAnalysisGeneratorBo bo);
+
+    /**
+     * 仓库商品需求分析历史
+     *
+     * @param bo 仓库商品需求分析历史参数
+     * @return 仓库商品需求分析历史结果
+     */
+    Page<WarehouseProductDemandAnalysisHistoryVo> history(WarehouseProductDemandAnalysisHistoryBo bo);
+
+    /**
+     * 仓库商品需求分析历史分页
+     *
+     * @param bo 仓库商品需求分析历史分页参数
+     * @return 仓库商品需求分析历史分页结果
+     */
+    Page<WarehouseProductDemandAnalysisVo> historyPage(WarehouseProductDemandAnalysisHistoryPageBo bo);
+}

+ 27 - 0
warehouse-admin-server/src/main/java/com/yr/warehouse/admin/service/warehouse/service/WarehouseProductService.java

@@ -0,0 +1,27 @@
+package com.yr.warehouse.admin.service.warehouse.service;
+
+import com.yr.warehouse.admin.warehouse.data.WarehouseProduct;
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.yr.warehouse.admin.warehouse.vo.WarehouseProductVo;
+
+import java.util.List;
+
+/**
+ * <p>
+ * 仓库商品表 服务类
+ * </p>
+ *
+ * @author 
+ * @since 2026-02-27 10:48:39
+ */
+public interface WarehouseProductService extends IService<WarehouseProduct> {
+
+    /**
+     * 根据商品编号查询仓库商品
+     *
+     * @param goodsCodes 商品编号
+     * @param warehouseId 仓库id
+     * @return 仓库商品
+     */
+    List<WarehouseProductVo> searchWarehouseProductByGoodsCodes(List<String> goodsCodes, Long warehouseId);
+}

+ 20 - 0
warehouse-admin-server/src/main/java/com/yr/warehouse/admin/service/warehouse/service/impl/WarehouseInfoServiceImpl.java

@@ -0,0 +1,20 @@
+package com.yr.warehouse.admin.service.warehouse.service.impl;
+
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.yr.warehouse.admin.service.warehouse.service.WarehouseInfoService;
+import com.yr.warehouse.admin.warehouse.data.WarehouseInfo;
+import com.yr.warehouse.admin.warehouse.mapper.WarehouseInfoMapper;
+import org.springframework.stereotype.Service;
+
+/**
+ * <p>
+ * 仓库信息 服务实现类
+ * </p>
+ *
+ * @author 
+ * @since 2026-02-27 14:35:26
+ */
+@Service
+public class WarehouseInfoServiceImpl extends ServiceImpl<WarehouseInfoMapper, WarehouseInfo> implements WarehouseInfoService {
+
+}

+ 20 - 0
warehouse-admin-server/src/main/java/com/yr/warehouse/admin/service/warehouse/service/impl/WarehouseProductDemandAnalysisDetailServiceImpl.java

@@ -0,0 +1,20 @@
+package com.yr.warehouse.admin.service.warehouse.service.impl;
+
+import com.yr.warehouse.admin.service.warehouse.service.WarehouseProductDemandAnalysisDetailService;
+import com.yr.warehouse.admin.warehouse.data.WarehouseProductDemandAnalysisDetail;
+import com.yr.warehouse.admin.warehouse.mapper.WarehouseProductDemandAnalysisDetailMapper;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import org.springframework.stereotype.Service;
+
+/**
+ * <p>
+ * 仓库商品需求分析详情表 服务实现类
+ * </p>
+ *
+ * @author 
+ * @since 2026-02-27 11:20:46
+ */
+@Service
+public class WarehouseProductDemandAnalysisDetailServiceImpl extends ServiceImpl<WarehouseProductDemandAnalysisDetailMapper, WarehouseProductDemandAnalysisDetail> implements WarehouseProductDemandAnalysisDetailService {
+
+}

+ 20 - 0
warehouse-admin-server/src/main/java/com/yr/warehouse/admin/service/warehouse/service/impl/WarehouseProductDemandAnalysisInfoServiceImpl.java

@@ -0,0 +1,20 @@
+package com.yr.warehouse.admin.service.warehouse.service.impl;
+
+import com.yr.warehouse.admin.service.warehouse.service.WarehouseProductDemandAnalysisInfoService;
+import com.yr.warehouse.admin.warehouse.data.WarehouseProductDemandAnalysisInfo;
+import com.yr.warehouse.admin.warehouse.mapper.WarehouseProductDemandAnalysisInfoMapper;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import org.springframework.stereotype.Service;
+
+/**
+ * <p>
+ * 仓库商品需求分析主表 服务实现类
+ * </p>
+ *
+ * @author 
+ * @since 2026-02-27 11:20:46
+ */
+@Service
+public class WarehouseProductDemandAnalysisInfoServiceImpl extends ServiceImpl<WarehouseProductDemandAnalysisInfoMapper, WarehouseProductDemandAnalysisInfo> implements WarehouseProductDemandAnalysisInfoService {
+
+}

+ 121 - 0
warehouse-admin-server/src/main/java/com/yr/warehouse/admin/service/warehouse/service/impl/WarehouseProductDemandAnalysisServiceImpl.java

@@ -0,0 +1,121 @@
+package com.yr.warehouse.admin.service.warehouse.service.impl;
+
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.yr.bluecat.common.entity.bo.BaseBo;
+import com.yr.bluecat.common.entity.exception.MessageException;
+import com.yr.warehouse.admin.service.warehouse.service.WarehouseProductDemandAnalysisService;
+import com.yr.warehouse.admin.warehouse.bo.*;
+import com.yr.warehouse.admin.warehouse.data.WarehouseInfo;
+import com.yr.warehouse.admin.warehouse.mapper.WarehouseInfoMapper;
+import com.yr.warehouse.admin.warehouse.mapper.WarehouseProductDemandAnalysisDetailMapper;
+import com.yr.warehouse.admin.warehouse.mapper.WarehouseProductDemandAnalysisInfoMapper;
+import com.yr.warehouse.admin.warehouse.mapper.WarehouseProductDemandAnalysisMapper;
+import com.yr.warehouse.admin.warehouse.vo.WarehouseProductDemandAnalysisHistoryVo;
+import com.yr.warehouse.admin.warehouse.vo.WarehouseProductDemandAnalysisVo;
+import com.yr.warehouse.admin.warehouse.vo.WarehouseRequirementsVo;
+import jakarta.annotation.Resource;
+import org.springframework.stereotype.Service;
+
+import java.math.BigDecimal;
+import java.math.RoundingMode;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
+
+/**
+ * 仓库商品需求分析服务实现类
+ */
+@Service
+public class WarehouseProductDemandAnalysisServiceImpl implements WarehouseProductDemandAnalysisService {
+    @Resource
+    private WarehouseInfoMapper warehouseInfoMapper;
+    @Resource
+    private WarehouseProductDemandAnalysisMapper warehouseProductDemandAnalysisMapper;
+    @Resource
+    private WarehouseProductDemandAnalysisInfoMapper warehouseProductDemandAnalysisInfoMapper;
+    @Resource
+    private WarehouseProductDemandAnalysisDetailMapper warehouseProductDemandAnalysisDetailMapper;
+
+    @Override
+    public Page<WarehouseProductDemandAnalysisVo> page(WarehouseProductDemandAnalysisPageBo bo) {
+        Page<WarehouseProductDemandAnalysisVo> page = new Page<>(bo.getPageNum(), bo.getPageSize());
+        page = warehouseProductDemandAnalysisMapper.page(page, bo);
+
+        // 处理仓库商品需求分析数据
+        List<WarehouseProductDemandAnalysisVo> warehouseProductDemandAnalysisVos = page.getRecords();
+        if (warehouseProductDemandAnalysisVos.isEmpty()) {
+            return page;
+        }
+
+        List<Integer> goodsIds = warehouseProductDemandAnalysisVos.stream().map(WarehouseProductDemandAnalysisVo::getGoodsId).collect(Collectors.toList());
+
+        List<WarehouseRequirementsVo> subWarehouseRequirementList = warehouseProductDemandAnalysisMapper.searchSubWarehouseRequirements(goodsIds, bo.getWarehouseId(), bo.getBeginStatisticsDate(), bo.getEndStatisticsDate());
+
+        Map<Integer, Long> subWarehouseRequirementsMap = subWarehouseRequirementList.stream().collect(Collectors.toMap(WarehouseRequirementsVo::getGoodsId, WarehouseRequirementsVo::getTotalOutbound));
+
+        warehouseProductDemandAnalysisVos.forEach(warehouseProductDemandAnalysisVo -> {
+            Long totalOutbound = subWarehouseRequirementsMap.get(warehouseProductDemandAnalysisVo.getGoodsId());
+
+            if (null == totalOutbound) {
+                totalOutbound = 0L;
+            }
+            BigDecimal subWarehouseRequirements = BigDecimal.valueOf(totalOutbound).divide(BigDecimal.valueOf(warehouseProductDemandAnalysisVo.getUnboxingPriority()), 2, RoundingMode.HALF_UP);
+            warehouseProductDemandAnalysisVo.setSubWarehouseRequirements(subWarehouseRequirements);
+            warehouseProductDemandAnalysisVo.build();
+        });
+        page.setRecords(warehouseProductDemandAnalysisVos);
+        return page;
+    }
+
+    @Override
+    public void editor(WarehouseProductDemandAnalysisEditorBo bo) {
+        bo.build();
+        warehouseProductDemandAnalysisMapper.editor(bo);
+    }
+
+    @Override
+    public void batchEditor(List<WarehouseProductDemandAnalysisEditorBo> batchBos, BaseBo bo) {
+        warehouseProductDemandAnalysisMapper.batchEditor(batchBos, bo);
+    }
+
+    @Override
+    public void generator(WarehouseProductDemandAnalysisGeneratorBo bo) {
+        WarehouseInfo warehouseInfo = warehouseInfoMapper.getById(bo.getWarehouseId());
+        if (null == warehouseInfo) {
+            throw new MessageException("仓库不存在");
+        }
+        bo.setOperatorChain(warehouseInfo.getOperatorChain());
+        WarehouseProductDemandAnalysisPageBo pageBo = new WarehouseProductDemandAnalysisPageBo();
+        pageBo.setWarehouseId(bo.getWarehouseId());
+        pageBo.setBeginStatisticsDate(bo.getBeginStatisticsDate());
+        pageBo.setEndStatisticsDate(bo.getEndStatisticsDate());
+        pageBo.setPageNum(1);
+        pageBo.setPageSize(1000);
+
+        List<WarehouseProductDemandAnalysisVo> all = new ArrayList<>();
+        while ( true) {
+            Page<WarehouseProductDemandAnalysisVo> page = page(pageBo);
+            List<WarehouseProductDemandAnalysisVo> records = page.getRecords();
+            if (records.isEmpty()) {
+                break;
+            }
+            all.addAll(records);
+            pageBo.setPageNum(pageBo.getPageNum() + 1);
+        }
+        warehouseProductDemandAnalysisInfoMapper.create(bo);
+        warehouseProductDemandAnalysisDetailMapper.create(all, bo);
+    }
+
+    @Override
+    public Page<WarehouseProductDemandAnalysisHistoryVo> history(WarehouseProductDemandAnalysisHistoryBo bo) {
+        Page<WarehouseProductDemandAnalysisHistoryVo> page = new Page<>(bo.getPageNum(), bo.getPageSize());
+        return warehouseProductDemandAnalysisInfoMapper.history(page, bo);
+    }
+
+    @Override
+    public Page<WarehouseProductDemandAnalysisVo> historyPage(WarehouseProductDemandAnalysisHistoryPageBo bo) {
+        Page<WarehouseProductDemandAnalysisVo> page = new Page<>(bo.getPageNum(), bo.getPageSize());
+        return warehouseProductDemandAnalysisDetailMapper.historyPage(page, bo);
+    }
+}

+ 27 - 0
warehouse-admin-server/src/main/java/com/yr/warehouse/admin/service/warehouse/service/impl/WarehouseProductServiceImpl.java

@@ -0,0 +1,27 @@
+package com.yr.warehouse.admin.service.warehouse.service.impl;
+
+import com.yr.warehouse.admin.service.warehouse.service.WarehouseProductService;
+import com.yr.warehouse.admin.warehouse.data.WarehouseProduct;
+import com.yr.warehouse.admin.warehouse.mapper.WarehouseProductMapper;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.yr.warehouse.admin.warehouse.vo.WarehouseProductVo;
+import org.springframework.stereotype.Service;
+
+import java.util.List;
+
+/**
+ * <p>
+ * 仓库商品表 服务实现类
+ * </p>
+ *
+ * @author 
+ * @since 2026-02-27 10:48:39
+ */
+@Service
+public class WarehouseProductServiceImpl extends ServiceImpl<WarehouseProductMapper, WarehouseProduct> implements WarehouseProductService {
+
+    @Override
+    public List<WarehouseProductVo> searchWarehouseProductByGoodsCodes(List<String> goodsCodes, Long warehouseId) {
+        return baseMapper.searchWarehouseProductByGoodsCodes(goodsCodes, warehouseId);
+    }
+}

+ 236 - 0
warehouse-admin-web/src/main/java/com/yr/warehouse/admin/web/product/controller/WarehouseProductDemandAnalysisController.java

@@ -0,0 +1,236 @@
+package com.yr.warehouse.admin.web.product.controller;
+
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.yr.bluecat.common.entity.bo.BaseBo;
+import com.yr.bluecat.common.entity.exception.MessageException;
+import com.yr.bluecat.common.entity.response.PageResult;
+import com.yr.bluecat.common.entity.response.Result;
+import com.yr.bluecat.common.entity.utils.StringUtils;
+import com.yr.bluecat.common.utils.excel.ExportClient;
+import com.yr.prism.auth.core.user.AdminUserInfo;
+import com.yr.warehouse.admin.service.warehouse.service.WarehouseProductDemandAnalysisService;
+import com.yr.warehouse.admin.service.warehouse.service.WarehouseProductService;
+import com.yr.warehouse.admin.warehouse.bo.*;
+import com.yr.warehouse.admin.warehouse.vo.WarehouseProductDemandAnalysisHistoryVo;
+import com.yr.warehouse.admin.warehouse.vo.WarehouseProductDemandAnalysisVo;
+import com.yr.warehouse.admin.warehouse.vo.WarehouseProductVo;
+import com.yr.warehouse.admin.web.common.BaseController;
+import com.yr.warehouse.admin.web.product.excel.WarehouseProductDemandAnalysisExcel;
+import com.yr.warehouse.admin.web.product.export.WarehouseProductDemandAnalysisExport;
+import com.yr.warehouse.admin.web.product.mapstruct.WarehouseProductMapStruct;
+import com.yr.warehouse.admin.web.product.request.*;
+import com.yr.warehouse.admin.web.product.response.WarehouseProductDemandAnalysisHistoryResponse;
+import com.yr.warehouse.admin.web.product.response.WarehouseProductDemandAnalysisResponse;
+import jakarta.annotation.Resource;
+import org.jetbrains.annotations.NotNull;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.stream.Collectors;
+
+/**
+ * 仓库商品需求分析控制器
+ */
+@RestController
+@RequestMapping("/warehouse/product/demandAnalysis")
+public class WarehouseProductDemandAnalysisController extends BaseController {
+    @Resource
+    private WarehouseProductDemandAnalysisService warehouseProductDemandAnalysisService;
+    @Resource
+    private WarehouseProductService warehouseProductService;
+    @Resource
+    private ExportClient exportClient;
+
+    @NotNull
+    private static WarehouseProductDemandAnalysisEditorBo generatorEditorBo(WarehouseProductDemandAnalysisExcel excel, WarehouseProductVo warehouseProduct) {
+        WarehouseProductDemandAnalysisEditorBo warehouseProductDemandAnalysisEditorBo = new WarehouseProductDemandAnalysisEditorBo();
+        warehouseProductDemandAnalysisEditorBo.setId(warehouseProduct.getId());
+        warehouseProductDemandAnalysisEditorBo.setProcurementCycle(excel.getProcurementCycle());
+        warehouseProductDemandAnalysisEditorBo.setMoq(excel.getMoq());
+        warehouseProductDemandAnalysisEditorBo.setInventoryWarningQuantity(excel.getInventoryWarningQuantity());
+        warehouseProductDemandAnalysisEditorBo.setWarningCoefficient(excel.getWarningCoefficient());
+        warehouseProductDemandAnalysisEditorBo.build();
+        return warehouseProductDemandAnalysisEditorBo;
+    }
+
+    /**
+     * 分页查询仓库商品需求分析列表
+     * @return 仓库商品分页结果
+     */
+    @PostMapping("/page")
+    @ResponseBody
+    public PageResult<WarehouseProductDemandAnalysisResponse> page(@RequestBody WarehouseProductDemandAnalysisPageRequest request, AdminUserInfo adminUserInfo) {
+        PageResult<WarehouseProductDemandAnalysisResponse> result = PageResult.newPageResult(request.getPageNum(), request.getPageSize());
+        if (Objects.isNull(request.getWarehouseId())) {
+            return result.success(new ArrayList<>());
+        }
+
+        WarehouseProductDemandAnalysisPageBo bo = WarehouseProductMapStruct.MAPSTRUCT.demandAnalysisPageRequestToBo(request);
+        buildUserInfo(bo, adminUserInfo);
+
+        Page<WarehouseProductDemandAnalysisVo> page = warehouseProductDemandAnalysisService.page(bo);
+        return result.success(page.getTotal(), WarehouseProductMapStruct.MAPSTRUCT.demandAnalysisVoToResponse(page.getRecords()));
+    }
+
+    /**
+     * 仓库商品编辑
+     * @return 仓库商品编辑结果
+     */
+    @PostMapping("/editor")
+    @ResponseBody
+    public Result<String> editor(@Validated @RequestBody WarehouseProductDemandAnalysisEditorRequest request, AdminUserInfo adminUserInfo) {
+        WarehouseProductDemandAnalysisEditorBo bo = WarehouseProductMapStruct.MAPSTRUCT.demandAnalysisEditorRequestToBo(request);
+        buildUserInfo(bo, adminUserInfo);
+        warehouseProductDemandAnalysisService.editor(bo);
+        return Result.success();
+    }
+
+    /**
+     * 仓库商品参数批量导入
+     * excel 文件中数据格式要求如下:
+     * 商品编号, 商品名称, 采购周期, 起订量, 安全库存数, 预警系数
+     *
+     * @return 仓库商品参数批量导入结果
+     */
+    @PostMapping("/batchImport")
+    @ResponseBody
+    public Result<String> batchImport(@Validated @RequestBody WarehouseProductDemandAnalysisBatchImportRequest request, AdminUserInfo adminUserInfo) {
+        List<WarehouseProductDemandAnalysisExcel> excels = exportClient.parseExcelData(request.getExcelPath(), WarehouseProductDemandAnalysisExcel.class);
+        if (excels.isEmpty()) {
+            throw new MessageException("导入文件数据为空");
+        }
+
+        List<String> exceptionMessages = new ArrayList<>();
+        List<String> goodsCodes = new ArrayList<>();
+        for (WarehouseProductDemandAnalysisExcel excel : excels) {
+            if (StringUtils.isNotBlank(excel.getGoodsName()) && StringUtils.isBlank(excel.getGoodsCode())) {
+                exceptionMessages.add(String.format("商品名称【%s】的商品编号为空, 该商品不予导入", excel.getGoodsName()));
+            }
+            if (StringUtils.isNotBlank(excel.getGoodsCode())) {
+                goodsCodes.add(excel.getGoodsCode());
+            }
+        }
+
+        List<WarehouseProductVo> warehouseProducts = warehouseProductService.searchWarehouseProductByGoodsCodes(goodsCodes, request.getWarehouseId());
+        Map<String, WarehouseProductVo> warehouseProductMap = warehouseProducts.stream().collect(Collectors.toMap(WarehouseProductVo::getGoodsCode, v -> v));
+
+        BaseBo bo = new BaseBo();
+        buildUserInfo(bo, adminUserInfo);
+        List<WarehouseProductDemandAnalysisEditorBo> batchBos = new ArrayList<>();
+        for (WarehouseProductDemandAnalysisExcel excel : excels) {
+            WarehouseProductVo warehouseProduct = warehouseProductMap.get(excel.getGoodsCode());
+            if (null == warehouseProduct) {
+                exceptionMessages.add(String.format("商品编号【%s】的商品不存在, 该商品不予导入", excel.getGoodsCode()));
+            } else {
+                WarehouseProductDemandAnalysisEditorBo warehouseProductDemandAnalysisEditorBo = generatorEditorBo(excel, warehouseProduct);
+                batchBos.add(warehouseProductDemandAnalysisEditorBo);
+            }
+        }
+
+        if (!exceptionMessages.isEmpty()) {
+            throw new MessageException(String.join("\n", exceptionMessages));
+        }
+
+        warehouseProductDemandAnalysisService.batchEditor(batchBos, bo);
+        return Result.success();
+    }
+
+    /**
+     * 仓库商品需求分析导出
+     * @return 仓库商品需求分析导出结果
+     */
+    @PostMapping("/export")
+    @ResponseBody
+    public Result<String> export(@Validated @RequestBody WarehouseProductDemandAnalysisExportRequest request, AdminUserInfo adminUserInfo) {
+        WarehouseProductDemandAnalysisPageBo bo = WarehouseProductMapStruct.MAPSTRUCT.demandAnalysisExportRequestToBo(request);
+        buildUserInfo(bo, adminUserInfo);
+
+        bo.setPageNum(1);
+        bo.setPageSize(1000);
+        List<WarehouseProductDemandAnalysisVo> all = new ArrayList<>();
+        while (true) {
+            Page<WarehouseProductDemandAnalysisVo> page = warehouseProductDemandAnalysisService.page(bo);
+            List<WarehouseProductDemandAnalysisVo> records = page.getRecords();
+            if (null == records || records.isEmpty()) {
+                break;
+            }
+            all.addAll(records);
+            bo.setPageNum(bo.getPageNum() + 1);
+        }
+        List<WarehouseProductDemandAnalysisExport> exportList = WarehouseProductMapStruct.MAPSTRUCT.demandAnalysisVoListToExportList(all);
+        String uri = exportClient.export(exportList, "export/warehouseProductDemandAnalysis", "仓库商品需求分析" + System.currentTimeMillis());
+        return Result.success(uri);
+    }
+
+    /**
+     * 仓库商品需求分析生成记录
+     * @return 仓库商品需求分析生成记录结果
+     */
+    @PostMapping("/generator")
+    @ResponseBody
+    public Result<String> generator(@Validated @RequestBody WarehouseProductDemandAnalysisGeneratorRequest request, AdminUserInfo adminUserInfo) {
+        WarehouseProductDemandAnalysisGeneratorBo bo = WarehouseProductMapStruct.MAPSTRUCT.demandAnalysisGeneratorRequestToBo(request);
+        buildUserInfo(bo, adminUserInfo);
+        warehouseProductDemandAnalysisService.generator(bo);
+        return Result.success();
+    }
+
+    /**
+     * 仓库商品需求分析生成记录主表列表
+     * @return 仓库商品需求分析生成记录主表列表结果
+     */
+    @PostMapping("/history")
+    @ResponseBody
+    public PageResult<WarehouseProductDemandAnalysisHistoryResponse> history(@Validated @RequestBody WarehouseProductDemandAnalysisHistoryRequest request, AdminUserInfo adminUserInfo) {
+        WarehouseProductDemandAnalysisHistoryBo bo = WarehouseProductMapStruct.MAPSTRUCT.demandAnalysisHistoryRequestToBo(request);
+        buildUserInfo(bo, adminUserInfo);
+        Page<WarehouseProductDemandAnalysisHistoryVo> page = warehouseProductDemandAnalysisService.history(bo);
+        PageResult<WarehouseProductDemandAnalysisHistoryResponse> result = PageResult.newPageResult(request.getPageNum(), request.getPageSize());
+        return result.success(page.getTotal(), WarehouseProductMapStruct.MAPSTRUCT.demandAnalysisHistoryVoListToResponseList(page.getRecords()));
+    }
+
+    /**
+     * 仓库商品需求分析生成记录子表列表
+     * @return 仓库商品需求分析生成记录子表列表结果
+     */
+    @PostMapping("/historyPage")
+    @ResponseBody
+    public PageResult<WarehouseProductDemandAnalysisResponse> historyPage(@Validated @RequestBody WarehouseProductDemandAnalysisHistoryPageRequest request, AdminUserInfo adminUserInfo) {
+        WarehouseProductDemandAnalysisHistoryPageBo bo = WarehouseProductMapStruct.MAPSTRUCT.demandAnalysisHistoryPageRequestToBo(request);
+        buildUserInfo(bo, adminUserInfo);
+        Page<WarehouseProductDemandAnalysisVo> page = warehouseProductDemandAnalysisService.historyPage(bo);
+        PageResult<WarehouseProductDemandAnalysisResponse> result = PageResult.newPageResult(request.getPageNum(), request.getPageSize());
+        return result.success(page.getTotal(), WarehouseProductMapStruct.MAPSTRUCT.demandAnalysisVoToResponse(page.getRecords()));
+    }
+
+    /**
+     * 仓库商品需求分析生成记录导出
+     * @return 仓库商品需求分析生成记录导出结果
+     */
+    @PostMapping("/historyExport")
+    @ResponseBody
+    public Result<String> historyExport(@Validated @RequestBody WarehouseProductDemandAnalysisHistoryExportRequest request, AdminUserInfo adminUserInfo) {
+        WarehouseProductDemandAnalysisHistoryPageBo bo = WarehouseProductMapStruct.MAPSTRUCT.demandAnalysisHistoryExportRequestToBo(request);
+        buildUserInfo(bo, adminUserInfo);
+        bo.setPageNum(1);
+        bo.setPageSize(1000);
+        List<WarehouseProductDemandAnalysisVo> all = new ArrayList<>();
+        while (true) {
+            Page<WarehouseProductDemandAnalysisVo> page = warehouseProductDemandAnalysisService.historyPage(bo);
+            List<WarehouseProductDemandAnalysisVo> records = page.getRecords();
+            if (null == records || records.isEmpty()) {
+                break;
+            }
+            all.addAll(records);
+            bo.setPageNum(bo.getPageNum() + 1);
+        }
+        List<WarehouseProductDemandAnalysisExport> exportList = WarehouseProductMapStruct.MAPSTRUCT.demandAnalysisVoListToExportList(all);
+        String uri = exportClient.export(exportList, "export/warehouseProductDemandAnalysis", "仓库商品需求分析生成记录" + System.currentTimeMillis());
+        return Result.success(uri);
+    }
+
+}

+ 59 - 0
warehouse-admin-web/src/main/java/com/yr/warehouse/admin/web/product/excel/WarehouseProductDemandAnalysisExcel.java

@@ -0,0 +1,59 @@
+package com.yr.warehouse.admin.web.product.excel;
+
+import com.alibaba.excel.annotation.ExcelProperty;
+import lombok.Data;
+
+import java.io.Serial;
+import java.io.Serializable;
+import java.math.BigDecimal;
+
+/**
+ * 仓库商品需求分析导入
+ */
+@Data
+public class WarehouseProductDemandAnalysisExcel implements Serializable {
+
+    @Serial
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 商品编号
+     */
+    @ExcelProperty("商品编号")
+    private String goodsCode;
+
+    /**
+     * 商品名称
+     */
+    @ExcelProperty("商品名称")
+    private String goodsName;
+
+    /**
+     * 采购周期
+     * 人工填写 默认 7 天
+     */
+    @ExcelProperty("采购周期")
+    private Long procurementCycle;
+
+    /**
+     * 起订量
+     * 人工填写 默认 0
+     */
+    @ExcelProperty("起订量")
+    private Long moq;
+
+    /**
+     * 安全库存数
+     * 人工填写 默认1
+     */
+    @ExcelProperty("安全库存数")
+    private Long inventoryWarningQuantity;
+
+    /**
+     * 预警系数
+     * 人工填写 默认1.0 - 预警系数必须大于等于: 1
+     */
+    @ExcelProperty("预警系数")
+    private BigDecimal warningCoefficient;
+
+}

+ 187 - 0
warehouse-admin-web/src/main/java/com/yr/warehouse/admin/web/product/export/WarehouseProductDemandAnalysisExport.java

@@ -0,0 +1,187 @@
+package com.yr.warehouse.admin.web.product.export;
+
+import com.alibaba.excel.annotation.ExcelProperty;
+import lombok.Data;
+
+import java.io.Serial;
+import java.io.Serializable;
+import java.math.BigDecimal;
+import java.time.LocalDate;
+
+/**
+ * 仓库商品需求分析导出
+ */
+@Data
+public class WarehouseProductDemandAnalysisExport implements Serializable {
+
+    @Serial
+    private static final long serialVersionUID = 1L;
+
+
+    /**
+     * 商品编号
+     */
+    @ExcelProperty("商品编号")
+    private String goodsCode;
+
+    /**
+     * 商品名称
+     */
+    @ExcelProperty("商品名称")
+    private String goodsName;
+
+    /**
+     * 规格
+     */
+    @ExcelProperty("规格")
+    private Integer unboxingPriority;
+
+    /**
+     * 保质期(天)
+     */
+    @ExcelProperty("保质期(天)")
+    private Integer shelfLife;
+
+    /**
+     * 采购周期
+     * 人工填写 默认 7 天
+     */
+    @ExcelProperty("采购周期")
+    private Long procurementCycle;
+
+    /**
+     * 起订量
+     * 人工填写 默认 0
+     */
+    @ExcelProperty("起订量")
+    private Long moq;
+
+    /**
+     * 周销售量(个)
+     */
+    @ExcelProperty("周销售量(个)")
+    private Long weeklySalesVolume;
+
+    /**
+     * 周销售量(件)
+     * 周销售量(个) / 规格, 保留两位小数
+     */
+    @ExcelProperty("周销售量(件)")
+    private BigDecimal weeklySalesVolumeUnits;
+
+    /**
+     * 安全库存数
+     * 人工填写 默认1
+     */
+    @ExcelProperty("安全库存数")
+    private Long inventoryWarningQuantity;
+
+    /**
+     * 预警系数
+     * 人工填写 默认1.0
+     */
+    @ExcelProperty("预警系数")
+    private BigDecimal warningCoefficient;
+
+    /**
+     * 预警值
+     * 安全库存数 * 预警系数 整数 向上取整
+     */
+    @ExcelProperty("预警值")
+    private Long warningQuantity;
+
+    /**
+     * 上机库存
+     * 仓库绑定的所有设备在统计日期内该商品的所有数量 实时设备库存
+     */
+    @ExcelProperty("上机库存")
+    private Long machineInventory;
+
+    /**
+     * 分仓需求
+     * 分仓批发数量(件) 出库管理的批发类型
+     */
+    @ExcelProperty("分仓需求")
+    private BigDecimal subWarehouseRequirements;
+
+    /**
+     * 需求量
+     * 周销售量(件) / 7 * (采购周期 + 7) * 预警系数 + 分仓需求 / 7 * (采购周期 + 7)
+     * 保留两位小数
+     */
+    @ExcelProperty("需求量")
+    private BigDecimal warehouseRequirements;
+
+    /**
+     * 结余库存
+     * 该商品在仓库里的库存数(件)
+     */
+    @ExcelProperty("结余库存")
+    private BigDecimal surplusInventory;
+
+    /**
+     * 状态
+     * 安全(结余库存 >= 安全库存 && 结余库存 >= 预警值) SAFETY
+     * 预警(结余库存 >= 安全库存 && 预警值 > 结余库存) WARNING
+     * 危险(安全库存 > 结余库存 && 预警值 > 结余库存) DANGER
+     */
+    @ExcelProperty("状态")
+    private String status;
+
+    /**
+     * 预计消耗天数
+     * (结余库存 + 上机库存) / 周销量(件) * 7 四舍五入取整
+     * 例如: (200 + 100) / 20 * 7 = 105
+     */
+    @ExcelProperty("预计消耗天数")
+    private BigDecimal expectedConsumptionDays;
+
+    /**
+     * 预计销售时间
+     * (结余库存 + 需求量) / 周销量(件) * 7 当前日期加上计算天数
+     * 例如: (200 + 300) / 20 * 7 = 175
+     * 2026-02-26 + 175 = 2026-08-20
+     */
+    @ExcelProperty("预计销售时间")
+    private LocalDate expectedSaleTime;
+
+    /**
+     * 期望到货时间
+     * 当前日期 + 预计消耗天数
+     * 例如: 2026-02-26 + 105 = 2026-06-11
+     */
+    @ExcelProperty("期望到货时间")
+    private LocalDate expectedArrivalTime;
+
+    /**
+     * 售卖天数
+     * (结余库存 - 分仓需求) / 周销量(件) * 7 四舍五入取整
+     */
+    @ExcelProperty("售卖天数")
+    private Long saleDays;
+
+    /**
+     * 上架数
+     * 该商品在设备里的上架设备数, 单台设备算1个上架数
+     * 只查询已上机的设备货道存在该商品的设备数
+     */
+    @ExcelProperty("上架数")
+    private Long upShelfNum;
+
+    /**
+     * 采购需求
+     * 需求量 (保留两位小数的原数据) - 结余库存
+     */
+    @ExcelProperty("采购需求")
+    private BigDecimal procurementDemand;
+
+    public String getStatus() {
+        return switch (status) {
+            case "SAFETY" -> "安全";
+            case "WARNING" -> "预警";
+            case "DANGER" -> "危险";
+            default -> "未知";
+        };
+    }
+
+}

+ 39 - 0
warehouse-admin-web/src/main/java/com/yr/warehouse/admin/web/product/mapstruct/WarehouseProductMapStruct.java

@@ -0,0 +1,39 @@
+package com.yr.warehouse.admin.web.product.mapstruct;
+
+import com.yr.warehouse.admin.warehouse.bo.*;
+import com.yr.warehouse.admin.warehouse.vo.WarehouseProductDemandAnalysisHistoryVo;
+import com.yr.warehouse.admin.warehouse.vo.WarehouseProductDemandAnalysisVo;
+import com.yr.warehouse.admin.web.product.export.WarehouseProductDemandAnalysisExport;
+import com.yr.warehouse.admin.web.product.request.*;
+import com.yr.warehouse.admin.web.product.response.WarehouseProductDemandAnalysisHistoryResponse;
+import com.yr.warehouse.admin.web.product.response.WarehouseProductDemandAnalysisResponse;
+import org.mapstruct.Mapper;
+import org.mapstruct.factory.Mappers;
+
+import java.util.List;
+
+@Mapper
+public interface WarehouseProductMapStruct {
+
+    WarehouseProductMapStruct MAPSTRUCT = Mappers.getMapper(WarehouseProductMapStruct.class);
+
+    WarehouseProductDemandAnalysisPageBo demandAnalysisPageRequestToBo(WarehouseProductDemandAnalysisPageRequest request);
+
+    List<WarehouseProductDemandAnalysisResponse> demandAnalysisVoToResponse(List<WarehouseProductDemandAnalysisVo> records);
+
+    WarehouseProductDemandAnalysisEditorBo demandAnalysisEditorRequestToBo(WarehouseProductDemandAnalysisEditorRequest request);
+
+    WarehouseProductDemandAnalysisPageBo demandAnalysisExportRequestToBo(WarehouseProductDemandAnalysisExportRequest request);
+
+    List<WarehouseProductDemandAnalysisExport> demandAnalysisVoListToExportList(List<WarehouseProductDemandAnalysisVo> all);
+
+    WarehouseProductDemandAnalysisGeneratorBo demandAnalysisGeneratorRequestToBo(WarehouseProductDemandAnalysisGeneratorRequest request);
+
+    WarehouseProductDemandAnalysisHistoryBo demandAnalysisHistoryRequestToBo(WarehouseProductDemandAnalysisHistoryRequest request);
+
+    List<WarehouseProductDemandAnalysisHistoryResponse> demandAnalysisHistoryVoListToResponseList(List<WarehouseProductDemandAnalysisHistoryVo> records);
+
+    WarehouseProductDemandAnalysisHistoryPageBo demandAnalysisHistoryPageRequestToBo(WarehouseProductDemandAnalysisHistoryPageRequest request);
+
+    WarehouseProductDemandAnalysisHistoryPageBo demandAnalysisHistoryExportRequestToBo(WarehouseProductDemandAnalysisHistoryExportRequest request);
+}

+ 26 - 0
warehouse-admin-web/src/main/java/com/yr/warehouse/admin/web/product/request/WarehouseProductDemandAnalysisBatchImportRequest.java

@@ -0,0 +1,26 @@
+package com.yr.warehouse.admin.web.product.request;
+
+import jakarta.validation.constraints.NotBlank;
+import jakarta.validation.constraints.NotNull;
+import lombok.Data;
+
+import java.io.Serializable;
+
+/**
+ * 仓库商品批量导入请求参数
+ */
+@Data
+public class WarehouseProductDemandAnalysisBatchImportRequest implements Serializable {
+
+    /**
+     * 仓库id
+     */
+    @NotNull(message = "仓库id不能为空")
+    private Long warehouseId;
+    /**
+     * 文件相对地址
+     */
+    @NotBlank(message = "文件地址不能为空")
+    private String excelPath;
+
+}

+ 49 - 0
warehouse-admin-web/src/main/java/com/yr/warehouse/admin/web/product/request/WarehouseProductDemandAnalysisEditorRequest.java

@@ -0,0 +1,49 @@
+package com.yr.warehouse.admin.web.product.request;
+
+import jakarta.validation.constraints.NotNull;
+import lombok.Data;
+
+import java.io.Serial;
+import java.io.Serializable;
+import java.math.BigDecimal;
+
+/**
+ * 仓库商品需求分析编辑请求参数
+ */
+@Data
+public class WarehouseProductDemandAnalysisEditorRequest implements Serializable {
+
+    @Serial
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 仓库商品id
+     */
+    @NotNull(message = "仓库商品id不能为空")
+    private Long id;
+
+    /**
+     * 采购周期
+     * 人工填写 默认 7 天
+     */
+    private Long procurementCycle;
+
+    /**
+     * 起订量
+     * 人工填写 默认 0
+     */
+    private Long moq;
+
+    /**
+     * 安全库存数
+     * 人工填写 默认1
+     */
+    private Long inventoryWarningQuantity;
+
+    /**
+     * 预警系数
+     * 人工填写 默认1.0 - 预警系数必须大于等于: 1
+     */
+    private BigDecimal warningCoefficient;
+
+}

+ 39 - 0
warehouse-admin-web/src/main/java/com/yr/warehouse/admin/web/product/request/WarehouseProductDemandAnalysisExportRequest.java

@@ -0,0 +1,39 @@
+package com.yr.warehouse.admin.web.product.request;
+
+import jakarta.validation.constraints.NotNull;
+import lombok.Data;
+
+import java.io.Serial;
+import java.io.Serializable;
+import java.time.LocalDate;
+
+/**
+ * 仓库商品需求分析导出请求参数
+ */
+@Data
+public class WarehouseProductDemandAnalysisExportRequest implements Serializable {
+
+    @Serial
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 仓库id
+     */
+    @NotNull(message = "仓库id不能为空")
+    private Long warehouseId;
+
+    /**
+     * 状态: 安全: SAFETY 预警: WARNING 危险: DANGER
+     */
+    private String status;
+
+    /**
+     * 开始统计时间
+     */
+    private LocalDate beginStatisticsDate;
+
+    /**
+     * 结束统计时间
+     */
+    private LocalDate endStatisticsDate;
+}

+ 59 - 0
warehouse-admin-web/src/main/java/com/yr/warehouse/admin/web/product/request/WarehouseProductDemandAnalysisGeneratorRequest.java

@@ -0,0 +1,59 @@
+package com.yr.warehouse.admin.web.product.request;
+
+import jakarta.validation.constraints.NotNull;
+import lombok.Data;
+
+import java.io.Serial;
+import java.io.Serializable;
+import java.time.LocalDate;
+
+/**
+ * 仓库商品需求分析导出请求参数
+ */
+@Data
+public class WarehouseProductDemandAnalysisGeneratorRequest implements Serializable {
+
+    @Serial
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 运营商id
+     */
+    @NotNull(message = "运营商id不能为空")
+    private Long operatorId;
+
+    /**
+     * 运营商名称
+     */
+    @NotNull(message = "运营商名称不能为空")
+    private String operatorName;
+
+    /**
+     * 仓库id
+     */
+    @NotNull(message = "仓库id不能为空")
+    private Long warehouseId;
+
+    /**
+     * 仓库名称
+     */
+    @NotNull(message = "仓库名称不能为空")
+    private String warehouseName;
+
+    /**
+     * 开始统计时间
+     */
+    @NotNull(message = "开始统计时间不能为空")
+    private LocalDate beginStatisticsDate;
+
+    /**
+     * 结束统计时间
+     */
+    @NotNull(message = "结束统计时间不能为空")
+    private LocalDate endStatisticsDate;
+
+    /**
+     * 备注
+     */
+    private String remark;
+}

+ 47 - 0
warehouse-admin-web/src/main/java/com/yr/warehouse/admin/web/product/request/WarehouseProductDemandAnalysisHistoryExportRequest.java

@@ -0,0 +1,47 @@
+package com.yr.warehouse.admin.web.product.request;
+
+import lombok.Data;
+
+import java.io.Serial;
+import java.io.Serializable;
+
+/**
+ * 仓库商品需求分析导出查询请求参数
+ */
+@Data
+public class WarehouseProductDemandAnalysisHistoryExportRequest implements Serializable {
+
+    @Serial
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 历史id
+     */
+    private Long historyId;
+
+    /**
+     * 商品名称
+     */
+    private String goodsName;
+
+    /**
+     * 状态: 安全: SAFETY 预警: WARNING 危险: DANGER
+     */
+    private String status;
+
+    /**
+     * 排序字段
+     * id 默认 id desc
+     * moq 起订量
+     * weeklySalesVolume 周销售量(个)
+     * weeklySalesVolumeUnits 周销售量(件)
+     * upShelfNum 上架数
+     *
+     */
+    private String sort;
+
+    /**
+     * 排序方式 asc: 升序 desc: 降序
+     */
+    private String sortType;
+}

+ 53 - 0
warehouse-admin-web/src/main/java/com/yr/warehouse/admin/web/product/request/WarehouseProductDemandAnalysisHistoryPageRequest.java

@@ -0,0 +1,53 @@
+package com.yr.warehouse.admin.web.product.request;
+
+import com.yr.bluecat.common.entity.request.PageRequest;
+import jakarta.validation.constraints.NotNull;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+import java.io.Serial;
+import java.io.Serializable;
+import java.time.LocalDate;
+
+/**
+ * 仓库商品需求分析分页查询请求参数
+ */
+@EqualsAndHashCode(callSuper = true)
+@Data
+public class WarehouseProductDemandAnalysisHistoryPageRequest extends PageRequest implements Serializable {
+
+    @Serial
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 历史id
+     */
+    @NotNull(message = "历史id不能为空")
+    private Long historyId;
+
+    /**
+     * 商品名称
+     */
+    private String goodsName;
+
+    /**
+     * 状态: 安全: SAFETY 预警: WARNING 危险: DANGER
+     */
+    private String status;
+
+    /**
+     * 排序字段
+     * id 默认 id desc
+     * moq 起订量
+     * weeklySalesVolume 周销售量(个)
+     * weeklySalesVolumeUnits 周销售量(件)
+     * upShelfNum 上架数
+     *
+     */
+    private String sort;
+
+    /**
+     * 排序方式 asc: 升序 desc: 降序
+     */
+    private String sortType;
+}

+ 31 - 0
warehouse-admin-web/src/main/java/com/yr/warehouse/admin/web/product/request/WarehouseProductDemandAnalysisHistoryRequest.java

@@ -0,0 +1,31 @@
+package com.yr.warehouse.admin.web.product.request;
+
+import com.yr.bluecat.common.entity.request.PageRequest;
+import jakarta.validation.constraints.NotNull;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+import java.io.Serial;
+import java.io.Serializable;
+
+/**
+ * 仓库商品需求分析历史查询请求参数
+ */
+@EqualsAndHashCode(callSuper = true)
+@Data
+public class WarehouseProductDemandAnalysisHistoryRequest extends PageRequest implements Serializable {
+
+    @Serial
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 运营商id
+     */
+    public Long operatorId;
+
+    /**
+     * 仓库id
+     */
+    private Long warehouseId;
+
+}

+ 62 - 0
warehouse-admin-web/src/main/java/com/yr/warehouse/admin/web/product/request/WarehouseProductDemandAnalysisPageRequest.java

@@ -0,0 +1,62 @@
+package com.yr.warehouse.admin.web.product.request;
+
+import com.yr.bluecat.common.entity.request.PageRequest;
+import jakarta.validation.constraints.NotNull;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+import java.io.Serial;
+import java.io.Serializable;
+import java.time.LocalDate;
+
+/**
+ * 仓库商品需求分析分页查询请求参数
+ */
+@EqualsAndHashCode(callSuper = true)
+@Data
+public class WarehouseProductDemandAnalysisPageRequest extends PageRequest implements Serializable {
+
+    @Serial
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 仓库id
+     */
+    private Long warehouseId;
+
+    /**
+     * 商品名称
+     */
+    private String goodsName;
+
+    /**
+     * 状态: 安全: SAFETY 预警: WARNING 危险: DANGER
+     */
+    private String status;
+
+    /**
+     * 开始统计时间
+     */
+    private LocalDate beginStatisticsDate;
+
+    /**
+     * 结束统计时间
+     */
+    private LocalDate endStatisticsDate;
+
+    /**
+     * 排序字段
+     * id 默认 id desc
+     * moq 起订量
+     * weeklySalesVolume 周销售量(个)
+     * weeklySalesVolumeUnits 周销售量(件)
+     * upShelfNum 上架数
+     *
+     */
+    private String sort;
+
+    /**
+     * 排序方式 asc: 升序 desc: 降序
+     */
+    private String sortType;
+}

+ 76 - 0
warehouse-admin-web/src/main/java/com/yr/warehouse/admin/web/product/response/WarehouseProductDemandAnalysisHistoryResponse.java

@@ -0,0 +1,76 @@
+package com.yr.warehouse.admin.web.product.response;
+
+import lombok.Data;
+
+import java.io.Serial;
+import java.io.Serializable;
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+
+/**
+ * 仓库商品需求分析历史生成记录列表
+ */
+@Data
+public class WarehouseProductDemandAnalysisHistoryResponse implements Serializable {
+
+    @Serial
+    private static final long serialVersionUID = 1L;
+
+    private Long id;
+
+    /**
+     * 运营商id
+     */
+    private Long operatorId;
+
+    /**
+     * 运营商链
+     */
+    private String operatorChain;
+
+    /**
+     * 运营商名称
+     */
+    private String operatorName;
+
+    /**
+     * 仓库id
+     */
+    private Long warehouseId;
+
+    /**
+     * 仓库名称
+     */
+    private String warehouseName;
+
+    /**
+     * 开始统计时间
+     */
+    private LocalDate beginStatisticsDate;
+
+    /**
+     * 结束统计时间
+     */
+    private LocalDate endStatisticsDate;
+
+    /**
+     * 备注
+     */
+    private String remark;
+
+    /**
+     * 创建用户名称
+     */
+    private String createUserName;
+
+    /**
+     * 创建用户id
+     */
+    private Long createUserId;
+
+    /**
+     * 创建时间
+     */
+    private LocalDateTime createTime;
+
+}

+ 159 - 0
warehouse-admin-web/src/main/java/com/yr/warehouse/admin/web/product/response/WarehouseProductDemandAnalysisResponse.java

@@ -0,0 +1,159 @@
+package com.yr.warehouse.admin.web.product.response;
+
+import lombok.Data;
+
+import java.io.Serial;
+import java.io.Serializable;
+import java.math.BigDecimal;
+import java.time.LocalDate;
+
+/**
+ * 仓库商品需求分析响应参数
+ */
+@Data
+public class WarehouseProductDemandAnalysisResponse implements Serializable {
+
+    @Serial
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 仓库商品id
+     */
+    private Long id;
+
+    /**
+     * 商品编号
+     */
+    private String goodsCode;
+
+    /**
+     * 商品名称
+     */
+    private String goodsName;
+
+    /**
+     * 规格
+     */
+    private Integer unboxingPriority;
+
+    /**
+     * 保质期(天)
+     */
+    private Integer shelfLife;
+
+    /**
+     * 采购周期
+     * 人工填写 默认 7 天
+     */
+    private Long procurementCycle;
+
+    /**
+     * 起订量
+     * 人工填写 默认 0
+     */
+    private Long moq;
+
+    /**
+     * 周销售量(个)
+     */
+    private Long weeklySalesVolume;
+
+    /**
+     * 周销售量(件)
+     * 周销售量(个) / 规格, 保留两位小数
+     */
+    private BigDecimal weeklySalesVolumeUnits;
+
+    /**
+     * 安全库存数
+     * 人工填写 默认1
+     */
+    private Long inventoryWarningQuantity;
+
+    /**
+     * 预警系数
+     * 人工填写 默认1.0 - 预警系数必须大于等于: 1
+     */
+    private BigDecimal warningCoefficient;
+
+    /**
+     * 预警值
+     * 安全库存数 * 预警系数 整数 向上取整
+     */
+    private Long warningQuantity;
+
+    /**
+     * 上机库存
+     * 仓库绑定的所有设备在统计日期内该商品的所有数量 ? 实际设备库存
+     */
+    private Long machineInventory;
+
+    /**
+     * 分仓需求
+     * 分仓批发数量(件) 出库管理的批发类型
+     */
+    private BigDecimal subWarehouseRequirements;
+
+    /**
+     * 需求量
+     * 周销售量(件) / 7 * (采购周期 + 7) * 预警系数 + 分仓需求 / 7 * (采购周期 + 7)
+     * 保留两位小数
+     */
+    private BigDecimal warehouseRequirements;
+
+    /**
+     * 结余库存
+     * 该商品在仓库里的库存数(件)
+     */
+    private BigDecimal surplusInventory;
+
+    /**
+     * 状态
+     * 安全(结余库存 >= 安全库存 && 结余库存 >= 预警值) SAFETY
+     * 预警(结余库存 >= 安全库存 && 预警值 > 结余库存) WARNING
+     * 危险(安全库存 > 结余库存 && 预警值 > 结余库存) DANGER
+     */
+    private String status;
+
+    /**
+     * 预计消耗天数
+     * (结余库存 + 上机库存) / 周销量(件) * 7 四舍五入取整
+     * 例如: (200 + 100) / 20 * 7 = 105
+     */
+    private BigDecimal expectedConsumptionDays;
+
+    /**
+     * 预计销售时间
+     * (结余库存 + 需求量) / 周销量(件) * 7 当前日期加上计算天数
+     * 例如: (200 + 300) / 20 * 7 = 175
+     * 2026-02-26 + 175 = 2026-08-20
+     */
+    private LocalDate expectedSaleTime;
+
+    /**
+     * 期望到货时间
+     * 当前日期 + 预计消耗天数
+     * 例如: 2026-02-26 + 105 = 2026-06-11
+     */
+    private LocalDate expectedArrivalTime;
+
+    /**
+     * 售卖天数
+     * (结余库存 - 分仓需求) / 周销量(件) * 7 四舍五入取整
+     */
+    private Long saleDays;
+
+    /**
+     * 上架数
+     * 该商品在设备里的上架设备数, 单台设备算1个上架数
+     * 只查询已上机的设备货道存在该商品的设备数
+     */
+    private Long upShelfNum;
+
+    /**
+     * 采购需求
+     * 需求量 (保留两位小数的原数据) - 结余库存
+     */
+    private BigDecimal procurementDemand;
+
+}