refactor(order): 重构订单购买逻辑并优化接口参数

- 调整 isBuy 方法参数顺序,增加 faceId 参数支持
- 删除冗余的购买检查方法和旧版 isBuy 重载方法
- 简化购买状态判断逻辑,移除重复代码
- 更新视频查看权限服务中的购买检查调用
- 修改人脸服务中景区 ID 类型为 Long
- 调整打印机服务中人脸查询方法参数类型
- 统一订单业务类中方法签名和调用方式
- 移除订单请求模型中无用字段注释
- 增加人脸 ID 列表字段支持批量查询
- 优化任务服务中购买状态检查逻辑
This commit is contained in:
2025-11-21 21:45:26 +08:00
parent 5b27cac6b0
commit 97e3ab19a0
14 changed files with 40 additions and 189 deletions

View File

@@ -163,6 +163,8 @@ public class OrderBiz {
}
public IsBuyRespVO isBuy(Long scenicId, Long memberId, Long faceId, int goodsType, Long goodsId) {
IsBuyRespVO respVO = new IsBuyRespVO();
respVO.setGoodsType(goodsType);
respVO.setGoodsId(goodsId);
OrderEntity orderEntity = orderMapper.getUserBuyFaceItem(memberId, faceId, goodsType, goodsId);
if (orderEntity != null) {
respVO.setOrderId(orderEntity.getId());
@@ -178,93 +180,13 @@ public class OrderBiz {
respVO.setSlashPrice(BigDecimal.ZERO);
return respVO;
}
PriceObj priceObj = queryPrice(scenicId, goodsType, goodsId);
if (priceObj == null) {
return respVO;
}
respVO.setBuy(false);
return respVO;
}
public IsBuyRespVO isBuy(Long userId, Long scenicId, int goodsType, Long goodsId) {
IsBuyRespVO respVO = new IsBuyRespVO();
boolean isBuy = orderRepository.checkUserBuyItem(userId, goodsType, goodsId);
// 模板购买逻辑
if (!isBuy) {
if (goodsType == 0) {
VideoEntity video = videoRepository.getVideo(goodsId);
if (video == null) {
return respVO;
}
TaskEntity task = videoTaskRepository.getTaskById(video.getTaskId());
Long templateId = video.getTemplateId();
// -1为整个模板购买
OrderEntity orderEntity = orderRepository.getUserBuyItem(userId, -1, templateId);
if (orderEntity != null && task != null) {
respVO.setOrderId(orderEntity.getId());
if (orderEntity.getFaceId() != null && task.getFaceId() != null) {
isBuy = orderEntity.getFaceId().equals(task.getFaceId());
}
}
}
}
// 免费送逻辑,之前已经赠送了的
if (!isBuy) {
isBuy = switch (goodsType) {
case 0 -> videoRepository.getUserIsBuy(userId, goodsId);
case 1, 2 -> sourceRepository.getUserIsBuy(userId, goodsType, goodsId);
default -> false;
};
} else {
OrderEntity orderEntity = orderRepository.getUserBuyItem(userId, goodsType, goodsId);
if (orderEntity != null) {
respVO.setOrderId(orderEntity.getId());
}
}
respVO.setBuy(isBuy);
// 还是没买
if (!isBuy) {
PriceObj priceObj = queryPrice(scenicId, goodsType, goodsId);
if (priceObj == null) {
return respVO;
}
FaceEntity face = faceRepository.getFace(priceObj.getFaceId());
respVO.setShare(true);
if (face != null && face.getMemberId().equals(userId)) {
respVO.setShare(false);
}
respVO.setFree(priceObj.isFree());
respVO.setGoodsType(goodsType);
respVO.setGoodsId(goodsId);
respVO.setOrigPrice(priceObj.getPrice());
respVO.setSlashPrice(priceObj.getSlashPrice());
switch (goodsType) {
case 0: // vlog
VideoEntity video = videoRepository.getVideo(goodsId);
TaskEntity taskById = videoTaskRepository.getTaskById(video.getTaskId());
if (taskById != null) {
CouponRecordQueryResp recordQueryResp = couponBiz.queryUserCouponRecord(scenicId, userId, taskById.getFaceId(), taskById.getTemplateId().toString());
if (recordQueryResp.isUsable()) {
respVO.setCouponId(recordQueryResp.getCouponId());
respVO.setCouponRecordId(recordQueryResp.getId());
CouponEntity coupon = recordQueryResp.getCoupon();
if (coupon != null) {
respVO.setCouponPrice(coupon.calculateDiscountPrice(priceObj.getPrice()));
}
}
}
break;
case 1:
case 2:
CouponRecordQueryResp recordQueryResp = couponBiz.queryUserCouponRecord(scenicId, userId, goodsId, String.valueOf(goodsType));
if (recordQueryResp.isUsable()) {
respVO.setCouponId(recordQueryResp.getCouponId());
respVO.setCouponRecordId(recordQueryResp.getId());
CouponEntity coupon = recordQueryResp.getCoupon();
if (coupon != null) {
respVO.setCouponPrice(coupon.calculateDiscountPrice(priceObj.getPrice()));
}
}
break;
}
}
respVO.setOrigPrice(priceObj.getPrice());
respVO.setSlashPrice(priceObj.getSlashPrice());
return respVO;
}

View File

@@ -93,9 +93,9 @@ public class AppOrderController {
}
@GetMapping("/scenic/{scenicId}/query")
public ApiResponse<IsBuyRespVO> isBuy(@PathVariable("scenicId") Long scenicId, @RequestParam("type") Integer type, @RequestParam("goodsId") Long goodsId) {
public ApiResponse<IsBuyRespVO> isBuy(@PathVariable("scenicId") Long scenicId, @RequestParam("type") Integer type, @RequestParam("goodsId") Long goodsId, @RequestParam(value = "faceId", required = false) Long faceId) {
Long userId = Long.parseLong(BaseContextHandler.getUserId());
return ApiResponse.success(orderBiz.isBuy(userId, scenicId, type, goodsId));
return ApiResponse.success(orderBiz.isBuy(scenicId, userId, faceId, type, goodsId));
}
@GetMapping("/scenic/{scenicId}/queryBatchPrice")

View File

@@ -17,71 +17,6 @@ import java.util.Date;
public class OrderAppPageReq extends BaseQueryParameterReq {
// 用户id
private Long memberId;
// /**
// * 微信openId
// */
// @ApiModelProperty("微信openId")
// private Long openId;
// /**
// * 价格
// */
// @ApiModelProperty("价格")
// private BigDecimal price;
// /**
// * 实际支付价格
// */
// @ApiModelProperty("实际支付价格")
// private BigDecimal payPrice;
// /**
// * 推客id
// */
// @ApiModelProperty("推客id")
// private Long brokerId;
// /**
// * 推客优惠码
// */
// @ApiModelProperty("推客优惠码")
// private String promoCode;
// /**
// * 退款原因
// */
// @ApiModelProperty("退款原因")
// private String refundReason;
// /**
// * 退款状态,0未提出,1已通过,2待审核
// */
// @ApiModelProperty("退款状态,0未提出,1已通过,2待审核")
// private Integer refundStatus;
// /**
// * 状态,0未支付,1已支付,2已退款,9已取消
// */
// @ApiModelProperty("状态,0未支付,1已支付,2已退款,9已取消")
// private Integer status;
// /**
// * 订单创建时间
// */
// @ApiModelProperty("订单创建时间")
// private Date startCreateTime;
// private Date endCreateTime;
// /**
// * 订单支付时间
// */
// @ApiModelProperty("订单支付时间")
// private Date startPayTime;
// private Date endPayTime;
// /**
// * 订单取消时间
// */
// @ApiModelProperty("订单取消时间")
// private Date startCancelTime;
// private Date endCancelTime;
// /**
// * 订单退款时间
// */
// @ApiModelProperty("订单退款时间")
// private Date startRefundTime;
// private Date endRefundTime;
// 订单类型 0成片(vlog) 1原片 2照片
private Integer type;
}

View File

@@ -8,6 +8,7 @@ import lombok.EqualsAndHashCode;
import java.math.BigDecimal;
import java.util.Date;
import java.util.List;
/**
* @Author:longbinbin
@@ -45,6 +46,8 @@ public class SourceReqQuery extends BaseQueryParameterReq {
// 是否被购买:0未购买,1已购买
private Integer isBuy;
private Long faceId;
// 人脸ID列表(批量查询用)
private List<Long> faceIds;
private Date startTime;
private Date endTime;
}

View File

@@ -86,22 +86,6 @@ public class OrderRepository {
return orderMapper.getUserBuyItem(userId, goodsType, goodsId);
}
public boolean checkUserBuyFaceSourceImage(Long userId, Long faceId) {
return checkUserBuyItem(userId, 2, faceId);
}
public boolean checkUserBuyFaceSourceVideo(Long userId, Long faceId) {
return checkUserBuyItem(userId, 1, faceId);
}
public boolean checkUserBuyVideo(Long userId, Long videoId) {
return checkUserBuyItem(userId, 0, videoId);
}
public boolean checkUserBuyTemplate(Long userId, Long templateId) {
return checkUserBuyItem(userId, -1, templateId);
}
public void clearUserBuyItemCache(Long userId, int goodsType, Long goodsId) {
redisTemplate.delete(String.format(ORDER_USER_TYPE_BUY_ITEM_CACHE_KEY, userId, goodsType, goodsId));
}

View File

@@ -4,11 +4,13 @@ import com.ycwl.basic.biz.OrderBiz;
import com.ycwl.basic.integration.common.manager.ScenicConfigManager;
import com.ycwl.basic.model.mobile.order.IsBuyRespVO;
import com.ycwl.basic.model.mobile.video.dto.VideoViewPermissionDTO;
import com.ycwl.basic.model.pc.task.entity.TaskEntity;
import com.ycwl.basic.model.pc.video.entity.UserVideoViewEntity;
import com.ycwl.basic.model.pc.video.entity.VideoEntity;
import com.ycwl.basic.repository.ScenicRepository;
import com.ycwl.basic.repository.UserVideoViewRepository;
import com.ycwl.basic.repository.VideoRepository;
import com.ycwl.basic.repository.VideoTaskRepository;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
@@ -28,6 +30,7 @@ public class VideoViewPermissionService {
private final VideoRepository videoRepository;
private final ScenicRepository scenicRepository;
private final OrderBiz orderBiz;
private final VideoTaskRepository videoTaskRepository;
/**
* 检查并记录用户查看视频
@@ -50,9 +53,10 @@ public class VideoViewPermissionService {
log.warn("视频缺少景区信息: videoId={}", videoId);
return createErrorPermission("视频信息不完整");
}
TaskEntity taskById = videoTaskRepository.getTaskById(video.getTaskId());
// 检查用户是否已购买
IsBuyRespVO buy = orderBiz.isBuy(userId, scenicId, 0, videoId);
IsBuyRespVO buy = orderBiz.isBuy(scenicId, userId, taskById.getFaceId(), 0, videoId);
if (buy != null && (buy.isBuy() || buy.isFree())) {
// 已购买,不限制查看
log.debug("用户已购买视频,无查看限制: userId={}, videoId={}", userId, videoId);
@@ -119,9 +123,10 @@ public class VideoViewPermissionService {
if (scenicId == null) {
return createErrorPermission("视频信息不完整");
}
TaskEntity taskById = videoTaskRepository.getTaskById(video.getTaskId());
// 检查用户是否已购买
IsBuyRespVO buy = orderBiz.isBuy(userId, scenicId, 0, videoId);
IsBuyRespVO buy = orderBiz.isBuy(scenicId, userId, taskById.getFaceId(), 0, videoId);
if (buy != null && (buy.isBuy() || buy.isFree())) {
// 已购买,不限制查看
log.debug("用户已购买视频,无查看限制: userId={}, videoId={}", userId, videoId);

View File

@@ -30,7 +30,7 @@ public interface FaceService {
FaceRecognizeResp faceUpload(MultipartFile file, Long scenicId, Long userId, String scene);
List<FaceRespVO> listByUser(Long userId, String scenicId);
List<FaceRespVO> listByUser(Long userId, Long scenicId);
SearchFaceRespVo matchFaceId(Long faceId);
SearchFaceRespVo matchFaceId(Long faceId, boolean isNew);

View File

@@ -319,7 +319,7 @@ public class FaceServiceImpl implements FaceService {
}
@Override
public List<FaceRespVO> listByUser(Long userId, String scenicId) {
public List<FaceRespVO> listByUser(Long userId, Long scenicId) {
return faceMapper.listByScenicAndUserId(scenicId, userId);
}
@@ -519,7 +519,7 @@ public class FaceServiceImpl implements FaceService {
sourceVideoContent.setGroup("直出原片");
sourceImageContent.setGroup("直出原片");
if (!scenicConfigFacade.isDisableSourceImage(face.getScenicId())) {
IsBuyRespVO isBuyRespVO = orderBiz.isBuy(userId, face.getScenicId(), SourceType.IMAGE.getCode(), faceId);
IsBuyRespVO isBuyRespVO = orderBiz.isBuy(face.getScenicId(), userId, faceId, SourceType.IMAGE.getCode(), faceId);
sourceImageContent.setSourceType(isBuyRespVO.getGoodsType());
sourceImageContent.setContentId(isBuyRespVO.getGoodsId());
if (isBuyRespVO.isBuy()) {
@@ -538,7 +538,7 @@ public class FaceServiceImpl implements FaceService {
contentList.add(sourceImageContent);
}
if (!scenicConfigFacade.isDisableSourceVideo(face.getScenicId())) {
IsBuyRespVO isBuyRespVO = orderBiz.isBuy(userId, face.getScenicId(), SourceType.VIDEO.getCode(), faceId);
IsBuyRespVO isBuyRespVO = orderBiz.isBuy(face.getScenicId(), userId, faceId, SourceType.VIDEO.getCode(), faceId);
sourceVideoContent.setSourceType(isBuyRespVO.getGoodsType());
sourceVideoContent.setContentId(isBuyRespVO.getGoodsId());
if (isBuyRespVO.isBuy()) {

View File

@@ -696,10 +696,6 @@ public class OrderServiceImpl implements OrderService {
// 使用synchronized确保同一用户对同一商品的订单创建操作串行化
synchronized (orderKey.intern()) {
IsBuyRespVO isBuy = orderBiz.isBuy(userId, createOrderReqVO.getScenicId(), createOrderReqVO.getGoodsType(), createOrderReqVO.getGoodsId());
if (isBuy.isBuy()) {
return ApiResponse.fail("您已购买此内容,无需重复购买!");
}
// 看看有没有之前购买的订单
OrderEntity order = orderMapper.getUserOrderItem(userId, createOrderReqVO.getScenicId(), 0, null, createOrderReqVO.getGoodsType(), createOrderReqVO.getGoodsId());
boolean haveOldOrder = false;
@@ -727,8 +723,14 @@ public class OrderServiceImpl implements OrderService {
order.setPrice(priceObj.getPrice());
// 判断是否是本人数据
FaceEntity goodsFace = faceRepository.getFace(priceObj.getFaceId());
if (goodsFace != null && !goodsFace.getMemberId().equals(userId)) {
return ApiResponse.fail("您无权购买此内容!");
if (goodsFace != null) {
if (!goodsFace.getMemberId().equals(userId)) {
return ApiResponse.fail("您无权购买此内容!");
}
IsBuyRespVO isBuy = orderBiz.isBuy(createOrderReqVO.getScenicId(), userId, goodsFace.getId(), createOrderReqVO.getGoodsType(), createOrderReqVO.getGoodsId());
if (isBuy.isBuy()) {
return ApiResponse.fail("您已购买此内容,无需重复购买!");
}
}
// promo code
order.setPayPrice(priceObj.getPrice());
@@ -940,7 +942,7 @@ public class OrderServiceImpl implements OrderService {
}
default -> 0L;
};
IsBuyRespVO isBuy = orderBiz.isBuy(userId, face.getScenicId(), type, goodsId);
IsBuyRespVO isBuy = orderBiz.isBuy(face.getScenicId(), userId, face.getId(), type, goodsId);
if (isBuy.isBuy()) {
throw new BaseException("您已购买此内容,无需重复购买!");
}

View File

@@ -45,7 +45,7 @@ public class BuyStatusProcessor {
}
// 获取用户购买状态
IsBuyRespVO isBuy = orderBiz.isBuy(memberId, scenicId,
IsBuyRespVO isBuy = orderBiz.isBuy(scenicId, memberId, faceId,
memberSourceEntityList.getFirst().getType(),
faceId);

View File

@@ -972,7 +972,7 @@ public class PrinterServiceImpl implements PrinterService {
Long faceId = null;
// 查询该用户在该景区的所有人脸记录
List<FaceRespVO> userFaces = faceMapper.listByScenicAndUserId(scenicId.toString(), userId);
List<FaceRespVO> userFaces = faceMapper.listByScenicAndUserId(scenicId, userId);
// 查找是否存在相同URL的记录
for (FaceRespVO faceResp : userFaces) {

View File

@@ -151,7 +151,7 @@ public class TaskFaceServiceImpl implements TaskFaceService {
return memberSourceEntity;
}).collect(Collectors.toList());
if (!memberSourceEntityList.isEmpty()) {
IsBuyRespVO isBuy = orderBiz.isBuy(face.getMemberId(), face.getScenicId(), memberSourceEntityList.getFirst().getType(), faceEntity.getId());
IsBuyRespVO isBuy = orderBiz.isBuy(face.getScenicId(), face.getMemberId(), faceEntity.getId(), memberSourceEntityList.getFirst().getType(), faceEntity.getId());
for (MemberSourceEntity memberSourceEntity : memberSourceEntityList) {
if (isBuy.isBuy()) { // 如果用户买过
memberSourceEntity.setIsBuy(1);

View File

@@ -442,7 +442,7 @@ public class TaskTaskServiceImpl implements TaskService {
memberVideoEntity.setTaskId(list.getFirst().getId());
VideoEntity video = videoMapper.findByTaskId(list.getFirst().getId());
if (video != null) {
IsBuyRespVO isBuy = orderBiz.isBuy(face.getMemberId(), list.getFirst().getScenicId(), 0, video.getId());
IsBuyRespVO isBuy = orderBiz.isBuy(list.getFirst().getScenicId(), face.getMemberId(), face.getId(), 0, video.getId());
if (isBuy.isBuy()) {
memberVideoEntity.setIsBuy(1);
memberVideoEntity.setOrderId(isBuy.getOrderId());
@@ -516,7 +516,7 @@ public class TaskTaskServiceImpl implements TaskService {
int isBuy = 0;
FaceEntity face = faceRepository.getFace(task.getFaceId());
if (face != null) {
IsBuyRespVO priceObj = orderBiz.isBuy(face.getMemberId(), task.getScenicId(), 0, video.getId());
IsBuyRespVO priceObj = orderBiz.isBuy(task.getScenicId(), face.getMemberId(), face.getId(), 0, video.getId());
if (priceObj.isBuy()) {
isBuy = 1;
}

View File

@@ -401,7 +401,7 @@ public class VideoPieceGetter {
videoSource.setFaceId(task.getFaceId());
videoSource.setScenicId(deviceV2.getScenicId());
videoSource.setSourceId(sourceEntity.getId());
IsBuyRespVO isBuy = orderBiz.isBuy(task.getMemberId(), deviceV2.getScenicId(), 1, task.getFaceId());
IsBuyRespVO isBuy = orderBiz.isBuy(deviceV2.getScenicId(), task.getMemberId(), task.getFaceId(), 1, task.getFaceId());
if (isBuy.isBuy()) { // 如果用户买过
videoSource.setIsBuy(1);
} else if (isBuy.isFree()) { // 全免费逻辑
@@ -432,7 +432,7 @@ public class VideoPieceGetter {
// 有原视频,source已存在,可以直接添加关联关系
if (task.memberId != null && task.faceId != null) {
List<MemberSourceEntity> memberSourceEntities = memberRelationRepository.listSourceByFaceRelation(task.faceId, 1);
IsBuyRespVO isBuy = orderBiz.isBuy(task.getMemberId(), deviceV2.getScenicId(), 1, task.getFaceId());
IsBuyRespVO isBuy = orderBiz.isBuy(deviceV2.getScenicId(), task.getMemberId(), task.getFaceId(), 1, task.getFaceId());
MemberSourceEntity videoSource = new MemberSourceEntity();
videoSource.setId(SnowFlakeUtil.getLongId());
videoSource.setScenicId(deviceV2.getScenicId());