feat(printer): 实现虚拟用户0元订单创建功能

- 新增CreateVirtualOrderRequest请求参数类
- 实现createVirtualOrder服务方法,支持根据source创建虚拟用户订单
- 自动生成虚拟用户ID并创建对应的人脸记录
- 创建member_print记录并设置照片数量
- 支持指定或自动选择景区内可用打印机
- 创建0元订单并触发购买后逻辑
- 返回订单相关信息包括orderId、faceId等
- 添加详细的日志记录便于调试和追踪
- 实现完整的异常处理和参数校验
This commit is contained in:
2025-12-17 22:07:42 +08:00
parent 8e0990832b
commit 99d0b9c340
3 changed files with 158 additions and 0 deletions

View File

@@ -0,0 +1,24 @@
package com.ycwl.basic.model.printer.req;
import lombok.Data;
/**
* 创建虚拟用户0元订单请求参数
*/
@Data
public class CreateVirtualOrderRequest {
/**
* source记录ID
*/
private Long sourceId;
/**
* 景区ID
*/
private Long scenicId;
/**
* 打印机ID(可选)
*/
private Integer printerId;
}

View File

@@ -105,4 +105,17 @@ public interface PrinterService {
Integer addUserPhotoFromPuzzle(Long memberId, Long scenicId, Long faceId, String resultImageUrl, Long puzzleRecordId); Integer addUserPhotoFromPuzzle(Long memberId, Long scenicId, Long faceId, String resultImageUrl, Long puzzleRecordId);
int handleReprint(Integer id, ReprintRequest request); int handleReprint(Integer id, ReprintRequest request);
/**
* 创建虚拟用户0元订单
* 1. 根据source创建人脸记录(使用虚拟用户ID)
* 2. 创建member_print记录
* 3. 创建0元订单并触发购买后逻辑
*
* @param sourceId source记录ID
* @param scenicId 景区ID
* @param printerId 打印机ID(可选)
* @return 订单信息
*/
Map<String, Object> createVirtualOrder(Long sourceId, Long scenicId, Integer printerId);
} }

View File

@@ -1571,4 +1571,125 @@ public class PrinterServiceImpl implements PrinterService {
return rows; return rows;
} }
@Override
public Map<String, Object> createVirtualOrder(Long sourceId, Long scenicId, Integer printerId) {
// 1. 查询source记录
SourceEntity source = sourceMapper.getEntity(sourceId);
FaceSampleEntity faceSample = faceSampleMapper.getEntity(source.getFaceSampleId());
if (source == null) {
throw new BaseException("Source记录不存在");
}
if (!scenicId.equals(source.getScenicId())) {
throw new BaseException("Source记录不属于该景区");
}
if (faceSample == null) {
throw new BaseException("人脸样本不存在");
}
// 2. 生成虚拟用户ID(使用雪花算法生成一个不在用户表中的ID)
Long virtualMemberId = SnowFlakeUtil.getLongId();
log.info("创建虚拟用户0元订单: virtualMemberId={}, sourceId={}, scenicId={}", virtualMemberId, sourceId, scenicId);
// 3. 创建人脸记录
Long faceId = SnowFlakeUtil.getLongId();
FaceEntity face = new FaceEntity();
face.setId(faceId);
face.setScenicId(scenicId);
face.setMemberId(virtualMemberId);
// 从source获取人脸URL
face.setFaceUrl(faceSample.getFaceUrl());
face.setCreateAt(new Date());
faceMapper.add(face);
log.info("创建人脸记录成功: faceId={}, virtualMemberId={}, origUrl={}", faceId, virtualMemberId, source.getUrl());
// 4. 创建member_print记录(参考addUserPhotoFromSource方法)
Integer memberPrintId = addUserPhoto(virtualMemberId, scenicId, source.getUrl(), faceId, sourceId);
if (memberPrintId == null) {
throw new BaseException("创建member_print记录失败");
}
log.info("创建member_print记录成功: memberPrintId={}, faceId={}", memberPrintId, faceId);
// 设置打印数量为1
setPhotoQuantity(virtualMemberId, scenicId, memberPrintId.longValue(), 1);
// 5. 验证打印机
if (printerId == null) {
List<PrinterResp> printerList = printerMapper.listByScenicId(scenicId);
if (printerList.isEmpty()) {
throw new BaseException("该景区没有可用的打印机");
}
if (printerList.size() != 1) {
throw new BaseException("请选择打印机");
}
printerId = printerList.getFirst().getId();
}
PrinterEntity printer = printerMapper.getById(printerId);
if (printer == null) {
throw new BaseException("打印机不存在");
}
if (printer.getStatus() != 1) {
throw new BaseException("打印机已停用");
}
if (!printer.getScenicId().equals(scenicId)) {
throw new BaseException("打印机不属于该景区");
}
// 6. 创建0元订单
OrderEntity order = new OrderEntity();
Long orderId = SnowFlakeUtil.getLongId();
redisTemplate.opsForValue().set("printer_size:" + orderId, printer.getPreferPaper(), 60, TimeUnit.SECONDS);
order.setId(orderId);
order.setMemberId(virtualMemberId);
order.setFaceId(faceId);
order.setOpenId(""); // 虚拟用户没有openId
order.setScenicId(scenicId);
order.setType(3); // 照片打印类型
// 设置打印机
batchSetUserPhotoListToPrinter(virtualMemberId, scenicId, printerId);
// 获取用户照片列表
List<MemberPrintResp> userPhotoList = getUserPhotoList(virtualMemberId, scenicId, faceId);
List<OrderItemEntity> orderItems = userPhotoList.stream().map(goods -> {
OrderItemEntity orderItem = new OrderItemEntity();
orderItem.setOrderId(orderId);
orderItem.setGoodsId(Long.valueOf(goods.getId()));
orderItem.setGoodsType(3);
return orderItem;
}).collect(Collectors.toList());
// 设置价格为0
order.setPrice(BigDecimal.ZERO);
order.setSlashPrice(BigDecimal.ZERO);
order.setPayPrice(BigDecimal.ZERO);
order.setFaceId(faceId);
order.setStatus(OrderStateEnum.PAID.getState());
order.setPayAt(new Date());
// 保存订单
orderMapper.add(order);
int addOrderItems = orderMapper.addOrderItems(orderItems);
if (addOrderItems == NumberConstant.ZERO) {
log.error("订单明细添加失败");
throw new BaseException("订单添加失败");
}
log.info("创建0元订单成功: orderId={}, virtualMemberId={}, faceId={}", orderId, virtualMemberId, faceId);
// 7. 触发购买后逻辑(调用setUserIsBuyItem)
setUserIsBuyItem(virtualMemberId, memberPrintId.longValue(), orderId);
log.info("触发购买后逻辑完成: orderId={}", orderId);
// 8. 返回结果
Map<String, Object> result = new HashMap<>();
result.put("orderId", orderId);
result.put("faceId", faceId);
result.put("virtualMemberId", virtualMemberId);
result.put("memberPrintId", memberPrintId);
result.put("needPay", false);
return result;
}
} }