Compare commits

...

6 Commits

Author SHA1 Message Date
062a128dcc fix(printer): 修正照片打印产品数量设置
All checks were successful
ZhenTu-BE/pipeline/head This commit looks good
- 将照片打印产品的数量固定为1
- 保留购买次数为源ID列表的大小
- 确保每个照片打印项只计算一次数量
2026-02-14 19:22:50 +08:00
f9c776b3ab feat(printer): 支持批量创建虚拟订单功能
- 修改CreateVirtualOrderRequest参数结构,将sourceId改为sourceIds列表
- 添加对sourceIds参数的空值校验
- 调用createBatchVirtualOrder方法替代原有单个订单创建逻辑
- 更新API接口支持多条source记录聚合为一笔订单
2026-02-14 19:07:12 +08:00
e5eea4c349 fix(face): 修复摄影师拍照内容购买状态显示问题
- 添加会员资源关系查询以获取正确的购买状态
- 修改内容设置逻辑使用会员资源关系中的购买状态
- 实现流式过滤匹配资源ID并设置对应的购买标识
2026-02-14 18:19:04 +08:00
0484c8077d fix(face): 修复摄影师拍照内容购买状态显示问题
- 添加会员资源关系查询以获取正确的购买状态
- 修改内容设置逻辑使用会员资源关系中的购买状态
- 实现流式过滤匹配资源ID并设置对应的购买标识
2026-02-14 18:05:46 +08:00
6a22fc87a7 feat(order): 添加单张照片订单类型支持
- 新增 member_single_photo_data CTE 查询单张照片数据
- 添加订单类型 14 对应单张照片类型的映射
- 在订单项目查询中增加对单张照片类型的支持
- 关联 member_single_photo_data 表获取单张照片的 face_id 和 URL
- 实现单张照片类型的 face_url 和 imgUrl 映射逻辑
2026-02-14 17:54:13 +08:00
b01056d829 feat(coupon): 添加景区ID过滤功能以查询用户可用优惠券
- 在getUserCoupons接口中添加scenicId参数支持
- 修改couponService实现以按景区ID过滤优惠券
- 添加空值检查跳过无效配置的优惠券
- 更新接口文档添加scenicId参数说明
2026-02-14 17:42:44 +08:00
9 changed files with 53 additions and 12 deletions

View File

