add GaoPackage
This commit is contained in:
+16
-1
@@ -59,6 +59,7 @@ public class AttachmentVariantServiceImplement implements AttachmentVariantServi
|
||||
private static final long THUMB_CACHE_TTL = Time.D * 7;
|
||||
private static final long THUMB_LOCK_TTL = Time.M * 10;
|
||||
private static final double THUMB_TARGET_SECONDS = 2;
|
||||
private static final int VARIANT_NAME_MAX_LENGTH = 255;
|
||||
private static final String THUMB_OUTPUT_FORMAT = "png";
|
||||
private static final String THUMB_ALGORITHM_VERSION = "v3";
|
||||
private static final String THUMB_LOCK_KEY_PREFIX = "ATTACHMENT:THUMB:LOCK:";
|
||||
@@ -158,7 +159,7 @@ public class AttachmentVariantServiceImplement implements AttachmentVariantServi
|
||||
thumbFile = createThumbFile(source, requestWidth, requestHeight, fitMode, isImage);
|
||||
variant = new AttachmentVariant();
|
||||
variant.setId(UUID.randomUUID().toString());
|
||||
variant.setName(Network.simpleURIFileName(source.getName()) + "." + THUMB_OUTPUT_FORMAT);
|
||||
variant.setName(buildVariantName(source.getName()));
|
||||
variant.setMimeType("image/" + THUMB_OUTPUT_FORMAT);
|
||||
long expireAt = Time.now() + THUMB_CACHE_TTL;
|
||||
variant.setSourceAttachmentId(source.getId());
|
||||
@@ -257,6 +258,20 @@ public class AttachmentVariantServiceImplement implements AttachmentVariantServi
|
||||
);
|
||||
}
|
||||
|
||||
/// 构建不超过数据库字段长度的变体名称
|
||||
///
|
||||
/// @param sourceName 源附件名称
|
||||
/// @return 变体名称
|
||||
private String buildVariantName(String sourceName) {
|
||||
String suffix = "." + THUMB_OUTPUT_FORMAT;
|
||||
String baseName = Network.simpleURIFileName(sourceName);
|
||||
int maxBaseLength = VARIANT_NAME_MAX_LENGTH - suffix.length();
|
||||
if (maxBaseLength < baseName.codePointCount(0, baseName.length())) {
|
||||
baseName = baseName.substring(0, baseName.offsetByCodePoints(0, maxBaseLength));
|
||||
}
|
||||
return baseName + suffix;
|
||||
}
|
||||
|
||||
private File createThumbFile(
|
||||
Attachment source,
|
||||
Integer requestWidth,
|
||||
|
||||
@@ -73,7 +73,7 @@ public enum GaoPermissionCode implements BuiltinPermissionCode {
|
||||
|
||||
CUSTOMER_PACKAGE_CANCEL("CUSTOMER_PACKAGE:CANCEL", "客户套餐取消", true, true),
|
||||
|
||||
CUSTOMER_PACKAGE_PRICE_OVERRIDE("CUSTOMER_PACKAGE:PRICE_OVERRIDE", "客户套餐成交价和产品定制", true, true),
|
||||
CUSTOMER_PACKAGE_PRICE_OVERRIDE("CUSTOMER_PACKAGE:PRICE_OVERRIDE", "客户套餐成交价和权益配额调整", true, true),
|
||||
|
||||
PACKAGE_DELIVERY_CREATE("PACKAGE_DELIVERY:CREATE", "套餐发放创建", true, true),
|
||||
|
||||
|
||||
@@ -16,7 +16,7 @@ public enum GaoRoleCode implements BuiltinRoleCode {
|
||||
GLOBAL_MANAGER("门店管理", null),
|
||||
|
||||
/// 店长
|
||||
STORE_MANAGER("店长", GLOBAL_MANAGER.name());
|
||||
STORE_MANAGER("店长", null);
|
||||
|
||||
final String defaultName;
|
||||
final String parentCode;
|
||||
|
||||
@@ -4,7 +4,10 @@ import com.imyeyu.api.modules.gao.annotation.RequireGaoPermission;
|
||||
import com.imyeyu.api.modules.gao.bean.GaoPermissionCode;
|
||||
import com.imyeyu.api.modules.gao.entity.GaoEvent;
|
||||
import com.imyeyu.api.modules.gao.entity.GaoEventOptionGroup;
|
||||
import com.imyeyu.api.modules.gao.entity.GaoPackageConfig;
|
||||
import com.imyeyu.api.modules.gao.entity.GaoPackageConfigItem;
|
||||
import com.imyeyu.api.modules.gao.service.GaoEventService;
|
||||
import com.imyeyu.api.modules.gao.service.GaoPackageConfigService;
|
||||
import com.imyeyu.api.modules.gao.service.GaoStoreScopeService;
|
||||
import com.imyeyu.java.TimiJava;
|
||||
import com.imyeyu.java.bean.timi.TimiException;
|
||||
@@ -32,6 +35,7 @@ import java.util.Map;
|
||||
public class GaoEventController {
|
||||
|
||||
private final GaoEventService service;
|
||||
private final GaoPackageConfigService packageConfigService;
|
||||
private final GaoStoreScopeService storeScopeService;
|
||||
|
||||
@AOPLog
|
||||
@@ -69,15 +73,38 @@ public class GaoEventController {
|
||||
event.setRoleCodeList(roleMap.get(event.getId()));
|
||||
}
|
||||
service.attachOptionGroupList(result.getList());
|
||||
attachPackageConfig(result.getList());
|
||||
return result;
|
||||
}
|
||||
|
||||
private void attachPackageConfig(List<GaoEvent> eventList) {
|
||||
List<String> packageConfigIdList = eventList.stream()
|
||||
.map(GaoEvent::getPackageConfigId)
|
||||
.filter(TimiJava::isNotEmpty)
|
||||
.distinct()
|
||||
.toList();
|
||||
if (packageConfigIdList.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
Map<String, GaoPackageConfig> packageConfigMap = packageConfigService.mapByIdList(packageConfigIdList);
|
||||
Map<String, List<GaoPackageConfigItem>> itemMap = packageConfigService.mapItemListByPackageConfigIdList(packageConfigIdList);
|
||||
for (GaoEvent event : eventList) {
|
||||
GaoPackageConfig packageConfig = packageConfigMap.get(event.getPackageConfigId());
|
||||
if (packageConfig != null) {
|
||||
packageConfig.setItemList(itemMap.getOrDefault(packageConfig.getId(), List.of()));
|
||||
event.setPackageConfig(packageConfig);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@AOPLog
|
||||
@RequestRateLimit
|
||||
@RequireGaoPermission(GaoPermissionCode.EVENT_READ)
|
||||
@PostMapping("/list/valid")
|
||||
public List<GaoEvent> listValid(@RequestParam String storeId) {
|
||||
return service.listValid(storeScopeService.resolveStoreId(storeId));
|
||||
List<GaoEvent> result = service.listValid(storeScopeService.resolveStoreId(storeId));
|
||||
attachPackageConfig(result);
|
||||
return result;
|
||||
}
|
||||
|
||||
@AOPLog
|
||||
@@ -90,6 +117,7 @@ public class GaoEventController {
|
||||
storeScopeService.checkStoreId(event.getStoreId());
|
||||
event.setRoleCodeList(service.listRoleCode(event.getId()));
|
||||
service.attachOptionGroupList(List.of(event));
|
||||
attachPackageConfig(List.of(event));
|
||||
return event;
|
||||
}
|
||||
|
||||
|
||||
@@ -13,10 +13,10 @@ import com.imyeyu.api.modules.gao.service.GaoEventRecordService;
|
||||
import com.imyeyu.api.modules.gao.service.GaoEventService;
|
||||
import com.imyeyu.api.modules.gao.service.GaoStoreScopeService;
|
||||
import com.imyeyu.api.modules.gao.vo.GaoCustomerEventRankView;
|
||||
import com.imyeyu.api.modules.gao.vo.GaoEventOptionStatView;
|
||||
import com.imyeyu.api.modules.gao.vo.GaoEventRecordPage;
|
||||
import com.imyeyu.api.modules.gao.vo.GaoEventRecordPageResult;
|
||||
import com.imyeyu.api.modules.gao.vo.GaoEventRecordRankPage;
|
||||
import com.imyeyu.api.modules.gao.vo.GaoEventOptionStatView;
|
||||
import com.imyeyu.api.modules.user.service.UserService;
|
||||
import com.imyeyu.java.TimiJava;
|
||||
import com.imyeyu.java.bean.timi.TimiException;
|
||||
@@ -114,6 +114,7 @@ public class GaoEventRecordController {
|
||||
record.setEvent(eventService.get(record.getEventId()));
|
||||
eventService.attachOptionGroupList(List.of(record.getEvent()));
|
||||
record.setOperator(userService.get(record.getOperatorUserId()));
|
||||
record.setUpdater(userService.get(record.getUpdatedBy()));
|
||||
if (record.getVerifierUserId() != null) {
|
||||
record.setVerifier(userService.get(record.getVerifierUserId()));
|
||||
}
|
||||
|
||||
@@ -106,6 +106,13 @@ public class GaoEvent extends UUIDEntity {
|
||||
/// 业务类型
|
||||
private BizType bizType;
|
||||
|
||||
/// 购买套餐事件绑定的套餐配置 ID
|
||||
private String packageConfigId;
|
||||
|
||||
/// 购买套餐事件绑定的套餐配置
|
||||
@Transient
|
||||
private GaoPackageConfig packageConfig;
|
||||
|
||||
/// 登记事件名称
|
||||
private String name;
|
||||
|
||||
|
||||
@@ -87,6 +87,9 @@ public class GaoEventRecord extends UUIDEntity {
|
||||
/// 营业日递增序号
|
||||
private Long businessDayNo;
|
||||
|
||||
/// 最后修改用户 ID
|
||||
private String updatedBy;
|
||||
|
||||
@Transient
|
||||
private GaoCustomer customer;
|
||||
|
||||
@@ -99,6 +102,10 @@ public class GaoEventRecord extends UUIDEntity {
|
||||
@Transient
|
||||
private User verifier;
|
||||
|
||||
/// 最后修改用户
|
||||
@Transient
|
||||
private User updater;
|
||||
|
||||
@Transient
|
||||
private List<Attachment> attachmentList;
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@ import com.imyeyu.api.modules.gao.entity.GaoEvent;
|
||||
import com.imyeyu.spring.bean.Page;
|
||||
import com.imyeyu.spring.mapper.BaseMapper;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
import org.apache.ibatis.annotations.Select;
|
||||
import org.apache.ibatis.annotations.SelectProvider;
|
||||
|
||||
import java.util.Collection;
|
||||
@@ -25,4 +26,7 @@ public interface GaoEventMapper extends BaseMapper<GaoEvent, String> {
|
||||
List<GaoEvent> selectByIdList(Collection<String> idList);
|
||||
|
||||
List<GaoEvent> selectValidList(@Param("storeId") String storeId, @Param("now") Long now);
|
||||
|
||||
@Select("SELECT COUNT(*) FROM `gao_event` WHERE `package_config_id` = #{packageConfigId} AND `deleted_at` IS NULL")
|
||||
long countByPackageConfigId(String packageConfigId);
|
||||
}
|
||||
|
||||
@@ -12,6 +12,7 @@ import com.imyeyu.api.modules.gao.vo.GaoEventOptionStatView;
|
||||
import com.imyeyu.api.modules.gao.vo.GaoStoreChartReq;
|
||||
import com.imyeyu.spring.mapper.BaseMapper;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
import org.apache.ibatis.annotations.Select;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@@ -21,6 +22,13 @@ import java.util.List;
|
||||
/// @since 2026-07-27 14:11
|
||||
public interface GaoEventRecordMapper extends BaseMapper<GaoEventRecord, String> {
|
||||
|
||||
/// 查询事件登记记录数量
|
||||
///
|
||||
/// @param eventId 事件 ID
|
||||
/// @return 登记记录数量
|
||||
@Select("SELECT COUNT(*) FROM `gao_event_record` WHERE `event_id` = #{eventId} AND `deleted_at` IS NULL")
|
||||
long countByEventId(String eventId);
|
||||
|
||||
Long count(String storeId, String customerId, String eventId, Long beginAt, Long endAt);
|
||||
|
||||
/// 查询事件中已携带数值的登记记录数量
|
||||
@@ -50,8 +58,9 @@ public interface GaoEventRecordMapper extends BaseMapper<GaoEventRecord, String>
|
||||
/// @param id 登记记录 ID
|
||||
/// @param verifierUserId 核销用户 ID
|
||||
/// @param verifiedAt 核销时间
|
||||
/// @param updatedBy 最后修改用户 ID
|
||||
/// @return 更新行数
|
||||
int verify(@Param("id") String id, @Param("verifierUserId") String verifierUserId, @Param("verifiedAt") Long verifiedAt);
|
||||
int verify(@Param("id") String id, @Param("verifierUserId") String verifierUserId, @Param("verifiedAt") Long verifiedAt, @Param("updatedBy") String updatedBy);
|
||||
|
||||
/// 按门店和登记日期统计登记记录数
|
||||
///
|
||||
|
||||
@@ -22,6 +22,12 @@ public interface GaoPackageConfigService extends BaseService<GaoPackageConfig, S
|
||||
/// 查询有效可购买套餐
|
||||
List<GaoPackageConfig> listValid(String storeId);
|
||||
|
||||
/// 批量查询套餐配置
|
||||
///
|
||||
/// @param idList 套餐配置 ID 列表
|
||||
/// @return 按套餐配置 ID 映射的配置
|
||||
Map<String, GaoPackageConfig> mapByIdList(Collection<String> idList);
|
||||
|
||||
/// 查询套餐配置产品明细
|
||||
///
|
||||
/// @param packageConfigId 套餐配置 ID
|
||||
|
||||
+50
-32
@@ -171,23 +171,25 @@ public class GaoCustomerPackageServiceImplement extends AbstractEntityService<Ga
|
||||
TimiException.required(request, "not found purchase request");
|
||||
TimiException.required(request.getRequestNo(), "not found requestNo");
|
||||
request.setRequestNo(request.getRequestNo().trim());
|
||||
TimiException.required(request.getPackageConfigId(), "not found packageConfigId");
|
||||
TimiException.required(request.getEventId(), "not found eventId");
|
||||
TimiException.required(request.getCustomerId(), "not found customerId");
|
||||
TimiException.required(request.getSaleAmount(), "not found saleAmount");
|
||||
TimiException.requiredTrue(0 <= request.getSaleAmount(), "成交价不能为负数");
|
||||
|
||||
GaoPackageConfig config = packageConfigService.get(request.getPackageConfigId());
|
||||
if (config == null) {
|
||||
GaoCustomerPackage existing = mapper.selectByRequestNoAnyStore(request.getRequestNo());
|
||||
if (existing != null) {
|
||||
storeScopeService.checkStoreId(existing.getStoreId());
|
||||
verifyPurchaseIdempotency(existing, request);
|
||||
return existing;
|
||||
}
|
||||
GaoEvent event = validatePurchaseEvent(request.getEventId());
|
||||
storeScopeService.checkStoreId(event.getStoreId());
|
||||
GaoPackageConfig config = packageConfigService.get(event.getPackageConfigId());
|
||||
TimiException.required(config, "购买事件绑定的套餐配置不存在");
|
||||
TimiException.requiredTrue(event.getStoreId().equals(config.getStoreId()), "购买事件和套餐配置不属于同一门店");
|
||||
List<GaoPackageConfigItem> configItemList = packageConfigService.listItemByPackageConfigId(config.getId());
|
||||
request.setSaleAmount(TimiJava.defaultIfNull(request.getSaleAmount(), config.getStandardAmount()));
|
||||
TimiException.requiredTrue(0 <= request.getSaleAmount(), "成交价不能为负数");
|
||||
if (request.getItemList() == null) {
|
||||
request.setItemList(defaultPurchaseItems(configItemList));
|
||||
}
|
||||
TimiException.required(config, "not found package config");
|
||||
storeScopeService.checkStoreId(config.getStoreId());
|
||||
List<GaoCustomerPackagePurchaseItem> itemList = new java.util.ArrayList<>(request.getItemList());
|
||||
verifyPurchaseItems(itemList);
|
||||
itemList.sort(java.util.Comparator.comparing(GaoCustomerPackagePurchaseItem::getSort));
|
||||
request.setItemList(itemList);
|
||||
|
||||
GaoCustomerPackage existing = mapper.selectByRequestNo(config.getStoreId(), request.getRequestNo());
|
||||
if (existing != null) {
|
||||
verifyPurchaseIdempotency(existing, request);
|
||||
@@ -199,17 +201,12 @@ public class GaoCustomerPackageServiceImplement extends AbstractEntityService<Ga
|
||||
TimiException.requiredTrue(config.getStatus() == GaoPackageConfig.Status.ACTIVE, "套餐配置不可购买");
|
||||
TimiException.requiredTrue(config.getBeginAt() == null || config.getBeginAt() <= now, "套餐配置尚未生效");
|
||||
TimiException.requiredTrue(config.getEndAt() == null || now <= config.getEndAt(), "套餐配置已过期");
|
||||
List<GaoPackageConfigItem> configItemList = packageConfigService.listItemByPackageConfigId(config.getId());
|
||||
GaoCustomer customer = validateCustomer(request.getCustomerId(), config.getStoreId());
|
||||
GaoEvent event = validatePurchaseEvent(request.getEventId(), config.getStoreId());
|
||||
|
||||
List<GaoCustomerPackagePurchaseItem> itemList = new java.util.ArrayList<>(TimiJava.defaultIfNull(request.getItemList(), List.of()));
|
||||
verifyPurchaseItems(itemList);
|
||||
itemList.sort(java.util.Comparator.comparing(GaoCustomerPackagePurchaseItem::getSort));
|
||||
boolean canOverride = permissionChecker.hasAny(ModuleCode.GAO, com.imyeyu.api.modules.gao.bean.GaoPermissionCode.CUSTOMER_PACKAGE_PRICE_OVERRIDE.getValue());
|
||||
if (!canOverride) {
|
||||
verifySameStructureAsConfig(itemList, configItemList);
|
||||
boolean canOverridePriceAndQuantity = permissionChecker.hasAny(ModuleCode.GAO, com.imyeyu.api.modules.gao.bean.GaoPermissionCode.CUSTOMER_PACKAGE_PRICE_OVERRIDE.getValue());
|
||||
if (!canOverridePriceAndQuantity) {
|
||||
TimiException.requiredTrue(request.getSaleAmount().equals(config.getStandardAmount()), "普通员工不能修改套餐成交价");
|
||||
verifySameAsConfig(itemList, configItemList);
|
||||
verifySameQuantityAsConfig(itemList, configItemList);
|
||||
}
|
||||
|
||||
GaoEventRecord eventRecord = new GaoEventRecord();
|
||||
@@ -299,14 +296,26 @@ public class GaoCustomerPackageServiceImplement extends AbstractEntityService<Ga
|
||||
return customer;
|
||||
}
|
||||
|
||||
private GaoEvent validatePurchaseEvent(String eventId, String storeId) {
|
||||
private GaoEvent validatePurchaseEvent(String eventId) {
|
||||
GaoEvent event = eventService.get(eventId);
|
||||
TimiException.required(event, "not found purchase event");
|
||||
TimiException.requiredTrue(storeId.equals(event.getStoreId()), "购买事件和套餐不属于同一门店");
|
||||
TimiException.requiredTrue(event.getBizType() == GaoEvent.BizType.PACKAGE_PURCHASE, "事件不是套餐购买事件");
|
||||
TimiException.required(event.getPackageConfigId(), "购买事件未绑定套餐配置");
|
||||
return event;
|
||||
}
|
||||
|
||||
private List<GaoCustomerPackagePurchaseItem> defaultPurchaseItems(List<GaoPackageConfigItem> configItemList) {
|
||||
return configItemList.stream().map(configItem -> {
|
||||
GaoCustomerPackagePurchaseItem item = new GaoCustomerPackagePurchaseItem();
|
||||
item.setProductName(configItem.getProductName());
|
||||
item.setUnit(configItem.getUnit());
|
||||
item.setTotalQuantity(configItem.getDefaultQuantity());
|
||||
item.setSort(configItem.getSort());
|
||||
item.setRemark(configItem.getRemark());
|
||||
return item;
|
||||
}).toList();
|
||||
}
|
||||
|
||||
private void verifyPurchaseItems(List<GaoCustomerPackagePurchaseItem> itemList) {
|
||||
TimiException.requiredTrue(!itemList.isEmpty(), "购买套餐至少需要一个产品");
|
||||
Set<String> keySet = new HashSet<>();
|
||||
@@ -326,20 +335,27 @@ public class GaoCustomerPackageServiceImplement extends AbstractEntityService<Ga
|
||||
}
|
||||
}
|
||||
|
||||
private void verifySameAsConfig(List<GaoCustomerPackagePurchaseItem> itemList, List<GaoPackageConfigItem> configItemList) {
|
||||
TimiException.requiredTrue(itemList.size() == configItemList.size(), "普通员工不能修改套餐产品明细");
|
||||
private void verifySameStructureAsConfig(List<GaoCustomerPackagePurchaseItem> itemList, List<GaoPackageConfigItem> configItemList) {
|
||||
TimiException.requiredTrue(itemList.size() == configItemList.size(), "套餐权益项目必须与事件绑定套餐一致");
|
||||
Map<String, GaoCustomerPackagePurchaseItem> itemMap = itemList.stream().collect(Collectors.toMap(item -> item.getProductName() + "|" + item.getUnit(), Function.identity()));
|
||||
for (GaoPackageConfigItem configItem : configItemList) {
|
||||
GaoCustomerPackagePurchaseItem item = itemMap.get(configItem.getProductName() + "|" + configItem.getUnit());
|
||||
TimiException.required(item, "普通员工不能修改套餐产品明细");
|
||||
TimiException.requiredTrue(item.getTotalQuantity().compareTo(configItem.getDefaultQuantity()) == 0
|
||||
&& item.getSort().equals(configItem.getSort()), "普通员工不能修改套餐产品明细");
|
||||
TimiException.required(item, "套餐权益项目必须与事件绑定套餐一致");
|
||||
TimiException.requiredTrue(item.getSort().equals(configItem.getSort())
|
||||
&& sameText(item.getRemark(), configItem.getRemark()), "套餐权益项目的名称、单位、排序和备注不可修改");
|
||||
}
|
||||
}
|
||||
|
||||
private void verifySameQuantityAsConfig(List<GaoCustomerPackagePurchaseItem> itemList, List<GaoPackageConfigItem> configItemList) {
|
||||
Map<String, GaoCustomerPackagePurchaseItem> itemMap = itemList.stream().collect(Collectors.toMap(item -> item.getProductName() + "|" + item.getUnit(), Function.identity()));
|
||||
for (GaoPackageConfigItem configItem : configItemList) {
|
||||
GaoCustomerPackagePurchaseItem item = itemMap.get(configItem.getProductName() + "|" + configItem.getUnit());
|
||||
TimiException.requiredTrue(item.getTotalQuantity().compareTo(configItem.getDefaultQuantity()) == 0, "普通员工不能修改套餐权益配额");
|
||||
}
|
||||
}
|
||||
|
||||
private void verifyPurchaseIdempotency(GaoCustomerPackage existing, GaoCustomerPackagePurchaseRequest request) {
|
||||
TimiException.requiredTrue(existing.getPackageConfigId().equals(request.getPackageConfigId())
|
||||
&& existing.getCustomerId().equals(request.getCustomerId())
|
||||
TimiException.requiredTrue(existing.getCustomerId().equals(request.getCustomerId())
|
||||
&& existing.getSaleAmount().equals(request.getSaleAmount()), "requestNo 已被其他购买请求使用");
|
||||
GaoEventRecord eventRecord = eventRecordService.get(existing.getPurchaseEventRecordId());
|
||||
TimiException.required(eventRecord, "购买事件登记不存在");
|
||||
@@ -354,7 +370,9 @@ public class GaoCustomerPackageServiceImplement extends AbstractEntityService<Ga
|
||||
for (GaoCustomerPackagePurchaseItem item : requestItemList) {
|
||||
GaoCustomerPackageItem existingItem = existingItemMap.get(item.getProductName() + "|" + item.getUnit());
|
||||
TimiException.required(existingItem, "requestNo 对应购买请求内容不一致");
|
||||
TimiException.requiredTrue(existingItem.getTotalQuantity().compareTo(item.getTotalQuantity()) == 0 && existingItem.getSort().equals(item.getSort()), "requestNo 对应购买请求内容不一致");
|
||||
TimiException.requiredTrue(existingItem.getTotalQuantity().compareTo(item.getTotalQuantity()) == 0
|
||||
&& existingItem.getSort().equals(item.getSort())
|
||||
&& sameText(existingItem.getRemark(), item.getRemark()), "requestNo 对应购买请求内容不一致");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+4
-2
@@ -139,7 +139,8 @@ public class GaoEventRecordServiceImplement extends AbstractEntityService<GaoEve
|
||||
GaoEventRecord record = get(id);
|
||||
TimiException.required(record, "not found event record");
|
||||
TimiException.requiredTrue(record.getVerificationStatus() == GaoEventRecord.VerificationStatus.PENDING, "登记记录无需核销或已核销");
|
||||
int updated = mapper.verify(id, userLoginService.getRequireLoginUserId(), Time.now());
|
||||
String loginUserId = userLoginService.getRequireLoginUserId();
|
||||
int updated = mapper.verify(id, loginUserId, Time.now(), loginUserId);
|
||||
TimiException.requiredTrue(0 < updated, "登记记录无需核销或已核销");
|
||||
logger.setLevel(Logger.Level.INFO);
|
||||
logger.setResult(id);
|
||||
@@ -175,7 +176,6 @@ public class GaoEventRecordServiceImplement extends AbstractEntityService<GaoEve
|
||||
return createInternal(record, true);
|
||||
}
|
||||
|
||||
@Transactional(TimiServerDBConfig.ROLLBACKER)
|
||||
private GaoEventRecord createInternal(GaoEventRecord record, boolean packagePurchase) {
|
||||
TimiException.required(record, "not found record");
|
||||
|
||||
@@ -224,6 +224,7 @@ public class GaoEventRecordServiceImplement extends AbstractEntityService<GaoEve
|
||||
dbRecord.setStoreId(event.getStoreId());
|
||||
dbRecord.setEventId(record.getEventId());
|
||||
dbRecord.setOperatorUserId(loginUserId);
|
||||
dbRecord.setUpdatedBy(loginUserId);
|
||||
dbRecord.setRemark(record.getRemark());
|
||||
dbRecord.setRegisteredAt(registeredAt);
|
||||
dbRecord.setRegisteredDateValue(registeredDateValue);
|
||||
@@ -318,6 +319,7 @@ public class GaoEventRecordServiceImplement extends AbstractEntityService<GaoEve
|
||||
verifyRecordAttachment(event, record.getAttachmentList());
|
||||
checkEventPermission(event);
|
||||
dbRecord.setRemark(record.getRemark());
|
||||
dbRecord.setUpdatedBy(userLoginService.getRequireLoginUserId());
|
||||
super.update(dbRecord);
|
||||
if (canonicalOptionList != null) {
|
||||
GaoEventRecordOption optionExample = new GaoEventRecordOption();
|
||||
|
||||
+13
@@ -6,12 +6,14 @@ import com.imyeyu.api.modules.gao.entity.GaoEvent;
|
||||
import com.imyeyu.api.modules.gao.entity.GaoEventOption;
|
||||
import com.imyeyu.api.modules.gao.entity.GaoEventOptionGroup;
|
||||
import com.imyeyu.api.modules.gao.entity.GaoEventRoleRelation;
|
||||
import com.imyeyu.api.modules.gao.entity.GaoPackageConfig;
|
||||
import com.imyeyu.api.modules.gao.mapper.GaoEventMapper;
|
||||
import com.imyeyu.api.modules.gao.mapper.GaoEventOptionGroupMapper;
|
||||
import com.imyeyu.api.modules.gao.mapper.GaoEventOptionMapper;
|
||||
import com.imyeyu.api.modules.gao.mapper.GaoEventRecordMapper;
|
||||
import com.imyeyu.api.modules.gao.mapper.GaoEventRoleRelationMapper;
|
||||
import com.imyeyu.api.modules.gao.service.GaoEventService;
|
||||
import com.imyeyu.api.modules.gao.service.GaoPackageConfigService;
|
||||
import com.imyeyu.api.modules.system.entity.Logger;
|
||||
import com.imyeyu.api.modules.system.service.LoggerService;
|
||||
import com.imyeyu.java.TimiJava;
|
||||
@@ -57,6 +59,7 @@ public class GaoEventServiceImplement extends AbstractEntityService<GaoEvent, St
|
||||
private final GaoEventOptionMapper optionMapper;
|
||||
private final GaoEventRecordMapper eventRecordMapper;
|
||||
private final GaoEventRoleRelationMapper roleRelationMapper;
|
||||
private final GaoPackageConfigService packageConfigService;
|
||||
|
||||
@Override
|
||||
protected BaseMapper<GaoEvent, String> mapper() {
|
||||
@@ -130,6 +133,10 @@ public class GaoEventServiceImplement extends AbstractEntityService<GaoEvent, St
|
||||
GaoEvent.BizType bizType = TimiJava.defaultIfNull(event.getBizType(), dbEvent.getBizType());
|
||||
TimiException.requiredTrue(bizType == TimiJava.defaultIfNull(dbEvent.getBizType(), GaoEvent.BizType.GENERAL), "事件业务类型创建后不可修改");
|
||||
dbEvent.setBizType(bizType);
|
||||
if (event.getPackageConfigId() != null && !event.getPackageConfigId().equals(dbEvent.getPackageConfigId())) {
|
||||
TimiException.requiredTrue(0 == eventRecordMapper.countByEventId(dbEvent.getId()), "已有登记记录的事件不能更换绑定套餐");
|
||||
dbEvent.setPackageConfigId(event.getPackageConfigId());
|
||||
}
|
||||
dbEvent.setValueType(TimiJava.defaultIfNull(event.getValueType(), oldValueType));
|
||||
if (event.getValueUnit() != null) {
|
||||
dbEvent.setValueUnit(event.getValueUnit());
|
||||
@@ -317,6 +324,12 @@ public class GaoEventServiceImplement extends AbstractEntityService<GaoEvent, St
|
||||
event.setBizType(TimiJava.defaultIfNull(event.getBizType(), GaoEvent.BizType.GENERAL));
|
||||
if (event.getBizType() == GaoEvent.BizType.PACKAGE_PURCHASE) {
|
||||
TimiException.requiredTrue(!Boolean.TRUE.equals(event.getRequireVerification()), "购买套餐事件不能要求核销");
|
||||
TimiException.required(event.getPackageConfigId(), "购买套餐事件必须绑定套餐配置");
|
||||
GaoPackageConfig packageConfig = packageConfigService.get(event.getPackageConfigId());
|
||||
TimiException.required(packageConfig, "购买套餐事件绑定的套餐配置不存在");
|
||||
TimiException.requiredTrue(event.getStoreId().equals(packageConfig.getStoreId()), "购买事件和套餐配置不属于同一门店");
|
||||
} else {
|
||||
TimiException.requiredNull(event.getPackageConfigId(), "普通事件不能绑定套餐配置");
|
||||
}
|
||||
GaoEvent.ValueType valueType = TimiJava.defaultIfNull(event.getValueType(), GaoEvent.ValueType.NONE);
|
||||
if (valueType == GaoEvent.ValueType.NONE) {
|
||||
|
||||
+12
@@ -7,6 +7,7 @@ import com.imyeyu.api.modules.system.entity.Logger;
|
||||
import com.imyeyu.api.modules.system.service.LoggerService;
|
||||
import com.imyeyu.api.modules.gao.mapper.GaoPackageConfigItemMapper;
|
||||
import com.imyeyu.api.modules.gao.mapper.GaoPackageConfigMapper;
|
||||
import com.imyeyu.api.modules.gao.mapper.GaoEventMapper;
|
||||
import com.imyeyu.api.modules.gao.service.GaoPackageConfigService;
|
||||
import com.imyeyu.api.modules.gao.vo.GaoPackageConfigPage;
|
||||
import com.imyeyu.api.modules.user.service.UserLoginService;
|
||||
@@ -37,6 +38,7 @@ public class GaoPackageConfigServiceImplement extends AbstractEntityService<GaoP
|
||||
|
||||
private final GaoPackageConfigMapper mapper;
|
||||
private final GaoPackageConfigItemMapper itemMapper;
|
||||
private final GaoEventMapper eventMapper;
|
||||
private final UserLoginService userLoginService;
|
||||
private final LoggerService loggerService;
|
||||
|
||||
@@ -60,6 +62,15 @@ public class GaoPackageConfigServiceImplement extends AbstractEntityService<GaoP
|
||||
return mapper.selectValidList(storeId, Time.now());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, GaoPackageConfig> mapByIdList(Collection<String> idList) {
|
||||
if (idList == null || idList.isEmpty()) {
|
||||
return Map.of();
|
||||
}
|
||||
return mapper.selectByIdList(idList).stream()
|
||||
.collect(java.util.stream.Collectors.toMap(GaoPackageConfig::getId, item -> item));
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<GaoPackageConfigItem> listItemByPackageConfigId(String packageConfigId) {
|
||||
TimiException.required(packageConfigId, "not found packageConfigId");
|
||||
@@ -134,6 +145,7 @@ public class GaoPackageConfigServiceImplement extends AbstractEntityService<GaoP
|
||||
loggerService.execute(Logger.Module.GAO, "GAO_PACKAGE_CONFIG_DELETE", id, () -> {
|
||||
GaoPackageConfig config = get(id);
|
||||
TimiException.required(config, "not found package config");
|
||||
TimiException.requiredTrue(0 == eventMapper.countByPackageConfigId(id), "套餐配置已绑定购买事件,不能删除");
|
||||
super.delete(id);
|
||||
return id;
|
||||
});
|
||||
|
||||
+1
-1
@@ -182,7 +182,7 @@ public class GaoPackageDeliveryServiceImplement extends AbstractEntityService<Ga
|
||||
BigDecimal reservedBefore = decimal(packageItem.getReservedQuantity());
|
||||
BigDecimal deliveredBefore = decimal(packageItem.getDeliveredQuantity());
|
||||
BigDecimal available = decimal(packageItem.getTotalQuantity()).subtract(reservedBefore).subtract(deliveredBefore);
|
||||
TimiException.requiredTrue(0 < requestItem.getQuantity().compareTo(available), "产品可发数量不足");
|
||||
TimiException.requiredTrue(0 <= available.compareTo(requestItem.getQuantity()), "产品可发数量不足");
|
||||
int updated = customerPackageService.updateItemReservedQuantity(packageItem.getId(), requestItem.getQuantity());
|
||||
TimiException.requiredTrue(0 < updated, "产品可发数量不足");
|
||||
GaoPackageDeliveryItem savedItem = copyDeliveryItem(requestItem);
|
||||
|
||||
@@ -21,16 +21,13 @@ public class GaoCustomerPackagePurchaseRequest {
|
||||
/// 客户 ID
|
||||
private String customerId;
|
||||
|
||||
/// 套餐配置 ID
|
||||
private String packageConfigId;
|
||||
|
||||
/// 实际成交价,单位分
|
||||
/// 实际成交价,单位分,空为事件绑定套餐的标准价
|
||||
private Long saleAmount;
|
||||
|
||||
/// 购买时间
|
||||
private Long purchasedAt;
|
||||
|
||||
/// 最终产品明细
|
||||
/// 最终产品明细,空为事件绑定套餐的默认产品明细
|
||||
private List<GaoCustomerPackagePurchaseItem> itemList;
|
||||
|
||||
/// 购买照片
|
||||
|
||||
@@ -206,6 +206,7 @@ public class InitBuiltinUser implements ApplicationRunner {
|
||||
private void bindBuiltinRoleParent(Map<String, Role> roleMap) {
|
||||
setRoleParent(roleMap, ModuleCode.CORE, CoreRoleCode.ADMIN.name(), ModuleCode.CORE, CoreRoleCode.SYSTEM.name());
|
||||
setRoleParent(roleMap, ModuleCode.GAO, GaoRoleCode.GLOBAL_MANAGER.name(), ModuleCode.CORE, CoreRoleCode.ADMIN.name());
|
||||
setRoleParent(roleMap, ModuleCode.GAO, GaoRoleCode.STORE_MANAGER.name(), ModuleCode.GAO, GaoRoleCode.GLOBAL_MANAGER.name());
|
||||
}
|
||||
|
||||
/// 按权限定义补齐 SYSTEM 和 ADMIN 的默认权限
|
||||
|
||||
Reference in New Issue
Block a user