Commit d99565d3ea563ef3a46ec0bb14dcff5c64b6f295
1 parent
4dca1ced
bugfix:优化代码调用逻辑,减少控制层代码行数,增加redis同步物料排行接口
Showing
6 changed files
with
170 additions
and
47 deletions
src/main/java/com/huaheng/pc/config/material/service/MaterialService.java
1 | 1 | package com.huaheng.pc.config.material.service; |
2 | 2 | |
3 | +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; | |
3 | 4 | import com.huaheng.framework.web.domain.AjaxResult; |
4 | 5 | import com.huaheng.mobile.shipment.Materialforecast; |
5 | 6 | import com.huaheng.pc.config.material.domain.Material; |
6 | 7 | import com.baomidou.mybatisplus.extension.service.IService; |
8 | +import com.huaheng.pc.inventory.inventoryTransaction.domain.InventoryTransaction; | |
7 | 9 | |
8 | 10 | import java.util.List; |
9 | 11 | import java.util.Map; |
... | ... | @@ -52,4 +54,21 @@ public interface MaterialService extends IService<Material>{ |
52 | 54 | * @return |
53 | 55 | */ |
54 | 56 | Map<String, String> getPhysicalDimensionByCodes(List<String> materialCodeList); |
57 | + | |
58 | + /** | |
59 | + * 统计物料排行 | |
60 | + * @param materialCode | |
61 | + * @param createdBegin | |
62 | + * @param createdEnd | |
63 | + * @return | |
64 | + */ | |
65 | + QueryWrapper<InventoryTransaction> inventoryTurnoverAnalysis(String type ,String materialCode, String createdBegin, String createdEnd); | |
66 | + | |
67 | + /** | |
68 | + * 物料日期统计排行 | |
69 | + * @param createdBegin | |
70 | + * @param createdEnd | |
71 | + * @return | |
72 | + */ | |
73 | + QueryWrapper<InventoryTransaction> inventoryCreatedAnalysis(String type ,String createdBegin, String createdEnd); | |
55 | 74 | } |
... | ... |
src/main/java/com/huaheng/pc/config/material/service/MaterialServiceImpl.java
... | ... | @@ -2,6 +2,7 @@ package com.huaheng.pc.config.material.service; |
2 | 2 | |
3 | 3 | import cn.hutool.core.util.ReUtil; |
4 | 4 | import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; |
5 | +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; | |
5 | 6 | import com.baomidou.mybatisplus.core.toolkit.Wrappers; |
6 | 7 | import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; |
7 | 8 | import com.huaheng.common.exception.BusinessException; |
... | ... | @@ -19,6 +20,7 @@ import com.huaheng.pc.config.materialUnit.domain.MaterialUnit; |
19 | 20 | import com.huaheng.pc.config.materialUnit.service.MaterialUnitService; |
20 | 21 | import com.huaheng.pc.inventory.inventoryDetail.domain.InventoryDetail; |
21 | 22 | import com.huaheng.pc.inventory.inventoryDetail.service.InventoryDetailService; |
23 | +import com.huaheng.pc.inventory.inventoryTransaction.domain.InventoryTransaction; | |
22 | 24 | import com.huaheng.pc.receipt.receiptDetail.domain.ReceiptDetail; |
23 | 25 | import com.huaheng.pc.receipt.receiptDetail.service.ReceiptDetailService; |
24 | 26 | import org.springframework.stereotype.Service; |
... | ... | @@ -242,6 +244,36 @@ public class MaterialServiceImpl extends ServiceImpl<MaterialMapper, Material> i |
242 | 244 | .collect(Collectors.toMap(Material::getCode,Material::getPhysicalDimension)); |
243 | 245 | } |
244 | 246 | |
247 | + @Override | |
248 | + public QueryWrapper<InventoryTransaction> inventoryTurnoverAnalysis(String type ,String materialCode, String createdBegin, String createdEnd) { | |
249 | + String countSql="SUM(CASE WHEN transactionType = 10 THEN taskQty ELSE 0 END) AS inQty," + | |
250 | + "ABS(SUM(CASE WHEN transactionType = 20 THEN taskQty ELSE 0 END)) AS outQty," + | |
251 | + "SUM(CASE WHEN taskQty > 0 THEN taskQty ELSE 0 END) + ABS(SUM(CASE WHEN taskQty < 0 THEN taskQty ELSE 0 END)) AS taskQty," + | |
252 | + "materialName,materialSpec,materialUnit\n"; | |
253 | + QueryWrapper<InventoryTransaction> materialQueryWrapper = new QueryWrapper<>(); | |
254 | + | |
255 | + return materialQueryWrapper | |
256 | + .select(type,countSql) | |
257 | + //物料编码 | |
258 | + .like(StringUtils.isNotEmpty(materialCode), "materialCode", materialCode) | |
259 | + .in("transactionType", 10, 20) | |
260 | + // 单独materialCode groupby 与SQL模式only_full_group_by不兼容 | |
261 | + .groupBy("materialCode","materialName","materialSpec","materialUnit") | |
262 | + .ge(StringUtils.isNotEmpty(createdBegin), "created", createdBegin) | |
263 | + .le(StringUtils.isNotEmpty(createdEnd), "created", createdEnd) | |
264 | + .orderByDesc("taskQty"); | |
265 | + } | |
266 | + | |
267 | + @Override | |
268 | + public QueryWrapper<InventoryTransaction> inventoryCreatedAnalysis(String type ,String createdBegin, String createdEnd) { | |
269 | + QueryWrapper<InventoryTransaction> datequeryWrapper = new QueryWrapper<>(); | |
270 | + return datequeryWrapper.select("DATE(created) as datee, SUM(CASE WHEN transactionType = 10 THEN taskQty ELSE 0 END) AS inQty, ABS(SUM(CASE WHEN transactionType = 20 THEN taskQty ELSE 0 END)) AS outQty, SUM(CASE WHEN taskQty > 0 THEN taskQty ELSE 0 END) + ABS(SUM(CASE WHEN taskQty < 0 THEN taskQty ELSE 0 END)) AS taskQty") | |
271 | + .in("transactionType", 10, 20) | |
272 | + .between("created",createdBegin,createdEnd) | |
273 | + .groupBy("DATE(created)"); | |
274 | + | |
275 | + } | |
276 | + | |
245 | 277 | /** |
246 | 278 | * 生成物料编码 |
247 | 279 | * @param code |
... | ... |
src/main/java/com/huaheng/pc/inventory/inventoryTransaction/controller/FrequencyStatisticsController.java
... | ... | @@ -15,6 +15,7 @@ import com.huaheng.framework.web.domain.AjaxResult; |
15 | 15 | import com.huaheng.framework.web.page.PageDomain; |
16 | 16 | import com.huaheng.framework.web.page.TableDataInfo; |
17 | 17 | import com.huaheng.framework.web.page.TableSupport; |
18 | +import com.huaheng.pc.config.material.service.MaterialService; | |
18 | 19 | import com.huaheng.pc.inventory.inventoryDetail.service.InventoryDetailService; |
19 | 20 | import com.huaheng.pc.inventory.inventoryHeader.service.InventoryHeaderService; |
20 | 21 | import com.huaheng.pc.inventory.inventoryTransaction.domain.InventoryTransaction; |
... | ... | @@ -65,6 +66,9 @@ public class FrequencyStatisticsController extends BaseController { |
65 | 66 | } |
66 | 67 | |
67 | 68 | |
69 | + @Resource | |
70 | + private MaterialService materialService; | |
71 | + | |
68 | 72 | @PostMapping("/frequencyStatisticsList") |
69 | 73 | @ResponseBody |
70 | 74 | public TableDataInfo inventoryTransactionList(InventoryTransaction inventoryTransaction, String createdBegin, String createdEnd) { |
... | ... | @@ -73,53 +77,22 @@ public class FrequencyStatisticsController extends BaseController { |
73 | 77 | Integer pageSize = pageDomain.getPageSize(); |
74 | 78 | |
75 | 79 | String type = StringUtils.isNotBlank(inventoryTransaction.getStatisticalType()) ? inventoryTransaction.getStatisticalType() : "materialCode"; |
80 | + QueryWrapper<InventoryTransaction> materialQueryWrapper = new QueryWrapper<>(); | |
76 | 81 | |
77 | - //物料 | |
78 | - if (type.equals("materialCode")) { | |
79 | - String countSql="SUM(CASE WHEN transactionType = 10 THEN taskQty ELSE 0 END) AS inQty," + | |
80 | - "ABS(SUM(CASE WHEN transactionType = 20 THEN taskQty ELSE 0 END)) AS outQty," + | |
81 | - "SUM(CASE WHEN taskQty > 0 THEN taskQty ELSE 0 END) + ABS(SUM(CASE WHEN taskQty < 0 THEN taskQty ELSE 0 END)) AS taskQty," + | |
82 | - "materialName,materialSpec,materialUnit\n"; | |
83 | - QueryWrapper<InventoryTransaction> materialQueryWrapper = new QueryWrapper<>(); | |
84 | - | |
85 | - materialQueryWrapper | |
86 | - .select(type,countSql) | |
87 | - .like(StringUtils.isNotEmpty(inventoryTransaction.getMaterialCode()), "materialCode", inventoryTransaction.getMaterialCode())//物料编码 | |
88 | - .in("transactionType", 10, 20) | |
89 | - // 单独materialCode groupby 与SQL模式only_full_group_by不兼容 | |
90 | - .groupBy("materialCode","materialName","materialSpec","materialUnit") | |
91 | - .ge(StringUtils.isNotEmpty(createdBegin), "created", createdBegin) | |
92 | - .le(StringUtils.isNotEmpty(createdEnd), "created", createdEnd) | |
93 | - .orderByDesc("taskQty"); | |
94 | - | |
95 | - if (StringUtils.isNotNull(pageNum) && StringUtils.isNotNull(pageSize)) { | |
96 | - Page<InventoryTransaction> page = new Page<>(pageNum, pageSize); | |
97 | - IPage<InventoryTransaction> iPage = inventoryTransactionService.page(page, materialQueryWrapper); | |
98 | - return getMpDataTable(iPage.getRecords(), iPage.getTotal()); | |
99 | - } else { | |
100 | - List<InventoryTransaction> list = inventoryTransactionService.list(materialQueryWrapper); | |
101 | - return getDataTable(list); | |
102 | - } | |
82 | + if ("materialCode".equals(type)) { | |
83 | + materialQueryWrapper = materialService.inventoryTurnoverAnalysis("materialCode",inventoryTransaction.getMaterialCode(),createdBegin,createdEnd); | |
84 | + }else if("created".equals(type)){ | |
85 | + materialQueryWrapper = materialService.inventoryCreatedAnalysis("created",createdBegin,createdEnd); | |
103 | 86 | } |
104 | 87 | |
105 | - //日期 | |
106 | - if (type.equals("created")){ | |
107 | - QueryWrapper<InventoryTransaction> datequeryWrapper = new QueryWrapper<>(); | |
108 | - datequeryWrapper.select("DATE(created) as datee, SUM(CASE WHEN transactionType = 10 THEN taskQty ELSE 0 END) AS inQty, ABS(SUM(CASE WHEN transactionType = 20 THEN taskQty ELSE 0 END)) AS outQty, SUM(CASE WHEN taskQty > 0 THEN taskQty ELSE 0 END) + ABS(SUM(CASE WHEN taskQty < 0 THEN taskQty ELSE 0 END)) AS taskQty") | |
109 | - .in("transactionType", 10, 20) | |
110 | - .between("created",createdBegin,createdEnd) | |
111 | - .groupBy("DATE(created)"); | |
112 | - | |
113 | - if (StringUtils.isNotNull(pageNum) && StringUtils.isNotNull(pageSize)) { | |
114 | - Page<InventoryTransaction> page = new Page<>(pageNum, pageSize); | |
115 | - IPage<InventoryTransaction> iPage = inventoryTransactionService.page(page, datequeryWrapper); | |
116 | - return getMpDataTable(iPage.getRecords(), iPage.getTotal()); | |
117 | - } else { | |
118 | - List<InventoryTransaction> list = inventoryTransactionService.list(datequeryWrapper); | |
119 | - return getDataTable(list); | |
120 | - } | |
88 | + if (StringUtils.isNotNull(pageNum) && StringUtils.isNotNull(pageSize)) { | |
89 | + Page<InventoryTransaction> page = new Page<>(pageNum, pageSize); | |
90 | + IPage<InventoryTransaction> iPage = inventoryTransactionService.page(page, materialQueryWrapper); | |
91 | + return getMpDataTable(iPage.getRecords(), iPage.getTotal()); | |
92 | + } else { | |
93 | + List<InventoryTransaction> list = inventoryTransactionService.list(materialQueryWrapper); | |
94 | + return getDataTable(list); | |
121 | 95 | } |
122 | - return null; | |
123 | 96 | } |
124 | 97 | |
125 | 98 | |
... | ... |
src/main/java/com/huaheng/pc/inventory/inventoryTransaction/domain/vo/InventoryRankVO.java
0 → 100644
1 | +package com.huaheng.pc.inventory.inventoryTransaction.domain.vo; | |
2 | + | |
3 | +import lombok.Builder; | |
4 | +import lombok.Data; | |
5 | + | |
6 | +import java.io.Serializable; | |
7 | +import java.math.BigDecimal; | |
8 | + | |
9 | +@Data | |
10 | +@Builder | |
11 | +public class InventoryRankVO implements Serializable { | |
12 | + | |
13 | + private static final long serialVersionUID = 2903643973589589715L; | |
14 | + | |
15 | + private String materialCode; | |
16 | + private Integer inQty; | |
17 | + private Integer outQty; | |
18 | + private BigDecimal taskQty; | |
19 | + private String materialName; | |
20 | + private String materialSpec; | |
21 | + private String materialUnit; | |
22 | +} | |
... | ... |
src/main/java/com/huaheng/pc/task/taskHeader/service/TaskHeaderServiceImpl.java
... | ... | @@ -757,6 +757,7 @@ public class TaskHeaderServiceImpl extends ServiceImpl<TaskHeaderMapper, TaskHea |
757 | 757 | if (locations.size() == 0) { |
758 | 758 | throw new ServiceException("没有空闲库位!"); |
759 | 759 | } |
760 | + // TODO | |
760 | 761 | //随机取库位 |
761 | 762 | Random rand = new Random(); |
762 | 763 | Location location = locations.get(rand.nextInt(locations.size())); |
... | ... |
src/test/java/com.huaheng.test/Demo.java
1 | 1 | package com.huaheng.test; |
2 | 2 | |
3 | +import cn.hutool.core.collection.CollectionUtil; | |
4 | +import cn.hutool.core.util.ObjectUtil; | |
3 | 5 | import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; |
6 | +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; | |
7 | +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; | |
4 | 8 | import com.huaheng.HuaHengApplication; |
9 | +import com.huaheng.framework.redis.RedisCache; | |
5 | 10 | import com.huaheng.pc.config.location.domain.Location; |
6 | 11 | import com.huaheng.pc.config.location.service.LocationService; |
12 | +import com.huaheng.pc.config.material.service.MaterialService; | |
13 | +import com.huaheng.pc.inventory.inventoryTransaction.domain.InventoryTransaction; | |
14 | +import com.huaheng.pc.inventory.inventoryTransaction.domain.vo.InventoryRankVO; | |
15 | +import com.huaheng.pc.inventory.inventoryTransaction.service.InventoryTransactionService; | |
7 | 16 | import lombok.extern.slf4j.Slf4j; |
8 | 17 | import org.junit.Test; |
9 | 18 | import org.junit.runner.RunWith; |
10 | 19 | import org.springframework.beans.factory.annotation.Autowired; |
11 | 20 | import org.springframework.boot.test.context.SpringBootTest; |
21 | +import org.springframework.data.redis.core.RedisTemplate; | |
12 | 22 | import org.springframework.test.context.junit4.SpringRunner; |
13 | 23 | |
24 | +import javax.annotation.Resource; | |
25 | +import java.util.ArrayList; | |
14 | 26 | import java.util.List; |
27 | +import java.util.Map; | |
28 | +import java.util.stream.Collectors; | |
15 | 29 | |
16 | 30 | /** |
17 | 31 | * @author yiwenpeng |
... | ... | @@ -24,15 +38,77 @@ public class Demo { |
24 | 38 | @Autowired |
25 | 39 | private LocationService locationService; |
26 | 40 | |
41 | + @Resource | |
42 | + private RedisCache redisCache; | |
43 | + | |
44 | + | |
45 | + @Resource | |
46 | + private MaterialService materialService; | |
47 | + | |
48 | + @Resource | |
49 | + private InventoryTransactionService inventoryTransactionService; | |
50 | + | |
51 | + /* | |
52 | + 将上一周物料出库次数排名前100的记录到数据库里面,每周更新一次这个排名,每次入库的时候用托盘中的所有物料,根据物料出入库次数排名计算出本次入库要分配的库位。 | |
53 | + | |
54 | + 方案一:假设一个仓库前后各一个出口,离这两个出口近的前2列,包括所有行和层,都设置为常用库位(A区),前4列所有行和层的外侧库位,设置为一般常用库位(B区),其他的就是剩余库位了,不常用C区。 | |
55 | + | |
56 | + 方案二:找到哪个离出口最近的库位,然后分配库位的时候,用方法找到离这个库位最近的库位,进行分配,但是每次分配只能分配离这个库位最近的。 | |
57 | + */ | |
58 | + | |
59 | + private final static String INVENTORY_RANKING_KEY = "INVENTORY_RANKING"; | |
27 | 60 | @Test |
28 | 61 | public void test() { |
29 | - List<Location> lists = locationService.list(new LambdaQueryWrapper<Location>().eq(Location::getZoneCode, "A")); | |
30 | - String locationCode = "A020303";//假设这个是离出口最近的库位号 | |
31 | - Location nearestLocation = findNearestLocation(lists, locationCode); | |
32 | - log.error("***********************************************" + nearestLocation); | |
62 | + // 统计物料出入库的频率,将常用的物料优先分配离出入口近的库位,外侧库位优先。 | |
63 | + // 常用的物料,需要华恒自己根据物料出入库的频次进行判断 | |
64 | + | |
65 | + // 获取统计排行前30位的物料信息 | |
66 | + // 优先出库原始数据,历史数据(1期暂时不做考虑,不需要考虑原始数据) | |
67 | + // 入库数据存放至A区 | |
68 | + // 常用库位(A区) | |
69 | + List<Object> rankList = redisCache.getCacheList(INVENTORY_RANKING_KEY); | |
70 | + if(CollectionUtil.isEmpty(rankList)){ | |
71 | + QueryWrapper<InventoryTransaction> materialQueryWrapper = materialService.inventoryTurnoverAnalysis("materialCode","", "", ""); | |
72 | + List<InventoryTransaction> inventoryTransactionList = inventoryTransactionService.page(new Page<>(0, 30), materialQueryWrapper).getRecords(); | |
73 | + List<InventoryRankVO> rankVOList = new ArrayList<>(); | |
74 | + inventoryTransactionList.forEach(inventory ->{ | |
75 | + rankVOList.add(InventoryRankVO.builder() | |
76 | + .materialCode(inventory.getMaterialCode()) | |
77 | + .inQty(inventory.getInQty()) | |
78 | + .outQty(inventory.getOutQty()) | |
79 | + .taskQty(inventory.getTaskQty()) | |
80 | + .materialName(inventory.getMaterialName()) | |
81 | + .materialSpec(inventory.getMaterialSpec()) | |
82 | + .materialUnit(inventory.getMaterialUnit()) | |
83 | + .build()); | |
84 | + }); | |
85 | + redisCache.setCacheList(INVENTORY_RANKING_KEY,rankVOList); | |
86 | + } | |
87 | + // key material code | |
88 | + // value material object | |
89 | + Map<String, InventoryRankVO> inventoryRankVOMap = rankList.stream() | |
90 | + .map(obj -> (InventoryRankVO) obj) | |
91 | + .collect(Collectors.toMap(InventoryRankVO::getMaterialCode, vo -> vo)); | |
92 | + | |
93 | + String inOutMaterialCode = "DR-QB-01M"; | |
94 | + | |
95 | + | |
96 | + InventoryRankVO inputMaterialCode = inventoryRankVOMap.get(inOutMaterialCode); | |
97 | + // 判断是否存在排行物料 true 存在 | |
98 | + if(ObjectUtil.isNotEmpty(inputMaterialCode)){ | |
99 | + | |
100 | + } | |
101 | + | |
102 | +// | |
103 | +// List<Location> lists = locationService.list(new LambdaQueryWrapper<Location>().eq(Location::getZoneCode, "A")); | |
104 | +// // 库位号 | |
105 | +// String locationCode = "A020303";//假设这个是离出口最近的库位号 | |
106 | +// Location nearestLocation = findNearestLocation(lists, locationCode); | |
107 | +// log.error("***********************************************" + nearestLocation); | |
33 | 108 | } |
34 | 109 | |
35 | 110 | |
111 | + | |
36 | 112 | public static Location findNearestLocation(List<Location> locations, String locationCode) { |
37 | 113 | if (locations == null || locations.isEmpty() || locationCode == null) { |
38 | 114 | return null; |
... | ... |