From 0c1e195b5d2a56109253a2dd8dc03ab9de8ea1bf Mon Sep 17 00:00:00 2001
From: youjie <272855983@qq.com>
Date: Mon, 19 Feb 2024 13:59:57 +0800
Subject: [PATCH] 增加物料热度报表

---
 ant-design-vue-jeecg/src/views/system/report/ReportInventoryTransactionList.vue              | 324 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 ant-design-vue-jeecg/src/views/system/task/AllTaskHeaderList.vue                             | 181 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-------------------------------------------------------------------------------------------
 huaheng-wms-core/src/main/java/org/jeecg/modules/wms/report/controller/ReportController.java | 111 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 525 insertions(+), 91 deletions(-)
 create mode 100644 ant-design-vue-jeecg/src/views/system/report/ReportInventoryTransactionList.vue
 create mode 100644 huaheng-wms-core/src/main/java/org/jeecg/modules/wms/report/controller/ReportController.java

diff --git a/ant-design-vue-jeecg/src/views/system/report/ReportInventoryTransactionList.vue b/ant-design-vue-jeecg/src/views/system/report/ReportInventoryTransactionList.vue
new file mode 100644
index 0000000..3082b1e
--- /dev/null
+++ b/ant-design-vue-jeecg/src/views/system/report/ReportInventoryTransactionList.vue
@@ -0,0 +1,324 @@
+<template>
+  <a-card :bordered="false">
+    <!-- 查询区域 -->
+    <div class="table-page-search-wrapper">
+      <a-form layout="inline" @keyup.enter.native="searchQuery">
+        <a-row :gutter="24">
+          <a-col :xl="6" :lg="7" :md="8" :sm="24">
+            <a-form-item label="物料编码">
+              <a-input placeholder="请输入物料编码" v-model="queryParam.materialCode"></a-input>
+            </a-form-item>
+          </a-col>
+            <a-col :xl="6" :lg="7" :md="8" :sm="24">
+              <a-form-item label="物料名称">
+                <a-input placeholder="请输入物料名称" v-model="queryParam.materialName"></a-input>
+              </a-form-item>
+            </a-col>
+            <a-col :xl="6" :lg="7" :md="8" :sm="24">
+              <a-form-item label="物料规格">
+                <a-input placeholder="请输入物料规格" v-model="queryParam.materialSpec"></a-input>
+              </a-form-item>
+            </a-col>
+            <a-col :xl="6" :lg="7" :md="8" :sm="24">
+              <a-form-item label="物料单位">
+                <a-input placeholder="请输入物料单位" v-model="queryParam.materialUnit"></a-input>
+              </a-form-item>
+            </a-col>
+          <a-col :xl="12" :lg="14" :md="16" :sm="24">
+            <a-form-item label="创建日期">
+              <j-date :show-date="true" date-format="YYYY-MM-DD" placeholder="请选择开始时间"
+                      class="query-group-cust" v-model="queryParam.createTime_begin"></j-date>
+              <span class="query-group-split-cust"></span>
+              <j-date :show-date="true" date-format="YYYY-MM-DD" placeholder="请选择结束时间"
+                      class="query-group-cust" v-model="queryParam.createTime_end"></j-date>
+            </a-form-item>
+          </a-col>
+          <a-col :xl="6" :lg="7" :md="8" :sm="24">
+            <span style="float: left;overflow: hidden;" class="table-page-search-submitButtons">
+              <a-button id="search" type="primary" @click="searchQuery" icon="search">查询</a-button>
+              <a-button type="primary" @click="searchReset" icon="reload" style="margin-left: 8px">重置</a-button>
+<!--              <a @click="handleToggleSearch" style="margin-left: 8px">-->
+<!--                {{ toggleSearchStatus ? '收起' : '展开' }}-->
+<!--                <a-icon :type="toggleSearchStatus ? 'up' : 'down'"/>-->
+<!--              </a>-->
+            </span>
+          </a-col>
+        </a-row>
+      </a-form>
+    </div>
+    <!-- 查询区域-END -->
+
+<!--    &lt;!&ndash; 操作按钮区域 &ndash;&gt;-->
+<!--    <div class="table-operator">-->
+<!--      <a-button v-has="'inventoryTransaction:export'" type="primary" icon="download"-->
+<!--                @click="handleExportXls('库存交易记录')">导出-->
+<!--      </a-button>-->
+<!--      <a-upload v-has="'inventoryTransaction:import'" name="file" :showUploadList="false" :multiple="false"-->
+<!--                :headers="tokenHeader" :action="importExcelUrl" @change="handleImportExcel">-->
+<!--        <a-button type="primary" icon="import">导入</a-button>-->
+<!--      </a-upload>-->
+<!--      <j-super-query :fieldList="superFieldList" v-has="'inventoryTransaction:superQuery'"-->
+<!--                     @handleSuperQuery="handleSuperQuery"/>-->
+<!--    </div>-->
+
+    <!-- table区域-begin -->
+    <div>
+      <a-table
+        ref="table"
+        size="middle"
+        :scroll="{x:true}"
+        bordered
+        rowKey="id"
+        :columns="columns"
+        :dataSource="dataSource"
+        :pagination="ipagination"
+        :loading="loading"
+        class="j-table-force-nowrap"
+        @change="handleTableChange">
+
+        <span slot="inventoryStatus_dictText" slot-scope="inventoryStatus_dictText">
+          <a-tag :key="inventoryStatus_dictText" :color="getStatusColor(inventoryStatus_dictText)">
+            {{ inventoryStatus_dictText }}
+          </a-tag>
+        </span>
+
+        <span slot="companyCode" slot-scope="companyCode">
+          <a-tag :key="companyCode" color=blue>
+            {{ solutionCompany(companyCode) }}
+          </a-tag>
+        </span>
+
+        <span slot="zoneCode" slot-scope="zoneCode">
+          <a-tag :key="zoneCode" color="blue">
+            {{ solutionZoneCode(zoneCode) }}
+          </a-tag>
+        </span>
+        <template slot="htmlSlot" slot-scope="text">
+          <div v-html="text"></div>
+        </template>
+        <template slot="imgSlot" slot-scope="text">
+          <span v-if="!text" style="font-size: 12px;font-style: italic;">无图片</span>
+          <img v-else :src="getImgView(text)" height="25px" alt=""
+               style="max-width:80px;font-size: 12px;font-style: italic;"/>
+        </template>
+        <template slot="fileSlot" slot-scope="text">
+          <span v-if="!text" style="font-size: 12px;font-style: italic;">无文件</span>
+          <a-button
+            v-else
+            :ghost="true"
+            type="primary"
+            icon="download"
+            size="small"
+            @click="downloadFile(text)">
+            下载
+          </a-button>
+        </template>
+        <span slot="action" slot-scope="text, record">
+          <a v-has="'inventoryTransaction:edit'" @click="handleEdit(record)">编辑<a-divider type="vertical"/></a>
+          <a-dropdown>
+            <a class="ant-dropdown-link">更多 <a-icon type="down"/></a>
+            <a-menu slot="overlay">
+              <a-menu-item>
+                <a @click="handleDetail(record)">详情</a>
+              </a-menu-item>
+              <a-menu-item v-has="'inventoryTransaction:delete'">
+                <a-popconfirm title="确定删除吗?" @confirm="() => handleDelete(record.id)">
+                  <a>删除</a>
+                </a-popconfirm>
+              </a-menu-item>
+            </a-menu>
+          </a-dropdown>
+        </span>
+      </a-table>
+    </div>
+
+    <inventory-transaction-modal ref="modalForm" @ok="modalFormOk"></inventory-transaction-modal>
+  </a-card>
+</template>
+
+<script>
+
+import '@/assets/less/TableExpand.less'
+import {mixinDevice} from '@/utils/mixin'
+import {JeecgListMixin} from '@/mixins/JeecgListMixin'
+import {filterMultiDictText} from '@/components/dict/JDictSelectUtil'
+import {getCompanyList, getZoneList} from '@/api/api'
+
+export default {
+  name: 'InventoryTransactionList',
+  mixins: [JeecgListMixin, mixinDevice],
+  components: {
+
+  },
+  data() {
+    return {
+      description: '库存交易记录管理页面',
+      companyList: [],
+      zoneList: [],
+      zoneOptions: [],
+      firstLoad:0,
+      // 表头
+      columns: [
+        {
+          title: '物料编码',
+          align: "center",
+          dataIndex: 'materialCode'
+        },
+        {
+          title: '物料名称',
+          align: "center",
+          dataIndex: 'materialName'
+        },
+        {
+          title: '物料规格',
+          align: "center",
+          dataIndex: 'materialSpec'
+        },
+        {
+          title: '物料单位',
+          align: "center",
+          dataIndex: 'materialUnit'
+        },
+        {
+          title: '出入库总数',
+          align: "center",
+          dataIndex: 'qty'
+        },
+        {
+          title: '入库数量',
+          align: "center",
+          dataIndex: 'receiptQty'
+        },
+        {
+          title: '出库数量',
+          align: "center",
+          dataIndex: 'shipmentQty'
+        },
+        // {
+        //   title: '本托盘库存数量',
+        //   align: "center",
+        //   dataIndex: 'containerInventoryQty'
+        // },
+        // {
+        //   title: '库存总数',
+        //   align: "center",
+        //   dataIndex: 'inventoryQty'
+        // },
+        // {
+        //   title: '操作',
+        //   dataIndex: 'action',
+        //   align: "center",
+        //   fixed: "right",
+        //   width: 147,
+        //   scopedSlots: {customRender: 'action'}
+        // }
+      ],
+      url: {
+        list: "/report/inventoryTransaction/list",
+      },
+      dictOptions: {},
+      superFieldList: [],
+    }
+  },
+  created() {
+    this.getSuperFieldList();
+    this.loadFrom();
+  },
+  mounted() {
+    if(this.firstLoad == 0) {
+      this.firstLoad = 1;
+      return;
+    }
+    //页面没加载完,此时methods里的方法找不到,使用定时器模拟点击
+    let timeSearch=setInterval(()=>{
+      let eleSearch= document.getElementById("search");
+      if (eleSearch!=null){
+        //调用成功,清除定时器
+        clearInterval(timeSearch)
+        eleSearch.click();
+      }
+    },200)
+  },
+  computed: {
+    importExcelUrl: function () {
+      return `${window._CONFIG['domianURL']}/${this.url.importExcelUrl}`;
+    },
+  },
+  methods: {
+    getStatusColor(status) {
+      const colors = {
+        '良品': 'green',
+        '报废品': 'purple',
+        '待确认	': 'grey',
+        '次品': 'red',
+        default: 'blue'
+      };
+      return colors[status] || colors.default;
+    },
+    initDictConfig() {
+    },
+    loadFrom() {
+      getZoneList().then((res) => {
+        if (res.success) {
+          this.zoneList = res.result
+          //延迟半秒执行,避免组件未加载完,数据已经加载完
+          setTimeout(() => {
+            //slice可以在数组的任何位置进行删除/添加操作
+            this.zoneOptions.splice(0, 1);
+            for (let i = 0; i < res.result.length; i++) {
+              this.zoneOptions.push({value: res.result[i].code, text: res.result[i].name})
+            }
+          }, 500)
+        }
+      });
+      getCompanyList().then((res) => {
+        if (res.success) {
+          this.companyList = res.result
+        }
+      });
+    },
+    solutionZoneCode(value) {
+      var actions = []
+      Object.keys(this.zoneList).some(key => {
+        if (this.zoneList[key].code === '' + value) {
+          actions.push(this.zoneList[key].name)
+          return true
+        }
+      })
+      return actions.join('')
+    },
+    solutionCompany(value) {
+      var actions = []
+      Object.keys(this.companyList).some((key) => {
+        if (this.companyList[key].code == ('' + value)) {
+          actions.push(this.companyList[key].name)
+          return true
+        }
+      })
+      return actions.join('')
+    },
+    getSuperFieldList() {
+      let fieldList = [];
+      fieldList.push({type: 'string', value: 'companyCode', text: '货主', dictCode: ''})
+      fieldList.push({type: 'string', value: 'containerCode', text: '容器编码', dictCode: ''})
+      fieldList.push({type: 'string', value: 'locationCode', text: '库位编码', dictCode: ''})
+      fieldList.push({type: 'int', value: 'type', text: '交易类型', dictCode: 'inventory_transaction_type'})
+      fieldList.push({type: 'string', value: 'materialCode', text: '物料编码', dictCode: ''})
+      fieldList.push({type: 'string', value: 'materialName', text: '物料名称', dictCode: ''})
+      fieldList.push({type: 'string', value: 'materialSpec', text: '物料规格', dictCode: ''})
+      fieldList.push({type: 'string', value: 'materialUnit', text: '物料单位', dictCode: ''})
+      fieldList.push({type: 'string', value: 'inventoryStatus', text: '库存状态', dictCode: 'inventory_status'})
+      fieldList.push({type: 'BigDecimal', value: 'qty', text: '数量', dictCode: ''})
+      fieldList.push({type: 'string', value: 'batch', text: '批次', dictCode: ''})
+      fieldList.push({type: 'string', value: 'createBy', text: '创建人', dictCode: ''})
+      fieldList.push({type: 'datetime', value: 'createTime', text: '创建日期'})
+      fieldList.push({type: 'string', value: 'updateBy', text: '更新人', dictCode: ''})
+      fieldList.push({type: 'datetime', value: 'updateTime', text: '更新日期'})
+      this.superFieldList = fieldList
+    }
+  }
+}
+</script>
+<style scoped>
+@import '~@assets/less/common.less';
+</style>
\ No newline at end of file
diff --git a/ant-design-vue-jeecg/src/views/system/task/AllTaskHeaderList.vue b/ant-design-vue-jeecg/src/views/system/task/AllTaskHeaderList.vue
index 5cd8ee2..8fa00af 100644
--- a/ant-design-vue-jeecg/src/views/system/task/AllTaskHeaderList.vue
+++ b/ant-design-vue-jeecg/src/views/system/task/AllTaskHeaderList.vue
@@ -161,7 +161,6 @@
             <a-divider type="vertical"/></a>
           <a v-if="record.isDoubleIn == 1 && record.exceptionState == 1" v-has="'taskHeader:executeTask'" @click="handleDoubleInTask(record)"><a-button type="danger">修复重入数据</a-button>
             <a-divider type="vertical"/></a>
