Эх сурвалжийг харах

友盛-BI大屏-右侧销售数据展示区:近7日出货量/销售额、主要商品销量/销售金额占比

tangyishan 1 сар өмнө
parent
commit
d8c47e69b5
20 өөрчлөгдсөн 672 нэмэгдсэн , 0 устгасан
  1. 32 0
      sckw-modules-api/sckw-order-api/src/main/java/com/sckw/order/api/feign/OrderStatisticsFeignService.java
  2. 12 0
      sckw-modules-api/sckw-order-api/src/main/java/com/sckw/order/api/model/DailySalesStatisticsDto.java
  3. 12 0
      sckw-modules-api/sckw-order-api/src/main/java/com/sckw/order/api/model/DailyShipmentStatisticsDto.java
  4. 11 0
      sckw-modules-api/sckw-order-api/src/main/java/com/sckw/order/api/model/GoodsAmountStatisticsDto.java
  5. 11 0
      sckw-modules-api/sckw-order-api/src/main/java/com/sckw/order/api/model/GoodsVolumeStatisticsDto.java
  6. 28 0
      sckw-modules/sckw-order/src/main/java/com/sckw/order/controller/KwoTradeOrderStatisticsController.java
  7. 36 0
      sckw-modules/sckw-order/src/main/java/com/sckw/order/dao/KwoTradeOrderMapper.java
  8. 12 0
      sckw-modules/sckw-order/src/main/java/com/sckw/order/model/dto/DailySalesStatisticsDTO.java
  9. 12 0
      sckw-modules/sckw-order/src/main/java/com/sckw/order/model/dto/DailyShipmentStatisticsDTO.java
  10. 11 0
      sckw-modules/sckw-order/src/main/java/com/sckw/order/model/dto/GoodsAmountStatisticsDTO.java
  11. 11 0
      sckw-modules/sckw-order/src/main/java/com/sckw/order/model/dto/GoodsVolumeStatisticsDTO.java
  12. 50 0
      sckw-modules/sckw-order/src/main/java/com/sckw/order/serivce/KwoTradeOrderStatisticsService.java
  13. 60 0
      sckw-modules/sckw-order/src/main/resources/mapper/KwoTradeOrderMapper.xml
  14. 47 0
      sckw-modules/sckw-report/src/main/java/com/sckw/report/controller/KwBiReportController.java
  15. 28 0
      sckw-modules/sckw-report/src/main/java/com/sckw/report/model/vo/DailySalesAmountVo.java
  16. 28 0
      sckw-modules/sckw-report/src/main/java/com/sckw/report/model/vo/DailyShipmentAmountVo.java
  17. 28 0
      sckw-modules/sckw-report/src/main/java/com/sckw/report/model/vo/GoodsSalesAmountRatioVo.java
  18. 28 0
      sckw-modules/sckw-report/src/main/java/com/sckw/report/model/vo/GoodsSalesVolumeRatioVo.java
  19. 17 0
      sckw-modules/sckw-report/src/main/java/com/sckw/report/service/KwBiReportService.java
  20. 198 0
      sckw-modules/sckw-report/src/main/java/com/sckw/report/service/impl/KwBiReportServiceImpl.java

+ 32 - 0
sckw-modules-api/sckw-order-api/src/main/java/com/sckw/order/api/feign/OrderStatisticsFeignService.java

@@ -0,0 +1,32 @@
+package com.sckw.order.api.feign;
+
+import com.sckw.core.web.response.BaseResult;
+import com.sckw.order.api.model.DailySalesStatisticsDto;
+import com.sckw.order.api.model.DailyShipmentStatisticsDto;
+import com.sckw.order.api.model.GoodsAmountStatisticsDto;
+import com.sckw.order.api.model.GoodsVolumeStatisticsDto;
+import org.springframework.cloud.openfeign.FeignClient;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+
+import java.util.List;
+
+@FeignClient(name = "sckw-ng-order", contextId = "orderStatisticsFeignService")
+public interface OrderStatisticsFeignService {
+
+    @GetMapping("/kwoTradeOrderStatistics/getDailyShipmentByCategory")
+    BaseResult<List<DailyShipmentStatisticsDto>> getDailyShipmentByCategory(
+            @RequestParam("entId") Long entId,
+            @RequestParam("days") Integer days);
+
+    @GetMapping("/kwoTradeOrderStatistics/getDailySalesByCategory")
+    BaseResult<List<DailySalesStatisticsDto>> getDailySalesByCategory(
+            @RequestParam("entId") Long entId,
+            @RequestParam("days") Integer days);
+
+    @GetMapping("/kwoTradeOrderStatistics/getGoodsVolumeTop5")
+    BaseResult<List<GoodsVolumeStatisticsDto>> getGoodsVolumeTop5(@RequestParam("entId") Long entId);
+
+    @GetMapping("/kwoTradeOrderStatistics/getGoodsAmountTop5")
+    BaseResult<List<GoodsAmountStatisticsDto>> getGoodsAmountTop5(@RequestParam("entId") Long entId);
+}

