Merge remote-tracking branch 'origin/master'

This commit is contained in:
pengsz 2025-12-05 09:01:40 +08:00
commit 41af1a5ec3
16 changed files with 506 additions and 25 deletions

View File

@ -1,6 +1,7 @@
package com.yzt.admin.controller; package com.yzt.admin.controller;
import com.yzt.common.page.CommonPage; import com.yzt.common.page.CommonPage;
import com.yzt.common.request.AdminGenerateQueueCodeRequest;
import com.yzt.common.request.PageParamRequest; import com.yzt.common.request.PageParamRequest;
import com.yzt.common.request.StoreCombinationRequest; import com.yzt.common.request.StoreCombinationRequest;
import com.yzt.common.request.StoreCombinationSearchRequest; import com.yzt.common.request.StoreCombinationSearchRequest;
@ -166,7 +167,14 @@ public class StoreCombinationController {
storePinkService.adminCancelQueueAndRecalculate(pinkId); storePinkService.adminCancelQueueAndRecalculate(pinkId);
return CommonResult.success(); return CommonResult.success();
} }
/**
* 后台管理员新增排队码
*/
@ApiOperation(value = "后台管理员新增排队码")
@RequestMapping(value = "/admin/generate/queue", method = RequestMethod.POST)
public CommonResult<Object> adminGenerateQueueCodes(@RequestBody @Validated AdminGenerateQueueCodeRequest request) {
storePinkService.adminGenerateQueueCodes(request.getUid(), request.getProductId(), request.getCount(), request.getRemark());
return CommonResult.success("排队码生成成功");
}
} }

View File

@ -21,7 +21,7 @@ import java.util.Date;
@Data @Data
@EqualsAndHashCode(callSuper = false) @EqualsAndHashCode(callSuper = false)
@Accessors(chain = true) @Accessors(chain = true)
@TableName("fw_schedule_job") @TableName("zp_schedule_job")
@ApiModel(value="ScheduleJob对象", description="定时任务") @ApiModel(value="ScheduleJob对象", description="定时任务")
public class ScheduleJob implements Serializable { public class ScheduleJob implements Serializable {

View File

@ -21,7 +21,7 @@ import java.util.Date;
@Data @Data
@EqualsAndHashCode(callSuper = false) @EqualsAndHashCode(callSuper = false)
@Accessors(chain = true) @Accessors(chain = true)
@TableName("fw_schedule_job_log") @TableName("zp_schedule_job_log")
@ApiModel(value="ScheduleJobLog对象", description="定时任务日志") @ApiModel(value="ScheduleJobLog对象", description="定时任务日志")
public class ScheduleJobLog implements Serializable { public class ScheduleJobLog implements Serializable {

View File

@ -68,10 +68,10 @@ public class StorePink implements Serializable {
@ApiModelProperty(value = "是否发送模板消息0未发送1已发送") @ApiModelProperty(value = "是否发送模板消息0未发送1已发送")
private Boolean isTpl; private Boolean isTpl;
@ApiModelProperty(value = "是否退款 0未退款 1已退款") @ApiModelProperty(value = "是否失效 0未失效 1已失效")
private Boolean isRefund; private Boolean isRefund;
@ApiModelProperty(value = "状态1进行中2已完成3未完成") @ApiModelProperty(value = "状态1排队中2已达成待领取3已领取")
private Integer status; private Integer status;
@ApiModelProperty(value = "用户昵称") @ApiModelProperty(value = "用户昵称")
@ -95,4 +95,10 @@ public class StorePink implements Serializable {
@ApiModelProperty(value = "排队码编号(年月日时分秒+六位随机数)") @ApiModelProperty(value = "排队码编号(年月日时分秒+六位随机数)")
private String queueCode; private String queueCode;
@ApiModelProperty(value = "操作的管理员ID")
private Integer adminId;
@ApiModelProperty(value = "备注")
private String remark;
} }

View File

@ -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;
}

View File

@ -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;
}

View File

@ -19,6 +19,6 @@ public class PinkQueryRequest {
@NotNull(message = "用户ID不能为空") @NotNull(message = "用户ID不能为空")
private Integer uid; private Integer uid;
@ApiModelProperty(value = "队列类型: 1-会员队列, 2-会馆队列") @ApiModelProperty(value = "队列类型: 1-黔行, 2-茅香")
private Integer queueType; private Integer queueType;
} }

View File

@ -2,12 +2,17 @@ package com.yzt.front.controller;
import com.github.pagehelper.PageInfo; import com.github.pagehelper.PageInfo;
import com.yzt.common.model.combination.StoreCombination; 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.page.CommonPage;
import com.yzt.common.request.ClaimProductRequest;
import com.yzt.common.request.PageParamRequest; import com.yzt.common.request.PageParamRequest;
import com.yzt.common.request.StorePinkRequest; import com.yzt.common.request.StorePinkRequest;
import com.yzt.common.response.*; import com.yzt.common.response.*;
import com.yzt.common.result.CommonResult; import com.yzt.common.result.CommonResult;
import com.yzt.service.service.StoreCombinationService; 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.Api;
import io.swagger.annotations.ApiOperation; import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
@ -28,6 +33,12 @@ public class CombinationController {
@Autowired @Autowired
private StoreCombinationService storeCombinationService; 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<String> 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<StoreProduct> 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());
}
}
} }

