浏览代码

[update] 生成统计结果逻辑开发

miajio 3 周之前
父节点
当前提交
55e2b7ff37
共有 23 个文件被更改,包括 700 次插入7 次删除
  1. 13 0
      warehouse-admin-component/src/main/java/com/yr/warehouse/admin/component/areastaff/AreaStaffComponent.java
  2. 16 0
      warehouse-admin-data/src/main/java/com/yr/warehouse/admin/driver/bo/DriverIntervalCargoDamageGeneratorBo.java
  3. 13 1
      warehouse-admin-data/src/main/java/com/yr/warehouse/admin/driver/data/DriverGoodsLossIntervalDetail.java
  4. 8 0
      warehouse-admin-data/src/main/java/com/yr/warehouse/admin/driver/mapper/DriverEquipmentLossRecordMapper.java
  5. 18 0
      warehouse-admin-data/src/main/java/com/yr/warehouse/admin/driver/mapper/DriverGoodsLossIntervalDetailMapper.java
  6. 7 0
      warehouse-admin-data/src/main/java/com/yr/warehouse/admin/driver/mapper/DriverGoodsLossIntervalMainMapper.java
  7. 7 0
      warehouse-admin-data/src/main/java/com/yr/warehouse/admin/driver/mapper/DriverGoodsLossRecordMapper.java
  8. 22 2
      warehouse-admin-data/src/main/java/com/yr/warehouse/admin/driver/mapper/DriverOnRouteAccountRecordMainMapper.java
  9. 16 0
      warehouse-admin-data/src/main/java/com/yr/warehouse/admin/driver/mapper/EquipmentLossIntervalDetailMapper.java
  10. 20 0
      warehouse-admin-data/src/main/java/com/yr/warehouse/admin/driver/menu/DriverGoodsLossIntervalStockTakingType.java
  11. 34 0
      warehouse-admin-data/src/main/java/com/yr/warehouse/admin/driver/vo/DriverGoodsLossIntervalVo.java
  12. 11 1
      warehouse-admin-data/src/main/java/com/yr/warehouse/admin/driver/vo/DriverIntervalCargoDamageDetailVo.java
  13. 11 0
      warehouse-admin-data/src/main/resources/mapper/driver/DriverEquipmentLossRecordMapper.xml
  14. 31 1
      warehouse-admin-data/src/main/resources/mapper/driver/DriverGoodsLossIntervalDetailMapper.xml
  15. 5 0
      warehouse-admin-data/src/main/resources/mapper/driver/DriverGoodsLossIntervalMainMapper.xml
  16. 10 0
      warehouse-admin-data/src/main/resources/mapper/driver/DriverGoodsLossRecordMapper.xml
  17. 34 0
      warehouse-admin-data/src/main/resources/mapper/driver/DriverOnRouteAccountRecordMainMapper.xml
  18. 21 0
      warehouse-admin-data/src/main/resources/mapper/driver/EquipmentLossIntervalDetailMapper.xml
  19. 15 0
      warehouse-admin-server/src/main/java/com/yr/warehouse/admin/service/driver/DriverGoodsLossIntervalService.java
  20. 373 0
      warehouse-admin-server/src/main/java/com/yr/warehouse/admin/service/driver/impl/DriverGoodsLossIntervalServiceImpl.java
  21. 4 2
      warehouse-admin-web/src/main/java/com/yr/warehouse/admin/web/driver/controller/DriverIntervalCargoDamageController.java
  22. 6 0
      warehouse-admin-web/src/main/java/com/yr/warehouse/admin/web/driver/export/DriverIntervalCargoDamageDetailExport.java
  23. 5 0
      warehouse-admin-web/src/main/java/com/yr/warehouse/admin/web/driver/response/DriverIntervalCargoDamageDetailResponse.java

+ 13 - 0
warehouse-admin-component/src/main/java/com/yr/warehouse/admin/component/areastaff/AreaStaffComponent.java

@@ -71,4 +71,17 @@ public class AreaStaffComponent {
         return areaStaffApi.searchByStaffIds(request).getData();
     }
 
+    /**
+     * 根据运营商id查询区域员工信息
+     *
+     * @param operatorId 运营商id
+     * @return 区域员工信息
+     */
+    public List<AreaStaffResponse> searchByOperatorId(Long operatorId) {
+        AreaStaffSearchRequest request = new AreaStaffSearchRequest();
+        request.setAppId(apolloConfigEvent.getAppId());
+        request.setOperatorId(operatorId);
+        return areaStaffApi.searchByStaffIds(request).getData();
+    }
+
 }

+ 16 - 0
warehouse-admin-data/src/main/java/com/yr/warehouse/admin/driver/bo/DriverIntervalCargoDamageGeneratorBo.java

@@ -6,6 +6,7 @@ import lombok.EqualsAndHashCode;
 
 import java.io.Serial;
 import java.io.Serializable;
+import java.time.LocalDate;
 import java.time.LocalDateTime;
 import java.util.List;
 
@@ -25,6 +26,21 @@ public class DriverIntervalCargoDamageGeneratorBo extends BaseBo implements Seri
     private Long operatorId;
 
     /**
+     * 统计类型 SPOT_CHECK 抽查(指定补货员) REGULAR 定期(全部补货员)
+     */
+    private String stockTakingType;
+
+    /**
+     * 区间统计开始时间
+     */
+    private LocalDate beginStatDate;
+
+    /**
+     * 区间统计结束时间
+     */
+    private LocalDate endStatDate;
+
+    /**
      * 区间开始时间
      */
     private LocalDateTime intervalStartTime;

+ 13 - 1
warehouse-admin-data/src/main/java/com/yr/warehouse/admin/driver/data/DriverGoodsLossIntervalDetail.java

@@ -85,12 +85,24 @@ public class DriverGoodsLossIntervalDetail implements Serializable {
     private Long returnWarehouseNum;
 
     /**
-     * 剩余未补货数
+     * 剩余未补货数 - 理论计算值
      */
     @TableField("remainingUnReplenishedNum")
     private Long remainingUnReplenishedNum;
 
     /**
+     * 在途库存数 - 实际流水值
+     */
+    @TableField("onRouteStock")
+    private Long onRouteStock;
+
+    /**
+     * 是否使用整件核实数 NO 未使用 YES 使用
+     */
+    @TableField("useVerifyNum")
+    private String useVerifyNum;
+
+    /**
      * 整件核实数
      */
     @TableField("wholeVerifyNum")

+ 8 - 0
warehouse-admin-data/src/main/java/com/yr/warehouse/admin/driver/mapper/DriverEquipmentLossRecordMapper.java

@@ -1,5 +1,6 @@
 package com.yr.warehouse.admin.driver.mapper;
 
+import com.yr.warehouse.admin.driver.bo.DriverIntervalCargoDamageGeneratorBo;
 import com.yr.warehouse.admin.driver.data.DriverEquipmentLossRecord;
 import com.baomidou.mybatisplus.core.mapper.BaseMapper;
 import org.apache.ibatis.annotations.Param;
@@ -29,4 +30,11 @@ public interface DriverEquipmentLossRecordMapper extends BaseMapper<DriverEquipm
      * @return
      */
     List<DriverEquipmentLossRecord> searchByStatDate(@Param("statDate") LocalDate statDate);
+
+    /**
+     * 按参数查询
+     * @param bo 查询参数
+     * @return 查询结果
+     */
+    List<DriverEquipmentLossRecord> searchGeneratorParam(@Param("bo") DriverIntervalCargoDamageGeneratorBo bo);
 }