+ 12 - 0
sckw-modules-api/sckw-order-api/src/main/java/com/sckw/order/api/model/DailySalesStatisticsDto.java

@@ -0,0 +1,12 @@
+package com.sckw.order.api.model;
+
+import lombok.Data;
+
+import java.math.BigDecimal;
+
+@Data
+public class DailySalesStatisticsDto {
+    private String orderDate;
+    private String goodsType;
+    private BigDecimal salesAmount;
+}

+ 12 - 0
sckw-modules-api/sckw-order-api/src/main/java/com/sckw/order/api/model/DailyShipmentStatisticsDto.java

@@ -0,0 +1,12 @@
+package com.sckw.order.api.model;
+
+import lombok.Data;
+
+import java.math.BigDecimal;
+
+@Data
+public class DailyShipmentStatisticsDto {
+    private String orderDate;
+    private String goodsType;
+    private BigDecimal actualAmount;
+}

+ 11 - 0
sckw-modules-api/sckw-order-api/src/main/java/com/sckw/order/api/model/GoodsAmountStatisticsDto.java

@@ -0,0 +1,11 @@
+package com.sckw.order.api.model;
+
+import lombok.Data;
+
+import java.math.BigDecimal;
+
+@Data
+public class GoodsAmountStatisticsDto {
+    private String goodsName;
+    private BigDecimal totalAmount;
+}

+ 11 - 0
sckw-modules-api/sckw-order-api/src/main/java/com/sckw/order/api/model/GoodsVolumeStatisticsDto.java

@@ -0,0 +1,11 @@
+package com.sckw.order.api.model;
+
+import lombok.Data;
+
+import java.math.BigDecimal;
+
+@Data
+public class GoodsVolumeStatisticsDto {
+    private String goodsName;
+    private BigDecimal totalVolume;
+}

+ 28 - 0
sckw-modules/sckw-order/src/main/java/com/sckw/order/controller/KwoTradeOrderStatisticsController.java

@@ -2,6 +2,10 @@ package com.sckw.order.controller;
 
 import com.sckw.core.web.response.BaseResult;
 import com.sckw.core.web.response.HttpResult;
+import com.sckw.order.api.model.DailySalesStatisticsDto;
+import com.sckw.order.api.model.DailyShipmentStatisticsDto;
+import com.sckw.order.api.model.GoodsAmountStatisticsDto;
+import com.sckw.order.api.model.GoodsVolumeStatisticsDto;
 import com.sckw.order.api.model.SalesReportDataVo;
 import com.sckw.order.api.model.SalesReportQueryDto;
 import com.sckw.order.model.vo.req.WbTOrderDataStsParam;
@@ -71,4 +75,28 @@ public class KwoTradeOrderStatisticsController {
     public BaseResult<List<SalesReportDataVo>> querySalesReportData(@RequestBody @Validated SalesReportQueryDto queryDto) {
         return BaseResult.success(kwoTradeOrderStatisticsService.querySalesReportData(queryDto));
     }
+
+    @GetMapping("/getDailyShipmentByCategory")
+    public BaseResult<List<DailyShipmentStatisticsDto>> getDailyShipmentByCategory(
+            @RequestParam("entId") Long entId,
+            @RequestParam(value = "days", defaultValue = "7") Integer days) {
+        return BaseResult.success(kwoTradeOrderStatisticsService.getDailyShipmentByCategory(entId, days));
+    }
+
+    @GetMapping("/getDailySalesByCategory")
+    public BaseResult<List<DailySalesStatisticsDto>> getDailySalesByCategory(
+            @RequestParam("entId") Long entId,
+            @RequestParam(value = "days", defaultValue = "7") Integer days) {
+        return BaseResult.success(kwoTradeOrderStatisticsService.getDailySalesByCategory(entId, days));
+    }
+
+    @GetMapping("/getGoodsVolumeTop5")
+    public BaseResult<List<GoodsVolumeStatisticsDto>> getGoodsVolumeTop5(@RequestParam("entId") Long entId) {
+        return BaseResult.success(kwoTradeOrderStatisticsService.getGoodsVolumeTop5(entId));
+    }
+
+    @GetMapping("/getGoodsAmountTop5")
+    public BaseResult<List<GoodsAmountStatisticsDto>> getGoodsAmountTop5(@RequestParam("entId") Long entId) {
+        return BaseResult.success(kwoTradeOrderStatisticsService.getGoodsAmountTop5(entId));
+    }
 }