-          <!--          <a v-if="record.status <= 10" v-has="'taskHeader:cancelTask'" @click="cancelTask(record)" >取消</a>-->
           <a-popconfirm v-if="record.status <= 10" v-has="'taskHeader:cancelTask'" title="确定取消任务吗?" @confirm="() => cancelTask(record)">
            <a-button type="danger">取消</a-button>
           </a-popconfirm>
@@ -233,23 +232,23 @@ export default {
           align: "center",
           dataIndex: 'taskType_dictText',
           scopedSlots: {customRender: 'taskType_dictText'},
-          filterMultiple: false,
-          filters: [
-            {text: '整盘入库', value: '100'},
-            {text: '补充入库', value: '200'},
-            {text: '空容器入库', value: '500'},
-            {text: '空托盘组入库', value: '1100'},
-            {text: '整盘出库', value: '300'},
-            {text: '分拣出库', value: '400'},
-            {text: '空容器出库', value: '600'},
-            {text: '空托盘组出库', value: '1200'},
-            {text: '移库', value: '800'},
-            {text: '换站', value: '1000'},
-            {text: '空托盘组换站', value: '1300'},
-            {text: '盘点', value: '700'},
-            {text: '质检', value: '1400'},
-            {text: '出库查看', value: '900'},
-          ]
+          // filterMultiple: false,
+          // filters: [
+          //   {text: '整盘入库', value: '100'},
+          //   {text: '补充入库', value: '200'},
+          //   {text: '空容器入库', value: '500'},
+          //   {text: '空托盘组入库', value: '1100'},
+          //   {text: '整盘出库', value: '300'},
+          //   {text: '分拣出库', value: '400'},
+          //   {text: '空容器出库', value: '600'},
+          //   {text: '空托盘组出库', value: '1200'},
+          //   {text: '移库', value: '800'},
+          //   {text: '换站', value: '1000'},
+          //   {text: '空托盘组换站', value: '1300'},
+          //   {text: '盘点', value: '700'},
+          //   {text: '质检', value: '1400'},
+          //   {text: '出库查看', value: '900'},
+          // ]
         },
         {
           title: '容器编码',
@@ -341,14 +340,14 @@ export default {
           align: "center",
           dataIndex: 'completeTime'
         },
-        // {
-        //   title: '操作',
-        //   dataIndex: 'action',
-        //   align: "center",
-        //   fixed: "right",
-        //   width: 147,
-        //   scopedSlots: {customRender: 'action'},
-        // }
+         {
+           title: '操作',
+           dataIndex: 'action',
+           align: "center",
+           fixed: "right",
+           width: 147,
+           scopedSlots: {customRender: 'action'},
+         }
       ],
       url: {
         list: "/task/taskHeader/list",
@@ -522,71 +521,71 @@ export default {
       })
       return actions.join('')
     },