View File

@ -82,19 +82,22 @@ public class StoreOrderController {
/** /**
* 订单列表 * 订单列表
* @param type 类型 * @param type 类型
* @param payType 支付方式
* @param pageRequest 分页 * @param pageRequest 分页
* @return 订单列表 * @return 订单列表
*/ */
@ApiOperation(value = "订单列表") @ApiOperation(value = "订单列表")
@RequestMapping(value = "/list", method = RequestMethod.GET) @RequestMapping(value = "/list", method = RequestMethod.GET)
@ApiImplicitParams ({ @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<CommonPage<OrderDetailResponse>> orderList( public CommonResult<CommonPage<OrderDetailResponse>> orderList(
@RequestParam(name = "keywords", required = false) String keywords, @RequestParam(name = "keywords", required = false) String keywords,
@RequestParam(name = "type", required = false) Integer type, @RequestParam(name = "type", required = false) Integer type,
@RequestParam(name = "payType", required = false) String payType,
@ModelAttribute PageParamRequest pageRequest) { @ModelAttribute PageParamRequest pageRequest) {
return CommonResult.success(CommonPage.restPage(orderService.list(keywords, type, pageRequest))); return CommonResult.success(CommonPage.restPage(orderService.list(keywords, type, payType, pageRequest)));
} }
/** /**

View File

@ -16,10 +16,11 @@ public interface OrderService {
/** /**
* 订单列表 * 订单列表
* @param type 类型 * @param type 类型
* @param payType 支付方式
* @param pageRequest 分页 * @param pageRequest 分页
* @return 订单集合 * @return 订单集合
*/ */
PageInfo<OrderDetailResponse> list(String keywords,Integer type, PageParamRequest pageRequest); PageInfo<OrderDetailResponse> list(String keywords,Integer type, String payType, PageParamRequest pageRequest);
/** /**
* 订单详情 * 订单详情

View File

@ -53,7 +53,7 @@ public interface StoreOrderService extends IService<StoreOrder> {
* @return 订单结果列表 * @return 订单结果列表
*/ */
List<StoreOrder> getUserOrderList(Integer uid, Integer status, PageParamRequest pageParamRequest); List<StoreOrder> getUserOrderList(Integer uid, Integer status, PageParamRequest pageParamRequest);
PageInfo<StoreOrder> getUserOrderList_2_3(String keywords, Integer uid, Integer status, PageParamRequest pageParamRequest); PageInfo<StoreOrder> getUserOrderList_2_3(String keywords, Integer uid, Integer status, String payType, PageParamRequest pageParamRequest);
/** /**
* 创建订单 * 创建订单
* @param storeOrder 订单参数 * @param storeOrder 订单参数

View File

@ -109,4 +109,21 @@ public interface StorePinkService extends IService<StorePink> {
* @param pinkId 拼团(排队)记录ID * @param pinkId 拼团(排队)记录ID
*/ */
void adminCancelQueueAndRecalculate(Integer pinkId); 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);
} }