@@ -62,9 +62,12 @@ public class SourceController {
*/ */
@PostMapping("/createVirtualOrder") @PostMapping("/createVirtualOrder")
public ApiResponse<Map<String, Object>> createVirtualOrder(@RequestBody CreateVirtualOrderRequest request) { public ApiResponse<Map<String, Object>> createVirtualOrder(@RequestBody CreateVirtualOrderRequest request) {
if (request.getSourceIds() == null || request.getSourceIds().isEmpty()) {
return ApiResponse.fail("sourceIds不能为空");
}
try { try {
Map<String, Object> result = printerService.createVirtualOrder( Map<String, Object> result = printerService.createBatchVirtualOrder(
request.getSourceId(), request.getSourceIds(),
request.getScenicId(), request.getScenicId(),
request.getPrinterId(), request.getPrinterId(),
request.getNeedEnhance(), request.getNeedEnhance(),

View File

@@ -2,15 +2,17 @@ package com.ycwl.basic.model.printer.req;
import lombok.Data; import lombok.Data;
import java.util.List;
/** /**
* 创建虚拟用户0元订单请求参数 * 创建虚拟用户0元订单请求参数
*/ */
@Data @Data
public class CreateVirtualOrderRequest { public class CreateVirtualOrderRequest {
/** /**
* source记录ID * source记录ID列表(支持单个或多个sourceId聚合为一笔订单)
*/ */
private Long sourceId; private List<Long> sourceIds;
/** /**
* 景区ID * 景区ID

View File

@@ -58,13 +58,13 @@ public class PriceCalculationController {
* 查询用户可用优惠券(包含领取记录信息) * 查询用户可用优惠券(包含领取记录信息)
*/ */
@GetMapping("/coupons/my-coupons") @GetMapping("/coupons/my-coupons")
public ApiResponse<List<UserCouponResp>> getUserCoupons() { public ApiResponse<List<UserCouponResp>> getUserCoupons(@RequestParam(required = false) String scenicId) {
Long userId = getUserId(); Long userId = getUserId();
if (userId == null) { if (userId == null) {
return ApiResponse.fail("用户未登录"); return ApiResponse.fail("用户未登录");
} }
List<UserCouponResp> coupons = couponService.getUserAvailableCoupons(userId); List<UserCouponResp> coupons = couponService.getUserAvailableCoupons(userId, scenicId);
return ApiResponse.success(coupons); return ApiResponse.success(coupons);
} }

View File

@@ -59,9 +59,10 @@ public interface ICouponService {
* 查询用户可用优惠券(包含领取记录信息) * 查询用户可用优惠券(包含领取记录信息)
* *
* @param userId 用户ID * @param userId 用户ID
* @param scenicId 景区ID,传入时仅返回该景区可用的优惠券,NULL时返回全部
* @return 用户优惠券列表(包含领取记录+优惠券配置) * @return 用户优惠券列表(包含领取记录+优惠券配置)
*/ */
List<UserCouponResp> getUserAvailableCoupons(Long userId); List<UserCouponResp> getUserAvailableCoupons(Long userId, String scenicId);
/** /**
* 领取优惠券(内部调用方法) * 领取优惠券(内部调用方法)

View File

@@ -295,15 +295,19 @@ public class CouponServiceImpl implements ICouponService {
} }
@Override @Override
public List<UserCouponResp> getUserAvailableCoupons(Long userId) { public List<UserCouponResp> getUserAvailableCoupons(Long userId, String scenicId) {
List<PriceCouponClaimRecord> records = couponClaimRecordMapper.selectUserAvailableCoupons(userId); List<PriceCouponClaimRecord> records = couponClaimRecordMapper.selectUserAvailableCoupons(userId);
List<UserCouponResp> coupons = new ArrayList<>(); List<UserCouponResp> coupons = new ArrayList<>();
for (PriceCouponClaimRecord record : records) { for (PriceCouponClaimRecord record : records) {
PriceCouponConfig config = couponConfigMapper.selectById(record.getCouponId()); PriceCouponConfig config = couponConfigMapper.selectById(record.getCouponId());
if (config != null) { if (config == null) {
coupons.add(buildUserCouponResp(record, config)); continue;
} }
if (scenicId != null && config.getScenicId() != null && !scenicId.equals(config.getScenicId())) {
continue;
}
coupons.add(buildUserCouponResp(record, config));
} }
return coupons; return coupons;

View File

@@ -483,6 +483,7 @@ public class FaceServiceImpl implements FaceService {
// 摄影师拍照 // 摄影师拍照
List<DeviceV2DTO> deviceList = deviceRepository.getAllDeviceByScenicId(face.getScenicId()); List<DeviceV2DTO> deviceList = deviceRepository.getAllDeviceByScenicId(face.getScenicId());
List<SourceEntity> sourceEntityList = sourceMapper.listSourceByFaceRelation(face.getId(), 2); List<SourceEntity> sourceEntityList = sourceMapper.listSourceByFaceRelation(face.getId(), 2);
List<MemberSourceEntity> memberSourceRelations = memberRelationRepository.listSourceByFaceRelation(face.getId(), 2);
for (SourceEntity sourceEntity : sourceEntityList) { for (SourceEntity sourceEntity : sourceEntityList) {
ContentPageVO content = new ContentPageVO(); ContentPageVO content = new ContentPageVO();
content.setName("摄影师拍照"); content.setName("摄影师拍照");
@@ -496,7 +497,9 @@ public class FaceServiceImpl implements FaceService {
content.setSourceType(2); content.setSourceType(2);
content.setOrigUrl(sourceEntity.getUrl()); content.setOrigUrl(sourceEntity.getUrl());
content.setTemplateCoverUrl(sourceEntity.getThumbUrl()); content.setTemplateCoverUrl(sourceEntity.getThumbUrl());
content.setIsBuy(sourceEntity.getIsBuy()); memberSourceRelations.stream().filter(relation -> relation.getSourceId().equals(sourceEntity.getId())).findAny().ifPresent(relation -> {
content.setIsBuy(relation.getIsBuy());
});
content.setLockType(-1); content.setLockType(-1);
result.add(content); result.add(content);
} }

View File

@@ -44,6 +44,7 @@ import com.ycwl.basic.model.pc.price.entity.PriceConfigEntity;
import com.ycwl.basic.model.pc.price.resp.GoodsListRespVO; import com.ycwl.basic.model.pc.price.resp.GoodsListRespVO;
import com.ycwl.basic.model.pc.printer.resp.MemberPrintResp; import com.ycwl.basic.model.pc.printer.resp.MemberPrintResp;
import com.ycwl.basic.model.pc.source.entity.SourceEntity; import com.ycwl.basic.model.pc.source.entity.SourceEntity;
import com.ycwl.basic.model.pc.source.resp.SourceRespVO;
import com.ycwl.basic.model.pc.task.entity.TaskEntity; import com.ycwl.basic.model.pc.task.entity.TaskEntity;
import com.ycwl.basic.model.pc.template.resp.TemplateRespVO; import com.ycwl.basic.model.pc.template.resp.TemplateRespVO;
import com.ycwl.basic.model.pc.video.entity.VideoEntity; import com.ycwl.basic.model.pc.video.entity.VideoEntity;
@@ -423,6 +424,21 @@ public class OrderServiceImpl implements OrderService {
goods.setTemplateCoverUrl(item.getCoverUrl()); goods.setTemplateCoverUrl(item.getCoverUrl());
goods.setScenicId(order.getScenicId()); goods.setScenicId(order.getScenicId());
goodsList.add(goods); goodsList.add(goods);
} else if (Integer.valueOf(14).equals(item.getGoodsType())) { // 单张照片 goodsId就是sourceId
SourceRespVO source = sourceMapper.getById(item.getGoodsId());
if (source != null) {
item.setCoverList(Collections.singletonList(source.getUrl()));
GoodsDetailVO goods = new GoodsDetailVO();
goods.setGoodsId(source.getId());
goods.setGoodsName("单张照片");
goods.setUrl(source.getUrl());
goods.setGoodsType(14);
goods.setScenicId(source.getScenicId());
goods.setTemplateCoverUrl(source.getUrl());
goods.setCreateTime(source.getCreateTime());
goodsList.add(goods);
item.setShootingTime(source.getCreateTime());
}
} else { } else {
item.setCoverList(Collections.singletonList(item.getCoverUrl())); item.setCoverList(Collections.singletonList(item.getCoverUrl()));
VideoEntity videoMapperById = videoRepository.getVideo(item.getGoodsId()); VideoEntity videoMapperById = videoRepository.getVideo(item.getGoodsId());

View File

@@ -2037,7 +2037,7 @@ public class PrinterServiceImpl implements PrinterService {
ProductItem photoItem = new ProductItem(); ProductItem photoItem = new ProductItem();
photoItem.setProductType(ProductType.PHOTO_PRINT); photoItem.setProductType(ProductType.PHOTO_PRINT);
photoItem.setProductId(scenicId.toString()); photoItem.setProductId(scenicId.toString());
photoItem.setQuantity(sourceIds.size()); photoItem.setQuantity(1);
photoItem.setPurchaseCount(sourceIds.size()); photoItem.setPurchaseCount(sourceIds.size());
photoItem.setScenicId(scenicId.toString()); photoItem.setScenicId(scenicId.toString());
productItems.add(photoItem); productItems.add(photoItem);

View File

@@ -115,6 +115,13 @@
SELECT 5 as type, gr.template_id as id, pt.scenic_id as scenic_id, gr.result_image_url as url, gr.face_id SELECT 5 as type, gr.template_id as id, pt.scenic_id as scenic_id, gr.result_image_url as url, gr.face_id
FROM puzzle_generation_record gr FROM puzzle_generation_record gr
left join puzzle_template pt on gr.template_id = pt.id left join puzzle_template pt on gr.template_id = pt.id
),
member_single_photo_data AS (
SELECT ms.source_id, ms.face_id, f.face_url, s.url
FROM member_source ms
LEFT JOIN face f ON ms.face_id = f.id
LEFT JOIN source s ON ms.source_id = s.id
WHERE s.id IS NOT NULL AND ms.deleted = 0
) )
SELECT SELECT
oi.id AS oiId, oi.id AS oiId,
@@ -136,6 +143,7 @@
WHEN '4' THEN '一体机照片打印' WHEN '4' THEN '一体机照片打印'
WHEN '5' THEN 'pLog' WHEN '5' THEN 'pLog'
WHEN '13' THEN '打卡点拍照' WHEN '13' THEN '打卡点拍照'
WHEN '14' THEN '单张照片'
ELSE '其他' ELSE '其他'
END AS goods_name, END AS goods_name,
CASE oi.goods_type CASE oi.goods_type
@@ -143,12 +151,14 @@
WHEN '1' THEN oi.goods_id WHEN '1' THEN oi.goods_id
WHEN '2' THEN oi.goods_id WHEN '2' THEN oi.goods_id
WHEN '13' THEN oi.goods_id WHEN '13' THEN oi.goods_id
WHEN '14' THEN mspd.face_id
END AS face_id, END AS face_id,
CASE oi.goods_type CASE oi.goods_type
WHEN '0' THEN mvd.face_url WHEN '0' THEN mvd.face_url
WHEN '1' THEN msd.face_url WHEN '1' THEN msd.face_url
WHEN '2' THEN msd.face_url WHEN '2' THEN msd.face_url
WHEN '13' THEN msac.face_url WHEN '13' THEN msac.face_url
WHEN '14' THEN mspd.face_url
END AS face_url, END AS face_url,
CASE oi.goods_type CASE oi.goods_type
WHEN '0' THEN mvd.video_url WHEN '0' THEN mvd.video_url
@@ -161,6 +171,7 @@
WHEN '4' THEN mpa.url WHEN '4' THEN mpa.url
WHEN '5' THEN mpl.url WHEN '5' THEN mpl.url
WHEN '13' THEN msac.url WHEN '13' THEN msac.url
WHEN '14' THEN mspd.url
END AS imgUrl END AS imgUrl
FROM order_item oi FROM order_item oi
LEFT JOIN `order` o ON oi.order_id = o.id LEFT JOIN `order` o ON oi.order_id = o.id
@@ -170,6 +181,7 @@
LEFT JOIN member_photo_data mpd ON oi.goods_id = mpd.id AND mpd.type = oi.goods_type LEFT JOIN member_photo_data mpd ON oi.goods_id = mpd.id AND mpd.type = oi.goods_type
LEFT JOIN member_aio_photo_data mpa ON oi.goods_id = mpa.id AND mpa.type = oi.goods_type LEFT JOIN member_aio_photo_data mpa ON oi.goods_id = mpa.id AND mpa.type = oi.goods_type
LEFT JOIN member_plog_data mpl ON (oi.goods_id = mpl.id OR oi.goods_id = mpl.scenic_id) AND mpl.type = oi.goods_type AND o.face_id = mpl.face_id LEFT JOIN member_plog_data mpl ON (oi.goods_id = mpl.id OR oi.goods_id = mpl.scenic_id) AND mpl.type = oi.goods_type AND o.face_id = mpl.face_id
LEFT JOIN member_single_photo_data mspd ON oi.goods_id = mspd.source_id AND o.face_id = mspd.face_id AND oi.goods_type = 14
WHERE oi.order_id = #{id}; WHERE oi.order_id = #{id};
</select> </select>