diff --git a/hiver-admin/test-output/test-report.html b/hiver-admin/test-output/test-report.html index e2bd5612..5bf4d372 100644 --- a/hiver-admin/test-output/test-report.html +++ b/hiver-admin/test-output/test-report.html @@ -35,7 +35,7 @@ Hiver
  • -四月 22, 2026 17:15:02 +四月 23, 2026 18:21:01
  • @@ -84,7 +84,7 @@

    passTest

    -

    17:15:02 下午 / 0.019 secs

    +

    18:21:02 下午 / 0.015 secs

    @@ -92,9 +92,9 @@
    #test-id=1
    passTest
    -04.22.2026 17:15:02 -04.22.2026 17:15:02 -0.019 secs +04.23.2026 18:21:02 +04.23.2026 18:21:02 +0.015 secs
    @@ -104,7 +104,7 @@ Pass - 17:15:02 + 18:21:02 Test passed @@ -128,13 +128,13 @@

    Started

    -

    四月 22, 2026 17:15:02

    +

    四月 23, 2026 18:21:01

    Ended

    -

    四月 22, 2026 17:15:02

    +

    四月 23, 2026 18:21:02

    diff --git a/hiver-core/src/main/java/cc/hiver/core/config/cache/RedisCacheConfig.java b/hiver-core/src/main/java/cc/hiver/core/config/cache/RedisCacheConfig.java index bc5af36c..3ce8957e 100644 --- a/hiver-core/src/main/java/cc/hiver/core/config/cache/RedisCacheConfig.java +++ b/hiver-core/src/main/java/cc/hiver/core/config/cache/RedisCacheConfig.java @@ -1,6 +1,7 @@ package cc.hiver.core.config.cache; import com.fasterxml.jackson.annotation.JsonAutoDetect; +import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.PropertyAccessor; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.SerializationFeature; @@ -81,6 +82,12 @@ public class RedisCacheConfig extends CachingConfigurerSupport { */ private ObjectMapper createObjectMapper() { ObjectMapper mapper = new ObjectMapper(); + + // ========================================== + // 銆愭牳蹇冧慨鏀广戯細寮哄埗搴忓垪鍖栨墍鏈夊瓧娈碉紝鍖呮嫭 null 鍊 + // ========================================== + mapper.setSerializationInclusion(JsonInclude.Include.ALWAYS); + // 璁剧疆鍙鎬 mapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY); // 鏀寔澶氭佺被鍨 @@ -102,13 +109,13 @@ public class RedisCacheConfig extends CachingConfigurerSupport { */ @Override public CacheErrorHandler errorHandler() { + // ... (淇濇寔涓嶅彉) return new CacheErrorHandler() { @Override public void handleCacheGetError(RuntimeException e, Cache cache, Object key) { log.error(CACHE_ERROR_PREFIX + "鑾峰彇缂撳瓨澶辫触 - 缂撳瓨鍚嶇О:[{}], 閿:[{}], 閿欒:[{}]", cache.getName(), key, e.getMessage(), e); } - @Override public void handleCachePutError(RuntimeException e, Cache cache, Object key, Object value) { log.error(CACHE_ERROR_PREFIX + "鍐欏叆缂撳瓨澶辫触 - 缂撳瓨鍚嶇О:[{}], 閿:[{}], 鍊肩被鍨:[{}], 閿欒:[{}]", @@ -116,13 +123,11 @@ public class RedisCacheConfig extends CachingConfigurerSupport { value != null ? value.getClass().getSimpleName() : "null", e.getMessage(), e); } - @Override public void handleCacheEvictError(RuntimeException e, Cache cache, Object key) { log.error(CACHE_ERROR_PREFIX + "娓呴櫎缂撳瓨椤瑰け璐 - 缂撳瓨鍚嶇О:[{}], 閿:[{}], 閿欒:[{}]", cache.getName(), key, e.getMessage(), e); } - @Override public void handleCacheClearError(RuntimeException e, Cache cache) { log.error(CACHE_ERROR_PREFIX + "娓呯┖缂撳瓨澶辫触 - 缂撳瓨鍚嶇О:[{}], 閿欒:[{}]", @@ -139,8 +144,9 @@ public class RedisCacheConfig extends CachingConfigurerSupport { // 浣跨敤Jackson搴忓垪鍖栧櫒 Jackson2JsonRedisSerializer serializer = new Jackson2JsonRedisSerializer<>(Object.class); - // 閰嶇疆ObjectMapper + // 閰嶇疆ObjectMapper (杩欓噷涔熼渶瑕佸悓姝ュ姞涓 Include.ALWAYS锛屼繚璇 redisTemplate 鎿嶄綔鏃朵篃瀛 null) ObjectMapper objectMapper = new ObjectMapper(); + objectMapper.setSerializationInclusion(JsonInclude.Include.ALWAYS); // 鍚屾淇敼 objectMapper.registerModule(new JavaTimeModule()); objectMapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS); objectMapper.setDateFormat(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss")); diff --git a/hiver-modules/hiver-base/src/main/java/cc/hiver/base/controller/manage/AuthController.java b/hiver-modules/hiver-base/src/main/java/cc/hiver/base/controller/manage/AuthController.java index e32dd9bd..ecb2696c 100644 --- a/hiver-modules/hiver-base/src/main/java/cc/hiver/base/controller/manage/AuthController.java +++ b/hiver-modules/hiver-base/src/main/java/cc/hiver/base/controller/manage/AuthController.java @@ -128,10 +128,11 @@ public class AuthController { @SystemLog(description = "璐﹀彿鐧诲綍", type = LogType.LOGIN) @ApiOperation("璐﹀彿/鎵嬫満/閭鐧诲綍") @Transactional - public Result login(@RequestParam String username,@RequestParam(required = false) String clientId, - @RequestParam String password, - @RequestParam(required = false) String type, - @RequestParam(required = false) Boolean saveLogin) { + public Result login(@RequestParam(value = "username", required = false) String username, + @RequestParam(value = "clientId", required = false) String clientId, + @RequestParam(value = "password", required = false) String password, + @RequestParam(value = "type", required = false) String type, + @RequestParam(value = "saveLogin", required = false) Boolean saveLogin) { final Map result = new HashMap<>(); final String loginFailKey = LOGIN_FAIL_FLAG + username; final String loginTimeKey = LOGIN_TIME_LIMIT + username; diff --git a/hiver-modules/hiver-base/src/main/java/cc/hiver/base/controller/manage/DepartmentController.java b/hiver-modules/hiver-base/src/main/java/cc/hiver/base/controller/manage/DepartmentController.java index 9a1610da..155df920 100644 --- a/hiver-modules/hiver-base/src/main/java/cc/hiver/base/controller/manage/DepartmentController.java +++ b/hiver-modules/hiver-base/src/main/java/cc/hiver/base/controller/manage/DepartmentController.java @@ -70,7 +70,7 @@ public class DepartmentController { @ApiOperation(value = "閫氳繃parentId鑾峰彇") public Result> getByParentId(@PathVariable String parentId, @ApiParam("鏄惁寮濮嬫暟鎹潈闄愯繃婊") - @RequestParam(required = false, defaultValue = "true") Boolean openDataFilter) { + @RequestParam(value = "openDataFilter", required = false, defaultValue = "true") Boolean openDataFilter) { List list; User u = securityUtil.getCurrUserSimple(); String key = "department::" + parentId + ":" + u.getId() + "_" + openDataFilter; diff --git a/hiver-modules/hiver-base/src/main/java/cc/hiver/base/controller/manage/UserController.java b/hiver-modules/hiver-base/src/main/java/cc/hiver/base/controller/manage/UserController.java index 3974d7f6..c666e11c 100644 --- a/hiver-modules/hiver-base/src/main/java/cc/hiver/base/controller/manage/UserController.java +++ b/hiver-modules/hiver-base/src/main/java/cc/hiver/base/controller/manage/UserController.java @@ -370,6 +370,7 @@ public class UserController { u.setDepartmentId(null); u.setDepartmentTitle(""); } + u.setType("0,3"); final User user = userService.save(u); if (roleIds != null) { diff --git a/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/controller/AdminMallOrderGroupController.java b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/controller/AdminMallOrderGroupController.java index b27b3ea4..ab2a7abe 100644 --- a/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/controller/AdminMallOrderGroupController.java +++ b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/controller/AdminMallOrderGroupController.java @@ -2,7 +2,9 @@ package cc.hiver.mall.controller; import cc.hiver.core.common.utils.ResultUtil; import cc.hiver.core.common.vo.Result; +import cc.hiver.mall.dao.mapper.MallOrderGoodsMapper; import cc.hiver.mall.entity.MallOrder; +import cc.hiver.mall.entity.MallOrderGoods; import cc.hiver.mall.entity.MallOrderGroup; import cc.hiver.mall.service.mybatis.MallOrderGroupService; import cc.hiver.mall.service.mybatis.MallOrderService; @@ -32,6 +34,9 @@ public class AdminMallOrderGroupController { @Autowired private MallOrderService mallOrderService; + @Autowired + private MallOrderGoodsMapper mallOrderGoodsMapper; + @Data public static class OrderGroupQuery { private String shopId; @@ -93,6 +98,17 @@ public class AdminMallOrderGroupController { LambdaQueryWrapper oqw = new LambdaQueryWrapper<>(); oqw.in(MallOrder::getId, orderIds); List childOrders = mallOrderService.list(oqw); + // 2. 涓娆 IN 鏌ヨ鎵鏈夊晢鍝佹槑缁 + List allGoods = mallOrderGoodsMapper.selectByOrderIds(orderIds); + + // 3. 鎸 orderId 鍒嗙粍 + java.util.Map> goodsMap = allGoods.stream() + .collect(java.util.stream.Collectors.groupingBy(MallOrderGoods::getOrderId)); + + // 4. 缁勮鍒版瘡涓 VO + for (MallOrder order : childOrders) { + order.setGoodsList(goodsMap.getOrDefault(order.getId(), java.util.Collections.emptyList())); + } vo.setChildOrders(childOrders); } else { vo.setChildOrders(new ArrayList<>()); diff --git a/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/controller/MallDeliveryOrderController.java b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/controller/MallDeliveryOrderController.java index e71408ae..f63e4f2c 100644 --- a/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/controller/MallDeliveryOrderController.java +++ b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/controller/MallDeliveryOrderController.java @@ -12,6 +12,8 @@ import cc.hiver.mall.entity.MallDeliveryOrder; import cc.hiver.mall.entity.MallOrder; import cc.hiver.mall.pojo.query.MallDeliveryOrderPageQuery; import cc.hiver.mall.service.mybatis.MallDeliveryOrderService; +import cc.hiver.mall.utils.WaitOrderCacheUtil; +import cc.hiver.mall.utils.WorkerOrderCacheUtil; import cn.hutool.core.util.StrUtil; import com.baomidou.mybatisplus.core.metadata.IPage; import io.swagger.annotations.Api; @@ -21,6 +23,7 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.*; import java.math.BigDecimal; +import java.util.HashMap; import java.util.List; import java.util.Map; @@ -44,8 +47,14 @@ public class MallDeliveryOrderController { @Autowired JPushServiceImpl jPushService; + @Autowired + WorkerOrderCacheUtil workerOrderCacheUtil; + @Autowired private WorkerService workerService; + @Autowired + private WaitOrderCacheUtil waitOrderCacheUtil; + /** * 鍒嗛〉鏌ヨ閰嶉佸崟 * hallOnly=true 鏃舵煡璇㈡姠鍗曞ぇ鍘咃紙鏈鎺ュ崟鐨勫崟锛 @@ -53,8 +62,17 @@ public class MallDeliveryOrderController { @PostMapping("/page") @ApiOperation(value = "鍒嗛〉鏌ヨ閰嶉佸崟", notes = "hallOnly=true 鏌ヨ鎶㈠崟澶у巺") public Result page(@RequestBody MallDeliveryOrderPageQuery q) { + + //棣栧厛浠庣紦瀛樹腑鏌ヨ + Map cacheResult = waitOrderCacheUtil.getAll(q); + if (cacheResult != null) { + return new ResultUtil().setData(cacheResult); + } + + //缂撳瓨鏈懡涓紝鏌ヨ鏁版嵁搴 + Map result = new HashMap<>(); if (q.getDeliveryType() == 4 && StrUtil.isNotBlank(q.getWorkerId())) { - //鍏堟煡褰撳墠鐢ㄦ埛鎸囨淳鍗曟湭纭鎺ュ崟鏁伴噺 + //鍏堟煡褰撳墠鐢ㄦ埛鎸囨淳鍗曟湭纭鎺ュ崟鏁伴噺 涓嶇敤鍒嗛〉 q.setHallOnly(false); q.setGetAreaId(null); q.setPutAreaId(null); @@ -62,19 +80,17 @@ public class MallDeliveryOrderController { //闅忎究缁欎釜鍊硷紝鎸囨淳鍗曚笉鍖哄垎绫诲瀷 q.setDeliveryType(null); IPage page = mallDeliveryOrderService.pageDelivery(q); - java.util.Map result = new java.util.HashMap<>(); result.put("records", page.getRecords()); result.put("total", page.getTotal()); result.put("size", page.getSize()); result.put("current", page.getCurrent()); result.put("pages", page.getPages()); result.put("zhipaiCount", page.getTotal()); - //澶栧崠銆佸揩閫掋佽窇鑵垮緟鎺ユ暟 + //鍐嶆煡澶栧崠銆佸揩閫掋佽窇鑵垮緟鎺ユ暟 result.put("orderCount", mallDeliveryOrderService.countOrdersByType(q.getRegionId())); return new ResultUtil().setData(result); }else{ if (Boolean.TRUE.equals(q.getHallOnly())) { - java.util.Map result = new java.util.HashMap<>(); Integer deliveryType = q.getDeliveryType(); String getAreaId = q.getGetAreaId(); String putAreaId = q.getPutAreaId(); @@ -85,19 +101,18 @@ public class MallDeliveryOrderController { q.setPutAreaId(null); //闅忎究缁欎釜鍊硷紝鎸囨淳鍗曚笉鍖哄垎绫诲瀷 q.setDeliveryType(null); - //闅忎究缁欎釜鍊硷紝鎸囨淳鍗曚笉鍖哄垎绫诲瀷 + //涓嶅垎椤 q.setPageSize(100); IPage page = mallDeliveryOrderService.pageDelivery(q); result.put("zhipaiCount", page.getTotal()); } - //鍏朵粬绫诲瀷澶栧崠銆佸揩閫掋佽窇鑵垮緟鎺ユ暟鎹 + //鍏朵粬绫诲瀷澶栧崠銆佸揩閫掋佽窇鑵垮緟鎺ュ崟鏁版嵁 q.setHallOnly(true); q.setGetAreaId(getAreaId); q.setPutAreaId(putAreaId); q.setDeliveryType(deliveryType); q.setWorkerId(null); IPage page1 = mallDeliveryOrderService.pageDelivery(q); - result.put("records", page1.getRecords()); result.put("total", page1.getTotal()); result.put("size", page1.getSize()); @@ -108,7 +123,7 @@ public class MallDeliveryOrderController { return new ResultUtil().setData(result); } } - return new ResultUtil().setData(mallDeliveryOrderService.pageDelivery(q)); + return new ResultUtil().setData(result); } @PostMapping("/countOrderByStatus") @@ -120,7 +135,23 @@ public class MallDeliveryOrderController { @PostMapping("/pagebyworker") @ApiOperation(value = "鍒嗛〉鏌ヨ閰嶉佸憳閰嶉佸崟") public Result pageByWorker(@RequestBody MallDeliveryOrderPageQuery q) { - return new ResultUtil().setData(mallDeliveryOrderService.pageDeliveryByStatus(q)); + + // 1. 鍏堜粠缂撳瓨鑾峰彇 + IPage page = workerOrderCacheUtil.getAll(q); + + // 2. 缂撳瓨鏈懡涓紝鏌ユ暟鎹簱 + if (page == null || page.getRecords().isEmpty()) { + // 寤鸿锛氬姞涓垽绌猴紝闃叉鏁版嵁搴撲篃娌℃暟鎹椂鍋氭棤鐢ㄥ姛 + page = mallDeliveryOrderService.pageDeliveryByStatus(q); + + // 3. 銆愬叧閿楠ゃ戝鏋滄煡鍒颁簡鏁版嵁锛屽繀椤诲洖鍐欏埌缂撳瓨锛 + if (page != null && !page.getRecords().isEmpty()) { + // 璁剧疆杩囨湡鏃堕棿锛屾瘮濡 30 鍒嗛挓锛堟牴鎹鍗曞钩鍧囬厤閫佹椂闀垮喅瀹氾級 + workerOrderCacheUtil.putAll(q.getWorkerId(), page.getRecords()); + } + } + + return new ResultUtil().setData(page); } /** diff --git a/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/controller/MallOrderController.java b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/controller/MallOrderController.java index efb480be..6d514db0 100644 --- a/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/controller/MallOrderController.java +++ b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/controller/MallOrderController.java @@ -78,7 +78,7 @@ public class MallOrderController { List orders = shopGroupOrderCacheUtil.getAll(group.getShopId()); // 2. 缂撳瓨鏈懡涓紝鏌ユ暟鎹簱 - if (orders == null) { + if (orders == null || orders.isEmpty()) { // 寤鸿锛氬姞涓垽绌猴紝闃叉鏁版嵁搴撲篃娌℃暟鎹椂鍋氭棤鐢ㄥ姛 orders = mallOrderGroupService.selectMallGroup(group); @@ -102,7 +102,7 @@ public class MallOrderController { List orders = userPendingOrderCacheUtil.getAll(userId); // 2. 缂撳瓨鏈懡涓紝鏌ユ暟鎹簱 - if (orders == null) { + if (orders == null || orders.isEmpty()) { // 寤鸿锛氬姞涓垽绌猴紝闃叉鏁版嵁搴撲篃娌℃暟鎹椂鍋氭棤鐢ㄥ姛 orders = mallOrderService.getPeiSongOrders(userId); diff --git a/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/controller/WorkerController.java b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/controller/WorkerController.java index 3ec41620..338cde7a 100644 --- a/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/controller/WorkerController.java +++ b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/controller/WorkerController.java @@ -281,7 +281,7 @@ public class WorkerController { @RequestMapping(value = "/getOnlineWorkerByArea", method = RequestMethod.GET) @ApiOperation(value = "鏌ヨ鍚勯鍫傚尯鍩熷湪绾块厤閫佸憳鏁伴噺") - public Result> getOnlineWorkerByArea(String parentId) { + public Result> getOnlineWorkerByArea(@RequestParam(value = "parentId")String parentId) { List list = workerRelaPriceMapper.getOnlineWorkerCountByCanteenArea(parentId); return new ResultUtil>().setData(list); } diff --git a/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/controller/WorkerRelaPriceController.java b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/controller/WorkerRelaPriceController.java index 10693249..2872caaf 100644 --- a/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/controller/WorkerRelaPriceController.java +++ b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/controller/WorkerRelaPriceController.java @@ -54,7 +54,7 @@ public class WorkerRelaPriceController { @RequestMapping(value = "/getByWorkerId", method = RequestMethod.GET) @ApiOperation("鏍规嵁閰嶉佸憳id鑾峰彇") - public Result getByProductId(@RequestParam String workerId) { + public Result getByProductId(@RequestParam(value = "workerId") String workerId) { WorkerRealPriceVo workerRealPriceVo = new WorkerRealPriceVo(); Worker worker = workerService.findByWorkerId(workerId); if(worker != null){ diff --git a/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/dao/mapper/MallOrderGoodsMapper.java b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/dao/mapper/MallOrderGoodsMapper.java index 9e1f381d..eab33210 100644 --- a/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/dao/mapper/MallOrderGoodsMapper.java +++ b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/dao/mapper/MallOrderGoodsMapper.java @@ -22,4 +22,9 @@ public interface MallOrderGoodsMapper extends BaseMapper { * 鎸夎鍗旾D闆嗗悎鎵归噺鏌ヨ */ List selectByOrderIds(@Param("orderIds") List orderIds); + + /** + * 鎸夎鍗旾D闆嗗悎鎵归噺鏌ヨ + */ + List selectByOrderIdsWait(@Param("orderIds") List orderIds); } diff --git a/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/entity/MallOrder.java b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/entity/MallOrder.java index 44529dde..70b32bbf 100644 --- a/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/entity/MallOrder.java +++ b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/entity/MallOrder.java @@ -15,6 +15,7 @@ import javax.persistence.Transient; import java.io.Serializable; import java.math.BigDecimal; import java.util.Date; +import java.util.List; @Data @Entity @@ -92,6 +93,11 @@ public class MallOrder implements Serializable { @ApiModelProperty(value = "浣跨敤鐨勪紭鎯犲埜ID(鎻愪氦璁㈠崟鏃朵紶鍏)") private String userCouponId; + @Transient + @TableField(exist = false) + @ApiModelProperty("璁㈠崟鍟嗗搧鍒楄〃") + private List goodsList; + @Transient @TableField(exist = false) @ApiModelProperty(value = "浼樻儬鍒告姷鎵i噾棰") diff --git a/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/pojo/query/MallDeliveryOrderPageQuery.java b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/pojo/query/MallDeliveryOrderPageQuery.java index 1bd5d691..3dcd39a9 100644 --- a/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/pojo/query/MallDeliveryOrderPageQuery.java +++ b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/pojo/query/MallDeliveryOrderPageQuery.java @@ -45,7 +45,7 @@ public class MallDeliveryOrderPageQuery extends HiverBasePageQuery { @ApiModelProperty(value = "瀛︽牎id") private String regionId; - @ApiModelProperty("璁㈠崟绫诲瀷 1:澶栧崠 2:蹇") + @ApiModelProperty("璁㈠崟绫诲瀷 1:澶栧崠 2:蹇 3:璺戣吙") private Integer deliveryType; @ApiModelProperty("鎺掑簭瑙勫垯锛堝鏋滄湁鍊间笖涓篸eliveryFee锛屽垯鎸変剑閲戦檷搴忥級") diff --git a/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/serviceimpl/mybatis/MallDeliveryOrderServiceImpl.java b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/serviceimpl/mybatis/MallDeliveryOrderServiceImpl.java index 845338d8..fd72285c 100644 --- a/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/serviceimpl/mybatis/MallDeliveryOrderServiceImpl.java +++ b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/serviceimpl/mybatis/MallDeliveryOrderServiceImpl.java @@ -21,6 +21,8 @@ import cc.hiver.mall.service.mybatis.MallRefundRecordService; import cc.hiver.mall.service.mybatis.MallUserCouponService; import cc.hiver.mall.utils.MerchantOrderSeqUtil; import cc.hiver.mall.utils.UserPendingOrderCacheUtil; +import cc.hiver.mall.utils.WaitOrderCacheUtil; +import cc.hiver.mall.utils.WorkerOrderCacheUtil; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; import com.baomidou.mybatisplus.core.metadata.IPage; @@ -80,6 +82,9 @@ public class MallDeliveryOrderServiceImpl extends ServiceImpl goodsList = new ArrayList<>(); //闇瑕佹煡璇㈣group鐨勬墍鏈夊叧鑱旇鍗曪紝濡傛灉鏄潰瀵归潰鎷煎洟闇瑕佹洿鏂拌鍗曞簭鍙 if(delivery.getGroupId() != null){ LambdaQueryWrapper gq = new LambdaQueryWrapper<>(); @@ -176,6 +185,10 @@ public class MallDeliveryOrderServiceImpl extends ServiceImpl orderIds = Arrays.asList(group.getGroupOrderIds().split(",")); orderIdsSend = orderIds; + + // 2. 涓娆 IN 鏌ヨ鎵鏈夊晢鍝佹槑缁 + goodsList = mallOrderGoodsMapper.selectByOrderIds(orderIds); + for (String orderId : orderIds) { MallOrder orderInner = mallOrderService.getById(orderId); if (orderInner != null) { @@ -195,7 +208,10 @@ public class MallDeliveryOrderServiceImpl extends ServiceImpl gq = new LambdaQueryWrapper<>(); @@ -351,6 +391,10 @@ public class MallDeliveryOrderServiceImpl extends ServiceImpl orderIdList = Arrays.asList(group.getGroupOrderIds().split(",")); - + List goodsList = new ArrayList<>(); LambdaQueryWrapper oqw = new LambdaQueryWrapper<>(); oqw.eq(MallOrder::getShopId, group.getShopId()) .eq(MallOrder::getStatus, ORDER_STATUS_WAIT_GROUP) @@ -205,6 +206,17 @@ public class MallOrderGroupServiceImpl extends ServiceImpl 璺宠繃寰呭晢瀹舵帴鍗曪紝鐩存帴杩涘叆寰呴厤閫佹垨寰呮秷璐 if (DELIVERY_TYPE_EXPRESS == order.getDeliveryType()) { updateOrderStatus(orderId, STATUS_WAIT_DELIVERY); + //鐢ㄦ埛褰撳墠璁㈠崟缂撳瓨 MallOrderVO orderVO = buildVO(order, null, null, null); orderVO.setStatus(STATUS_WAIT_DELIVERY); userPendingOrderCacheUtil.update(order.getUserId(), orderVO); @@ -512,6 +516,13 @@ public class MallOrderServiceImpl extends ServiceImpl qw = new LambdaQueryWrapper<>(); + qw.eq(MallDeliveryOrder::getOrderId, orderId); + MallDeliveryOrder deliveryOrder = mallDeliveryOrderMapper.selectOne(qw); + List goodsList = mallOrderGoodsMapper.selectByOrderId(orderId); + deliveryOrder.setGoodsList(goodsList); + waitOrderCacheUtil.put(order.getRegionId(), deliveryOrder); // 瑙﹀彂寮傛鎺ㄩ佸拰寤惰繜鐩戝惉娴佺▼ triggerDeliveryAsyncEvents(orderId); } else { @@ -880,6 +891,8 @@ public class MallOrderServiceImpl extends ServiceImpl guw = new LambdaUpdateWrapper<>(); guw.eq(MallOrderGroup::getId, group.getId()) @@ -965,6 +980,8 @@ public class MallOrderServiceImpl extends ServiceImpl qw = new LambdaQueryWrapper<>(); qw.eq(MallDeliveryOrder::getOrderId, order.getId()); MallDeliveryOrder delivery = mallDeliveryOrderMapper.selectOne(qw); smsUtil.sendCode(delivery.getWorkerPhone(), null, SettingConstant.SMS_TYPE.SMS_ORDERRETURN.name()); + //鏇存柊缂撳瓨 + MallDeliveryOrder delivery1 = workerOrderCacheUtil.get(workerId,delivery.getId()); + delivery1.setIsReturn(IS_RETURN_EXPRESS); + workerOrderCacheUtil.update(workerId,delivery1); } } diff --git a/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/serviceimpl/mybatis/MallRefundRecordServiceImpl.java b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/serviceimpl/mybatis/MallRefundRecordServiceImpl.java index 52940d8e..7d62c59e 100644 --- a/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/serviceimpl/mybatis/MallRefundRecordServiceImpl.java +++ b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/serviceimpl/mybatis/MallRefundRecordServiceImpl.java @@ -12,6 +12,7 @@ import cc.hiver.mall.service.mybatis.MallRefundRecordService; import cc.hiver.mall.service.mybatis.MallUserCouponService; import cc.hiver.mall.utils.UserPendingOrderCacheUtil; import cc.hiver.mall.utils.WechatPayUtil; +import cc.hiver.mall.utils.WorkerOrderCacheUtil; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; import com.baomidou.mybatisplus.core.metadata.IPage; @@ -66,6 +67,9 @@ public class MallRefundRecordServiceImpl extends ServiceImpl qw = new LambdaQueryWrapper<>(); + qw.eq(MallDeliveryOrder::getOrderId, mallRefundRecord.getOrderId()); + MallDeliveryOrder deliveryOrder = mallDeliveryOrderMapper.selectOne(qw); + workerOrderCacheUtil.remove(deliveryOrder.getWorkerId(),deliveryOrder.getId()); } BigDecimal totalRefund = result.getRecords().stream() .map(item -> item.getRefundAmount()) // 鎻愬彇 BigDecimal 閲戦 @@ -267,6 +276,11 @@ public class MallRefundRecordServiceImpl extends ServiceImpl qw = new LambdaQueryWrapper<>(); + qw.eq(MallDeliveryOrder::getOrderId, mallRefundRecord.getOrderId()); + MallDeliveryOrder deliveryOrder = mallDeliveryOrderMapper.selectOne(qw); + workerOrderCacheUtil.remove(deliveryOrder.getWorkerId(),deliveryOrder.getId()); } wechatPayUtil.refund(mallRefundRecord.getOrderId(), mallRefundRecord.getRefundAmount().multiply(new BigDecimal(100)).longValue(), mallRefundRecord.getRefundAmount().multiply(new BigDecimal(100)).longValue()); if(mallRefundRecord.getLinkId().toUpperCase().startsWith("W")){ diff --git a/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/utils/ShopGroupOrderCacheUtil.java b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/utils/ShopGroupOrderCacheUtil.java index 4ffc6295..79238407 100644 --- a/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/utils/ShopGroupOrderCacheUtil.java +++ b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/utils/ShopGroupOrderCacheUtil.java @@ -2,7 +2,6 @@ package cc.hiver.mall.utils; import cc.hiver.core.common.redis.RedisTemplateHelper; import cc.hiver.mall.entity.MallOrderGroup; -import cc.hiver.mall.pojo.vo.MallOrderVO; import cn.hutool.json.JSONUtil; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; @@ -221,7 +220,7 @@ public class ShopGroupOrderCacheUtil { * @param orderId 璁㈠崟ID * @return 缂撳瓨鐨勮鍗昖O锛屼笉瀛樺湪鏃惰繑鍥 null */ - public MallOrderVO get(String shopId, String orderId) { + public MallOrderGroup get(String shopId, String orderId) { if (StringUtils.isBlank(shopId) || StringUtils.isBlank(orderId)) { return null; } @@ -231,7 +230,7 @@ public class ShopGroupOrderCacheUtil { if (value == null) { return null; } - return JSONUtil.toBean(value.toString(), MallOrderVO.class); + return JSONUtil.toBean(value.toString(), MallOrderGroup.class); } catch (Exception e) { log.info("鑾峰彇搴楅摵鍗曚釜寰呮垚鍥㈣鍗曠紦瀛樺け璐: shopId={}, orderId={}", shopId, orderId, e); return null; diff --git a/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/utils/WaitOrderCacheUtil.java b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/utils/WaitOrderCacheUtil.java new file mode 100644 index 00000000..609dde17 --- /dev/null +++ b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/utils/WaitOrderCacheUtil.java @@ -0,0 +1,535 @@ +package cc.hiver.mall.utils; + +import cc.hiver.core.common.redis.RedisTemplateHelper; +import cc.hiver.mall.entity.MallDeliveryOrder; +import cc.hiver.mall.pojo.dto.AreaRuleDTO; +import cc.hiver.mall.pojo.query.MallDeliveryOrderPageQuery; +import cn.hutool.json.JSONUtil; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import java.math.BigDecimal; +import java.text.SimpleDateFormat; +import java.util.*; +import java.util.stream.Collectors; + +/** + * 鎶㈠崟澶у巺寰呭畬鎴愯鍗曠紦瀛樺伐鍏风被 + *

    + * 搴曞眰浣跨敤 Redis Hash 缁撴瀯锛屼繚璇佹寜 regionId + orderId 缁村害鐨 O(1) 璇诲啓鏁堢巼銆 + *

    + *   Key   = WAIT_ORDERS:{regionId}
    + *   Field = orderId
    + *   Value = MallDeliveryOrder 鐨 JSON 搴忓垪鍖
    + * 
    + *

    + * 浣跨敤鍦烘櫙锛氳鍗曠姸鎬佸彂鐢熷彉鍖栨椂锛堝垱寤恒佹洿鏂般佸彇娑堛佸畬鎴愮瓑锛夛紝 + * 鐢变笟鍔℃柟涓诲姩璋冪敤鏈伐鍏风被鐨勬柟娉曠淮鎶ょ紦瀛橈紝浠ュ噺灏 pagebyworker 鎺ュ彛瀵规暟鎹簱鐨勬煡璇㈠帇鍔涖 + * + * @author system + */ +@Slf4j +@Component +public class WaitOrderCacheUtil { + + /** Redis Key 鍓嶇紑 */ + private static final String KEY_PREFIX = "WAIT_ORDERS:"; + + @Autowired + private RedisTemplateHelper redisTemplateHelper; + + // ================================================================ + // Key 鏋勫缓 + // ================================================================ + + private String buildKey(String regionId) { + return KEY_PREFIX + regionId; + } + + // ================================================================ + // 瀛樻斁锛坧ut锛 + // ================================================================ + + /** + * 瀛樻斁鍗曚釜璁㈠崟鍒扮紦瀛 + * + * @param regionId 鍖哄煙ID + * @param orderVO 璁㈠崟VO锛堝繀椤诲寘鍚湁鏁堢殑 id锛 + */ + public void put(String regionId, MallDeliveryOrder orderVO) { + if (StringUtils.isBlank(regionId) || orderVO == null || StringUtils.isBlank(orderVO.getId())) { + log.info("UserPendingOrderCacheUtil.put 鍙傛暟鏃犳晥, userId={}, orderVO={}", regionId, orderVO); + return; + } + try { + String key = buildKey(regionId); + String json = JSONUtil.toJsonStr(orderVO); + redisTemplateHelper.hPut(key, orderVO.getId(), json); + log.info("缂撳瓨鎶㈠崟澶у巺璁㈠崟: regionId={}, orderId={}", regionId, orderVO.getId()); + } catch (Exception e) { + log.info("缂撳瓨鎶㈠崟澶у巺璁㈠崟澶辫触: regionId={}, orderId={}", regionId, orderVO.getId(), e); + } + } + + /** + * 鎵归噺瀛樻斁璁㈠崟鍒扮紦瀛橈紙閫氬父鐢ㄤ簬缂撳瓨棰勭儹 / 棣栨鍔犺浇锛 + * + * @param regionId 鍖哄煙ID + * @param orders 璁㈠崟鍒楄〃 + */ + public void putAll(String regionId, List orders) { + if (StringUtils.isBlank(regionId) || orders == null || orders.isEmpty()) { + return; + } + try { + String key = buildKey(regionId); + Map map = new LinkedHashMap<>(orders.size()); + for (MallDeliveryOrder order : orders) { + if (order != null && StringUtils.isNotBlank(order.getId())) { + map.put(order.getId(), JSONUtil.toJsonStr(order)); + } + } + if (!map.isEmpty()) { + redisTemplateHelper.hPutAll(key, map); + log.info("鎵归噺缂撳瓨鎶㈠崟澶у巺璁㈠崟: regionId={}, count={}", regionId, map.size()); + } + } catch (Exception e) { + log.info("鎵归噺缂撳瓨鎶㈠崟澶у巺璁㈠崟澶辫触: regionId={}", regionId, e); + } + } + + // ================================================================ + // 鍒犻櫎锛坮emove锛 + // ================================================================ + + /** + * 鏍规嵁 regionId 鍜 orderId 浠庣紦瀛樹腑鍒犻櫎鎸囧畾璁㈠崟 + *

    + * 鍏稿瀷鍦烘櫙锛氳鍗曟垚鍥€佸彇娑堛侀娆炬垚鍔熷悗璋冪敤銆 + * + * @param regionId 鍖哄煙ID + * @param orderId 璁㈠崟ID + */ + public void remove(String regionId, String orderId) { + if (StringUtils.isBlank(regionId) || StringUtils.isBlank(orderId)) { + log.info("UserPendingOrderCacheUtil.remove 鍙傛暟鏃犳晥, regionId={}, orderId={}", regionId, orderId); + return; + } + try { + String key = buildKey(regionId); + redisTemplateHelper.hDelete(key, orderId); + log.info("鍒犻櫎璁㈠崟缂撳瓨: regionId={}, orderId={}", regionId, orderId); + } catch (Exception e) { + log.info("鍒犻櫎璁㈠崟缂撳瓨澶辫触: regionId={}, orderId={}", regionId, orderId, e); + } + } + + /** + * 娓呴櫎鎸囧畾鎶㈠崟澶у巺鎵鏈夎鍗曠紦瀛 + *

    + * 鍏稿瀷鍦烘櫙锛氶渶瑕佸己鍒跺埛鏂拌鎶㈠崟澶у巺缂撳瓨鏃惰皟鐢ㄣ + * + * @param regionId 鍖哄煙ID + */ + public void removeAll(String regionId) { + if (StringUtils.isBlank(regionId)) { + return; + } + try { + redisTemplateHelper.delete(buildKey(regionId)); + log.info("娓呴櫎鎶㈠崟澶у巺璁㈠崟缂撳瓨: regionId={}", regionId); + } catch (Exception e) { + log.info("娓呴櫎鎶㈠崟澶у巺璁㈠崟缂撳瓨澶辫触: regionId={}", regionId, e); + } + } + + // ================================================================ + // 鏇存柊锛坲pdate锛 + // ================================================================ + + /** + * 鏍规嵁 regionId 鍜 orderId 鏇存柊缂撳瓨涓殑璁㈠崟淇℃伅 + *

    + * 濡傛灉鏇存柊鍚庣殑璁㈠崟鐘舵佸凡缁忎笉灞炰簬"寰呭畬鎴"锛坰tatus 鈭 {10}锛夛紝 + * 鍒欒嚜鍔ㄤ粠缂撳瓨涓Щ闄よ璁㈠崟锛屾棤闇璋冪敤鏂归澶栧垽鏂 + * + * @param regionId 鍖哄煙ID + * @param orderVO 鏇存柊鍚庣殑璁㈠崟VO + */ + public void update(String regionId, MallDeliveryOrder orderVO) { + if (StringUtils.isBlank(regionId) || orderVO == null || StringUtils.isBlank(orderVO.getId())) { + log.warn("UserPendingOrderCacheUtil.update 鍙傛暟鏃犳晥, regionId={}, orderVO={}", regionId, orderVO); + return; + } + try { + // 濡傛灉璁㈠崟鐘舵佸凡涓嶅睘浜庯紝鐩存帴鍒犻櫎 + /*if (!isTerminalStatus(orderVO.getStatus())) { + remove(regionId, orderVO.getId()); + log.debug("璁㈠崟宸茬粓鎬侊紝浠庣紦瀛樼Щ闄: regionId={}, orderId={}, status={}", + regionId, orderVO.getId(), orderVO.getStatus()); + return; + }*/ + // 瑕嗙洊鏇存柊 + put(regionId, orderVO); + log.info("鏇存柊鎶㈠崟澶у巺缂撳瓨: regionId={}, orderId={}, status={}", + regionId, orderVO.getId(), orderVO.getStatus()); + } catch (Exception e) { + log.info("鏇存柊鐢ㄦ埛寰呭畬鎴愯鍗曠紦瀛樺け璐: regionId={}, orderId={}", regionId, orderVO.getId(), e); + } + } + + // ================================================================ + // 鏌ヨ锛坓et锛 + // ================================================================ + + /** + * 鑾峰彇鎶㈠崟澶у巺璁㈠崟缂撳瓨锛堝惈鍒嗛〉銆佽繃婊ゃ佹帓搴忓拰鍚勭被鍨嬭鍗曟暟缁熻锛 + *

    + * 涓ょ鍦烘櫙锛 + * 1. deliveryType==4 涓 workerId 闈炵┖ 鈫 鏌ョ湅鎸囨淳鍗曞垪琛 + 鍏朵粬绫诲瀷璁㈠崟鏁 + * 2. 鍏朵粬鎯呭喌锛坔allOnly=true锛夆啋 鏌ョ湅鎶㈠崟澶у巺鏌愮被鍨嬭鍗曞垪琛(鍒嗛〉) + 鎸囨淳鍗曟暟 + 鍚勭被鍨嬭鍗曟暟 + * + * @param q 鏌ヨ鍙傛暟 + * @return 鍖呭惈鍒嗛〉鏁版嵁鍜岀粺璁℃暟鎹殑 Map锛岀紦瀛樹笉瀛樺湪鏃惰繑鍥 null锛堣皟鐢ㄦ柟鎹鍥炴簮鏌ュ簱锛 + */ + public Map getAll(MallDeliveryOrderPageQuery q) { + // 1. 鍩虹鏍¢獙 + if (StringUtils.isBlank(q.getRegionId())) { + return null; + } + + try { + String key = buildKey(q.getRegionId()); + // 2. 鑾峰彇 Hash 涓殑鎵鏈夎鍗曟暟鎹 + Map entries = redisTemplateHelper.hGetAll(key); + + // 濡傛灉缂撳瓨涓病鏈夋暟鎹紝杩斿洖 null 璁╄皟鐢ㄦ柟鍘绘煡搴 + if (entries == null || entries.isEmpty()) { + return null; + } + + // 3. 鍙嶅簭鍒楀寲鎵鏈夌紦瀛樿鍗 + List allCachedOrders = new ArrayList<>(entries.size()); + for (Object value : entries.values()) { + if (value != null) { + allCachedOrders.add(JSONUtil.toBean(value.toString(), MallDeliveryOrder.class)); + } + } + + Map result = new HashMap<>(); + + if (q.getDeliveryType() != null && q.getDeliveryType() == 4 + && StringUtils.isNotBlank(q.getWorkerId())) { + // ====== 鍦烘櫙A: 鏌ョ湅鎸囨淳鍗曡鍗曞垪琛 ====== + // 绛涢夛細workerId 鍖归厤銆乻tatus=0锛屼笉鍖哄垎 deliveryType + List zhipaiList = allCachedOrders.stream() + .filter(o -> q.getWorkerId().equals(o.getWorkerId())) + .filter(o -> o.getStatus() != null && o.getStatus() == 0) + .collect(Collectors.toList()); + + // 鎺掑簭锛堝鍒 selectPageVO 鐨 ORDER BY锛 + zhipaiList.sort(buildComparator(q)); + + long total = zhipaiList.size(); + int limit = (int) Math.min(total, 100); + List records = new ArrayList<>(zhipaiList.subList(0, limit)); + + result.put("records", records); + result.put("total", total); + result.put("size", 100); + result.put("current", 1); + result.put("pages", 1); + result.put("zhipaiCount", total); + // 澶栧崠銆佸揩閫掋佽窇鑵垮緟鎺ュ崟鏁 + result.put("orderCount", countOrdersByTypeInMemory(allCachedOrders)); + + } else { + // ====== 鍦烘櫙B: 鏌ョ湅鎶㈠崟澶у巺璁㈠崟鍒楄〃锛堝鍗/蹇/璺戣吙锛====== + + // 鍏堣绠楁寚娲惧崟鏁伴噺锛坵orkerId 鍖归厤銆乻tatus=0锛 + if (StringUtils.isNotBlank(q.getWorkerId())) { + long zhipaiCount = allCachedOrders.stream() + .filter(o -> q.getWorkerId().equals(o.getWorkerId())) + .filter(o -> o.getStatus() != null && o.getStatus() == 0) + .count(); + result.put("zhipaiCount", zhipaiCount); + } + + // 杩囨护鎶㈠崟澶у巺璁㈠崟锛歸orkerId 涓虹┖ 涓 status=0 + List filteredList = allCachedOrders.stream() + .filter(o -> StringUtils.isBlank(o.getWorkerId())) + .filter(o -> o.getStatus() != null && o.getStatus() == 0) + .collect(Collectors.toList()); + + // 鎸 deliveryType 杩囨护 + if (q.getDeliveryType() != null) { + final Integer deliveryType = q.getDeliveryType(); + filteredList = filteredList.stream() + .filter(o -> deliveryType.equals(o.getDeliveryType())) + .collect(Collectors.toList()); + } + + // 鎸 getAreaId 杩囨护 + if (StringUtils.isNotBlank(q.getGetAreaId())) { + filteredList = filteredList.stream() + .filter(o -> q.getGetAreaId().equals(o.getGetAreaId())) + .collect(Collectors.toList()); + } + + // 鎸 putAreaId 杩囨护 + if (StringUtils.isNotBlank(q.getPutAreaId())) { + filteredList = filteredList.stream() + .filter(o -> q.getPutAreaId().equals(o.getPutAreaId())) + .collect(Collectors.toList()); + } + + // 鎸 shopId 杩囨护 + if (StringUtils.isNotBlank(q.getShopId())) { + filteredList = filteredList.stream() + .filter(o -> q.getShopId().equals(o.getShopId())) + .collect(Collectors.toList()); + } + + // 鎸 shopName 妯$硦杩囨护 + if (StringUtils.isNotBlank(q.getShopName())) { + final String shopNameKeyword = q.getShopName(); + filteredList = filteredList.stream() + .filter(o -> o.getShopName() != null && o.getShopName().contains(shopNameKeyword)) + .collect(Collectors.toList()); + } + + // 鎸夋棩鏈熻寖鍥磋繃婊 + if (StringUtils.isNotBlank(q.getStartDate())) { + filteredList = filteredList.stream() + .filter(o -> o.getCreateTime() != null + && formatDate(o.getCreateTime()).compareTo(q.getStartDate()) >= 0) + .collect(Collectors.toList()); + } + if (StringUtils.isNotBlank(q.getEndDate())) { + filteredList = filteredList.stream() + .filter(o -> o.getCreateTime() != null + && formatDate(o.getCreateTime()).compareTo(q.getEndDate()) <= 0) + .collect(Collectors.toList()); + } + + // 鎺掑簭锛堝鍒 selectPageVO 鐨 ORDER BY锛 + filteredList.sort(buildComparator(q)); + + // 鍒嗛〉锛堟姠鍗曞ぇ鍘呮瘡椤20鏉★級 + int pageSize = 20; + int pageNum = q.getPageNum(); + long total = filteredList.size(); + long pages = total > 0 ? (total + pageSize - 1) / pageSize : 0; + + // 寰幆鍒嗛〉锛堝悓 pageDelivery 閫昏緫锛氶〉鐮佽秺鐣屾椂寰幆鍥炲埌鍓嶉潰锛 + if (pages > 0 && pageNum > pages) { + pageNum = (int) (((pageNum - 1) % pages) + 1); + } + + List records; + if (total > 0) { + int offset = (pageNum - 1) * pageSize; + if (offset >= total) { + records = Collections.emptyList(); + } else { + int end = (int) Math.min(offset + pageSize, total); + records = new ArrayList<>(filteredList.subList(offset, end)); + } + } else { + records = Collections.emptyList(); + } + + result.put("records", records); + result.put("total", total); + result.put("size", pageSize); + result.put("current", pageNum); + result.put("pages", pages); + // 澶栧崠銆佸揩閫掋佽窇鑵垮緟鎺ュ崟鏁 + result.put("orderCount", countOrdersByTypeInMemory(allCachedOrders)); + } + + return result; + + } catch (Exception e) { + log.error("鑾峰彇鎶㈠崟澶у巺璁㈠崟缂撳瓨澶辫触: regionId={}", q.getRegionId(), e); + // 鍙戠敓寮傚父杩斿洖 null锛屽己鍒跺洖婧愭煡搴擄紝淇濊瘉绯荤粺鍙敤鎬 + return null; + } + } + + /** + * 鑾峰彇鎶㈠崟澶у巺缂撳瓨鍗曚釜璁㈠崟 + * + * @param regionId 鍖哄煙ID + * @param orderId 璁㈠崟ID + * @return 缂撳瓨鐨勮鍗昖O锛屼笉瀛樺湪鏃惰繑鍥 null + */ + public MallDeliveryOrder get(String regionId, String orderId) { + if (StringUtils.isBlank(regionId) || StringUtils.isBlank(orderId)) { + return null; + } + try { + String key = buildKey(regionId); + Object value = redisTemplateHelper.hGet(key, orderId); + if (value == null) { + return null; + } + return JSONUtil.toBean(value.toString(), MallDeliveryOrder.class); + } catch (Exception e) { + log.info("鑾峰彇鎶㈠崟澶у巺鍗曚釜璁㈠崟缂撳瓨澶辫触: regionId={}, orderId={}", regionId, orderId, e); + return null; + } + } + + /** + * 鍒ゆ柇璇ユ姠鍗曞ぇ鍘呯殑缂撳瓨鏄惁宸插瓨鍦 + * + * @param regionId 鍖哄煙ID + * @return true 琛ㄧず缂撳瓨瀛樺湪 + */ + public boolean exists(String regionId) { + if (StringUtils.isBlank(regionId)) { + return false; + } + Boolean hasKey = redisTemplateHelper.hasKey(buildKey(regionId)); + return hasKey != null && hasKey; + } + + // ================================================================ + // 鍐呴儴宸ュ叿 + // ================================================================ + + /** + * 鏋勫缓鎺掑簭姣旇緝鍣紙澶嶅埢 selectPageVO 鐨 ORDER BY 閫昏緫锛 + *

    +     * ORDER BY:
    +     *   1. 濡傛灉 order='deliveryFee' 鈫 delivery_fee DESC
    +     *   2. 濡傛灉鏈 waimaiData/kuaidiData 鈫 鍖哄煙鍖归厤浼樺厛 DESC
    +     *   3. must_finish_time IS NULL 鎺掓渶鍚庯紙ASC: NOT NULL=0, NULL=1锛
    +     *   4. must_finish_time ASC
    +     *   5. delivery_fee DESC
    +     * 
    + */ + private Comparator buildComparator(MallDeliveryOrderPageQuery q) { + List> comparators = new ArrayList<>(); + + // 1. 鎸変剑閲戦檷搴忥紙濡傛灉 order=deliveryFee锛 + if ("deliveryFee".equals(q.getOrder())) { + comparators.add((a, b) -> { + BigDecimal feeA = a.getDeliveryFee() != null ? a.getDeliveryFee() : BigDecimal.ZERO; + BigDecimal feeB = b.getDeliveryFee() != null ? b.getDeliveryFee() : BigDecimal.ZERO; + return feeB.compareTo(feeA); + }); + } + + // 2. 鍖哄煙鍖归厤瑙勫垯鎺掑簭锛堝尮閰=1 涓嶅尮閰=0锛孌ESC锛 + boolean hasWaimai = q.getWaimaiData() != null && !q.getWaimaiData().isEmpty(); + boolean hasKuaidi = q.getKuaidiData() != null && !q.getKuaidiData().isEmpty(); + if (hasWaimai || hasKuaidi) { + comparators.add((a, b) -> { + int scoreA = calcAreaMatchScore(a, q); + int scoreB = calcAreaMatchScore(b, q); + return Integer.compare(scoreB, scoreA); + }); + } + + // 3. must_finish_time IS NULL 鎺掓渶鍚 (NULL鈫1, NOT NULL鈫0, ASC) + comparators.add((a, b) -> { + int nullA = a.getMustFinishTime() == null ? 1 : 0; + int nullB = b.getMustFinishTime() == null ? 1 : 0; + return Integer.compare(nullA, nullB); + }); + + // 4. must_finish_time ASC + comparators.add((a, b) -> { + if (a.getMustFinishTime() == null && b.getMustFinishTime() == null) return 0; + if (a.getMustFinishTime() == null) return 1; + if (b.getMustFinishTime() == null) return -1; + return a.getMustFinishTime().compareTo(b.getMustFinishTime()); + }); + + // 5. delivery_fee DESC + comparators.add((a, b) -> { + BigDecimal feeA = a.getDeliveryFee() != null ? a.getDeliveryFee() : BigDecimal.ZERO; + BigDecimal feeB = b.getDeliveryFee() != null ? b.getDeliveryFee() : BigDecimal.ZERO; + return feeB.compareTo(feeA); + }); + + // 缁勫悎鎵鏈夋瘮杈冨櫒 + return (a, b) -> { + for (Comparator c : comparators) { + int cmp = c.compare(a, b); + if (cmp != 0) return cmp; + } + return 0; + }; + } + + /** + * 璁$畻鍖哄煙鍖归厤寰楀垎锛堝鍒 selectPageVO 涓 CASE WHEN 閫昏緫锛 + * 澶栧崠(deliveryType=1)鍖归厤 waimaiData锛屽揩閫(deliveryType=2)鍖归厤 kuaidiData + */ + private int calcAreaMatchScore(MallDeliveryOrder order, MallDeliveryOrderPageQuery q) { + if (order.getDeliveryType() == null) return 0; + // 澶栧崠鍖归厤瑙勫垯 + if (order.getDeliveryType() == 1 && q.getWaimaiData() != null) { + for (AreaRuleDTO rule : q.getWaimaiData()) { + if (Objects.equals(order.getGetAreaId(), rule.getGetAreaId()) + && Objects.equals(order.getPutAreaId(), rule.getPutAreaId())) { + return 1; + } + } + } + // 蹇掑尮閰嶈鍒 + if (order.getDeliveryType() == 2 && q.getKuaidiData() != null) { + for (AreaRuleDTO rule : q.getKuaidiData()) { + if (Objects.equals(order.getGetAreaId(), rule.getGetAreaId()) + && Objects.equals(order.getPutAreaId(), rule.getPutAreaId())) { + return 1; + } + } + } + return 0; + } + + /** + * 鍦ㄥ唴瀛樹腑缁熻鍚勭被鍨嬪緟鎺ュ崟鏁帮紙澶嶅埢 countOrdersByType SQL 閫昏緫锛 + * 鏉′欢锛歸orker_id IS NULL锛宻tatus=0锛屾寜 delivery_type 鍒嗙粍璁℃暟 + */ + private List> countOrdersByTypeInMemory(List allOrders) { + Map countMap = allOrders.stream() + .filter(o -> StringUtils.isBlank(o.getWorkerId())) + .filter(o -> o.getStatus() != null && o.getStatus() == 0) + .filter(o -> o.getDeliveryType() != null) + .collect(Collectors.groupingBy(MallDeliveryOrder::getDeliveryType, Collectors.counting())); + + List> result = new ArrayList<>(); + for (Map.Entry entry : countMap.entrySet()) { + Map m = new HashMap<>(); + m.put("deliveryType", entry.getKey()); + m.put("orderCount", entry.getValue()); + result.add(m); + } + return result; + } + + /** + * 鏃ユ湡鏍煎紡鍖栦负 yyyy-MM-dd锛堢敤浜庢棩鏈熻寖鍥磋繃婊ゆ瘮杈冿級 + */ + private String formatDate(Date date) { + SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd"); + return sdf.format(date); + } + + /** + * 鍒ゆ柇璁㈠崟鐘舵佹槸鍚︿负缁堟侊紙涓嶅啀灞炰簬""锛 + */ + /* private boolean isTerminalStatus(Integer status) { + if (status == null) { + return false; + } + return status == STATUS_DONE; + }*/ +} diff --git a/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/utils/WorkerOrderCacheUtil.java b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/utils/WorkerOrderCacheUtil.java new file mode 100644 index 00000000..62affe5b --- /dev/null +++ b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/utils/WorkerOrderCacheUtil.java @@ -0,0 +1,324 @@ +package cc.hiver.mall.utils; + +import cc.hiver.core.common.redis.RedisTemplateHelper; +import cc.hiver.mall.entity.MallDeliveryOrder; +import cc.hiver.mall.pojo.query.MallDeliveryOrderPageQuery; +import cn.hutool.json.JSONUtil; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import java.util.*; +import java.util.stream.Collectors; + +/** + * 閰嶉佸憳寰呭畬鎴愯鍗曠紦瀛樺伐鍏风被 + *

    + * 搴曞眰浣跨敤 Redis Hash 缁撴瀯锛屼繚璇佹寜 workerId + orderId 缁村害鐨 O(1) 璇诲啓鏁堢巼銆 + *

    + *   Key   = WORKER_ORDERS:{workerId}
    + *   Field = orderId
    + *   Value = MallDeliveryOrder 鐨 JSON 搴忓垪鍖
    + * 
    + *

    + * 浣跨敤鍦烘櫙锛氳鍗曠姸鎬佸彂鐢熷彉鍖栨椂锛堝垱寤恒佹洿鏂般佸彇娑堛佸畬鎴愮瓑锛夛紝 + * 鐢变笟鍔℃柟涓诲姩璋冪敤鏈伐鍏风被鐨勬柟娉曠淮鎶ょ紦瀛橈紝浠ュ噺灏 pagebyworker 鎺ュ彛瀵规暟鎹簱鐨勬煡璇㈠帇鍔涖 + * + * @author system + */ +@Slf4j +@Component +public class WorkerOrderCacheUtil { + + /** Redis Key 鍓嶇紑 */ + private static final String KEY_PREFIX = "WORKER_ORDERS:"; + + @Autowired + private RedisTemplateHelper redisTemplateHelper; + + // ================================================================ + // Key 鏋勫缓 + // ================================================================ + + private String buildKey(String workerId) { + return KEY_PREFIX + workerId; + } + + // ================================================================ + // 瀛樻斁锛坧ut锛 + // ================================================================ + + /** + * 瀛樻斁鍗曚釜璁㈠崟鍒扮紦瀛 + * + * @param workerId 閰嶉佸憳ID + * @param orderVO 璁㈠崟VO锛堝繀椤诲寘鍚湁鏁堢殑 id锛 + */ + public void put(String workerId, MallDeliveryOrder orderVO) { + if (StringUtils.isBlank(workerId) || orderVO == null || StringUtils.isBlank(orderVO.getId())) { + log.info("UserPendingOrderCacheUtil.put 鍙傛暟鏃犳晥, userId={}, orderVO={}", workerId, orderVO); + return; + } + try { + String key = buildKey(workerId); + String json = JSONUtil.toJsonStr(orderVO); + redisTemplateHelper.hPut(key, orderVO.getId(), json); + log.info("缂撳瓨閰嶉佸憳璁㈠崟: workerId={}, orderId={}", workerId, orderVO.getId()); + } catch (Exception e) { + log.info("缂撳瓨閰嶉佸憳璁㈠崟澶辫触: workerId={}, orderId={}", workerId, orderVO.getId(), e); + } + } + + /** + * 鎵归噺瀛樻斁璁㈠崟鍒扮紦瀛橈紙閫氬父鐢ㄤ簬缂撳瓨棰勭儹 / 棣栨鍔犺浇锛 + * + * @param workerId 閰嶉佸憳ID + * @param orders 璁㈠崟鍒楄〃 + */ + public void putAll(String workerId, List orders) { + if (StringUtils.isBlank(workerId) || orders == null || orders.isEmpty()) { + return; + } + try { + String key = buildKey(workerId); + Map map = new java.util.LinkedHashMap<>(orders.size()); + for (MallDeliveryOrder order : orders) { + if (order != null && StringUtils.isNotBlank(order.getId())) { + map.put(order.getId(), JSONUtil.toJsonStr(order)); + } + } + if (!map.isEmpty()) { + redisTemplateHelper.hPutAll(key, map); + log.info("鎵归噺缂撳瓨閰嶉佸憳璁㈠崟: workerId={}, count={}", workerId, map.size()); + } + } catch (Exception e) { + log.info("鎵归噺缂撳瓨閰嶉佸憳璁㈠崟澶辫触: workerId={}", workerId, e); + } + } + + // ================================================================ + // 鍒犻櫎锛坮emove锛 + // ================================================================ + + /** + * 鏍规嵁 workerId 鍜 orderId 浠庣紦瀛樹腑鍒犻櫎鎸囧畾璁㈠崟 + *

    + * 鍏稿瀷鍦烘櫙锛氳鍗曟垚鍥€佸彇娑堛侀娆炬垚鍔熷悗璋冪敤銆 + * + * @param workerId 閰嶉佸憳ID + * @param orderId 璁㈠崟ID + */ + public void remove(String workerId, String orderId) { + if (StringUtils.isBlank(workerId) || StringUtils.isBlank(orderId)) { + log.info("UserPendingOrderCacheUtil.remove 鍙傛暟鏃犳晥, workerId={}, orderId={}", workerId, orderId); + return; + } + try { + String key = buildKey(workerId); + redisTemplateHelper.hDelete(key, orderId); + log.info("鍒犻櫎璁㈠崟缂撳瓨: workerId={}, orderId={}", workerId, orderId); + } catch (Exception e) { + log.info("鍒犻櫎璁㈠崟缂撳瓨澶辫触: workerId={}, orderId={}", workerId, orderId, e); + } + } + + /** + * 娓呴櫎鎸囧畾閰嶉佸憳鎵鏈夎鍗曠紦瀛 + *

    + * 鍏稿瀷鍦烘櫙锛氶渶瑕佸己鍒跺埛鏂拌閰嶉佸憳缂撳瓨鏃惰皟鐢ㄣ + * + * @param workerId 閰嶉佸憳ID + */ + public void removeAll(String workerId) { + if (StringUtils.isBlank(workerId)) { + return; + } + try { + redisTemplateHelper.delete(buildKey(workerId)); + log.info("娓呴櫎閰嶉佸憳璁㈠崟缂撳瓨: workerId={}", workerId); + } catch (Exception e) { + log.info("娓呴櫎閰嶉佸憳璁㈠崟缂撳瓨澶辫触: workerId={}", workerId, e); + } + } + + // ================================================================ + // 鏇存柊锛坲pdate锛 + // ================================================================ + + /** + * 鏍规嵁 workerId 鍜 orderId 鏇存柊缂撳瓨涓殑璁㈠崟淇℃伅 + *

    + * 濡傛灉鏇存柊鍚庣殑璁㈠崟鐘舵佸凡缁忎笉灞炰簬"寰呭畬鎴"锛坰tatus 鈭 {10}锛夛紝 + * 鍒欒嚜鍔ㄤ粠缂撳瓨涓Щ闄よ璁㈠崟锛屾棤闇璋冪敤鏂归澶栧垽鏂 + * + * @param workerId 閰嶉佸憳ID + * @param orderVO 鏇存柊鍚庣殑璁㈠崟VO + */ + public void update(String workerId, MallDeliveryOrder orderVO) { + if (StringUtils.isBlank(workerId) || orderVO == null || StringUtils.isBlank(orderVO.getId())) { + log.warn("UserPendingOrderCacheUtil.update 鍙傛暟鏃犳晥, workerId={}, orderVO={}", workerId, orderVO); + return; + } + try { + // 濡傛灉璁㈠崟鐘舵佸凡涓嶅睘浜庯紝鐩存帴鍒犻櫎 + /*if (!isTerminalStatus(orderVO.getStatus())) { + remove(workerId, orderVO.getId()); + log.debug("璁㈠崟宸茬粓鎬侊紝浠庣紦瀛樼Щ闄: workerId={}, orderId={}, status={}", + workerId, orderVO.getId(), orderVO.getStatus()); + return; + }*/ + // 瑕嗙洊鏇存柊 + put(workerId, orderVO); + log.info("鏇存柊閰嶉佸憳缂撳瓨: workerId={}, orderId={}, status={}", + workerId, orderVO.getId(), orderVO.getStatus()); + } catch (Exception e) { + log.info("鏇存柊鐢ㄦ埛寰呭畬鎴愯鍗曠紦瀛樺け璐: workerId={}, orderId={}", workerId, orderVO.getId(), e); + } + } + + // ================================================================ + // 鏌ヨ锛坓et锛 + // ================================================================ + + /** + * 鑾峰彇閰嶉佸憳璁㈠崟缂撳瓨 + * + * @param q 閰嶉佸憳褰撳墠璁㈠崟鏌ヨ瀹炰綋 deliveryType/pageNum/pageSize/regionId/status/workerId + * @return 缂撳瓨鐨勮鍗曞垪琛紝缂撳瓨涓嶅瓨鍦ㄦ椂杩斿洖 null锛堣皟鐢ㄦ柟鍙嵁姝ゅ垽鏂槸鍚﹂渶瑕佸洖婧愭煡搴擄級 + */ + public IPage getAll(MallDeliveryOrderPageQuery q) { + // 1. 鍩虹鏍¢獙 + if (StringUtils.isBlank(q.getWorkerId())) { + return null; + } + + try { + String key = buildKey(q.getWorkerId()); + // 2. 鑾峰彇 Hash 涓殑鎵鏈夎鍗曟暟鎹 + Map entries = redisTemplateHelper.hGetAll(key); + + // 濡傛灉缂撳瓨涓病鏈夋暟鎹紝杩斿洖 null 璁╄皟鐢ㄦ柟鍘绘煡搴 + if (entries == null || entries.isEmpty()) { + return null; + } + + // 3. 鍙嶅簭鍒楀寲骞惰浆鎹负 List + List allCachedOrders = new ArrayList<>(entries.size()); + for (Object value : entries.values()) { + if (value != null) { + // 鍋囪 JSONUtil 鏄 Hutool 鎴栫被浼煎伐鍏风被 + allCachedOrders.add(JSONUtil.toBean(value.toString(), MallDeliveryOrder.class)); + } + } + + // 4. 鍐呭瓨杩囨护 (鏍规嵁 deliveryType, regionId, status) + List filteredList = allCachedOrders.stream() + .filter(order -> { + // 鐘舵佽繃婊 + if (q.getStatus() != null && !Objects.equals(order.getStatus(), q.getStatus())) { + return false; + } + // 閰嶉佺被鍨嬭繃婊 + if (q.getDeliveryType() != null && !Objects.equals(order.getDeliveryType(), q.getDeliveryType())) { + return false; + } + // 鍖哄煙ID杩囨护 + if (StringUtils.isNotBlank(q.getRegionId()) && !Objects.equals(order.getRegionId(), q.getRegionId())) { + return false; + } + return true; + }) + .collect(Collectors.toList()); + filteredList.sort(Comparator.comparing(MallDeliveryOrder::getMustFinishTime, + Comparator.nullsLast(Comparator.naturalOrder()))); + + // 5. 鍐呭瓨鍒嗛〉 + // 鍒濆鍖栧垎椤靛璞 + Integer pageNum = q.getPageNum(); + Integer pageSize = q.getPageSize(); + + IPage page = new Page<>(pageNum, pageSize); + + // 璁$畻鎬昏褰曟暟 + long total = filteredList.size(); + page.setTotal(total); + + // 璁$畻褰撳墠椤电殑鏁版嵁 + if (total > 0) { + long offset = (pageNum - 1) * pageSize; + // 闃叉瓒婄晫 + if (offset >= total) { + page.setRecords(Collections.emptyList()); + } else { + int start = (int) Math.min(offset, total); + int end = (int) Math.min(offset + pageSize, total); + page.setRecords(filteredList.subList(start, end)); + } + } else { + page.setRecords(Collections.emptyList()); + } + + return page; + + } catch (Exception e) { + log.error("鑾峰彇閰嶉佸憳璁㈠崟缂撳瓨澶辫触: workerId={}", q.getWorkerId(), e); + // 鍙戠敓寮傚父杩斿洖 null锛屽己鍒跺洖婧愭煡搴擄紝淇濊瘉绯荤粺鍙敤鎬 + return null; + } + } + + /** + * 鑾峰彇閰嶉佸憳缂撳瓨鍗曚釜璁㈠崟 + * + * @param workerId 閰嶉佸憳ID + * @param orderId 璁㈠崟ID + * @return 缂撳瓨鐨勮鍗昖O锛屼笉瀛樺湪鏃惰繑鍥 null + */ + public MallDeliveryOrder get(String workerId, String orderId) { + if (StringUtils.isBlank(workerId) || StringUtils.isBlank(orderId)) { + return null; + } + try { + String key = buildKey(workerId); + Object value = redisTemplateHelper.hGet(key, orderId); + if (value == null) { + return null; + } + return JSONUtil.toBean(value.toString(), MallDeliveryOrder.class); + } catch (Exception e) { + log.info("鑾峰彇閰嶉佸憳鍗曚釜璁㈠崟缂撳瓨澶辫触: workerId={}, orderId={}", workerId, orderId, e); + return null; + } + } + + /** + * 鍒ゆ柇璇ラ厤閫佸憳鐨勭紦瀛樻槸鍚﹀凡瀛樺湪 + * + * @param workerId 閰嶉佸憳ID + * @return true 琛ㄧず缂撳瓨瀛樺湪 + */ + public boolean exists(String workerId) { + if (StringUtils.isBlank(workerId)) { + return false; + } + Boolean hasKey = redisTemplateHelper.hasKey(buildKey(workerId)); + return hasKey != null && hasKey; + } + + // ================================================================ + // 鍐呴儴宸ュ叿 + // ================================================================ + + /** + * 鍒ゆ柇璁㈠崟鐘舵佹槸鍚︿负缁堟侊紙涓嶅啀灞炰簬""锛 + */ + /* private boolean isTerminalStatus(Integer status) { + if (status == null) { + return false; + } + return status == STATUS_DONE; + }*/ +} diff --git a/hiver-modules/hiver-mall/src/main/resources/mapper/MallOrderGoodsMapper.xml b/hiver-modules/hiver-mall/src/main/resources/mapper/MallOrderGoodsMapper.xml index 0062f1f9..10d985a4 100644 --- a/hiver-modules/hiver-mall/src/main/resources/mapper/MallOrderGoodsMapper.xml +++ b/hiver-modules/hiver-mall/src/main/resources/mapper/MallOrderGoodsMapper.xml @@ -24,9 +24,19 @@ + + +