+ 18 - 0
warehouse-admin-data/src/main/java/com/yr/warehouse/admin/driver/mapper/DriverGoodsLossIntervalDetailMapper.java

@@ -7,6 +7,8 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper;
 import com.yr.warehouse.admin.driver.vo.DriverIntervalCargoDamageDetailVo;
 import org.apache.ibatis.annotations.Param;
 
+import java.util.List;
+
 /**
  * <p>
  * 司机货损区间统计明细表 Mapper 接口
@@ -25,4 +27,20 @@ public interface DriverGoodsLossIntervalDetailMapper extends BaseMapper<DriverGo
      * @return 列表
      */
     Page<DriverIntervalCargoDamageDetailVo> searchForPage(@Param("page") Page<DriverIntervalCargoDamageDetailVo> page, @Param("bo") DriverIntervalCargoDamageDetailPageBo bo);
+
+    /**
+     * 批量写入区间统计记录
+     * @param driverGoodsLossIntervalDetails 区间统计记录
+     */
+    void insertBatch(@Param("goodsLossMonthlyMainId") Long goodsLossMonthlyMainId, @Param("driverGoodsLossIntervalDetails") List<DriverGoodsLossIntervalDetail> driverGoodsLossIntervalDetails);
+
+    /**
+     * 根据区间统计记录主键查询区间统计记录
+     * @param goodsLossMonthlyMainId 区间统计记录主键
+     * @param areaStaffIds 区域员工ids
+     * @return 区间统计记录
+     */
+    List<DriverGoodsLossIntervalDetail> selectByMainIdAndAreaStaffId(@Param("goodsLossMonthlyMainId") Long goodsLossMonthlyMainId, @Param("areaStaffIds") List<Long> areaStaffIds);
+
+
 }

+ 7 - 0
warehouse-admin-data/src/main/java/com/yr/warehouse/admin/driver/mapper/DriverGoodsLossIntervalMainMapper.java

@@ -34,4 +34,11 @@ public interface DriverGoodsLossIntervalMainMapper extends BaseMapper<DriverGood
      * @return
      */
     Page<DriverIntervalCargoDamageVo> searchForPage(@Param("page") Page<DriverIntervalCargoDamageVo> page, @Param("bo") DriverIntervalCargoDamagePageBo bo);
+
+    /**
+     * 查询指定运营商最后生成统计记录
+     * @param operatorId 运营商id
+     * @return 司机货损统计记录
+     */
+    DriverGoodsLossIntervalMain queryLastByOperatorId(@Param("operatorId") Long operatorId);
 }

+ 7 - 0
warehouse-admin-data/src/main/java/com/yr/warehouse/admin/driver/mapper/DriverGoodsLossRecordMapper.java

@@ -2,6 +2,7 @@ package com.yr.warehouse.admin.driver.mapper;
 
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.yr.warehouse.admin.driver.bo.DriverDailyCargoDamagePageBo;
+import com.yr.warehouse.admin.driver.bo.DriverIntervalCargoDamageGeneratorBo;
 import com.yr.warehouse.admin.driver.data.DriverGoodsLossRecord;
 import com.baomidou.mybatisplus.core.mapper.BaseMapper;
 import com.yr.warehouse.admin.driver.vo.DriverGoodsLossRecordVo;
@@ -40,4 +41,10 @@ public interface DriverGoodsLossRecordMapper extends BaseMapper<DriverGoodsLossR
      * @return 司机货损记录
      */
     Page<DriverGoodsLossRecordVo> searchForPage(@Param("page") Page<DriverGoodsLossRecordVo> page, @Param("bo") DriverDailyCargoDamagePageBo bo);
+
+    /**
+     * 查询司机货损统计参数
+     * @param bo 查询参数
+     */
+    List<DriverGoodsLossRecord> searchGeneratorParam(@Param("bo") DriverIntervalCargoDamageGeneratorBo bo);
 }

+ 22 - 2
warehouse-admin-data/src/main/java/com/yr/warehouse/admin/driver/mapper/DriverOnRouteAccountRecordMainMapper.java

@@ -1,21 +1,24 @@
 package com.yr.warehouse.admin.driver.mapper;
 
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.yr.warehouse.admin.common.bo.BaseBo;
 import com.yr.warehouse.admin.common.bo.BaseIdBo;
 import com.yr.warehouse.admin.driver.bo.DriverIntervalRouteAccountRecordCreateBo;
 import com.yr.warehouse.admin.driver.bo.DriverIntervalRouteAccountRecordEditorBo;
 import com.yr.warehouse.admin.driver.bo.DriverRouteAccountRecordPageBo;
 import com.yr.warehouse.admin.driver.data.DriverOnRouteAccountRecordMain;
-import com.baomidou.mybatisplus.core.mapper.BaseMapper;
 import com.yr.warehouse.admin.driver.vo.DriverRouteAccountRecordMainVo;
 import org.apache.ibatis.annotations.Param;
 
+import java.util.List;
+
 /**
  * <p>
  * 司机在途核算记录主表 Mapper 接口
  * </p>
  *
- * @author 
+ * @author
  * @since 2025-12-03 15:26:37
  */
 public interface DriverOnRouteAccountRecordMainMapper extends BaseMapper<DriverOnRouteAccountRecordMain> {
@@ -49,4 +52,21 @@ public interface DriverOnRouteAccountRecordMainMapper extends BaseMapper<DriverO
      * @param bo 编辑参数
      */
     void edit(@Param("bo") DriverIntervalRouteAccountRecordEditorBo bo);
+
+    /**
+     * 查询未核算的司机在途核算记录
+     *
+     * @param areaStaffIds 区域员工id
+     * @return 结果
+     */
+    List<DriverOnRouteAccountRecordMain> selectUnVerified(@Param("areaStaffIds") List<Long> areaStaffIds);
+
+    /**
+     * 批量绑定司机在途核算记录
+     *
+     * @param bo 用户参数
+     * @param ids 使用的司机在途核算记录id
+     * @param goodsLossMonthlyMainId 货损区间统计主表id
+     */
+    void batchBind(@Param("bo") BaseBo bo, @Param("ids") List<Long> ids, @Param("goodsLossMonthlyMainId") Long goodsLossMonthlyMainId);
 }

+ 16 - 0
warehouse-admin-data/src/main/java/com/yr/warehouse/admin/driver/mapper/EquipmentLossIntervalDetailMapper.java

@@ -2,6 +2,9 @@ package com.yr.warehouse.admin.driver.mapper;
 
 import com.yr.warehouse.admin.driver.data.EquipmentLossIntervalDetail;
 import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import org.apache.ibatis.annotations.Param;
