Merge pull request 'v1.0.38' (#50) from dev into master
Reviewed-on: #50
This commit was merged in pull request #50.
This commit is contained in:
@@ -11,7 +11,7 @@
|
|||||||
|
|
||||||
<groupId>com.imyeyu.timiserverapi</groupId>
|
<groupId>com.imyeyu.timiserverapi</groupId>
|
||||||
<artifactId>TimiServerAPI</artifactId>
|
<artifactId>TimiServerAPI</artifactId>
|
||||||
<version>1.0.37</version>
|
<version>1.0.38</version>
|
||||||
<packaging>jar</packaging>
|
<packaging>jar</packaging>
|
||||||
<name>TimiServerAPI</name>
|
<name>TimiServerAPI</name>
|
||||||
<description>imyeyu.com API</description>
|
<description>imyeyu.com API</description>
|
||||||
|
|||||||
@@ -45,6 +45,11 @@ public enum CorePermissionCode implements BuiltinPermissionCode {
|
|||||||
TAG_UPDATE("TAG:UPDATE", "标签修改", false, true),
|
TAG_UPDATE("TAG:UPDATE", "标签修改", false, true),
|
||||||
TAG_DELETE("TAG:DELETE", "标签删除", false, true),
|
TAG_DELETE("TAG:DELETE", "标签删除", false, true),
|
||||||
|
|
||||||
|
ARTICLE_CREATE("ARTICLE:CREATE", "文章创建", false, true),
|
||||||
|
ARTICLE_READ("ARTICLE:READ", "文章读取", false, true),
|
||||||
|
ARTICLE_UPDATE("ARTICLE:UPDATE", "文章修改", false, true),
|
||||||
|
ARTICLE_DELETE("ARTICLE:DELETE", "文章删除", false, true),
|
||||||
|
|
||||||
USER_CREATE("USER:CREATE", "用户创建", false, true),
|
USER_CREATE("USER:CREATE", "用户创建", false, true),
|
||||||
USER_READ("USER:READ", "用户读取", false, true),
|
USER_READ("USER:READ", "用户读取", false, true),
|
||||||
USER_UPDATE("USER:UPDATE", "用户修改", false, true),
|
USER_UPDATE("USER:UPDATE", "用户修改", false, true),
|
||||||
|
|||||||
@@ -0,0 +1,95 @@
|
|||||||
|
package com.imyeyu.api.modules.common.controller;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonView;
|
||||||
|
import com.imyeyu.api.annotation.RequireCorePermission;
|
||||||
|
import com.imyeyu.api.bean.CorePermissionCode;
|
||||||
|
import com.imyeyu.api.modules.common.entity.Article;
|
||||||
|
import com.imyeyu.api.modules.common.entity.Attachment;
|
||||||
|
import com.imyeyu.api.modules.common.service.ArticleService;
|
||||||
|
import com.imyeyu.api.modules.common.service.AttachmentService;
|
||||||
|
import com.imyeyu.spring.annotation.AOPLog;
|
||||||
|
import com.imyeyu.spring.annotation.RequestRateLimit;
|
||||||
|
import com.imyeyu.spring.bean.Page;
|
||||||
|
import com.imyeyu.spring.bean.PageResult;
|
||||||
|
import com.imyeyu.spring.util.ResponseView;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.web.bind.annotation.PostMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RequestBody;
|
||||||
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RequestParam;
|
||||||
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
|
||||||
|
/// 文章接口
|
||||||
|
///
|
||||||
|
/// @author Codex
|
||||||
|
/// @since 2026-09-09
|
||||||
|
@Slf4j
|
||||||
|
@RestController
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
@RequestMapping("/article")
|
||||||
|
public class ArticleController {
|
||||||
|
|
||||||
|
private final ArticleService service;
|
||||||
|
private final AttachmentService attachmentService;
|
||||||
|
|
||||||
|
/// 查询文章列表
|
||||||
|
///
|
||||||
|
/// @param page 分页参数
|
||||||
|
/// @return 文章分页
|
||||||
|
@JsonView(ResponseView.Public.class)
|
||||||
|
@RequestRateLimit
|
||||||
|
@PostMapping("/list")
|
||||||
|
public PageResult<Article> list(@RequestBody Page<Article> page) {
|
||||||
|
return service.page(page);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 查询文章详情
|
||||||
|
///
|
||||||
|
/// @param id 文章 ID
|
||||||
|
/// @return 文章详情
|
||||||
|
@JsonView(ResponseView.Public.class)
|
||||||
|
@RequestRateLimit
|
||||||
|
@PostMapping("/detail")
|
||||||
|
public Article detail(@RequestParam String id) {
|
||||||
|
Article article = service.get(id);
|
||||||
|
article.setAttachmentList(attachmentService.listByBizId(Attachment.BizType.ARTICLE, article.getId()));
|
||||||
|
return article;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 创建文章
|
||||||
|
///
|
||||||
|
/// @param article 文章
|
||||||
|
/// @return 创建后的文章
|
||||||
|
@AOPLog
|
||||||
|
@JsonView(ResponseView.Public.class)
|
||||||
|
@RequestRateLimit
|
||||||
|
@RequireCorePermission(CorePermissionCode.ARTICLE_CREATE)
|
||||||
|
@PostMapping("/create")
|
||||||
|
public Article create(@RequestBody Article article) {
|
||||||
|
service.create(article);
|
||||||
|
return article;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 更新文章
|
||||||
|
///
|
||||||
|
/// @param article 文章
|
||||||
|
@AOPLog
|
||||||
|
@RequestRateLimit
|
||||||
|
@RequireCorePermission(CorePermissionCode.ARTICLE_UPDATE)
|
||||||
|
@PostMapping("/update")
|
||||||
|
public void update(@RequestBody Article article) {
|
||||||
|
service.update(article);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 删除文章
|
||||||
|
///
|
||||||
|
/// @param id 文章 ID
|
||||||
|
@AOPLog
|
||||||
|
@RequestRateLimit
|
||||||
|
@RequireCorePermission(CorePermissionCode.ARTICLE_DELETE)
|
||||||
|
@PostMapping("/delete")
|
||||||
|
public void delete(@RequestParam String id) {
|
||||||
|
service.delete(id);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -34,6 +34,8 @@ public class Article extends UUIDEntity implements SettingSupport {
|
|||||||
/// GAO 门店日记
|
/// GAO 门店日记
|
||||||
GAO_STORE_DIARY,
|
GAO_STORE_DIARY,
|
||||||
|
|
||||||
|
GAO_SYSTEM,
|
||||||
|
|
||||||
/// 反馈
|
/// 反馈
|
||||||
FEEDBACK
|
FEEDBACK
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -111,6 +111,8 @@ public enum GaoPermissionCode implements BuiltinPermissionCode {
|
|||||||
|
|
||||||
CUSTOMER_PACKAGE_PRICE_OVERRIDE("CUSTOMER_PACKAGE:PRICE_OVERRIDE", "客户套餐成交价和权益配额调整", true, true),
|
CUSTOMER_PACKAGE_PRICE_OVERRIDE("CUSTOMER_PACKAGE:PRICE_OVERRIDE", "客户套餐成交价和权益配额调整", true, true),
|
||||||
|
|
||||||
|
CUSTOMER_PACKAGE_GIFT_CREATE("CUSTOMER_PACKAGE:GIFT_CREATE", "客户套餐创建赠送", true, true),
|
||||||
|
|
||||||
FUND_RECORD_READ("FUND_RECORD:READ", "资金流水读取", true, true),
|
FUND_RECORD_READ("FUND_RECORD:READ", "资金流水读取", true, true),
|
||||||
|
|
||||||
FUND_RECEIVE_CREATE("FUND_RECEIVE:CREATE", "线下收款创建", true, true),
|
FUND_RECEIVE_CREATE("FUND_RECEIVE:CREATE", "线下收款创建", true, true),
|
||||||
|
|||||||
@@ -0,0 +1,27 @@
|
|||||||
|
package com.imyeyu.api.modules.gao.bean;
|
||||||
|
|
||||||
|
import com.imyeyu.api.annotation.SettingBizType;
|
||||||
|
import com.imyeyu.api.bean.SettingEnum;
|
||||||
|
import com.imyeyu.api.modules.common.entity.Setting;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Getter;
|
||||||
|
|
||||||
|
///
|
||||||
|
///
|
||||||
|
/// @author 夜雨
|
||||||
|
/// @since 2026-09-09 16:11
|
||||||
|
@Getter
|
||||||
|
@SettingBizType("GAO_SYSTEM")
|
||||||
|
@AllArgsConstructor
|
||||||
|
public enum GaoSystemSetting implements SettingEnum {
|
||||||
|
|
||||||
|
SERVICE_LICENSE(null, Setting.ValueType.STRING),
|
||||||
|
|
||||||
|
PRIVACY_LICENSE(null, Setting.ValueType.STRING),
|
||||||
|
|
||||||
|
OPEN_SOURCE_LICENSE(null, Setting.ValueType.STRING);
|
||||||
|
|
||||||
|
final String defaultValue;
|
||||||
|
|
||||||
|
final Setting.ValueType valueType;
|
||||||
|
}
|
||||||
@@ -1,8 +1,8 @@
|
|||||||
package com.imyeyu.api.modules.gao.controller;
|
package com.imyeyu.api.modules.gao.controller;
|
||||||
|
|
||||||
|
import com.imyeyu.api.bean.PermissionMatchMode;
|
||||||
import com.imyeyu.api.modules.gao.annotation.RequireGaoPermission;
|
import com.imyeyu.api.modules.gao.annotation.RequireGaoPermission;
|
||||||
import com.imyeyu.api.modules.gao.bean.GaoPermissionCode;
|
import com.imyeyu.api.modules.gao.bean.GaoPermissionCode;
|
||||||
import com.imyeyu.api.bean.PermissionMatchMode;
|
|
||||||
import com.imyeyu.api.modules.gao.entity.GaoFundRecord;
|
import com.imyeyu.api.modules.gao.entity.GaoFundRecord;
|
||||||
import com.imyeyu.api.modules.gao.entity.GaoSalesOrder;
|
import com.imyeyu.api.modules.gao.entity.GaoSalesOrder;
|
||||||
import com.imyeyu.api.modules.gao.service.GaoOrderPaymentService;
|
import com.imyeyu.api.modules.gao.service.GaoOrderPaymentService;
|
||||||
@@ -17,6 +17,8 @@ import com.imyeyu.api.modules.gao.vo.GaoOrderPaymentRevokeRequest;
|
|||||||
import com.imyeyu.api.modules.gao.vo.GaoSalesOrderCancelRequest;
|
import com.imyeyu.api.modules.gao.vo.GaoSalesOrderCancelRequest;
|
||||||
import com.imyeyu.api.modules.gao.vo.GaoSalesOrderPage;
|
import com.imyeyu.api.modules.gao.vo.GaoSalesOrderPage;
|
||||||
import com.imyeyu.api.modules.gao.vo.GaoSalesOrderUpdateRequest;
|
import com.imyeyu.api.modules.gao.vo.GaoSalesOrderUpdateRequest;
|
||||||
|
import com.imyeyu.api.modules.user.service.UserService;
|
||||||
|
import com.imyeyu.java.TimiJava;
|
||||||
import com.imyeyu.java.bean.timi.TimiException;
|
import com.imyeyu.java.bean.timi.TimiException;
|
||||||
import com.imyeyu.spring.annotation.AOPLog;
|
import com.imyeyu.spring.annotation.AOPLog;
|
||||||
import com.imyeyu.spring.annotation.RequestRateLimit;
|
import com.imyeyu.spring.annotation.RequestRateLimit;
|
||||||
@@ -40,6 +42,7 @@ public class GaoSalesOrderController {
|
|||||||
private final GaoSalesOrderService service;
|
private final GaoSalesOrderService service;
|
||||||
private final GaoOrderPaymentService paymentService;
|
private final GaoOrderPaymentService paymentService;
|
||||||
private final GaoStoreScopeService storeScopeService;
|
private final GaoStoreScopeService storeScopeService;
|
||||||
|
private final UserService userService;
|
||||||
|
|
||||||
@AOPLog
|
@AOPLog
|
||||||
@RequestRateLimit
|
@RequestRateLimit
|
||||||
@@ -56,7 +59,11 @@ public class GaoSalesOrderController {
|
|||||||
@RequireGaoPermission(GaoPermissionCode.SALES_ORDER_READ)
|
@RequireGaoPermission(GaoPermissionCode.SALES_ORDER_READ)
|
||||||
@PostMapping("/detail")
|
@PostMapping("/detail")
|
||||||
public GaoSalesOrder detail(@RequestParam String id) {
|
public GaoSalesOrder detail(@RequestParam String id) {
|
||||||
return service.detail(id);
|
GaoSalesOrder result = service.detail(id);
|
||||||
|
if (TimiJava.isNotEmpty(result.getCancelOperatorUserId())) {
|
||||||
|
result.setCancelOperator(userService.get(result.getCancelOperatorUserId()));
|
||||||
|
}
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@AOPLog
|
@AOPLog
|
||||||
|
|||||||
@@ -34,6 +34,9 @@ public class GaoSalesOrderItem extends UUIDEntity {
|
|||||||
/// 订单项类型
|
/// 订单项类型
|
||||||
private ItemType itemType;
|
private ItemType itemType;
|
||||||
|
|
||||||
|
/// true 为赠送权益
|
||||||
|
private Boolean gifted;
|
||||||
|
|
||||||
/// SKU ID
|
/// SKU ID
|
||||||
private String skuId;
|
private String skuId;
|
||||||
|
|
||||||
|
|||||||
+57
-7
@@ -4,6 +4,7 @@ import com.imyeyu.api.bean.ModuleCode;
|
|||||||
import com.imyeyu.api.config.dbsource.TimiServerDBConfig;
|
import com.imyeyu.api.config.dbsource.TimiServerDBConfig;
|
||||||
import com.imyeyu.api.modules.common.entity.Attachment;
|
import com.imyeyu.api.modules.common.entity.Attachment;
|
||||||
import com.imyeyu.api.modules.common.service.AttachmentService;
|
import com.imyeyu.api.modules.common.service.AttachmentService;
|
||||||
|
import com.imyeyu.api.modules.gao.bean.GaoPermissionCode;
|
||||||
import com.imyeyu.api.modules.gao.entity.GaoCustomer;
|
import com.imyeyu.api.modules.gao.entity.GaoCustomer;
|
||||||
import com.imyeyu.api.modules.gao.entity.GaoCustomerPackage;
|
import com.imyeyu.api.modules.gao.entity.GaoCustomerPackage;
|
||||||
import com.imyeyu.api.modules.gao.entity.GaoPackageConfig;
|
import com.imyeyu.api.modules.gao.entity.GaoPackageConfig;
|
||||||
@@ -44,6 +45,7 @@ import java.util.ArrayList;
|
|||||||
import java.util.Comparator;
|
import java.util.Comparator;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
|
import java.util.LinkedHashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
@@ -151,10 +153,13 @@ public class GaoCustomerPackageServiceImplement extends AbstractEntityService<Ga
|
|||||||
request.setItemList(defaultPurchaseItems(configItemList));
|
request.setItemList(defaultPurchaseItems(configItemList));
|
||||||
}
|
}
|
||||||
List<GaoCustomerPackagePurchaseItem> requestItemList = new ArrayList<>(request.getItemList());
|
List<GaoCustomerPackagePurchaseItem> requestItemList = new ArrayList<>(request.getItemList());
|
||||||
|
normalizePurchaseItems(requestItemList);
|
||||||
verifyPurchaseItems(requestItemList);
|
verifyPurchaseItems(requestItemList);
|
||||||
boolean canOverridePriceAndQuantity = permissionChecker.hasAny(ModuleCode.GAO,
|
boolean canOverridePriceAndQuantity = permissionChecker.hasAny(ModuleCode.GAO,
|
||||||
com.imyeyu.api.modules.gao.bean.GaoPermissionCode.CUSTOMER_PACKAGE_PRICE_OVERRIDE.getValue());
|
GaoPermissionCode.CUSTOMER_PACKAGE_PRICE_OVERRIDE.getValue());
|
||||||
List<GaoCustomerPackagePurchaseItem> itemList = resolvePurchaseItems(config.getStoreId(), requestItemList, configItemList, canOverridePriceAndQuantity);
|
boolean canCreateGift = permissionChecker.hasAny(ModuleCode.GAO, GaoPermissionCode.CUSTOMER_PACKAGE_GIFT_CREATE.getValue());
|
||||||
|
List<GaoCustomerPackagePurchaseItem> itemList = resolvePurchaseItems(config.getStoreId(), requestItemList, configItemList,
|
||||||
|
canOverridePriceAndQuantity, canCreateGift);
|
||||||
itemList.sort(Comparator.comparing(GaoCustomerPackagePurchaseItem::getSort).thenComparing(GaoCustomerPackagePurchaseItem::getSkuId)
|
itemList.sort(Comparator.comparing(GaoCustomerPackagePurchaseItem::getSort).thenComparing(GaoCustomerPackagePurchaseItem::getSkuId)
|
||||||
.thenComparing(GaoCustomerPackagePurchaseItem::getSkuUnitId));
|
.thenComparing(GaoCustomerPackagePurchaseItem::getSkuUnitId));
|
||||||
request.setItemList(itemList);
|
request.setItemList(itemList);
|
||||||
@@ -246,6 +251,7 @@ public class GaoCustomerPackageServiceImplement extends AbstractEntityService<Ga
|
|||||||
GaoCustomerPackagePurchaseItem item = new GaoCustomerPackagePurchaseItem();
|
GaoCustomerPackagePurchaseItem item = new GaoCustomerPackagePurchaseItem();
|
||||||
item.setSkuId(configItem.getSkuId());
|
item.setSkuId(configItem.getSkuId());
|
||||||
item.setSkuUnitId(configItem.getSkuUnitId());
|
item.setSkuUnitId(configItem.getSkuUnitId());
|
||||||
|
item.setGifted(false);
|
||||||
item.setProductNameSnapshot(configItem.getProductNameSnapshot());
|
item.setProductNameSnapshot(configItem.getProductNameSnapshot());
|
||||||
item.setProductIdSnapshot(configItem.getProductIdSnapshot());
|
item.setProductIdSnapshot(configItem.getProductIdSnapshot());
|
||||||
item.setSkuCodeSnapshot(configItem.getSkuCodeSnapshot());
|
item.setSkuCodeSnapshot(configItem.getSkuCodeSnapshot());
|
||||||
@@ -265,6 +271,7 @@ public class GaoCustomerPackageServiceImplement extends AbstractEntityService<Ga
|
|||||||
item.setItemType(GaoSalesOrderItem.ItemType.PACKAGE_ENTITLEMENT);
|
item.setItemType(GaoSalesOrderItem.ItemType.PACKAGE_ENTITLEMENT);
|
||||||
item.setSkuId(source.getSkuId());
|
item.setSkuId(source.getSkuId());
|
||||||
item.setSkuUnitId(source.getSkuUnitId());
|
item.setSkuUnitId(source.getSkuUnitId());
|
||||||
|
item.setGifted(Boolean.TRUE.equals(source.getGifted()));
|
||||||
item.setProductNameSnapshot(source.getProductNameSnapshot());
|
item.setProductNameSnapshot(source.getProductNameSnapshot());
|
||||||
item.setProductIdSnapshot(source.getProductIdSnapshot());
|
item.setProductIdSnapshot(source.getProductIdSnapshot());
|
||||||
item.setSkuCodeSnapshot(source.getSkuCodeSnapshot());
|
item.setSkuCodeSnapshot(source.getSkuCodeSnapshot());
|
||||||
@@ -284,6 +291,32 @@ public class GaoCustomerPackageServiceImplement extends AbstractEntityService<Ga
|
|||||||
return item;
|
return item;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void normalizePurchaseItems(List<GaoCustomerPackagePurchaseItem> itemList) {
|
||||||
|
Map<String, Integer> indexMap = new LinkedHashMap<>();
|
||||||
|
for (int i = 0; i < itemList.size(); i++) {
|
||||||
|
GaoCustomerPackagePurchaseItem item = itemList.get(i);
|
||||||
|
if (item == null) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
item.setGifted(Boolean.TRUE.equals(item.getGifted()));
|
||||||
|
if (item.getSkuId() == null || item.getSkuUnitId() == null || item.getTotalQuantity() == null) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
String key = item.getSkuId() + "|" + item.getSkuUnitId() + "|" + item.getGifted();
|
||||||
|
Integer existingIndex = indexMap.putIfAbsent(key, i);
|
||||||
|
if (existingIndex == null) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
GaoCustomerPackagePurchaseItem existingItem = itemList.get(existingIndex);
|
||||||
|
if (existingItem == null || existingItem.getTotalQuantity() == null) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
existingItem.setTotalQuantity(existingItem.getTotalQuantity().add(item.getTotalQuantity()));
|
||||||
|
itemList.set(i, null);
|
||||||
|
}
|
||||||
|
itemList.removeIf(item -> item == null);
|
||||||
|
}
|
||||||
|
|
||||||
private void verifyPurchaseItems(List<GaoCustomerPackagePurchaseItem> itemList) {
|
private void verifyPurchaseItems(List<GaoCustomerPackagePurchaseItem> itemList) {
|
||||||
Set<String> keySet = new HashSet<>();
|
Set<String> keySet = new HashSet<>();
|
||||||
for (int i = 0; i < itemList.size(); i++) {
|
for (int i = 0; i < itemList.size(); i++) {
|
||||||
@@ -294,14 +327,15 @@ public class GaoCustomerPackageServiceImplement extends AbstractEntityService<Ga
|
|||||||
TimiException.required(item.getTotalQuantity(), "购买产品数量不能为空");
|
TimiException.required(item.getTotalQuantity(), "购买产品数量不能为空");
|
||||||
TimiException.requiredTrue(0 <= item.getTotalQuantity().signum(), "购买产品数量不能为负数");
|
TimiException.requiredTrue(0 <= item.getTotalQuantity().signum(), "购买产品数量不能为负数");
|
||||||
TimiException.requiredTrue(3 >= item.getTotalQuantity().stripTrailingZeros().scale(), "购买产品数量最多保留三位小数");
|
TimiException.requiredTrue(3 >= item.getTotalQuantity().stripTrailingZeros().scale(), "购买产品数量最多保留三位小数");
|
||||||
String key = item.getSkuId() + "|" + item.getSkuUnitId();
|
item.setGifted(Boolean.TRUE.equals(item.getGifted()));
|
||||||
|
String key = item.getSkuId() + "|" + item.getSkuUnitId() + "|" + item.getGifted();
|
||||||
TimiException.requiredTrue(keySet.add(key), "购买套餐内 SKU 和单位不能重复");
|
TimiException.requiredTrue(keySet.add(key), "购买套餐内 SKU 和单位不能重复");
|
||||||
item.setSort(TimiJava.defaultIfNull(item.getSort(), i));
|
item.setSort(TimiJava.defaultIfNull(item.getSort(), i));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<GaoCustomerPackagePurchaseItem> resolvePurchaseItems(String storeId, List<GaoCustomerPackagePurchaseItem> requestItemList,
|
private List<GaoCustomerPackagePurchaseItem> resolvePurchaseItems(String storeId, List<GaoCustomerPackagePurchaseItem> requestItemList,
|
||||||
List<GaoPackageConfigItem> configItemList, boolean canOverridePriceAndQuantity) {
|
List<GaoPackageConfigItem> configItemList, boolean canOverridePriceAndQuantity, boolean canCreateGift) {
|
||||||
Map<String, List<GaoPackageConfigItem>> configItemMap = configItemList.stream()
|
Map<String, List<GaoPackageConfigItem>> configItemMap = configItemList.stream()
|
||||||
.collect(Collectors.groupingBy(GaoPackageConfigItem::getSkuId));
|
.collect(Collectors.groupingBy(GaoPackageConfigItem::getSkuId));
|
||||||
Map<String, BigDecimal> configBaseQuantityMap = new HashMap<>();
|
Map<String, BigDecimal> configBaseQuantityMap = new HashMap<>();
|
||||||
@@ -312,23 +346,32 @@ public class GaoCustomerPackageServiceImplement extends AbstractEntityService<Ga
|
|||||||
Map<String, BigDecimal> requestBaseQuantityMap = new HashMap<>();
|
Map<String, BigDecimal> requestBaseQuantityMap = new HashMap<>();
|
||||||
List<GaoCustomerPackagePurchaseItem> result = new ArrayList<>();
|
List<GaoCustomerPackagePurchaseItem> result = new ArrayList<>();
|
||||||
for (GaoCustomerPackagePurchaseItem requestItem : requestItemList) {
|
for (GaoCustomerPackagePurchaseItem requestItem : requestItemList) {
|
||||||
|
boolean gifted = Boolean.TRUE.equals(requestItem.getGifted());
|
||||||
List<GaoPackageConfigItem> skuConfigItemList = configItemMap.get(requestItem.getSkuId());
|
List<GaoPackageConfigItem> skuConfigItemList = configItemMap.get(requestItem.getSkuId());
|
||||||
|
if (gifted) {
|
||||||
|
TimiException.requiredTrue(canCreateGift, "没有客户套餐创建赠送权限");
|
||||||
|
} else {
|
||||||
TimiException.requiredTrue(skuConfigItemList != null && !skuConfigItemList.isEmpty(), "购买 SKU 不属于套餐配置");
|
TimiException.requiredTrue(skuConfigItemList != null && !skuConfigItemList.isEmpty(), "购买 SKU 不属于套餐配置");
|
||||||
|
}
|
||||||
GaoProductSkuUnitSelection selection = skuService.getSellableSkuUnit(storeId, requestItem.getSkuId(), requestItem.getSkuUnitId());
|
GaoProductSkuUnitSelection selection = skuService.getSellableSkuUnit(storeId, requestItem.getSkuId(), requestItem.getSkuUnitId());
|
||||||
|
if (!gifted) {
|
||||||
TimiException.requiredTrue(skuConfigItemList.stream().anyMatch(configItem -> 0 <= configItem.getBaseQuantityPerUnitSnapshot()
|
TimiException.requiredTrue(skuConfigItemList.stream().anyMatch(configItem -> 0 <= configItem.getBaseQuantityPerUnitSnapshot()
|
||||||
.compareTo(selection.getUnit().getBaseQuantityPerUnit())), "套餐权益单位不能高于配置单位");
|
.compareTo(selection.getUnit().getBaseQuantityPerUnit())), "套餐权益单位不能高于配置单位");
|
||||||
|
}
|
||||||
BigDecimal requestBaseQuantity = toBaseQuantity(requestItem.getTotalQuantity(), selection.getUnit().getBaseQuantityPerUnit(), "套餐权益基础数量最多保留三位小数");
|
BigDecimal requestBaseQuantity = toBaseQuantity(requestItem.getTotalQuantity(), selection.getUnit().getBaseQuantityPerUnit(), "套餐权益基础数量最多保留三位小数");
|
||||||
|
if (!gifted) {
|
||||||
requestBaseQuantityMap.merge(requestItem.getSkuId(), requestBaseQuantity, BigDecimal::add);
|
requestBaseQuantityMap.merge(requestItem.getSkuId(), requestBaseQuantity, BigDecimal::add);
|
||||||
|
}
|
||||||
if (requestItem.getTotalQuantity().signum() == 0) {
|
if (requestItem.getTotalQuantity().signum() == 0) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (!Boolean.TRUE.equals(selection.getSku().getAllowDecimalQuantity())) {
|
if (!Boolean.TRUE.equals(selection.getSku().getAllowDecimalQuantity())) {
|
||||||
TimiException.requiredTrue(requestItem.getTotalQuantity().stripTrailingZeros().scale() <= 0, "该 SKU 不允许小数数量");
|
TimiException.requiredTrue(requestItem.getTotalQuantity().stripTrailingZeros().scale() <= 0, "该 SKU 不允许小数数量");
|
||||||
}
|
}
|
||||||
GaoPackageConfigItem template = resolveItemTemplate(skuConfigItemList, selection.getUnit().getId());
|
|
||||||
GaoCustomerPackagePurchaseItem item = new GaoCustomerPackagePurchaseItem();
|
GaoCustomerPackagePurchaseItem item = new GaoCustomerPackagePurchaseItem();
|
||||||
item.setSkuId(selection.getSku().getId());
|
item.setSkuId(selection.getSku().getId());
|
||||||
item.setSkuUnitId(selection.getUnit().getId());
|
item.setSkuUnitId(selection.getUnit().getId());
|
||||||
|
item.setGifted(gifted);
|
||||||
item.setProductNameSnapshot(selection.getProduct().getName());
|
item.setProductNameSnapshot(selection.getProduct().getName());
|
||||||
item.setProductIdSnapshot(selection.getProduct().getId());
|
item.setProductIdSnapshot(selection.getProduct().getId());
|
||||||
item.setSkuCodeSnapshot(selection.getSku().getCode());
|
item.setSkuCodeSnapshot(selection.getSku().getCode());
|
||||||
@@ -337,8 +380,14 @@ public class GaoCustomerPackageServiceImplement extends AbstractEntityService<Ga
|
|||||||
item.setUnitSnapshot(selection.getUnit().getName());
|
item.setUnitSnapshot(selection.getUnit().getName());
|
||||||
item.setBaseQuantityPerUnitSnapshot(selection.getUnit().getBaseQuantityPerUnit());
|
item.setBaseQuantityPerUnitSnapshot(selection.getUnit().getBaseQuantityPerUnit());
|
||||||
item.setTotalQuantity(requestItem.getTotalQuantity());
|
item.setTotalQuantity(requestItem.getTotalQuantity());
|
||||||
|
if (gifted) {
|
||||||
|
item.setSort(requestItem.getSort());
|
||||||
|
item.setRemark(requestItem.getRemark());
|
||||||
|
} else {
|
||||||
|
GaoPackageConfigItem template = resolveItemTemplate(skuConfigItemList, selection.getUnit().getId());
|
||||||
item.setSort(template.getSort());
|
item.setSort(template.getSort());
|
||||||
item.setRemark(template.getRemark());
|
item.setRemark(template.getRemark());
|
||||||
|
}
|
||||||
result.add(item);
|
result.add(item);
|
||||||
}
|
}
|
||||||
TimiException.requiredTrue(!result.isEmpty(), "购买套餐至少需要一个产品");
|
TimiException.requiredTrue(!result.isEmpty(), "购买套餐至少需要一个产品");
|
||||||
@@ -378,9 +427,10 @@ public class GaoCustomerPackageServiceImplement extends AbstractEntityService<Ga
|
|||||||
List<GaoCustomerPackagePurchaseItem> requestItemList = TimiJava.defaultIfNull(request.getItemList(), List.of());
|
List<GaoCustomerPackagePurchaseItem> requestItemList = TimiJava.defaultIfNull(request.getItemList(), List.of());
|
||||||
verifyPurchaseItems(requestItemList);
|
verifyPurchaseItems(requestItemList);
|
||||||
TimiException.requiredTrue(existingItemList.size() == requestItemList.size(), "requestNo 对应购买请求内容不一致");
|
TimiException.requiredTrue(existingItemList.size() == requestItemList.size(), "requestNo 对应购买请求内容不一致");
|
||||||
Map<String, GaoSalesOrderItem> existingItemMap = existingItemList.stream().collect(Collectors.toMap(item -> item.getSkuId() + "|" + item.getSkuUnitId(), Function.identity()));
|
Map<String, GaoSalesOrderItem> existingItemMap = existingItemList.stream().collect(Collectors.toMap(item -> item.getSkuId() + "|" + item.getSkuUnitId() + "|"
|
||||||
|
+ Boolean.TRUE.equals(item.getGifted()), Function.identity()));
|
||||||
for (GaoCustomerPackagePurchaseItem item : requestItemList) {
|
for (GaoCustomerPackagePurchaseItem item : requestItemList) {
|
||||||
GaoSalesOrderItem existingItem = existingItemMap.get(item.getSkuId() + "|" + item.getSkuUnitId());
|
GaoSalesOrderItem existingItem = existingItemMap.get(item.getSkuId() + "|" + item.getSkuUnitId() + "|" + Boolean.TRUE.equals(item.getGifted()));
|
||||||
TimiException.required(existingItem, "requestNo 对应购买请求内容不一致");
|
TimiException.required(existingItem, "requestNo 对应购买请求内容不一致");
|
||||||
TimiException.requiredTrue(existingItem.getItemType() == GaoSalesOrderItem.ItemType.PACKAGE_ENTITLEMENT
|
TimiException.requiredTrue(existingItem.getItemType() == GaoSalesOrderItem.ItemType.PACKAGE_ENTITLEMENT
|
||||||
&& existingItem.getQuantity().compareTo(item.getTotalQuantity()) == 0
|
&& existingItem.getQuantity().compareTo(item.getTotalQuantity()) == 0
|
||||||
|
|||||||
+8
-3
@@ -453,9 +453,11 @@ public class GaoSalesOrderServiceImplement extends AbstractEntityService<GaoSale
|
|||||||
for (GaoSalesOrderItem item : itemList) {
|
for (GaoSalesOrderItem item : itemList) {
|
||||||
TimiException.required(item, "销售订单明细不能为空");
|
TimiException.required(item, "销售订单明细不能为空");
|
||||||
TimiException.requiredTrue(item.getItemType() == expectedItemType, "订单项类型与订单类型不匹配");
|
TimiException.requiredTrue(item.getItemType() == expectedItemType, "订单项类型与订单类型不匹配");
|
||||||
|
item.setGifted(Boolean.TRUE.equals(item.getGifted()));
|
||||||
TimiException.required(item.getSkuId(), "订单项 SKU 不能为空");
|
TimiException.required(item.getSkuId(), "订单项 SKU 不能为空");
|
||||||
TimiException.required(item.getSkuUnitId(), "订单项 SKU 单位不能为空");
|
TimiException.required(item.getSkuUnitId(), "订单项 SKU 单位不能为空");
|
||||||
TimiException.requiredTrue(skuUnitKeySet.add(item.getSkuId() + "|" + item.getSkuUnitId()),
|
String skuUnitKey = item.getSkuId() + "|" + item.getSkuUnitId() + "|" + item.getGifted();
|
||||||
|
TimiException.requiredTrue(skuUnitKeySet.add(skuUnitKey),
|
||||||
"同一订单不能重复 SKU 和单位");
|
"同一订单不能重复 SKU 和单位");
|
||||||
TimiException.required(item.getQuantity(), "订单项数量不能为空");
|
TimiException.required(item.getQuantity(), "订单项数量不能为空");
|
||||||
TimiException.requiredTrue(0 < item.getQuantity().signum(), "订单项数量必须大于 0");
|
TimiException.requiredTrue(0 < item.getQuantity().signum(), "订单项数量必须大于 0");
|
||||||
@@ -511,11 +513,14 @@ public class GaoSalesOrderServiceImplement extends AbstractEntityService<GaoSale
|
|||||||
List<GaoSalesOrderItem> existingItemList = itemMapper.selectBySalesOrderId(existing.getId());
|
List<GaoSalesOrderItem> existingItemList = itemMapper.selectBySalesOrderId(existing.getId());
|
||||||
TimiException.requiredTrue(existingItemList.size() == requestItemList.size(), "requestNo 对应订单内容不一致");
|
TimiException.requiredTrue(existingItemList.size() == requestItemList.size(), "requestNo 对应订单内容不一致");
|
||||||
Map<String, GaoSalesOrderItem> existingItemMap = existingItemList.stream()
|
Map<String, GaoSalesOrderItem> existingItemMap = existingItemList.stream()
|
||||||
.collect(java.util.stream.Collectors.toMap(item -> item.getSkuId() + "|" + item.getSkuUnitId(), java.util.function.Function.identity()));
|
.collect(java.util.stream.Collectors.toMap(item -> item.getSkuId() + "|" + item.getSkuUnitId() + "|" + Boolean.TRUE.equals(item.getGifted()),
|
||||||
|
java.util.function.Function.identity()));
|
||||||
for (GaoSalesOrderItem requestItem : requestItemList) {
|
for (GaoSalesOrderItem requestItem : requestItemList) {
|
||||||
GaoSalesOrderItem existingItem = existingItemMap.get(requestItem.getSkuId() + "|" + requestItem.getSkuUnitId());
|
GaoSalesOrderItem existingItem = existingItemMap.get(requestItem.getSkuId() + "|" + requestItem.getSkuUnitId() + "|"
|
||||||
|
+ Boolean.TRUE.equals(requestItem.getGifted()));
|
||||||
TimiException.required(existingItem, "requestNo 对应订单内容不一致");
|
TimiException.required(existingItem, "requestNo 对应订单内容不一致");
|
||||||
TimiException.requiredTrue(existingItem.getItemType() == GaoSalesOrderItem.ItemType.PACKAGE_ENTITLEMENT
|
TimiException.requiredTrue(existingItem.getItemType() == GaoSalesOrderItem.ItemType.PACKAGE_ENTITLEMENT
|
||||||
|
&& Boolean.TRUE.equals(existingItem.getGifted()) == Boolean.TRUE.equals(requestItem.getGifted())
|
||||||
&& existingItem.getQuantity().compareTo(requestItem.getQuantity()) == 0
|
&& existingItem.getQuantity().compareTo(requestItem.getQuantity()) == 0
|
||||||
&& existingItem.getSort().equals(requestItem.getSort())
|
&& existingItem.getSort().equals(requestItem.getSort())
|
||||||
&& sameText(existingItem.getRemark(), requestItem.getRemark()), "requestNo 对应订单内容不一致");
|
&& sameText(existingItem.getRemark(), requestItem.getRemark()), "requestNo 对应订单内容不一致");
|
||||||
|
|||||||
@@ -17,6 +17,9 @@ public class GaoCustomerPackagePurchaseItem {
|
|||||||
/// SKU 单位 ID
|
/// SKU 单位 ID
|
||||||
private String skuUnitId;
|
private String skuUnitId;
|
||||||
|
|
||||||
|
/// true 表示请求将该明细作为赠送权益创建
|
||||||
|
private Boolean gifted;
|
||||||
|
|
||||||
/// 产品名称快照,由后端生成
|
/// 产品名称快照,由后端生成
|
||||||
private String productNameSnapshot;
|
private String productNameSnapshot;
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,5 @@
|
|||||||
|
ALTER TABLE `gao_sales_order_item`
|
||||||
|
ADD COLUMN `gifted` TINYINT(1) NOT NULL DEFAULT 0 COMMENT 'true 为赠送权益' AFTER `item_type`,
|
||||||
|
DROP KEY `uk_gao_sales_order_item_sku_unit`,
|
||||||
|
ADD UNIQUE KEY `uk_gao_sales_order_item_sku_unit_gifted` (`sales_order_id`, `sku_id`, `sku_unit_id`, `gifted`),
|
||||||
|
ADD KEY `idx_gao_sales_order_item_order_gifted` (`sales_order_id`, `gifted`, `sort`, `created_at`);
|
||||||
Reference in New Issue
Block a user