Compare commits
14 Commits
059d6edc12
...
fcbe4762b3
| Author | SHA1 | Date | |
|---|---|---|---|
| fcbe4762b3 | |||
| e750adcc94 | |||
|
|
b58b8df88f | ||
|
|
c09f734a30 | ||
| 1464689657 | |||
| 9ae1626309 | |||
| 70a41bdfbc | |||
|
|
8757db4f3d | ||
|
|
a8e3304db2 | ||
|
|
26f2299381 | ||
| c1a5799da7 | |||
| 94c0e81335 | |||
| b9641474ba | |||
|
|
db1048d875 |
@@ -0,0 +1,9 @@
|
||||
package com.ai.da.common.constant;
|
||||
|
||||
public class AffiliateConstants {
|
||||
public static final String STATUS_ACTIVE = "Active";
|
||||
public static final String STATUS_INACTIVE = "Inactive";
|
||||
public static final String STATUS_DELETE = "Delete";
|
||||
public static final Integer DELETED = 1;
|
||||
public static final Integer NOT_DELETED = 0;
|
||||
}
|
||||
@@ -122,7 +122,7 @@ public class PaymentTask {
|
||||
|
||||
@Scheduled(cron = "0 */5 * * * *") // Run every 5 minutes
|
||||
public void calcCouponsCommission(){
|
||||
log.info("优惠券佣金计算定时器");
|
||||
// log.info("优惠券佣金计算定时器");
|
||||
affiliateService.calcCouponsCommission();
|
||||
}
|
||||
|
||||
|
||||
@@ -7,6 +7,7 @@ import com.ai.da.mapper.primary.entity.Account;
|
||||
import com.ai.da.mapper.primary.entity.SubscriptionInfo;
|
||||
import com.ai.da.service.StripeService;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||
import io.netty.util.internal.StringUtil;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
@@ -45,6 +46,11 @@ public class SubscriptionReminderTask {
|
||||
log.warn("未知的订阅类型: {}", subscriptionInfo.getType());
|
||||
continue;
|
||||
}
|
||||
String emailType = subscriptionInfo.getStatus().equals("active") ? "reminder_subscriber" : subscriptionInfo.getStatus().equals("canceled") ? "reminder_expire" : null;
|
||||
if (StringUtil.isNullOrEmpty(emailType)) {
|
||||
log.warn("未知订阅状态:{}", subscriptionInfo.getStatus());
|
||||
continue;
|
||||
}
|
||||
|
||||
boolean success = stripeService.sendEmail(subscriptionInfo.getSubscriptionId(), "reminder_subscriber", null);
|
||||
if (success) {
|
||||
@@ -78,7 +84,7 @@ public class SubscriptionReminderTask {
|
||||
QueryWrapper<SubscriptionInfo> qw = new QueryWrapper<>();
|
||||
qw.ge("current_period_end", startTimestamp);
|
||||
qw.lt("current_period_end", endTimestamp);
|
||||
qw.eq("status", "active");
|
||||
// qw.eq("status", "active");
|
||||
qw.eq("subscription_type", subscriptionType);
|
||||
|
||||
return subscriptionInfoMapper.selectList(qw);
|
||||
|
||||
@@ -840,6 +840,18 @@ public class SendEmailUtil {
|
||||
templateUser.setTemplateID(156074L);
|
||||
}
|
||||
break;
|
||||
case "reminder_expire":
|
||||
if (language.equals("ENGLISH")) {
|
||||
user.setSubject("[Code-Create] AiDA account is about to expire");
|
||||
templateUser.setTemplateID(156749L);
|
||||
} else if (language.equals("CHINESE")){
|
||||
user.setSubject("[Code-Create] 您的AiDA账号即将到期");
|
||||
templateUser.setTemplateID(156750L);
|
||||
} else {
|
||||
user.setSubject("[Code-Create] 您的AiDA帳號即將到期");
|
||||
templateUser.setTemplateID(156751L);
|
||||
}
|
||||
break;
|
||||
case "reminder_trial":
|
||||
if (language.equals("ENGLISH")) {
|
||||
user.setSubject("[Code-Create] AiDA — Free Trial Ending");
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package com.ai.da.service.impl;
|
||||
|
||||
import com.ai.da.common.config.exception.BusinessException;
|
||||
import com.ai.da.common.constant.AffiliateConstants;
|
||||
import com.ai.da.common.constant.CommonConstant;
|
||||
import com.ai.da.common.context.UserContext;
|
||||
import com.ai.da.common.response.PageBaseResponse;
|
||||
@@ -200,29 +201,69 @@ public class AffiliateServiceImpl extends ServiceImpl<AffiliateMapper, Affiliate
|
||||
return true;
|
||||
}
|
||||
|
||||
public void editAffiliate(Long id, Float commission, String operationType){
|
||||
public void editAffiliate(Long id, Float commission, String operationType) {
|
||||
// 参数验证
|
||||
if (id == null) {
|
||||
throw new BusinessException("affiliate.id.cannot.be.null");
|
||||
}
|
||||
|
||||
Affiliate affiliate = baseMapper.selectById(id);
|
||||
if (Objects.isNull(affiliate)){
|
||||
log.info("未知affiliate id :{}", id);
|
||||
throw new BusinessException("unknown affiliate");
|
||||
}
|
||||
if (!Objects.equals(affiliate.getCommissionPercent(), commission)){
|
||||
affiliate.setCommissionPercent(commission);
|
||||
if (affiliate == null) {
|
||||
log.warn("未知affiliate id: {}", id); // 使用warn级别更合适
|
||||
throw new BusinessException("unknown.affiliate");
|
||||
}
|
||||
|
||||
// operationType Active -> 激活 | Inactive -> 关闭 | Delete -> 删除
|
||||
// 构建更新条件
|
||||
UpdateWrapper<Affiliate> updateWrapper = buildUpdateWrapper(affiliate, commission, operationType);
|
||||
baseMapper.update(null, updateWrapper);
|
||||
}
|
||||
|
||||
private UpdateWrapper<Affiliate> buildUpdateWrapper(Affiliate affiliate, Float commission, String operationType) {
|
||||
UpdateWrapper<Affiliate> updateWrapper = new UpdateWrapper<>();
|
||||
updateWrapper.lambda()
|
||||
.eq(Affiliate::getId, affiliate.getId())
|
||||
.set(Affiliate::getUpdateTime, LocalDateTime.now());
|
||||
|
||||
// 处理佣金更新
|
||||
handleCommissionUpdate(affiliate, commission, updateWrapper);
|
||||
|
||||
// 处理操作类型
|
||||
if (!StringUtil.isNullOrEmpty(operationType)) {
|
||||
if (operationType.equals("Delete") || operationType.equals("Active") || operationType.equals("Inactive")) {
|
||||
affiliate.setStatus(operationType);
|
||||
} else {
|
||||
throw new BusinessException("unknown.operationType");
|
||||
}
|
||||
handleOperationType(affiliate, operationType, updateWrapper);
|
||||
}
|
||||
affiliate.setUpdateTime(LocalDateTime.now());
|
||||
baseMapper.updateById(affiliate);
|
||||
|
||||
if (operationType.equals("Delete")) {
|
||||
baseMapper.deleteById(id);
|
||||
return updateWrapper;
|
||||
}
|
||||
|
||||
private void handleCommissionUpdate(Affiliate affiliate, Float commission,
|
||||
UpdateWrapper<Affiliate> updateWrapper) {
|
||||
if (commission != null && !Objects.equals(affiliate.getCommissionPercent(), commission)) {
|
||||
updateWrapper.lambda().set(Affiliate::getCommissionPercent, commission);
|
||||
}
|
||||
}
|
||||
|
||||
private void handleOperationType(Affiliate affiliate, String operationType,
|
||||
UpdateWrapper<Affiliate> updateWrapper) {
|
||||
switch (operationType) {
|
||||
case AffiliateConstants.STATUS_DELETE:
|
||||
updateWrapper.lambda()
|
||||
.set(Affiliate::getStatus, AffiliateConstants.STATUS_DELETE)
|
||||
.set(Affiliate::getIsDeleted, AffiliateConstants.DELETED);
|
||||
break;
|
||||
|
||||
case AffiliateConstants.STATUS_ACTIVE:
|
||||
case AffiliateConstants.STATUS_INACTIVE:
|
||||
updateWrapper.lambda().set(Affiliate::getStatus, operationType);
|
||||
// 激活时生成链接
|
||||
if (AffiliateConstants.STATUS_ACTIVE.equals(operationType) &&
|
||||
StringUtil.isNullOrEmpty(affiliate.getLink())) {
|
||||
updateWrapper.lambda().set(Affiliate::getLink,
|
||||
CommonConstant.AFFILIATE_LINK + affiliate.getId());
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
throw new BusinessException("unknown.operationType");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -60,7 +60,7 @@ import java.util.stream.Collectors;
|
||||
@RequiredArgsConstructor
|
||||
public class CollectionElementServiceImpl extends ServiceImpl<CollectionElementMapper, CollectionElement> implements CollectionElementService {
|
||||
private final CollectionElementMapper collectionElementMapper;
|
||||
private final EmailService emailService;
|
||||
// private final EmailService emailService;
|
||||
private final FileProperties fileProperties;
|
||||
private final GenerateMapper generateMapper;
|
||||
private final GenerateDetailMapper generateDetailMapper;
|
||||
|
||||
@@ -19,6 +19,7 @@ public class DesignItemDetailPrintServiceImpl extends ServiceImpl<DesignItemDeta
|
||||
QueryWrapper<DesignItemDetailPrint> queryWrapper = new QueryWrapper<>();
|
||||
queryWrapper.eq("design_item_detail_id", designItemDetailId);
|
||||
queryWrapper.eq("print_type", printType);
|
||||
queryWrapper.eq("is_deleted", 0);
|
||||
|
||||
return baseMapper.selectList(queryWrapper);
|
||||
}
|
||||
|
||||
@@ -65,6 +65,7 @@ public class DesignItemDetailServiceImpl extends ServiceImpl<DesignItemDetailMap
|
||||
public List<DesignItemDetail> selectByDesignItemId(Long designItemId) {
|
||||
QueryWrapper<DesignItemDetail> queryWrapper = new QueryWrapper<>();
|
||||
queryWrapper.eq("design_item_id", designItemId);
|
||||
queryWrapper.eq("is_deleted", 0);
|
||||
return designItemDetailMapper.selectList(queryWrapper);
|
||||
}
|
||||
|
||||
|
||||
@@ -23,6 +23,7 @@ import com.alibaba.fastjson.JSON;
|
||||
import com.alibaba.fastjson.JSONArray;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.fasterxml.jackson.databind.SerializationFeature;
|
||||
@@ -288,25 +289,48 @@ public class DesignItemServiceImpl extends ServiceImpl<DesignItemMapper, DesignI
|
||||
response.setDesignItemUrl(url);
|
||||
//更新item
|
||||
updateById(designItem);
|
||||
//删除itemDetail
|
||||
designItemDetailService.deleteByDesignItemId(designItemId);
|
||||
|
||||
// 查询现有的记录,用于 saveOrUpdate
|
||||
List<DesignItemDetail> existingDetails = designItemDetailService.selectByDesignItemId(designItemId);
|
||||
// 创建 Map,以 priority 为 key,方便快速查找
|
||||
Map<Integer, DesignItemDetail> existingDetailMap = existingDetails.stream()
|
||||
.filter(detail -> Objects.nonNull(detail.getPriority()))
|
||||
.collect(Collectors.toMap(DesignItemDetail::getPriority, detail -> detail, (old, newVal) -> old));
|
||||
Map<String, Deque<DesignItemDetail>> detailBuckets = buildDetailTypeBuckets(existingDetails);
|
||||
Set<Long> reusedDetailIds = new HashSet<>();
|
||||
|
||||
List<DesignItemDetail> designItemDetails = Lists.newArrayList();
|
||||
pythonObjects.getObjects().get(0).getItems().forEach(detail -> {
|
||||
if (null == detail) {
|
||||
return;
|
||||
}
|
||||
DesignItemDetail designItemDetail = CopyUtil.copyObject(detail, DesignItemDetail.class);
|
||||
Integer priority = SysFileLevel2TypeEnum.BODY.getRealName().equals(detail.getType()) ? 0 : detail.getPriority();
|
||||
|
||||
DesignItemDetail designItemDetail = reuseDesignItemDetail(priority, detail.getType(),
|
||||
existingDetailMap, detailBuckets, reusedDetailIds);
|
||||
if (Objects.nonNull(designItemDetail)) {
|
||||
designItemDetail.setUpdateDate(DateUtil.getByTimeZone(timeZone));
|
||||
} else {
|
||||
designItemDetail = new DesignItemDetail();
|
||||
designItemDetail.setCreateDate(DateUtil.getByTimeZone(timeZone));
|
||||
}
|
||||
|
||||
// 设置/更新字段
|
||||
designItemDetail.setAccountId(userInfo.getId());
|
||||
designItemDetail.setDesignId(designId);
|
||||
designItemDetail.setDesignItemId(designItemId);
|
||||
designItemDetail.setCollectionElementId(detail.getElementId());
|
||||
designItemDetail.setCreateDate(DateUtil.getByTimeZone(timeZone));
|
||||
designItemDetail.setType(detail.getType());
|
||||
designItemDetail.setPriority(priority);
|
||||
if (SysFileLevel2TypeEnum.BODY.getRealName().equals(detail.getType())) {
|
||||
designItemDetail.setPath(detail.getBody_path());
|
||||
//BODY不关联businessId
|
||||
designItemDetail.setBusinessId(0L);
|
||||
} else {
|
||||
// 非BODY类型使用path字段
|
||||
designItemDetail.setPath(detail.getPath());
|
||||
}
|
||||
designItemDetail.setColor(detail.getColor());
|
||||
designItemDetail.setIconPath(detail.getIcon());
|
||||
// todo
|
||||
DesignPythonItemPrint printObject = detail.getPrint().getSingle();
|
||||
@@ -314,7 +338,19 @@ public class DesignItemServiceImpl extends ServiceImpl<DesignItemMapper, DesignI
|
||||
designItemDetail.setPrintJson(JSON.toJSONString(printObject));
|
||||
designItemDetails.add(designItemDetail);
|
||||
});
|
||||
designItemDetailService.saveBatch(designItemDetails);
|
||||
|
||||
// 逻辑删除未复用的旧记录
|
||||
existingDetails.stream()
|
||||
.filter(existingDetail -> Objects.nonNull(existingDetail.getId()) && !reusedDetailIds.contains(existingDetail.getId()))
|
||||
.forEach(existingDetail -> {
|
||||
UpdateWrapper<DesignItemDetail> updateWrapper = new UpdateWrapper<>();
|
||||
updateWrapper.eq("id", existingDetail.getId());
|
||||
updateWrapper.set("is_deleted", (byte) 1);
|
||||
updateWrapper.set("update_date", DateUtil.getByTimeZone(timeZone));
|
||||
designItemDetailService.update(null, updateWrapper);
|
||||
});
|
||||
|
||||
designItemDetailService.saveOrUpdateBatch(designItemDetails);
|
||||
//封装item信息
|
||||
List<DesignCollectionItemVO> designCollectionItems = CopyUtil.copyList(getByDesignId(designId)
|
||||
, DesignCollectionItemVO.class, (o, d) -> {
|
||||
@@ -343,27 +379,49 @@ public class DesignItemServiceImpl extends ServiceImpl<DesignItemMapper, DesignI
|
||||
// 1、更新designItem
|
||||
// updateById(designItem);
|
||||
updateDesignItem(designItem);
|
||||
// 2、删除designItemDetail(逻辑删除)
|
||||
designItemDetailService.deleteByDesignItemId(designItemId);
|
||||
|
||||
// 2、查询现有的记录,用于 saveOrUpdate
|
||||
List<DesignItemDetail> existingDetails = designItemDetailService.selectByDesignItemId(designItemId);
|
||||
// 创建 Map,以 priority 为 key,方便快速查找
|
||||
Map<Integer, DesignItemDetail> existingDetailMap = existingDetails.stream()
|
||||
.filter(detail -> Objects.nonNull(detail.getPriority()))
|
||||
.collect(Collectors.toMap(DesignItemDetail::getPriority, detail -> detail, (old, newVal) -> old));
|
||||
Map<String, Deque<DesignItemDetail>> detailBuckets = buildDetailTypeBuckets(existingDetails);
|
||||
Set<Long> reusedDetailIds = new HashSet<>();
|
||||
|
||||
List<DesignItemDetail> designItemDetails = Lists.newArrayList();
|
||||
// 3、保存新的designItemDetail
|
||||
// 3、保存新的designItemDetail(使用 saveOrUpdate 方式)
|
||||
pythonObjects.getObjects().get(0).getItems().forEach(detail -> {
|
||||
if (null == detail) {
|
||||
return;
|
||||
}
|
||||
DesignItemDetail designItemDetail = CopyUtil.copyObject(detail, DesignItemDetail.class);
|
||||
Integer priority = SysFileLevel2TypeEnum.BODY.getRealName().equals(detail.getType()) ? 0 : detail.getPriority();
|
||||
|
||||
DesignItemDetail designItemDetail = reuseDesignItemDetail(priority, detail.getType(),
|
||||
existingDetailMap, detailBuckets, reusedDetailIds);
|
||||
if (Objects.nonNull(designItemDetail)) {
|
||||
designItemDetail.setUpdateDate(DateUtil.getByTimeZone(timeZone));
|
||||
} else {
|
||||
designItemDetail = new DesignItemDetail();
|
||||
designItemDetail.setCreateDate(DateUtil.getByTimeZone(timeZone));
|
||||
}
|
||||
|
||||
// 设置/更新字段
|
||||
designItemDetail.setAccountId(userId);
|
||||
designItemDetail.setDesignId(designId);
|
||||
designItemDetail.setDesignItemId(designItemId);
|
||||
designItemDetail.setCollectionElementId(detail.getElementId());
|
||||
designItemDetail.setPriority(detail.getPriority());
|
||||
designItemDetail.setCreateDate(DateUtil.getByTimeZone(timeZone));
|
||||
designItemDetail.setType(detail.getType());
|
||||
designItemDetail.setPriority(priority);
|
||||
if (SysFileLevel2TypeEnum.BODY.getRealName().equals(detail.getType())) {
|
||||
designItemDetail.setPath(detail.getBody_path());
|
||||
//BODY不关联businessId
|
||||
designItemDetail.setBusinessId(0L);
|
||||
designItemDetail.setPriority(0);
|
||||
} else {
|
||||
// 非BODY类型使用path字段
|
||||
designItemDetail.setPath(detail.getPath());
|
||||
}
|
||||
designItemDetail.setColor(detail.getColor());
|
||||
designItemDetail.setIconPath(detail.getIcon());
|
||||
// designItemDetail.setUndividedLayer(priorityAndUndividedLayer.get(detail.getType().toLowerCase()));
|
||||
if (!detail.getType().equals("Body")) {
|
||||
@@ -380,12 +438,24 @@ public class DesignItemServiceImpl extends ServiceImpl<DesignItemMapper, DesignI
|
||||
designItemDetail.setPartialDesign(Objects.isNull(detail.getPrint()) ? null : detail.getPrint().getPartial());
|
||||
designItemDetails.add(designItemDetail);
|
||||
});
|
||||
// businessId 来自t_sys_file或者t_library
|
||||
designItemDetailService.saveBatch(designItemDetails);
|
||||
|
||||
// 4、保存印花信息到designItemDetailPrint
|
||||
// 逻辑删除未复用的旧记录
|
||||
existingDetails.stream()
|
||||
.filter(existingDetail -> Objects.nonNull(existingDetail.getId()) && !reusedDetailIds.contains(existingDetail.getId()))
|
||||
.forEach(existingDetail -> {
|
||||
UpdateWrapper<DesignItemDetail> updateWrapper = new UpdateWrapper<>();
|
||||
updateWrapper.eq("id", existingDetail.getId());
|
||||
updateWrapper.set("is_deleted", (byte) 1);
|
||||
updateWrapper.set("update_date", DateUtil.getByTimeZone(timeZone));
|
||||
designItemDetailService.update(null, updateWrapper);
|
||||
});
|
||||
|
||||
// businessId 来自t_sys_file或者t_library
|
||||
designItemDetailService.saveOrUpdateBatch(designItemDetails);
|
||||
|
||||
// 4、保存印花信息到designItemDetailPrint(使用 saveOrUpdate 方式)
|
||||
List<DesignItemDetailPrint> designItemDetailPrints = setDesignItemDetailPrintList(designItemDetails, designSingleItemDTOList, timeZone);
|
||||
designItemDetailPrintService.saveBatch(designItemDetailPrints);
|
||||
designItemDetailPrintService.saveOrUpdateBatch(designItemDetailPrints);
|
||||
|
||||
// 5、覆盖designPythonOutfit表中的模特全身图
|
||||
TDesignPythonOutfit designPythonOutfit = new TDesignPythonOutfit();
|
||||
@@ -394,10 +464,16 @@ public class DesignItemServiceImpl extends ServiceImpl<DesignItemMapper, DesignI
|
||||
designPythonOutfit.setUpdateDate(LocalDateTime.now(ZoneId.of(timeZone)));
|
||||
designPythonOutfitService.updateById(designPythonOutfit);
|
||||
|
||||
// 6、删除designPythonOutfitDetail表中原始的图层信息(逻辑删除)
|
||||
designPythonOutfitDetailService.deleteByDesignPythonOutfitIdLogical(designPythonOutfit.getId());
|
||||
// 6、查询现有的图层信息,用于 saveOrUpdate
|
||||
List<TDesignPythonOutfitDetail> existingLayers = designPythonOutfitDetailService.getDetailByDesignPythonOutfitId(designPythonOutfit.getId());
|
||||
// 创建 Map,以 priority 为 key,方便快速查找
|
||||
Map<Integer, TDesignPythonOutfitDetail> existingLayerMap = existingLayers.stream()
|
||||
.filter(layer -> Objects.nonNull(layer.getPriority()))
|
||||
.collect(Collectors.toMap(layer -> Math.abs(layer.getPriority()), layer -> layer, (old, newVal) -> old));
|
||||
Map<String, Deque<TDesignPythonOutfitDetail>> layerBuckets = buildOutfitCategoryBuckets(existingLayers);
|
||||
Set<Long> reusedLayerIds = new HashSet<>();
|
||||
|
||||
// 7、将新生成的图层信息存入designPythonOutfitDetail表
|
||||
// 7、将新生成的图层信息存入designPythonOutfitDetail表(使用 saveOrUpdate 方式)
|
||||
JSONArray layers = outfit.getJSONArray("layers");
|
||||
|
||||
Map<Integer, List<Long>> priorityOffset = null;
|
||||
@@ -405,9 +481,50 @@ public class DesignItemServiceImpl extends ServiceImpl<DesignItemMapper, DesignI
|
||||
priorityOffset = designSingleItemDTOList.stream()
|
||||
.collect(Collectors.toMap(DesignSingleItemDTO::getPriority, DesignSingleItemDTO::getOffset));
|
||||
}
|
||||
List<TDesignPythonOutfitDetail> list = setTDesignPythonOutfitDetailList(layers, designId, designPythonOutfit.getId(), userId, priorityOffset);
|
||||
List<TDesignPythonOutfitDetail> list = new ArrayList<>();
|
||||
for (int i = 0; i < layers.size(); i++) {
|
||||
JSONObject jsonObject = layers.getJSONObject(i);
|
||||
Integer priority = (Integer) jsonObject.get("priority");
|
||||
|
||||
designPythonOutfitDetailService.saveBatch(list);
|
||||
TDesignPythonOutfitDetail designPythonOutfitDetail = reuseOutfitDetail(priority,
|
||||
jsonObject.getString("image_category"), existingLayerMap, layerBuckets, reusedLayerIds);
|
||||
if (Objects.nonNull(designPythonOutfitDetail)) {
|
||||
designPythonOutfitDetail.setUpdateDate(LocalDateTime.now(ZoneId.of(timeZone)));
|
||||
} else {
|
||||
designPythonOutfitDetail = new TDesignPythonOutfitDetail();
|
||||
designPythonOutfitDetail.setCreateDate(LocalDateTime.now(ZoneId.of(timeZone)));
|
||||
}
|
||||
|
||||
// 设置/更新字段
|
||||
designPythonOutfitDetail.setDesignId(designId);
|
||||
designPythonOutfitDetail.setDesignPythonOutfitId(designPythonOutfit.getId());
|
||||
designPythonOutfitDetail.setPosition(jsonObject.getString("position"));
|
||||
designPythonOutfitDetail.setImageUrl(jsonObject.getString("image_url"));
|
||||
designPythonOutfitDetail.setImageSize(jsonObject.getString("image_size"));
|
||||
designPythonOutfitDetail.setImageCategory(jsonObject.getString("image_category"));
|
||||
designPythonOutfitDetail.setMaskUrl(jsonObject.getString("mask_url"));
|
||||
designPythonOutfitDetail.setScale(Objects.isNull(jsonObject.getString("resize_scale")) ? "1.0" : jsonObject.getString("resize_scale"));
|
||||
designPythonOutfitDetail.setUserId(userId);
|
||||
if (priorityOffset != null && !priorityOffset.isEmpty()){
|
||||
designPythonOutfitDetail.setOffset(String.valueOf(priorityOffset.get(Math.abs(priority))));
|
||||
}
|
||||
designPythonOutfitDetail.setPriority(priority);
|
||||
|
||||
list.add(designPythonOutfitDetail);
|
||||
}
|
||||
|
||||
// 逻辑删除未复用的旧记录
|
||||
existingLayers.stream()
|
||||
.filter(existingLayer -> Objects.nonNull(existingLayer.getId()) && !reusedLayerIds.contains(existingLayer.getId()))
|
||||
.forEach(existingLayer -> {
|
||||
UpdateWrapper<TDesignPythonOutfitDetail> updateWrapper = new UpdateWrapper<>();
|
||||
updateWrapper.eq("id", existingLayer.getId());
|
||||
updateWrapper.set("is_deleted", 1);
|
||||
updateWrapper.set("update_date", LocalDateTime.now(ZoneId.of(timeZone)));
|
||||
designPythonOutfitDetailService.update(null, updateWrapper);
|
||||
});
|
||||
|
||||
designPythonOutfitDetailService.saveOrUpdateBatch(list);
|
||||
|
||||
return list;
|
||||
}
|
||||
@@ -445,6 +562,112 @@ public class DesignItemServiceImpl extends ServiceImpl<DesignItemMapper, DesignI
|
||||
return list;
|
||||
}
|
||||
|
||||
private Map<String, Deque<DesignItemDetail>> buildDetailTypeBuckets(List<DesignItemDetail> details) {
|
||||
return details.stream()
|
||||
.collect(Collectors.groupingBy(DesignItemDetail::getType,
|
||||
Collectors.collectingAndThen(Collectors.toList(), list -> {
|
||||
list.sort(Comparator
|
||||
.comparingInt(this::extractDetailPriorityForSort)
|
||||
.thenComparing(DesignItemDetail::getId, Comparator.nullsLast(Long::compareTo)));
|
||||
return new ArrayDeque<>(list);
|
||||
})));
|
||||
}
|
||||
|
||||
private DesignItemDetail reuseDesignItemDetail(Integer priority, String type,
|
||||
Map<Integer, DesignItemDetail> priorityMap,
|
||||
Map<String, Deque<DesignItemDetail>> typeBuckets,
|
||||
Set<Long> reusedIds) {
|
||||
DesignItemDetail reused = null;
|
||||
if (Objects.nonNull(priority)) {
|
||||
reused = priorityMap.remove(priority);
|
||||
}
|
||||
if (Objects.nonNull(reused)) {
|
||||
markReusedDetail(reused, reusedIds);
|
||||
return reused;
|
||||
}
|
||||
Deque<DesignItemDetail> bucket = typeBuckets.get(type);
|
||||
while (bucket != null && !bucket.isEmpty()) {
|
||||
DesignItemDetail candidate = bucket.pollFirst();
|
||||
if (markReusedDetail(candidate, reusedIds)) {
|
||||
Integer candidatePriority = candidate.getPriority();
|
||||
if (Objects.nonNull(candidatePriority)) {
|
||||
priorityMap.remove(candidatePriority, candidate);
|
||||
}
|
||||
return candidate;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private Map<String, Deque<TDesignPythonOutfitDetail>> buildOutfitCategoryBuckets(List<TDesignPythonOutfitDetail> details) {
|
||||
return details.stream()
|
||||
.collect(Collectors.groupingBy(TDesignPythonOutfitDetail::getImageCategory,
|
||||
Collectors.collectingAndThen(Collectors.toList(), list -> {
|
||||
list.sort(Comparator
|
||||
.comparingInt(this::extractOutfitPriorityForSort)
|
||||
.thenComparing(TDesignPythonOutfitDetail::getId, Comparator.nullsLast(Long::compareTo)));
|
||||
return new ArrayDeque<>(list);
|
||||
})));
|
||||
}
|
||||
|
||||
private TDesignPythonOutfitDetail reuseOutfitDetail(Integer priority, String imageCategory,
|
||||
Map<Integer, TDesignPythonOutfitDetail> priorityMap,
|
||||
Map<String, Deque<TDesignPythonOutfitDetail>> categoryBuckets,
|
||||
Set<Long> reusedIds) {
|
||||
TDesignPythonOutfitDetail reused = null;
|
||||
if (Objects.nonNull(priority)) {
|
||||
reused = priorityMap.remove(Math.abs(priority));
|
||||
}
|
||||
if (Objects.nonNull(reused)) {
|
||||
markReusedLayer(reused, reusedIds);
|
||||
return reused;
|
||||
}
|
||||
Deque<TDesignPythonOutfitDetail> bucket = categoryBuckets.get(imageCategory);
|
||||
while (bucket != null && !bucket.isEmpty()) {
|
||||
TDesignPythonOutfitDetail candidate = bucket.pollFirst();
|
||||
if (markReusedLayer(candidate, reusedIds)) {
|
||||
Integer candidatePriority = candidate.getPriority();
|
||||
if (Objects.nonNull(candidatePriority)) {
|
||||
priorityMap.remove(Math.abs(candidatePriority), candidate);
|
||||
}
|
||||
return candidate;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private boolean markReusedDetail(DesignItemDetail detail, Set<Long> reusedIds) {
|
||||
if (Objects.isNull(detail)) {
|
||||
return false;
|
||||
}
|
||||
Long id = detail.getId();
|
||||
return Objects.isNull(id) || reusedIds.add(id);
|
||||
}
|
||||
|
||||
private boolean markReusedLayer(TDesignPythonOutfitDetail detail, Set<Long> reusedIds) {
|
||||
if (Objects.isNull(detail)) {
|
||||
return false;
|
||||
}
|
||||
Long id = detail.getId();
|
||||
return Objects.isNull(id) || reusedIds.add(id);
|
||||
}
|
||||
|
||||
private int safePriorityValue(Integer priority) {
|
||||
return Objects.isNull(priority) ? Integer.MAX_VALUE : priority;
|
||||
}
|
||||
|
||||
private int safeAbsPriorityValue(Integer priority) {
|
||||
return Objects.isNull(priority) ? Integer.MAX_VALUE : Math.abs(priority);
|
||||
}
|
||||
|
||||
private int extractDetailPriorityForSort(DesignItemDetail detail) {
|
||||
return safePriorityValue(detail.getPriority());
|
||||
}
|
||||
|
||||
private int extractOutfitPriorityForSort(TDesignPythonOutfitDetail detail) {
|
||||
return safeAbsPriorityValue(detail.getPriority());
|
||||
}
|
||||
|
||||
private DesignItem selectById(Long id) {
|
||||
QueryWrapper<DesignItem> queryWrapper = new QueryWrapper<>();
|
||||
queryWrapper.eq("id", id);
|
||||
@@ -929,7 +1152,6 @@ public class DesignItemServiceImpl extends ServiceImpl<DesignItemMapper, DesignI
|
||||
Map<Integer, Long> designItemDetailTypeIdMap,
|
||||
String timeZone) {
|
||||
|
||||
// todo 这边这样做对吗
|
||||
DesignSinglePrintDTO printObject;
|
||||
if (printType.equals("print")) {
|
||||
printObject = designSingleItem.getPrintObject();
|
||||
@@ -937,32 +1159,64 @@ public class DesignItemServiceImpl extends ServiceImpl<DesignItemMapper, DesignI
|
||||
printObject = designSingleItem.getTrims();
|
||||
}
|
||||
|
||||
Long designItemDetailId = designItemDetailTypeIdMap.get(designSingleItem.getPriority());
|
||||
|
||||
// 查询现有的记录,用于 saveOrUpdate
|
||||
List<DesignItemDetailPrint> existingPrints = designItemDetailPrintService.getByDesignItemDetailId(designItemDetailId, printType);
|
||||
// 创建 Map,以 priority 为 key,方便快速查找
|
||||
Map<Integer, DesignItemDetailPrint> existingPrintMap = existingPrints.stream()
|
||||
.collect(Collectors.toMap(DesignItemDetailPrint::getPriority, print -> print, (old, newVal) -> old));
|
||||
|
||||
// 收集新 print 的 priority,用于后续删除不存在的旧记录
|
||||
Set<Integer> newPrintPriorities = new HashSet<>();
|
||||
|
||||
if (!CollectionUtil.isEmpty(printObject.getPrints())) {
|
||||
// 2、有印花,添加到list
|
||||
// 处理新的印花列表
|
||||
printObject.getPrints().forEach(print -> {
|
||||
// 2.1 判断是否第一次添加印花,是:直接添加
|
||||
List<DesignItemDetailPrint> designItemDetailPrintList = designItemDetailPrintService.getByDesignItemDetailId(designItemDetailTypeIdMap.get(designSingleItem.getPriority()), printType);
|
||||
if (!designItemDetailPrintList.isEmpty()) {
|
||||
// 2.2 否:先删除原始印花,再添加新印花信息
|
||||
designItemDetailPrintService.deleteByDesignItemDetailId(designItemDetailTypeIdMap.get(designSingleItem.getPriority()));
|
||||
}
|
||||
setUriToMinioPath(print);
|
||||
|
||||
DesignItemDetailPrint designItemDetailPrint = new DesignItemDetailPrint();
|
||||
designItemDetailPrint.setDesignItemDetailId(designItemDetailTypeIdMap.get(designSingleItem.getPriority()));
|
||||
Integer priority = print.getPriority();
|
||||
newPrintPriorities.add(priority);
|
||||
|
||||
DesignItemDetailPrint designItemDetailPrint;
|
||||
// 如果存在相同 priority 的记录,则更新;否则创建新记录
|
||||
if (existingPrintMap.containsKey(priority)) {
|
||||
// 更新现有记录
|
||||
designItemDetailPrint = existingPrintMap.get(priority);
|
||||
designItemDetailPrint.setUpdateDate(LocalDateTime.now(ZoneId.of(timeZone)));
|
||||
} else {
|
||||
// 创建新记录
|
||||
designItemDetailPrint = new DesignItemDetailPrint();
|
||||
designItemDetailPrint.setCreateDate(LocalDateTime.now(ZoneId.of(timeZone)));
|
||||
}
|
||||
|
||||
// 设置/更新字段
|
||||
designItemDetailPrint.setDesignItemDetailId(designItemDetailId);
|
||||
designItemDetailPrint.setPrintType(printType);
|
||||
designItemDetailPrint.setLevel2Type(print.getLevel2Type());
|
||||
designItemDetailPrint.setPath(print.getMinIOPath());
|
||||
designItemDetailPrint.setScale(print.getScale().toString());
|
||||
designItemDetailPrint.setSingleOrOverall(printType.equals("print") ? print.getIfSingle() ? "single" : "overall" : "single");
|
||||
designItemDetailPrint.setCreateDate(LocalDateTime.now(ZoneId.of(timeZone)));
|
||||
// single、overall模式下都有position、angle和priority
|
||||
designItemDetailPrint.setPosition(print.getLocation().toString());
|
||||
designItemDetailPrint.setAngle(print.getAngle());
|
||||
designItemDetailPrint.setPriority(print.getPriority());
|
||||
designItemDetailPrint.setPriority(priority);
|
||||
|
||||
designItemDetailPrints.add(designItemDetailPrint);
|
||||
});
|
||||
}
|
||||
|
||||
// 逻辑删除不在新列表中的旧记录
|
||||
existingPrints.forEach(existingPrint -> {
|
||||
if (!newPrintPriorities.contains(existingPrint.getPriority())) {
|
||||
// 该记录不在新列表中,需要逻辑删除
|
||||
UpdateWrapper<DesignItemDetailPrint> updateWrapper = new UpdateWrapper<>();
|
||||
updateWrapper.eq("id", existingPrint.getId());
|
||||
updateWrapper.set("is_deleted", (byte) 1);
|
||||
updateWrapper.set("update_date", LocalDateTime.now(ZoneId.of(timeZone)));
|
||||
designItemDetailPrintService.update(null, updateWrapper);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// 对印花类型为Generate的图片路径进行特殊处理
|
||||
|
||||
@@ -730,7 +730,7 @@ public class EmailServiceImpl implements EmailService {
|
||||
jsonObject.put("quantity", quantity);
|
||||
jsonObject.put("totalFee", amount);
|
||||
|
||||
sendEmail(Arrays.asList(merchantEmail,developerEmail), jsonObject, CREDITS_PURCHASE_MERCHANT, "New Credit Purchase Order", null, null);
|
||||
sendEmail(Arrays.asList(merchantEmail, developerEmail), jsonObject, CREDITS_PURCHASE_MERCHANT, "New Credit Purchase Order", null, null);
|
||||
}
|
||||
|
||||
private final static String COMMON_EXCEPTION_REMINDER = "135279_common-exception-reminder.html";
|
||||
|
||||
@@ -402,21 +402,27 @@ public class MessageCenterServiceImpl extends ServiceImpl<NotificationMapper, No
|
||||
notification.setType("system");
|
||||
notification.setReceiverId(userId);
|
||||
if (isSuccess) {
|
||||
if (language.equals(Language.ENGLISH.name())) {
|
||||
sysNotificationDTO.setTitle("System Notification 系统通知");
|
||||
sysNotificationDTO.setContent("Your video generation task in Project " + projectName + " is ready!\n"
|
||||
+ "您在项目 " + projectName + " 中创建的视频生成任务已完成!");
|
||||
/*if (language.equals(Language.ENGLISH.name())) {
|
||||
sysNotificationDTO.setTitle("System Notification");
|
||||
sysNotificationDTO.setContent("Your video generation task in Project " + projectName + " is ready!");
|
||||
} else {
|
||||
sysNotificationDTO.setTitle("系统通知");
|
||||
sysNotificationDTO.setContent("您在项目 " + projectName + " 中创建的视频生成任务已完成!");
|
||||
}
|
||||
}*/
|
||||
} else {
|
||||
if (language.equals(Language.ENGLISH.name())) {
|
||||
sysNotificationDTO.setTitle("System Notification 系统通知");
|
||||
sysNotificationDTO.setContent("Your video generation task in Project " + projectName + " has failed.\n"
|
||||
+ "您在项目 " + projectName + " 中创建的视频生成任务失败。");
|
||||
/*if (language.equals(Language.ENGLISH.name())) {
|
||||
sysNotificationDTO.setTitle("System Notification");
|
||||
sysNotificationDTO.setContent("Your video generation task in Project " + projectName + " has failed.");
|
||||
} else {
|
||||
sysNotificationDTO.setTitle("系统通知");
|
||||
sysNotificationDTO.setContent("视频生成任务失败。");
|
||||
}
|
||||
}*/
|
||||
}
|
||||
notification.setContent(JSON.toJSONString(sysNotificationDTO));
|
||||
notification.setIsRead(0);
|
||||
|
||||
@@ -45,6 +45,7 @@ public class TDesignPythonOutfitDetailServiceImpl extends ServiceImpl<TDesignPyt
|
||||
public List<TDesignPythonOutfitDetail> getDetailByDesignPythonOutfitId(Long designPythonOutfitId) {
|
||||
QueryWrapper<TDesignPythonOutfitDetail> queryWrapper = new QueryWrapper<>();
|
||||
queryWrapper.eq("design_python_outfit_id", designPythonOutfitId);
|
||||
queryWrapper.eq("is_deleted", 0);
|
||||
|
||||
return baseMapper.selectList(queryWrapper);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user