+
+import java.util.List;
 
 /**
  * <p>
@@ -13,4 +16,17 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper;
  */
 public interface EquipmentLossIntervalDetailMapper extends BaseMapper<EquipmentLossIntervalDetail> {
 
+    /**
+     * 批量插入
+     * @param equipmentLossIntervalDetails 设备货损区间统计明细
+     */
+    void insertBatch(@Param("goodsLossMonthlyMainId") Long goodsLossMonthlyMainId, @Param("equipmentLossIntervalDetails") List<EquipmentLossIntervalDetail> equipmentLossIntervalDetails);
+
+    /**
+     * 根据设备货损区间统计主表id查询
+     * @param goodsLossMonthlyMainId 设备货损区间统计主表id
+     * @param areaStaffIds 区域员工id
+     * @return 设备货损区间统计明细
+     */
+    List<EquipmentLossIntervalDetail> selectByMainIdAndAreaStaffId(@Param("goodsLossMonthlyMainId") Long goodsLossMonthlyMainId, @Param("areaStaffIds") List<Long> areaStaffIds);
 }

+ 20 - 0
warehouse-admin-data/src/main/java/com/yr/warehouse/admin/driver/menu/DriverGoodsLossIntervalStockTakingType.java

@@ -0,0 +1,20 @@
+package com.yr.warehouse.admin.driver.menu;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+
+/**
+ * 区间货损库存盘点类型
+ */
+@AllArgsConstructor
+@Getter
+public enum DriverGoodsLossIntervalStockTakingType {
+
+    SPOT_CHECK("抽查"),
+    REGULAR("定期");
+
+    private final String desc;
+
+
+
+}

+ 34 - 0
warehouse-admin-data/src/main/java/com/yr/warehouse/admin/driver/vo/DriverGoodsLossIntervalVo.java

@@ -0,0 +1,34 @@
+package com.yr.warehouse.admin.driver.vo;
+
+import com.yr.warehouse.admin.driver.data.DriverGoodsLossIntervalDetail;
+import com.yr.warehouse.admin.driver.data.EquipmentLossIntervalDetail;
+import lombok.Data;
+
+import java.io.Serial;
+import java.io.Serializable;
+
+/**
+ * 司机货损区间统计视图
+ */
+@Data
+public class DriverGoodsLossIntervalVo implements Serializable {
+
+    @Serial
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 司机货损区间统计数据
+     */
+    private DriverGoodsLossIntervalDetail driverGoodsLossIntervalDetail;
+
+    /**
+     * 设备货损区间统计数据
+     */
+    private EquipmentLossIntervalDetail equipmentLossIntervalDetail;
+
+    /**
+     * 使用司机货损区间核算id
+     */
+    private Long useDriverOnRouteAccountRecordMainId;
+
+}

+ 11 - 1
warehouse-admin-data/src/main/java/com/yr/warehouse/admin/driver/vo/DriverIntervalCargoDamageDetailVo.java

@@ -61,11 +61,21 @@ public class DriverIntervalCargoDamageDetailVo implements AreaStaffIdFace, Seria
     private Long returnWarehouseNum;
 
     /**
-     * 本次未补货数
+     * 本次未补货数 - 理论计算值
      */
     private Long remainingUnReplenishedNum;
 
     /**
+     * 本次在途库存数 - 实际流水值
+     */
+    private Long onRouteStock;
+
+    /**
+     * 是否使用整件核实数 NO 未使用 YES 使用
+     */
+    private String useVerifyNum;
+
+    /**
      * 整件核实数
      */
     private Long wholeVerifyNum;

+ 11 - 0
warehouse-admin-data/src/main/resources/mapper/driver/DriverEquipmentLossRecordMapper.xml

@@ -41,5 +41,16 @@
         <include refid="Base_Column_List"/>
         from yr_driver_equipment_loss_record where statDate = #{statDate}
     </select>
+    <select id="searchGeneratorParam" resultType="com.yr.warehouse.admin.driver.data.DriverEquipmentLossRecord"
+            parameterType="com.yr.warehouse.admin.driver.bo.DriverIntervalCargoDamageGeneratorBo">
+        select
+            <include refid="Base_Column_List" />
+        from yr_driver_equipment_loss_record
+        where operatorId = #{bo.operatorId} and statDate >= #{bo.beginStatDate} and #{bo.endStatDate} >= statDate
+        <foreach collection="bo.areaStaffIds" item="areaStaffId" open="and areaStaffId in (" separator="," close=")">
+            #{areaStaffId}
+        </foreach>
+        order by id desc
+    </select>
 
 </mapper>

+ 31 - 1
warehouse-admin-data/src/main/resources/mapper/driver/DriverGoodsLossIntervalDetailMapper.xml

@@ -15,6 +15,8 @@
         <result column="replenishNum" property="replenishNum" />
         <result column="returnWarehouseNum" property="returnWarehouseNum" />
         <result column="remainingUnReplenishedNum" property="remainingUnReplenishedNum" />
+        <result column="onRouteStock" property="onRouteStock" />
+        <result column="useVerifyNum" property="useVerifyNum" />
         <result column="wholeVerifyNum" property="wholeVerifyNum" />
         <result column="profitLossNum" property="profitLossNum" />
         <result column="createTime" property="createTime" />
@@ -22,8 +24,22 @@
 
     <!-- 通用查询结果列 -->
     <sql id="Base_Column_List">
-        id, goodsLossMonthlyMainId, areaStaffId, lastRemainingOnRouteStock, pickingOrderCreateNum, wholeOrderCreateNum, unshippedCancelNum, shippedCancelNum, replenishNum, returnWarehouseNum, remainingUnReplenishedNum, wholeVerifyNum, profitLossNum, createTime
+        id, goodsLossMonthlyMainId, areaStaffId, lastRemainingOnRouteStock, pickingOrderCreateNum, wholeOrderCreateNum, unshippedCancelNum, shippedCancelNum, replenishNum, returnWarehouseNum, remainingUnReplenishedNum, onRouteStock, useVerifyNum, wholeVerifyNum, profitLossNum, createTime
     </sql>