-    // cancelTask(record) {
-    //   this.loading = true;
-    //   this.model = Object.assign({}, record);
-    //   cancelTask(this.model.id).then((res) => {
-    //     this.loading = false;
-    //     if (res.success) {
-    //       this.$message.success(res.message);
-    //     } else {
-    //       this.$message.error(res.message);
-    //     }
-    //     this.searchQuery();
-    //   });
-    // },
-    // executeTask(record) {
-    //   this.loading = true;
-    //   this.model = Object.assign({}, record);
-    //   execute(this.model).then((res) => {
-    //     this.loading = false;
-    //     if (res.success) {
-    //       this.$message.success(res.message);
-    //     } else {
-    //       this.$message.error(res.message);
-    //     }
-    //     this.searchQuery();
-    //   });
-    // },
-    // handleEmptyOutTask(record) {
-    //   this.loading = true;
-    //   this.model = Object.assign({}, record);
-    //   handleEmptyOut(this.model.id).then((res) => {
-    //     this.loading = false;
-    //     if (res.success) {
-    //       this.$message.success(res.message);
-    //     } else {
-    //       this.$message.error(res.message);
-    //     }
-    //     this.searchQuery();
-    //   });
-    // },
-    // handlePickupErrorTask(record) {
-    //   this.loading = true;
-    //   this.model = Object.assign({}, record);
-    //   handlePickupError(this.model.id).then((res) => {
-    //     this.loading = false;
-    //     if (res.success) {
-    //       this.$message.success(res.message);
-    //     } else {
-    //       this.$message.error(res.message);
-    //     }
-    //     this.searchQuery();
-    //   });
-    // },
-    // handleDoubleInTask(record) {
-    //   this.loading = true;
-    //   this.model = Object.assign({}, record);
-    //   handleDoubleIn(this.model.id).then((res) => {
-    //     this.loading = false;
-    //     if (res.success) {
-    //       this.$message.success(res.message);
-    //     } else {
-    //       this.$message.error(res.message);
-    //     }
-    //     this.searchQuery();
-    //   });
-    // },
+    cancelTask(record) {
+      this.loading = true;
+      this.model = Object.assign({}, record);
+      cancelTask(this.model.id).then((res) => {
+        this.loading = false;
+        if (res.success) {
+          this.$message.success(res.message);
+        } else {
+          this.$message.error(res.message);
+        }
+        this.searchQuery();
+      });
+    },
+    executeTask(record) {
+      this.loading = true;
+      this.model = Object.assign({}, record);
+      execute(this.model).then((res) => {
+        this.loading = false;
+        if (res.success) {
+          this.$message.success(res.message);
+        } else {
+          this.$message.error(res.message);
+        }
+        this.searchQuery();
+      });
+    },
+    handleEmptyOutTask(record) {
+      this.loading = true;
+      this.model = Object.assign({}, record);
+      handleEmptyOut(this.model.id).then((res) => {
+        this.loading = false;
+        if (res.success) {
+          this.$message.success(res.message);
+        } else {
+          this.$message.error(res.message);
+        }
+        this.searchQuery();
+      });
+    },
+    handlePickupErrorTask(record) {
+      this.loading = true;
+      this.model = Object.assign({}, record);
+      handlePickupError(this.model.id).then((res) => {
+        this.loading = false;
+        if (res.success) {
+          this.$message.success(res.message);
+        } else {
+          this.$message.error(res.message);
+        }
+        this.searchQuery();
+      });
+    },
+    handleDoubleInTask(record) {
+      this.loading = true;
+      this.model = Object.assign({}, record);
+      handleDoubleIn(this.model.id).then((res) => {
+        this.loading = false;
+        if (res.success) {
+          this.$message.success(res.message);
+        } else {
+          this.$message.error(res.message);
+        }
+        this.searchQuery();
+      });
+    },
     getSuperFieldList() {
       let fieldList = [];
       fieldList.push({type: 'int', value: 'taskType', text: '任务类型', dictCode: 'task_type'})
diff --git a/huaheng-wms-core/src/main/java/org/jeecg/modules/wms/report/controller/ReportController.java b/huaheng-wms-core/src/main/java/org/jeecg/modules/wms/report/controller/ReportController.java
new file mode 100644
index 0000000..7763951
--- /dev/null
+++ b/huaheng-wms-core/src/main/java/org/jeecg/modules/wms/report/controller/ReportController.java
@@ -0,0 +1,111 @@
+package org.jeecg.modules.wms.report.controller;
+
+import java.math.BigDecimal;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
+
+import javax.annotation.Resource;
+import javax.servlet.http.HttpServletRequest;
+
+import org.jeecg.common.api.vo.Result;
+import org.jeecg.common.system.base.controller.JeecgController;
+import org.jeecg.common.system.query.QueryGenerator;
+import org.jeecg.modules.wms.config.material.entity.Material;
+import org.jeecg.modules.wms.config.material.service.IMaterialService;
+import org.jeecg.modules.wms.config.parameterConfiguration.service.IParameterConfigurationService;
+import org.jeecg.modules.wms.inventory.inventoryTransaction.entity.InventoryTransaction;
+import org.jeecg.modules.wms.inventory.inventoryTransaction.service.IInventoryTransactionService;
+import org.jeecg.utils.HuahengJwtUtil;
+import org.jeecg.utils.StringUtils;
+import org.jeecg.utils.constant.QuantityConstant;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.RestController;
+
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import lombok.extern.slf4j.Slf4j;
+
+/**
+ * @author 游杰
+ */
+@Api(tags = "报表记录")
+@RestController
+@RequestMapping("/report/inventoryTransaction")
+@Slf4j
+public class ReportController extends JeecgController<InventoryTransaction, IInventoryTransactionService> {
+    @Autowired
+    private IInventoryTransactionService inventoryTransactionService;
+
+    @Resource
+    private HuahengJwtUtil huahengJwtUtil;
+
+    @Resource
+    private IParameterConfigurationService parameterConfigurationService;
+    @Resource
+    private IMaterialService materialService;
+
+    /**
+     * 分页列表查询
+     * @param  inventoryTransaction
+     * @param  pageNo
+     * @param  pageSize
+     * @param  req
+     * @return
+     */
+    // @AutoLog(value = "库存交易记录-分页列表查询")
+    @ApiOperation(value = "库存交易记录-分页列表查询", notes = "库存交易记录-分页列表查询")
+    @GetMapping(value = "/list")
+    public Result queryPageList(InventoryTransaction inventoryTransaction, @RequestParam(name = "pageNo", defaultValue = "1") Integer pageNo,
+        @RequestParam(name = "pageSize", defaultValue = "10") Integer pageSize, HttpServletRequest req) {
+        QueryWrapper<InventoryTransaction> queryWrapper = QueryGenerator.initQueryWrapper(inventoryTransaction, req.getParameterMap());
+        List<InventoryTransaction> inventoryTransactionList = inventoryTransactionService.list(queryWrapper);
+        if (CollectionUtils.isEmpty(inventoryTransactionList)) {
+            return Result.error("没有找到库存热度记录");
+        }
+        List<String> materialCodeList = inventoryTransactionList.stream().map(InventoryTransaction::getMaterialCode).distinct().collect(Collectors.toList());
+        Map<Integer, List<InventoryTransaction>> inventoryTransactionMap =
+            inventoryTransactionList.stream().collect(Collectors.groupingBy(InventoryTransaction::getType));
+        List<InventoryTransaction> receiptInventoryTransactionList = inventoryTransactionMap.get(QuantityConstant.INVENTORY_TRANSACTION_RECEIPT);
+        List<InventoryTransaction> shipmentInventoryTransactionList = inventoryTransactionMap.get(QuantityConstant.INVENTORY_TRANSACTION_SHIPMENT);
+        List<InventoryTransaction> inventoryTransactionList1 = new ArrayList<>();
+        for (String materialCode : materialCodeList) {
+            BigDecimal receiptQty = BigDecimal.ZERO;
+            BigDecimal shipmentQty = BigDecimal.ZERO;
+            if (StringUtils.isNotEmpty(receiptInventoryTransactionList)) {
+                receiptQty = receiptInventoryTransactionList.stream().filter(o -> materialCode.equals(o.getMaterialCode())).map(InventoryTransaction::getQty)
+                    .reduce(BigDecimal.ZERO, BigDecimal::add);
+            }
+            if (StringUtils.isNotEmpty(shipmentInventoryTransactionList)) {
+                shipmentQty = shipmentInventoryTransactionList.stream().filter(o -> materialCode.equals(o.getMaterialCode())).map(InventoryTransaction::getQty)
+                    .reduce(BigDecimal.ZERO, BigDecimal::add);
+            }
+            BigDecimal totalQty = receiptQty.add(shipmentQty);
+            InventoryTransaction inventoryTransaction1 = new InventoryTransaction();
+            inventoryTransaction1.setReceiptQty(receiptQty);
+            inventoryTransaction1.setShipmentQty(shipmentQty);
+            inventoryTransaction1.setMaterialCode(materialCode);
+            inventoryTransaction1.setQty(totalQty);
+            Material material = materialService.getMaterialByCode(materialCode);
+            if (material != null) {
+                inventoryTransaction1.setMaterialName(material.getName());
+                inventoryTransaction1.setMaterialUnit(material.getUnit());
+                inventoryTransaction1.setMaterialSpec(material.getSpec());
+            }
+            inventoryTransactionList1.add(inventoryTransaction1);
+        }
+        Page<InventoryTransaction> page = new Page<InventoryTransaction>(pageNo, pageSize);
+        IPage<InventoryTransaction> pageList = inventoryTransactionService.page(page, queryWrapper);
+        return Result.OK(inventoryTransactionList1);
+    }
+
+}
--
libgit2 0.22.2