diff --git a/cash-common/cash-common-service/src/main/java/com/czg/account/service/AShopUserService.java b/cash-common/cash-common-service/src/main/java/com/czg/account/service/AShopUserService.java index 88733e08..583d2b07 100644 --- a/cash-common/cash-common-service/src/main/java/com/czg/account/service/AShopUserService.java +++ b/cash-common/cash-common-service/src/main/java/com/czg/account/service/AShopUserService.java @@ -3,11 +3,10 @@ package com.czg.account.service; import com.czg.account.dto.shopuser.*; import com.czg.account.entity.ShopUser; import com.czg.market.entity.SmsPushEventUser; -import com.czg.resp.CzgResult; import com.mybatisflex.core.paginate.Page; -import com.mybatisflex.core.service.IService; import java.math.BigDecimal; +import java.util.List; /** * 商户储值会员 服务层。 @@ -22,6 +21,8 @@ public interface AShopUserService { Page getPage(String key, Integer isVip, BigDecimal amount); Page getPushEventUser(SmsPushEventUser smsPushEventUser); + List getPushEventUserList(SmsPushEventUser smsPushEventUser); + Boolean add(Long shopId, ShopUserAddDTO shopUserAddDTO); Boolean updateInfo(Long shopId, ShopUserEditDTO shopUserEditDTO); diff --git a/cash-common/cash-common-service/src/main/java/com/czg/market/service/MkShopCouponRecordService.java b/cash-common/cash-common-service/src/main/java/com/czg/market/service/MkShopCouponRecordService.java index 6ccddda4..cbc071fe 100644 --- a/cash-common/cash-common-service/src/main/java/com/czg/market/service/MkShopCouponRecordService.java +++ b/cash-common/cash-common-service/src/main/java/com/czg/market/service/MkShopCouponRecordService.java @@ -1,6 +1,7 @@ package com.czg.market.service; import com.czg.account.dto.QueryReceiveDto; +import com.czg.account.entity.ShopUser; import com.czg.account.vo.CouponReceiveVo; import com.czg.account.vo.UserCouponVo; import com.czg.market.dto.MkRewardCouponDTO; @@ -47,6 +48,13 @@ public interface MkShopCouponRecordService extends IService */ void receiveCoupon(MkShopCouponGiftDTO giftDTO, Integer number, boolean isLimit); + /** + * 发放券 批量发放 不计限领 + * 检查优惠券状态 检查店铺ID是否存在且与发放店铺一致 检查优惠券是否失效 + * @param giftDTO 除 sourceFlowId shopUserId外 全必填 如果有 也填 + * @param number 发放数量 + */ + void batchReceiveCoupon(MkShopCouponGiftDTO giftDTO, Integer number, List userList); /** * 用户优惠券 失效/删除 diff --git a/cash-service/account-service/src/main/java/com/czg/service/account/service/impl/AShopUserServiceImpl.java b/cash-service/account-service/src/main/java/com/czg/service/account/service/impl/AShopUserServiceImpl.java index 392b4785..c43db703 100644 --- a/cash-service/account-service/src/main/java/com/czg/service/account/service/impl/AShopUserServiceImpl.java +++ b/cash-service/account-service/src/main/java/com/czg/service/account/service/impl/AShopUserServiceImpl.java @@ -35,6 +35,7 @@ import org.apache.dubbo.config.annotation.DubboService; import org.springframework.transaction.annotation.Transactional; import java.math.BigDecimal; +import java.util.ArrayList; import java.util.List; @@ -102,12 +103,23 @@ public class AShopUserServiceImpl implements AShopUserService { List shopUsers = shopUserMapper.selectPushEventUser(mainShopId, smsPushEventUser.getShopId(), smsPushEventUser); return PageUtil.convert(new PageInfo<>(shopUsers)); - }catch (Exception e){ + } catch (Exception e) { log.info("获取营销推送任务用户列表失败{},{}", smsPushEventUser, e.getMessage()); return PageUtil.convert(new PageInfo<>()); } } + @Override + public List getPushEventUserList(SmsPushEventUser smsPushEventUser) { + List shopUserIds = new ArrayList<>(); + Long mainShopId = shopInfoService.getMainIdByShopId(smsPushEventUser.getShopId()); + smsPushEventUser.checkIsAll(); + // 调用Mapper层查询 + List shopUsers = shopUserMapper.selectPushEventUser(mainShopId, + smsPushEventUser.getShopId(), smsPushEventUser); + return shopUsers; + } + @Override public Boolean updateInfo(Long shopId, ShopUserEditDTO shopUserEditDTO) { if (StrUtil.isNotBlank(shopUserEditDTO.getPhone())) { diff --git a/cash-service/market-service/src/main/java/com/czg/service/market/service/impl/MkShopCouponRecordServiceImpl.java b/cash-service/market-service/src/main/java/com/czg/service/market/service/impl/MkShopCouponRecordServiceImpl.java index fc4161bf..23e44ce4 100644 --- a/cash-service/market-service/src/main/java/com/czg/service/market/service/impl/MkShopCouponRecordServiceImpl.java +++ b/cash-service/market-service/src/main/java/com/czg/service/market/service/impl/MkShopCouponRecordServiceImpl.java @@ -1,11 +1,9 @@ package com.czg.service.market.service.impl; -import cn.hutool.core.collection.CollUtil; import cn.hutool.core.date.LocalDateTimeUtil; import cn.hutool.core.util.StrUtil; import com.alibaba.fastjson2.JSONObject; import com.czg.account.dto.QueryReceiveDto; -import com.czg.account.entity.PictureGallery; import com.czg.account.entity.ShopInfo; import com.czg.account.entity.ShopUser; import com.czg.account.entity.UserInfo; @@ -21,7 +19,6 @@ import com.czg.market.dto.MkShopCouponRecordDTO; import com.czg.market.entity.MkShopCouponRecord; import com.czg.market.entity.ShopCoupon; import com.czg.market.service.MkShopCouponRecordService; -import com.czg.market.service.ShopCouponService; import com.czg.market.vo.UserCouponVO; import com.czg.service.market.mapper.MkShopCouponRecordMapper; import com.czg.service.market.mapper.ShopCouponMapper; @@ -30,7 +27,6 @@ import com.czg.utils.CzgStrUtils; import com.czg.utils.PageUtil; import com.mybatisflex.core.paginate.Page; import com.mybatisflex.core.query.QueryWrapper; -import com.mybatisflex.core.update.UpdateWrapper; import com.mybatisflex.spring.service.impl.ServiceImpl; import jakarta.annotation.Resource; import org.apache.dubbo.config.annotation.DubboReference; @@ -39,10 +35,8 @@ import org.apache.dubbo.config.annotation.DubboService; import java.time.LocalDateTime; import java.time.LocalTime; import java.time.temporal.ChronoUnit; -import java.util.HashMap; +import java.util.ArrayList; import java.util.List; -import java.util.Map; -import java.util.stream.Collectors; /** * 优惠券发放记录表 服务层实现。 @@ -126,6 +120,7 @@ public class MkShopCouponRecordServiceImpl extends ServiceImpl getConsumerRecord(MkShopCouponRecordDTO mkShopCouponRecordDTO, String startTime, String endTime) { QueryWrapper recordQueryWrapper = new QueryWrapper(); @@ -276,6 +271,93 @@ public class MkShopCouponRecordServiceImpl extends ServiceImpl userList) { + if (number == null || number <= 0) { + throw new CzgException("发放数量不能小于0"); + } + AssertUtil.isNull(giftDTO.getShopId(), "店铺id不能为空"); + AssertUtil.isNull(giftDTO.getCouponId(), "优惠券id不能为空"); + AssertUtil.isNull(giftDTO.getSourceId(), "来源活动id不能为空"); + AssertUtil.isBlank(giftDTO.getSource(), "来源描述不能为空"); + ShopInfo shopInfo = shopInfoService.getById(giftDTO.getShopId()); + AssertUtil.isNull(shopInfo, "店铺不存在"); + ShopCoupon coupon = couponService.selectOneById(giftDTO.getCouponId()); + AssertUtil.isNull(coupon, "优惠券不存在"); + // 检查优惠券状态 + if (coupon.getIsDel() != 0) { + // 状态异常,直接返回 + return; + } + // 检查店铺ID是否存在且与发放店铺一致 + if (coupon.getShopId() == null || !coupon.getShopId().equals(giftDTO.getShopId())) { + return; + } + // 检查优惠券是否失效 + if (coupon.getStatus() != 1) { + return; + } + + coupon.setGiftNum(coupon.getGiftNum() + userList.size() * number); + String couponJson = JSONObject.toJSONString(coupon); + LocalDateTime start = LocalDateTime.now().with(LocalTime.MIN); + LocalDateTime end = null; + if ("fixed".equals(coupon.getValidType())) { + //固定时间 + if (coupon.getDaysToTakeEffect() != null && coupon.getDaysToTakeEffect() > 0) { + start = LocalDateTimeUtil.offset(start, coupon.getDaysToTakeEffect(), ChronoUnit.DAYS).with(LocalTime.MIN); + } + end = LocalDateTimeUtil.offset(start, coupon.getValidDays(), ChronoUnit.DAYS).with(LocalTime.MAX).truncatedTo(ChronoUnit.SECONDS); + } else if ("custom".equals(coupon.getValidType())) { + //自定义时间 + start = coupon.getValidStartTime(); + end = coupon.getValidEndTime(); + } + List recordList = new ArrayList<>(); + for (int i = 0; i < number; i++) { + for (ShopUser shopUser : userList) { + MkShopCouponRecord record = new MkShopCouponRecord(); + record.setShopId(giftDTO.getShopId()); + record.setShopUserId(shopUser.getId()); + record.setUserId(shopUser.getUserId()); + record.setCouponId(giftDTO.getCouponId()); + record.setCouponSyncId(coupon.getSyncId()); + record.setSourceId(giftDTO.getSourceId()); + record.setSourceFlowId(giftDTO.getSourceFlowId()); + record.setSource(giftDTO.getSource()); + record.setStatus(0); + record.setType(coupon.getCouponType()); + record.setFullAmount(coupon.getFullAmount()); + record.setDiscountAmount(coupon.getDiscountAmount()); + record.setDiscountRate(coupon.getDiscountRate()); + record.setMaxDiscountAmount(coupon.getMaxDiscountAmount()); + record.setCreateTime(LocalDateTime.now()); + record.setIsDel(0); + record.setCouponJson(couponJson); + record.setName(coupon.getTitle()); + + record.setUseStartTime(start); + record.setUseEndTime(end); + recordList.add(record); + } + } + saveBatch(recordList); + QueryWrapper queryWrapper = new QueryWrapper(); + ShopCoupon newCoupon = new ShopCoupon(); + newCoupon.setGiftNum(coupon.getGiftNum()); + if (coupon.getSyncId() != null) { + queryWrapper.and(q -> { + q.eq(ShopCoupon::getId, coupon.getSyncId()).or(q1 -> { + q1.eq(ShopCoupon::getSyncId, coupon.getSyncId()); + }); + }); + couponService.updateByQuery(newCoupon, queryWrapper); + } else { + queryWrapper.eq(ShopCoupon::getId, coupon.getId()); + couponService.update(coupon, true); + } + } + @Override public void deleteRecord(Long id) { // updateById(new MkShopCouponRecord().setId(id).setIsDel(1), true); diff --git a/cash-service/market-service/src/main/java/com/czg/service/market/service/impl/SmsPushEventServiceImpl.java b/cash-service/market-service/src/main/java/com/czg/service/market/service/impl/SmsPushEventServiceImpl.java index e1bfe2ca..d677b690 100644 --- a/cash-service/market-service/src/main/java/com/czg/service/market/service/impl/SmsPushEventServiceImpl.java +++ b/cash-service/market-service/src/main/java/com/czg/service/market/service/impl/SmsPushEventServiceImpl.java @@ -1,11 +1,19 @@ package com.czg.service.market.service.impl; import cn.hutool.core.bean.BeanUtil; +import cn.hutool.core.util.StrUtil; +import com.alibaba.fastjson2.JSON; +import com.alibaba.fastjson2.JSONArray; +import com.alibaba.fastjson2.JSONObject; +import com.czg.account.entity.ShopUser; +import com.czg.account.service.AShopUserService; import com.czg.config.RabbitPublisher; import com.czg.exception.CzgException; +import com.czg.market.dto.MkShopCouponGiftDTO; import com.czg.market.dto.SmsPushEventDTO; import com.czg.market.entity.SmsPushEvent; import com.czg.market.entity.SmsPushEventUser; +import com.czg.market.service.MkShopCouponRecordService; import com.czg.market.service.SmsPushEventService; import com.czg.service.market.mapper.SmsPushEventMapper; import com.czg.service.market.mapper.SmsPushEventUserMapper; @@ -14,10 +22,14 @@ import com.mybatisflex.core.paginate.Page; import com.mybatisflex.core.query.QueryWrapper; import com.mybatisflex.spring.service.impl.ServiceImpl; import jakarta.annotation.Resource; +import lombok.extern.slf4j.Slf4j; +import org.apache.dubbo.config.annotation.DubboReference; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import java.time.LocalDateTime; +import java.util.List; +import java.util.concurrent.CompletableFuture; /** * 营销推送发送记录 服务层实现。 @@ -25,12 +37,17 @@ import java.time.LocalDateTime; * @author ww * @since 2025-10-14 */ +@Slf4j @Service public class SmsPushEventServiceImpl extends ServiceImpl implements SmsPushEventService { @Resource private SmsPushEventUserMapper eventUserMapper; @Resource + private MkShopCouponRecordService couponRecordService; + @DubboReference + private AShopUserService shopUserService; + @Resource private RabbitPublisher rabbitPublisher; @Override @@ -79,6 +96,39 @@ public class SmsPushEventServiceImpl extends ServiceImpl { + try { + grantCoupon(param); + } catch (Exception e) { + log.error("异步发放优惠券失败", e); + } + }); + } + + // 发放优惠券 + private void grantCoupon(SmsPushEventDTO param) { + if (StrUtil.isBlank(param.getCoupon())) { + return; + } + List userList = shopUserService.getPushEventUserList(param.getSmsPushEventUser()); + // 2. 将JSON字符串解析为JSONArray + JSONArray couponArray = JSON.parseArray(param.getCoupon()); + + // 3. 遍历JSONArray,逐个获取JSONObject的字段值 + for (int i = 0; i < couponArray.size(); i++) { + // 获取单个优惠券的JSONObject对象 + JSONObject couponObj = couponArray.getJSONObject(i); + // 通过键名获取对应值(需注意字段类型,按需转换) + Long id = couponObj.getLong("id"); + Integer num = couponObj.getInteger("num"); + MkShopCouponGiftDTO giftDTO = new MkShopCouponGiftDTO(); + giftDTO.setShopId(param.getShopId()); + giftDTO.setSourceId(param.getId()); + giftDTO.setCouponId(id); + giftDTO.setSource("营销短信发放"); + couponRecordService.batchReceiveCoupon(giftDTO, num, userList); + } } /** diff --git a/cash-service/market-service/src/main/java/com/czg/service/market/service/impl/SmsShopTemplateServiceImpl.java b/cash-service/market-service/src/main/java/com/czg/service/market/service/impl/SmsShopTemplateServiceImpl.java index 4cdde77a..30733f58 100644 --- a/cash-service/market-service/src/main/java/com/czg/service/market/service/impl/SmsShopTemplateServiceImpl.java +++ b/cash-service/market-service/src/main/java/com/czg/service/market/service/impl/SmsShopTemplateServiceImpl.java @@ -82,13 +82,10 @@ public class SmsShopTemplateServiceImpl extends ServiceImpl