+    <insert id="insertBatch">
+        insert into yr_driver_goods_loss_interval_detail
+            (goodsLossMonthlyMainId, areaStaffId, lastRemainingOnRouteStock,
+             pickingOrderCreateNum, wholeOrderCreateNum, unshippedCancelNum,
+             shippedCancelNum, replenishNum, returnWarehouseNum,
+             remainingUnReplenishedNum, onRouteStock, useVerifyNum, wholeVerifyNum, profitLossNum)
+        values
+        <foreach item="item" collection="driverGoodsLossIntervalDetails" separator=",">
+            (#{goodsLossMonthlyMainId}, #{item.areaStaffId}, #{item.lastRemainingOnRouteStock},
+            #{item.pickingOrderCreateNum}, #{item.wholeOrderCreateNum}, #{item.unshippedCancelNum},
+            #{item.shippedCancelNum}, #{item.replenishNum}, #{item.returnWarehouseNum},
+            #{item.remainingUnReplenishedNum}, #{item.onRouteStock}, #{item.useVerifyNum}, #{item.wholeVerifyNum}, #{item.profitLossNum})
+        </foreach>
+    </insert>
     <select id="searchForPage" resultType="com.yr.warehouse.admin.driver.vo.DriverIntervalCargoDamageDetailVo">
         select
         dglid.areaStaffId as areaStaffId,
@@ -35,6 +51,8 @@
         dglid.replenishNum as replenishNum,
         dglid.returnWarehouseNum as returnWarehouseNum,
         dglid.remainingUnReplenishedNum as remainingUnReplenishedNum,
+        dglid.onRouteStock as onRouteStock,
+        dglid.useVerifyNum as useVerifyNum,
         dglid.wholeVerifyNum as wholeVerifyNum,
         dglid.profitLossNum as profitLossNum,
         elid.lastRemainingEquipmentStock as lastRemainingEquipmentStock,
@@ -57,5 +75,17 @@
         </if>
         order by dglid.areaStaffId
     </select>
+    <select id="selectByMainIdAndAreaStaffId" resultType="com.yr.warehouse.admin.driver.data.DriverGoodsLossIntervalDetail">
+        select
+        <include refid="Base_Column_List"/>
+        from yr_driver_goods_loss_interval_detail
+        where goodsLossMonthlyMainId = #{goodsLossMonthlyMainId}
+        <if test="areaStaffIds != null and areaStaffIds.size > 0">
+            and areaStaffId in
+            <foreach item="item" collection="areaStaffIds" separator="," open="(" close=")" index="">
+                #{item}
+            </foreach>
+        </if>
+    </select>
 
 </mapper>

+ 5 - 0
warehouse-admin-data/src/main/resources/mapper/driver/DriverGoodsLossIntervalMainMapper.xml

@@ -78,5 +78,10 @@
         </where>
 
     </select>
+    <select id="queryLastByOperatorId" resultType="com.yr.warehouse.admin.driver.data.DriverGoodsLossIntervalMain"
+            parameterType="java.lang.Long">
+        select * from yr_driver_goods_loss_interval_main where operatorId = #{operatorId} and stockTakingType = 'REGULAR'
+        order by intervalEndTime desc limit 1
+    </select>
 
 </mapper>

+ 10 - 0
warehouse-admin-data/src/main/resources/mapper/driver/DriverGoodsLossRecordMapper.xml

@@ -86,5 +86,15 @@
         </where>
         order by dglr.operatorId, dglr.areaStaffId desc
     </select>
+    <select id="searchGeneratorParam"
+            parameterType="com.yr.warehouse.admin.driver.bo.DriverIntervalCargoDamageGeneratorBo"
+            resultType="com.yr.warehouse.admin.driver.data.DriverGoodsLossRecord">
+        select <include refid="Base_Column_List" /> from yr_driver_goods_loss_record
+        where operatorId = #{bo.operatorId} and statDate >= #{bo.beginStatDate} and #{bo.endStatDate} >= statDate
+        <foreach collection="bo.areaStaffIds" item="areaStaffId" open="and areaStaffId in (" separator="," close=")">
+            #{areaStaffId}
+        </foreach>
+        order by id desc
+    </select>
 
 </mapper>

+ 34 - 0
warehouse-admin-data/src/main/resources/mapper/driver/DriverOnRouteAccountRecordMainMapper.xml

@@ -26,6 +26,11 @@
     <sql id="Base_Column_List">
         id, operatorId, operatorChain, areaStaffId, warehouseId, statDate, goodsLossMonthlyMainId, statTotalNum, status, createTime, createUid, createName, modifyTime, modifyUid, modifyName, isDelete
     </sql>
+
+    <sql id="Base_As_Column_List">
+        ${column}.id, ${column}.operatorId, ${column}.operatorChain, ${column}.areaStaffId, ${column}.warehouseId, ${column}.statDate, ${column}.goodsLossMonthlyMainId, ${column}.statTotalNum, ${column}.status, ${column}.createTime, ${column}.createUid, ${column}.createName, ${column}.modifyTime, ${column}.modifyUid, ${column}.modifyName, ${column}.isDelete
+    </sql>
+
     <insert id="create"
             parameterType="com.yr.warehouse.admin.driver.bo.DriverIntervalRouteAccountRecordCreateBo" keyProperty="id" useGeneratedKeys="true">
         insert into yr_driver_on_route_account_record_main
@@ -40,6 +45,16 @@
             modifyName = #{bo.username}
         where id = #{bo.id}
     </update>
+    <update id="batchBind">
+        update yr_driver_on_route_account_record_main set goodsLossMonthlyMainId = #{goodsLossMonthlyMainId},
+                                                          modifyUid = #{bo.uid},
+                                                          modifyName = #{bo.username}
+        where
+        isDelete != 'DELETE' and id in
+        <foreach item="item" index="index" collection="ids" separator="," close=")">
+            #{item}
+        </foreach>
+    </update>
     <delete id="cancel"
             parameterType="com.yr.warehouse.admin.common.bo.BaseIdBo">
         update yr_driver_on_route_account_record_main set status = 'CANCEL', modifyUid = #{bo.uid}, modifyName = #{bo.username} where id = #{bo.id} and status = 'UN_VERIFIED' and isDelete = 'NORMAL'
@@ -81,5 +96,24 @@
         </if>
         order by warehouseId, areaStaffId desc
     </select>
+    <select id="selectUnVerified" resultType="com.yr.warehouse.admin.driver.data.DriverOnRouteAccountRecordMain" parameterType="java.util.List">
+        select
+        <include refid="Base_As_Column_List">
+            <property name="column" value="do1"/>
+        </include>
+        from yr_driver_on_route_account_record_main as do1
+        INNER JOIN (
+        SELECT areaStaffId, max(id) as lastId from yr_driver_on_route_account_record_main
+        where isDelete = 'NORMAL'
+         <if test="areaStaffIds != null and areaStaffIds.size > 0">
+         and areaStaffId in
+        <foreach collection="areaStaffIds" item="item" open="(" separator="," close=")">
+            #{item}
+        </foreach>
+         </if>
+        GROUP BY areaStaffId
+        ) as do2 ON do1.areaStaffId = do2.areaStaffId and do1.id = do2.lastId
+        WHERE do1.status = 'UN_VERIFIED' and do1.isDelete = 'NORMAL'
+    </select>
 
 </mapper>

+ 21 - 0
warehouse-admin-data/src/main/resources/mapper/driver/EquipmentLossIntervalDetailMapper.xml

@@ -20,5 +20,26 @@
     <sql id="Base_Column_List">
         id, goodsLossMonthlyMainId, areaStaffId, lastRemainingEquipmentStock, totalReplenishNum, equipmentSalesNum, theoreticalStockNum, actualStockNum, profitLossNum, createTime
     </sql>
+    <insert id="insertBatch">
+        insert into yr_equipment_loss_interval_detail
+        (goodsLossMonthlyMainId, areaStaffId, lastRemainingEquipmentStock,
+        totalReplenishNum, equipmentSalesNum, theoreticalStockNum,
+        actualStockNum, profitLossNum)
+        values
+        <foreach collection="equipmentLossIntervalDetails" item="item" separator=",">
+            (#{goodsLossMonthlyMainId}, #{item.areaStaffId}, #{item.lastRemainingEquipmentStock},
+            #{item.totalReplenishNum}, #{item.equipmentSalesNum}, #{item.theoreticalStockNum},
+            #{item.actualStockNum}, #{item.profitLossNum})
+        </foreach>
+    </insert>
+    <select id="selectByMainIdAndAreaStaffId" resultType="com.yr.warehouse.admin.driver.data.EquipmentLossIntervalDetail">
+        select <include refid="Base_Column_List" /> from yr_equipment_loss_interval_detail where goodsLossMonthlyMainId = #{goodsLossMonthlyMainId}
+        <if test="areaStaffIds != null and areaStaffIds.size > 0">
+            and areaStaffId in
+            <foreach collection="areaStaffIds" item="areaStaffId" open="(" separator="," close=")">
+                #{areaStaffId}
+            </foreach>
+        </if>
+    </select>
 
 </mapper>

+ 15 - 0
warehouse-admin-server/src/main/java/com/yr/warehouse/admin/service/driver/DriverGoodsLossIntervalService.java

@@ -0,0 +1,15 @@
+package com.yr.warehouse.admin.service.driver;
+
+import com.yr.warehouse.admin.driver.bo.DriverIntervalCargoDamageGeneratorBo;
+
+/**
+ * 司机区间货损服务接口
+ */
+public interface DriverGoodsLossIntervalService {
+    /**
+     * 生成司机区间货损
+     *
+     * @param bo 生成参数
+     */
+    void generator(DriverIntervalCargoDamageGeneratorBo bo);
+}

+ 373 - 0
warehouse-admin-server/src/main/java/com/yr/warehouse/admin/service/driver/impl/DriverGoodsLossIntervalServiceImpl.java

@@ -0,0 +1,373 @@
+package com.yr.warehouse.admin.service.driver.impl;
+
+import com.supplychain.api.response.areastaff.AreaStaffResponse;
+import com.yr.bluecat.common.entity.exception.MessageException;
+import com.yr.warehouse.admin.common.menu.BoolEnum;
+import com.yr.warehouse.admin.component.areastaff.AreaStaffComponent;
+import com.yr.warehouse.admin.component.auth.OperatorComponent;
+import com.yr.warehouse.admin.component.auth.vo.OrgOperatorVo;
+import com.yr.warehouse.admin.driver.bo.DriverIntervalCargoDamageGeneratorBo;
+import com.yr.warehouse.admin.driver.data.*;
+import com.yr.warehouse.admin.driver.mapper.*;
+import com.yr.warehouse.admin.driver.menu.DriverGoodsLossIntervalStockTakingType;
+import com.yr.warehouse.admin.driver.vo.DriverGoodsLossIntervalVo;
+import com.yr.warehouse.admin.service.driver.DriverGoodsLossIntervalService;
+import jakarta.annotation.Resource;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.support.TransactionTemplate;
+
+import java.util.*;
+import java.util.function.Function;
+import java.util.stream.Collectors;
+
+/**
+ * 司机区间货损服务接口实现
+ */
+@Service
+public class DriverGoodsLossIntervalServiceImpl implements DriverGoodsLossIntervalService {
+    @Resource
+    private AreaStaffComponent areaStaffComponent;
+
+    @Resource
+    private OperatorComponent operatorComponent;
+
+    @Resource
+    private DriverGoodsLossRecordMapper driverGoodsLossRecordMapper;
+
+    @Resource
+    private DriverEquipmentLossRecordMapper driverEquipmentLossRecordMapper;
+
+    @Resource
+    private DriverGoodsLossIntervalMainMapper driverGoodsLossIntervalMainMapper;
+
+    @Resource
+    private DriverOnRouteAccountRecordMainMapper driverOnRouteAccountRecordMainMapper;
+
+    @Resource
+    private DriverGoodsLossIntervalDetailMapper driverGoodsLossIntervalDetailMapper;
+
+    @Resource
+    private EquipmentLossIntervalDetailMapper equipmentLossIntervalDetailMapper;
+
+    @Resource
+    private TransactionTemplate transactionTemplate;
+
+
+    @Override
+    public void generator(DriverIntervalCargoDamageGeneratorBo bo) {
+        // 获取当前运营商下所有司机
+        List<AreaStaffResponse> areaStaffResponses = areaStaffComponent.searchByOperatorId(bo.getOperatorId());
+        if (null == areaStaffResponses || areaStaffResponses.isEmpty()) {
+            throw new MessageException("当前运营商下没有司机");
+        }
+
+        // 获取当前运营商id链
+        OrgOperatorVo orgOperatorVo = operatorComponent.queryOperatorById(bo.getOperatorId());
+
+        List<Long> operatorAreaStaffIds = areaStaffResponses.stream().map(AreaStaffResponse::getId).collect(Collectors.toList());
+        // 基于参数中运营商司机id列表及运营商实际司机id列表进行校验,判断当前生成逻辑是定期货损统计还是抽查货损统计
+        String stockTakingType = checkStockTakingType(bo.getAreaStaffIds(), operatorAreaStaffIds);
+
+        // 如果是定期货损统计, 则将参数中司机id列表设置为运营商实际司机id列表
+        if (DriverGoodsLossIntervalStockTakingType.REGULAR.name().equals(stockTakingType)) {
+            bo.setAreaStaffIds(operatorAreaStaffIds);
+        }
+
+        // 获取上一次司机的货损统计记录
+        DriverGoodsLossIntervalMain lastDriverGoodsLossIntervalMain = driverGoodsLossIntervalMainMapper.queryLastByOperatorId(bo.getOperatorId());
+        List<DriverGoodsLossIntervalDetail> lastDriverGoodsLossIntervalDetails = null;
+        List<EquipmentLossIntervalDetail> lastEquipmentLossIntervalDetails = null;
+        if (null != lastDriverGoodsLossIntervalMain) {
+            lastDriverGoodsLossIntervalDetails = driverGoodsLossIntervalDetailMapper.selectByMainIdAndAreaStaffId(lastDriverGoodsLossIntervalMain.getId(), bo.getAreaStaffIds());
+            lastEquipmentLossIntervalDetails = equipmentLossIntervalDetailMapper.selectByMainIdAndAreaStaffId(lastDriverGoodsLossIntervalMain.getId(), bo.getAreaStaffIds());
+        }
+
+        // 获取当前司机下所有未核算的核算记录主表
+        List<DriverOnRouteAccountRecordMain> driverOnRouteAccountRecordMains = driverOnRouteAccountRecordMainMapper.selectUnVerified(bo.getAreaStaffIds());
+        Map<Long, DriverOnRouteAccountRecordMain> driverOnRouteAccountRecordMainMap = driverOnRouteAccountRecordMains.stream().collect(Collectors.toMap(DriverOnRouteAccountRecordMain::getAreaStaffId, Function.identity()));
+
+        // 基于开始时间及结束时间抽取这段时间内每日统计的司机货损记录及设备货损记录
+        List<DriverGoodsLossRecord> driverGoodsLossRecords = driverGoodsLossRecordMapper.searchGeneratorParam(bo);
+        List<DriverEquipmentLossRecord> driverEquipmentLossRecords = driverEquipmentLossRecordMapper.searchGeneratorParam(bo);
+
+        // 基于司机货损记录及设备货损记录生成司机对应的货损统计记录
+        Map<Long, DriverGoodsLossIntervalVo> driverGoodsLossIntervalDetailMap = generatorDriverGoodsLossIntervalDetailMap(bo.getAreaStaffIds(),
+                driverOnRouteAccountRecordMainMap,
+                driverGoodsLossRecords,
+                driverEquipmentLossRecords,
+                lastDriverGoodsLossIntervalDetails,
+                lastEquipmentLossIntervalDetails);
+
+        List<DriverGoodsLossIntervalDetail> driverGoodsLossIntervalDetails = new ArrayList<>();
+        List<EquipmentLossIntervalDetail> equipmentLossIntervalDetails = new ArrayList<>();
+
+        DriverGoodsLossIntervalMain driverGoodsLossIntervalMain = new DriverGoodsLossIntervalMain();
+        driverGoodsLossIntervalMain.setIntervalStartTime(bo.getIntervalStartTime());
+        driverGoodsLossIntervalMain.setIntervalEndTime(bo.getIntervalEndTime());
+        driverGoodsLossIntervalMain.setOperatorId(bo.getOperatorId());
+        driverGoodsLossIntervalMain.setOperatorChain(orgOperatorVo.getOperatorChain());
+        driverGoodsLossIntervalMain.setStockTakingType(stockTakingType);
+        long pickingOrderCreateNum = 0L; // 拣货单创建数
+        long wholeOrderCreateNum = 0L; // 整单创建数
+        long replenishNum = 0L; // 补货数
+        long returnWarehouseNum = 0L; // 回仓数
+        long onRouteInventoryNum = 0L; // 在途库存数
+        long unshippedCancelNum = 0L; // 未出库取消数
+        long shippedCancelNum = 0L; // 已出库取消数
+        long unReplenishedNum = 0L; // 未补货数
+        long driverProfitLossNum = 0L; // 司机货损数
+        long equipmentProfitLossNum = 0L; // 设备货损数
+        long totalProfitLossNum = 0L; // 总货损数
+
+        List<Long> useDriverOnRouteAccountRecordMains = new ArrayList<>();
+
+        for (Long areaStaffId : driverGoodsLossIntervalDetailMap.keySet()) {
+            DriverGoodsLossIntervalVo driverGoodsLossIntervalVo = driverGoodsLossIntervalDetailMap.get(areaStaffId);
+
+            if (null != driverGoodsLossIntervalVo) {
+                DriverGoodsLossIntervalDetail driverGoodsLossIntervalDetail = driverGoodsLossIntervalVo.getDriverGoodsLossIntervalDetail();
+                if (null != driverGoodsLossIntervalDetail) {
+                    driverGoodsLossIntervalDetails.add(driverGoodsLossIntervalDetail);
+                    pickingOrderCreateNum += driverGoodsLossIntervalDetail.getPickingOrderCreateNum();
+                    wholeOrderCreateNum += driverGoodsLossIntervalDetail.getWholeOrderCreateNum();
+                    replenishNum += driverGoodsLossIntervalDetail.getReplenishNum();
+                    returnWarehouseNum += driverGoodsLossIntervalDetail.getReturnWarehouseNum();
+                    onRouteInventoryNum += driverGoodsLossIntervalDetail.getLastRemainingOnRouteStock();
+                    unshippedCancelNum += driverGoodsLossIntervalDetail.getUnshippedCancelNum();
+                    shippedCancelNum += driverGoodsLossIntervalDetail.getShippedCancelNum();
+                    unReplenishedNum += driverGoodsLossIntervalDetail.getRemainingUnReplenishedNum();
+                    driverProfitLossNum += driverGoodsLossIntervalDetail.getProfitLossNum();
+                }
+                EquipmentLossIntervalDetail equipmentLossIntervalDetail = driverGoodsLossIntervalVo.getEquipmentLossIntervalDetail();
+                if (null != equipmentLossIntervalDetail) {
+                    equipmentLossIntervalDetails.add(equipmentLossIntervalDetail);
+                    equipmentProfitLossNum += equipmentLossIntervalDetail.getProfitLossNum();
+                }
+
+                totalProfitLossNum = driverProfitLossNum + equipmentProfitLossNum;
+
+                if (null != driverGoodsLossIntervalVo.getUseDriverOnRouteAccountRecordMainId()) {
+                    useDriverOnRouteAccountRecordMains.add(driverGoodsLossIntervalVo.getUseDriverOnRouteAccountRecordMainId());
+                }
+            }
+        }
+
+        driverGoodsLossIntervalMain.setPickingOrderCreateNum(pickingOrderCreateNum);
+        driverGoodsLossIntervalMain.setWholeOrderCreateNum(wholeOrderCreateNum);
+        driverGoodsLossIntervalMain.setReplenishNum(replenishNum);
+        driverGoodsLossIntervalMain.setReturnWarehouseNum(returnWarehouseNum);
+        driverGoodsLossIntervalMain.setOnRouteInventoryNum(onRouteInventoryNum);
+        driverGoodsLossIntervalMain.setUnshippedCancelNum(unshippedCancelNum);
+        driverGoodsLossIntervalMain.setShippedCancelNum(shippedCancelNum);
+        driverGoodsLossIntervalMain.setUnReplenishedNum(unReplenishedNum);
+        driverGoodsLossIntervalMain.setDriverProfitLossNum(driverProfitLossNum);
+        driverGoodsLossIntervalMain.setEquipmentProfitLossNum(equipmentProfitLossNum);
+        driverGoodsLossIntervalMain.setTotalProfitLossNum(totalProfitLossNum);
+
+        transactionTemplate.execute(status -> {
+            driverGoodsLossIntervalMainMapper.insert(driverGoodsLossIntervalMain);
+
+            driverGoodsLossIntervalDetailMapper.insertBatch(driverGoodsLossIntervalMain.getId(), driverGoodsLossIntervalDetails);
+            equipmentLossIntervalDetailMapper.insertBatch(driverGoodsLossIntervalMain.getId(), equipmentLossIntervalDetails);
+            driverOnRouteAccountRecordMainMapper.batchBind(bo, useDriverOnRouteAccountRecordMains, driverGoodsLossIntervalMain.getId());
+            return null;
+        });
+    }
+
+    /**
+     * 生成司机货损统计数据
+     *
+     * @param driverGoodsLossRecords 司机货损统计
+     * @param driverEquipmentLossRecords 设备货损统计
+     * @param lastDriverGoodsLossIntervalDetails 上一次的司机货损统计
+     * @param lastEquipmentLossIntervalDetails 上一次的设备货损统计
+     * @return 司机对应的区间货损统计Map
+     */
+    private Map<Long, DriverGoodsLossIntervalVo> generatorDriverGoodsLossIntervalDetailMap(List<Long> areaStaffIds,
+                                                                                           Map<Long, DriverOnRouteAccountRecordMain> driverOnRouteAccountRecordMainMap,
+                                                                                           List<DriverGoodsLossRecord> driverGoodsLossRecords,
+                                                                                           List<DriverEquipmentLossRecord> driverEquipmentLossRecords,
+                                                                                           List<DriverGoodsLossIntervalDetail> lastDriverGoodsLossIntervalDetails,
+                                                                                           List<EquipmentLossIntervalDetail> lastEquipmentLossIntervalDetails) {
+        Map<Long, List<DriverGoodsLossRecord>> areaStaffDriverGoodsLossRecordMap = driverGoodsLossRecords.stream().collect(Collectors.groupingBy(DriverGoodsLossRecord::getAreaStaffId));
+        Map<Long, List<DriverEquipmentLossRecord>> areaStaffDriverEquipmentLossRecordMap = driverEquipmentLossRecords.stream().collect(Collectors.groupingBy(DriverEquipmentLossRecord::getAreaStaffId));
+
+        Map<Long, DriverGoodsLossIntervalDetail> lastDriverGoodsLossIntervalDetailMap = null != lastDriverGoodsLossIntervalDetails && !lastDriverGoodsLossIntervalDetails.isEmpty() ?
+                lastDriverGoodsLossIntervalDetails.stream().collect(Collectors.toMap(DriverGoodsLossIntervalDetail::getAreaStaffId, v -> v)) : new HashMap<>();
+        Map<Long, EquipmentLossIntervalDetail> lastEquipmentLossIntervalDetailMap = null != lastEquipmentLossIntervalDetails && !lastEquipmentLossIntervalDetails.isEmpty() ?
+                lastEquipmentLossIntervalDetails.stream().collect(Collectors.toMap(EquipmentLossIntervalDetail::getAreaStaffId, v -> v)) : new HashMap<>();
+
+        Map<Long, DriverGoodsLossIntervalVo> result = new HashMap<>();
+        for (Long areaStaffId : areaStaffIds) {
+            DriverOnRouteAccountRecordMain driverOnRouteAccountRecordMain = driverOnRouteAccountRecordMainMap.get(areaStaffId);
+
+
+            List<DriverGoodsLossRecord> driverGoodsLossRecordList = areaStaffDriverGoodsLossRecordMap.get(areaStaffId);
+            List<DriverEquipmentLossRecord> driverEquipmentLossRecordList = areaStaffDriverEquipmentLossRecordMap.get(areaStaffId);
+
+            DriverGoodsLossIntervalDetail lastDriverGoodsLossIntervalDetail = lastDriverGoodsLossIntervalDetailMap.get(areaStaffId);
+            EquipmentLossIntervalDetail lastEquipmentLossIntervalDetail = lastEquipmentLossIntervalDetailMap.get(areaStaffId);
+
+
+            DriverGoodsLossIntervalDetail driverGoodsLossIntervalDetail = new DriverGoodsLossIntervalDetail();
+            driverGoodsLossIntervalDetail.setAreaStaffId(areaStaffId);
+            buildDriverGoodsLossRecord(driverGoodsLossIntervalDetail, lastDriverGoodsLossIntervalDetail, driverGoodsLossRecordList, driverOnRouteAccountRecordMain);
+
+            EquipmentLossIntervalDetail equipmentLossIntervalDetail = new EquipmentLossIntervalDetail();
+            equipmentLossIntervalDetail.setAreaStaffId(areaStaffId);
+            buildDriverEquipmentLossRecord(equipmentLossIntervalDetail, lastEquipmentLossIntervalDetail, driverEquipmentLossRecordList);
+
+            DriverGoodsLossIntervalVo driverGoodsLossIntervalVo = new DriverGoodsLossIntervalVo();
+            driverGoodsLossIntervalVo.setDriverGoodsLossIntervalDetail(driverGoodsLossIntervalDetail);
+            driverGoodsLossIntervalVo.setEquipmentLossIntervalDetail(equipmentLossIntervalDetail);
+            if (null !=driverOnRouteAccountRecordMain) {
+                driverGoodsLossIntervalVo.setUseDriverOnRouteAccountRecordMainId(driverOnRouteAccountRecordMain.getId());
+            }
+
+            result.put(areaStaffId, driverGoodsLossIntervalVo);
+        }
+        return result;
+    }
+
+    /**
+     * 构建司机货损统计数据
+     *
+     * @param driverGoodsLossIntervalDetail 货损统计数据
+     * @param lastDriverGoodsLossIntervalDetail 上一次的货损统计数据
+     * @param driverGoodsLossRecordList 货损统计数据
+     * @param driverOnRouteAccountRecordMain 司机在途核算数据
+     */
+    private void buildDriverGoodsLossRecord(DriverGoodsLossIntervalDetail driverGoodsLossIntervalDetail,
+                                            DriverGoodsLossIntervalDetail lastDriverGoodsLossIntervalDetail,
+                                            List<DriverGoodsLossRecord> driverGoodsLossRecordList,
+                                            DriverOnRouteAccountRecordMain driverOnRouteAccountRecordMain) {
+        Long lastRemainingOnRouteStock = 0L;
+        if (null != lastDriverGoodsLossIntervalDetail) {
+            if (BoolEnum.isYes(lastDriverGoodsLossIntervalDetail.getUseVerifyNum())) {
+                lastRemainingOnRouteStock = lastDriverGoodsLossIntervalDetail.getWholeVerifyNum();
+            } else {
+                lastRemainingOnRouteStock = lastDriverGoodsLossIntervalDetail.getRemainingUnReplenishedNum();
+            }
+        }
+
+        // 上一次剩余在途库存数
+        driverGoodsLossIntervalDetail.setLastRemainingOnRouteStock(lastRemainingOnRouteStock);
+        // 是否核算
+        String useVerifyNum = BoolEnum.NO.name();
+        // 核算数
+        Long wholeVerifyNum = 0L;
+
+        if (null != driverOnRouteAccountRecordMain) {
+            useVerifyNum = BoolEnum.YES.name();
+            wholeVerifyNum = driverOnRouteAccountRecordMain.getStatTotalNum();
+        }
+
+        // 是否使用整件核数
+        driverGoodsLossIntervalDetail.setUseVerifyNum(useVerifyNum);
+        // 整件单核数
+        driverGoodsLossIntervalDetail.setWholeVerifyNum(wholeVerifyNum);
+
+        Long pickingOrderCreateNum = 0L; // 拣货单开单数
+        Long wholeOrderCreateNum = 0L; // 整件单开单数
+        Long unshippedCancelNum = 0L; // 未出库取消数
+        Long shippedCancelNum = 0L; // 已出库取消数
+        Long replenishNum = 0L; // 补货数
+        Long returnWarehouseNum = 0L; // 回仓数
+        Long onRouteStock = 0L; // 当日在途数
+
+
+        if (null != driverGoodsLossRecordList && !driverGoodsLossRecordList.isEmpty()) {
+            for (DriverGoodsLossRecord driverGoodsLossRecord : driverGoodsLossRecordList) {
+                pickingOrderCreateNum += driverGoodsLossRecord.getPickingOrderCreateNum();
+                wholeOrderCreateNum += driverGoodsLossRecord.getWholeOrderCreateNum();
+                unshippedCancelNum += driverGoodsLossRecord.getUnshippedCancelNum();
+                shippedCancelNum += driverGoodsLossRecord.getShippedCancelNum();
+                replenishNum += driverGoodsLossRecord.getReplenishNum();
+                returnWarehouseNum += driverGoodsLossRecord.getReturnWarehouseNum();
+            }
+
+            // 获取 driverGoodsLossRecordList 中 id 最大 driverGoodsLossRecord 对象
+            DriverGoodsLossRecord driverGoodsLossRecord = driverGoodsLossRecordList.stream().max(Comparator.comparing(DriverGoodsLossRecord::getId)).get();
+            if (BoolEnum.isYes(driverGoodsLossRecord.getUseVerified())) {
+                onRouteStock = driverGoodsLossRecord.getVerifiedNum();
+            } else {
+                onRouteStock = driverGoodsLossRecord.getCurrentOnRouteNum();
+            }
+        }
+
+        // 理论剩余未补数
+        Long remainingUnReplenishedNum = lastRemainingOnRouteStock + pickingOrderCreateNum + wholeOrderCreateNum - unshippedCancelNum - replenishNum - returnWarehouseNum;
+
+        // 盈亏数
+        Long profitLossNum = remainingUnReplenishedNum - onRouteStock;
+
+        driverGoodsLossIntervalDetail.setPickingOrderCreateNum(pickingOrderCreateNum);
+        driverGoodsLossIntervalDetail.setWholeOrderCreateNum(wholeOrderCreateNum);
+        driverGoodsLossIntervalDetail.setUnshippedCancelNum(unshippedCancelNum);
+        driverGoodsLossIntervalDetail.setShippedCancelNum(shippedCancelNum);
+        driverGoodsLossIntervalDetail.setReplenishNum(replenishNum);
+        driverGoodsLossIntervalDetail.setReturnWarehouseNum(returnWarehouseNum);
+        driverGoodsLossIntervalDetail.setRemainingUnReplenishedNum(remainingUnReplenishedNum);
+        driverGoodsLossIntervalDetail.setOnRouteStock(onRouteStock);
+        driverGoodsLossIntervalDetail.setProfitLossNum(profitLossNum);
+    }
+
+    /**
+     * 构建司机设备货损统计数据
+     *
+     * @param equipmentLossIntervalDetail 设备货损统计数据
+     * @param lastEquipmentLossIntervalDetail 上次设备货损统计数据
+     * @param driverEquipmentLossRecordList 设备货损统计数据
+     */
+    private void buildDriverEquipmentLossRecord(EquipmentLossIntervalDetail equipmentLossIntervalDetail,
+                                                EquipmentLossIntervalDetail lastEquipmentLossIntervalDetail,
+                                                List<DriverEquipmentLossRecord> driverEquipmentLossRecordList) {
+
+        Long lastRemainingEquipmentStock = 0L; // 上次剩余设备库存
+        if (null != lastEquipmentLossIntervalDetail) {
+            lastRemainingEquipmentStock = lastEquipmentLossIntervalDetail.getActualStockNum();
+        }
+        Long totalReplenishNum = 0L; // 设备补货数
+        Long equipmentSalesNum = 0L; // 设备销量
+        Long actualStockNum = 0L; // 实际设备库存
+
+
+        if (null != driverEquipmentLossRecordList && !driverEquipmentLossRecordList.isEmpty()) {
+            for (DriverEquipmentLossRecord driverEquipmentLossRecord : driverEquipmentLossRecordList) {
+                totalReplenishNum += driverEquipmentLossRecord.getEquipmentReplenishNum();
+                equipmentSalesNum += driverEquipmentLossRecord.getEquipmentSalesNum();
+            }
+
+            // 获取 driverEquipmentLossRecordList 中 id 最大 driverEquipmentLossRecord 对象
+            DriverEquipmentLossRecord driverEquipmentLossRecord = driverEquipmentLossRecordList.stream().max(Comparator.comparing(DriverEquipmentLossRecord::getId)).get();
+            actualStockNum = driverEquipmentLossRecord.getActualEquipmentStockNum();
+        }
+
+        equipmentLossIntervalDetail.setLastRemainingEquipmentStock(lastRemainingEquipmentStock);
+        equipmentLossIntervalDetail.setTotalReplenishNum(totalReplenishNum);
+        equipmentLossIntervalDetail.setEquipmentSalesNum(equipmentSalesNum);
+        Long theoreticalStockNum = lastRemainingEquipmentStock + totalReplenishNum - equipmentSalesNum;
+        equipmentLossIntervalDetail.setTheoreticalStockNum(theoreticalStockNum);
+        equipmentLossIntervalDetail.setActualStockNum(actualStockNum);
+
+    }
+
+    public String checkStockTakingType(List<Long> areaStaffIds, List<Long> operatorAreaStaffIds) {
+        if (null == areaStaffIds || areaStaffIds.isEmpty()) {
+            return DriverGoodsLossIntervalStockTakingType.REGULAR.name();
+        }
+        // 如果 bo.getAreaStaffIds() 中存在不属于 operatorAreaStaffIds 的区域员工id
+        for (Long areaStaffId : areaStaffIds) {
+            if (!operatorAreaStaffIds.contains(areaStaffId)) {
+                throw new MessageException("选择的人员中存在不属于当前运营商的人员");
+            }
+        }
+        for (Long areaStaffId : operatorAreaStaffIds) {
+            if (!areaStaffIds.contains(areaStaffId)) {
+                return DriverGoodsLossIntervalStockTakingType.SPOT_CHECK.name();
+            }
+        }
+        return DriverGoodsLossIntervalStockTakingType.REGULAR.name();
+    }
+
+}

+ 4 - 2
warehouse-admin-web/src/main/java/com/yr/warehouse/admin/web/driver/controller/DriverIntervalCargoDamageController.java

@@ -50,6 +50,8 @@ import java.util.stream.Collectors;
 @RestController
 @RequestMapping("/driver/interval/cargoDamage")
 public class DriverIntervalCargoDamageController extends BaseController {
+    @Resource
+    private DriverGoodsLossIntervalService driverGoodsLossIntervalService;
 
     @Resource
     private DriverGoodsLossIntervalMainService driverGoodsLossIntervalMainService;
@@ -97,8 +99,8 @@ public class DriverIntervalCargoDamageController extends BaseController {
         DriverIntervalCargoDamageGeneratorBo bo = DriverIntervalCargoDamageMapStruct.MAPSTRUCT.generatorRequestToBo(request);
         buildUserInfo(bo, adminUserInfo);
         // TODO: 区间记录生成
-
-        return null;
+        driverGoodsLossIntervalService.generator(bo);
+        return Result.success("success");
     }
 
     /**

+ 6 - 0
warehouse-admin-web/src/main/java/com/yr/warehouse/admin/web/driver/export/DriverIntervalCargoDamageDetailExport.java

@@ -40,6 +40,12 @@ public class DriverIntervalCargoDamageDetailExport implements Serializable {
     private Long wholeOrderCreateNum;
 
     /**
+     * 本次在途库存数
+     */
+    @ExcelProperty("本次在途库存数")
+    private Long onRouteStock;
+
+    /**
      * 本次已取消数(未出库) - 页面展示这个*
      */
     @ExcelProperty("本次已取消数")

+ 5 - 0
warehouse-admin-web/src/main/java/com/yr/warehouse/admin/web/driver/response/DriverIntervalCargoDamageDetailResponse.java

@@ -65,6 +65,11 @@ public class DriverIntervalCargoDamageDetailResponse implements Serializable {
     private Long remainingUnReplenishedNum;
 
     /**
+     * 本次在途库存数
+     */
+    private Long onRouteStock;
+
+    /**
      * 整件核实数
      */
     private Long wholeVerifyNum;