+ 36 - 0
sckw-modules/sckw-order/src/main/java/com/sckw/order/dao/KwoTradeOrderMapper.java

@@ -181,4 +181,40 @@ public interface KwoTradeOrderMapper extends BaseMapper<KwoTradeOrder> {
 
     List<TradeOrderDto> joinSelect();
 
+    /**
+     * 按日期和一级分类统计近7日已完成订单的净重
+     * @param entId 企业ID
+     * @param startTime 开始时间
+     * @param endTime 结束时间
+     * @return 每日出货量统计列表
+     */
+    List<DailyShipmentStatisticsDTO> selectDailyShipmentByCategory(@Param("entId") Long entId,
+                                                                   @Param("startTime") Date startTime,
+                                                                   @Param("endTime") Date endTime);
+
+    /**
+     * 按日期和一级分类统计近7日销售额
+     * @param entId 企业ID
+     * @param startTime 开始时间
+     * @param endTime 结束时间
+     * @return 每日销售额统计列表
+     */
+    List<DailySalesStatisticsDTO> selectDailySalesByCategory(@Param("entId") Long entId,
+                                                             @Param("startTime") Date startTime,
+                                                             @Param("endTime") Date endTime);
+
+    /**
+     * 按最低级分类统计历史完成订单的净重总和(取前5名)
+     * @param entId 企业ID
+     * @return 商品销量统计列表
+     */
+    List<GoodsVolumeStatisticsDTO> selectGoodsVolumeTop5(@Param("entId") Long entId);
+
+    /**
+     * 按最低级分类统计历史完成订单的销售金额总和(取前5名)
+     * @param entId 企业ID
+     * @return 商品销售金额统计列表
+     */
+    List<GoodsAmountStatisticsDTO> selectGoodsAmountTop5(@Param("entId") Long entId);
+
 }

+ 12 - 0
sckw-modules/sckw-order/src/main/java/com/sckw/order/model/dto/DailySalesStatisticsDTO.java

@@ -0,0 +1,12 @@
+package com.sckw.order.model.dto;
+
+import lombok.Data;
+
+import java.math.BigDecimal;
+
+@Data
+public class DailySalesStatisticsDTO {
+    private String orderDate;
+    private String goodsType;
+    private BigDecimal salesAmount;
+}

+ 12 - 0
sckw-modules/sckw-order/src/main/java/com/sckw/order/model/dto/DailyShipmentStatisticsDTO.java

@@ -0,0 +1,12 @@
+package com.sckw.order.model.dto;
+
+import lombok.Data;
+
+import java.math.BigDecimal;
+
+@Data
+public class DailyShipmentStatisticsDTO {
+    private String orderDate;
+    private String goodsType;
+    private BigDecimal actualAmount;
+}

+ 11 - 0
sckw-modules/sckw-order/src/main/java/com/sckw/order/model/dto/GoodsAmountStatisticsDTO.java

@@ -0,0 +1,11 @@
+package com.sckw.order.model.dto;
+
+import lombok.Data;
+
+import java.math.BigDecimal;
+
+@Data
+public class GoodsAmountStatisticsDTO {
+    private String goodsName;
+    private BigDecimal totalAmount;
+}

+ 11 - 0
sckw-modules/sckw-order/src/main/java/com/sckw/order/model/dto/GoodsVolumeStatisticsDTO.java

@@ -0,0 +1,11 @@
+package com.sckw.order.model.dto;
+
+import lombok.Data;
+
+import java.math.BigDecimal;
+
+@Data
+public class GoodsVolumeStatisticsDTO {
+    private String goodsName;
+    private BigDecimal totalVolume;
+}

+ 50 - 0
sckw-modules/sckw-order/src/main/java/com/sckw/order/serivce/KwoTradeOrderStatisticsService.java

@@ -13,6 +13,10 @@ import com.sckw.core.web.context.LoginUserHolder;
 import com.sckw.order.dao.KwoTradeOrderMapper;
 import com.sckw.order.model.SalesReportRawData;
 import com.sckw.order.model.dto.*;
