diff --git a/fightwine-admin/src/main/java/com/yzt/admin/controller/StoreCombinationController.java b/fightwine-admin/src/main/java/com/yzt/admin/controller/StoreCombinationController.java index ce8b56a..c5fb26d 100644 --- a/fightwine-admin/src/main/java/com/yzt/admin/controller/StoreCombinationController.java +++ b/fightwine-admin/src/main/java/com/yzt/admin/controller/StoreCombinationController.java @@ -1,6 +1,7 @@ package com.yzt.admin.controller; import com.yzt.common.page.CommonPage; +import com.yzt.common.request.AdminGenerateQueueCodeRequest; import com.yzt.common.request.PageParamRequest; import com.yzt.common.request.StoreCombinationRequest; import com.yzt.common.request.StoreCombinationSearchRequest; @@ -166,7 +167,14 @@ public class StoreCombinationController { storePinkService.adminCancelQueueAndRecalculate(pinkId); return CommonResult.success(); } + + /** + * 后台管理员新增排队码 + */ + @ApiOperation(value = "后台管理员新增排队码") + @RequestMapping(value = "/admin/generate/queue", method = RequestMethod.POST) + public CommonResult adminGenerateQueueCodes(@RequestBody @Validated AdminGenerateQueueCodeRequest request) { + storePinkService.adminGenerateQueueCodes(request.getUid(), request.getProductId(), request.getCount(), request.getRemark()); + return CommonResult.success("排队码生成成功"); + } } - - - diff --git a/fightwine-admin/src/main/java/com/yzt/admin/model/ScheduleJob.java b/fightwine-admin/src/main/java/com/yzt/admin/model/ScheduleJob.java index a350ab0..f725d41 100644 --- a/fightwine-admin/src/main/java/com/yzt/admin/model/ScheduleJob.java +++ b/fightwine-admin/src/main/java/com/yzt/admin/model/ScheduleJob.java @@ -21,7 +21,7 @@ import java.util.Date; @Data @EqualsAndHashCode(callSuper = false) @Accessors(chain = true) -@TableName("fw_schedule_job") +@TableName("zp_schedule_job") @ApiModel(value="ScheduleJob对象", description="定时任务") public class ScheduleJob implements Serializable { diff --git a/fightwine-admin/src/main/java/com/yzt/admin/model/ScheduleJobLog.java b/fightwine-admin/src/main/java/com/yzt/admin/model/ScheduleJobLog.java index 2bd0a71..58cc3d5 100644 --- a/fightwine-admin/src/main/java/com/yzt/admin/model/ScheduleJobLog.java +++ b/fightwine-admin/src/main/java/com/yzt/admin/model/ScheduleJobLog.java @@ -21,7 +21,7 @@ import java.util.Date; @Data @EqualsAndHashCode(callSuper = false) @Accessors(chain = true) -@TableName("fw_schedule_job_log") +@TableName("zp_schedule_job_log") @ApiModel(value="ScheduleJobLog对象", description="定时任务日志") public class ScheduleJobLog implements Serializable { diff --git a/fightwine-common/src/main/java/com/yzt/common/model/combination/StorePink.java b/fightwine-common/src/main/java/com/yzt/common/model/combination/StorePink.java index 633a9ec..ce84576 100644 --- a/fightwine-common/src/main/java/com/yzt/common/model/combination/StorePink.java +++ b/fightwine-common/src/main/java/com/yzt/common/model/combination/StorePink.java @@ -68,10 +68,10 @@ public class StorePink implements Serializable { @ApiModelProperty(value = "是否发送模板消息0未发送1已发送") private Boolean isTpl; - @ApiModelProperty(value = "是否退款 0未退款 1已退款") + @ApiModelProperty(value = "是否失效 0未失效 1已失效") private Boolean isRefund; - @ApiModelProperty(value = "状态1进行中2已完成3未完成") + @ApiModelProperty(value = "状态1排队中2已达成待领取3已领取") private Integer status; @ApiModelProperty(value = "用户昵称") @@ -95,4 +95,10 @@ public class StorePink implements Serializable { @ApiModelProperty(value = "排队码编号(年月日时分秒+六位随机数)") private String queueCode; + @ApiModelProperty(value = "操作的管理员ID") + private Integer adminId; + + @ApiModelProperty(value = "备注") + private String remark; + } diff --git a/fightwine-common/src/main/java/com/yzt/common/request/AdminGenerateQueueCodeRequest.java b/fightwine-common/src/main/java/com/yzt/common/request/AdminGenerateQueueCodeRequest.java new file mode 100644 index 0000000..7ecf0f6 --- /dev/null +++ b/fightwine-common/src/main/java/com/yzt/common/request/AdminGenerateQueueCodeRequest.java @@ -0,0 +1,32 @@ +package com.yzt.common.request; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import javax.validation.constraints.Min; +import javax.validation.constraints.NotNull; + +/** + * 后台管理员新增排队码请求参数 + */ +@Data +@ApiModel(value = "AdminGenerateQueueCodeRequest", description = "后台管理员新增排队码请求参数") +public class AdminGenerateQueueCodeRequest { + + @ApiModelProperty(value = "用户uid", required = true) + @NotNull(message = "用户uid不能为空") + private Integer uid; + + @ApiModelProperty(value = "商品product_id", required = true) + @NotNull(message = "商品product_id不能为空") + private Integer productId; + + @ApiModelProperty(value = "生成码数量", required = true) + @NotNull(message = "生成码数量不能为空") + @Min(value = 1, message = "生成码数量至少为1") + private Integer count; + + @ApiModelProperty(value = "备注") + private String remark; +} diff --git a/fightwine-common/src/main/java/com/yzt/common/request/ClaimProductRequest.java b/fightwine-common/src/main/java/com/yzt/common/request/ClaimProductRequest.java new file mode 100644 index 0000000..cf55e08 --- /dev/null +++ b/fightwine-common/src/main/java/com/yzt/common/request/ClaimProductRequest.java @@ -0,0 +1,23 @@ +package com.yzt.common.request; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import javax.validation.constraints.NotNull; + +/** + * 领取商品请求对象 + */ +@Data +@ApiModel("领取商品请求") +public class ClaimProductRequest { + + @ApiModelProperty(value = "拼团ID(zp_store_pink表的主键id)", required = true) + @NotNull(message = "拼团ID不能为空") + private Integer pinkId; + + @ApiModelProperty(value = "收货地址ID(zp_user_address表的主键id)", required = true) + @NotNull(message = "收货地址ID不能为空") + private Integer addressId; +} diff --git a/fightwine-common/src/main/java/com/yzt/common/request/PinkQueryRequest.java b/fightwine-common/src/main/java/com/yzt/common/request/PinkQueryRequest.java index 72a006e..1c93481 100644 --- a/fightwine-common/src/main/java/com/yzt/common/request/PinkQueryRequest.java +++ b/fightwine-common/src/main/java/com/yzt/common/request/PinkQueryRequest.java @@ -19,6 +19,6 @@ public class PinkQueryRequest { @NotNull(message = "用户ID不能为空") private Integer uid; - @ApiModelProperty(value = "队列类型: 1-会员队列, 2-会馆队列") + @ApiModelProperty(value = "队列类型: 1-黔行, 2-茅香") private Integer queueType; } diff --git a/fightwine-front/src/main/java/com/yzt/front/controller/CombinationController.java b/fightwine-front/src/main/java/com/yzt/front/controller/CombinationController.java index ab4c422..acc477a 100644 --- a/fightwine-front/src/main/java/com/yzt/front/controller/CombinationController.java +++ b/fightwine-front/src/main/java/com/yzt/front/controller/CombinationController.java @@ -2,12 +2,17 @@ package com.yzt.front.controller; import com.github.pagehelper.PageInfo; import com.yzt.common.model.combination.StoreCombination; +import com.yzt.common.model.combination.StorePink; +import com.yzt.common.model.product.StoreProduct; import com.yzt.common.page.CommonPage; +import com.yzt.common.request.ClaimProductRequest; import com.yzt.common.request.PageParamRequest; import com.yzt.common.request.StorePinkRequest; import com.yzt.common.response.*; import com.yzt.common.result.CommonResult; import com.yzt.service.service.StoreCombinationService; +import com.yzt.service.service.StorePinkService; +import com.yzt.service.service.StoreProductService; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import lombok.extern.slf4j.Slf4j; @@ -28,6 +33,12 @@ public class CombinationController { @Autowired private StoreCombinationService storeCombinationService; + @Autowired + private StorePinkService storePinkService; + + @Autowired + private StoreProductService storeProductService; + /** * 拼团首页 */ @@ -99,4 +110,45 @@ public class CombinationController { } } + /** + * 领取商品(拼团达成后免费送一份商品) + */ + @ApiOperation(value = "领取商品") + @RequestMapping(value = "/claim", method = RequestMethod.POST) + public CommonResult claimProduct(@RequestBody @Validated ClaimProductRequest request) { + try { + String orderNo = storePinkService.claimProduct(request.getPinkId(), request.getAddressId()); + return CommonResult.success(orderNo).setMessage("领取成功"); + } catch (Exception e) { + log.error("领取商品失败: {}", e.getMessage(), e); + return CommonResult.failed(e.getMessage()); + } + } + + /** + * 根据拼团ID查询商品详情 + */ + @ApiOperation(value = "根据拼团ID查询商品详情") + @RequestMapping(value = "/product/{pinkId}", method = RequestMethod.GET) + public CommonResult getProductByPinkId(@PathVariable(value = "pinkId") Integer pinkId) { + try { + // 根据拼团ID查询拼团信息 + StorePink storePink = storePinkService.getById(pinkId); + if (storePink == null) { + return CommonResult.failed("拼团信息不存在"); + } + + // 根据商品ID查询商品基本信息 + StoreProduct storeProduct = storeProductService.getById(storePink.getPid()); + if (storeProduct == null) { + return CommonResult.failed("商品信息不存在"); + } + + return CommonResult.success(storeProduct); + } catch (Exception e) { + log.error("根据拼团ID查询商品详情失败: {}", e.getMessage(), e); + return CommonResult.failed(e.getMessage()); + } + } + } diff --git a/fightwine-front/src/main/java/com/yzt/front/controller/StoreOrderController.java b/fightwine-front/src/main/java/com/yzt/front/controller/StoreOrderController.java index 7bc6d9c..69650ac 100644 --- a/fightwine-front/src/main/java/com/yzt/front/controller/StoreOrderController.java +++ b/fightwine-front/src/main/java/com/yzt/front/controller/StoreOrderController.java @@ -82,19 +82,22 @@ public class StoreOrderController { /** * 订单列表 * @param type 类型 + * @param payType 支付方式 * @param pageRequest 分页 * @return 订单列表 */ @ApiOperation(value = "订单列表") @RequestMapping(value = "/list", method = RequestMethod.GET) @ApiImplicitParams ({ - @ApiImplicitParam(name = "type", value = "评价等级|0=未支付,1=待发货,2=待收货,3=待评价,4=已完成,-3=售后/退款,-4=已取消", required = false) + @ApiImplicitParam(name = "type", value = "评价等级|0=未支付,1=待发货,2=待收货,3=待评价,4=已完成,-3=售后/退款,-4=已取消", required = false), + @ApiImplicitParam(name = "payType", value = "支付方式,free表示免费订单", required = false) }) public CommonResult> orderList( @RequestParam(name = "keywords", required = false) String keywords, @RequestParam(name = "type", required = false) Integer type, + @RequestParam(name = "payType", required = false) String payType, @ModelAttribute PageParamRequest pageRequest) { - return CommonResult.success(CommonPage.restPage(orderService.list(keywords, type, pageRequest))); + return CommonResult.success(CommonPage.restPage(orderService.list(keywords, type, payType, pageRequest))); } /** diff --git a/fightwine-service/src/main/java/com/yzt/service/service/OrderService.java b/fightwine-service/src/main/java/com/yzt/service/service/OrderService.java index b4f70e0..bc7d64e 100644 --- a/fightwine-service/src/main/java/com/yzt/service/service/OrderService.java +++ b/fightwine-service/src/main/java/com/yzt/service/service/OrderService.java @@ -16,10 +16,11 @@ public interface OrderService { /** * 订单列表 * @param type 类型 + * @param payType 支付方式 * @param pageRequest 分页 * @return 订单集合 */ - PageInfo list(String keywords,Integer type, PageParamRequest pageRequest); + PageInfo list(String keywords,Integer type, String payType, PageParamRequest pageRequest); /** * 订单详情 diff --git a/fightwine-service/src/main/java/com/yzt/service/service/StoreOrderService.java b/fightwine-service/src/main/java/com/yzt/service/service/StoreOrderService.java index 1bc820f..a0e0858 100644 --- a/fightwine-service/src/main/java/com/yzt/service/service/StoreOrderService.java +++ b/fightwine-service/src/main/java/com/yzt/service/service/StoreOrderService.java @@ -53,7 +53,7 @@ public interface StoreOrderService extends IService { * @return 订单结果列表 */ List getUserOrderList(Integer uid, Integer status, PageParamRequest pageParamRequest); - PageInfo getUserOrderList_2_3(String keywords, Integer uid, Integer status, PageParamRequest pageParamRequest); + PageInfo getUserOrderList_2_3(String keywords, Integer uid, Integer status, String payType, PageParamRequest pageParamRequest); /** * 创建订单 * @param storeOrder 订单参数 diff --git a/fightwine-service/src/main/java/com/yzt/service/service/StorePinkService.java b/fightwine-service/src/main/java/com/yzt/service/service/StorePinkService.java index c1028b7..274f5e3 100644 --- a/fightwine-service/src/main/java/com/yzt/service/service/StorePinkService.java +++ b/fightwine-service/src/main/java/com/yzt/service/service/StorePinkService.java @@ -109,4 +109,21 @@ public interface StorePinkService extends IService { * @param pinkId 拼团(排队)记录ID */ void adminCancelQueueAndRecalculate(Integer pinkId); + + /** + * 后台管理员新增排队码 + * @param uid 用户ID + * @param productId 商品ID + * @param count 生成码数量 + * @param remark 备注 + */ + void adminGenerateQueueCodes(Integer uid, Integer productId, Integer count, String remark); + + /** + * H5端用户领取商品(免费送一份商品) + * @param pinkId 拼团ID + * @param addressId 收货地址ID + * @return 订单编号 + */ + String claimProduct(Integer pinkId, Integer addressId); } diff --git a/fightwine-service/src/main/java/com/yzt/service/service/impl/OrderServiceImpl.java b/fightwine-service/src/main/java/com/yzt/service/service/impl/OrderServiceImpl.java index d049cc2..d306b8c 100644 --- a/fightwine-service/src/main/java/com/yzt/service/service/impl/OrderServiceImpl.java +++ b/fightwine-service/src/main/java/com/yzt/service/service/impl/OrderServiceImpl.java @@ -448,14 +448,15 @@ public class OrderServiceImpl implements OrderService { * 订单列表 * * @param status 类型 + * @param payType 支付方式 * @param pageRequest 分页 * @return CommonPage */ @Override - public PageInfo list(String keywords, Integer status, PageParamRequest pageRequest) { + public PageInfo list(String keywords, Integer status, String payType, PageParamRequest pageRequest) { Integer userId = userService.getUserIdException(); - PageInfo orderPageInfo = storeOrderService.getUserOrderList_2_3(keywords,userId, status, pageRequest); + PageInfo orderPageInfo = storeOrderService.getUserOrderList_2_3(keywords,userId, status, payType, pageRequest); List orderList = orderPageInfo.getList(); if (CollUtil.isEmpty(orderList)) { return CommonPage.copyPageInfo(orderPageInfo, CollUtil.newArrayList()); diff --git a/fightwine-service/src/main/java/com/yzt/service/service/impl/StoreOrderServiceImpl.java b/fightwine-service/src/main/java/com/yzt/service/service/impl/StoreOrderServiceImpl.java index 32735f8..7fbef9f 100644 --- a/fightwine-service/src/main/java/com/yzt/service/service/impl/StoreOrderServiceImpl.java +++ b/fightwine-service/src/main/java/com/yzt/service/service/impl/StoreOrderServiceImpl.java @@ -198,17 +198,19 @@ public class StoreOrderServiceImpl extends ServiceImpl getUserOrderList_2_3(String keywords, - Integer uid, Integer status, PageParamRequest pageParamRequest) { + Integer uid, Integer status, String payType, PageParamRequest pageParamRequest) { Page page = PageHelper.startPage(pageParamRequest.getPage(), pageParamRequest.getLimit()); Map searchMap = new HashMap<>(); String searchKey = URLUtil.decode(keywords); searchMap.put("keywords", searchKey); searchMap.put("status", status); searchMap.put("uid", uid); + searchMap.put("payType", payType); List orderList = mapper.findFrontList(searchMap); return CommonPage.copyPageInfo(page, orderList); diff --git a/fightwine-service/src/main/java/com/yzt/service/service/impl/StorePinkServiceImpl.java b/fightwine-service/src/main/java/com/yzt/service/service/impl/StorePinkServiceImpl.java index 46d3657..169cc73 100644 --- a/fightwine-service/src/main/java/com/yzt/service/service/impl/StorePinkServiceImpl.java +++ b/fightwine-service/src/main/java/com/yzt/service/service/impl/StorePinkServiceImpl.java @@ -16,8 +16,12 @@ import com.yzt.common.exception.YztException; import com.yzt.common.model.combination.StoreCombination; import com.yzt.common.model.combination.StorePink; import com.yzt.common.model.order.StoreOrder; +import com.yzt.common.model.order.StoreOrderInfo; +import com.yzt.common.model.product.StoreProduct; +import com.yzt.common.model.product.StoreProductAttr; import com.yzt.common.model.system.SystemNotification; import com.yzt.common.model.user.User; +import com.yzt.common.model.user.UserAddress; import com.yzt.common.model.user.UserBrokerageRecord; import com.yzt.common.model.user.UserRechargeApplication; import com.yzt.common.model.user.UserToken; @@ -28,6 +32,7 @@ import com.yzt.common.request.StorePinkSearchRequest; import com.yzt.common.response.StorePinkAdminListResponse; import com.yzt.common.response.StorePinkDetailResponse; import com.yzt.common.utils.YztDateUtil; +import com.yzt.common.utils.YztUtil; import com.yzt.common.vo.DateLimitUtilVo; import com.yzt.common.vo.MyRecord; import com.yzt.service.mapper.StorePinkMapper; @@ -88,6 +93,21 @@ public class StorePinkServiceImpl extends ServiceImpl attrWrapper = new LambdaQueryWrapper<>(); + attrWrapper.eq(StoreProductAttr::getProductId, productId); + attrWrapper.eq(StoreProductAttr::getIsDel, false); + List attrList = storeProductAttrService.list(attrWrapper); + + if (CollUtil.isEmpty(attrList)) { + throw new YztException("商品属性不存在"); + } + + // 获取第一个属性的attrValues + String attrValues = attrList.get(0).getAttrValues(); + if (StrUtil.isBlank(attrValues)) { + throw new YztException("商品属性值为空"); + } + + //判断队列类型 + Integer queueType; + String redisKey; + if ("1".equals(attrValues)) { + queueType = 1; + redisKey = "queue:counter:member"; + } else if ("2".equals(attrValues)) { + queueType = 2; + redisKey = "queue:counter:hall"; + } else { + throw new YztException("商品属性值异常:" + attrValues + ",仅支持1(黔行)或2(茅香)"); + } + + List queueList = new ArrayList<>(); + long currentTimeSeconds = System.currentTimeMillis() / 1000; + String orderId = String.valueOf(currentTimeSeconds); + + for (int i = 0; i < count; i++) { + // 使用Redis递增获取排队号 + long currentQueueNo = redisUtil.incr(redisKey, 1); + + StorePink queueItem = new StorePink(); + + // 用户信息 + queueItem.setUid(user.getUid()); + queueItem.setNickname(user.getNickname()); + queueItem.setAvatar(user.getAvatar()); + + queueItem.setOrderId(orderId); + queueItem.setOrderIdKey(0); + + queueItem.setPid(productId); + queueItem.setCid(productId); + queueItem.setTotalNum(count); + queueItem.setPrice(BigDecimal.ZERO); + queueItem.setTotalPrice(BigDecimal.ZERO); + + queueItem.setPeople(1); + queueItem.setKId(0); + queueItem.setStatus(1); + queueItem.setAddTime(currentTimeSeconds); + queueItem.setStopTime(0L); + + queueItem.setIsTpl(false); + queueItem.setIsRefund(false); + queueItem.setIs_virtual(false); + + queueItem.setQueueType(queueType); + queueItem.setQueueNo((int) currentQueueNo); + queueItem.setQueueProgress(BigDecimal.ZERO); // 初始为0,后续重算 + + // 生成排队码编号:年月日时分秒+六位随机数 + String queueCode = generateQueueCode(currentTimeSeconds); + queueItem.setQueueCode(queueCode); + + // 设置备注 + queueItem.setRemark(remark); + + try { + Integer adminId = com.yzt.common.utils.SecurityUtil.getCurrentUserId(); + queueItem.setAdminId(adminId); + } catch (Exception e) { + // 如果获取不到管理员ID,不影响主流程,只记录日志 + logger.warn("无法获取当前管理员ID: {}", e.getMessage()); + } + + queueList.add(queueItem); + } + + if (!queueList.isEmpty()) { + this.saveBatch(queueList); + logger.info("管理员生成排队码成功: uid={}, productId={}, count={}, queueType={}, remark={}", + uid, productId, count, queueType, remark); + } + + //重新计算队列进度(查询该队列中所有is_refund=0且status=1的记录) + LambdaQueryWrapper waitingWrapper = new LambdaQueryWrapper<>(); + waitingWrapper.eq(StorePink::getQueueType, queueType) + .eq(StorePink::getStatus, 1) + .eq(StorePink::getIsRefund, false) + .orderByAsc(StorePink::getQueueNo); + List waitingList = this.list(waitingWrapper); + + if (CollUtil.isEmpty(waitingList)) { + return; + } + + // 使用Redis中的计数器值作为Y(队列当前排到的位置) + long redisVal = redisUtil.get(redisKey) == null ? 0 : Long.parseLong(redisUtil.get(redisKey).toString()); + int currentY = (int) redisVal; + if (currentY <= 0) { + currentY = waitingList.size(); + } + + // 重新计算进度:公式 (Y-X) / (5X) + List updates = new ArrayList<>(); + for (StorePink xUser : waitingList) { + Integer xNo = xUser.getQueueNo(); + if (xNo == null || xNo <= 0) { + continue; + } + int x = xNo; + if (x >= currentY) { + continue; + } + + BigDecimal numerator = new BigDecimal(currentY - x); // 分子 = Y - X + BigDecimal denominator = new BigDecimal(5 * x); // 分母 = 5X + if (denominator.compareTo(BigDecimal.ZERO) <= 0) { + // 分母异常时跳过,避免除零错误 + continue; + } + + // 判断是否免单成功 + if (numerator.compareTo(denominator) >= 0) { + // (Y-X) >= (5X),即 progress >= 1 + xUser.setQueueProgress(BigDecimal.ONE); + xUser.setStatus(2); + } else { + // 计算进度值,保留6位小数 + BigDecimal progress = numerator.divide(denominator, 6, BigDecimal.ROUND_DOWN); + xUser.setQueueProgress(progress); + } + updates.add(xUser); + } + if (CollUtil.isNotEmpty(updates)) { + this.updateBatchById(updates); + logger.info("重新计算队列进度完成: queueType={}, 更新记录数={}", queueType, updates.size()); + } + } + + /** + * 生成排队码编号:年月日时分秒+六位随机数 + * @param addTime Unix时间戳(秒) + * @return 排队码编号 + */ + private String generateQueueCode(Long addTime) { + // 将Unix时间戳转换为日期时间格式 + cn.hutool.core.date.DateTime dateTime = cn.hutool.core.date.DateUtil.date(addTime * 1000); + String timeStr = cn.hutool.core.date.DateUtil.format(dateTime, "yyMMddHHmmss"); + + // 生成六位随机数 + int randomNum = (int)(Math.random() * 1000000); + String randomStr = String.format("%06d", randomNum); + + return timeStr + randomStr; + } + + /** + * H5端用户领取商品(免费送一份商品) + * @param pinkId 拼团ID + * @param addressId 收货地址ID + * @return 订单编号 + */ + @Override + @Transactional(rollbackFor = Exception.class) + public String claimProduct(Integer pinkId, Integer addressId) { + // 验证拼团记录 + StorePink storePink = getById(pinkId); + if (ObjectUtil.isNull(storePink)) { + throw new YztException("拼团记录不存在"); + } + if (storePink.getIsRefund() != null && storePink.getIsRefund()) { + throw new YztException("该拼团记录已取消,无法领取"); + } + if (storePink.getStatus() != 2) { + throw new YztException("只有已达成待领取状态的拼团才能领取商品"); + } + + // 验证收货地址 + UserAddress userAddress = userAddressService.getById(addressId); + if (ObjectUtil.isNull(userAddress) || userAddress.getIsDel()) { + throw new YztException("收货地址不存在或已删除"); + } + if (!userAddress.getUid().equals(storePink.getUid())) { + throw new YztException("收货地址与拼团用户不匹配"); + } + + // 获取用户信息 + User user = userService.getById(storePink.getUid()); + if (ObjectUtil.isNull(user)) { + throw new YztException("用户信息不存在"); + } + + // 获取商品信息(从拼团记录的pid字段获取) + StoreProduct storeProduct = storeProductService.getById(storePink.getPid()); + if (ObjectUtil.isNull(storeProduct)) { + throw new YztException("商品不存在"); + } + + // 生成订单号 + String orderNo = YztUtil.getOrderNo("claim"); + + // 创建免费订单 + StoreOrder claimOrder = new StoreOrder(); + claimOrder.setUid(user.getUid()); + claimOrder.setTenantId(user.getTenantId()); + claimOrder.setOrderId(orderNo); + claimOrder.setRealName(userAddress.getRealName()); + claimOrder.setUserPhone(userAddress.getPhone()); + claimOrder.setUserAddress(userAddress.getProvince() + userAddress.getCity() + userAddress.getDistrict() + userAddress.getDetail()); + + // 免费领取 + claimOrder.setTotalNum(1); // 送一份 + claimOrder.setTotalPrice(BigDecimal.ZERO); + claimOrder.setProTotalPrice(BigDecimal.ZERO); + claimOrder.setTotalPostage(BigDecimal.ZERO); + claimOrder.setPayPrice(BigDecimal.ZERO); + claimOrder.setPayPostage(BigDecimal.ZERO); + claimOrder.setDeductionPrice(BigDecimal.ZERO); + claimOrder.setCouponId(0); + claimOrder.setCouponPrice(BigDecimal.ZERO); + claimOrder.setUseIntegral(0); + claimOrder.setGainIntegral(0); + claimOrder.setBackIntegral(0); + claimOrder.setCost(BigDecimal.ZERO); + + // 设置为已支付状态 + claimOrder.setPaid(true); + claimOrder.setPayTime(YztDateUtil.nowDateTime()); + claimOrder.setPayType("free"); // 标记为免费领取 + + claimOrder.setCreateTime(YztDateUtil.nowDateTime()); + claimOrder.setStatus(0); // 待发货 + claimOrder.setRefundStatus(0); + claimOrder.setShippingType(1); // 快递配送 + claimOrder.setCombinationId(0); + claimOrder.setPinkId(0); + claimOrder.setIsDel(false); + claimOrder.setIsSystemDel(false); + claimOrder.setIsRemind(false); + claimOrder.setType(0); // 普通订单 + claimOrder.setMark("拼团ID:" + pinkId + " 达成后免费领取"); + + // 保存订单 + boolean orderSaved = storeOrderService.create(claimOrder); + if (!orderSaved) { + throw new YztException("创建领取订单失败"); + } + + // 创建订单详情 + StoreOrderInfo orderInfo = new StoreOrderInfo(); + orderInfo.setOrderId(claimOrder.getId()); + orderInfo.setProductId(storeProduct.getId()); + orderInfo.setOrderNo(orderNo); + orderInfo.setProductName(storeProduct.getStoreName()); + orderInfo.setAttrValueId(0); // 无需规格 + orderInfo.setImage(storeProduct.getImage()); + orderInfo.setSku("免费领取"); + orderInfo.setPrice(BigDecimal.ZERO); // 免费 + orderInfo.setPayNum(1); // 送一份 + orderInfo.setWeight(BigDecimal.ZERO); + orderInfo.setVolume(BigDecimal.ZERO); + orderInfo.setGiveIntegral(0); + orderInfo.setIsReply(false); + orderInfo.setIsSub(false); + orderInfo.setVipPrice(BigDecimal.ZERO); + orderInfo.setProductType(Constants.PRODUCT_TYPE_NORMAL); + orderInfo.setUnique("claim_" + pinkId); + + // 构建详细信息JSON(简化版) + orderInfo.setInfo("{\"productId\":" + storeProduct.getId() + ",\"productName\":\"" + storeProduct.getStoreName() + "\",\"price\":0,\"payNum\":1}"); + + List orderInfoList = new ArrayList<>(); + orderInfoList.add(orderInfo); + storeOrderInfoService.saveOrderInfos(orderInfoList); + + // 更新拼团状态为已领取 + storePink.setStatus(3); + updateById(storePink); + + // 创建订单日志 + storeOrderStatusService.createLog(claimOrder.getId(), Constants.ORDER_STATUS_CACHE_CREATE_ORDER, "拼团达成免费领取商品订单生成"); + storeOrderStatusService.createLog(claimOrder.getId(), Constants.ORDER_STATUS_CACHE_CREATE_ORDER, "免费领取,自动标记为已支付"); + + logger.info("用户 {} 领取拼团商品成功,拼团ID: {}, 订单号: {}", user.getUid(), pinkId, orderNo); + + return orderNo; + } } diff --git a/fightwine-service/src/main/resources/mapper/store/StoreOrderMapper.xml b/fightwine-service/src/main/resources/mapper/store/StoreOrderMapper.xml index e77b479..d8f8166 100644 --- a/fightwine-service/src/main/resources/mapper/store/StoreOrderMapper.xml +++ b/fightwine-service/src/main/resources/mapper/store/StoreOrderMapper.xml @@ -3,16 +3,16 @@ select sum(o.pay_price) as num,date_format(o.create_time, '%Y-%m-%d') as time - from fw_store_order o + from zp_store_order o where o.is_del >= 0 and o.paid >= 1 and o.refund_status >= 0 and o.create_time >= #{ startTime } and o.create_time < #{ endTime } @@ -102,7 +105,7 @@ select count(*) as num, sum(o.pay_price) as price - from fw_store_order as o - right join fw_user_brokerage_record as br on br.link_id = o.order_id and br.status = 3 and br.uid = #{spreadId} + from zp_store_order as o + right join zp_user_brokerage_record as br on br.link_id = o.order_id and br.status = 3 and br.uid = #{spreadId} where o.uid = #{uid} and o.status > 1;