From 3a7bf15f7b277a5cdadb2af07aaa20086ba96c8c Mon Sep 17 00:00:00 2001 From: wangfukang <15630117759@163.com> Date: Sat, 27 Jun 2026 18:17:54 +0800 Subject: [PATCH] =?UTF-8?q?=E5=AF=B9=E6=8E=A5=E6=8B=BC=E5=9B=A2=E6=95=B0?= =?UTF-8?q?=E6=8D=AE1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- hiver-admin/test-output/test-report.html | 16 +- .../mall/controller/CommentController.java | 27 +++ .../mall/controller/MallCouponController.java | 17 ++ .../hiver/mall/controller/ShopController.java | 36 ++-- .../mall/dao/mapper/MallOrderMapper.java | 2 +- .../cc/hiver/mall/entity/MallUserCoupon.java | 2 +- .../cc/hiver/mall/mq/OrderAsyncConsumer.java | 87 ++++++-- .../cc/hiver/mall/mq/OrderDelayConsumer.java | 15 ++ .../mall/quartz/IeDailyQuotaResetTask.java | 40 ++++ .../service/mybatis/MallOrderService.java | 5 + .../mybatis/MallUserCouponService.java | 1 + .../mybatis/MallDeliveryOrderServiceImpl.java | 19 +- .../mybatis/MallOrderGroupServiceImpl.java | 6 +- .../mybatis/MallOrderServiceImpl.java | 200 +++++++++++++++--- .../mybatis/MallRefundRecordServiceImpl.java | 72 +++++-- .../mybatis/MallUserCouponServiceImpl.java | 18 ++ .../java/cc/hiver/mall/utils/UpdateUtils.java | 28 +++ .../main/resources/mapper/MallOrderMapper.xml | 17 +- 18 files changed, 512 insertions(+), 96 deletions(-) create mode 100644 hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/quartz/IeDailyQuotaResetTask.java create mode 100644 hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/utils/UpdateUtils.java diff --git a/hiver-admin/test-output/test-report.html b/hiver-admin/test-output/test-report.html index 506af16c..42f2d819 100644 --- a/hiver-admin/test-output/test-report.html +++ b/hiver-admin/test-output/test-report.html @@ -35,7 +35,7 @@ Hiver
  • -ÁùÔÂ 24, 2026 14:41:22 +ÁùÔÂ 27, 2026 17:16:55
  • @@ -84,7 +84,7 @@

    passTest

    -

    14:41:23 ÏÂÎç / 0.026 secs

    +

    17:16:55 ÏÂÎç / 0.037 secs

    @@ -92,9 +92,9 @@
    #test-id=1
    passTest
    -06.24.2026 14:41:23 -06.24.2026 14:41:23 -0.026 secs +06.27.2026 17:16:55 +06.27.2026 17:16:55 +0.037 secs
    @@ -104,7 +104,7 @@ Pass - 14:41:23 + 17:16:55 Test passed @@ -128,13 +128,13 @@

    Started

    -

    ÁùÔÂ 24, 2026 14:41:22

    +

    ÁùÔÂ 27, 2026 17:16:55

    Ended

    -

    ÁùÔÂ 24, 2026 14:41:23

    +

    ÁùÔÂ 27, 2026 17:16:55

    diff --git a/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/controller/CommentController.java b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/controller/CommentController.java index 2bbe1414..d01c7e63 100644 --- a/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/controller/CommentController.java +++ b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/controller/CommentController.java @@ -32,6 +32,7 @@ import cc.hiver.mall.service.ShopService; import cc.hiver.mall.utils.CommentCacheUtil; import cc.hiver.mall.utils.WorkerRedisCacheUtil; import cn.hutool.json.JSONUtil; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; @@ -80,6 +81,22 @@ public class CommentController { @ApiOperation("ä¿å­˜") public Result save( @RequestBody List comment) { comment.forEach(e -> { + if(e.getScore() == null || e.getScore().compareTo(BigDecimal.ZERO) == 0){ + e.setScore(BigDecimal.valueOf(5)); + } + if(StringUtils.isEmpty(e.getRemark())){ + if(e.getScore().equals(5)){ + e.setRemark("该用户觉得很好,给出了5星好评"); + }else if(e.getScore().equals(4)){ + e.setRemark("该用户觉得还å¯ä»¥ï¼Œç»™å‡ºäº†4星评价"); + }else if(e.getScore().equals(3)){ + e.setRemark("该用户觉得一般,给出了3星评价"); + }else if(e.getScore().equals(2)){ + e.setRemark("该用户觉得ä¸å¥½ï¼Œç»™å‡ºäº†2星评价"); + }else{ + e.setRemark("该用户觉得很ä¸å¥½ï¼Œç»™å‡ºäº†1星差评"); + } + } e.setCreateTime(new Date()); if(StringUtils.isEmpty(e.getParentId())){ e.setLevel(ShopConstant.SHOP_STATUS_LOCK); @@ -175,6 +192,16 @@ public class CommentController { return ResultUtil.success("删除æˆåŠŸ"); } + @RequestMapping(value = "/getByOrderId", method = RequestMethod.POST) + @ApiOperation("æ ¹æ®è®¢å•id获å–评论") + public Result> getByOrderId( @RequestParam String orderId) { + List comments = commentService.list(new LambdaQueryWrapper() + .eq(Comment::getOrderId, orderId) + .eq(Comment::getLevel, ShopConstant.SHOP_STATUS_LOCK) + .orderByDesc(Comment::getCreateTime)); + return ResultUtil.data(comments); + } + @RequestMapping(value = "/getCommentList", method = RequestMethod.POST) @ApiOperation("获å–店铺评论") public Result> getCommentList( @RequestBody CommentQuery commentQuery) { diff --git a/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/controller/MallCouponController.java b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/controller/MallCouponController.java index e8b5b107..6970d64f 100644 --- a/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/controller/MallCouponController.java +++ b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/controller/MallCouponController.java @@ -61,6 +61,14 @@ public class MallCouponController { private String couponId; } + @Data + public static class UserCouponPageReq { + private String userId; + private String regionId; + private Integer pageNum = 1; + private Integer pageSize = 10; + } + @PostMapping("/add") @ApiOperation(value = "添加/å‘行优惠券") public Result addCoupon(@RequestBody MallCoupon coupon) { @@ -118,6 +126,15 @@ public class MallCouponController { public Result> list(MallCouponQuery query) { return new ResultUtil>().setData(mallUserCouponService.selectPageVO(query)); } + + @PostMapping("/userList") + @ApiOperation(value = "获å–ç”¨æˆ·å½“å‰æ ¡åŒºå¯ç”¨ä¼˜æƒ åˆ¸åˆ—表") + public Result> userList(@RequestBody UserCouponPageReq query) { + return new ResultUtil>().setData( + mallUserCouponService.selectUserCouponPage(query.getUserId(), query.getRegionId(), query.getPageNum(), query.getPageSize()) + ); + } + @PostMapping("/addFreeOrder") @ApiOperation(value = "å¼€å¯å…å•优惠") public Result addFreeOrder(@RequestBody MallOrderFreeVO freeOrder) { diff --git a/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/controller/ShopController.java b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/controller/ShopController.java index 0a83077d..91107220 100644 --- a/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/controller/ShopController.java +++ b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/controller/ShopController.java @@ -43,6 +43,7 @@ import cc.hiver.mall.service.ShopAreaService; import cc.hiver.mall.service.ShopService; import cc.hiver.mall.service.ShopTakeawayService; import cc.hiver.mall.service.ShopUserService; +import cc.hiver.mall.utils.UpdateUtils; import cn.hutool.core.text.CharSequenceUtil; import cn.hutool.json.JSONUtil; import com.baomidou.mybatisplus.core.metadata.IPage; @@ -152,27 +153,34 @@ public class ShopController { @ResponseBody @ApiOperation("编辑") public Result edit(Shop shop) { - // èŽ·å–æ—§åº—é“ºä¿¡æ¯ + // 1. èŽ·å–æ•°æ®åº“ä¸­å®Œæ•´çš„æ—§åº—é“ºä¿¡æ¯ Shop oldShop = shopService.get(shop.getId()); + if (oldShop == null) { + throw new RuntimeException("店铺ä¸å­˜åœ¨"); + } + + // 2. 处ç†å•†åœˆç›¸å…³é€»è¾‘ï¼ˆä¿æŒä½ åŽŸæœ‰çš„ä¸šåŠ¡é€»è¾‘ï¼‰ if (CharSequenceUtil.isNotBlank(shop.getShopArea())) { final ShopArea d = shopAreaService.get(shop.getShopArea()); if (d != null) { - shop.setShopAreaTitle(d.getTitle()); + oldShop.setShopAreaTitle(d.getTitle()); } - // 获å–商圈的idå’Œåç§° final ShopArea topShopAreaById = shopAreaService.findTopShopAreaById(shop.getShopArea()); - shop.setRegion(topShopAreaById.getTitle()); - shop.setRegionId(topShopAreaById.getId()); + if (topShopAreaById != null) { + oldShop.setRegion(topShopAreaById.getTitle()); + oldShop.setRegionId(topShopAreaById.getId()); + } + oldShop.setShopArea(shop.getShopArea()); // åŒæ­¥æ›´æ–°å•†åœˆID } else { - shop.setShopArea(null); - shop.setShopAreaTitle(""); - shop.setRegion(""); - shop.setRegionId(null); - } - if(shop.getSaleCount() == null){ - shop.setSaleCount(0); - } - shopService.update(shop); + // 如果å‰ç«¯æ˜Žç¡®ä¼ äº†ç©ºï¼Œè¯´æ˜Žè¦æ¸…ç©ºå•†åœˆä¿¡æ¯ + oldShop.setShopArea(null); + oldShop.setShopAreaTitle(""); + oldShop.setRegion(""); + oldShop.setRegionId(null); + } + UpdateUtils.copyNonNullProperties(shop, oldShop); + // 4. æ›´æ–°æ•°æ®åº“(此时更新的是带有完整数æ®çš„ oldShop,ä¸ä¼šè¯¯æ¸…空其他字段) + shopService.update(oldShop); //如果更æ¢åº—ä¸»ï¼Œé‚£ä¹ˆå°±é‡æ–°è®¾ç½®åº—主åŠåº—å‘˜ä¿¡æ¯ diff --git a/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/dao/mapper/MallOrderMapper.java b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/dao/mapper/MallOrderMapper.java index 4e9e789c..7d1435cf 100644 --- a/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/dao/mapper/MallOrderMapper.java +++ b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/dao/mapper/MallOrderMapper.java @@ -27,7 +27,7 @@ public interface MallOrderMapper extends BaseMapper { List> selectOrderStatusCount(@Param("shopId") String shopId); - HashMap selectOrderRevenueAndCount(@Param("shopId") String shopId,@Param("startTime") LocalDateTime startTime,@Param("endTime") LocalDateTime endTime); + List selectOrderRevenueAndCount(@Param("shopId") String shopId,@Param("startTime") LocalDateTime startTime,@Param("endTime") LocalDateTime endTime); Integer selectPendingBadReviewCount(@Param("shopId") String shopId); diff --git a/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/entity/MallUserCoupon.java b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/entity/MallUserCoupon.java index e20304ed..dd377559 100644 --- a/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/entity/MallUserCoupon.java +++ b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/entity/MallUserCoupon.java @@ -29,7 +29,7 @@ public class MallUserCoupon extends HiverBaseEntity { @ApiModelProperty(value = "呿”¾æ–¹ID") private String issuerId; - @ApiModelProperty(value = "适用场景") + @ApiModelProperty(value = "适用场景:0-通用,1-外å–/买饭,2-快递/跑腿,3-二手物å“交易ã€4团购") private Integer applyScene; @ApiModelProperty(value = "使用门槛") diff --git a/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/mq/OrderAsyncConsumer.java b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/mq/OrderAsyncConsumer.java index 912a841e..1638769e 100644 --- a/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/mq/OrderAsyncConsumer.java +++ b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/mq/OrderAsyncConsumer.java @@ -11,6 +11,7 @@ import cc.hiver.mall.entity.MallOrder; import cc.hiver.mall.ie.service.IeMatchService; import cc.hiver.mall.planet.hook.PlanetRewardHook; import cc.hiver.mall.pojo.dto.CreateOrderDTO; +import cc.hiver.mall.pojo.vo.WorkerRedisVo; import cc.hiver.mall.serviceimpl.mybatis.MallOrderServiceImpl; import cc.hiver.mall.utils.*; import com.alibaba.fastjson.JSON; @@ -26,9 +27,7 @@ import org.springframework.data.redis.core.StringRedisTemplate; import org.springframework.stereotype.Component; import java.text.SimpleDateFormat; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; +import java.util.*; /** * 处ç†éžæ ¸å¿ƒã€å“åº”æ—¶é—´ä¸æ•感的常规异步队列。 @@ -98,21 +97,20 @@ public class OrderAsyncConsumer { } List targetOpenIds = new ArrayList<>(); + List targetWorkers = new ArrayList<>(); String orderTypeStr = "抢å•大厅å•"; if (StringUtils.isNotBlank(delivery.getWorkerId())) { orderTypeStr = "指定接å•"; - // èŽ·å–æŒ‡å®šéª‘æ‰‹çš„å…³è” userId å’Œ openid - String openId = getOfficialAccountOpenidByWorkerId(delivery.getWorkerId()); - if (StringUtils.isNotBlank(openId)) { - targetOpenIds.add(openId); + WorkerRedisVo workerRedisVo = workerRedisCacheUtil.get(delivery.getRegionId(), delivery.getWorkerId()); + Worker worker = getOnlineWorkerInRegion(workerRedisVo, delivery.getRegionId()); + if (worker != null) { + targetWorkers.add(worker); } } else { - // 如果没有指定人,å‘给所有人?业务需求:给所有é…é€å‘˜å‘å¾®ä¿¡å…¬ä¼—å·æ¶ˆæ¯ - // è¿™å¯èƒ½éœ€è¦æŸ¥å‡ºæ‰€æœ‰ Worker å…³è”çš„ user.officialAccountOpenid (实际应用中å¯èƒ½éœ€è¦åŠ çŠ¶æ€è¿‡æ»¤) - // ä¸ºç®€åŒ–å¹¶å®žçŽ°é€»è¾‘ï¼Œè¿™é‡ŒåªæŸ¥æœ‰æ•ˆçš„骑手 user - targetOpenIds = getAllWorkerOpenIds(); + targetWorkers = getOnlineWorkersInRegion(delivery.getRegionId()); } + targetOpenIds = getOfficialAccountOpenids(targetWorkers); if (targetOpenIds.isEmpty()) { log.info("ã€å¼‚步队列处ç†ã€‘æ²¡æœ‰æ‰¾åˆ°å¯æŽ¨é€å¾®ä¿¡æ¨¡æ¿çš„openid,目标跳过推é€ã€‚orderId={}", orderId); @@ -149,19 +147,68 @@ public class OrderAsyncConsumer { } - private String getOfficialAccountOpenidByWorkerId(String workerId) { - Worker worker = workerService.findByWorkerId(workerId); - if (worker != null && StringUtils.isNotBlank(worker.getUserId())) { - User user = userService.findById(worker.getUserId()); - if (user != null) { - return user.getOfficialAccountOpenid(); + private Worker getOnlineWorkerInRegion(WorkerRedisVo workerRedisVo, String regionId) { + if (workerRedisVo == null || workerRedisVo.getWorker() == null) { + return null; + } + Worker worker = workerRedisVo.getWorker(); + if (!isOnlineWorkerInRegion(worker, regionId) || StringUtils.isBlank(worker.getUserId())) { + return null; + } + return worker; + } + + private List getOnlineWorkersInRegion(String regionId) { + List workers = new ArrayList<>(); + List workerRedisVoList = workerRedisCacheUtil.getAll(regionId); + if (workerRedisVoList == null || workerRedisVoList.isEmpty()) { + return workers; + } + for (WorkerRedisVo workerRedisVo : workerRedisVoList) { + Worker worker = getOnlineWorkerInRegion(workerRedisVo, regionId); + if (worker != null) { + workers.add(worker); + } + } + return workers; + } + + private List getOfficialAccountOpenids(List workers) { + List openids = new ArrayList<>(); + if (workers == null || workers.isEmpty()) { + return openids; + } + Set userIds = new LinkedHashSet<>(); + for (Worker worker : workers) { + if (worker != null && StringUtils.isNotBlank(worker.getUserId())) { + userIds.add(worker.getUserId()); + } + } + if (userIds.isEmpty()) { + return openids; + } + List users = userService.findAll((root, query, cb) -> root.get("id").in(userIds)); + Map openidMap = new LinkedHashMap<>(); + for (User user : users) { + if (user != null && StringUtils.isNotBlank(user.getOfficialAccountOpenid())) { + openidMap.put(user.getId(), user.getOfficialAccountOpenid()); + } + } + Set dedupOpenids = new LinkedHashSet<>(); + for (Worker worker : workers) { + String openid = openidMap.get(worker.getUserId()); + if (StringUtils.isNotBlank(openid)) { + dedupOpenids.add(openid); } } - return null; + openids.addAll(dedupOpenids); + return openids; } - private List getAllWorkerOpenIds() { - return mallOrderMapper.getWeChatId(); + private boolean isOnlineWorkerInRegion(Worker worker, String regionId) { + return worker != null + && StringUtils.equals(worker.getRegion(), regionId) + && Integer.valueOf(1).equals(worker.getIsOnLine()); } @RabbitListener(queues = OrderQueueConfig.ASYNC_CACHE_QUEUE) diff --git a/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/mq/OrderDelayConsumer.java b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/mq/OrderDelayConsumer.java index 0b93d7f4..c62913f2 100644 --- a/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/mq/OrderDelayConsumer.java +++ b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/mq/OrderDelayConsumer.java @@ -10,6 +10,7 @@ import cc.hiver.mall.entity.MallDeliveryOrder; import cc.hiver.mall.entity.MallOrder; import cc.hiver.mall.entity.MallRefundRecord; import cc.hiver.mall.entity.Shop; +import cc.hiver.mall.service.mybatis.MallOrderService; import cc.hiver.mall.service.mybatis.MallRefundRecordService; import cc.hiver.mall.utils.WaitOrderCacheUtil; import cc.hiver.mall.utils.WorkerOrderCacheUtil; @@ -39,6 +40,9 @@ public class OrderDelayConsumer { @Autowired private MallRefundRecordService mallRefundRecordService; + @Autowired + private MallOrderService mallOrderService; + @Autowired private ShopMapper shopMapper; @@ -92,6 +96,9 @@ public class OrderDelayConsumer { String refundId = msg.getString("refundId"); handleRefundAutoAgree(refundId); break; + case "Order_Pay_Timeout_1h": + handleOrderPayTimeout(orderId); + break; default: log.warn("ã€è®¢å•延时处ç†ã€‘未知的延迟类型: {}", delayType); } @@ -150,6 +157,14 @@ public class OrderDelayConsumer { } } + private void handleOrderPayTimeout(String orderId) { + if (StringUtils.isBlank(orderId)) { + log.warn("ã€è®¢å•支付超时处ç†ã€‘orderId 为空,跳过"); + return; + } + mallOrderService.autoCancelUnpaidOrder(orderId); + } + private void moveAssignedOrderBackToWaitCache(String workerId, MallDeliveryOrder delivery) { if (delivery == null || StringUtils.isBlank(delivery.getId())) { return; diff --git a/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/quartz/IeDailyQuotaResetTask.java b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/quartz/IeDailyQuotaResetTask.java new file mode 100644 index 00000000..3acd0f9a --- /dev/null +++ b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/quartz/IeDailyQuotaResetTask.java @@ -0,0 +1,40 @@ +package cc.hiver.mall.quartz; + +import cc.hiver.mall.ie.constant.IeConstants; +import cc.hiver.mall.ie.entity.IeUserProfile; +import cc.hiver.mall.ie.mapper.IeUserProfileMapper; +import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.scheduling.annotation.Scheduled; +import org.springframework.stereotype.Component; + +import java.util.Date; + +/** + * i/e æ¯æ—¥åŒ¹é…次数é‡ç½®ä»»åŠ¡ + */ +@Slf4j +@Component +public class IeDailyQuotaResetTask { + + @Autowired + private IeUserProfileMapper userProfileMapper; + + /** + * æ¯å¤©å‡Œæ™¨é‡ç½®å½“æ—¥åŒ¹é…æ¬¡æ•°ä¸Šé™ï¼Œé¿å…下å•奖励跨天累加。 + */ + @Scheduled(cron = "0 0 0 * * ?") + public void resetDailyQuota() { + try { + LambdaUpdateWrapper wrapper = new LambdaUpdateWrapper<>(); + wrapper.set(IeUserProfile::getDailyQuota, IeConstants.DEFAULT_DAILY_QUOTA) + .set(IeUserProfile::getUsedQuota, 0) + .set(IeUserProfile::getUpdateTime, new Date()); + int count = userProfileMapper.update(null, wrapper); + log.info("[i/eæ¯æ—¥åŒ¹é…次数é‡ç½®] 完æˆï¼Œå¤„ç† {} 个用户", count); + } catch (Exception e) { + log.error("[i/eæ¯æ—¥åŒ¹é…次数é‡ç½®] 任务异常: {}", e.getMessage(), e); + } + } +} diff --git a/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/service/mybatis/MallOrderService.java b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/service/mybatis/MallOrderService.java index adb8b431..0cd33d5a 100644 --- a/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/service/mybatis/MallOrderService.java +++ b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/service/mybatis/MallOrderService.java @@ -52,6 +52,11 @@ public interface MallOrderService extends IService { */ void cancelOrder(String orderId, String userId,Integer refundType, Integer refundTypeStatus, String reason, String pictures); + /** + * ç³»ç»Ÿè‡ªåŠ¨å–æ¶ˆè¶…时未支付订å•。 + */ + void autoCancelUnpaidOrder(String orderId); + /** * 申请退款 */ diff --git a/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/service/mybatis/MallUserCouponService.java b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/service/mybatis/MallUserCouponService.java index e74b06f7..073b2a08 100644 --- a/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/service/mybatis/MallUserCouponService.java +++ b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/service/mybatis/MallUserCouponService.java @@ -16,5 +16,6 @@ public interface MallUserCouponService extends IService { boolean useCoupon(String orderId); boolean refundCoupon(String orderId); IPage selectPageVO(MallCouponQuery q); + IPage selectUserCouponPage(String userId, String regionId, Integer pageNum, Integer pageSize); void send(String userPhones,Integer type,String couponId,Integer giveNum); } 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 8eb0c543..4faf35c2 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 @@ -722,7 +722,7 @@ public class MallDeliveryOrderServiceImpl extends ServiceImpl uw = new LambdaUpdateWrapper<>(); uw.eq(MallDeliveryOrder::getId, deliveryId) .set(MallDeliveryOrder::getWorkerId, newWorkerId) .set(MallDeliveryOrder::getWorkerName, newWorkerName) .set(MallDeliveryOrder::getWorkerPhone, newWorkerPhone); + if(bonus != null){ + uw.set(MallDeliveryOrder::getDeliveryFeeMarketplace, bonus); + } this.update(uw); + delivery.setWorkerId(newWorkerId); delivery.setWorkerName(newWorkerName); delivery.setWorkerPhone(newWorkerPhone); @@ -1220,6 +1232,7 @@ public class MallDeliveryOrderServiceImpl extends ServiceImpl ouw = new LambdaUpdateWrapper<>(); //代表该拼团å­è®¢å•订å•选择到店 if(targetStatus == 3){ - String latestSeq = merchantOrderSeqUtil.generateOrderSequence(order.getShopId(), 2); + String latestSeq = String.format("%s%s", + LocalDate.now().format(DateTimeFormatter.BASIC_ISO_DATE), + merchantOrderSeqUtil.generateOrderSequence(order.getShopId(), 2)); ouw.eq(MallOrder::getId, order.getId()) .eq(MallOrder::getStatus, ORDER_STATUS_WAIT_GROUP) .set(MallOrder::getStatus, targetStatus) diff --git a/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/serviceimpl/mybatis/MallOrderServiceImpl.java b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/serviceimpl/mybatis/MallOrderServiceImpl.java index ac387cf5..076ce5a9 100644 --- a/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/serviceimpl/mybatis/MallOrderServiceImpl.java +++ b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/serviceimpl/mybatis/MallOrderServiceImpl.java @@ -48,6 +48,7 @@ import java.time.LocalDate; import java.time.LocalDateTime; import java.time.LocalTime; import java.time.ZoneId; +import java.time.format.DateTimeFormatter; import java.util.*; import java.util.stream.Collectors; @@ -71,6 +72,9 @@ public class MallOrderServiceImpl extends ServiceImpl= group.getTargetMembers()) { throw new RuntimeException("拼团已满员"); }*/ - boolean isFace2Face = (group.getStatus() == GROUP_STATUS_FACE2FACE); + boolean isFace2Face = (group.getIsFace() == 1); // é¢å¯¹é¢å›¢ï¼šä¸å†é‡æ–°è®¡ç®—ï¼Œç›´æŽ¥ä½¿ç”¨æ ¹æ® targetMembers 凿‘Šçš„é‡‘é¢ BigDecimal deliveryFee = BigDecimal.ZERO; @@ -575,6 +591,8 @@ public class MallOrderServiceImpl extends ServiceImpl uw = new LambdaUpdateWrapper<>(); uw.eq(MallOrder::getId, orderId) .set(MallOrder::getStatus, STATUS_WAIT_PICKUP) @@ -670,6 +690,26 @@ public class MallOrderServiceImpl extends ServiceImpl gq = new LambdaQueryWrapper<>(); + gq.eq(MallOrderGroup::getHeadOrderId, orderId); + MallOrderGroup group = mallOrderGroupMapper.selectOne(gq);*/ + + LambdaQueryWrapper gq2 = new LambdaQueryWrapper<>(); + gq2.eq(MallOrderGroup::getShopId, order.getShopId()) + .like(MallOrderGroup::getGroupOrderIds, order.getId()) + .last("LIMIT 1"); + MallOrderGroup group = mallOrderGroupMapper.selectOne(gq2); + + if(group.getStatus() == 2){ + //æ‹¼å›¢å¤±è´¥ï¼Œç»™ç”¨æˆ·é€€æ¬¾ï¼ŒåŒæ—¶æ›´æ–°order + updateOrderStatus(orderId, 6, null); + wechatPayUtil.refund(order.getId(), toCent(order.getTotalAmount()), toCent(order.getTotalAmount())); + log.info("拼团失败,已自动å‘起退款, orderId={}", orderId); + return; + } + + // æ‹¼å›¢è®¢å•æ”¯ä»˜æˆåŠŸ -> 改为待æˆå›¢ updateOrderStatus(orderId, STATUS_WAIT_GROUP, payTime); @@ -677,17 +717,9 @@ public class MallOrderServiceImpl extends ServiceImpl gq = new LambdaQueryWrapper<>(); - gq.eq(MallOrderGroup::getHeadOrderId, orderId); - MallOrderGroup group = mallOrderGroupMapper.selectOne(gq); - if (group == null) { + + if (!group.getHeadOrderId().equals(orderId)) { // å¦‚æžœä¸æ˜¯å›¢é•¿ï¼ŒæŒ‰å‚团人查找 - LambdaQueryWrapper gq2 = new LambdaQueryWrapper<>(); - gq2.eq(MallOrderGroup::getShopId, order.getShopId()) - .like(MallOrderGroup::getGroupOrderIds, order.getId()) - .last("LIMIT 1"); - group = mallOrderGroupMapper.selectOne(gq2); //æ›´æ–°å‚团人数+1 int newMembers = group.getCurrentMembers() + 1; LambdaUpdateWrapper guw = new LambdaUpdateWrapper<>(); @@ -745,6 +777,14 @@ public class MallOrderServiceImpl extends ServiceImpl orderRevenueAndCount = this.baseMapper.selectOrderRevenueAndCount(shopId,startTime,endTime); + //统计è¥ä¸šé¢ã€è®¢å•é‡ã€å·²åŒæ„å”®åŽç¬”数和售åŽå•†å“é‡‘é¢ + List revenueOrders = this.baseMapper.selectOrderRevenueAndCount(shopId,startTime,endTime); + HashMap orderRevenueAndCount = buildOrderRevenueAndCount(shopId, revenueOrders); result.put("orderRevenueAndCount", orderRevenueAndCount); //待处ç†å·®è¯„è®¢å•æ•° Integer pendingBadReviewCount = this.baseMapper.selectPendingBadReviewCount(shopId); @@ -1289,6 +1362,75 @@ public class MallOrderServiceImpl extends ServiceImpl buildOrderRevenueAndCount(String shopId, List revenueOrders) { + HashMap orderRevenueAndCount = new HashMap<>(); + List orders = revenueOrders == null ? Collections.emptyList() : revenueOrders; + BigDecimal amount = orders.stream() + .map(order -> safeAmount(order.getGoodsAmount()).add(safeAmount(order.getPackageFee()))) + .reduce(BigDecimal.ZERO, BigDecimal::add); + Map orderMap = orders.stream() + .filter(order -> StringUtils.isNotBlank(order.getId())) + .collect(Collectors.toMap(MallOrder::getId, order -> order, (left, right) -> left)); + + orderRevenueAndCount.put("count", orders.size()); + orderRevenueAndCount.put("amount", amount); + orderRevenueAndCount.put("afterSaleCount", 0); + orderRevenueAndCount.put("afterSaleAmount", BigDecimal.ZERO); + + List orderIds = orders.stream() + .map(MallOrder::getId) + .filter(StringUtils::isNotBlank) + .distinct() + .collect(Collectors.toList()); + if (orderIds.isEmpty()) { + return orderRevenueAndCount; + } + + LambdaQueryWrapper refundWrapper = new LambdaQueryWrapper<>(); + refundWrapper.eq(MallRefundRecord::getLinkId, shopId) + .eq(MallRefundRecord::getStatus, REFUND_STATUS_AFTER_SALE_AGREED) + .in(MallRefundRecord::getOrderId, orderIds); + List refundRecords = mallRefundRecordMapper.selectList(refundWrapper); + if (refundRecords == null || refundRecords.isEmpty()) { + return orderRevenueAndCount; + } + + List refundOrderIds = refundRecords.stream() + .map(MallRefundRecord::getOrderId) + .filter(StringUtils::isNotBlank) + .distinct() + .collect(Collectors.toList()); + if (refundOrderIds.isEmpty()) { + orderRevenueAndCount.put("afterSaleCount", refundRecords.size()); + return orderRevenueAndCount; + } + + LambdaQueryWrapper goodsWrapper = new LambdaQueryWrapper<>(); + goodsWrapper.in(MallReturnOrderGoods::getOrderId, refundOrderIds); + List returnGoodsList = mallReturnOrderGoodsMapper.selectList(goodsWrapper); + BigDecimal afterSaleAmount = returnGoodsList == null ? BigDecimal.ZERO : returnGoodsList.stream() + .map(goods -> calculateReturnGoodsAmount(goods, orderMap.get(goods.getOrderId()))) + .reduce(BigDecimal.ZERO, BigDecimal::add); + + orderRevenueAndCount.put("afterSaleCount", refundRecords.size()); + orderRevenueAndCount.put("afterSaleAmount", afterSaleAmount); + return orderRevenueAndCount; + } + + private BigDecimal calculateReturnGoodsAmount(MallReturnOrderGoods goods, MallOrder order) { + BigDecimal quantity = goods.getQuantity() == null ? BigDecimal.ZERO : BigDecimal.valueOf(goods.getQuantity()); + BigDecimal unitAmount = safeAmount(goods.getPrice()); + if (shouldIncludePackageFee(order)) { + unitAmount = unitAmount.add(safeAmount(goods.getPackageFee())); + } + return unitAmount.multiply(quantity); + } + + private boolean shouldIncludePackageFee(MallOrder order) { + return order != null + && (Objects.equals(order.getDeliveryType(), DELIVERY_TYPE_EXPRESS) || Objects.equals(order.getIsPack(), 1)); + } + @Override public List getPeiSongOrders(String userId) { List orders = this.baseMapper.getPeiSongOrders(userId); @@ -1430,7 +1572,7 @@ public class MallOrderServiceImpl extends ServiceImpl rq = new LambdaQueryWrapper<>(); rq.eq(MallRefundRecord::getOrderId, orderId); List sallRefundRecord = mallRefundRecordMapper.selectList(rq); - if(sallRefundRecord != null){ + if(!sallRefundRecord.isEmpty()){ sallRefundRecord.forEach(item -> { if(item.getRefundType() == 1){ //å”®åŽå•†å“详情 @@ -1969,14 +2111,18 @@ public class MallOrderServiceImpl extends ServiceImpl 0){ + shopRefund = order.getGoodsAmount().add(order.getPackageFee()).subtract(order.getGoodsAmount().add(order.getPackageFee()).multiply(ratio)).setScale(2, RoundingMode.UP); + record.setRefundAmount(shopRefund); }else{ - record.setRefundAmount(order.getGoodsAmount().add(order.getPackageFee()).setScale(2, RoundingMode.HALF_UP)); + record.setRefundAmount(order.getGoodsAmount().add(order.getPackageFee())); } /*if(ratio != null){ @@ -1993,8 +2139,8 @@ public class MallOrderServiceImpl extends ServiceImpl 0){ + mallRefundRecord1.setRefundAmount(order.getTotalAmount().subtract(shopRefund)); }else{ mallRefundRecord1.setRefundAmount(order.getDeliveryFee()); } 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 a531c2e3..69d2b234 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 @@ -23,6 +23,7 @@ import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.redis.core.StringRedisTemplate; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -30,6 +31,7 @@ import java.math.BigDecimal; import java.math.RoundingMode; import java.util.Date; import java.util.List; +import java.util.concurrent.TimeUnit; import java.util.stream.Collectors; /** @@ -55,6 +57,7 @@ public class MallRefundRecordServiceImpl extends ServiceImpl 0){ mallRefundRecord.setRefundAmount(mallRefundRecord.getRefundAmount() - .subtract(mallRefundRecord.getRefundAmount().multiply(ratio)).setScale(2, RoundingMode.HALF_UP)); + .subtract(mallRefundRecord.getRefundAmount().multiply(ratio)).setScale(2, RoundingMode.UP)); + } + //订å•金é¢ä¼˜æƒ åŽ å˜æˆ0.01åŽé€€æ¬¾å˜æˆ0.01 + if(order.getTotalAmount().compareTo(new BigDecimal("0.01")) == 0){ + mallRefundRecord.setRefundAmount(BigDecimal.valueOf(0.01)); } mallRefundRecordMapper.insert(mallRefundRecord); //å”®åŽæ”¾åˆ°ç¼“å­˜ @@ -187,9 +197,13 @@ public class MallRefundRecordServiceImpl extends ServiceImpl 0){ mallRefundRecord.setRefundAmount(mallRefundRecord.getRefundAmount() - .subtract(mallRefundRecord.getRefundAmount().multiply(ratio)).setScale(2, RoundingMode.HALF_UP)); + .subtract(mallRefundRecord.getRefundAmount().multiply(ratio)).setScale(2, RoundingMode.UP)); + } + //订å•金é¢ä¼˜æƒ åŽ å˜æˆ0.01åŽé€€æ¬¾å˜æˆ0.01 + if(order.getTotalAmount().compareTo(new BigDecimal("0.01")) == 0){ + mallRefundRecord.setRefundAmount(BigDecimal.valueOf(0.01)); } mallRefundRecordMapper.insert(mallRefundRecord); //å”®åŽæ”¾åˆ°ç¼“å­˜ @@ -221,9 +235,11 @@ public class MallRefundRecordServiceImpl extends ServiceImpl 0){ + shopRefund = mallRefundRecord.getRefundAmount() + .subtract(mallRefundRecord.getRefundAmount().multiply(ratio)).setScale(2, RoundingMode.UP); + mallRefundRecord.setRefundAmount(shopRefund); } mallRefundRecordMapper.insert(mallRefundRecord); //å”®åŽæ”¾åˆ°ç¼“å­˜ @@ -235,9 +251,8 @@ public class MallRefundRecordServiceImpl extends ServiceImpl 0){ + mallRefundRecord1.setRefundAmount(order.getTotalAmount().subtract(shopRefund)); } mallRefundRecordMapper.insert(mallRefundRecord1); //å”®åŽæ”¾åˆ°ç¼“å­˜ @@ -276,6 +291,7 @@ public class MallRefundRecordServiceImpl extends ServiceImpl uw = new LambdaUpdateWrapper<>(); uw.eq(MallRefundRecord::getId, mallRefundRecord.getId()) .set(MallRefundRecord::getSuccessTime, new Date()) @@ -333,10 +349,10 @@ public class MallRefundRecordServiceImpl extends ServiceImpl item.getRefundAmount()) // æå– BigDecimal é‡‘é¢ - .reduce(BigDecimal.ZERO, BigDecimal::add); - mallOrderDeliveryFeeRefundHelper.refundOrderWithAddedDeliveryFee(order, totalRefund); + .reduce(BigDecimal.ZERO, BigDecimal::add);*/ + mallOrderDeliveryFeeRefundHelper.refundOrderWithAddedDeliveryFee(order, order.getTotalAmount()); if(mallRefundRecord.getLinkId().toUpperCase().startsWith("W")){ //é…é€å‘˜åŒæ„é€€æ¬¾ã€‚æ‰£æŽ‰ä½™é¢ Worker worker = workerServiceImpl.findByWorkerId(mallRefundRecord.getLinkId()); @@ -454,7 +470,7 @@ public class MallRefundRecordServiceImpl extends ServiceImpl 3 ? 3 : 0; + if (dbRecord.getStatus() == null || dbRecord.getStatus() != waitStatus) { + throw new RuntimeException("该退款/å”®åŽç”³è¯·å·²å¤„ç†ï¼Œè¯·åˆ·æ–°é¡µé¢"); + } + } + private boolean shouldRefundAddedDeliveryFee(MallRefundRecord mallRefundRecord) { if (mallRefundRecord == null) { return false; diff --git a/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/serviceimpl/mybatis/MallUserCouponServiceImpl.java b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/serviceimpl/mybatis/MallUserCouponServiceImpl.java index d7c52185..3880de31 100644 --- a/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/serviceimpl/mybatis/MallUserCouponServiceImpl.java +++ b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/serviceimpl/mybatis/MallUserCouponServiceImpl.java @@ -137,6 +137,24 @@ public class MallUserCouponServiceImpl extends ServiceImpl selectUserCouponPage(String userId, String regionId, Integer pageNum, Integer pageSize) { + if (StringUtils.isEmpty(userId) || StringUtils.isEmpty(regionId)) { + throw new HiverException("用户或校区ä¸èƒ½ä¸ºç©º"); + } + int current = pageNum == null || pageNum < 1 ? 1 : pageNum; + int size = pageSize == null || pageSize < 1 ? 10 : pageSize; + QueryWrapper qw = new QueryWrapper<>(); + qw.eq("user_id", userId) + .eq("region_id", regionId) + .eq("status", 0) + .le("valid_start_time", new Date()) + .ge("valid_end_time", new Date()) + .orderByAsc("valid_end_time") + .orderByDesc("receive_time"); + return this.page(new Page<>(current, size), qw); + } + @Override public void send(String userPhones, Integer type,String couponId,Integer giveNum) { //ç²¾å‡†å‘æ”¾ diff --git a/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/utils/UpdateUtils.java b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/utils/UpdateUtils.java new file mode 100644 index 00000000..68983434 --- /dev/null +++ b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/utils/UpdateUtils.java @@ -0,0 +1,28 @@ +package cc.hiver.mall.utils; + +import org.springframework.beans.BeanUtils; +import org.springframework.beans.BeanWrapper; +import org.springframework.beans.BeanWrapperImpl; + +import java.util.HashSet; +import java.util.Set; + +public class UpdateUtils { + public static void copyNonNullProperties(Object source, Object target) { + BeanUtils.copyProperties(source, target, getNullPropertyNames(source)); + } + + private static String[] getNullPropertyNames(Object source) { + final BeanWrapper src = new BeanWrapperImpl(source); + java.beans.PropertyDescriptor[] pds = src.getPropertyDescriptors(); + Set emptyNames = new HashSet<>(); + for (java.beans.PropertyDescriptor pd : pds) { + Object srcValue = src.getPropertyValue(pd.getName()); + if (srcValue == null) { + emptyNames.add(pd.getName()); + } + } + String[] result = new String[emptyNames.size()]; + return emptyNames.toArray(result); + } +} diff --git a/hiver-modules/hiver-mall/src/main/resources/mapper/MallOrderMapper.xml b/hiver-modules/hiver-mall/src/main/resources/mapper/MallOrderMapper.xml index b434dfd5..5deafabf 100644 --- a/hiver-modules/hiver-mall/src/main/resources/mapper/MallOrderMapper.xml +++ b/hiver-modules/hiver-mall/src/main/resources/mapper/MallOrderMapper.xml @@ -69,19 +69,22 @@ FROM mall_order m1 JOIN mall_order_group g ON FIND_IN_SET(m1.id, g.group_order_ids) > 0 JOIN mall_order m2 ON FIND_IN_SET(m2.id, g.group_order_ids) > 0 - WHERE m2.status != 6 and m1.id = #{orderId} + WHERE m2.status != 6 and m2.status != 0 and m1.id = #{orderId} - - SELECT - COUNT(*) as count, - SUM(goods_amount + package_fee) as amount + id, + goods_amount AS goodsAmount, + package_fee AS packageFee, + delivery_type AS deliveryType, + is_pack AS isPack FROM mall_order - AND `status` IN (5, 12) + AND `status` IN (5, 11, 12) - AND create_time BETWEEN #{startTime} AND #{endTime} + AND pay_time BETWEEN #{startTime} AND #{endTime}