+import com.sckw.order.api.model.DailySalesStatisticsDto;
+import com.sckw.order.api.model.DailyShipmentStatisticsDto;
+import com.sckw.order.api.model.GoodsAmountStatisticsDto;
+import com.sckw.order.api.model.GoodsVolumeStatisticsDto;
 import com.sckw.order.api.model.SalesReportDataVo;
 import com.sckw.order.api.model.SalesReportQueryDto;
 import com.sckw.order.model.vo.req.WbTOrderDataStsParam;
@@ -410,5 +414,51 @@ public class KwoTradeOrderStatisticsService {
         
         return result;
     }
+
+    public List<DailyShipmentStatisticsDto> getDailyShipmentByCategory(Long entId, Integer days) {
+        Date endTime = new Date();
+        Date startTime = DateUtils.getStartTime(days, LocalDateTime.now());
+        List<DailyShipmentStatisticsDTO> list = tradeOrderMapper.selectDailyShipmentByCategory(entId, startTime, endTime);
+        return list.stream().map(dto -> {
+            DailyShipmentStatisticsDto result = new DailyShipmentStatisticsDto();
+            result.setOrderDate(dto.getOrderDate());
+            result.setGoodsType(dto.getGoodsType());
+            result.setActualAmount(dto.getActualAmount());
+            return result;
+        }).collect(Collectors.toList());
+    }
+
+    public List<DailySalesStatisticsDto> getDailySalesByCategory(Long entId, Integer days) {
+        Date endTime = new Date();
+        Date startTime = DateUtils.getStartTime(days, LocalDateTime.now());
+        List<DailySalesStatisticsDTO> list = tradeOrderMapper.selectDailySalesByCategory(entId, startTime, endTime);
+        return list.stream().map(dto -> {
+            DailySalesStatisticsDto result = new DailySalesStatisticsDto();
+            result.setOrderDate(dto.getOrderDate());
+            result.setGoodsType(dto.getGoodsType());
+            result.setSalesAmount(dto.getSalesAmount());
+            return result;
+        }).collect(Collectors.toList());
+    }
+
+    public List<GoodsVolumeStatisticsDto> getGoodsVolumeTop5(Long entId) {
+        List<GoodsVolumeStatisticsDTO> list = tradeOrderMapper.selectGoodsVolumeTop5(entId);
+        return list.stream().map(dto -> {
+            GoodsVolumeStatisticsDto result = new GoodsVolumeStatisticsDto();
+            result.setGoodsName(dto.getGoodsName());
+            result.setTotalVolume(dto.getTotalVolume());
+            return result;
+        }).collect(Collectors.toList());
+    }
+
+    public List<GoodsAmountStatisticsDto> getGoodsAmountTop5(Long entId) {
+        List<GoodsAmountStatisticsDTO> list = tradeOrderMapper.selectGoodsAmountTop5(entId);
+        return list.stream().map(dto -> {
+            GoodsAmountStatisticsDto result = new GoodsAmountStatisticsDto();
+            result.setGoodsName(dto.getGoodsName());
+            result.setTotalAmount(dto.getTotalAmount());
+            return result;
+        }).collect(Collectors.toList());
+    }
 }
 

+ 60 - 0
sckw-modules/sckw-order/src/main/resources/mapper/KwoTradeOrderMapper.xml

@@ -1044,4 +1044,64 @@
             limit 20
         </where>
     </select>