View File

@ -448,14 +448,15 @@ public class OrderServiceImpl implements OrderService {
* 订单列表 * 订单列表
* *
* @param status 类型 * @param status 类型
* @param payType 支付方式
* @param pageRequest 分页 * @param pageRequest 分页
* @return CommonPage<OrderDetailResponse> * @return CommonPage<OrderDetailResponse>
*/ */
@Override @Override
public PageInfo<OrderDetailResponse> list(String keywords, Integer status, PageParamRequest pageRequest) { public PageInfo<OrderDetailResponse> list(String keywords, Integer status, String payType, PageParamRequest pageRequest) {
Integer userId = userService.getUserIdException(); Integer userId = userService.getUserIdException();
PageInfo<StoreOrder> orderPageInfo = storeOrderService.getUserOrderList_2_3(keywords,userId, status, pageRequest); PageInfo<StoreOrder> orderPageInfo = storeOrderService.getUserOrderList_2_3(keywords,userId, status, payType, pageRequest);
List<StoreOrder> orderList = orderPageInfo.getList(); List<StoreOrder> orderList = orderPageInfo.getList();
if (CollUtil.isEmpty(orderList)) { if (CollUtil.isEmpty(orderList)) {
return CommonPage.copyPageInfo(orderPageInfo, CollUtil.newArrayList()); return CommonPage.copyPageInfo(orderPageInfo, CollUtil.newArrayList());

View File

@ -198,17 +198,19 @@ public class StoreOrderServiceImpl extends ServiceImpl<StoreOrderMapper, StoreOr
* @param keywords 搜索条件 * @param keywords 搜索条件
* @param uid 用户uid * @param uid 用户uid
* @param status 评价等级|0=未支付,1=待发货,2=待收货,3=待评价,4=已完成,-3=售后/退款 * @param status 评价等级|0=未支付,1=待发货,2=待收货,3=待评价,4=已完成,-3=售后/退款
* @param payType 支付方式
* @param pageParamRequest 分页参数 * @param pageParamRequest 分页参数
* @return 订单结果列表 * @return 订单结果列表
*/ */
public PageInfo<StoreOrder> getUserOrderList_2_3(String keywords, public PageInfo<StoreOrder> getUserOrderList_2_3(String keywords,
Integer uid, Integer status, PageParamRequest pageParamRequest) { Integer uid, Integer status, String payType, PageParamRequest pageParamRequest) {
Page<StoreOrder> page = PageHelper.startPage(pageParamRequest.getPage(), pageParamRequest.getLimit()); Page<StoreOrder> page = PageHelper.startPage(pageParamRequest.getPage(), pageParamRequest.getLimit());
Map<String, Object> searchMap = new HashMap<>(); Map<String, Object> searchMap = new HashMap<>();
String searchKey = URLUtil.decode(keywords); String searchKey = URLUtil.decode(keywords);
searchMap.put("keywords", searchKey); searchMap.put("keywords", searchKey);
searchMap.put("status", status); searchMap.put("status", status);
searchMap.put("uid", uid); searchMap.put("uid", uid);
searchMap.put("payType", payType);
List<StoreOrder> orderList = mapper.findFrontList(searchMap); List<StoreOrder> orderList = mapper.findFrontList(searchMap);
return CommonPage.copyPageInfo(page, orderList); return CommonPage.copyPageInfo(page, orderList);

View File

@ -16,8 +16,12 @@ import com.yzt.common.exception.YztException;
import com.yzt.common.model.combination.StoreCombination; import com.yzt.common.model.combination.StoreCombination;
import com.yzt.common.model.combination.StorePink; import com.yzt.common.model.combination.StorePink;
import com.yzt.common.model.order.StoreOrder; 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.system.SystemNotification;
import com.yzt.common.model.user.User; 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.UserBrokerageRecord;
import com.yzt.common.model.user.UserRechargeApplication; import com.yzt.common.model.user.UserRechargeApplication;
import com.yzt.common.model.user.UserToken; 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.StorePinkAdminListResponse;
import com.yzt.common.response.StorePinkDetailResponse; import com.yzt.common.response.StorePinkDetailResponse;
import com.yzt.common.utils.YztDateUtil; import com.yzt.common.utils.YztDateUtil;
import com.yzt.common.utils.YztUtil;
import com.yzt.common.vo.DateLimitUtilVo; import com.yzt.common.vo.DateLimitUtilVo;
import com.yzt.common.vo.MyRecord; import com.yzt.common.vo.MyRecord;
import com.yzt.service.mapper.StorePinkMapper; import com.yzt.service.mapper.StorePinkMapper;
@ -88,6 +93,21 @@ public class StorePinkServiceImpl extends ServiceImpl<StorePinkMapper, StorePink
@Autowired @Autowired
private TenantService tenantService; private TenantService tenantService;
@Autowired
private StoreProductAttrService storeProductAttrService;
@Autowired
private UserAddressService userAddressService;
@Autowired
private StoreProductService storeProductService;
@Autowired
private StoreOrderInfoService storeOrderInfoService;
@Autowired
private StoreOrderStatusService storeOrderStatusService;
/** /**
* 列表 * 列表
@ -618,5 +638,318 @@ public class StorePinkServiceImpl extends ServiceImpl<StorePinkMapper, StorePink
logger.warn("===== StorePinkService.saveBatch COMPLETED: {} records =====", entityList.size()); logger.warn("===== StorePinkService.saveBatch COMPLETED: {} records =====", entityList.size());
return result; return result;
} }
/**
* 后台管理员新增排队码
* @param uid 用户ID
* @param productId 商品ID
* @param count 生成码数量
* @param remark 备注
*/
@Override
@Transactional(rollbackFor = Exception.class)
public void adminGenerateQueueCodes(Integer uid, Integer productId, Integer count, String remark) {
if (uid == null || productId == null || count == null || count <= 0) {
throw new YztException("参数错误");
}
User user = userService.getById(uid);
if (user == null) {
throw new YztException("用户不存在");
}
LambdaQueryWrapper<StoreProductAttr> attrWrapper = new LambdaQueryWrapper<>();
attrWrapper.eq(StoreProductAttr::getProductId, productId);
attrWrapper.eq(StoreProductAttr::getIsDel, false);
List<StoreProductAttr> 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<StorePink> 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<StorePink> waitingWrapper = new LambdaQueryWrapper<>();
waitingWrapper.eq(StorePink::getQueueType, queueType)
.eq(StorePink::getStatus, 1)
.eq(StorePink::getIsRefund, false)
.orderByAsc(StorePink::getQueueNo);
List<StorePink> 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<StorePink> 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<StoreOrderInfo> 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;
}
} }

View File

@ -3,16 +3,16 @@
<mapper namespace="com.yzt.service.mapper.StoreOrderMapper"> <mapper namespace="com.yzt.service.mapper.StoreOrderMapper">
<select id="getTotalPrice" resultType="java.math.BigDecimal"> <select id="getTotalPrice" resultType="java.math.BigDecimal">
select sum(pay_price) from fw_store_order where ${where} and refund_status = 0 select sum(pay_price) from zp_store_order where ${where} and refund_status = 0
</select> </select>
<select id="getRefundPrice" resultType="java.math.BigDecimal"> <select id="getRefundPrice" resultType="java.math.BigDecimal">
select sum(refund_price) from fw_store_order where ${where} and refund_status = 2 select sum(refund_price) from zp_store_order where ${where} and refund_status = 2
</select> </select>
<select id="getRefundTotal" resultType="java.lang.Integer"> <select id="getRefundTotal" resultType="java.lang.Integer">
select count(id) from fw_store_order where ${where} and refund_status = 2 select count(id) from zp_store_order where ${where} and refund_status = 2
</select> </select>
<select id="findFrontList" resultType="com.yzt.common.model.order.StoreOrder" parameterType="Map"> <select id="findFrontList" resultType="com.yzt.common.model.order.StoreOrder" parameterType="Map">
select * from fw_store_order select * from zp_store_order
where where
uid = #{uid} uid = #{uid}
<if test="status != null "> <if test="status != null ">
@ -72,14 +72,17 @@
<if test="keywords != null and keywords !='' "> <if test="keywords != null and keywords !='' ">
and (order_id like CONCAT('%',#{keywords},'%') and (order_id like CONCAT('%',#{keywords},'%')
or or
order_id in (select order_no from fw_store_order_info where product_name like CONCAT('%',#{keywords},'%'))) order_id in (select order_no from zp_store_order_info where product_name like CONCAT('%',#{keywords},'%')))
</if>
<if test="payType != null and payType !='' ">
and pay_type = #{payType}
</if> </if>
order by id desc order by id desc
</select> </select>
<select id="getOrderVerificationDetail" parameterType="com.yzt.common.request.PageParamRequest" <select id="getOrderVerificationDetail" parameterType="com.yzt.common.request.PageParamRequest"
resultType="com.yzt.common.response.StoreStaffDetail"> resultType="com.yzt.common.response.StoreStaffDetail">
select sum(o.`pay_price`) as price, count(o.`id`) as count, DATE_FORMAT(o.`create_time`, '%Y-%m-%d') as time select sum(o.`pay_price`) as price, count(o.`id`) as count, 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 where o.`is_del` = 0 and o.`paid` = 1 and o.`refund_status` = 0
<if test="null != startTime and startTime != ''"> <if test="null != startTime and startTime != ''">
and o.create_time >= #{ startTime } and o.create_time >= #{ startTime }
@ -92,7 +95,7 @@
<select id="getOrderStatisticsPriceDetail" parameterType="com.yzt.common.request.StoreDateRangeSqlPram" <select id="getOrderStatisticsPriceDetail" parameterType="com.yzt.common.request.StoreDateRangeSqlPram"
resultType="com.yzt.common.response.StoreOrderStatisticsChartItemResponse"> resultType="com.yzt.common.response.StoreOrderStatisticsChartItemResponse">
select sum(o.pay_price) as num,date_format(o.create_time, '%Y-%m-%d') as time 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 where o.is_del >= 0 and o.paid >= 1 and o.refund_status >= 0
and o.create_time >= #{ startTime } and o.create_time >= #{ startTime }
and o.create_time &lt; #{ endTime } and o.create_time &lt; #{ endTime }
@ -102,7 +105,7 @@
<select id="getOrderStatisticsOrderCountDetail" parameterType="com.yzt.common.request.StoreDateRangeSqlPram" <select id="getOrderStatisticsOrderCountDetail" parameterType="com.yzt.common.request.StoreDateRangeSqlPram"
resultType="com.yzt.common.response.StoreOrderStatisticsChartItemResponse"> resultType="com.yzt.common.response.StoreOrderStatisticsChartItemResponse">
select count(id) as num, date_format(o.create_time, '%Y-%m-%d') as time select count(id) 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 where o.is_del >= 0 and o.paid >= 1 and o.refund_status >= 0
and o.create_time >= #{ startTime } and o.create_time >= #{ startTime }
and o.create_time &lt; #{ endTime } and o.create_time &lt; #{ endTime }
@ -112,8 +115,8 @@
<select id="getBrokerageData" resultType="com.yzt.common.response.OrderBrokerageData"> <select id="getBrokerageData" resultType="com.yzt.common.response.OrderBrokerageData">
select count(*) as num, sum(o.pay_price) as price select count(*) as num, sum(o.pay_price) as price
from fw_store_order as o from zp_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} 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; where o.uid = #{uid} and o.status > 1;
</select> </select>
</mapper> </mapper>