+
+    <select id="selectDailyShipmentByCategory" resultType="com.sckw.order.model.dto.DailyShipmentStatisticsDTO">
+        select DATE_FORMAT(kto.create_time, '%Y-%m-%d') as orderDate,
+               ktog.goods_type as goodsType,
+               SUM(kto.actual_amount) as actualAmount
+        from kwo_trade_order kto
+                 inner join kwo_trade_order_goods ktog on kto.id = ktog.t_order_id and ktog.del_flag = 0
+                 inner join kwo_trade_order_unit ku on kto.id = ku.t_order_id and ku.unit_type = '2' and ku.del_flag = 0
+        where kto.del_flag = 0
+          and kto.status = 5
+          and ku.top_ent_id = #{entId}
+          and kto.create_time >= #{startTime}
+          and kto.create_time <= #{endTime}
+        group by DATE_FORMAT(kto.create_time, '%Y-%m-%d'), ktog.goods_type
+        order by orderDate, goodsType;
+    </select>
+
+    <select id="selectDailySalesByCategory" resultType="com.sckw.order.model.dto.DailySalesStatisticsDTO">
+        select DATE_FORMAT(kto.create_time, '%Y-%m-%d') as orderDate,
+               ktog.goods_type as goodsType,
+               SUM(kto.price) as salesAmount
+        from kwo_trade_order kto
+                 inner join kwo_trade_order_goods ktog on kto.id = ktog.t_order_id and ktog.del_flag = 0
+                 inner join kwo_trade_order_unit ku on kto.id = ku.t_order_id and ku.unit_type = '2' and ku.del_flag = 0
+        where kto.del_flag = 0
+          and kto.status = 5
+          and ku.top_ent_id = #{entId}
+          and kto.create_time >= #{startTime}
+          and kto.create_time <= #{endTime}
+        group by DATE_FORMAT(kto.create_time, '%Y-%m-%d'), ktog.goods_type
+        order by orderDate, goodsType;
+    </select>
+
+    <select id="selectGoodsVolumeTop5" resultType="com.sckw.order.model.dto.GoodsVolumeStatisticsDTO">
+        select ktog.goods_name as goodsName,
+               SUM(kto.actual_amount) as totalVolume
+        from kwo_trade_order kto
+                 inner join kwo_trade_order_goods ktog on kto.id = ktog.t_order_id and ktog.del_flag = 0
+                 inner join kwo_trade_order_unit ku on kto.id = ku.t_order_id and ku.unit_type = '2' and ku.del_flag = 0
+        where kto.del_flag = 0
+          and kto.status = 5
+          and ku.top_ent_id = #{entId}
+        group by ktog.goods_name
+        order by totalVolume desc
+        limit 5;
+    </select>
+
+    <select id="selectGoodsAmountTop5" resultType="com.sckw.order.model.dto.GoodsAmountStatisticsDTO">
+        select ktog.goods_name as goodsName,
+               SUM(kto.price) as totalAmount
+        from kwo_trade_order kto
+                 inner join kwo_trade_order_goods ktog on kto.id = ktog.t_order_id and ktog.del_flag = 0
+                 inner join kwo_trade_order_unit ku on kto.id = ku.t_order_id and ku.unit_type = '2' and ku.del_flag = 0
+        where kto.del_flag = 0
+          and kto.status = 5
+          and ku.top_ent_id = #{entId}
+        group by ktog.goods_name
+        order by totalAmount desc
+        limit 5;
+    </select>
 </mapper>

+ 47 - 0
sckw-modules/sckw-report/src/main/java/com/sckw/report/controller/KwBiReportController.java

@@ -0,0 +1,47 @@
+package com.sckw.report.controller;
+
+import com.sckw.core.web.response.BaseResult;
+import com.sckw.report.model.vo.DailySalesAmountVo;
+import com.sckw.report.model.vo.DailyShipmentAmountVo;
+import com.sckw.report.model.vo.GoodsSalesAmountRatioVo;
+import com.sckw.report.model.vo.GoodsSalesVolumeRatioVo;
+import com.sckw.report.service.KwBiReportService;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import lombok.RequiredArgsConstructor;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+@RestController
+@RequestMapping("/kwBiReport")
+@Tag(name = "BI报表统计", description = "BI报表统计接口")
+@RequiredArgsConstructor
+public class KwBiReportController {
+
+    private final KwBiReportService kwBiReportService;
+
+    @GetMapping("/dailyShipmentAmount")
+    @Operation(summary = "近7日出货量", description = "折线图展示近7个自然日,每个一级分类下所有商品的已完成运单的净重汇总")
+    public BaseResult<DailyShipmentAmountVo> getDailyShipmentAmount() {
+        return BaseResult.success(kwBiReportService.getDailyShipmentAmount());
+    }
+
+    @GetMapping("/dailySalesAmount")
+    @Operation(summary = "近7日销售额", description = "折线图展示近7个自然日,每个一级分类下所有商品的销售额汇总")
+    public BaseResult<DailySalesAmountVo> getDailySalesAmount() {
+        return BaseResult.success(kwBiReportService.getDailySalesAmount());
+    }
+
+    @GetMapping("/goodsSalesVolumeRatio")
+    @Operation(summary = "主要商品销量占比", description = "饼状图展示,按最低级分类统计历史完成订单的净重总和,取前5名")
+    public BaseResult<GoodsSalesVolumeRatioVo> getGoodsSalesVolumeRatio() {
+        return BaseResult.success(kwBiReportService.getGoodsSalesVolumeRatio());
+    }
+
+    @GetMapping("/goodsSalesAmountRatio")
+    @Operation(summary = "主要商品销售金额占比", description = "饼状图展示,按最低级分类统计历史完成订单的销售金额总和,取前5名")
+    public BaseResult<GoodsSalesAmountRatioVo> getGoodsSalesAmountRatio() {
+        return BaseResult.success(kwBiReportService.getGoodsSalesAmountRatio());
+    }
+}

+ 28 - 0
sckw-modules/sckw-report/src/main/java/com/sckw/report/model/vo/DailySalesAmountVo.java

@@ -0,0 +1,28 @@
+package com.sckw.report.model.vo;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+import java.math.BigDecimal;
+import java.util.List;
+
+@Data
+@Schema(description = "近7日销售额响应")
+public class DailySalesAmountVo {
+
+    @Schema(description = "日期列表")
+    private List<String> dates;
+
+    @Schema(description = "分类数据列表")
+    private List<SalesCategoryData> categoryDataList;
+
+    @Data
+    @Schema(description = "分类销售额数据")
+    public static class SalesCategoryData {
+        @Schema(description = "一级分类名称")
+        private String categoryName;
+
+        @Schema(description = "销售额列表(元)")
+        private List<BigDecimal> amounts;
+    }
+}

+ 28 - 0
sckw-modules/sckw-report/src/main/java/com/sckw/report/model/vo/DailyShipmentAmountVo.java

@@ -0,0 +1,28 @@
+package com.sckw.report.model.vo;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+import java.math.BigDecimal;
+import java.util.List;
+
+@Data
+@Schema(description = "近7日出货量响应")
+public class DailyShipmentAmountVo {
+
+    @Schema(description = "日期列表")
+    private List<String> dates;
+
+    @Schema(description = "分类数据列表")
+    private List<ShipmentCategoryData> categoryDataList;
+
+    @Data
+    @Schema(description = "分类出货量数据")
+    public static class ShipmentCategoryData {
+        @Schema(description = "一级分类名称")
+        private String categoryName;
+
+        @Schema(description = "出货量列表(吨)")
+        private List<BigDecimal> amounts;
+    }
+}

+ 28 - 0
sckw-modules/sckw-report/src/main/java/com/sckw/report/model/vo/GoodsSalesAmountRatioVo.java

@@ -0,0 +1,28 @@
+package com.sckw.report.model.vo;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+import java.math.BigDecimal;
+import java.util.List;
+
+@Data
+@Schema(description = "主要商品销售金额占比响应")
+public class GoodsSalesAmountRatioVo {
+
+    @Schema(description = "商品销售金额占比列表")
+    private List<GoodsAmountRatioItem> ratioList;
+
+    @Data
+    @Schema(description = "商品销售金额占比项")
+    public static class GoodsAmountRatioItem {
+        @Schema(description = "商品名称(最低级分类)")
+        private String goodsName;
+
+        @Schema(description = "销售金额(元)")
+        private BigDecimal amount;
+
+        @Schema(description = "占比(%)")
+        private BigDecimal percentage;
+    }
+}

+ 28 - 0
sckw-modules/sckw-report/src/main/java/com/sckw/report/model/vo/GoodsSalesVolumeRatioVo.java

@@ -0,0 +1,28 @@
+package com.sckw.report.model.vo;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+import java.math.BigDecimal;
+import java.util.List;
+
+@Data
+@Schema(description = "主要商品销量占比响应")
+public class GoodsSalesVolumeRatioVo {
+
+    @Schema(description = "商品销量占比列表")
+    private List<GoodsVolumeRatioItem> ratioList;
+
+    @Data
+    @Schema(description = "商品销量占比项")
+    public static class GoodsVolumeRatioItem {
+        @Schema(description = "商品名称(最低级分类)")
+        private String goodsName;
+
+        @Schema(description = "销量(吨)")
+        private BigDecimal volume;
+
+        @Schema(description = "占比(%)")
+        private BigDecimal percentage;
+    }
+}

+ 17 - 0
sckw-modules/sckw-report/src/main/java/com/sckw/report/service/KwBiReportService.java

@@ -0,0 +1,17 @@
+package com.sckw.report.service;
+
+import com.sckw.report.model.vo.DailySalesAmountVo;
+import com.sckw.report.model.vo.DailyShipmentAmountVo;
+import com.sckw.report.model.vo.GoodsSalesAmountRatioVo;
+import com.sckw.report.model.vo.GoodsSalesVolumeRatioVo;
+
+public interface KwBiReportService {
+
+    DailyShipmentAmountVo getDailyShipmentAmount();
+
+    DailySalesAmountVo getDailySalesAmount();
+
+    GoodsSalesVolumeRatioVo getGoodsSalesVolumeRatio();
+
+    GoodsSalesAmountRatioVo getGoodsSalesAmountRatio();
+}

+ 198 - 0
sckw-modules/sckw-report/src/main/java/com/sckw/report/service/impl/KwBiReportServiceImpl.java

@@ -0,0 +1,198 @@
+package com.sckw.report.service.impl;
+
+import com.sckw.core.web.context.LoginUserHolder;
+import com.sckw.core.web.response.BaseResult;
+import com.sckw.order.api.feign.OrderStatisticsFeignService;
+import com.sckw.order.api.model.DailySalesStatisticsDto;
+import com.sckw.order.api.model.DailyShipmentStatisticsDto;
+import com.sckw.order.api.model.GoodsAmountStatisticsDto;
+import com.sckw.order.api.model.GoodsVolumeStatisticsDto;
+import com.sckw.report.model.vo.*;
+import com.sckw.report.service.KwBiReportService;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.math.BigDecimal;
+import java.math.RoundingMode;
+import java.time.LocalDate;
+import java.time.format.DateTimeFormatter;
+import java.util.*;
+import java.util.stream.Collectors;
+
+@Service
+@Slf4j
+@RequiredArgsConstructor
+public class KwBiReportServiceImpl implements KwBiReportService {
+
+    @Autowired
+    private OrderStatisticsFeignService orderStatisticsFeignService;
+
+    @Override
+    public DailyShipmentAmountVo getDailyShipmentAmount() {
+        Long entId = LoginUserHolder.getEntId();
+        BaseResult<List<DailyShipmentStatisticsDto>> result = orderStatisticsFeignService.getDailyShipmentByCategory(entId, 7);
+        
+        DailyShipmentAmountVo vo = new DailyShipmentAmountVo();
+        List<String> dates = generateLast7Days();
+        vo.setDates(dates);
+
+        if (result == null || !result.isSuccess() || result.getData() == null) {
+            vo.setCategoryDataList(Collections.emptyList());
+            return vo;
+        }
+
+        Map<String, Map<String, BigDecimal>> dataMap = result.getData().stream()
+                .collect(Collectors.groupingBy(
+                        DailyShipmentStatisticsDto::getGoodsType,
+                        Collectors.toMap(
+                                DailyShipmentStatisticsDto::getOrderDate,
+                                DailyShipmentStatisticsDto::getActualAmount,
+                                BigDecimal::add
+                        )
+                ));
+
+        List<DailyShipmentAmountVo.ShipmentCategoryData> categoryDataList = new ArrayList<>();
+        dataMap.forEach((category, dateAmountMap) -> {
+            DailyShipmentAmountVo.ShipmentCategoryData data = new DailyShipmentAmountVo.ShipmentCategoryData();
+            data.setCategoryName(category);
+            
+            List<BigDecimal> amounts = new ArrayList<>();
+            for (String date : dates) {
+                amounts.add(dateAmountMap.getOrDefault(date, BigDecimal.ZERO));
+            }
+            data.setAmounts(amounts);
+            categoryDataList.add(data);
+        });
+        vo.setCategoryDataList(categoryDataList);
+
+        return vo;
+    }
+
+    @Override
+    public DailySalesAmountVo getDailySalesAmount() {
+        Long entId = LoginUserHolder.getEntId();
+        BaseResult<List<DailySalesStatisticsDto>> result = orderStatisticsFeignService.getDailySalesByCategory(entId, 7);
+
+        DailySalesAmountVo vo = new DailySalesAmountVo();
+        List<String> dates = generateLast7Days();
+        vo.setDates(dates);
+
+        if (result == null || !result.isSuccess() || result.getData() == null) {
+            vo.setCategoryDataList(Collections.emptyList());
+            return vo;
+        }
+
+        Map<String, Map<String, BigDecimal>> dataMap = result.getData().stream()
+                .collect(Collectors.groupingBy(
+                        DailySalesStatisticsDto::getGoodsType,
+                        Collectors.toMap(
+                                DailySalesStatisticsDto::getOrderDate,
+                                DailySalesStatisticsDto::getSalesAmount,
+                                BigDecimal::add
+                        )
+                ));
+
+        List<DailySalesAmountVo.SalesCategoryData> categoryDataList = new ArrayList<>();
+        dataMap.forEach((category, dateAmountMap) -> {
+            DailySalesAmountVo.SalesCategoryData data = new DailySalesAmountVo.SalesCategoryData();
+            data.setCategoryName(category);
+
+            List<BigDecimal> amounts = new ArrayList<>();
+            for (String date : dates) {
+                amounts.add(dateAmountMap.getOrDefault(date, BigDecimal.ZERO));
+            }
+            data.setAmounts(amounts);
+            categoryDataList.add(data);
+        });
+        vo.setCategoryDataList(categoryDataList);
+
+        return vo;
+    }
+
+    @Override
+    public GoodsSalesVolumeRatioVo getGoodsSalesVolumeRatio() {
+        Long entId = LoginUserHolder.getEntId();
+        BaseResult<List<GoodsVolumeStatisticsDto>> result = orderStatisticsFeignService.getGoodsVolumeTop5(entId);
+
+        GoodsSalesVolumeRatioVo vo = new GoodsSalesVolumeRatioVo();
+
+        if (result == null || !result.isSuccess() || result.getData() == null || result.getData().isEmpty()) {
+            vo.setRatioList(Collections.emptyList());
+            return vo;
+        }
+
+        List<GoodsVolumeStatisticsDto> dataList = result.getData();
+        BigDecimal totalVolume = dataList.stream()
+                .map(dto -> dto.getTotalVolume() != null ? dto.getTotalVolume() : BigDecimal.ZERO)
+                .reduce(BigDecimal.ZERO, BigDecimal::add);
+
+        List<GoodsSalesVolumeRatioVo.GoodsVolumeRatioItem> ratioList = new ArrayList<>();
+        for (GoodsVolumeStatisticsDto dto : dataList) {
+            GoodsSalesVolumeRatioVo.GoodsVolumeRatioItem item = new GoodsSalesVolumeRatioVo.GoodsVolumeRatioItem();
+            item.setGoodsName(dto.getGoodsName());
+            item.setVolume(dto.getTotalVolume() != null ? dto.getTotalVolume() : BigDecimal.ZERO);
+            
+            BigDecimal percentage = BigDecimal.ZERO;
+            if (totalVolume.compareTo(BigDecimal.ZERO) > 0) {
+                percentage = item.getVolume().multiply(new BigDecimal("100"))
+                        .divide(totalVolume, 2, RoundingMode.HALF_UP);
+            }
+            item.setPercentage(percentage);
+            ratioList.add(item);
+        }
+
+        vo.setRatioList(ratioList);
+        return vo;
+    }
+
+    @Override
+    public GoodsSalesAmountRatioVo getGoodsSalesAmountRatio() {
+        Long entId = LoginUserHolder.getEntId();
+        BaseResult<List<GoodsAmountStatisticsDto>> result = orderStatisticsFeignService.getGoodsAmountTop5(entId);
+
+        GoodsSalesAmountRatioVo vo = new GoodsSalesAmountRatioVo();
+
+        if (result == null || !result.isSuccess() || result.getData() == null || result.getData().isEmpty()) {
+            vo.setRatioList(Collections.emptyList());
+            return vo;
+        }
+
+        List<GoodsAmountStatisticsDto> dataList = result.getData();
+        BigDecimal totalAmount = dataList.stream()
+                .map(dto -> dto.getTotalAmount() != null ? dto.getTotalAmount() : BigDecimal.ZERO)
+                .reduce(BigDecimal.ZERO, BigDecimal::add);
+
+        List<GoodsSalesAmountRatioVo.GoodsAmountRatioItem> ratioList = new ArrayList<>();
+        for (GoodsAmountStatisticsDto dto : dataList) {
+            GoodsSalesAmountRatioVo.GoodsAmountRatioItem item = new GoodsSalesAmountRatioVo.GoodsAmountRatioItem();
+            item.setGoodsName(dto.getGoodsName());
+            item.setAmount(dto.getTotalAmount() != null ? dto.getTotalAmount() : BigDecimal.ZERO);
+
+            BigDecimal percentage = BigDecimal.ZERO;
+            if (totalAmount.compareTo(BigDecimal.ZERO) > 0) {
+                percentage = item.getAmount().multiply(new BigDecimal("100"))
+                        .divide(totalAmount, 2, RoundingMode.HALF_UP);
+            }
+            item.setPercentage(percentage);
+            ratioList.add(item);
+        }
+
+        vo.setRatioList(ratioList);
+        return vo;
+    }
+
+    private List<String> generateLast7Days() {
+        List<String> dates = new ArrayList<>();
+        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("MM/dd");
+        LocalDate today = LocalDate.now();
+        
+        for (int i = 6; i >= 0; i--) {
+            LocalDate date = today.minusDays(i);
+            dates.add(date.format(formatter));
+        }
+        
+        return dates;
+    }
+}