Compare commits
38
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
feb4d7af66 | ||
|
|
d75ab1ed5f | ||
|
|
a501eb7443 | ||
|
|
19941d9480 | ||
|
|
cd3d522d4f | ||
|
|
181c5078e9 | ||
|
|
e97f46e6b4 | ||
|
|
c0f89deb83 | ||
|
|
ce695463d3 | ||
|
|
83c683d473 | ||
|
|
9555474b0b | ||
|
|
a150f9e017 | ||
|
|
ecd2fa1c33 | ||
|
|
e3236d262d | ||
|
|
c8e2e16ba5 | ||
|
|
99b44faf09 | ||
|
|
b3e3cbf84b | ||
|
|
0aee11d824 | ||
|
|
fcf358a768 | ||
|
|
619369104c | ||
|
|
4f1408b9d0 | ||
|
|
029eea70cc | ||
|
|
22b1e65385 | ||
|
|
2170c48763 | ||
|
|
c2d1c48aae | ||
|
|
e14958c643 | ||
|
|
da288338cd | ||
|
|
ea430f2468 | ||
|
|
f76f79744a | ||
|
|
19daaff907 | ||
|
|
db94d8f932 | ||
|
|
53618fe362 | ||
|
|
523edffc4e | ||
|
|
c7ddb1a8b0 | ||
|
|
45c9fc814a | ||
|
|
407dc13ac4 | ||
|
|
0c06bf16c2 | ||
|
|
1db39e77d3 |
@@ -11,7 +11,7 @@
|
|||||||
|
|
||||||
<groupId>com.imyeyu.timiserverapi</groupId>
|
<groupId>com.imyeyu.timiserverapi</groupId>
|
||||||
<artifactId>TimiServerAPI</artifactId>
|
<artifactId>TimiServerAPI</artifactId>
|
||||||
<version>1.0.29</version>
|
<version>1.0.28</version>
|
||||||
<packaging>jar</packaging>
|
<packaging>jar</packaging>
|
||||||
<name>TimiServerAPI</name>
|
<name>TimiServerAPI</name>
|
||||||
<description>imyeyu.com API</description>
|
<description>imyeyu.com API</description>
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
package com.imyeyu.api.modules.common.entity;
|
package com.imyeyu.api.modules.common.entity;
|
||||||
|
|
||||||
import com.imyeyu.api.modules.common.bean.attachment.SettingSupport;
|
import com.imyeyu.api.modules.common.bean.attachment.SettingSupport;
|
||||||
import com.imyeyu.api.modules.user.entity.User;
|
|
||||||
import com.imyeyu.spring.annotation.table.PageIgnore;
|
import com.imyeyu.spring.annotation.table.PageIgnore;
|
||||||
import com.imyeyu.spring.annotation.table.Transient;
|
import com.imyeyu.spring.annotation.table.Transient;
|
||||||
import com.imyeyu.spring.entity.UUIDEntity;
|
import com.imyeyu.spring.entity.UUIDEntity;
|
||||||
@@ -31,9 +30,6 @@ public class Article extends UUIDEntity implements SettingSupport {
|
|||||||
/** 博客 */
|
/** 博客 */
|
||||||
BLOG,
|
BLOG,
|
||||||
|
|
||||||
/// GAO 门店日记
|
|
||||||
GAO_STORE_DIARY,
|
|
||||||
|
|
||||||
/// 反馈
|
/// 反馈
|
||||||
FEEDBACK
|
FEEDBACK
|
||||||
}
|
}
|
||||||
@@ -97,12 +93,6 @@ public class Article extends UUIDEntity implements SettingSupport {
|
|||||||
/** 文章状态 */
|
/** 文章状态 */
|
||||||
protected Status status;
|
protected Status status;
|
||||||
|
|
||||||
/// 最后更新用户 ID
|
|
||||||
protected String updatedBy;
|
|
||||||
|
|
||||||
@Transient
|
|
||||||
protected User updater;
|
|
||||||
|
|
||||||
@Transient
|
@Transient
|
||||||
protected List<Setting> settingList;
|
protected List<Setting> settingList;
|
||||||
|
|
||||||
|
|||||||
@@ -40,10 +40,6 @@ public class Attachment extends UUIDEntity {
|
|||||||
|
|
||||||
GAO_EVENT_RECORD,
|
GAO_EVENT_RECORD,
|
||||||
|
|
||||||
GAO_PACKAGE_DELIVERY,
|
|
||||||
|
|
||||||
GAO_FUND_RECORD,
|
|
||||||
|
|
||||||
TEMP_FILE,
|
TEMP_FILE,
|
||||||
|
|
||||||
MIRROR
|
MIRROR
|
||||||
|
|||||||
+1
-16
@@ -59,7 +59,6 @@ public class AttachmentVariantServiceImplement implements AttachmentVariantServi
|
|||||||
private static final long THUMB_CACHE_TTL = Time.D * 7;
|
private static final long THUMB_CACHE_TTL = Time.D * 7;
|
||||||
private static final long THUMB_LOCK_TTL = Time.M * 10;
|
private static final long THUMB_LOCK_TTL = Time.M * 10;
|
||||||
private static final double THUMB_TARGET_SECONDS = 2;
|
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_OUTPUT_FORMAT = "png";
|
||||||
private static final String THUMB_ALGORITHM_VERSION = "v3";
|
private static final String THUMB_ALGORITHM_VERSION = "v3";
|
||||||
private static final String THUMB_LOCK_KEY_PREFIX = "ATTACHMENT:THUMB:LOCK:";
|
private static final String THUMB_LOCK_KEY_PREFIX = "ATTACHMENT:THUMB:LOCK:";
|
||||||
@@ -159,7 +158,7 @@ public class AttachmentVariantServiceImplement implements AttachmentVariantServi
|
|||||||
thumbFile = createThumbFile(source, requestWidth, requestHeight, fitMode, isImage);
|
thumbFile = createThumbFile(source, requestWidth, requestHeight, fitMode, isImage);
|
||||||
variant = new AttachmentVariant();
|
variant = new AttachmentVariant();
|
||||||
variant.setId(UUID.randomUUID().toString());
|
variant.setId(UUID.randomUUID().toString());
|
||||||
variant.setName(buildVariantName(source.getName()));
|
variant.setName(Network.simpleURIFileName(source.getName()) + "." + THUMB_OUTPUT_FORMAT);
|
||||||
variant.setMimeType("image/" + THUMB_OUTPUT_FORMAT);
|
variant.setMimeType("image/" + THUMB_OUTPUT_FORMAT);
|
||||||
long expireAt = Time.now() + THUMB_CACHE_TTL;
|
long expireAt = Time.now() + THUMB_CACHE_TTL;
|
||||||
variant.setSourceAttachmentId(source.getId());
|
variant.setSourceAttachmentId(source.getId());
|
||||||
@@ -258,20 +257,6 @@ 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(
|
private File createThumbFile(
|
||||||
Attachment source,
|
Attachment source,
|
||||||
Integer requestWidth,
|
Integer requestWidth,
|
||||||
|
|||||||
@@ -21,14 +21,6 @@ public enum GaoPermissionCode implements BuiltinPermissionCode {
|
|||||||
|
|
||||||
STORE_DELETE("STORE:DELETE", "门店删除", false, true),
|
STORE_DELETE("STORE:DELETE", "门店删除", false, true),
|
||||||
|
|
||||||
STORE_DIARY_CREATE("STORE_DIARY:CREATE", "门店日记创建", true, false),
|
|
||||||
|
|
||||||
STORE_DIARY_READ("STORE_DIARY:READ", "门店日记读取", true, false),
|
|
||||||
|
|
||||||
STORE_DIARY_UPDATE("STORE_DIARY:UPDATE", "门店日记修改", true, false),
|
|
||||||
|
|
||||||
STORE_DIARY_DELETE("STORE_DIARY:DELETE", "门店日记删除", true, false),
|
|
||||||
|
|
||||||
CUSTOMER_CREATE("CUSTOMER:CREATE", "客户创建", false, false),
|
CUSTOMER_CREATE("CUSTOMER:CREATE", "客户创建", false, false),
|
||||||
|
|
||||||
CUSTOMER_READ("CUSTOMER:READ", "客户读取", false, false),
|
CUSTOMER_READ("CUSTOMER:READ", "客户读取", false, false),
|
||||||
@@ -59,40 +51,6 @@ public enum GaoPermissionCode implements BuiltinPermissionCode {
|
|||||||
|
|
||||||
EVENT_RECORD_DELETE("EVENT_RECORD:DELETE", "登记事件记录删除", false, false),
|
EVENT_RECORD_DELETE("EVENT_RECORD:DELETE", "登记事件记录删除", false, false),
|
||||||
|
|
||||||
PACKAGE_CONFIG_CREATE("PACKAGE_CONFIG:CREATE", "套餐配置创建", true, true),
|
|
||||||
|
|
||||||
PACKAGE_CONFIG_READ("PACKAGE_CONFIG:READ", "套餐配置读取", true, true),
|
|
||||||
|
|
||||||
PACKAGE_CONFIG_UPDATE("PACKAGE_CONFIG:UPDATE", "套餐配置修改", true, true),
|
|
||||||
|
|
||||||
PACKAGE_CONFIG_DELETE("PACKAGE_CONFIG:DELETE", "套餐配置删除", true, true),
|
|
||||||
|
|
||||||
CUSTOMER_PACKAGE_CREATE("CUSTOMER_PACKAGE:CREATE", "客户套餐创建", true, true),
|
|
||||||
|
|
||||||
CUSTOMER_PACKAGE_READ("CUSTOMER_PACKAGE:READ", "客户套餐读取", true, true),
|
|
||||||
|
|
||||||
CUSTOMER_PACKAGE_CANCEL("CUSTOMER_PACKAGE:CANCEL", "客户套餐取消", true, true),
|
|
||||||
|
|
||||||
CUSTOMER_PACKAGE_PRICE_OVERRIDE("CUSTOMER_PACKAGE:PRICE_OVERRIDE", "客户套餐成交价和权益配额调整", true, true),
|
|
||||||
|
|
||||||
PACKAGE_DELIVERY_CREATE("PACKAGE_DELIVERY:CREATE", "套餐发放创建", true, true),
|
|
||||||
|
|
||||||
PACKAGE_DELIVERY_READ("PACKAGE_DELIVERY:READ", "套餐发放读取", true, true),
|
|
||||||
|
|
||||||
PACKAGE_DELIVERY_VERIFY("PACKAGE_DELIVERY:VERIFY", "套餐发放核销", true, true),
|
|
||||||
|
|
||||||
PACKAGE_DELIVERY_REVOKE("PACKAGE_DELIVERY:REVOKE", "套餐发放冲正", true, true),
|
|
||||||
|
|
||||||
FUND_RECORD_READ("FUND_RECORD:READ", "资金流水读取", true, true),
|
|
||||||
|
|
||||||
FUND_RECEIVE_CREATE("FUND_RECEIVE:CREATE", "线下收款创建", true, true),
|
|
||||||
|
|
||||||
FUND_RECEIVE_VERIFY("FUND_RECEIVE:VERIFY", "线下收款核销", true, true),
|
|
||||||
|
|
||||||
FUND_REFUND("FUND:REFUND", "套餐退款", true, true),
|
|
||||||
|
|
||||||
FUND_REVOKE("FUND:REVOKE", "资金流水冲正", true, true),
|
|
||||||
|
|
||||||
POINT_ACCOUNT_READ("POINT_ACCOUNT:READ", "客户积分账户读取", true, true),
|
POINT_ACCOUNT_READ("POINT_ACCOUNT:READ", "客户积分账户读取", true, true),
|
||||||
|
|
||||||
POINT_LEDGER_READ("POINT_LEDGER:READ", "客户积分流水读取", true, true),
|
POINT_LEDGER_READ("POINT_LEDGER:READ", "客户积分流水读取", true, true),
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ public enum GaoRoleCode implements BuiltinRoleCode {
|
|||||||
GLOBAL_MANAGER("门店管理", null),
|
GLOBAL_MANAGER("门店管理", null),
|
||||||
|
|
||||||
/// 店长
|
/// 店长
|
||||||
STORE_MANAGER("店长", null);
|
STORE_MANAGER("店长", GLOBAL_MANAGER.name());
|
||||||
|
|
||||||
final String defaultName;
|
final String defaultName;
|
||||||
final String parentCode;
|
final String parentCode;
|
||||||
|
|||||||
-265
@@ -1,265 +0,0 @@
|
|||||||
package com.imyeyu.api.modules.gao.controller;
|
|
||||||
|
|
||||||
import com.imyeyu.api.modules.common.entity.Attachment;
|
|
||||||
import com.imyeyu.api.modules.common.service.AttachmentService;
|
|
||||||
import com.imyeyu.api.modules.gao.annotation.RequireGaoPermission;
|
|
||||||
import com.imyeyu.api.modules.gao.bean.GaoPermissionCode;
|
|
||||||
import com.imyeyu.api.modules.gao.entity.GaoCustomer;
|
|
||||||
import com.imyeyu.api.modules.gao.entity.GaoCustomerPackage;
|
|
||||||
import com.imyeyu.api.modules.gao.entity.GaoCustomerPackageItem;
|
|
||||||
import com.imyeyu.api.modules.gao.entity.GaoEventRecord;
|
|
||||||
import com.imyeyu.api.modules.gao.entity.GaoFundRecord;
|
|
||||||
import com.imyeyu.api.modules.gao.entity.GaoPackageDelivery;
|
|
||||||
import com.imyeyu.api.modules.gao.entity.GaoPackageDeliveryItem;
|
|
||||||
import com.imyeyu.api.modules.gao.service.GaoCustomerPackageService;
|
|
||||||
import com.imyeyu.api.modules.gao.service.GaoCustomerService;
|
|
||||||
import com.imyeyu.api.modules.gao.service.GaoEventRecordService;
|
|
||||||
import com.imyeyu.api.modules.gao.service.GaoFundRecordService;
|
|
||||||
import com.imyeyu.api.modules.gao.service.GaoPackageDeliveryService;
|
|
||||||
import com.imyeyu.api.modules.gao.service.GaoStoreScopeService;
|
|
||||||
import com.imyeyu.api.modules.gao.vo.GaoCustomerPackageCancelRequest;
|
|
||||||
import com.imyeyu.api.modules.gao.vo.GaoCustomerPackagePage;
|
|
||||||
import com.imyeyu.api.modules.gao.vo.GaoCustomerPackagePurchaseRequest;
|
|
||||||
import com.imyeyu.api.modules.gao.vo.GaoFundActionRequest;
|
|
||||||
import com.imyeyu.api.modules.gao.vo.GaoFundConfirmNoRefundRequest;
|
|
||||||
import com.imyeyu.api.modules.gao.vo.GaoFundReceiveRequest;
|
|
||||||
import com.imyeyu.api.modules.gao.vo.GaoFundRefundRequest;
|
|
||||||
import com.imyeyu.api.modules.user.entity.User;
|
|
||||||
import com.imyeyu.api.modules.user.service.UserService;
|
|
||||||
import com.imyeyu.java.bean.timi.TimiException;
|
|
||||||
import com.imyeyu.spring.annotation.AOPLog;
|
|
||||||
import com.imyeyu.spring.annotation.RequestRateLimit;
|
|
||||||
import com.imyeyu.spring.bean.PageResult;
|
|
||||||
import lombok.RequiredArgsConstructor;
|
|
||||||
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;
|
|
||||||
|
|
||||||
import java.math.BigDecimal;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.stream.Stream;
|
|
||||||
|
|
||||||
/// GAO 客户套餐和收退款接口
|
|
||||||
///
|
|
||||||
/// @author Codex
|
|
||||||
/// @since 2026-08-31
|
|
||||||
@RestController
|
|
||||||
@RequiredArgsConstructor
|
|
||||||
@RequestMapping("/gao/customer/package")
|
|
||||||
public class GaoCustomerPackageController {
|
|
||||||
|
|
||||||
private final GaoCustomerPackageService service;
|
|
||||||
private final GaoCustomerService customerService;
|
|
||||||
private final GaoEventRecordService eventRecordService;
|
|
||||||
private final GaoPackageDeliveryService deliveryService;
|
|
||||||
private final GaoFundRecordService fundRecordService;
|
|
||||||
private final AttachmentService attachmentService;
|
|
||||||
private final GaoStoreScopeService storeScopeService;
|
|
||||||
private final UserService userService;
|
|
||||||
|
|
||||||
@AOPLog
|
|
||||||
@RequestRateLimit
|
|
||||||
@RequireGaoPermission(GaoPermissionCode.CUSTOMER_PACKAGE_READ)
|
|
||||||
@PostMapping("/list")
|
|
||||||
public PageResult<GaoCustomerPackage> list(@RequestBody GaoCustomerPackagePage page) {
|
|
||||||
TimiException.required(page, "not found page");
|
|
||||||
page.setStoreId(storeScopeService.resolveStoreId(page.getStoreId()));
|
|
||||||
PageResult<GaoCustomerPackage> result = service.pageByQuery(page);
|
|
||||||
if (result.getList().isEmpty()) {
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
fillTransient(result.getList());
|
|
||||||
Map<String, GaoCustomer> customerMap = customerService.mapByIdList(result.getList().stream().map(GaoCustomerPackage::getCustomerId).toList());
|
|
||||||
for (GaoCustomerPackage packageEntity : result.getList()) {
|
|
||||||
packageEntity.setCustomer(customerMap.get(packageEntity.getCustomerId()));
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
@AOPLog
|
|
||||||
@RequestRateLimit
|
|
||||||
@RequireGaoPermission(GaoPermissionCode.CUSTOMER_PACKAGE_READ)
|
|
||||||
@PostMapping("/detail")
|
|
||||||
public GaoCustomerPackage detail(@RequestParam String id) {
|
|
||||||
GaoCustomerPackage result = service.get(id);
|
|
||||||
TimiException.required(result, "not found customer package");
|
|
||||||
storeScopeService.checkStoreId(result.getStoreId());
|
|
||||||
fillTransient(List.of(result));
|
|
||||||
GaoCustomer customer = customerService.get(result.getCustomerId());
|
|
||||||
if (customer != null) {
|
|
||||||
customer.setAttachmentList(attachmentService.listByBizId(Attachment.BizType.GAO_CUSTOMER, customer.getId()));
|
|
||||||
}
|
|
||||||
result.setCustomer(customer);
|
|
||||||
GaoEventRecord purchaseRecord = eventRecordService.get(result.getPurchaseEventRecordId());
|
|
||||||
if (purchaseRecord != null) {
|
|
||||||
purchaseRecord.setAttachmentList(attachmentService.listByBizId(Attachment.BizType.GAO_EVENT_RECORD, purchaseRecord.getId()));
|
|
||||||
}
|
|
||||||
result.setPurchaseEventRecord(purchaseRecord);
|
|
||||||
result.setDeliveryList(deliveryService.listByCustomerPackageId(result.getId()));
|
|
||||||
fillDeliveryTransient(result.getDeliveryList());
|
|
||||||
result.setFundRecordList(fundRecordService.listByCustomerPackageId(result.getId()));
|
|
||||||
fillFundTransient(result.getFundRecordList());
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
@AOPLog
|
|
||||||
@RequestRateLimit
|
|
||||||
@RequireGaoPermission(GaoPermissionCode.CUSTOMER_PACKAGE_CREATE)
|
|
||||||
@PostMapping("/purchase")
|
|
||||||
public GaoCustomerPackage purchase(@RequestBody GaoCustomerPackagePurchaseRequest request) {
|
|
||||||
GaoCustomerPackage result = service.purchase(request);
|
|
||||||
fillTransient(List.of(result));
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
@AOPLog
|
|
||||||
@RequestRateLimit
|
|
||||||
@RequireGaoPermission(GaoPermissionCode.CUSTOMER_PACKAGE_CANCEL)
|
|
||||||
@PostMapping("/cancel")
|
|
||||||
public GaoCustomerPackage cancel(@RequestBody GaoCustomerPackageCancelRequest request) {
|
|
||||||
GaoCustomerPackage result = service.cancel(request);
|
|
||||||
fillTransient(List.of(result));
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
@AOPLog
|
|
||||||
@RequestRateLimit
|
|
||||||
@RequireGaoPermission(GaoPermissionCode.FUND_RECEIVE_CREATE)
|
|
||||||
@PostMapping("/payment/receive")
|
|
||||||
public GaoCustomerPackage receive(@RequestBody GaoFundReceiveRequest request) {
|
|
||||||
fundRecordService.receive(request);
|
|
||||||
return packageResponse(request.getCustomerPackageId());
|
|
||||||
}
|
|
||||||
|
|
||||||
@AOPLog
|
|
||||||
@RequestRateLimit
|
|
||||||
@RequireGaoPermission(GaoPermissionCode.FUND_RECEIVE_VERIFY)
|
|
||||||
@PostMapping("/payment/verify")
|
|
||||||
public GaoCustomerPackage verifyPayment(@RequestParam String id) {
|
|
||||||
fundRecordService.verify(id);
|
|
||||||
return packageAfterFundAction(id);
|
|
||||||
}
|
|
||||||
|
|
||||||
@AOPLog
|
|
||||||
@RequestRateLimit
|
|
||||||
@RequireGaoPermission(GaoPermissionCode.FUND_RECEIVE_VERIFY)
|
|
||||||
@PostMapping("/payment/reject")
|
|
||||||
public GaoCustomerPackage rejectPayment(@RequestBody GaoFundActionRequest request) {
|
|
||||||
fundRecordService.reject(request);
|
|
||||||
return packageAfterFundAction(request.getFundRecordId());
|
|
||||||
}
|
|
||||||
|
|
||||||
@AOPLog
|
|
||||||
@RequestRateLimit
|
|
||||||
@RequireGaoPermission(GaoPermissionCode.FUND_RECEIVE_CREATE)
|
|
||||||
@PostMapping("/payment/cancel")
|
|
||||||
public GaoCustomerPackage cancelPayment(@RequestBody GaoFundActionRequest request) {
|
|
||||||
fundRecordService.cancel(request);
|
|
||||||
return packageAfterFundAction(request.getFundRecordId());
|
|
||||||
}
|
|
||||||
|
|
||||||
@AOPLog
|
|
||||||
@RequestRateLimit
|
|
||||||
@RequireGaoPermission(GaoPermissionCode.FUND_REFUND)
|
|
||||||
@PostMapping("/refund")
|
|
||||||
public GaoCustomerPackage refund(@RequestBody GaoFundRefundRequest request) {
|
|
||||||
fundRecordService.refund(request);
|
|
||||||
return packageResponse(request.getCustomerPackageId());
|
|
||||||
}
|
|
||||||
|
|
||||||
@AOPLog
|
|
||||||
@RequestRateLimit
|
|
||||||
@RequireGaoPermission(GaoPermissionCode.FUND_REFUND)
|
|
||||||
@PostMapping("/refund/confirm-none")
|
|
||||||
public GaoCustomerPackage confirmNoRefund(@RequestBody GaoFundConfirmNoRefundRequest request) {
|
|
||||||
fundRecordService.confirmNoRefund(request);
|
|
||||||
return packageResponse(request.getCustomerPackageId());
|
|
||||||
}
|
|
||||||
|
|
||||||
private GaoCustomerPackage packageAfterFundAction(String fundRecordId) {
|
|
||||||
var record = fundRecordService.get(fundRecordId);
|
|
||||||
TimiException.required(record, "not found fund record");
|
|
||||||
return packageResponse(record.getBizId());
|
|
||||||
}
|
|
||||||
|
|
||||||
private GaoCustomerPackage packageResponse(String packageId) {
|
|
||||||
GaoCustomerPackage result = service.get(packageId);
|
|
||||||
TimiException.required(result, "not found customer package");
|
|
||||||
fillTransient(List.of(result));
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void fillTransient(List<GaoCustomerPackage> packageList) {
|
|
||||||
if (packageList == null || packageList.isEmpty()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
Map<String, List<GaoCustomerPackageItem>> itemMap = service.mapItemListByCustomerPackageIdList(packageList.stream().map(GaoCustomerPackage::getId).toList());
|
|
||||||
List<String> userIdList = packageList.stream()
|
|
||||||
.flatMap(packageEntity -> Stream.of(packageEntity.getOperatorUserId(), packageEntity.getCancelOperatorUserId()))
|
|
||||||
.filter(value -> value != null && !value.isBlank())
|
|
||||||
.distinct()
|
|
||||||
.toList();
|
|
||||||
Map<String, User> userMap = userIdList.isEmpty() ? Map.of() : userService.mapByIdList(userIdList);
|
|
||||||
for (GaoCustomerPackage packageEntity : packageList) {
|
|
||||||
List<GaoCustomerPackageItem> itemList = itemMap.getOrDefault(packageEntity.getId(), List.of());
|
|
||||||
for (GaoCustomerPackageItem item : itemList) {
|
|
||||||
fillDerived(item);
|
|
||||||
}
|
|
||||||
packageEntity.setItemList(itemList);
|
|
||||||
packageEntity.setOperator(userMap.get(packageEntity.getOperatorUserId()));
|
|
||||||
packageEntity.setCancelOperator(userMap.get(packageEntity.getCancelOperatorUserId()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void fillDeliveryTransient(List<GaoPackageDelivery> deliveryList) {
|
|
||||||
if (deliveryList == null || deliveryList.isEmpty()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
List<String> idList = deliveryList.stream().map(GaoPackageDelivery::getId).toList();
|
|
||||||
Map<String, List<GaoPackageDeliveryItem>> itemMap = deliveryService.mapItemListByDeliveryIdList(idList);
|
|
||||||
Map<String, List<Attachment>> attachmentMap = attachmentService.mapByBizIdList(Attachment.BizType.GAO_PACKAGE_DELIVERY, idList);
|
|
||||||
List<String> userIdList = deliveryList.stream()
|
|
||||||
.flatMap(delivery -> Stream.of(delivery.getOperatorUserId(), delivery.getVerifierUserId()))
|
|
||||||
.filter(value -> value != null && !value.isBlank())
|
|
||||||
.distinct()
|
|
||||||
.toList();
|
|
||||||
Map<String, User> userMap = userIdList.isEmpty() ? Map.of() : userService.mapByIdList(userIdList);
|
|
||||||
for (GaoPackageDelivery delivery : deliveryList) {
|
|
||||||
delivery.setItemList(itemMap.getOrDefault(delivery.getId(), List.of()));
|
|
||||||
delivery.setAttachmentList(attachmentMap.getOrDefault(delivery.getId(), List.of()));
|
|
||||||
delivery.setOperator(userMap.get(delivery.getOperatorUserId()));
|
|
||||||
delivery.setVerifier(userMap.get(delivery.getVerifierUserId()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void fillFundTransient(List<GaoFundRecord> recordList) {
|
|
||||||
if (recordList == null || recordList.isEmpty()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
List<String> idList = recordList.stream().map(GaoFundRecord::getId).toList();
|
|
||||||
Map<String, List<Attachment>> attachmentMap = attachmentService.mapByBizIdList(Attachment.BizType.GAO_FUND_RECORD, idList);
|
|
||||||
List<String> userIdList = recordList.stream()
|
|
||||||
.flatMap(record -> Stream.of(record.getOperatorUserId(), record.getVerifierUserId()))
|
|
||||||
.filter(value -> value != null && !value.isBlank())
|
|
||||||
.distinct()
|
|
||||||
.toList();
|
|
||||||
Map<String, User> userMap = userIdList.isEmpty() ? Map.of() : userService.mapByIdList(userIdList);
|
|
||||||
for (GaoFundRecord record : recordList) {
|
|
||||||
record.setAttachmentList(attachmentMap.getOrDefault(record.getId(), List.of()));
|
|
||||||
record.setOperator(userMap.get(record.getOperatorUserId()));
|
|
||||||
record.setVerifier(userMap.get(record.getVerifierUserId()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void fillDerived(GaoCustomerPackageItem item) {
|
|
||||||
BigDecimal reserved = item.getReservedQuantity() == null ? BigDecimal.ZERO : item.getReservedQuantity();
|
|
||||||
BigDecimal delivered = item.getDeliveredQuantity() == null ? BigDecimal.ZERO : item.getDeliveredQuantity();
|
|
||||||
BigDecimal total = item.getTotalQuantity() == null ? BigDecimal.ZERO : item.getTotalQuantity();
|
|
||||||
item.setPendingQuantity(reserved);
|
|
||||||
item.setAvailableQuantity(total.subtract(reserved).subtract(delivered));
|
|
||||||
item.setRemainingQuantity(total.subtract(delivered));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -4,10 +4,7 @@ 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.modules.gao.entity.GaoEvent;
|
import com.imyeyu.api.modules.gao.entity.GaoEvent;
|
||||||
import com.imyeyu.api.modules.gao.entity.GaoEventOptionGroup;
|
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.GaoEventService;
|
||||||
import com.imyeyu.api.modules.gao.service.GaoPackageConfigService;
|
|
||||||
import com.imyeyu.api.modules.gao.service.GaoStoreScopeService;
|
import com.imyeyu.api.modules.gao.service.GaoStoreScopeService;
|
||||||
import com.imyeyu.java.TimiJava;
|
import com.imyeyu.java.TimiJava;
|
||||||
import com.imyeyu.java.bean.timi.TimiException;
|
import com.imyeyu.java.bean.timi.TimiException;
|
||||||
@@ -35,7 +32,6 @@ import java.util.Map;
|
|||||||
public class GaoEventController {
|
public class GaoEventController {
|
||||||
|
|
||||||
private final GaoEventService service;
|
private final GaoEventService service;
|
||||||
private final GaoPackageConfigService packageConfigService;
|
|
||||||
private final GaoStoreScopeService storeScopeService;
|
private final GaoStoreScopeService storeScopeService;
|
||||||
|
|
||||||
@AOPLog
|
@AOPLog
|
||||||
@@ -44,67 +40,26 @@ public class GaoEventController {
|
|||||||
@PostMapping("/list")
|
@PostMapping("/list")
|
||||||
public PageResult<GaoEvent> list(@RequestBody Page<GaoEvent> page) {
|
public PageResult<GaoEvent> list(@RequestBody Page<GaoEvent> page) {
|
||||||
TimiException.required(page, "not found page");
|
TimiException.required(page, "not found page");
|
||||||
resolveStoreScope(page);
|
|
||||||
PageResult<GaoEvent> result = service.pageWithoutDeleted(page);
|
|
||||||
return attachEventRelations(result);
|
|
||||||
}
|
|
||||||
|
|
||||||
@AOPLog
|
|
||||||
@RequestRateLimit
|
|
||||||
@RequireGaoPermission(GaoPermissionCode.EVENT_CREATE)
|
|
||||||
@PostMapping("/list/history")
|
|
||||||
public PageResult<GaoEvent> listHistory(@RequestBody Page<GaoEvent> page) {
|
|
||||||
TimiException.required(page, "not found page");
|
|
||||||
resolveStoreScope(page);
|
|
||||||
return attachEventRelations(service.page(page));
|
|
||||||
}
|
|
||||||
|
|
||||||
private void resolveStoreScope(Page<GaoEvent> page) {
|
|
||||||
if (!storeScopeService.hasGlobalScope()) {
|
if (!storeScopeService.hasGlobalScope()) {
|
||||||
GaoEvent example = TimiJava.defaultIfNull(page.getEqualsExample(), new GaoEvent());
|
GaoEvent example = TimiJava.defaultIfNull(page.getEqualsExample(), new GaoEvent());
|
||||||
example.setStoreId(storeScopeService.resolveStoreId(example.getStoreId()));
|
example.setStoreId(storeScopeService.resolveStoreId(example.getStoreId()));
|
||||||
page.setEqualsExample(example);
|
page.setEqualsExample(example);
|
||||||
}
|
}
|
||||||
}
|
PageResult<GaoEvent> result = service.page(page);
|
||||||
|
|
||||||
private PageResult<GaoEvent> attachEventRelations(PageResult<GaoEvent> result) {
|
|
||||||
Map<String, List<String>> roleMap = service.mapRoleCodeListByEventIdList(result.getList().stream().map(GaoEvent::getId).toList());
|
Map<String, List<String>> roleMap = service.mapRoleCodeListByEventIdList(result.getList().stream().map(GaoEvent::getId).toList());
|
||||||
for (GaoEvent event : result.getList()) {
|
for (GaoEvent event : result.getList()) {
|
||||||
event.setRoleCodeList(roleMap.get(event.getId()));
|
event.setRoleCodeList(roleMap.get(event.getId()));
|
||||||
}
|
}
|
||||||
service.attachOptionGroupList(result.getList());
|
service.attachOptionGroupList(result.getList());
|
||||||
attachPackageConfig(result.getList());
|
|
||||||
return result;
|
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
|
@AOPLog
|
||||||
@RequestRateLimit
|
@RequestRateLimit
|
||||||
@RequireGaoPermission(GaoPermissionCode.EVENT_READ)
|
@RequireGaoPermission(GaoPermissionCode.EVENT_READ)
|
||||||
@PostMapping("/list/valid")
|
@PostMapping("/list/valid")
|
||||||
public List<GaoEvent> listValid(@RequestParam String storeId) {
|
public List<GaoEvent> listValid(@RequestParam String storeId) {
|
||||||
List<GaoEvent> result = service.listValid(storeScopeService.resolveStoreId(storeId));
|
return service.listValid(storeScopeService.resolveStoreId(storeId));
|
||||||
attachPackageConfig(result);
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@AOPLog
|
@AOPLog
|
||||||
@@ -117,7 +72,6 @@ public class GaoEventController {
|
|||||||
storeScopeService.checkStoreId(event.getStoreId());
|
storeScopeService.checkStoreId(event.getStoreId());
|
||||||
event.setRoleCodeList(service.listRoleCode(event.getId()));
|
event.setRoleCodeList(service.listRoleCode(event.getId()));
|
||||||
service.attachOptionGroupList(List.of(event));
|
service.attachOptionGroupList(List.of(event));
|
||||||
attachPackageConfig(List.of(event));
|
|
||||||
return 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.GaoEventService;
|
||||||
import com.imyeyu.api.modules.gao.service.GaoStoreScopeService;
|
import com.imyeyu.api.modules.gao.service.GaoStoreScopeService;
|
||||||
import com.imyeyu.api.modules.gao.vo.GaoCustomerEventRankView;
|
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.GaoEventRecordPage;
|
||||||
import com.imyeyu.api.modules.gao.vo.GaoEventRecordPageResult;
|
import com.imyeyu.api.modules.gao.vo.GaoEventRecordPageResult;
|
||||||
import com.imyeyu.api.modules.gao.vo.GaoEventRecordRankPage;
|
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.api.modules.user.service.UserService;
|
||||||
import com.imyeyu.java.TimiJava;
|
import com.imyeyu.java.TimiJava;
|
||||||
import com.imyeyu.java.bean.timi.TimiException;
|
import com.imyeyu.java.bean.timi.TimiException;
|
||||||
@@ -114,7 +114,6 @@ public class GaoEventRecordController {
|
|||||||
record.setEvent(eventService.get(record.getEventId()));
|
record.setEvent(eventService.get(record.getEventId()));
|
||||||
eventService.attachOptionGroupList(List.of(record.getEvent()));
|
eventService.attachOptionGroupList(List.of(record.getEvent()));
|
||||||
record.setOperator(userService.get(record.getOperatorUserId()));
|
record.setOperator(userService.get(record.getOperatorUserId()));
|
||||||
record.setUpdater(userService.get(record.getUpdatedBy()));
|
|
||||||
if (record.getVerifierUserId() != null) {
|
if (record.getVerifierUserId() != null) {
|
||||||
record.setVerifier(userService.get(record.getVerifierUserId()));
|
record.setVerifier(userService.get(record.getVerifierUserId()));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,95 +0,0 @@
|
|||||||
package com.imyeyu.api.modules.gao.controller;
|
|
||||||
|
|
||||||
import com.imyeyu.api.modules.common.entity.Attachment;
|
|
||||||
import com.imyeyu.api.modules.common.service.AttachmentService;
|
|
||||||
import com.imyeyu.api.modules.gao.annotation.RequireGaoPermission;
|
|
||||||
import com.imyeyu.api.modules.gao.bean.GaoPermissionCode;
|
|
||||||
import com.imyeyu.api.modules.gao.entity.GaoFundRecord;
|
|
||||||
import com.imyeyu.api.modules.gao.service.GaoFundRecordService;
|
|
||||||
import com.imyeyu.api.modules.gao.service.GaoStoreScopeService;
|
|
||||||
import com.imyeyu.api.modules.gao.vo.GaoFundRecordPage;
|
|
||||||
import com.imyeyu.api.modules.gao.vo.GaoFundRevokeRequest;
|
|
||||||
import com.imyeyu.api.modules.user.entity.User;
|
|
||||||
import com.imyeyu.api.modules.user.service.UserService;
|
|
||||||
import com.imyeyu.java.bean.timi.TimiException;
|
|
||||||
import com.imyeyu.spring.annotation.AOPLog;
|
|
||||||
import com.imyeyu.spring.annotation.RequestRateLimit;
|
|
||||||
import com.imyeyu.spring.bean.PageResult;
|
|
||||||
import lombok.RequiredArgsConstructor;
|
|
||||||
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;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.stream.Stream;
|
|
||||||
|
|
||||||
/// GAO 资金流水接口
|
|
||||||
///
|
|
||||||
/// @author Codex
|
|
||||||
/// @since 2026-08-31
|
|
||||||
@RestController
|
|
||||||
@RequiredArgsConstructor
|
|
||||||
@RequestMapping("/gao/fund/record")
|
|
||||||
public class GaoFundRecordController {
|
|
||||||
|
|
||||||
private final GaoFundRecordService service;
|
|
||||||
private final GaoStoreScopeService storeScopeService;
|
|
||||||
private final AttachmentService attachmentService;
|
|
||||||
private final UserService userService;
|
|
||||||
|
|
||||||
@AOPLog
|
|
||||||
@RequestRateLimit
|
|
||||||
@RequireGaoPermission(GaoPermissionCode.FUND_RECORD_READ)
|
|
||||||
@PostMapping("/list")
|
|
||||||
public PageResult<GaoFundRecord> list(@RequestBody GaoFundRecordPage page) {
|
|
||||||
TimiException.required(page, "not found page");
|
|
||||||
page.setStoreId(storeScopeService.resolveStoreId(page.getStoreId()));
|
|
||||||
PageResult<GaoFundRecord> result = service.pageByQuery(page);
|
|
||||||
fillTransient(result.getList());
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
@AOPLog
|
|
||||||
@RequestRateLimit
|
|
||||||
@RequireGaoPermission(GaoPermissionCode.FUND_RECORD_READ)
|
|
||||||
@PostMapping("/detail")
|
|
||||||
public GaoFundRecord detail(@RequestParam String id) {
|
|
||||||
GaoFundRecord result = service.get(id);
|
|
||||||
TimiException.required(result, "not found fund record");
|
|
||||||
storeScopeService.checkStoreId(result.getStoreId());
|
|
||||||
fillTransient(List.of(result));
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
@AOPLog
|
|
||||||
@RequestRateLimit
|
|
||||||
@RequireGaoPermission(GaoPermissionCode.FUND_REVOKE)
|
|
||||||
@PostMapping("/revoke")
|
|
||||||
public GaoFundRecord revoke(@RequestBody GaoFundRevokeRequest request) {
|
|
||||||
GaoFundRecord result = service.revoke(request);
|
|
||||||
fillTransient(List.of(result));
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void fillTransient(List<GaoFundRecord> recordList) {
|
|
||||||
if (recordList == null || recordList.isEmpty()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
List<String> idList = recordList.stream().map(GaoFundRecord::getId).toList();
|
|
||||||
Map<String, List<Attachment>> attachmentMap = attachmentService.mapByBizIdList(Attachment.BizType.GAO_FUND_RECORD, idList);
|
|
||||||
List<String> userIdList = recordList.stream()
|
|
||||||
.flatMap(record -> Stream.of(record.getOperatorUserId(), record.getVerifierUserId()))
|
|
||||||
.filter(value -> value != null && !value.isBlank())
|
|
||||||
.distinct()
|
|
||||||
.toList();
|
|
||||||
Map<String, User> userMap = userIdList.isEmpty() ? Map.of() : userService.mapByIdList(userIdList);
|
|
||||||
for (GaoFundRecord record : recordList) {
|
|
||||||
record.setAttachmentList(attachmentMap.getOrDefault(record.getId(), List.of()));
|
|
||||||
record.setOperator(userMap.get(record.getOperatorUserId()));
|
|
||||||
record.setVerifier(userMap.get(record.getVerifierUserId()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,121 +0,0 @@
|
|||||||
package com.imyeyu.api.modules.gao.controller;
|
|
||||||
|
|
||||||
import com.imyeyu.api.modules.gao.annotation.RequireGaoPermission;
|
|
||||||
import com.imyeyu.api.modules.gao.bean.GaoPermissionCode;
|
|
||||||
import com.imyeyu.api.modules.gao.entity.GaoPackageConfig;
|
|
||||||
import com.imyeyu.api.modules.gao.entity.GaoPackageConfigItem;
|
|
||||||
import com.imyeyu.api.modules.gao.service.GaoPackageConfigService;
|
|
||||||
import com.imyeyu.api.modules.gao.service.GaoStoreScopeService;
|
|
||||||
import com.imyeyu.api.modules.gao.vo.GaoPackageConfigPage;
|
|
||||||
import com.imyeyu.api.modules.user.entity.User;
|
|
||||||
import com.imyeyu.api.modules.user.service.UserService;
|
|
||||||
import com.imyeyu.java.bean.timi.TimiException;
|
|
||||||
import com.imyeyu.spring.annotation.AOPLog;
|
|
||||||
import com.imyeyu.spring.annotation.RequestRateLimit;
|
|
||||||
import com.imyeyu.spring.bean.PageResult;
|
|
||||||
import lombok.RequiredArgsConstructor;
|
|
||||||
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;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
/// GAO 套餐配置接口
|
|
||||||
///
|
|
||||||
/// @author Codex
|
|
||||||
/// @since 2026-08-31
|
|
||||||
@RestController
|
|
||||||
@RequiredArgsConstructor
|
|
||||||
@RequestMapping("/gao/package/config")
|
|
||||||
public class GaoPackageConfigController {
|
|
||||||
|
|
||||||
private final GaoPackageConfigService service;
|
|
||||||
private final GaoStoreScopeService storeScopeService;
|
|
||||||
private final UserService userService;
|
|
||||||
|
|
||||||
@AOPLog
|
|
||||||
@RequestRateLimit
|
|
||||||
@RequireGaoPermission(GaoPermissionCode.PACKAGE_CONFIG_READ)
|
|
||||||
@PostMapping("/list")
|
|
||||||
public PageResult<GaoPackageConfig> list(@RequestBody GaoPackageConfigPage page) {
|
|
||||||
TimiException.required(page, "not found page");
|
|
||||||
page.setStoreId(storeScopeService.resolveStoreId(page.getStoreId()));
|
|
||||||
PageResult<GaoPackageConfig> result = service.pageByQuery(page);
|
|
||||||
fillTransient(result.getList());
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
@AOPLog
|
|
||||||
@RequestRateLimit
|
|
||||||
@RequireGaoPermission(GaoPermissionCode.PACKAGE_CONFIG_READ)
|
|
||||||
@PostMapping("/list/valid")
|
|
||||||
public List<GaoPackageConfig> listValid(@RequestParam String storeId) {
|
|
||||||
List<GaoPackageConfig> result = service.listValid(storeScopeService.resolveStoreId(storeId));
|
|
||||||
fillTransient(result);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
@AOPLog
|
|
||||||
@RequestRateLimit
|
|
||||||
@RequireGaoPermission(GaoPermissionCode.PACKAGE_CONFIG_READ)
|
|
||||||
@PostMapping("/detail")
|
|
||||||
public GaoPackageConfig detail(@RequestParam String id) {
|
|
||||||
GaoPackageConfig config = service.get(id);
|
|
||||||
TimiException.required(config, "not found package config");
|
|
||||||
storeScopeService.checkStoreId(config.getStoreId());
|
|
||||||
fillTransient(List.of(config));
|
|
||||||
return config;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void fillTransient(List<GaoPackageConfig> configList) {
|
|
||||||
if (configList == null || configList.isEmpty()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
Map<String, List<GaoPackageConfigItem>> itemMap = service.mapItemListByPackageConfigIdList(configList.stream().map(GaoPackageConfig::getId).toList());
|
|
||||||
List<String> updaterIdList = configList.stream().map(GaoPackageConfig::getUpdatedBy).filter(value -> value != null && !value.isBlank()).distinct().toList();
|
|
||||||
Map<String, User> updaterMap = updaterIdList.isEmpty() ? Map.of() : userService.mapByIdList(updaterIdList);
|
|
||||||
for (GaoPackageConfig config : configList) {
|
|
||||||
config.setItemList(itemMap.getOrDefault(config.getId(), List.of()));
|
|
||||||
config.setUpdater(updaterMap.get(config.getUpdatedBy()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@AOPLog
|
|
||||||
@RequestRateLimit
|
|
||||||
@RequireGaoPermission(GaoPermissionCode.PACKAGE_CONFIG_CREATE)
|
|
||||||
@PostMapping("/create")
|
|
||||||
public String create(@RequestBody GaoPackageConfig config) {
|
|
||||||
TimiException.required(config, "not found package config");
|
|
||||||
config.setStoreId(storeScopeService.resolveStoreId(config.getStoreId()));
|
|
||||||
service.create(config);
|
|
||||||
return config.getId();
|
|
||||||
}
|
|
||||||
|
|
||||||
@AOPLog
|
|
||||||
@RequestRateLimit
|
|
||||||
@RequireGaoPermission(GaoPermissionCode.PACKAGE_CONFIG_UPDATE)
|
|
||||||
@PostMapping("/update")
|
|
||||||
public void update(@RequestBody GaoPackageConfig config) {
|
|
||||||
TimiException.required(config, "not found package config");
|
|
||||||
TimiException.required(config.getId(), "not found packageConfig.id");
|
|
||||||
GaoPackageConfig dbConfig = service.get(config.getId());
|
|
||||||
TimiException.required(dbConfig, "not found package config");
|
|
||||||
storeScopeService.checkStoreId(dbConfig.getStoreId());
|
|
||||||
config.setStoreId(dbConfig.getStoreId());
|
|
||||||
service.update(config);
|
|
||||||
}
|
|
||||||
|
|
||||||
@AOPLog
|
|
||||||
@RequestRateLimit
|
|
||||||
@RequireGaoPermission(GaoPermissionCode.PACKAGE_CONFIG_DELETE)
|
|
||||||
@PostMapping("/delete")
|
|
||||||
public void delete(@RequestParam String id) {
|
|
||||||
GaoPackageConfig config = service.get(id);
|
|
||||||
TimiException.required(config, "not found package config");
|
|
||||||
storeScopeService.checkStoreId(config.getStoreId());
|
|
||||||
service.delete(id);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
-140
@@ -1,140 +0,0 @@
|
|||||||
package com.imyeyu.api.modules.gao.controller;
|
|
||||||
|
|
||||||
import com.imyeyu.api.modules.common.entity.Attachment;
|
|
||||||
import com.imyeyu.api.modules.common.service.AttachmentService;
|
|
||||||
import com.imyeyu.api.modules.gao.annotation.RequireGaoPermission;
|
|
||||||
import com.imyeyu.api.modules.gao.bean.GaoPermissionCode;
|
|
||||||
import com.imyeyu.api.modules.gao.entity.GaoPackageDelivery;
|
|
||||||
import com.imyeyu.api.modules.gao.entity.GaoPackageDeliveryItem;
|
|
||||||
import com.imyeyu.api.modules.gao.service.GaoPackageDeliveryService;
|
|
||||||
import com.imyeyu.api.modules.gao.service.GaoStoreScopeService;
|
|
||||||
import com.imyeyu.api.modules.gao.vo.GaoPackageDeliveryActionRequest;
|
|
||||||
import com.imyeyu.api.modules.gao.vo.GaoPackageDeliveryCreateRequest;
|
|
||||||
import com.imyeyu.api.modules.gao.vo.GaoPackageDeliveryPage;
|
|
||||||
import com.imyeyu.api.modules.gao.vo.GaoPackageDeliveryRevokeRequest;
|
|
||||||
import com.imyeyu.api.modules.user.entity.User;
|
|
||||||
import com.imyeyu.api.modules.user.service.UserService;
|
|
||||||
import com.imyeyu.java.bean.timi.TimiException;
|
|
||||||
import com.imyeyu.spring.annotation.AOPLog;
|
|
||||||
import com.imyeyu.spring.annotation.RequestRateLimit;
|
|
||||||
import com.imyeyu.spring.bean.PageResult;
|
|
||||||
import lombok.RequiredArgsConstructor;
|
|
||||||
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;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.stream.Stream;
|
|
||||||
|
|
||||||
/// GAO 套餐发放接口
|
|
||||||
///
|
|
||||||
/// @author Codex
|
|
||||||
/// @since 2026-08-31
|
|
||||||
@RestController
|
|
||||||
@RequiredArgsConstructor
|
|
||||||
@RequestMapping("/gao/package/delivery")
|
|
||||||
public class GaoPackageDeliveryController {
|
|
||||||
|
|
||||||
private final GaoPackageDeliveryService service;
|
|
||||||
private final GaoStoreScopeService storeScopeService;
|
|
||||||
private final AttachmentService attachmentService;
|
|
||||||
private final UserService userService;
|
|
||||||
|
|
||||||
@AOPLog
|
|
||||||
@RequestRateLimit
|
|
||||||
@RequireGaoPermission(GaoPermissionCode.PACKAGE_DELIVERY_READ)
|
|
||||||
@PostMapping("/list")
|
|
||||||
public PageResult<GaoPackageDelivery> list(@RequestBody GaoPackageDeliveryPage page) {
|
|
||||||
TimiException.required(page, "not found page");
|
|
||||||
page.setStoreId(storeScopeService.resolveStoreId(page.getStoreId()));
|
|
||||||
PageResult<GaoPackageDelivery> result = service.pageByQuery(page);
|
|
||||||
fillTransient(result.getList());
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
@AOPLog
|
|
||||||
@RequestRateLimit
|
|
||||||
@RequireGaoPermission(GaoPermissionCode.PACKAGE_DELIVERY_READ)
|
|
||||||
@PostMapping("/detail")
|
|
||||||
public GaoPackageDelivery detail(@RequestParam String id) {
|
|
||||||
GaoPackageDelivery result = service.get(id);
|
|
||||||
TimiException.required(result, "not found delivery");
|
|
||||||
storeScopeService.checkStoreId(result.getStoreId());
|
|
||||||
fillTransient(List.of(result));
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
@AOPLog
|
|
||||||
@RequestRateLimit
|
|
||||||
@RequireGaoPermission(GaoPermissionCode.PACKAGE_DELIVERY_CREATE)
|
|
||||||
@PostMapping("/create")
|
|
||||||
public GaoPackageDelivery create(@RequestBody GaoPackageDeliveryCreateRequest request) {
|
|
||||||
GaoPackageDelivery result = service.createDelivery(request);
|
|
||||||
fillTransient(List.of(result));
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
@AOPLog
|
|
||||||
@RequestRateLimit
|
|
||||||
@RequireGaoPermission(GaoPermissionCode.PACKAGE_DELIVERY_VERIFY)
|
|
||||||
@PostMapping("/verify")
|
|
||||||
public GaoPackageDelivery verify(@RequestParam String id) {
|
|
||||||
GaoPackageDelivery result = service.verify(id);
|
|
||||||
fillTransient(List.of(result));
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
@AOPLog
|
|
||||||
@RequestRateLimit
|
|
||||||
@RequireGaoPermission(GaoPermissionCode.PACKAGE_DELIVERY_VERIFY)
|
|
||||||
@PostMapping("/reject")
|
|
||||||
public GaoPackageDelivery reject(@RequestBody GaoPackageDeliveryActionRequest request) {
|
|
||||||
GaoPackageDelivery result = service.reject(request);
|
|
||||||
fillTransient(List.of(result));
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
@AOPLog
|
|
||||||
@RequestRateLimit
|
|
||||||
@RequireGaoPermission(GaoPermissionCode.PACKAGE_DELIVERY_CREATE)
|
|
||||||
@PostMapping("/cancel")
|
|
||||||
public GaoPackageDelivery cancel(@RequestBody GaoPackageDeliveryActionRequest request) {
|
|
||||||
GaoPackageDelivery result = service.cancel(request);
|
|
||||||
fillTransient(List.of(result));
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
@AOPLog
|
|
||||||
@RequestRateLimit
|
|
||||||
@RequireGaoPermission(GaoPermissionCode.PACKAGE_DELIVERY_REVOKE)
|
|
||||||
@PostMapping("/revoke")
|
|
||||||
public GaoPackageDelivery revoke(@RequestBody GaoPackageDeliveryRevokeRequest request) {
|
|
||||||
GaoPackageDelivery result = service.revoke(request);
|
|
||||||
fillTransient(List.of(result));
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void fillTransient(List<GaoPackageDelivery> deliveryList) {
|
|
||||||
if (deliveryList == null || deliveryList.isEmpty()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
List<String> idList = deliveryList.stream().map(GaoPackageDelivery::getId).toList();
|
|
||||||
Map<String, List<GaoPackageDeliveryItem>> itemMap = service.mapItemListByDeliveryIdList(idList);
|
|
||||||
Map<String, List<Attachment>> attachmentMap = attachmentService.mapByBizIdList(Attachment.BizType.GAO_PACKAGE_DELIVERY, idList);
|
|
||||||
List<String> userIdList = deliveryList.stream()
|
|
||||||
.flatMap(delivery -> Stream.of(delivery.getOperatorUserId(), delivery.getVerifierUserId()))
|
|
||||||
.filter(value -> value != null && !value.isBlank())
|
|
||||||
.distinct()
|
|
||||||
.toList();
|
|
||||||
Map<String, User> userMap = userIdList.isEmpty() ? Map.of() : userService.mapByIdList(userIdList);
|
|
||||||
for (GaoPackageDelivery delivery : deliveryList) {
|
|
||||||
delivery.setItemList(itemMap.getOrDefault(delivery.getId(), List.of()));
|
|
||||||
delivery.setAttachmentList(attachmentMap.getOrDefault(delivery.getId(), List.of()));
|
|
||||||
delivery.setOperator(userMap.get(delivery.getOperatorUserId()));
|
|
||||||
delivery.setVerifier(userMap.get(delivery.getVerifierUserId()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,129 +0,0 @@
|
|||||||
package com.imyeyu.api.modules.gao.controller;
|
|
||||||
|
|
||||||
import com.fasterxml.jackson.annotation.JsonView;
|
|
||||||
import com.imyeyu.api.modules.common.entity.Article;
|
|
||||||
import com.imyeyu.api.modules.common.entity.Attachment;
|
|
||||||
import com.imyeyu.api.modules.common.service.AttachmentService;
|
|
||||||
import com.imyeyu.api.modules.gao.annotation.RequireGaoPermission;
|
|
||||||
import com.imyeyu.api.modules.gao.bean.GaoPermissionCode;
|
|
||||||
import com.imyeyu.api.modules.gao.service.GaoStoreDiaryService;
|
|
||||||
import com.imyeyu.api.modules.gao.service.GaoStoreScopeService;
|
|
||||||
import com.imyeyu.api.modules.user.entity.User;
|
|
||||||
import com.imyeyu.api.modules.user.service.UserLoginService;
|
|
||||||
import com.imyeyu.api.modules.user.service.UserService;
|
|
||||||
import com.imyeyu.java.TimiJava;
|
|
||||||
import com.imyeyu.java.bean.timi.TimiException;
|
|
||||||
import com.imyeyu.spring.annotation.AOPLog;
|
|
||||||
import com.imyeyu.spring.annotation.RequestRateLimit;
|
|
||||||
import com.imyeyu.spring.bean.PageResult;
|
|
||||||
import com.imyeyu.api.modules.gao.vo.GaoStoreDiaryPage;
|
|
||||||
import com.imyeyu.spring.util.ResponseView;
|
|
||||||
import lombok.RequiredArgsConstructor;
|
|
||||||
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;
|
|
||||||
|
|
||||||
/// GAO 门店日记接口
|
|
||||||
///
|
|
||||||
/// @author Codex
|
|
||||||
/// @since 2026-08-31
|
|
||||||
@RestController
|
|
||||||
@RequiredArgsConstructor
|
|
||||||
@RequestMapping("/gao/store/diary")
|
|
||||||
public class GaoStoreDiaryController {
|
|
||||||
|
|
||||||
private final GaoStoreDiaryService service;
|
|
||||||
private final GaoStoreScopeService storeScopeService;
|
|
||||||
private final UserLoginService userLoginService;
|
|
||||||
private final UserService userService;
|
|
||||||
private final AttachmentService attachmentService;
|
|
||||||
|
|
||||||
/// 分页查询门店日记
|
|
||||||
///
|
|
||||||
/// @param page 分页查询条件
|
|
||||||
/// @return 门店日记分页结果
|
|
||||||
@AOPLog
|
|
||||||
@RequestRateLimit
|
|
||||||
@RequireGaoPermission(GaoPermissionCode.STORE_DIARY_READ)
|
|
||||||
@PostMapping("/list")
|
|
||||||
@JsonView(ResponseView.Public.class)
|
|
||||||
public PageResult<Article> list(@RequestBody GaoStoreDiaryPage page) {
|
|
||||||
TimiException.required(page, "未找到分页参数");
|
|
||||||
TimiException.required(page.getBeginCreatedAt(), "未找到门店日记开始时间");
|
|
||||||
TimiException.required(page.getEndCreatedAt(), "未找到门店日记结束时间");
|
|
||||||
TimiException.requiredTrue(page.getBeginCreatedAt() < page.getEndCreatedAt(), "门店日记时间范围无效");
|
|
||||||
page.setStoreId(storeScopeService.resolveStoreId(page.getStoreId()));
|
|
||||||
return service.page(page);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// 查询门店日记详情
|
|
||||||
///
|
|
||||||
/// @param id 日记 ID
|
|
||||||
/// @return 门店日记
|
|
||||||
@AOPLog
|
|
||||||
@RequestRateLimit
|
|
||||||
@RequireGaoPermission(GaoPermissionCode.STORE_DIARY_READ)
|
|
||||||
@PostMapping("/detail")
|
|
||||||
@JsonView(ResponseView.Public.class)
|
|
||||||
public Article detail(@RequestParam String id) {
|
|
||||||
Article article = service.get(id);
|
|
||||||
storeScopeService.checkStoreId(article.getBizId());
|
|
||||||
article.setAttachmentList(attachmentService.listByBizId(Attachment.BizType.ARTICLE, article.getId()));
|
|
||||||
if (TimiJava.isNotEmpty(article.getUpdatedBy())) {
|
|
||||||
User updater = userService.get(article.getUpdatedBy());
|
|
||||||
if (updater != null) {
|
|
||||||
updater.setAttachmentList(attachmentService.listByBizId(
|
|
||||||
Attachment.BizType.USER,
|
|
||||||
updater.getId(),
|
|
||||||
User.AttachType.AVATAR.toString()
|
|
||||||
));
|
|
||||||
}
|
|
||||||
article.setUpdater(updater);
|
|
||||||
}
|
|
||||||
return article;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// 创建门店日记
|
|
||||||
///
|
|
||||||
/// @param article 门店日记
|
|
||||||
/// @return 日记 ID
|
|
||||||
@AOPLog
|
|
||||||
@RequestRateLimit
|
|
||||||
@RequireGaoPermission(GaoPermissionCode.STORE_DIARY_CREATE)
|
|
||||||
@PostMapping("/create")
|
|
||||||
public String create(@RequestBody Article article) {
|
|
||||||
article.setBizId(storeScopeService.resolveStoreId(article.getBizId()));
|
|
||||||
service.create(article, userLoginService.getRequireLoginUserId());
|
|
||||||
return article.getId();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// 修改门店日记
|
|
||||||
///
|
|
||||||
/// @param article 门店日记
|
|
||||||
@AOPLog
|
|
||||||
@RequestRateLimit
|
|
||||||
@RequireGaoPermission(GaoPermissionCode.STORE_DIARY_UPDATE)
|
|
||||||
@PostMapping("/update")
|
|
||||||
public void update(@RequestBody Article article) {
|
|
||||||
TimiException.required(article, "未找到门店日记");
|
|
||||||
TimiException.required(article.getId(), "未找到门店日记 ID");
|
|
||||||
Article dbArticle = service.get(article.getId());
|
|
||||||
storeScopeService.checkStoreId(dbArticle.getBizId());
|
|
||||||
service.update(article, userLoginService.getRequireLoginUserId());
|
|
||||||
}
|
|
||||||
|
|
||||||
/// 删除门店日记
|
|
||||||
///
|
|
||||||
/// @param id 日记 ID
|
|
||||||
@AOPLog
|
|
||||||
@RequestRateLimit
|
|
||||||
@RequireGaoPermission(GaoPermissionCode.STORE_DIARY_DELETE)
|
|
||||||
@PostMapping("/delete")
|
|
||||||
public void delete(@RequestParam String id) {
|
|
||||||
Article article = service.get(id);
|
|
||||||
storeScopeService.checkStoreId(article.getBizId());
|
|
||||||
service.delete(article.getId());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,145 +0,0 @@
|
|||||||
package com.imyeyu.api.modules.gao.entity;
|
|
||||||
|
|
||||||
import com.imyeyu.api.modules.user.entity.User;
|
|
||||||
import com.imyeyu.spring.annotation.table.Transient;
|
|
||||||
import com.imyeyu.spring.entity.UUIDEntity;
|
|
||||||
import lombok.Data;
|
|
||||||
import lombok.EqualsAndHashCode;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
/// GAO 客户实际购买的套餐
|
|
||||||
///
|
|
||||||
/// @author Codex
|
|
||||||
/// @since 2026-08-31
|
|
||||||
@Data
|
|
||||||
@EqualsAndHashCode(callSuper = true)
|
|
||||||
public class GaoCustomerPackage extends UUIDEntity {
|
|
||||||
|
|
||||||
/// 客户套餐状态
|
|
||||||
public enum Status {
|
|
||||||
|
|
||||||
/// 履约中
|
|
||||||
ACTIVE,
|
|
||||||
|
|
||||||
/// 已全部履约
|
|
||||||
FULFILLED,
|
|
||||||
|
|
||||||
/// 已取消
|
|
||||||
CANCELLED
|
|
||||||
}
|
|
||||||
|
|
||||||
/// 付款状态
|
|
||||||
public enum PaymentStatus {
|
|
||||||
|
|
||||||
/// 未付款
|
|
||||||
UNPAID,
|
|
||||||
|
|
||||||
/// 部分付款
|
|
||||||
PARTIALLY_PAID,
|
|
||||||
|
|
||||||
/// 已付清
|
|
||||||
PAID
|
|
||||||
}
|
|
||||||
|
|
||||||
/// 退款状态
|
|
||||||
public enum RefundStatus {
|
|
||||||
|
|
||||||
/// 无需退款
|
|
||||||
NOT_REQUIRED,
|
|
||||||
|
|
||||||
/// 待退款或待确认无需退款
|
|
||||||
PENDING,
|
|
||||||
|
|
||||||
/// 已完成退款处理
|
|
||||||
REFUNDED
|
|
||||||
}
|
|
||||||
|
|
||||||
/// 门店 ID
|
|
||||||
private String storeId;
|
|
||||||
|
|
||||||
/// 客户 ID
|
|
||||||
private String customerId;
|
|
||||||
|
|
||||||
/// 来源套餐配置 ID
|
|
||||||
private String packageConfigId;
|
|
||||||
|
|
||||||
/// 购买事件登记 ID
|
|
||||||
private String purchaseEventRecordId;
|
|
||||||
|
|
||||||
/// 购买幂等请求号
|
|
||||||
private String requestNo;
|
|
||||||
|
|
||||||
/// 套餐名称快照
|
|
||||||
private String packageNameSnapshot;
|
|
||||||
|
|
||||||
/// 标准价快照,单位分
|
|
||||||
private Long standardAmountSnapshot;
|
|
||||||
|
|
||||||
/// 实际成交价,单位分
|
|
||||||
private Long saleAmount;
|
|
||||||
|
|
||||||
/// 待核销收款合计,单位分
|
|
||||||
private Long pendingPaidAmount;
|
|
||||||
|
|
||||||
/// 累计有效收款,单位分
|
|
||||||
private Long paidAmount;
|
|
||||||
|
|
||||||
/// 累计有效退款,单位分
|
|
||||||
private Long refundedAmount;
|
|
||||||
|
|
||||||
/// 套餐状态
|
|
||||||
private Status status;
|
|
||||||
|
|
||||||
/// 付款状态
|
|
||||||
private PaymentStatus paymentStatus;
|
|
||||||
|
|
||||||
/// 退款状态
|
|
||||||
private RefundStatus refundStatus;
|
|
||||||
|
|
||||||
/// 购买时间
|
|
||||||
private Long purchasedAt;
|
|
||||||
|
|
||||||
/// 购买登记人
|
|
||||||
private String operatorUserId;
|
|
||||||
|
|
||||||
/// 取消时间
|
|
||||||
private Long cancelledAt;
|
|
||||||
|
|
||||||
/// 取消操作人
|
|
||||||
private String cancelOperatorUserId;
|
|
||||||
|
|
||||||
/// 取消原因
|
|
||||||
private String cancelReason;
|
|
||||||
|
|
||||||
/// 备注
|
|
||||||
private String remark;
|
|
||||||
|
|
||||||
/// 客户
|
|
||||||
@Transient
|
|
||||||
private GaoCustomer customer;
|
|
||||||
|
|
||||||
/// 购买事件登记
|
|
||||||
@Transient
|
|
||||||
private GaoEventRecord purchaseEventRecord;
|
|
||||||
|
|
||||||
/// 购买操作人
|
|
||||||
@Transient
|
|
||||||
private User operator;
|
|
||||||
|
|
||||||
/// 取消操作人
|
|
||||||
@Transient
|
|
||||||
private User cancelOperator;
|
|
||||||
|
|
||||||
/// 产品权益列表
|
|
||||||
@Transient
|
|
||||||
private List<GaoCustomerPackageItem> itemList;
|
|
||||||
|
|
||||||
/// 发放历史
|
|
||||||
@Transient
|
|
||||||
private List<GaoPackageDelivery> deliveryList;
|
|
||||||
|
|
||||||
/// 资金历史
|
|
||||||
@Transient
|
|
||||||
private List<GaoFundRecord> fundRecordList;
|
|
||||||
}
|
|
||||||
@@ -1,53 +0,0 @@
|
|||||||
package com.imyeyu.api.modules.gao.entity;
|
|
||||||
|
|
||||||
import com.imyeyu.spring.annotation.table.Transient;
|
|
||||||
import com.imyeyu.spring.entity.UUIDEntity;
|
|
||||||
import lombok.Data;
|
|
||||||
import lombok.EqualsAndHashCode;
|
|
||||||
|
|
||||||
import java.math.BigDecimal;
|
|
||||||
|
|
||||||
/// GAO 客户套餐产品权益快照
|
|
||||||
///
|
|
||||||
/// @author Codex
|
|
||||||
/// @since 2026-08-31
|
|
||||||
@Data
|
|
||||||
@EqualsAndHashCode(callSuper = true)
|
|
||||||
public class GaoCustomerPackageItem extends UUIDEntity {
|
|
||||||
|
|
||||||
/// 客户套餐 ID
|
|
||||||
private String customerPackageId;
|
|
||||||
|
|
||||||
/// 产品名称快照
|
|
||||||
private String productNameSnapshot;
|
|
||||||
|
|
||||||
/// 产品单位快照
|
|
||||||
private String unitSnapshot;
|
|
||||||
|
|
||||||
/// 总权益数量
|
|
||||||
private BigDecimal totalQuantity;
|
|
||||||
|
|
||||||
/// 待核销占用数量
|
|
||||||
private BigDecimal reservedQuantity;
|
|
||||||
|
|
||||||
/// 已核销净发放数量
|
|
||||||
private BigDecimal deliveredQuantity;
|
|
||||||
|
|
||||||
/// 排序值
|
|
||||||
private Integer sort;
|
|
||||||
|
|
||||||
/// 备注
|
|
||||||
private String remark;
|
|
||||||
|
|
||||||
/// 待核销数量
|
|
||||||
@Transient
|
|
||||||
private BigDecimal pendingQuantity;
|
|
||||||
|
|
||||||
/// 当前可发数量
|
|
||||||
@Transient
|
|
||||||
private BigDecimal availableQuantity;
|
|
||||||
|
|
||||||
/// 权益剩余数量
|
|
||||||
@Transient
|
|
||||||
private BigDecimal remainingQuantity;
|
|
||||||
}
|
|
||||||
@@ -18,16 +18,6 @@ import java.util.List;
|
|||||||
@EqualsAndHashCode(callSuper = true)
|
@EqualsAndHashCode(callSuper = true)
|
||||||
public class GaoEvent extends UUIDEntity {
|
public class GaoEvent extends UUIDEntity {
|
||||||
|
|
||||||
/// 事件业务类型
|
|
||||||
public enum BizType {
|
|
||||||
|
|
||||||
/// 普通登记事件
|
|
||||||
GENERAL,
|
|
||||||
|
|
||||||
/// 购买产品套餐
|
|
||||||
PACKAGE_PURCHASE
|
|
||||||
}
|
|
||||||
|
|
||||||
///
|
///
|
||||||
/// 登记事件状态
|
/// 登记事件状态
|
||||||
///
|
///
|
||||||
@@ -103,16 +93,6 @@ public class GaoEvent extends UUIDEntity {
|
|||||||
/// 统计图表颜色
|
/// 统计图表颜色
|
||||||
private String color;
|
private String color;
|
||||||
|
|
||||||
/// 业务类型
|
|
||||||
private BizType bizType;
|
|
||||||
|
|
||||||
/// 购买套餐事件绑定的套餐配置 ID
|
|
||||||
private String packageConfigId;
|
|
||||||
|
|
||||||
/// 购买套餐事件绑定的套餐配置
|
|
||||||
@Transient
|
|
||||||
private GaoPackageConfig packageConfig;
|
|
||||||
|
|
||||||
/// 登记事件名称
|
/// 登记事件名称
|
||||||
private String name;
|
private String name;
|
||||||
|
|
||||||
|
|||||||
@@ -87,9 +87,6 @@ public class GaoEventRecord extends UUIDEntity {
|
|||||||
/// 营业日递增序号
|
/// 营业日递增序号
|
||||||
private Long businessDayNo;
|
private Long businessDayNo;
|
||||||
|
|
||||||
/// 最后修改用户 ID
|
|
||||||
private String updatedBy;
|
|
||||||
|
|
||||||
@Transient
|
@Transient
|
||||||
private GaoCustomer customer;
|
private GaoCustomer customer;
|
||||||
|
|
||||||
@@ -102,10 +99,6 @@ public class GaoEventRecord extends UUIDEntity {
|
|||||||
@Transient
|
@Transient
|
||||||
private User verifier;
|
private User verifier;
|
||||||
|
|
||||||
/// 最后修改用户
|
|
||||||
@Transient
|
|
||||||
private User updater;
|
|
||||||
|
|
||||||
@Transient
|
@Transient
|
||||||
private List<Attachment> attachmentList;
|
private List<Attachment> attachmentList;
|
||||||
|
|
||||||
|
|||||||
@@ -1,115 +0,0 @@
|
|||||||
package com.imyeyu.api.modules.gao.entity;
|
|
||||||
|
|
||||||
import com.imyeyu.api.modules.common.entity.Attachment;
|
|
||||||
import com.imyeyu.api.modules.user.entity.User;
|
|
||||||
import com.imyeyu.spring.annotation.table.Transient;
|
|
||||||
import com.imyeyu.spring.entity.UUIDEntity;
|
|
||||||
import lombok.Data;
|
|
||||||
import lombok.EqualsAndHashCode;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
/// GAO 通用资金操作流水
|
|
||||||
///
|
|
||||||
/// @author Codex
|
|
||||||
/// @since 2026-08-31
|
|
||||||
@Data
|
|
||||||
@EqualsAndHashCode(callSuper = true)
|
|
||||||
public class GaoFundRecord extends UUIDEntity {
|
|
||||||
|
|
||||||
/// 资金业务类型
|
|
||||||
public enum BizType {
|
|
||||||
|
|
||||||
/// 客户套餐
|
|
||||||
CUSTOMER_PACKAGE
|
|
||||||
}
|
|
||||||
|
|
||||||
/// 资金操作类型
|
|
||||||
public enum OperationType {
|
|
||||||
|
|
||||||
/// 线下收款
|
|
||||||
RECEIVE,
|
|
||||||
|
|
||||||
/// 退款
|
|
||||||
REFUND,
|
|
||||||
|
|
||||||
/// 确认无需退款
|
|
||||||
CONFIRM_NO_REFUND,
|
|
||||||
|
|
||||||
/// 资金操作冲正
|
|
||||||
REVOKE
|
|
||||||
}
|
|
||||||
|
|
||||||
/// 资金操作状态
|
|
||||||
public enum Status {
|
|
||||||
|
|
||||||
/// 待店长核销
|
|
||||||
PENDING,
|
|
||||||
|
|
||||||
/// 已生效
|
|
||||||
VERIFIED,
|
|
||||||
|
|
||||||
/// 店长已拒绝
|
|
||||||
REJECTED,
|
|
||||||
|
|
||||||
/// 提交人已撤销
|
|
||||||
CANCELLED
|
|
||||||
}
|
|
||||||
|
|
||||||
/// 门店 ID
|
|
||||||
private String storeId;
|
|
||||||
|
|
||||||
/// 客户 ID
|
|
||||||
private String customerId;
|
|
||||||
|
|
||||||
/// 资金业务类型
|
|
||||||
private BizType bizType;
|
|
||||||
|
|
||||||
/// 业务对象 ID
|
|
||||||
private String bizId;
|
|
||||||
|
|
||||||
/// 操作类型
|
|
||||||
private OperationType operationType;
|
|
||||||
|
|
||||||
/// 操作状态
|
|
||||||
private Status status;
|
|
||||||
|
|
||||||
/// 金额,单位分
|
|
||||||
private Long amount;
|
|
||||||
|
|
||||||
/// 冲正时关联原资金记录
|
|
||||||
private String sourceRecordId;
|
|
||||||
|
|
||||||
/// 幂等请求号
|
|
||||||
private String requestNo;
|
|
||||||
|
|
||||||
/// 提交操作的用户 ID
|
|
||||||
private String operatorUserId;
|
|
||||||
|
|
||||||
/// 收款核销用户 ID
|
|
||||||
private String verifierUserId;
|
|
||||||
|
|
||||||
/// 收款核销时间
|
|
||||||
private Long verifiedAt;
|
|
||||||
|
|
||||||
/// 线下操作发生时间
|
|
||||||
private Long occurredAt;
|
|
||||||
|
|
||||||
/// 原因
|
|
||||||
private String reason;
|
|
||||||
|
|
||||||
/// 备注
|
|
||||||
private String remark;
|
|
||||||
|
|
||||||
/// 操作人
|
|
||||||
@Transient
|
|
||||||
private User operator;
|
|
||||||
|
|
||||||
/// 核销人
|
|
||||||
@Transient
|
|
||||||
private User verifier;
|
|
||||||
|
|
||||||
/// 附件
|
|
||||||
@Transient
|
|
||||||
private List<Attachment> attachmentList;
|
|
||||||
}
|
|
||||||
@@ -1,66 +0,0 @@
|
|||||||
package com.imyeyu.api.modules.gao.entity;
|
|
||||||
|
|
||||||
import com.imyeyu.api.modules.user.entity.User;
|
|
||||||
import com.imyeyu.spring.annotation.table.Transient;
|
|
||||||
import com.imyeyu.spring.entity.UUIDEntity;
|
|
||||||
import lombok.Data;
|
|
||||||
import lombok.EqualsAndHashCode;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
/// GAO 套餐配置
|
|
||||||
///
|
|
||||||
/// @author Codex
|
|
||||||
/// @since 2026-08-31
|
|
||||||
@Data
|
|
||||||
@EqualsAndHashCode(callSuper = true)
|
|
||||||
public class GaoPackageConfig extends UUIDEntity {
|
|
||||||
|
|
||||||
/// 套餐配置状态
|
|
||||||
public enum Status {
|
|
||||||
|
|
||||||
/// 草稿,不可销售
|
|
||||||
DRAFT,
|
|
||||||
|
|
||||||
/// 启用,可在有效期内销售
|
|
||||||
ACTIVE,
|
|
||||||
|
|
||||||
/// 停用,不可销售
|
|
||||||
INACTIVE
|
|
||||||
}
|
|
||||||
|
|
||||||
/// 门店 ID
|
|
||||||
private String storeId;
|
|
||||||
|
|
||||||
/// 套餐名称
|
|
||||||
private String name;
|
|
||||||
|
|
||||||
/// 套餐说明
|
|
||||||
private String description;
|
|
||||||
|
|
||||||
/// 标准总价,单位分
|
|
||||||
private Long standardAmount;
|
|
||||||
|
|
||||||
/// 状态
|
|
||||||
private Status status;
|
|
||||||
|
|
||||||
/// 生效开始时间戳,毫秒,空为不限制
|
|
||||||
private Long beginAt;
|
|
||||||
|
|
||||||
/// 生效结束时间戳,毫秒,空为不限制
|
|
||||||
private Long endAt;
|
|
||||||
|
|
||||||
/// 排序值
|
|
||||||
private Integer sort;
|
|
||||||
|
|
||||||
/// 最后修改用户 ID
|
|
||||||
private String updatedBy;
|
|
||||||
|
|
||||||
/// 最后修改用户
|
|
||||||
@Transient
|
|
||||||
private User updater;
|
|
||||||
|
|
||||||
/// 配置产品列表
|
|
||||||
@Transient
|
|
||||||
private List<GaoPackageConfigItem> itemList;
|
|
||||||
}
|
|
||||||
@@ -1,34 +0,0 @@
|
|||||||
package com.imyeyu.api.modules.gao.entity;
|
|
||||||
|
|
||||||
import com.imyeyu.spring.entity.UUIDEntity;
|
|
||||||
import lombok.Data;
|
|
||||||
import lombok.EqualsAndHashCode;
|
|
||||||
|
|
||||||
import java.math.BigDecimal;
|
|
||||||
|
|
||||||
/// GAO 套餐配置产品明细
|
|
||||||
///
|
|
||||||
/// @author Codex
|
|
||||||
/// @since 2026-08-31
|
|
||||||
@Data
|
|
||||||
@EqualsAndHashCode(callSuper = true)
|
|
||||||
public class GaoPackageConfigItem extends UUIDEntity {
|
|
||||||
|
|
||||||
/// 套餐配置 ID
|
|
||||||
private String packageConfigId;
|
|
||||||
|
|
||||||
/// 产品名称
|
|
||||||
private String productName;
|
|
||||||
|
|
||||||
/// 产品单位
|
|
||||||
private String unit;
|
|
||||||
|
|
||||||
/// 默认数量
|
|
||||||
private BigDecimal defaultQuantity;
|
|
||||||
|
|
||||||
/// 排序值
|
|
||||||
private Integer sort;
|
|
||||||
|
|
||||||
/// 备注
|
|
||||||
private String remark;
|
|
||||||
}
|
|
||||||
@@ -1,107 +0,0 @@
|
|||||||
package com.imyeyu.api.modules.gao.entity;
|
|
||||||
|
|
||||||
import com.imyeyu.api.modules.common.entity.Attachment;
|
|
||||||
import com.imyeyu.api.modules.user.entity.User;
|
|
||||||
import com.imyeyu.spring.annotation.table.Transient;
|
|
||||||
import com.imyeyu.spring.entity.UUIDEntity;
|
|
||||||
import lombok.Data;
|
|
||||||
import lombok.EqualsAndHashCode;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
/// GAO 套餐发放操作
|
|
||||||
///
|
|
||||||
/// @author Codex
|
|
||||||
/// @since 2026-08-31
|
|
||||||
@Data
|
|
||||||
@EqualsAndHashCode(callSuper = true)
|
|
||||||
public class GaoPackageDelivery extends UUIDEntity {
|
|
||||||
|
|
||||||
/// 发放操作类型
|
|
||||||
public enum OperationType {
|
|
||||||
|
|
||||||
/// 正常发放
|
|
||||||
DELIVER,
|
|
||||||
|
|
||||||
/// 整单冲正
|
|
||||||
REVOKE
|
|
||||||
}
|
|
||||||
|
|
||||||
/// 发放状态
|
|
||||||
public enum Status {
|
|
||||||
|
|
||||||
/// 待核销
|
|
||||||
PENDING,
|
|
||||||
|
|
||||||
/// 已核销
|
|
||||||
VERIFIED,
|
|
||||||
|
|
||||||
/// 店长已拒绝
|
|
||||||
REJECTED,
|
|
||||||
|
|
||||||
/// 提交人已撤销
|
|
||||||
CANCELLED,
|
|
||||||
|
|
||||||
/// 已核销后被整单冲正
|
|
||||||
REVOKED
|
|
||||||
}
|
|
||||||
|
|
||||||
/// 客户套餐 ID
|
|
||||||
private String customerPackageId;
|
|
||||||
|
|
||||||
/// 门店 ID
|
|
||||||
private String storeId;
|
|
||||||
|
|
||||||
/// 客户 ID
|
|
||||||
private String customerId;
|
|
||||||
|
|
||||||
/// 操作类型
|
|
||||||
private OperationType operationType;
|
|
||||||
|
|
||||||
/// 发放状态
|
|
||||||
private Status status;
|
|
||||||
|
|
||||||
/// 客户端幂等请求号
|
|
||||||
private String requestNo;
|
|
||||||
|
|
||||||
/// 提交人
|
|
||||||
private String operatorUserId;
|
|
||||||
|
|
||||||
/// 实际发放时间
|
|
||||||
private Long deliveredAt;
|
|
||||||
|
|
||||||
/// 核销或拒绝操作人
|
|
||||||
private String verifierUserId;
|
|
||||||
|
|
||||||
/// 核销或拒绝时间
|
|
||||||
private Long verifiedAt;
|
|
||||||
|
|
||||||
/// 冲正单指向原发放单
|
|
||||||
private String sourceDeliveryId;
|
|
||||||
|
|
||||||
/// 拒绝、撤销或冲正原因
|
|
||||||
private String reason;
|
|
||||||
|
|
||||||
/// 备注
|
|
||||||
private String remark;
|
|
||||||
|
|
||||||
/// 操作人
|
|
||||||
@Transient
|
|
||||||
private User operator;
|
|
||||||
|
|
||||||
/// 核销或拒绝操作人
|
|
||||||
@Transient
|
|
||||||
private User verifier;
|
|
||||||
|
|
||||||
/// 原发放单
|
|
||||||
@Transient
|
|
||||||
private GaoPackageDelivery sourceDelivery;
|
|
||||||
|
|
||||||
/// 发放明细
|
|
||||||
@Transient
|
|
||||||
private List<GaoPackageDeliveryItem> itemList;
|
|
||||||
|
|
||||||
/// 附件
|
|
||||||
@Transient
|
|
||||||
private List<Attachment> attachmentList;
|
|
||||||
}
|
|
||||||
@@ -1,43 +0,0 @@
|
|||||||
package com.imyeyu.api.modules.gao.entity;
|
|
||||||
|
|
||||||
import com.imyeyu.spring.entity.UUIDEntity;
|
|
||||||
import lombok.Data;
|
|
||||||
import lombok.EqualsAndHashCode;
|
|
||||||
|
|
||||||
import java.math.BigDecimal;
|
|
||||||
|
|
||||||
/// GAO 套餐发放产品明细
|
|
||||||
///
|
|
||||||
/// @author Codex
|
|
||||||
/// @since 2026-08-31
|
|
||||||
@Data
|
|
||||||
@EqualsAndHashCode(callSuper = true)
|
|
||||||
public class GaoPackageDeliveryItem extends UUIDEntity {
|
|
||||||
|
|
||||||
/// 发放单 ID
|
|
||||||
private String deliveryId;
|
|
||||||
|
|
||||||
/// 客户套餐产品 ID
|
|
||||||
private String customerPackageItemId;
|
|
||||||
|
|
||||||
/// 本次数量
|
|
||||||
private BigDecimal quantity;
|
|
||||||
|
|
||||||
/// 操作前占用数量快照
|
|
||||||
private BigDecimal reservedBefore;
|
|
||||||
|
|
||||||
/// 操作后占用数量快照
|
|
||||||
private BigDecimal reservedAfter;
|
|
||||||
|
|
||||||
/// 操作前已发数量快照
|
|
||||||
private BigDecimal deliveredBefore;
|
|
||||||
|
|
||||||
/// 操作后已发数量快照
|
|
||||||
private BigDecimal deliveredAfter;
|
|
||||||
|
|
||||||
/// 产品名称快照
|
|
||||||
private String productNameSnapshot;
|
|
||||||
|
|
||||||
/// 产品单位快照
|
|
||||||
private String unitSnapshot;
|
|
||||||
}
|
|
||||||
@@ -1,30 +0,0 @@
|
|||||||
package com.imyeyu.api.modules.gao.mapper;
|
|
||||||
|
|
||||||
import com.imyeyu.api.modules.gao.entity.GaoCustomerPackageItem;
|
|
||||||
import com.imyeyu.spring.mapper.BaseMapper;
|
|
||||||
import org.apache.ibatis.annotations.Param;
|
|
||||||
|
|
||||||
import java.util.Collection;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
/// GAO 客户套餐产品权益 Mapper
|
|
||||||
///
|
|
||||||
/// @author Codex
|
|
||||||
/// @since 2026-08-31
|
|
||||||
public interface GaoCustomerPackageItemMapper extends BaseMapper<GaoCustomerPackageItem, String> {
|
|
||||||
|
|
||||||
/// 按客户套餐查询产品权益
|
|
||||||
List<GaoCustomerPackageItem> selectByCustomerPackageId(@Param("customerPackageId") String customerPackageId);
|
|
||||||
|
|
||||||
/// 批量查询客户套餐产品权益
|
|
||||||
List<GaoCustomerPackageItem> selectByCustomerPackageIdList(@Param("customerPackageIdList") Collection<String> customerPackageIdList);
|
|
||||||
|
|
||||||
/// 锁定客户套餐产品
|
|
||||||
GaoCustomerPackageItem selectForUpdate(@Param("id") String id);
|
|
||||||
|
|
||||||
/// 调整待核销占用数量
|
|
||||||
int updateReservedQuantity(@Param("id") String id, @Param("delta") java.math.BigDecimal delta);
|
|
||||||
|
|
||||||
/// 调整已核销发放数量
|
|
||||||
int updateDeliveredQuantity(@Param("id") String id, @Param("delta") java.math.BigDecimal delta);
|
|
||||||
}
|
|
||||||
@@ -1,40 +0,0 @@
|
|||||||
package com.imyeyu.api.modules.gao.mapper;
|
|
||||||
|
|
||||||
import com.imyeyu.api.modules.gao.entity.GaoCustomerPackage;
|
|
||||||
import com.imyeyu.api.modules.gao.vo.GaoCustomerPackagePage;
|
|
||||||
import com.imyeyu.spring.mapper.BaseMapper;
|
|
||||||
import org.apache.ibatis.annotations.Param;
|
|
||||||
|
|
||||||
/// GAO 客户套餐 Mapper
|
|
||||||
///
|
|
||||||
/// @author Codex
|
|
||||||
/// @since 2026-08-31
|
|
||||||
public interface GaoCustomerPackageMapper extends BaseMapper<GaoCustomerPackage, String> {
|
|
||||||
|
|
||||||
/// 按门店和请求号查询购买结果
|
|
||||||
GaoCustomerPackage selectByRequestNo(@Param("storeId") String storeId, @Param("requestNo") String requestNo);
|
|
||||||
|
|
||||||
/// 按请求号查询购买结果,用于配置删除后的幂等重试
|
|
||||||
GaoCustomerPackage selectByRequestNoAnyStore(@Param("requestNo") String requestNo);
|
|
||||||
|
|
||||||
/// 锁定客户套餐
|
|
||||||
GaoCustomerPackage selectForUpdate(@Param("id") String id);
|
|
||||||
|
|
||||||
/// 按购买事件登记查询客户套餐
|
|
||||||
GaoCustomerPackage selectByPurchaseEventRecordId(@Param("purchaseEventRecordId") String purchaseEventRecordId);
|
|
||||||
|
|
||||||
/// 按条件统计客户套餐
|
|
||||||
long countByQuery(GaoCustomerPackagePage page);
|
|
||||||
|
|
||||||
/// 按条件查询客户套餐
|
|
||||||
java.util.List<GaoCustomerPackage> selectByQuery(GaoCustomerPackagePage page);
|
|
||||||
|
|
||||||
/// 原子调整待核销收款
|
|
||||||
int updatePendingPaidAmountDelta(@Param("id") String id, @Param("delta") Long delta);
|
|
||||||
|
|
||||||
/// 原子调整有效收款
|
|
||||||
int updatePaidAmountDelta(@Param("id") String id, @Param("delta") Long delta);
|
|
||||||
|
|
||||||
/// 带状态条件更新套餐状态
|
|
||||||
int updateStatusIf(@Param("id") String id, @Param("fromStatus") GaoCustomerPackage.Status fromStatus, @Param("toStatus") GaoCustomerPackage.Status toStatus, @Param("cancelledAt") Long cancelledAt, @Param("cancelOperatorUserId") String cancelOperatorUserId, @Param("cancelReason") String cancelReason, @Param("refundStatus") GaoCustomerPackage.RefundStatus refundStatus);
|
|
||||||
}
|
|
||||||
@@ -1,11 +1,8 @@
|
|||||||
package com.imyeyu.api.modules.gao.mapper;
|
package com.imyeyu.api.modules.gao.mapper;
|
||||||
|
|
||||||
import com.imyeyu.api.modules.gao.entity.GaoEvent;
|
import com.imyeyu.api.modules.gao.entity.GaoEvent;
|
||||||
import com.imyeyu.spring.bean.Page;
|
|
||||||
import com.imyeyu.spring.mapper.BaseMapper;
|
import com.imyeyu.spring.mapper.BaseMapper;
|
||||||
import org.apache.ibatis.annotations.Param;
|
import org.apache.ibatis.annotations.Param;
|
||||||
import org.apache.ibatis.annotations.Select;
|
|
||||||
import org.apache.ibatis.annotations.SelectProvider;
|
|
||||||
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@@ -17,16 +14,7 @@ import java.util.List;
|
|||||||
/// @since 2026-07-27 15:53
|
/// @since 2026-07-27 15:53
|
||||||
public interface GaoEventMapper extends BaseMapper<GaoEvent, String> {
|
public interface GaoEventMapper extends BaseMapper<GaoEvent, String> {
|
||||||
|
|
||||||
@SelectProvider(type = GaoEventSQLProvider.class, method = "selectPageWithoutDeleted")
|
|
||||||
List<GaoEvent> selectPageWithoutDeleted(Page<GaoEvent> page);
|
|
||||||
|
|
||||||
@SelectProvider(type = GaoEventSQLProvider.class, method = "countPageWithoutDeleted")
|
|
||||||
long countPageWithoutDeleted(Page<GaoEvent> page);
|
|
||||||
|
|
||||||
List<GaoEvent> selectByIdList(Collection<String> idList);
|
List<GaoEvent> selectByIdList(Collection<String> idList);
|
||||||
|
|
||||||
List<GaoEvent> selectValidList(@Param("storeId") String storeId, @Param("now") Long now);
|
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,7 +12,6 @@ import com.imyeyu.api.modules.gao.vo.GaoEventOptionStatView;
|
|||||||
import com.imyeyu.api.modules.gao.vo.GaoStoreChartReq;
|
import com.imyeyu.api.modules.gao.vo.GaoStoreChartReq;
|
||||||
import com.imyeyu.spring.mapper.BaseMapper;
|
import com.imyeyu.spring.mapper.BaseMapper;
|
||||||
import org.apache.ibatis.annotations.Param;
|
import org.apache.ibatis.annotations.Param;
|
||||||
import org.apache.ibatis.annotations.Select;
|
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
@@ -22,13 +21,6 @@ import java.util.List;
|
|||||||
/// @since 2026-07-27 14:11
|
/// @since 2026-07-27 14:11
|
||||||
public interface GaoEventRecordMapper extends BaseMapper<GaoEventRecord, String> {
|
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);
|
Long count(String storeId, String customerId, String eventId, Long beginAt, Long endAt);
|
||||||
|
|
||||||
/// 查询事件中已携带数值的登记记录数量
|
/// 查询事件中已携带数值的登记记录数量
|
||||||
@@ -58,9 +50,8 @@ public interface GaoEventRecordMapper extends BaseMapper<GaoEventRecord, String>
|
|||||||
/// @param id 登记记录 ID
|
/// @param id 登记记录 ID
|
||||||
/// @param verifierUserId 核销用户 ID
|
/// @param verifierUserId 核销用户 ID
|
||||||
/// @param verifiedAt 核销时间
|
/// @param verifiedAt 核销时间
|
||||||
/// @param updatedBy 最后修改用户 ID
|
|
||||||
/// @return 更新行数
|
/// @return 更新行数
|
||||||
int verify(@Param("id") String id, @Param("verifierUserId") String verifierUserId, @Param("verifiedAt") Long verifiedAt, @Param("updatedBy") String updatedBy);
|
int verify(@Param("id") String id, @Param("verifierUserId") String verifierUserId, @Param("verifiedAt") Long verifiedAt);
|
||||||
|
|
||||||
/// 按门店和登记日期统计登记记录数
|
/// 按门店和登记日期统计登记记录数
|
||||||
///
|
///
|
||||||
|
|||||||
@@ -1,32 +0,0 @@
|
|||||||
package com.imyeyu.api.modules.gao.mapper;
|
|
||||||
|
|
||||||
import com.imyeyu.api.modules.gao.entity.GaoEvent;
|
|
||||||
import com.imyeyu.spring.bean.Page;
|
|
||||||
import com.imyeyu.spring.util.SQLProvider;
|
|
||||||
import org.apache.ibatis.annotations.Param;
|
|
||||||
import org.apache.ibatis.builder.annotation.ProviderContext;
|
|
||||||
|
|
||||||
/// 登记事件分页查询 SQL 提供器
|
|
||||||
///
|
|
||||||
/// @author Codex
|
|
||||||
public class GaoEventSQLProvider extends SQLProvider {
|
|
||||||
|
|
||||||
/// 分页查询未删除的登记事件
|
|
||||||
public String selectPageWithoutDeleted(ProviderContext context, @Param("page") Page<?> page) {
|
|
||||||
EntityMeta meta = getEntityMeta(context);
|
|
||||||
return appendWithoutDeleted(buildSelectByPageSQL(meta, meta.getTable(), page, "#{offset}", "#{limit}"));
|
|
||||||
}
|
|
||||||
|
|
||||||
/// 统计未删除的登记事件
|
|
||||||
public String countPageWithoutDeleted(ProviderContext context, @Param("page") Page<?> page) {
|
|
||||||
EntityMeta meta = getEntityMeta(context);
|
|
||||||
return appendWithoutDeleted(buildCountByPageSQL(meta, meta.getTable(), page));
|
|
||||||
}
|
|
||||||
|
|
||||||
private String appendWithoutDeleted(String sql) {
|
|
||||||
return sql.replace(
|
|
||||||
"WHERE 1 = 1",
|
|
||||||
"WHERE 1 = 1 AND (`status` IS NULL OR `status` <> '%s')".formatted(GaoEvent.Status.DELETED.name())
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,39 +0,0 @@
|
|||||||
package com.imyeyu.api.modules.gao.mapper;
|
|
||||||
|
|
||||||
import com.imyeyu.api.modules.gao.entity.GaoFundRecord;
|
|
||||||
import com.imyeyu.api.modules.gao.vo.GaoFundRecordPage;
|
|
||||||
import com.imyeyu.spring.mapper.BaseMapper;
|
|
||||||
import org.apache.ibatis.annotations.Param;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
/// GAO 资金流水 Mapper
|
|
||||||
///
|
|
||||||
/// @author Codex
|
|
||||||
/// @since 2026-08-31
|
|
||||||
public interface GaoFundRecordMapper extends BaseMapper<GaoFundRecord, String> {
|
|
||||||
|
|
||||||
/// 按门店和请求号查询资金操作
|
|
||||||
GaoFundRecord selectByRequestNo(@Param("storeId") String storeId, @Param("requestNo") String requestNo);
|
|
||||||
|
|
||||||
/// 锁定资金记录
|
|
||||||
GaoFundRecord selectForUpdate(@Param("id") String id);
|
|
||||||
|
|
||||||
/// 查询资金冲正记录
|
|
||||||
GaoFundRecord selectRevokeBySourceRecordId(@Param("sourceRecordId") String sourceRecordId);
|
|
||||||
|
|
||||||
/// 查询客户套餐待核销收款数量
|
|
||||||
long countPendingReceiveByBizId(@Param("bizId") String bizId);
|
|
||||||
|
|
||||||
/// 查询客户套餐资金历史
|
|
||||||
List<GaoFundRecord> selectByBizId(@Param("bizId") String bizId);
|
|
||||||
|
|
||||||
/// 按条件统计资金记录
|
|
||||||
long countByQuery(GaoFundRecordPage page);
|
|
||||||
|
|
||||||
/// 按条件查询资金记录
|
|
||||||
List<GaoFundRecord> selectByQuery(GaoFundRecordPage page);
|
|
||||||
|
|
||||||
/// 带状态条件更新资金记录
|
|
||||||
int updateStatusIf(@Param("id") String id, @Param("fromStatus") GaoFundRecord.Status fromStatus, @Param("toStatus") GaoFundRecord.Status toStatus, @Param("verifierUserId") String verifierUserId, @Param("verifiedAt") Long verifiedAt, @Param("reason") String reason);
|
|
||||||
}
|
|
||||||
@@ -1,21 +0,0 @@
|
|||||||
package com.imyeyu.api.modules.gao.mapper;
|
|
||||||
|
|
||||||
import com.imyeyu.api.modules.gao.entity.GaoPackageConfigItem;
|
|
||||||
import com.imyeyu.spring.mapper.BaseMapper;
|
|
||||||
import org.apache.ibatis.annotations.Param;
|
|
||||||
|
|
||||||
import java.util.Collection;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
/// GAO 套餐配置产品 Mapper
|
|
||||||
///
|
|
||||||
/// @author Codex
|
|
||||||
/// @since 2026-08-31
|
|
||||||
public interface GaoPackageConfigItemMapper extends BaseMapper<GaoPackageConfigItem, String> {
|
|
||||||
|
|
||||||
/// 按套餐配置 ID 查询产品
|
|
||||||
List<GaoPackageConfigItem> selectByPackageConfigId(@Param("packageConfigId") String packageConfigId);
|
|
||||||
|
|
||||||
/// 批量查询套餐配置产品
|
|
||||||
List<GaoPackageConfigItem> selectByPackageConfigIdList(@Param("packageConfigIdList") Collection<String> packageConfigIdList);
|
|
||||||
}
|
|
||||||
@@ -1,31 +0,0 @@
|
|||||||
package com.imyeyu.api.modules.gao.mapper;
|
|
||||||
|
|
||||||
import com.imyeyu.api.modules.gao.entity.GaoPackageConfig;
|
|
||||||
import com.imyeyu.api.modules.gao.vo.GaoPackageConfigPage;
|
|
||||||
import com.imyeyu.spring.mapper.BaseMapper;
|
|
||||||
import org.apache.ibatis.annotations.Param;
|
|
||||||
|
|
||||||
import java.util.Collection;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
/// GAO 套餐配置 Mapper
|
|
||||||
///
|
|
||||||
/// @author Codex
|
|
||||||
/// @since 2026-08-31
|
|
||||||
public interface GaoPackageConfigMapper extends BaseMapper<GaoPackageConfig, String> {
|
|
||||||
|
|
||||||
/// 按 ID 列表查询套餐配置
|
|
||||||
List<GaoPackageConfig> selectByIdList(@Param("idList") Collection<String> idList);
|
|
||||||
|
|
||||||
/// 查询有效可购买套餐
|
|
||||||
List<GaoPackageConfig> selectValidList(@Param("storeId") String storeId, @Param("now") Long now);
|
|
||||||
|
|
||||||
/// 按条件统计套餐配置
|
|
||||||
long countByQuery(GaoPackageConfigPage page);
|
|
||||||
|
|
||||||
/// 按条件查询套餐配置
|
|
||||||
List<GaoPackageConfig> selectByQuery(GaoPackageConfigPage page);
|
|
||||||
|
|
||||||
/// 查询门店内同名配置
|
|
||||||
GaoPackageConfig selectByStoreIdAndName(@Param("storeId") String storeId, @Param("name") String name, @Param("excludeId") String excludeId);
|
|
||||||
}
|
|
||||||
@@ -1,21 +0,0 @@
|
|||||||
package com.imyeyu.api.modules.gao.mapper;
|
|
||||||
|
|
||||||
import com.imyeyu.api.modules.gao.entity.GaoPackageDeliveryItem;
|
|
||||||
import com.imyeyu.spring.mapper.BaseMapper;
|
|
||||||
import org.apache.ibatis.annotations.Param;
|
|
||||||
|
|
||||||
import java.util.Collection;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
/// GAO 套餐发放明细 Mapper
|
|
||||||
///
|
|
||||||
/// @author Codex
|
|
||||||
/// @since 2026-08-31
|
|
||||||
public interface GaoPackageDeliveryItemMapper extends BaseMapper<GaoPackageDeliveryItem, String> {
|
|
||||||
|
|
||||||
/// 按发放单查询明细
|
|
||||||
List<GaoPackageDeliveryItem> selectByDeliveryId(@Param("deliveryId") String deliveryId);
|
|
||||||
|
|
||||||
/// 批量查询发放明细
|
|
||||||
List<GaoPackageDeliveryItem> selectByDeliveryIdList(@Param("deliveryIdList") Collection<String> deliveryIdList);
|
|
||||||
}
|
|
||||||
@@ -1,42 +0,0 @@
|
|||||||
package com.imyeyu.api.modules.gao.mapper;
|
|
||||||
|
|
||||||
import com.imyeyu.api.modules.gao.entity.GaoPackageDelivery;
|
|
||||||
import com.imyeyu.api.modules.gao.vo.GaoPackageDeliveryPage;
|
|
||||||
import com.imyeyu.spring.mapper.BaseMapper;
|
|
||||||
import org.apache.ibatis.annotations.Param;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
/// GAO 套餐发放 Mapper
|
|
||||||
///
|
|
||||||
/// @author Codex
|
|
||||||
/// @since 2026-08-31
|
|
||||||
public interface GaoPackageDeliveryMapper extends BaseMapper<GaoPackageDelivery, String> {
|
|
||||||
|
|
||||||
/// 按门店和请求号查询发放结果
|
|
||||||
GaoPackageDelivery selectByRequestNo(@Param("storeId") String storeId, @Param("requestNo") String requestNo);
|
|
||||||
|
|
||||||
/// 锁定发放单
|
|
||||||
GaoPackageDelivery selectForUpdate(@Param("id") String id);
|
|
||||||
|
|
||||||
/// 查询原发放单的冲正记录
|
|
||||||
GaoPackageDelivery selectRevokeBySourceDeliveryId(@Param("sourceDeliveryId") String sourceDeliveryId);
|
|
||||||
|
|
||||||
/// 查询客户套餐待核销发放数量
|
|
||||||
long countPendingByCustomerPackageId(@Param("customerPackageId") String customerPackageId);
|
|
||||||
|
|
||||||
/// 查询客户套餐已核销正常发放数量
|
|
||||||
long countVerifiedByCustomerPackageId(@Param("customerPackageId") String customerPackageId);
|
|
||||||
|
|
||||||
/// 查询客户套餐发放历史
|
|
||||||
java.util.List<GaoPackageDelivery> selectByCustomerPackageId(@Param("customerPackageId") String customerPackageId);
|
|
||||||
|
|
||||||
/// 按条件统计发放单
|
|
||||||
long countByQuery(GaoPackageDeliveryPage page);
|
|
||||||
|
|
||||||
/// 按条件查询发放单
|
|
||||||
List<GaoPackageDelivery> selectByQuery(GaoPackageDeliveryPage page);
|
|
||||||
|
|
||||||
/// 带状态条件更新发放单
|
|
||||||
int updateStatusIf(@Param("id") String id, @Param("fromStatus") GaoPackageDelivery.Status fromStatus, @Param("toStatus") GaoPackageDelivery.Status toStatus, @Param("verifierUserId") String verifierUserId, @Param("verifiedAt") Long verifiedAt, @Param("reason") String reason);
|
|
||||||
}
|
|
||||||
@@ -1,26 +0,0 @@
|
|||||||
package com.imyeyu.api.modules.gao.mapper;
|
|
||||||
|
|
||||||
import com.imyeyu.api.modules.common.entity.Article;
|
|
||||||
import com.imyeyu.api.modules.gao.vo.GaoStoreDiaryPage;
|
|
||||||
import com.imyeyu.spring.mapper.BaseMapper;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
/// GAO 门店日记 Mapper
|
|
||||||
///
|
|
||||||
/// @author Codex
|
|
||||||
/// @since 2026-08-31
|
|
||||||
public interface GaoStoreDiaryMapper extends BaseMapper<Article, String> {
|
|
||||||
|
|
||||||
/// 查询月份内的门店日记
|
|
||||||
///
|
|
||||||
/// @param page 月份分页查询请求
|
|
||||||
/// @return 门店日记列表
|
|
||||||
List<Article> selectByMonth(GaoStoreDiaryPage page);
|
|
||||||
|
|
||||||
/// 统计月份内的门店日记数量
|
|
||||||
///
|
|
||||||
/// @param page 月份分页查询请求
|
|
||||||
/// @return 门店日记数量
|
|
||||||
long countByMonth(GaoStoreDiaryPage page);
|
|
||||||
}
|
|
||||||
@@ -1,87 +0,0 @@
|
|||||||
package com.imyeyu.api.modules.gao.service;
|
|
||||||
|
|
||||||
import com.imyeyu.api.modules.gao.entity.GaoCustomerPackage;
|
|
||||||
import com.imyeyu.api.modules.gao.entity.GaoCustomerPackageItem;
|
|
||||||
import com.imyeyu.api.modules.gao.vo.GaoCustomerPackageCancelRequest;
|
|
||||||
import com.imyeyu.api.modules.gao.vo.GaoCustomerPackagePage;
|
|
||||||
import com.imyeyu.api.modules.gao.vo.GaoCustomerPackagePurchaseRequest;
|
|
||||||
import com.imyeyu.spring.bean.PageResult;
|
|
||||||
import com.imyeyu.spring.service.BaseService;
|
|
||||||
|
|
||||||
import java.math.BigDecimal;
|
|
||||||
import java.util.Collection;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
/// GAO 客户套餐服务
|
|
||||||
///
|
|
||||||
/// @author Codex
|
|
||||||
/// @since 2026-08-31
|
|
||||||
public interface GaoCustomerPackageService extends BaseService<GaoCustomerPackage, String> {
|
|
||||||
|
|
||||||
/// 按条件查询客户套餐
|
|
||||||
PageResult<GaoCustomerPackage> pageByQuery(GaoCustomerPackagePage page);
|
|
||||||
|
|
||||||
/// 创建客户套餐及购买事件登记
|
|
||||||
GaoCustomerPackage purchase(GaoCustomerPackagePurchaseRequest request);
|
|
||||||
|
|
||||||
/// 取消客户套餐
|
|
||||||
GaoCustomerPackage cancel(GaoCustomerPackageCancelRequest request);
|
|
||||||
|
|
||||||
/// 锁定客户套餐
|
|
||||||
///
|
|
||||||
/// @param id 客户套餐 ID
|
|
||||||
/// @return 已锁定的客户套餐,不存在时为空
|
|
||||||
GaoCustomerPackage getForUpdate(String id);
|
|
||||||
|
|
||||||
/// 查询客户套餐产品权益
|
|
||||||
///
|
|
||||||
/// @param customerPackageId 客户套餐 ID
|
|
||||||
/// @return 产品权益列表
|
|
||||||
List<GaoCustomerPackageItem> listItemByCustomerPackageId(String customerPackageId);
|
|
||||||
|
|
||||||
/// 批量查询客户套餐产品权益
|
|
||||||
///
|
|
||||||
/// @param customerPackageIdList 客户套餐 ID 列表
|
|
||||||
/// @return 按客户套餐 ID 分组的产品权益
|
|
||||||
Map<String, List<GaoCustomerPackageItem>> mapItemListByCustomerPackageIdList(Collection<String> customerPackageIdList);
|
|
||||||
|
|
||||||
/// 锁定客户套餐产品权益
|
|
||||||
///
|
|
||||||
/// @param itemId 客户套餐产品权益 ID
|
|
||||||
/// @return 已锁定的产品权益,不存在时为空
|
|
||||||
GaoCustomerPackageItem getItemForUpdate(String itemId);
|
|
||||||
|
|
||||||
/// 原子调整待核销发放占用数量
|
|
||||||
///
|
|
||||||
/// @param itemId 客户套餐产品权益 ID
|
|
||||||
/// @param delta 调整量
|
|
||||||
/// @return 受影响行数
|
|
||||||
int updateItemReservedQuantity(String itemId, BigDecimal delta);
|
|
||||||
|
|
||||||
/// 原子调整已核销发放数量
|
|
||||||
///
|
|
||||||
/// @param itemId 客户套餐产品权益 ID
|
|
||||||
/// @param delta 调整量
|
|
||||||
/// @return 受影响行数
|
|
||||||
int updateItemDeliveredQuantity(String itemId, BigDecimal delta);
|
|
||||||
|
|
||||||
/// 原子调整待核销收款金额
|
|
||||||
///
|
|
||||||
/// @param id 客户套餐 ID
|
|
||||||
/// @param delta 调整量
|
|
||||||
/// @return 受影响行数
|
|
||||||
int updatePendingPaidAmountDelta(String id, Long delta);
|
|
||||||
|
|
||||||
/// 原子调整有效收款金额
|
|
||||||
///
|
|
||||||
/// @param id 客户套餐 ID
|
|
||||||
/// @param delta 调整量
|
|
||||||
/// @return 受影响行数
|
|
||||||
int updatePaidAmountDelta(String id, Long delta);
|
|
||||||
|
|
||||||
/// 保存客户套餐聚合状态
|
|
||||||
///
|
|
||||||
/// @param packageEntity 客户套餐聚合
|
|
||||||
void updateAggregateState(GaoCustomerPackage packageEntity);
|
|
||||||
}
|
|
||||||
@@ -41,18 +41,6 @@ public interface GaoEventRecordService extends BaseService<GaoEventRecord, Strin
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// 创建单条普通事件登记
|
|
||||||
///
|
|
||||||
/// @param record 事件登记
|
|
||||||
/// @return 创建后的事件登记
|
|
||||||
GaoEventRecord createOne(GaoEventRecord record);
|
|
||||||
|
|
||||||
/// 由套餐购买服务创建购买事件登记
|
|
||||||
///
|
|
||||||
/// @param record 购买事件登记
|
|
||||||
/// @return 创建后的事件登记
|
|
||||||
GaoEventRecord createPackagePurchaseRecord(GaoEventRecord record);
|
|
||||||
|
|
||||||
void createWithCustomer(GaoCustomer customer);
|
void createWithCustomer(GaoCustomer customer);
|
||||||
|
|
||||||
/// 按任意时间范围查询登记事件记录
|
/// 按任意时间范围查询登记事件记录
|
||||||
|
|||||||
@@ -2,8 +2,6 @@ package com.imyeyu.api.modules.gao.service;
|
|||||||
|
|
||||||
import com.imyeyu.api.modules.gao.entity.GaoEvent;
|
import com.imyeyu.api.modules.gao.entity.GaoEvent;
|
||||||
import com.imyeyu.api.modules.gao.entity.GaoEventOptionGroup;
|
import com.imyeyu.api.modules.gao.entity.GaoEventOptionGroup;
|
||||||
import com.imyeyu.spring.bean.Page;
|
|
||||||
import com.imyeyu.spring.bean.PageResult;
|
|
||||||
import com.imyeyu.spring.service.BaseService;
|
import com.imyeyu.spring.service.BaseService;
|
||||||
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
@@ -17,12 +15,6 @@ import java.util.Map;
|
|||||||
/// @since 2026-07-27
|
/// @since 2026-07-27
|
||||||
public interface GaoEventService extends BaseService<GaoEvent, String> {
|
public interface GaoEventService extends BaseService<GaoEvent, String> {
|
||||||
|
|
||||||
/// 分页查询未删除的登记事件
|
|
||||||
///
|
|
||||||
/// @param page 分页参数
|
|
||||||
/// @return 登记事件分页结果
|
|
||||||
PageResult<GaoEvent> pageWithoutDeleted(Page<GaoEvent> page);
|
|
||||||
|
|
||||||
Map<String, GaoEvent> mapByIdList(Collection<String> idList);
|
Map<String, GaoEvent> mapByIdList(Collection<String> idList);
|
||||||
|
|
||||||
Map<String, List<String>> mapRoleCodeListByEventIdList(Collection<String> eventIdList);
|
Map<String, List<String>> mapRoleCodeListByEventIdList(Collection<String> eventIdList);
|
||||||
|
|||||||
@@ -1,53 +0,0 @@
|
|||||||
package com.imyeyu.api.modules.gao.service;
|
|
||||||
|
|
||||||
import com.imyeyu.api.modules.gao.entity.GaoFundRecord;
|
|
||||||
import com.imyeyu.api.modules.gao.vo.GaoFundActionRequest;
|
|
||||||
import com.imyeyu.api.modules.gao.vo.GaoFundConfirmNoRefundRequest;
|
|
||||||
import com.imyeyu.api.modules.gao.vo.GaoFundRecordPage;
|
|
||||||
import com.imyeyu.api.modules.gao.vo.GaoFundReceiveRequest;
|
|
||||||
import com.imyeyu.api.modules.gao.vo.GaoFundRefundRequest;
|
|
||||||
import com.imyeyu.api.modules.gao.vo.GaoFundRevokeRequest;
|
|
||||||
import com.imyeyu.spring.bean.PageResult;
|
|
||||||
import com.imyeyu.spring.service.BaseService;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
/// GAO 通用资金流水服务
|
|
||||||
///
|
|
||||||
/// @author Codex
|
|
||||||
/// @since 2026-08-31
|
|
||||||
public interface GaoFundRecordService extends BaseService<GaoFundRecord, String> {
|
|
||||||
|
|
||||||
/// 按条件查询资金流水
|
|
||||||
PageResult<GaoFundRecord> pageByQuery(GaoFundRecordPage page);
|
|
||||||
|
|
||||||
/// 查询客户套餐资金历史
|
|
||||||
List<GaoFundRecord> listByCustomerPackageId(String customerPackageId);
|
|
||||||
|
|
||||||
/// 登记线下收款
|
|
||||||
GaoFundRecord receive(GaoFundReceiveRequest request);
|
|
||||||
|
|
||||||
/// 核销收款
|
|
||||||
GaoFundRecord verify(String fundRecordId);
|
|
||||||
|
|
||||||
/// 拒绝待核销收款
|
|
||||||
GaoFundRecord reject(GaoFundActionRequest request);
|
|
||||||
|
|
||||||
/// 撤销自己提交的待核销收款
|
|
||||||
GaoFundRecord cancel(GaoFundActionRequest request);
|
|
||||||
|
|
||||||
/// 登记退款
|
|
||||||
GaoFundRecord refund(GaoFundRefundRequest request);
|
|
||||||
|
|
||||||
/// 确认无需退款
|
|
||||||
GaoFundRecord confirmNoRefund(GaoFundConfirmNoRefundRequest request);
|
|
||||||
|
|
||||||
/// 冲正资金流水
|
|
||||||
GaoFundRecord revoke(GaoFundRevokeRequest request);
|
|
||||||
|
|
||||||
/// 统计客户套餐待核销收款数量
|
|
||||||
///
|
|
||||||
/// @param bizId 业务 ID
|
|
||||||
/// @return 待核销收款数量
|
|
||||||
long countPendingReceiveByBizId(String bizId);
|
|
||||||
}
|
|
||||||
@@ -1,42 +0,0 @@
|
|||||||
package com.imyeyu.api.modules.gao.service;
|
|
||||||
|
|
||||||
import com.imyeyu.api.modules.gao.entity.GaoPackageConfig;
|
|
||||||
import com.imyeyu.api.modules.gao.entity.GaoPackageConfigItem;
|
|
||||||
import com.imyeyu.api.modules.gao.vo.GaoPackageConfigPage;
|
|
||||||
import com.imyeyu.spring.bean.PageResult;
|
|
||||||
import com.imyeyu.spring.service.BaseService;
|
|
||||||
|
|
||||||
import java.util.Collection;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
/// GAO 套餐配置服务
|
|
||||||
///
|
|
||||||
/// @author Codex
|
|
||||||
/// @since 2026-08-31
|
|
||||||
public interface GaoPackageConfigService extends BaseService<GaoPackageConfig, String> {
|
|
||||||
|
|
||||||
/// 按条件查询套餐配置
|
|
||||||
PageResult<GaoPackageConfig> pageByQuery(GaoPackageConfigPage page);
|
|
||||||
|
|
||||||
/// 查询有效可购买套餐
|
|
||||||
List<GaoPackageConfig> listValid(String storeId);
|
|
||||||
|
|
||||||
/// 批量查询套餐配置
|
|
||||||
///
|
|
||||||
/// @param idList 套餐配置 ID 列表
|
|
||||||
/// @return 按套餐配置 ID 映射的配置
|
|
||||||
Map<String, GaoPackageConfig> mapByIdList(Collection<String> idList);
|
|
||||||
|
|
||||||
/// 查询套餐配置产品明细
|
|
||||||
///
|
|
||||||
/// @param packageConfigId 套餐配置 ID
|
|
||||||
/// @return 产品明细列表
|
|
||||||
List<GaoPackageConfigItem> listItemByPackageConfigId(String packageConfigId);
|
|
||||||
|
|
||||||
/// 批量查询套餐配置产品明细
|
|
||||||
///
|
|
||||||
/// @param packageConfigIdList 套餐配置 ID 列表
|
|
||||||
/// @return 按套餐配置 ID 分组的产品明细
|
|
||||||
Map<String, List<GaoPackageConfigItem>> mapItemListByPackageConfigIdList(Collection<String> packageConfigIdList);
|
|
||||||
}
|
|
||||||
@@ -1,60 +0,0 @@
|
|||||||
package com.imyeyu.api.modules.gao.service;
|
|
||||||
|
|
||||||
import com.imyeyu.api.modules.gao.entity.GaoPackageDelivery;
|
|
||||||
import com.imyeyu.api.modules.gao.entity.GaoPackageDeliveryItem;
|
|
||||||
import com.imyeyu.api.modules.gao.vo.GaoPackageDeliveryActionRequest;
|
|
||||||
import com.imyeyu.api.modules.gao.vo.GaoPackageDeliveryCreateRequest;
|
|
||||||
import com.imyeyu.api.modules.gao.vo.GaoPackageDeliveryPage;
|
|
||||||
import com.imyeyu.api.modules.gao.vo.GaoPackageDeliveryRevokeRequest;
|
|
||||||
import com.imyeyu.spring.bean.PageResult;
|
|
||||||
import com.imyeyu.spring.service.BaseService;
|
|
||||||
|
|
||||||
import java.util.Collection;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
/// GAO 套餐发放服务
|
|
||||||
///
|
|
||||||
/// @author Codex
|
|
||||||
/// @since 2026-08-31
|
|
||||||
public interface GaoPackageDeliveryService extends BaseService<GaoPackageDelivery, String> {
|
|
||||||
|
|
||||||
/// 按条件查询发放单
|
|
||||||
PageResult<GaoPackageDelivery> pageByQuery(GaoPackageDeliveryPage page);
|
|
||||||
|
|
||||||
/// 查询客户套餐发放历史
|
|
||||||
List<GaoPackageDelivery> listByCustomerPackageId(String customerPackageId);
|
|
||||||
|
|
||||||
/// 批量查询发放明细
|
|
||||||
///
|
|
||||||
/// @param deliveryIdList 发放单 ID 列表
|
|
||||||
/// @return 按发放单 ID 分组的发放明细
|
|
||||||
Map<String, List<GaoPackageDeliveryItem>> mapItemListByDeliveryIdList(Collection<String> deliveryIdList);
|
|
||||||
|
|
||||||
/// 创建待核销发放单
|
|
||||||
GaoPackageDelivery createDelivery(GaoPackageDeliveryCreateRequest request);
|
|
||||||
|
|
||||||
/// 核销发放单
|
|
||||||
GaoPackageDelivery verify(String deliveryId);
|
|
||||||
|
|
||||||
/// 拒绝待核销发放单
|
|
||||||
GaoPackageDelivery reject(GaoPackageDeliveryActionRequest request);
|
|
||||||
|
|
||||||
/// 撤销自己提交的待核销发放单
|
|
||||||
GaoPackageDelivery cancel(GaoPackageDeliveryActionRequest request);
|
|
||||||
|
|
||||||
/// 整单冲正已核销发放单
|
|
||||||
GaoPackageDelivery revoke(GaoPackageDeliveryRevokeRequest request);
|
|
||||||
|
|
||||||
/// 统计客户套餐待核销发放单数量
|
|
||||||
///
|
|
||||||
/// @param customerPackageId 客户套餐 ID
|
|
||||||
/// @return 待核销发放单数量
|
|
||||||
long countPendingByCustomerPackageId(String customerPackageId);
|
|
||||||
|
|
||||||
/// 统计客户套餐已核销正常发放单数量
|
|
||||||
///
|
|
||||||
/// @param customerPackageId 客户套餐 ID
|
|
||||||
/// @return 已核销正常发放单数量
|
|
||||||
long countVerifiedByCustomerPackageId(String customerPackageId);
|
|
||||||
}
|
|
||||||
@@ -1,46 +0,0 @@
|
|||||||
package com.imyeyu.api.modules.gao.service;
|
|
||||||
|
|
||||||
import com.imyeyu.api.modules.common.entity.Article;
|
|
||||||
import com.imyeyu.spring.bean.PageResult;
|
|
||||||
import com.imyeyu.api.modules.gao.vo.GaoStoreDiaryPage;
|
|
||||||
|
|
||||||
/// GAO 门店日记服务
|
|
||||||
///
|
|
||||||
/// @author Codex
|
|
||||||
/// @since 2026-08-31
|
|
||||||
public interface GaoStoreDiaryService {
|
|
||||||
|
|
||||||
/// 分页查询门店日记
|
|
||||||
///
|
|
||||||
/// @param page 分页查询条件
|
|
||||||
/// @return 门店日记分页结果
|
|
||||||
PageResult<Article> page(GaoStoreDiaryPage page);
|
|
||||||
|
|
||||||
/// 查询门店日记详情
|
|
||||||
///
|
|
||||||
/// @param id 日记 ID
|
|
||||||
/// @return 门店日记
|
|
||||||
Article get(String id);
|
|
||||||
|
|
||||||
/// 创建门店日记
|
|
||||||
///
|
|
||||||
/// @param article 门店日记
|
|
||||||
/// @param userId 操作用户 ID
|
|
||||||
void create(Article article, String userId);
|
|
||||||
|
|
||||||
/// 修改门店日记
|
|
||||||
///
|
|
||||||
/// @param article 门店日记
|
|
||||||
/// @param userId 操作用户 ID
|
|
||||||
void update(Article article, String userId);
|
|
||||||
|
|
||||||
/// 删除门店日记
|
|
||||||
///
|
|
||||||
/// @param id 日记 ID
|
|
||||||
void delete(String id);
|
|
||||||
|
|
||||||
/// 删除门店下的全部日记
|
|
||||||
///
|
|
||||||
/// @param storeId 门店 ID
|
|
||||||
void deleteByStoreId(String storeId);
|
|
||||||
}
|
|
||||||
-406
@@ -1,406 +0,0 @@
|
|||||||
package com.imyeyu.api.modules.gao.service.implement;
|
|
||||||
|
|
||||||
import com.imyeyu.api.bean.ModuleCode;
|
|
||||||
import com.imyeyu.api.config.dbsource.TimiServerDBConfig;
|
|
||||||
import com.imyeyu.api.modules.gao.entity.GaoCustomer;
|
|
||||||
import com.imyeyu.api.modules.gao.entity.GaoCustomerPackage;
|
|
||||||
import com.imyeyu.api.modules.gao.entity.GaoCustomerPackageItem;
|
|
||||||
import com.imyeyu.api.modules.gao.entity.GaoEvent;
|
|
||||||
import com.imyeyu.api.modules.gao.entity.GaoEventRecord;
|
|
||||||
import com.imyeyu.api.modules.gao.entity.GaoPackageConfig;
|
|
||||||
import com.imyeyu.api.modules.gao.entity.GaoPackageConfigItem;
|
|
||||||
import com.imyeyu.api.modules.gao.mapper.GaoCustomerPackageItemMapper;
|
|
||||||
import com.imyeyu.api.modules.gao.mapper.GaoCustomerPackageMapper;
|
|
||||||
import com.imyeyu.api.modules.gao.service.GaoCustomerService;
|
|
||||||
import com.imyeyu.api.modules.gao.service.GaoCustomerPackageService;
|
|
||||||
import com.imyeyu.api.modules.gao.service.GaoEventRecordService;
|
|
||||||
import com.imyeyu.api.modules.gao.service.GaoEventService;
|
|
||||||
import com.imyeyu.api.modules.gao.service.GaoFundRecordService;
|
|
||||||
import com.imyeyu.api.modules.gao.service.GaoPackageDeliveryService;
|
|
||||||
import com.imyeyu.api.modules.gao.service.GaoPackageConfigService;
|
|
||||||
import com.imyeyu.api.modules.gao.service.GaoStoreScopeService;
|
|
||||||
import com.imyeyu.api.modules.gao.vo.GaoCustomerPackageCancelRequest;
|
|
||||||
import com.imyeyu.api.modules.gao.vo.GaoCustomerPackagePage;
|
|
||||||
import com.imyeyu.api.modules.gao.vo.GaoCustomerPackagePurchaseRequest;
|
|
||||||
import com.imyeyu.api.modules.gao.vo.GaoCustomerPackagePurchaseItem;
|
|
||||||
import com.imyeyu.api.modules.system.entity.Logger;
|
|
||||||
import com.imyeyu.api.modules.system.service.LoggerService;
|
|
||||||
import com.imyeyu.api.modules.user.service.PermissionChecker;
|
|
||||||
import com.imyeyu.api.modules.user.service.UserLoginService;
|
|
||||||
import com.imyeyu.java.TimiJava;
|
|
||||||
import com.imyeyu.java.bean.timi.TimiException;
|
|
||||||
import com.imyeyu.spring.bean.PageResult;
|
|
||||||
import com.imyeyu.spring.mapper.BaseMapper;
|
|
||||||
import com.imyeyu.spring.service.AbstractEntityService;
|
|
||||||
import com.imyeyu.utils.Time;
|
|
||||||
import lombok.RequiredArgsConstructor;
|
|
||||||
import org.springframework.beans.factory.ObjectProvider;
|
|
||||||
import org.springframework.stereotype.Service;
|
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
|
||||||
|
|
||||||
import java.math.BigDecimal;
|
|
||||||
import java.util.Collection;
|
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Set;
|
|
||||||
import java.util.function.Function;
|
|
||||||
import java.util.stream.Collectors;
|
|
||||||
|
|
||||||
/// GAO 客户套餐服务实现
|
|
||||||
///
|
|
||||||
/// @author Codex
|
|
||||||
/// @since 2026-08-31
|
|
||||||
@Service
|
|
||||||
@RequiredArgsConstructor
|
|
||||||
public class GaoCustomerPackageServiceImplement extends AbstractEntityService<GaoCustomerPackage, String> implements GaoCustomerPackageService {
|
|
||||||
|
|
||||||
private static final BigDecimal ZERO = BigDecimal.ZERO;
|
|
||||||
|
|
||||||
private final GaoCustomerPackageMapper mapper;
|
|
||||||
private final GaoCustomerPackageItemMapper itemMapper;
|
|
||||||
private final ObjectProvider<GaoPackageDeliveryService> deliveryServiceProvider;
|
|
||||||
private final ObjectProvider<GaoFundRecordService> fundRecordServiceProvider;
|
|
||||||
private final GaoPackageConfigService packageConfigService;
|
|
||||||
private final GaoCustomerService customerService;
|
|
||||||
private final GaoEventService eventService;
|
|
||||||
private final GaoEventRecordService eventRecordService;
|
|
||||||
private final GaoStoreScopeService storeScopeService;
|
|
||||||
private final UserLoginService userLoginService;
|
|
||||||
private final PermissionChecker permissionChecker;
|
|
||||||
private final LoggerService loggerService;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected BaseMapper<GaoCustomerPackage, String> mapper() {
|
|
||||||
return mapper;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public GaoCustomerPackage getForUpdate(String id) {
|
|
||||||
return mapper.selectForUpdate(id);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public List<GaoCustomerPackageItem> listItemByCustomerPackageId(String customerPackageId) {
|
|
||||||
return itemMapper.selectByCustomerPackageId(customerPackageId);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public GaoCustomerPackageItem getItemForUpdate(String itemId) {
|
|
||||||
return itemMapper.selectForUpdate(itemId);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int updateItemReservedQuantity(String itemId, BigDecimal delta) {
|
|
||||||
return itemMapper.updateReservedQuantity(itemId, delta);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int updateItemDeliveredQuantity(String itemId, BigDecimal delta) {
|
|
||||||
return itemMapper.updateDeliveredQuantity(itemId, delta);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int updatePendingPaidAmountDelta(String id, Long delta) {
|
|
||||||
return mapper.updatePendingPaidAmountDelta(id, delta);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int updatePaidAmountDelta(String id, Long delta) {
|
|
||||||
return mapper.updatePaidAmountDelta(id, delta);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void updateAggregateState(GaoCustomerPackage packageEntity) {
|
|
||||||
mapper.update(packageEntity);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// 客户套餐必须通过购买流程创建
|
|
||||||
///
|
|
||||||
/// @param packageEntity 客户套餐
|
|
||||||
@Override
|
|
||||||
public void create(GaoCustomerPackage packageEntity) {
|
|
||||||
TimiException.requiredTrue(false, "客户套餐必须通过购买接口创建");
|
|
||||||
}
|
|
||||||
|
|
||||||
/// 客户套餐创建后不允许通用修改
|
|
||||||
///
|
|
||||||
/// @param packageEntity 客户套餐
|
|
||||||
@Override
|
|
||||||
public void update(GaoCustomerPackage packageEntity) {
|
|
||||||
TimiException.requiredTrue(false, "客户套餐不允许通用修改");
|
|
||||||
}
|
|
||||||
|
|
||||||
/// 客户套餐不允许通用删除
|
|
||||||
///
|
|
||||||
/// @param id 客户套餐 ID
|
|
||||||
@Override
|
|
||||||
public void delete(String id) {
|
|
||||||
TimiException.requiredTrue(false, "客户套餐不允许删除");
|
|
||||||
}
|
|
||||||
|
|
||||||
/// 客户套餐不允许物理删除
|
|
||||||
///
|
|
||||||
/// @param id 客户套餐 ID
|
|
||||||
@Override
|
|
||||||
public void destroy(String id) {
|
|
||||||
TimiException.requiredTrue(false, "客户套餐不允许物理删除");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public PageResult<GaoCustomerPackage> pageByQuery(GaoCustomerPackagePage page) {
|
|
||||||
TimiException.required(page, "not found page");
|
|
||||||
PageResult<GaoCustomerPackage> result = new PageResult<>();
|
|
||||||
result.setTotal(mapper.countByQuery(page));
|
|
||||||
result.setList(mapper.selectByQuery(page));
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public GaoCustomerPackage get(String id) {
|
|
||||||
return super.get(id);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Transactional(TimiServerDBConfig.ROLLBACKER)
|
|
||||||
@Override
|
|
||||||
public GaoCustomerPackage purchase(GaoCustomerPackagePurchaseRequest request) {
|
|
||||||
return loggerService.execute(Logger.Module.GAO, "GAO_CUSTOMER_PACKAGE_PURCHASE", request, () -> purchaseInternal(request));
|
|
||||||
}
|
|
||||||
|
|
||||||
private GaoCustomerPackage purchaseInternal(GaoCustomerPackagePurchaseRequest request) {
|
|
||||||
TimiException.required(request, "not found purchase request");
|
|
||||||
TimiException.required(request.getRequestNo(), "not found requestNo");
|
|
||||||
request.setRequestNo(request.getRequestNo().trim());
|
|
||||||
TimiException.required(request.getEventId(), "not found eventId");
|
|
||||||
TimiException.required(request.getCustomerId(), "not found customerId");
|
|
||||||
|
|
||||||
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));
|
|
||||||
}
|
|
||||||
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);
|
|
||||||
return existing;
|
|
||||||
}
|
|
||||||
|
|
||||||
Long purchasedAt = TimiJava.defaultIfNull(request.getPurchasedAt(), Time.now());
|
|
||||||
Long now = Time.now();
|
|
||||||
TimiException.requiredTrue(config.getStatus() == GaoPackageConfig.Status.ACTIVE, "套餐配置不可购买");
|
|
||||||
TimiException.requiredTrue(config.getBeginAt() == null || config.getBeginAt() <= now, "套餐配置尚未生效");
|
|
||||||
TimiException.requiredTrue(config.getEndAt() == null || now <= config.getEndAt(), "套餐配置已过期");
|
|
||||||
GaoCustomer customer = validateCustomer(request.getCustomerId(), config.getStoreId());
|
|
||||||
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()), "普通员工不能修改套餐成交价");
|
|
||||||
verifySameQuantityAsConfig(itemList, configItemList);
|
|
||||||
}
|
|
||||||
|
|
||||||
GaoEventRecord eventRecord = new GaoEventRecord();
|
|
||||||
eventRecord.setCustomerId(customer.getId());
|
|
||||||
eventRecord.setStoreId(config.getStoreId());
|
|
||||||
eventRecord.setEventId(event.getId());
|
|
||||||
eventRecord.setRegisteredAt(purchasedAt);
|
|
||||||
eventRecord.setRemark(request.getRemark());
|
|
||||||
if (event.getValueType() == GaoEvent.ValueType.NUMBER && event.getValueUnit() == GaoEvent.ValueUnit.CENT) {
|
|
||||||
eventRecord.setNumberValue(request.getSaleAmount());
|
|
||||||
}
|
|
||||||
GaoEventRecord createdEventRecord = eventRecordService.createPackagePurchaseRecord(eventRecordWithAttachments(eventRecord, request));
|
|
||||||
|
|
||||||
GaoCustomerPackage result = new GaoCustomerPackage();
|
|
||||||
result.setStoreId(config.getStoreId());
|
|
||||||
result.setCustomerId(customer.getId());
|
|
||||||
result.setPackageConfigId(config.getId());
|
|
||||||
result.setPurchaseEventRecordId(createdEventRecord.getId());
|
|
||||||
result.setRequestNo(request.getRequestNo());
|
|
||||||
result.setPackageNameSnapshot(config.getName());
|
|
||||||
result.setStandardAmountSnapshot(config.getStandardAmount());
|
|
||||||
result.setSaleAmount(request.getSaleAmount());
|
|
||||||
result.setPendingPaidAmount(0L);
|
|
||||||
result.setPaidAmount(0L);
|
|
||||||
result.setRefundedAmount(0L);
|
|
||||||
result.setStatus(GaoCustomerPackage.Status.ACTIVE);
|
|
||||||
result.setPaymentStatus(request.getSaleAmount() == 0 ? GaoCustomerPackage.PaymentStatus.PAID : GaoCustomerPackage.PaymentStatus.UNPAID);
|
|
||||||
result.setRefundStatus(GaoCustomerPackage.RefundStatus.NOT_REQUIRED);
|
|
||||||
result.setPurchasedAt(purchasedAt);
|
|
||||||
result.setOperatorUserId(userLoginService.getRequireLoginUserId());
|
|
||||||
result.setRemark(request.getRemark());
|
|
||||||
super.create(result);
|
|
||||||
for (GaoCustomerPackagePurchaseItem source : itemList) {
|
|
||||||
GaoCustomerPackageItem item = new GaoCustomerPackageItem();
|
|
||||||
item.setCustomerPackageId(result.getId());
|
|
||||||
item.setProductNameSnapshot(source.getProductName().trim());
|
|
||||||
item.setUnitSnapshot(source.getUnit().trim());
|
|
||||||
item.setTotalQuantity(source.getTotalQuantity());
|
|
||||||
item.setReservedQuantity(ZERO);
|
|
||||||
item.setDeliveredQuantity(ZERO);
|
|
||||||
item.setSort(source.getSort());
|
|
||||||
item.setRemark(source.getRemark());
|
|
||||||
itemMapper.insert(item);
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Transactional(TimiServerDBConfig.ROLLBACKER)
|
|
||||||
@Override
|
|
||||||
public GaoCustomerPackage cancel(GaoCustomerPackageCancelRequest request) {
|
|
||||||
return loggerService.execute(Logger.Module.GAO, "GAO_CUSTOMER_PACKAGE_CANCEL", request, () -> cancelInternal(request));
|
|
||||||
}
|
|
||||||
|
|
||||||
private GaoCustomerPackage cancelInternal(GaoCustomerPackageCancelRequest request) {
|
|
||||||
TimiException.required(request, "not found cancel request");
|
|
||||||
TimiException.required(request.getCustomerPackageId(), "not found customerPackageId");
|
|
||||||
String reason = requiredReason(request.getReason(), "取消原因不能为空");
|
|
||||||
GaoCustomerPackage packageEntity = mapper.selectForUpdate(request.getCustomerPackageId());
|
|
||||||
TimiException.required(packageEntity, "not found customer package");
|
|
||||||
storeScopeService.checkStoreId(packageEntity.getStoreId());
|
|
||||||
TimiException.requiredTrue(packageEntity.getStatus() == GaoCustomerPackage.Status.ACTIVE, "当前套餐不可取消");
|
|
||||||
TimiException.requiredTrue(0 == deliveryServiceProvider.getObject().countPendingByCustomerPackageId(packageEntity.getId()), "存在待核销发放,不能取消套餐");
|
|
||||||
TimiException.requiredTrue(0 == fundRecordServiceProvider.getObject().countPendingReceiveByBizId(packageEntity.getId()), "存在待核销收款,不能取消套餐");
|
|
||||||
TimiException.requiredTrue(0 == pendingAmount(packageEntity), "存在待核销收款,不能取消套餐");
|
|
||||||
List<GaoCustomerPackageItem> itemList = itemMapper.selectByCustomerPackageId(packageEntity.getId());
|
|
||||||
for (GaoCustomerPackageItem item : itemList) {
|
|
||||||
TimiException.requiredTrue(item.getDeliveredQuantity().compareTo(item.getTotalQuantity()) < 0, "已全部履约的套餐不能取消");
|
|
||||||
}
|
|
||||||
packageEntity.setStatus(GaoCustomerPackage.Status.CANCELLED);
|
|
||||||
packageEntity.setCancelledAt(Time.now());
|
|
||||||
packageEntity.setCancelOperatorUserId(userLoginService.getRequireLoginUserId());
|
|
||||||
packageEntity.setCancelReason(reason);
|
|
||||||
packageEntity.setRefundStatus(0 < safeLong(packageEntity.getPaidAmount()) ? GaoCustomerPackage.RefundStatus.PENDING : GaoCustomerPackage.RefundStatus.NOT_REQUIRED);
|
|
||||||
mapper.update(packageEntity);
|
|
||||||
return packageEntity;
|
|
||||||
}
|
|
||||||
|
|
||||||
private GaoEventRecord eventRecordWithAttachments(GaoEventRecord record, GaoCustomerPackagePurchaseRequest request) {
|
|
||||||
record.setAttachmentList(request.getAttachmentList());
|
|
||||||
return record;
|
|
||||||
}
|
|
||||||
|
|
||||||
private GaoCustomer validateCustomer(String customerId, String storeId) {
|
|
||||||
GaoCustomer customer = customerService.get(customerId);
|
|
||||||
TimiException.required(customer, "not found customer");
|
|
||||||
TimiException.requiredTrue(storeId.equals(customer.getStoreId()), "客户和套餐不属于同一门店");
|
|
||||||
return customer;
|
|
||||||
}
|
|
||||||
|
|
||||||
private GaoEvent validatePurchaseEvent(String eventId) {
|
|
||||||
GaoEvent event = eventService.get(eventId);
|
|
||||||
TimiException.required(event, "not found purchase event");
|
|
||||||
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<>();
|
|
||||||
for (int i = 0; i < itemList.size(); i++) {
|
|
||||||
GaoCustomerPackagePurchaseItem item = itemList.get(i);
|
|
||||||
TimiException.required(item, "购买产品明细不能为空");
|
|
||||||
TimiException.required(item.getProductName(), "购买产品名称不能为空");
|
|
||||||
TimiException.required(item.getUnit(), "购买产品单位不能为空");
|
|
||||||
TimiException.required(item.getTotalQuantity(), "购买产品数量不能为空");
|
|
||||||
TimiException.requiredTrue(0 < item.getTotalQuantity().signum(), "购买产品数量必须大于 0");
|
|
||||||
TimiException.requiredTrue(3 >= item.getTotalQuantity().scale(), "购买产品数量最多保留三位小数");
|
|
||||||
String key = item.getProductName().trim() + "|" + item.getUnit().trim();
|
|
||||||
TimiException.requiredTrue(keySet.add(key), "购买套餐内产品名称和单位不能重复");
|
|
||||||
item.setProductName(item.getProductName().trim());
|
|
||||||
item.setUnit(item.getUnit().trim());
|
|
||||||
item.setSort(TimiJava.defaultIfNull(item.getSort(), i));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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.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.getCustomerId().equals(request.getCustomerId())
|
|
||||||
&& existing.getSaleAmount().equals(request.getSaleAmount()), "requestNo 已被其他购买请求使用");
|
|
||||||
GaoEventRecord eventRecord = eventRecordService.get(existing.getPurchaseEventRecordId());
|
|
||||||
TimiException.required(eventRecord, "购买事件登记不存在");
|
|
||||||
TimiException.requiredTrue(eventRecord.getEventId().equals(request.getEventId())
|
|
||||||
&& (request.getPurchasedAt() == null || eventRecord.getRegisteredAt().equals(request.getPurchasedAt()))
|
|
||||||
&& sameText(existing.getRemark(), request.getRemark()), "requestNo 对应购买请求内容不一致");
|
|
||||||
List<GaoCustomerPackageItem> existingItemList = itemMapper.selectByCustomerPackageId(existing.getId());
|
|
||||||
List<GaoCustomerPackagePurchaseItem> requestItemList = TimiJava.defaultIfNull(request.getItemList(), List.of());
|
|
||||||
verifyPurchaseItems(requestItemList);
|
|
||||||
TimiException.requiredTrue(existingItemList.size() == requestItemList.size(), "requestNo 对应购买请求内容不一致");
|
|
||||||
Map<String, GaoCustomerPackageItem> existingItemMap = existingItemList.stream().collect(Collectors.toMap(item -> item.getProductNameSnapshot() + "|" + item.getUnitSnapshot(), Function.identity()));
|
|
||||||
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())
|
|
||||||
&& sameText(existingItem.getRemark(), item.getRemark()), "requestNo 对应购买请求内容不一致");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Map<String, List<GaoCustomerPackageItem>> mapItemListByCustomerPackageIdList(Collection<String> customerPackageIdList) {
|
|
||||||
if (customerPackageIdList == null || customerPackageIdList.isEmpty()) {
|
|
||||||
return Map.of();
|
|
||||||
}
|
|
||||||
return itemMapper.selectByCustomerPackageIdList(customerPackageIdList).stream()
|
|
||||||
.collect(Collectors.groupingBy(GaoCustomerPackageItem::getCustomerPackageId));
|
|
||||||
}
|
|
||||||
|
|
||||||
private Long pendingAmount(GaoCustomerPackage packageEntity) {
|
|
||||||
return safeLong(packageEntity.getPendingPaidAmount());
|
|
||||||
}
|
|
||||||
|
|
||||||
private long safeLong(Long value) {
|
|
||||||
return value == null ? 0L : value;
|
|
||||||
}
|
|
||||||
|
|
||||||
private String requiredReason(String reason, String message) {
|
|
||||||
TimiException.required(reason, message);
|
|
||||||
String result = reason.trim();
|
|
||||||
TimiException.requiredTrue(!result.isEmpty(), message);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean sameText(String left, String right) {
|
|
||||||
return left == null ? right == null : left.equals(right);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
+1
-30
@@ -139,8 +139,7 @@ public class GaoEventRecordServiceImplement extends AbstractEntityService<GaoEve
|
|||||||
GaoEventRecord record = get(id);
|
GaoEventRecord record = get(id);
|
||||||
TimiException.required(record, "not found event record");
|
TimiException.required(record, "not found event record");
|
||||||
TimiException.requiredTrue(record.getVerificationStatus() == GaoEventRecord.VerificationStatus.PENDING, "登记记录无需核销或已核销");
|
TimiException.requiredTrue(record.getVerificationStatus() == GaoEventRecord.VerificationStatus.PENDING, "登记记录无需核销或已核销");
|
||||||
String loginUserId = userLoginService.getRequireLoginUserId();
|
int updated = mapper.verify(id, userLoginService.getRequireLoginUserId(), Time.now());
|
||||||
int updated = mapper.verify(id, loginUserId, Time.now(), loginUserId);
|
|
||||||
TimiException.requiredTrue(0 < updated, "登记记录无需核销或已核销");
|
TimiException.requiredTrue(0 < updated, "登记记录无需核销或已核销");
|
||||||
logger.setLevel(Logger.Level.INFO);
|
logger.setLevel(Logger.Level.INFO);
|
||||||
logger.setResult(id);
|
logger.setResult(id);
|
||||||
@@ -161,22 +160,6 @@ public class GaoEventRecordServiceImplement extends AbstractEntityService<GaoEve
|
|||||||
@Transactional(TimiServerDBConfig.ROLLBACKER)
|
@Transactional(TimiServerDBConfig.ROLLBACKER)
|
||||||
@Override
|
@Override
|
||||||
public void create(GaoEventRecord record) {
|
public void create(GaoEventRecord record) {
|
||||||
createInternal(record, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Transactional(TimiServerDBConfig.ROLLBACKER)
|
|
||||||
@Override
|
|
||||||
public GaoEventRecord createOne(GaoEventRecord record) {
|
|
||||||
return createInternal(record, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Transactional(TimiServerDBConfig.ROLLBACKER)
|
|
||||||
@Override
|
|
||||||
public GaoEventRecord createPackagePurchaseRecord(GaoEventRecord record) {
|
|
||||||
return createInternal(record, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
private GaoEventRecord createInternal(GaoEventRecord record, boolean packagePurchase) {
|
|
||||||
TimiException.required(record, "not found record");
|
TimiException.required(record, "not found record");
|
||||||
|
|
||||||
Logger logger = new Logger(Logger.Module.GAO, "GAO_EVENT_RECORD_BATCH_CREATE");
|
Logger logger = new Logger(Logger.Module.GAO, "GAO_EVENT_RECORD_BATCH_CREATE");
|
||||||
@@ -188,12 +171,6 @@ public class GaoEventRecordServiceImplement extends AbstractEntityService<GaoEve
|
|||||||
GaoEvent event = eventService.get(record.getEventId());
|
GaoEvent event = eventService.get(record.getEventId());
|
||||||
TimiException.required(event, "not found event");
|
TimiException.required(event, "not found event");
|
||||||
TimiException.required(event.getStoreId(), "not found event.storeId");
|
TimiException.required(event.getStoreId(), "not found event.storeId");
|
||||||
if (packagePurchase) {
|
|
||||||
TimiException.requiredTrue(event.getBizType() == GaoEvent.BizType.PACKAGE_PURCHASE, "购买事件类型无效");
|
|
||||||
TimiException.requiredTrue(!Boolean.TRUE.equals(event.getRequireVerification()), "购买套餐事件不能要求核销");
|
|
||||||
} else {
|
|
||||||
TimiException.requiredTrue(event.getBizType() != GaoEvent.BizType.PACKAGE_PURCHASE, "购买套餐事件必须通过套餐购买接口登记");
|
|
||||||
}
|
|
||||||
eventService.attachOptionGroupList(List.of(event));
|
eventService.attachOptionGroupList(List.of(event));
|
||||||
List<GaoEventRecordOption> canonicalOptionList = resolveRecordOptionList(event, record.getSelectedOptionGroupList());
|
List<GaoEventRecordOption> canonicalOptionList = resolveRecordOptionList(event, record.getSelectedOptionGroupList());
|
||||||
verifyRecordValue(event, record.getNumberValue());
|
verifyRecordValue(event, record.getNumberValue());
|
||||||
@@ -224,7 +201,6 @@ public class GaoEventRecordServiceImplement extends AbstractEntityService<GaoEve
|
|||||||
dbRecord.setStoreId(event.getStoreId());
|
dbRecord.setStoreId(event.getStoreId());
|
||||||
dbRecord.setEventId(record.getEventId());
|
dbRecord.setEventId(record.getEventId());
|
||||||
dbRecord.setOperatorUserId(loginUserId);
|
dbRecord.setOperatorUserId(loginUserId);
|
||||||
dbRecord.setUpdatedBy(loginUserId);
|
|
||||||
dbRecord.setRemark(record.getRemark());
|
dbRecord.setRemark(record.getRemark());
|
||||||
dbRecord.setRegisteredAt(registeredAt);
|
dbRecord.setRegisteredAt(registeredAt);
|
||||||
dbRecord.setRegisteredDateValue(registeredDateValue);
|
dbRecord.setRegisteredDateValue(registeredDateValue);
|
||||||
@@ -256,7 +232,6 @@ public class GaoEventRecordServiceImplement extends AbstractEntityService<GaoEve
|
|||||||
}
|
}
|
||||||
logger.setLevel(Logger.Level.INFO);
|
logger.setLevel(Logger.Level.INFO);
|
||||||
logger.setResult(String.join(",", logIdList));
|
logger.setResult(String.join(",", logIdList));
|
||||||
return firstRecord;
|
|
||||||
} catch (TimiException e) {
|
} catch (TimiException e) {
|
||||||
logger.setLevel(Logger.Level.WARN);
|
logger.setLevel(Logger.Level.WARN);
|
||||||
logger.setException(e.getMessage());
|
logger.setException(e.getMessage());
|
||||||
@@ -310,7 +285,6 @@ public class GaoEventRecordServiceImplement extends AbstractEntityService<GaoEve
|
|||||||
GaoEvent event = eventService.get(dbRecord.getEventId());
|
GaoEvent event = eventService.get(dbRecord.getEventId());
|
||||||
TimiException.required(event, "not found event");
|
TimiException.required(event, "not found event");
|
||||||
TimiException.required(event.getStoreId(), "not found event.storeId");
|
TimiException.required(event.getStoreId(), "not found event.storeId");
|
||||||
TimiException.requiredTrue(event.getBizType() != GaoEvent.BizType.PACKAGE_PURCHASE, "购买套餐事件登记不可通过通用接口修改");
|
|
||||||
List<GaoEventRecordOption> canonicalOptionList = null;
|
List<GaoEventRecordOption> canonicalOptionList = null;
|
||||||
if (record.getSelectedOptionGroupList() != null) {
|
if (record.getSelectedOptionGroupList() != null) {
|
||||||
eventService.attachOptionGroupList(List.of(event));
|
eventService.attachOptionGroupList(List.of(event));
|
||||||
@@ -319,7 +293,6 @@ public class GaoEventRecordServiceImplement extends AbstractEntityService<GaoEve
|
|||||||
verifyRecordAttachment(event, record.getAttachmentList());
|
verifyRecordAttachment(event, record.getAttachmentList());
|
||||||
checkEventPermission(event);
|
checkEventPermission(event);
|
||||||
dbRecord.setRemark(record.getRemark());
|
dbRecord.setRemark(record.getRemark());
|
||||||
dbRecord.setUpdatedBy(userLoginService.getRequireLoginUserId());
|
|
||||||
super.update(dbRecord);
|
super.update(dbRecord);
|
||||||
if (canonicalOptionList != null) {
|
if (canonicalOptionList != null) {
|
||||||
GaoEventRecordOption optionExample = new GaoEventRecordOption();
|
GaoEventRecordOption optionExample = new GaoEventRecordOption();
|
||||||
@@ -353,8 +326,6 @@ public class GaoEventRecordServiceImplement extends AbstractEntityService<GaoEve
|
|||||||
logger.setContent(id);
|
logger.setContent(id);
|
||||||
GaoEventRecord record = get(id);
|
GaoEventRecord record = get(id);
|
||||||
TimiException.required(record, "not found event record");
|
TimiException.required(record, "not found event record");
|
||||||
GaoEvent event = eventService.get(record.getEventId());
|
|
||||||
TimiException.requiredTrue(event == null || event.getBizType() != GaoEvent.BizType.PACKAGE_PURCHASE, "购买套餐事件登记不可通过通用接口删除");
|
|
||||||
pointTriggerService.revokeByEventRecord(record);
|
pointTriggerService.revokeByEventRecord(record);
|
||||||
GaoEventRecordOption optionExample = new GaoEventRecordOption();
|
GaoEventRecordOption optionExample = new GaoEventRecordOption();
|
||||||
optionExample.setEventRecordId(record.getId());
|
optionExample.setEventRecordId(record.getId());
|
||||||
|
|||||||
-33
@@ -6,21 +6,17 @@ import com.imyeyu.api.modules.gao.entity.GaoEvent;
|
|||||||
import com.imyeyu.api.modules.gao.entity.GaoEventOption;
|
import com.imyeyu.api.modules.gao.entity.GaoEventOption;
|
||||||
import com.imyeyu.api.modules.gao.entity.GaoEventOptionGroup;
|
import com.imyeyu.api.modules.gao.entity.GaoEventOptionGroup;
|
||||||
import com.imyeyu.api.modules.gao.entity.GaoEventRoleRelation;
|
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.GaoEventMapper;
|
||||||
import com.imyeyu.api.modules.gao.mapper.GaoEventOptionGroupMapper;
|
import com.imyeyu.api.modules.gao.mapper.GaoEventOptionGroupMapper;
|
||||||
import com.imyeyu.api.modules.gao.mapper.GaoEventOptionMapper;
|
import com.imyeyu.api.modules.gao.mapper.GaoEventOptionMapper;
|
||||||
import com.imyeyu.api.modules.gao.mapper.GaoEventRecordMapper;
|
import com.imyeyu.api.modules.gao.mapper.GaoEventRecordMapper;
|
||||||
import com.imyeyu.api.modules.gao.mapper.GaoEventRoleRelationMapper;
|
import com.imyeyu.api.modules.gao.mapper.GaoEventRoleRelationMapper;
|
||||||
import com.imyeyu.api.modules.gao.service.GaoEventService;
|
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.entity.Logger;
|
||||||
import com.imyeyu.api.modules.system.service.LoggerService;
|
import com.imyeyu.api.modules.system.service.LoggerService;
|
||||||
import com.imyeyu.java.TimiJava;
|
import com.imyeyu.java.TimiJava;
|
||||||
import com.imyeyu.java.bean.timi.TimiCode;
|
import com.imyeyu.java.bean.timi.TimiCode;
|
||||||
import com.imyeyu.java.bean.timi.TimiException;
|
import com.imyeyu.java.bean.timi.TimiException;
|
||||||
import com.imyeyu.spring.bean.Page;
|
|
||||||
import com.imyeyu.spring.bean.PageResult;
|
|
||||||
import com.imyeyu.spring.mapper.BaseMapper;
|
import com.imyeyu.spring.mapper.BaseMapper;
|
||||||
import com.imyeyu.spring.service.AbstractEntityService;
|
import com.imyeyu.spring.service.AbstractEntityService;
|
||||||
import com.imyeyu.utils.Time;
|
import com.imyeyu.utils.Time;
|
||||||
@@ -59,21 +55,12 @@ public class GaoEventServiceImplement extends AbstractEntityService<GaoEvent, St
|
|||||||
private final GaoEventOptionMapper optionMapper;
|
private final GaoEventOptionMapper optionMapper;
|
||||||
private final GaoEventRecordMapper eventRecordMapper;
|
private final GaoEventRecordMapper eventRecordMapper;
|
||||||
private final GaoEventRoleRelationMapper roleRelationMapper;
|
private final GaoEventRoleRelationMapper roleRelationMapper;
|
||||||
private final GaoPackageConfigService packageConfigService;
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected BaseMapper<GaoEvent, String> mapper() {
|
protected BaseMapper<GaoEvent, String> mapper() {
|
||||||
return mapper;
|
return mapper;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public PageResult<GaoEvent> pageWithoutDeleted(Page<GaoEvent> page) {
|
|
||||||
PageResult<GaoEvent> result = new PageResult<>();
|
|
||||||
result.setTotal(mapper.countPageWithoutDeleted(page));
|
|
||||||
result.setList(mapper.selectPageWithoutDeleted(page));
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Transactional(TimiServerDBConfig.ROLLBACKER)
|
@Transactional(TimiServerDBConfig.ROLLBACKER)
|
||||||
@Override
|
@Override
|
||||||
public void create(GaoEvent event) {
|
public void create(GaoEvent event) {
|
||||||
@@ -86,7 +73,6 @@ public class GaoEventServiceImplement extends AbstractEntityService<GaoEvent, St
|
|||||||
logger.setContent(jackson.writeValueAsString(event));
|
logger.setContent(jackson.writeValueAsString(event));
|
||||||
|
|
||||||
event.setStatus(TimiJava.defaultIfNull(event.getStatus(), GaoEvent.Status.DRAFT));
|
event.setStatus(TimiJava.defaultIfNull(event.getStatus(), GaoEvent.Status.DRAFT));
|
||||||
event.setBizType(TimiJava.defaultIfNull(event.getBizType(), GaoEvent.BizType.GENERAL));
|
|
||||||
event.setValueType(TimiJava.defaultIfNull(event.getValueType(), GaoEvent.ValueType.NONE));
|
event.setValueType(TimiJava.defaultIfNull(event.getValueType(), GaoEvent.ValueType.NONE));
|
||||||
event.setRequireValue(TimiJava.defaultIfNull(event.getRequireValue(), false));
|
event.setRequireValue(TimiJava.defaultIfNull(event.getRequireValue(), false));
|
||||||
event.setRequirePhoto(TimiJava.defaultIfNull(event.getRequirePhoto(), false));
|
event.setRequirePhoto(TimiJava.defaultIfNull(event.getRequirePhoto(), false));
|
||||||
@@ -123,20 +109,12 @@ public class GaoEventServiceImplement extends AbstractEntityService<GaoEvent, St
|
|||||||
GaoEvent dbEvent = get(event.getId());
|
GaoEvent dbEvent = get(event.getId());
|
||||||
TimiException.required(dbEvent, "not found event");
|
TimiException.required(dbEvent, "not found event");
|
||||||
TimiException.requiredTrue(dbEvent.getStoreId().equals(event.getStoreId()), "event.storeId invalid");
|
TimiException.requiredTrue(dbEvent.getStoreId().equals(event.getStoreId()), "event.storeId invalid");
|
||||||
TimiException.requiredTrue(dbEvent.getStatus() != GaoEvent.Status.DELETED, "已删除登记事件不可编辑");
|
|
||||||
GaoEvent.ValueType oldValueType = dbEvent.getValueType();
|
GaoEvent.ValueType oldValueType = dbEvent.getValueType();
|
||||||
GaoEvent.ValueUnit oldValueUnit = dbEvent.getValueUnit();
|
GaoEvent.ValueUnit oldValueUnit = dbEvent.getValueUnit();
|
||||||
dbEvent.setName(event.getName());
|
dbEvent.setName(event.getName());
|
||||||
dbEvent.setDescription(event.getDescription());
|
dbEvent.setDescription(event.getDescription());
|
||||||
dbEvent.setColor(event.getColor());
|
dbEvent.setColor(event.getColor());
|
||||||
dbEvent.setStatus(event.getStatus());
|
dbEvent.setStatus(event.getStatus());
|
||||||
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));
|
dbEvent.setValueType(TimiJava.defaultIfNull(event.getValueType(), oldValueType));
|
||||||
if (event.getValueUnit() != null) {
|
if (event.getValueUnit() != null) {
|
||||||
dbEvent.setValueUnit(event.getValueUnit());
|
dbEvent.setValueUnit(event.getValueUnit());
|
||||||
@@ -193,7 +171,6 @@ public class GaoEventServiceImplement extends AbstractEntityService<GaoEvent, St
|
|||||||
logger.setContent(jackson.writeValueAsString(optionGroupList));
|
logger.setContent(jackson.writeValueAsString(optionGroupList));
|
||||||
GaoEvent event = get(eventId);
|
GaoEvent event = get(eventId);
|
||||||
TimiException.required(event, "not found event");
|
TimiException.required(event, "not found event");
|
||||||
TimiException.requiredTrue(event.getStatus() != GaoEvent.Status.DELETED, "已删除登记事件不可编辑");
|
|
||||||
verifyOptionGroupList(optionGroupList);
|
verifyOptionGroupList(optionGroupList);
|
||||||
saveOptionGroupList(eventId, optionGroupList);
|
saveOptionGroupList(eventId, optionGroupList);
|
||||||
logger.setLevel(Logger.Level.INFO);
|
logger.setLevel(Logger.Level.INFO);
|
||||||
@@ -321,16 +298,6 @@ public class GaoEventServiceImplement extends AbstractEntityService<GaoEvent, St
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void verifyEvent(GaoEvent event) {
|
private void verifyEvent(GaoEvent event) {
|
||||||
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);
|
GaoEvent.ValueType valueType = TimiJava.defaultIfNull(event.getValueType(), GaoEvent.ValueType.NONE);
|
||||||
if (valueType == GaoEvent.ValueType.NONE) {
|
if (valueType == GaoEvent.ValueType.NONE) {
|
||||||
TimiException.requiredNull(event.getValueUnit(), "NONE 事件不能配置数值单位");
|
TimiException.requiredNull(event.getValueUnit(), "NONE 事件不能配置数值单位");
|
||||||
|
|||||||
-389
@@ -1,389 +0,0 @@
|
|||||||
package com.imyeyu.api.modules.gao.service.implement;
|
|
||||||
|
|
||||||
import com.imyeyu.api.config.dbsource.TimiServerDBConfig;
|
|
||||||
import com.imyeyu.api.modules.common.entity.Attachment;
|
|
||||||
import com.imyeyu.api.modules.common.service.AttachmentService;
|
|
||||||
import com.imyeyu.api.modules.gao.entity.GaoCustomerPackage;
|
|
||||||
import com.imyeyu.api.modules.gao.entity.GaoFundRecord;
|
|
||||||
import com.imyeyu.api.modules.gao.mapper.GaoFundRecordMapper;
|
|
||||||
import com.imyeyu.api.modules.gao.service.GaoCustomerPackageService;
|
|
||||||
import com.imyeyu.api.modules.gao.service.GaoFundRecordService;
|
|
||||||
import com.imyeyu.api.modules.gao.service.GaoPackageDeliveryService;
|
|
||||||
import com.imyeyu.api.modules.gao.service.GaoStoreScopeService;
|
|
||||||
import com.imyeyu.api.modules.gao.vo.GaoFundActionRequest;
|
|
||||||
import com.imyeyu.api.modules.gao.vo.GaoFundConfirmNoRefundRequest;
|
|
||||||
import com.imyeyu.api.modules.gao.vo.GaoFundRecordPage;
|
|
||||||
import com.imyeyu.api.modules.gao.vo.GaoFundReceiveRequest;
|
|
||||||
import com.imyeyu.api.modules.gao.vo.GaoFundRefundRequest;
|
|
||||||
import com.imyeyu.api.modules.gao.vo.GaoFundRevokeRequest;
|
|
||||||
import com.imyeyu.api.modules.system.entity.Logger;
|
|
||||||
import com.imyeyu.api.modules.system.service.LoggerService;
|
|
||||||
import com.imyeyu.api.modules.user.service.UserLoginService;
|
|
||||||
import com.imyeyu.java.TimiJava;
|
|
||||||
import com.imyeyu.java.bean.timi.TimiException;
|
|
||||||
import com.imyeyu.spring.bean.PageResult;
|
|
||||||
import com.imyeyu.spring.mapper.BaseMapper;
|
|
||||||
import com.imyeyu.spring.service.AbstractEntityService;
|
|
||||||
import com.imyeyu.utils.Time;
|
|
||||||
import lombok.RequiredArgsConstructor;
|
|
||||||
import org.springframework.stereotype.Service;
|
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
/// GAO 通用资金流水服务实现
|
|
||||||
///
|
|
||||||
/// @author Codex
|
|
||||||
/// @since 2026-08-31
|
|
||||||
@Service
|
|
||||||
@RequiredArgsConstructor
|
|
||||||
public class GaoFundRecordServiceImplement extends AbstractEntityService<GaoFundRecord, String> implements GaoFundRecordService {
|
|
||||||
|
|
||||||
private final GaoFundRecordMapper mapper;
|
|
||||||
private final GaoCustomerPackageService customerPackageService;
|
|
||||||
private final GaoPackageDeliveryService deliveryService;
|
|
||||||
private final AttachmentService attachmentService;
|
|
||||||
private final GaoStoreScopeService storeScopeService;
|
|
||||||
private final UserLoginService userLoginService;
|
|
||||||
private final LoggerService loggerService;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected BaseMapper<GaoFundRecord, String> mapper() {
|
|
||||||
return mapper;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// 资金流水必须通过专用操作创建
|
|
||||||
///
|
|
||||||
/// @param record 资金流水
|
|
||||||
@Override
|
|
||||||
public void create(GaoFundRecord record) {
|
|
||||||
TimiException.requiredTrue(false, "资金流水必须通过专用接口创建");
|
|
||||||
}
|
|
||||||
|
|
||||||
/// 资金流水不允许通用修改
|
|
||||||
///
|
|
||||||
/// @param record 资金流水
|
|
||||||
@Override
|
|
||||||
public void update(GaoFundRecord record) {
|
|
||||||
TimiException.requiredTrue(false, "资金流水不允许通用修改");
|
|
||||||
}
|
|
||||||
|
|
||||||
/// 资金流水不允许删除
|
|
||||||
///
|
|
||||||
/// @param id 资金流水 ID
|
|
||||||
@Override
|
|
||||||
public void delete(String id) {
|
|
||||||
TimiException.requiredTrue(false, "资金流水不允许删除");
|
|
||||||
}
|
|
||||||
|
|
||||||
/// 资金流水不允许物理删除
|
|
||||||
///
|
|
||||||
/// @param id 资金流水 ID
|
|
||||||
@Override
|
|
||||||
public void destroy(String id) {
|
|
||||||
TimiException.requiredTrue(false, "资金流水不允许物理删除");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public PageResult<GaoFundRecord> pageByQuery(GaoFundRecordPage page) {
|
|
||||||
TimiException.required(page, "not found page");
|
|
||||||
PageResult<GaoFundRecord> result = new PageResult<>();
|
|
||||||
result.setTotal(mapper.countByQuery(page));
|
|
||||||
result.setList(mapper.selectByQuery(page));
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public List<GaoFundRecord> listByCustomerPackageId(String customerPackageId) {
|
|
||||||
TimiException.required(customerPackageId, "not found customerPackageId");
|
|
||||||
return mapper.selectByBizId(customerPackageId);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public long countPendingReceiveByBizId(String bizId) {
|
|
||||||
return mapper.countPendingReceiveByBizId(bizId);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public GaoFundRecord get(String id) {
|
|
||||||
return super.get(id);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Transactional(TimiServerDBConfig.ROLLBACKER)
|
|
||||||
@Override
|
|
||||||
public GaoFundRecord receive(GaoFundReceiveRequest request) {
|
|
||||||
return loggerService.execute(Logger.Module.GAO, "GAO_FUND_RECEIVE_CREATE", request, () -> receiveInternal(request));
|
|
||||||
}
|
|
||||||
|
|
||||||
private GaoFundRecord receiveInternal(GaoFundReceiveRequest request) {
|
|
||||||
TimiException.required(request, "not found receive request");
|
|
||||||
TimiException.required(request.getRequestNo(), "not found requestNo");
|
|
||||||
request.setRequestNo(request.getRequestNo().trim());
|
|
||||||
TimiException.required(request.getCustomerPackageId(), "not found customerPackageId");
|
|
||||||
TimiException.required(request.getAmount(), "not found amount");
|
|
||||||
TimiException.requiredTrue(0 < request.getAmount(), "收款金额必须大于 0");
|
|
||||||
GaoCustomerPackage packageEntity = lockPackage(request.getCustomerPackageId());
|
|
||||||
GaoFundRecord existing = mapper.selectByRequestNo(packageEntity.getStoreId(), request.getRequestNo());
|
|
||||||
if (existing != null) {
|
|
||||||
TimiException.requiredTrue(existing.getBizId().equals(packageEntity.getId())
|
|
||||||
&& existing.getOperationType() == GaoFundRecord.OperationType.RECEIVE
|
|
||||||
&& existing.getAmount().equals(request.getAmount())
|
|
||||||
&& (request.getOccurredAt() == null || request.getOccurredAt().equals(existing.getOccurredAt()))
|
|
||||||
&& sameText(existing.getRemark(), request.getRemark()), "requestNo 已被其他资金操作使用");
|
|
||||||
return get(existing.getId());
|
|
||||||
}
|
|
||||||
TimiException.requiredTrue(hasAttachment(request.getAttachmentList()), "收款必须上传照片");
|
|
||||||
checkPackageReceivable(packageEntity);
|
|
||||||
TimiException.requiredTrue(safeLong(packageEntity.getPaidAmount()) + safeLong(packageEntity.getPendingPaidAmount()) + request.getAmount() <= safeLong(packageEntity.getSaleAmount()), "累计收款不能超过成交价");
|
|
||||||
GaoFundRecord record = newRecord(packageEntity, GaoFundRecord.OperationType.RECEIVE, request.getRequestNo(), request.getAmount(), request.getOccurredAt(), request.getRemark());
|
|
||||||
record.setStatus(GaoFundRecord.Status.PENDING);
|
|
||||||
super.create(record);
|
|
||||||
TimiException.requiredTrue(0 < customerPackageService.updatePendingPaidAmountDelta(packageEntity.getId(), request.getAmount()), "待核销收款更新失败");
|
|
||||||
attachmentService.updateByBizId(Attachment.BizType.GAO_FUND_RECORD, record.getId(), request.getAttachmentList());
|
|
||||||
return record;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Transactional(TimiServerDBConfig.ROLLBACKER)
|
|
||||||
@Override
|
|
||||||
public GaoFundRecord verify(String fundRecordId) {
|
|
||||||
return loggerService.execute(Logger.Module.GAO, "GAO_FUND_RECEIVE_VERIFY", fundRecordId, () -> verifyInternal(fundRecordId));
|
|
||||||
}
|
|
||||||
|
|
||||||
private GaoFundRecord verifyInternal(String fundRecordId) {
|
|
||||||
GaoFundRecord record = mapper.selectForUpdate(fundRecordId);
|
|
||||||
TimiException.required(record, "not found fund record");
|
|
||||||
storeScopeService.checkStoreId(record.getStoreId());
|
|
||||||
TimiException.requiredTrue(record.getOperationType() == GaoFundRecord.OperationType.RECEIVE && record.getStatus() == GaoFundRecord.Status.PENDING, "收款记录不是待核销状态");
|
|
||||||
GaoCustomerPackage packageEntity = lockPackage(record.getBizId());
|
|
||||||
TimiException.requiredTrue(0 < customerPackageService.updatePendingPaidAmountDelta(packageEntity.getId(), -record.getAmount()), "待核销收款更新失败");
|
|
||||||
TimiException.requiredTrue(0 < customerPackageService.updatePaidAmountDelta(packageEntity.getId(), record.getAmount()), "有效收款更新失败");
|
|
||||||
String userId = userLoginService.getRequireLoginUserId();
|
|
||||||
TimiException.requiredTrue(0 < mapper.updateStatusIf(record.getId(), GaoFundRecord.Status.PENDING, GaoFundRecord.Status.VERIFIED, userId, Time.now(), record.getReason()), "收款记录状态已变化");
|
|
||||||
updatePaymentStatus(packageEntity, safeLong(packageEntity.getPaidAmount()) + record.getAmount(), safeLong(packageEntity.getPendingPaidAmount()) - record.getAmount());
|
|
||||||
record.setStatus(GaoFundRecord.Status.VERIFIED);
|
|
||||||
record.setVerifierUserId(userId);
|
|
||||||
record.setVerifiedAt(Time.now());
|
|
||||||
return record;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Transactional(TimiServerDBConfig.ROLLBACKER)
|
|
||||||
@Override
|
|
||||||
public GaoFundRecord reject(GaoFundActionRequest request) {
|
|
||||||
return loggerService.execute(Logger.Module.GAO, "GAO_FUND_RECEIVE_REJECT", request, () -> releasePending(request, GaoFundRecord.Status.REJECTED));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Transactional(TimiServerDBConfig.ROLLBACKER)
|
|
||||||
@Override
|
|
||||||
public GaoFundRecord cancel(GaoFundActionRequest request) {
|
|
||||||
return loggerService.execute(Logger.Module.GAO, "GAO_FUND_RECEIVE_CANCEL", request, () -> {
|
|
||||||
TimiException.required(request, "not found fund action request");
|
|
||||||
TimiException.required(request.getFundRecordId(), "not found fundRecordId");
|
|
||||||
GaoFundRecord record = mapper.selectForUpdate(request.getFundRecordId());
|
|
||||||
TimiException.required(record, "not found fund record");
|
|
||||||
TimiException.requiredTrue(userLoginService.getRequireLoginUserId().equals(record.getOperatorUserId()), "只能撤销自己提交的收款");
|
|
||||||
return releasePending(request, GaoFundRecord.Status.CANCELLED);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
@Transactional(TimiServerDBConfig.ROLLBACKER)
|
|
||||||
@Override
|
|
||||||
public GaoFundRecord refund(GaoFundRefundRequest request) {
|
|
||||||
return loggerService.execute(Logger.Module.GAO, "GAO_FUND_REFUND", request, () -> refundInternal(request));
|
|
||||||
}
|
|
||||||
|
|
||||||
private GaoFundRecord refundInternal(GaoFundRefundRequest request) {
|
|
||||||
TimiException.required(request, "not found refund request");
|
|
||||||
TimiException.required(request.getRequestNo(), "not found requestNo");
|
|
||||||
request.setRequestNo(request.getRequestNo().trim());
|
|
||||||
TimiException.required(request.getCustomerPackageId(), "not found customerPackageId");
|
|
||||||
TimiException.required(request.getAmount(), "not found amount");
|
|
||||||
TimiException.requiredTrue(0 < request.getAmount(), "退款金额必须大于 0");
|
|
||||||
TimiException.requiredTrue(hasReason(request.getReason()), "退款原因不能为空");
|
|
||||||
GaoCustomerPackage packageEntity = lockPackage(request.getCustomerPackageId());
|
|
||||||
GaoFundRecord existing = mapper.selectByRequestNo(packageEntity.getStoreId(), request.getRequestNo());
|
|
||||||
if (existing != null) {
|
|
||||||
TimiException.requiredTrue(existing.getBizId().equals(packageEntity.getId())
|
|
||||||
&& existing.getOperationType() == GaoFundRecord.OperationType.REFUND
|
|
||||||
&& existing.getAmount().equals(request.getAmount())
|
|
||||||
&& (request.getOccurredAt() == null || request.getOccurredAt().equals(existing.getOccurredAt()))
|
|
||||||
&& sameText(existing.getReason(), request.getReason().trim())
|
|
||||||
&& sameText(existing.getRemark(), request.getRemark()), "requestNo 已被其他资金操作使用");
|
|
||||||
return get(existing.getId());
|
|
||||||
}
|
|
||||||
TimiException.requiredTrue(hasAttachment(request.getAttachmentList()), "退款必须上传照片");
|
|
||||||
checkRefundable(packageEntity);
|
|
||||||
TimiException.requiredTrue(request.getAmount() <= safeLong(packageEntity.getPaidAmount()), "退款金额不能超过累计有效收款");
|
|
||||||
GaoFundRecord record = newRecord(packageEntity, GaoFundRecord.OperationType.REFUND, request.getRequestNo(), request.getAmount(), request.getOccurredAt(), request.getRemark());
|
|
||||||
record.setStatus(GaoFundRecord.Status.VERIFIED);
|
|
||||||
record.setReason(request.getReason().trim());
|
|
||||||
super.create(record);
|
|
||||||
packageEntity.setRefundedAmount(request.getAmount());
|
|
||||||
packageEntity.setRefundStatus(GaoCustomerPackage.RefundStatus.REFUNDED);
|
|
||||||
customerPackageService.updateAggregateState(packageEntity);
|
|
||||||
attachmentService.updateByBizId(Attachment.BizType.GAO_FUND_RECORD, record.getId(), request.getAttachmentList());
|
|
||||||
return record;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Transactional(TimiServerDBConfig.ROLLBACKER)
|
|
||||||
@Override
|
|
||||||
public GaoFundRecord confirmNoRefund(GaoFundConfirmNoRefundRequest request) {
|
|
||||||
return loggerService.execute(Logger.Module.GAO, "GAO_FUND_CONFIRM_NO_REFUND", request, () -> confirmNoRefundInternal(request));
|
|
||||||
}
|
|
||||||
|
|
||||||
private GaoFundRecord confirmNoRefundInternal(GaoFundConfirmNoRefundRequest request) {
|
|
||||||
TimiException.required(request, "not found no refund request");
|
|
||||||
TimiException.required(request.getRequestNo(), "not found requestNo");
|
|
||||||
request.setRequestNo(request.getRequestNo().trim());
|
|
||||||
TimiException.required(request.getCustomerPackageId(), "not found customerPackageId");
|
|
||||||
TimiException.requiredTrue(hasReason(request.getReason()), "确认无需退款原因不能为空");
|
|
||||||
GaoCustomerPackage packageEntity = lockPackage(request.getCustomerPackageId());
|
|
||||||
GaoFundRecord existing = mapper.selectByRequestNo(packageEntity.getStoreId(), request.getRequestNo());
|
|
||||||
if (existing != null) {
|
|
||||||
TimiException.requiredTrue(existing.getBizId().equals(packageEntity.getId())
|
|
||||||
&& existing.getOperationType() == GaoFundRecord.OperationType.CONFIRM_NO_REFUND
|
|
||||||
&& (request.getOccurredAt() == null || request.getOccurredAt().equals(existing.getOccurredAt()))
|
|
||||||
&& sameText(existing.getReason(), request.getReason().trim())
|
|
||||||
&& sameText(existing.getRemark(), request.getRemark()), "requestNo 已被其他资金操作使用");
|
|
||||||
return get(existing.getId());
|
|
||||||
}
|
|
||||||
checkRefundable(packageEntity);
|
|
||||||
GaoFundRecord record = newRecord(packageEntity, GaoFundRecord.OperationType.CONFIRM_NO_REFUND, request.getRequestNo(), 0L, request.getOccurredAt(), request.getRemark());
|
|
||||||
record.setStatus(GaoFundRecord.Status.VERIFIED);
|
|
||||||
record.setReason(request.getReason().trim());
|
|
||||||
super.create(record);
|
|
||||||
packageEntity.setRefundedAmount(0L);
|
|
||||||
packageEntity.setRefundStatus(GaoCustomerPackage.RefundStatus.REFUNDED);
|
|
||||||
customerPackageService.updateAggregateState(packageEntity);
|
|
||||||
return record;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Transactional(TimiServerDBConfig.ROLLBACKER)
|
|
||||||
@Override
|
|
||||||
public GaoFundRecord revoke(GaoFundRevokeRequest request) {
|
|
||||||
return loggerService.execute(Logger.Module.GAO, "GAO_FUND_REVOKE", request, () -> revokeInternal(request));
|
|
||||||
}
|
|
||||||
|
|
||||||
private GaoFundRecord revokeInternal(GaoFundRevokeRequest request) {
|
|
||||||
TimiException.required(request, "not found fund revoke request");
|
|
||||||
TimiException.required(request.getRequestNo(), "not found requestNo");
|
|
||||||
request.setRequestNo(request.getRequestNo().trim());
|
|
||||||
TimiException.required(request.getFundRecordId(), "not found fundRecordId");
|
|
||||||
TimiException.requiredTrue(hasReason(request.getReason()), "资金冲正原因不能为空");
|
|
||||||
GaoFundRecord source = mapper.selectForUpdate(request.getFundRecordId());
|
|
||||||
TimiException.required(source, "not found fund record");
|
|
||||||
storeScopeService.checkStoreId(source.getStoreId());
|
|
||||||
GaoFundRecord existing = mapper.selectByRequestNo(source.getStoreId(), request.getRequestNo());
|
|
||||||
if (existing != null) {
|
|
||||||
TimiException.requiredTrue(existing.getOperationType() == GaoFundRecord.OperationType.REVOKE
|
|
||||||
&& source.getId().equals(existing.getSourceRecordId()), "requestNo 已被其他资金操作使用");
|
|
||||||
return get(existing.getId());
|
|
||||||
}
|
|
||||||
TimiException.requiredTrue(hasAttachment(request.getAttachmentList()), "资金冲正必须上传照片");
|
|
||||||
TimiException.requiredTrue(source.getStatus() == GaoFundRecord.Status.VERIFIED && source.getOperationType() != GaoFundRecord.OperationType.REVOKE, "只有已生效资金记录可以冲正");
|
|
||||||
TimiException.requiredNull(mapper.selectRevokeBySourceRecordId(source.getId()), "该资金记录已经冲正");
|
|
||||||
GaoCustomerPackage packageEntity = lockPackage(source.getBizId());
|
|
||||||
if (source.getOperationType() == GaoFundRecord.OperationType.RECEIVE) {
|
|
||||||
TimiException.requiredTrue(packageEntity.getRefundStatus() != GaoCustomerPackage.RefundStatus.REFUNDED, "退款完成后不能冲正相关收款");
|
|
||||||
long paidAfter = safeLong(packageEntity.getPaidAmount()) - source.getAmount();
|
|
||||||
if (0 < deliveryService.countVerifiedByCustomerPackageId(packageEntity.getId())) {
|
|
||||||
TimiException.requiredTrue(packageEntity.getSaleAmount() <= paidAfter, "存在已核销发放,冲正收款后套餐仍须付清");
|
|
||||||
}
|
|
||||||
TimiException.requiredTrue(0 < customerPackageService.updatePaidAmountDelta(packageEntity.getId(), -source.getAmount()), "有效收款冲正失败");
|
|
||||||
packageEntity.setPaidAmount(paidAfter);
|
|
||||||
updatePaymentStatus(packageEntity, paidAfter, packageEntity.getPendingPaidAmount());
|
|
||||||
} else {
|
|
||||||
TimiException.requiredTrue(packageEntity.getRefundStatus() == GaoCustomerPackage.RefundStatus.REFUNDED, "资金记录退款状态无效");
|
|
||||||
packageEntity.setRefundedAmount(0L);
|
|
||||||
packageEntity.setRefundStatus(GaoCustomerPackage.RefundStatus.PENDING);
|
|
||||||
customerPackageService.updateAggregateState(packageEntity);
|
|
||||||
}
|
|
||||||
GaoFundRecord revoke = newRecord(packageEntity, GaoFundRecord.OperationType.REVOKE, request.getRequestNo(), source.getAmount(), request.getOccurredAt(), request.getRemark());
|
|
||||||
revoke.setStatus(GaoFundRecord.Status.VERIFIED);
|
|
||||||
revoke.setSourceRecordId(source.getId());
|
|
||||||
revoke.setReason(request.getReason().trim());
|
|
||||||
super.create(revoke);
|
|
||||||
attachmentService.updateByBizId(Attachment.BizType.GAO_FUND_RECORD, revoke.getId(), request.getAttachmentList());
|
|
||||||
return revoke;
|
|
||||||
}
|
|
||||||
|
|
||||||
private GaoFundRecord releasePending(GaoFundActionRequest request, GaoFundRecord.Status targetStatus) {
|
|
||||||
TimiException.required(request, "not found fund action request");
|
|
||||||
TimiException.required(request.getFundRecordId(), "not found fundRecordId");
|
|
||||||
TimiException.requiredTrue(hasReason(request.getReason()), "拒绝或撤销原因不能为空");
|
|
||||||
GaoFundRecord record = mapper.selectForUpdate(request.getFundRecordId());
|
|
||||||
TimiException.required(record, "not found fund record");
|
|
||||||
storeScopeService.checkStoreId(record.getStoreId());
|
|
||||||
TimiException.requiredTrue(record.getOperationType() == GaoFundRecord.OperationType.RECEIVE && record.getStatus() == GaoFundRecord.Status.PENDING, "收款记录不是待核销状态");
|
|
||||||
GaoCustomerPackage packageEntity = lockPackage(record.getBizId());
|
|
||||||
TimiException.requiredTrue(0 < customerPackageService.updatePendingPaidAmountDelta(packageEntity.getId(), -record.getAmount()), "待核销收款更新失败");
|
|
||||||
String userId = userLoginService.getRequireLoginUserId();
|
|
||||||
TimiException.requiredTrue(0 < mapper.updateStatusIf(record.getId(), GaoFundRecord.Status.PENDING, targetStatus, userId, Time.now(), request.getReason().trim()), "收款记录状态已变化");
|
|
||||||
record.setStatus(targetStatus);
|
|
||||||
record.setVerifierUserId(userId);
|
|
||||||
record.setVerifiedAt(Time.now());
|
|
||||||
record.setReason(request.getReason().trim());
|
|
||||||
return record;
|
|
||||||
}
|
|
||||||
|
|
||||||
private GaoCustomerPackage lockPackage(String id) {
|
|
||||||
GaoCustomerPackage result = customerPackageService.getForUpdate(id);
|
|
||||||
TimiException.required(result, "not found customer package");
|
|
||||||
storeScopeService.checkStoreId(result.getStoreId());
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void checkPackageReceivable(GaoCustomerPackage packageEntity) {
|
|
||||||
TimiException.requiredTrue(packageEntity.getStatus() != GaoCustomerPackage.Status.CANCELLED, "已取消套餐不能收款");
|
|
||||||
TimiException.requiredTrue(packageEntity.getRefundStatus() != GaoCustomerPackage.RefundStatus.REFUNDED, "已完成退款套餐不能收款");
|
|
||||||
}
|
|
||||||
|
|
||||||
private void checkRefundable(GaoCustomerPackage packageEntity) {
|
|
||||||
TimiException.requiredTrue(packageEntity.getStatus() == GaoCustomerPackage.Status.CANCELLED, "只有已取消套餐可以退款");
|
|
||||||
TimiException.requiredTrue(packageEntity.getRefundStatus() == GaoCustomerPackage.RefundStatus.PENDING, "当前套餐不在待退款状态");
|
|
||||||
}
|
|
||||||
|
|
||||||
private GaoFundRecord newRecord(GaoCustomerPackage packageEntity, GaoFundRecord.OperationType operationType, String requestNo, Long amount, Long occurredAt, String remark) {
|
|
||||||
GaoFundRecord record = new GaoFundRecord();
|
|
||||||
record.setStoreId(packageEntity.getStoreId());
|
|
||||||
record.setCustomerId(packageEntity.getCustomerId());
|
|
||||||
record.setBizType(GaoFundRecord.BizType.CUSTOMER_PACKAGE);
|
|
||||||
record.setBizId(packageEntity.getId());
|
|
||||||
record.setOperationType(operationType);
|
|
||||||
record.setAmount(amount);
|
|
||||||
record.setRequestNo(requestNo);
|
|
||||||
record.setOperatorUserId(userLoginService.getRequireLoginUserId());
|
|
||||||
record.setOccurredAt(TimiJava.defaultIfNull(occurredAt, Time.now()));
|
|
||||||
record.setRemark(remark);
|
|
||||||
return record;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void updatePaymentStatus(GaoCustomerPackage packageEntity, long paidAmount, long pendingAmount) {
|
|
||||||
packageEntity.setPaidAmount(paidAmount);
|
|
||||||
packageEntity.setPendingPaidAmount(pendingAmount);
|
|
||||||
packageEntity.setPaymentStatus(safeLong(packageEntity.getSaleAmount()) == 0 || paidAmount >= safeLong(packageEntity.getSaleAmount())
|
|
||||||
? GaoCustomerPackage.PaymentStatus.PAID
|
|
||||||
: (0 < paidAmount ? GaoCustomerPackage.PaymentStatus.PARTIALLY_PAID : GaoCustomerPackage.PaymentStatus.UNPAID));
|
|
||||||
customerPackageService.updateAggregateState(packageEntity);
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean hasAttachment(List<Attachment> attachmentList) {
|
|
||||||
for (Attachment attachment : TimiJava.safeIterable(attachmentList)) {
|
|
||||||
if (attachment != null && (attachment.getAttachType() == null || "PHOTO".equalsIgnoreCase(attachment.getAttachType()))) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean hasReason(String reason) {
|
|
||||||
return reason != null && !reason.trim().isEmpty();
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean sameText(String left, String right) {
|
|
||||||
return left == null ? right == null : left.equals(right);
|
|
||||||
}
|
|
||||||
|
|
||||||
private long safeLong(Long value) {
|
|
||||||
return value == null ? 0L : value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
-215
@@ -1,215 +0,0 @@
|
|||||||
package com.imyeyu.api.modules.gao.service.implement;
|
|
||||||
|
|
||||||
import com.imyeyu.api.config.dbsource.TimiServerDBConfig;
|
|
||||||
import com.imyeyu.api.modules.gao.entity.GaoPackageConfig;
|
|
||||||
import com.imyeyu.api.modules.gao.entity.GaoPackageConfigItem;
|
|
||||||
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;
|
|
||||||
import com.imyeyu.java.TimiJava;
|
|
||||||
import com.imyeyu.java.bean.timi.TimiException;
|
|
||||||
import com.imyeyu.spring.bean.PageResult;
|
|
||||||
import com.imyeyu.spring.mapper.BaseMapper;
|
|
||||||
import com.imyeyu.spring.service.AbstractEntityService;
|
|
||||||
import com.imyeyu.utils.Time;
|
|
||||||
import lombok.RequiredArgsConstructor;
|
|
||||||
import org.springframework.stereotype.Service;
|
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
|
||||||
|
|
||||||
import java.math.BigDecimal;
|
|
||||||
import java.util.Collection;
|
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
/// GAO 套餐配置服务实现
|
|
||||||
///
|
|
||||||
/// @author Codex
|
|
||||||
/// @since 2026-08-31
|
|
||||||
@Service
|
|
||||||
@RequiredArgsConstructor
|
|
||||||
public class GaoPackageConfigServiceImplement extends AbstractEntityService<GaoPackageConfig, String> implements GaoPackageConfigService {
|
|
||||||
|
|
||||||
private final GaoPackageConfigMapper mapper;
|
|
||||||
private final GaoPackageConfigItemMapper itemMapper;
|
|
||||||
private final GaoEventMapper eventMapper;
|
|
||||||
private final UserLoginService userLoginService;
|
|
||||||
private final LoggerService loggerService;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected BaseMapper<GaoPackageConfig, String> mapper() {
|
|
||||||
return mapper;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public PageResult<GaoPackageConfig> pageByQuery(GaoPackageConfigPage page) {
|
|
||||||
TimiException.required(page, "not found page");
|
|
||||||
PageResult<GaoPackageConfig> result = new PageResult<>();
|
|
||||||
result.setTotal(mapper.countByQuery(page));
|
|
||||||
result.setList(mapper.selectByQuery(page));
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public List<GaoPackageConfig> listValid(String storeId) {
|
|
||||||
TimiException.required(storeId, "not found storeId");
|
|
||||||
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");
|
|
||||||
return itemMapper.selectByPackageConfigId(packageConfigId);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Map<String, List<GaoPackageConfigItem>> mapItemListByPackageConfigIdList(Collection<String> packageConfigIdList) {
|
|
||||||
if (packageConfigIdList == null || packageConfigIdList.isEmpty()) {
|
|
||||||
return Map.of();
|
|
||||||
}
|
|
||||||
return itemMapper.selectByPackageConfigIdList(packageConfigIdList).stream()
|
|
||||||
.collect(java.util.stream.Collectors.groupingBy(GaoPackageConfigItem::getPackageConfigId));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Transactional(TimiServerDBConfig.ROLLBACKER)
|
|
||||||
@Override
|
|
||||||
public void create(GaoPackageConfig config) {
|
|
||||||
loggerService.execute(Logger.Module.GAO, "GAO_PACKAGE_CONFIG_CREATE", config, () -> {
|
|
||||||
createInternal(config);
|
|
||||||
return config;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
private void createInternal(GaoPackageConfig config) {
|
|
||||||
TimiException.required(config, "not found package config");
|
|
||||||
TimiException.required(config.getStoreId(), "not found packageConfig.storeId");
|
|
||||||
TimiException.required(config.getItemList(), "套餐至少配置一个产品");
|
|
||||||
prepareConfig(config, null);
|
|
||||||
config.setUpdatedBy(userLoginService.getRequireLoginUserId());
|
|
||||||
super.create(config);
|
|
||||||
saveItems(config.getId(), config.getItemList());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Transactional(TimiServerDBConfig.ROLLBACKER)
|
|
||||||
@Override
|
|
||||||
public void update(GaoPackageConfig request) {
|
|
||||||
loggerService.execute(Logger.Module.GAO, "GAO_PACKAGE_CONFIG_UPDATE", request, () -> {
|
|
||||||
updateInternal(request);
|
|
||||||
return request;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
private void updateInternal(GaoPackageConfig request) {
|
|
||||||
TimiException.required(request, "not found package config");
|
|
||||||
TimiException.required(request.getId(), "not found packageConfig.id");
|
|
||||||
GaoPackageConfig dbConfig = get(request.getId());
|
|
||||||
TimiException.required(dbConfig, "not found package config");
|
|
||||||
TimiException.requiredTrue(request.getStoreId() == null || request.getStoreId().equals(dbConfig.getStoreId()), "packageConfig.storeId invalid");
|
|
||||||
dbConfig.setName(request.getName());
|
|
||||||
dbConfig.setDescription(request.getDescription());
|
|
||||||
dbConfig.setStandardAmount(TimiJava.defaultIfNull(request.getStandardAmount(), dbConfig.getStandardAmount()));
|
|
||||||
dbConfig.setStatus(TimiJava.defaultIfNull(request.getStatus(), dbConfig.getStatus()));
|
|
||||||
dbConfig.setBeginAt(request.getBeginAt());
|
|
||||||
dbConfig.setEndAt(request.getEndAt());
|
|
||||||
dbConfig.setSort(request.getSort());
|
|
||||||
prepareConfig(dbConfig, dbConfig.getId());
|
|
||||||
dbConfig.setUpdatedBy(userLoginService.getRequireLoginUserId());
|
|
||||||
super.update(dbConfig);
|
|
||||||
if (request.getItemList() != null) {
|
|
||||||
verifyItems(request.getItemList());
|
|
||||||
GaoPackageConfigItem example = new GaoPackageConfigItem();
|
|
||||||
example.setPackageConfigId(dbConfig.getId());
|
|
||||||
itemMapper.deleteAllByExample(example);
|
|
||||||
saveItems(dbConfig.getId(), request.getItemList());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Transactional(TimiServerDBConfig.ROLLBACKER)
|
|
||||||
@Override
|
|
||||||
public void delete(String id) {
|
|
||||||
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;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/// 套餐配置只允许逻辑删除
|
|
||||||
///
|
|
||||||
/// @param id 套餐配置 ID
|
|
||||||
@Override
|
|
||||||
public void destroy(String id) {
|
|
||||||
TimiException.requiredTrue(false, "套餐配置不允许物理删除");
|
|
||||||
}
|
|
||||||
|
|
||||||
private void prepareConfig(GaoPackageConfig config, String excludeId) {
|
|
||||||
String name = trimRequired(config.getName(), "套餐名称不能为空");
|
|
||||||
TimiException.requiredNull(mapper.selectByStoreIdAndName(config.getStoreId(), name, excludeId), "门店内套餐名称不能重复");
|
|
||||||
config.setName(name);
|
|
||||||
config.setStandardAmount(TimiJava.defaultIfNull(config.getStandardAmount(), 0L));
|
|
||||||
TimiException.requiredTrue(0 <= config.getStandardAmount(), "套餐标准价不能为负数");
|
|
||||||
config.setStatus(TimiJava.defaultIfNull(config.getStatus(), GaoPackageConfig.Status.DRAFT));
|
|
||||||
config.setSort(TimiJava.defaultIfNull(config.getSort(), 0));
|
|
||||||
TimiException.requiredTrue(config.getBeginAt() == null || config.getEndAt() == null || config.getBeginAt() <= config.getEndAt(), "套餐有效期无效");
|
|
||||||
if (config.getItemList() != null) {
|
|
||||||
verifyItems(config.getItemList());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void verifyItems(List<GaoPackageConfigItem> itemList) {
|
|
||||||
TimiException.requiredTrue(!itemList.isEmpty(), "套餐至少配置一个产品");
|
|
||||||
Set<String> keySet = new HashSet<>();
|
|
||||||
for (int i = 0; i < itemList.size(); i++) {
|
|
||||||
GaoPackageConfigItem item = itemList.get(i);
|
|
||||||
TimiException.required(item, "套餐产品明细不能为空");
|
|
||||||
String name = trimRequired(item.getProductName(), "产品名称不能为空");
|
|
||||||
String unit = trimRequired(item.getUnit(), "产品单位不能为空");
|
|
||||||
BigDecimal quantity = item.getDefaultQuantity();
|
|
||||||
TimiException.required(quantity, "产品默认数量不能为空");
|
|
||||||
TimiException.requiredTrue(0 < quantity.signum(), "产品默认数量必须大于 0");
|
|
||||||
TimiException.requiredTrue(3 >= quantity.scale(), "产品数量最多保留三位小数");
|
|
||||||
String key = name + "|" + unit;
|
|
||||||
TimiException.requiredTrue(keySet.add(key), "同一套餐内产品名称和单位不能重复");
|
|
||||||
item.setProductName(name);
|
|
||||||
item.setUnit(unit);
|
|
||||||
item.setSort(TimiJava.defaultIfNull(item.getSort(), i));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void saveItems(String configId, List<GaoPackageConfigItem> itemList) {
|
|
||||||
for (GaoPackageConfigItem source : TimiJava.safeIterable(itemList)) {
|
|
||||||
GaoPackageConfigItem item = new GaoPackageConfigItem();
|
|
||||||
item.setPackageConfigId(configId);
|
|
||||||
item.setProductName(source.getProductName());
|
|
||||||
item.setUnit(source.getUnit());
|
|
||||||
item.setDefaultQuantity(source.getDefaultQuantity());
|
|
||||||
item.setSort(source.getSort());
|
|
||||||
item.setRemark(source.getRemark());
|
|
||||||
itemMapper.insert(item);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private String trimRequired(String value, String message) {
|
|
||||||
TimiException.required(value, message);
|
|
||||||
String result = value.trim();
|
|
||||||
TimiException.requiredTrue(!result.isEmpty(), message);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
-410
@@ -1,410 +0,0 @@
|
|||||||
package com.imyeyu.api.modules.gao.service.implement;
|
|
||||||
|
|
||||||
import com.imyeyu.api.config.dbsource.TimiServerDBConfig;
|
|
||||||
import com.imyeyu.api.modules.common.entity.Attachment;
|
|
||||||
import com.imyeyu.api.modules.common.service.AttachmentService;
|
|
||||||
import com.imyeyu.api.modules.gao.entity.GaoCustomerPackage;
|
|
||||||
import com.imyeyu.api.modules.gao.entity.GaoCustomerPackageItem;
|
|
||||||
import com.imyeyu.api.modules.gao.entity.GaoPackageDelivery;
|
|
||||||
import com.imyeyu.api.modules.gao.entity.GaoPackageDeliveryItem;
|
|
||||||
import com.imyeyu.api.modules.gao.mapper.GaoPackageDeliveryItemMapper;
|
|
||||||
import com.imyeyu.api.modules.gao.mapper.GaoPackageDeliveryMapper;
|
|
||||||
import com.imyeyu.api.modules.gao.service.GaoCustomerPackageService;
|
|
||||||
import com.imyeyu.api.modules.gao.service.GaoPackageDeliveryService;
|
|
||||||
import com.imyeyu.api.modules.gao.service.GaoStoreScopeService;
|
|
||||||
import com.imyeyu.api.modules.gao.vo.GaoPackageDeliveryActionRequest;
|
|
||||||
import com.imyeyu.api.modules.gao.vo.GaoPackageDeliveryCreateRequest;
|
|
||||||
import com.imyeyu.api.modules.gao.vo.GaoPackageDeliveryPage;
|
|
||||||
import com.imyeyu.api.modules.gao.vo.GaoPackageDeliveryRevokeRequest;
|
|
||||||
import com.imyeyu.api.modules.system.entity.Logger;
|
|
||||||
import com.imyeyu.api.modules.system.service.LoggerService;
|
|
||||||
import com.imyeyu.api.modules.user.service.UserLoginService;
|
|
||||||
import com.imyeyu.java.TimiJava;
|
|
||||||
import com.imyeyu.java.bean.timi.TimiCode;
|
|
||||||
import com.imyeyu.java.bean.timi.TimiException;
|
|
||||||
import com.imyeyu.spring.bean.PageResult;
|
|
||||||
import com.imyeyu.spring.mapper.BaseMapper;
|
|
||||||
import com.imyeyu.spring.service.AbstractEntityService;
|
|
||||||
import com.imyeyu.utils.Time;
|
|
||||||
import lombok.RequiredArgsConstructor;
|
|
||||||
import org.springframework.stereotype.Service;
|
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
|
||||||
|
|
||||||
import java.math.BigDecimal;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Collection;
|
|
||||||
import java.util.Comparator;
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
/// GAO 套餐发放服务实现
|
|
||||||
///
|
|
||||||
/// @author Codex
|
|
||||||
/// @since 2026-08-31
|
|
||||||
@Service
|
|
||||||
@RequiredArgsConstructor
|
|
||||||
public class GaoPackageDeliveryServiceImplement extends AbstractEntityService<GaoPackageDelivery, String> implements GaoPackageDeliveryService {
|
|
||||||
|
|
||||||
private static final BigDecimal ZERO = BigDecimal.ZERO;
|
|
||||||
|
|
||||||
private final GaoPackageDeliveryMapper mapper;
|
|
||||||
private final GaoPackageDeliveryItemMapper itemMapper;
|
|
||||||
private final GaoCustomerPackageService customerPackageService;
|
|
||||||
private final AttachmentService attachmentService;
|
|
||||||
private final GaoStoreScopeService storeScopeService;
|
|
||||||
private final UserLoginService userLoginService;
|
|
||||||
private final LoggerService loggerService;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected BaseMapper<GaoPackageDelivery, String> mapper() {
|
|
||||||
return mapper;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// 发放流水必须通过专用操作创建
|
|
||||||
///
|
|
||||||
/// @param delivery 发放流水
|
|
||||||
@Override
|
|
||||||
public void create(GaoPackageDelivery delivery) {
|
|
||||||
throw new TimiException(TimiCode.ERROR, "发放流水必须通过专用接口创建");
|
|
||||||
}
|
|
||||||
|
|
||||||
/// 发放流水不允许通用修改
|
|
||||||
///
|
|
||||||
/// @param delivery 发放流水
|
|
||||||
@Override
|
|
||||||
public void update(GaoPackageDelivery delivery) {
|
|
||||||
throw new TimiException(TimiCode.ERROR, "发放流水不允许通用修改");
|
|
||||||
}
|
|
||||||
|
|
||||||
/// 发放流水不允许删除
|
|
||||||
///
|
|
||||||
/// @param id 发放流水 ID
|
|
||||||
@Override
|
|
||||||
public void delete(String id) {
|
|
||||||
throw new TimiException(TimiCode.ERROR, "发放流水不允许删除");
|
|
||||||
}
|
|
||||||
|
|
||||||
/// 发放流水不允许物理删除
|
|
||||||
///
|
|
||||||
/// @param id 发放流水 ID
|
|
||||||
@Override
|
|
||||||
public void destroy(String id) {
|
|
||||||
throw new TimiException(TimiCode.ERROR, "发放流水不允许物理删除");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public PageResult<GaoPackageDelivery> pageByQuery(GaoPackageDeliveryPage page) {
|
|
||||||
TimiException.required(page, "not found page");
|
|
||||||
PageResult<GaoPackageDelivery> result = new PageResult<>();
|
|
||||||
result.setTotal(mapper.countByQuery(page));
|
|
||||||
result.setList(mapper.selectByQuery(page));
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public List<GaoPackageDelivery> listByCustomerPackageId(String customerPackageId) {
|
|
||||||
TimiException.required(customerPackageId, "not found customerPackageId");
|
|
||||||
return mapper.selectByCustomerPackageId(customerPackageId);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Map<String, List<GaoPackageDeliveryItem>> mapItemListByDeliveryIdList(Collection<String> deliveryIdList) {
|
|
||||||
if (deliveryIdList == null || deliveryIdList.isEmpty()) {
|
|
||||||
return Map.of();
|
|
||||||
}
|
|
||||||
return itemMapper.selectByDeliveryIdList(deliveryIdList).stream()
|
|
||||||
.collect(java.util.stream.Collectors.groupingBy(GaoPackageDeliveryItem::getDeliveryId));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public long countPendingByCustomerPackageId(String customerPackageId) {
|
|
||||||
return mapper.countPendingByCustomerPackageId(customerPackageId);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public long countVerifiedByCustomerPackageId(String customerPackageId) {
|
|
||||||
return mapper.countVerifiedByCustomerPackageId(customerPackageId);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public GaoPackageDelivery get(String id) {
|
|
||||||
return super.get(id);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Transactional(TimiServerDBConfig.ROLLBACKER)
|
|
||||||
@Override
|
|
||||||
public GaoPackageDelivery createDelivery(GaoPackageDeliveryCreateRequest request) {
|
|
||||||
return loggerService.execute(Logger.Module.GAO, "GAO_PACKAGE_DELIVERY_CREATE", request, () -> createDeliveryInternal(request));
|
|
||||||
}
|
|
||||||
|
|
||||||
private GaoPackageDelivery createDeliveryInternal(GaoPackageDeliveryCreateRequest request) {
|
|
||||||
TimiException.required(request, "not found delivery request");
|
|
||||||
TimiException.required(request.getRequestNo(), "not found requestNo");
|
|
||||||
request.setRequestNo(request.getRequestNo().trim());
|
|
||||||
TimiException.required(request.getCustomerPackageId(), "not found customerPackageId");
|
|
||||||
GaoCustomerPackage packageEntity = customerPackageService.getForUpdate(request.getCustomerPackageId());
|
|
||||||
TimiException.required(packageEntity, "not found customer package");
|
|
||||||
storeScopeService.checkStoreId(packageEntity.getStoreId());
|
|
||||||
GaoPackageDelivery existing = mapper.selectByRequestNo(packageEntity.getStoreId(), request.getRequestNo());
|
|
||||||
if (existing != null) {
|
|
||||||
TimiException.requiredTrue(existing.getOperationType() == GaoPackageDelivery.OperationType.DELIVER, "requestNo 已被其他发放操作使用");
|
|
||||||
verifyCreateIdempotency(existing, request);
|
|
||||||
return get(existing.getId());
|
|
||||||
}
|
|
||||||
TimiException.requiredTrue(hasAttachment(request.getAttachmentList()), "发放必须上传照片");
|
|
||||||
TimiException.requiredTrue(packageEntity.getStatus() == GaoCustomerPackage.Status.ACTIVE, "当前套餐不可发放");
|
|
||||||
TimiException.requiredTrue(packageEntity.getPaymentStatus() == GaoCustomerPackage.PaymentStatus.PAID, "套餐未付清,不能发放");
|
|
||||||
List<GaoPackageDeliveryItem> requestItemList = validateRequestItems(request.getItemList());
|
|
||||||
Map<String, GaoCustomerPackageItem> packageItemMap = new HashMap<>();
|
|
||||||
for (GaoPackageDeliveryItem requestItem : requestItemList) {
|
|
||||||
GaoCustomerPackageItem packageItem = customerPackageService.getItemForUpdate(requestItem.getCustomerPackageItemId());
|
|
||||||
TimiException.required(packageItem, "not found customer package item");
|
|
||||||
TimiException.requiredTrue(packageEntity.getId().equals(packageItem.getCustomerPackageId()), "发放产品不属于当前套餐");
|
|
||||||
packageItemMap.put(packageItem.getId(), packageItem);
|
|
||||||
}
|
|
||||||
|
|
||||||
GaoPackageDelivery delivery = new GaoPackageDelivery();
|
|
||||||
delivery.setCustomerPackageId(packageEntity.getId());
|
|
||||||
delivery.setStoreId(packageEntity.getStoreId());
|
|
||||||
delivery.setCustomerId(packageEntity.getCustomerId());
|
|
||||||
delivery.setOperationType(GaoPackageDelivery.OperationType.DELIVER);
|
|
||||||
delivery.setStatus(GaoPackageDelivery.Status.PENDING);
|
|
||||||
delivery.setRequestNo(request.getRequestNo());
|
|
||||||
delivery.setOperatorUserId(userLoginService.getRequireLoginUserId());
|
|
||||||
delivery.setDeliveredAt(TimiJava.defaultIfNull(request.getDeliveredAt(), Time.now()));
|
|
||||||
delivery.setRemark(request.getRemark());
|
|
||||||
super.create(delivery);
|
|
||||||
for (GaoPackageDeliveryItem requestItem : requestItemList) {
|
|
||||||
GaoCustomerPackageItem packageItem = packageItemMap.get(requestItem.getCustomerPackageItemId());
|
|
||||||
BigDecimal reservedBefore = decimal(packageItem.getReservedQuantity());
|
|
||||||
BigDecimal deliveredBefore = decimal(packageItem.getDeliveredQuantity());
|
|
||||||
BigDecimal available = decimal(packageItem.getTotalQuantity()).subtract(reservedBefore).subtract(deliveredBefore);
|
|
||||||
TimiException.requiredTrue(0 <= available.compareTo(requestItem.getQuantity()), "产品可发数量不足");
|
|
||||||
int updated = customerPackageService.updateItemReservedQuantity(packageItem.getId(), requestItem.getQuantity());
|
|
||||||
TimiException.requiredTrue(0 < updated, "产品可发数量不足");
|
|
||||||
GaoPackageDeliveryItem savedItem = copyDeliveryItem(requestItem);
|
|
||||||
savedItem.setDeliveryId(delivery.getId());
|
|
||||||
savedItem.setReservedBefore(reservedBefore);
|
|
||||||
savedItem.setReservedAfter(reservedBefore.add(requestItem.getQuantity()));
|
|
||||||
savedItem.setDeliveredBefore(deliveredBefore);
|
|
||||||
savedItem.setDeliveredAfter(deliveredBefore);
|
|
||||||
savedItem.setProductNameSnapshot(packageItem.getProductNameSnapshot());
|
|
||||||
savedItem.setUnitSnapshot(packageItem.getUnitSnapshot());
|
|
||||||
itemMapper.insert(savedItem);
|
|
||||||
}
|
|
||||||
attachmentService.updateByBizId(Attachment.BizType.GAO_PACKAGE_DELIVERY, delivery.getId(), request.getAttachmentList());
|
|
||||||
return delivery;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Transactional(TimiServerDBConfig.ROLLBACKER)
|
|
||||||
@Override
|
|
||||||
public GaoPackageDelivery verify(String deliveryId) {
|
|
||||||
return loggerService.execute(Logger.Module.GAO, "GAO_PACKAGE_DELIVERY_VERIFY", deliveryId, () -> verifyInternal(deliveryId));
|
|
||||||
}
|
|
||||||
|
|
||||||
private GaoPackageDelivery verifyInternal(String deliveryId) {
|
|
||||||
GaoPackageDelivery delivery = mapper.selectForUpdate(deliveryId);
|
|
||||||
TimiException.required(delivery, "not found delivery");
|
|
||||||
storeScopeService.checkStoreId(delivery.getStoreId());
|
|
||||||
TimiException.requiredTrue(delivery.getStatus() == GaoPackageDelivery.Status.PENDING && delivery.getOperationType() == GaoPackageDelivery.OperationType.DELIVER, "发放单不是待核销状态");
|
|
||||||
GaoCustomerPackage packageEntity = customerPackageService.getForUpdate(delivery.getCustomerPackageId());
|
|
||||||
TimiException.required(packageEntity, "not found customer package");
|
|
||||||
TimiException.requiredTrue(packageEntity.getStatus() == GaoCustomerPackage.Status.ACTIVE, "当前套餐不可核销发放");
|
|
||||||
TimiException.requiredTrue(packageEntity.getPaymentStatus() == GaoCustomerPackage.PaymentStatus.PAID, "套餐未付清,不能核销发放");
|
|
||||||
List<GaoPackageDeliveryItem> itemList = itemMapper.selectByDeliveryId(delivery.getId());
|
|
||||||
for (GaoPackageDeliveryItem deliveryItem : itemList) {
|
|
||||||
GaoCustomerPackageItem packageItem = customerPackageService.getItemForUpdate(deliveryItem.getCustomerPackageItemId());
|
|
||||||
TimiException.required(packageItem, "not found customer package item");
|
|
||||||
TimiException.requiredTrue(0 < customerPackageService.updateItemReservedQuantity(packageItem.getId(), deliveryItem.getQuantity().negate()), "发放占用数量异常");
|
|
||||||
TimiException.requiredTrue(0 < customerPackageService.updateItemDeliveredQuantity(packageItem.getId(), deliveryItem.getQuantity()), "发放数量异常");
|
|
||||||
}
|
|
||||||
TimiException.requiredTrue(0 < mapper.updateStatusIf(delivery.getId(), GaoPackageDelivery.Status.PENDING, GaoPackageDelivery.Status.VERIFIED, userLoginService.getRequireLoginUserId(), Time.now(), delivery.getReason()), "发放单状态已变化");
|
|
||||||
delivery.setStatus(GaoPackageDelivery.Status.VERIFIED);
|
|
||||||
delivery.setVerifierUserId(userLoginService.getRequireLoginUserId());
|
|
||||||
delivery.setVerifiedAt(Time.now());
|
|
||||||
refreshPackageStatus(packageEntity);
|
|
||||||
return delivery;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Transactional(TimiServerDBConfig.ROLLBACKER)
|
|
||||||
@Override
|
|
||||||
public GaoPackageDelivery reject(GaoPackageDeliveryActionRequest request) {
|
|
||||||
return loggerService.execute(Logger.Module.GAO, "GAO_PACKAGE_DELIVERY_REJECT", request, () -> releasePending(request, GaoPackageDelivery.Status.REJECTED));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Transactional(TimiServerDBConfig.ROLLBACKER)
|
|
||||||
@Override
|
|
||||||
public GaoPackageDelivery cancel(GaoPackageDeliveryActionRequest request) {
|
|
||||||
return loggerService.execute(Logger.Module.GAO, "GAO_PACKAGE_DELIVERY_CANCEL", request, () -> cancelInternal(request));
|
|
||||||
}
|
|
||||||
|
|
||||||
private GaoPackageDelivery cancelInternal(GaoPackageDeliveryActionRequest request) {
|
|
||||||
TimiException.required(request, "not found delivery request");
|
|
||||||
GaoPackageDelivery delivery = mapper.selectForUpdate(request.getDeliveryId());
|
|
||||||
TimiException.required(delivery, "not found delivery");
|
|
||||||
String loginUserId = userLoginService.getRequireLoginUserId();
|
|
||||||
TimiException.requiredTrue(loginUserId.equals(delivery.getOperatorUserId()), "只能撤销自己提交的发放");
|
|
||||||
return releasePending(request, GaoPackageDelivery.Status.CANCELLED);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Transactional(TimiServerDBConfig.ROLLBACKER)
|
|
||||||
@Override
|
|
||||||
public GaoPackageDelivery revoke(GaoPackageDeliveryRevokeRequest request) {
|
|
||||||
return loggerService.execute(Logger.Module.GAO, "GAO_PACKAGE_DELIVERY_REVOKE", request, () -> revokeInternal(request));
|
|
||||||
}
|
|
||||||
|
|
||||||
private GaoPackageDelivery revokeInternal(GaoPackageDeliveryRevokeRequest request) {
|
|
||||||
TimiException.required(request, "not found revoke request");
|
|
||||||
TimiException.required(request.getRequestNo(), "not found requestNo");
|
|
||||||
request.setRequestNo(request.getRequestNo().trim());
|
|
||||||
TimiException.required(request.getDeliveryId(), "not found deliveryId");
|
|
||||||
TimiException.required(hasReason(request.getReason()), "冲正原因不能为空");
|
|
||||||
GaoPackageDelivery source = mapper.selectForUpdate(request.getDeliveryId());
|
|
||||||
TimiException.required(source, "not found delivery");
|
|
||||||
storeScopeService.checkStoreId(source.getStoreId());
|
|
||||||
GaoPackageDelivery existing = mapper.selectByRequestNo(source.getStoreId(), request.getRequestNo());
|
|
||||||
if (existing != null) {
|
|
||||||
TimiException.requiredTrue(existing.getOperationType() == GaoPackageDelivery.OperationType.REVOKE
|
|
||||||
&& source.getId().equals(existing.getSourceDeliveryId()), "requestNo 已被其他发放操作使用");
|
|
||||||
return get(existing.getId());
|
|
||||||
}
|
|
||||||
TimiException.requiredTrue(hasAttachment(request.getAttachmentList()), "发放冲正必须上传照片");
|
|
||||||
TimiException.requiredTrue(source.getOperationType() == GaoPackageDelivery.OperationType.DELIVER && source.getStatus() == GaoPackageDelivery.Status.VERIFIED, "只有已核销发放可以冲正");
|
|
||||||
TimiException.requiredNull(mapper.selectRevokeBySourceDeliveryId(source.getId()), "该发放单已经冲正");
|
|
||||||
GaoCustomerPackage packageEntity = customerPackageService.getForUpdate(source.getCustomerPackageId());
|
|
||||||
TimiException.required(packageEntity, "not found customer package");
|
|
||||||
List<GaoPackageDeliveryItem> sourceItemList = itemMapper.selectByDeliveryId(source.getId());
|
|
||||||
GaoPackageDelivery revoke = new GaoPackageDelivery();
|
|
||||||
revoke.setCustomerPackageId(source.getCustomerPackageId());
|
|
||||||
revoke.setStoreId(source.getStoreId());
|
|
||||||
revoke.setCustomerId(source.getCustomerId());
|
|
||||||
revoke.setOperationType(GaoPackageDelivery.OperationType.REVOKE);
|
|
||||||
revoke.setStatus(GaoPackageDelivery.Status.VERIFIED);
|
|
||||||
revoke.setRequestNo(request.getRequestNo());
|
|
||||||
revoke.setOperatorUserId(userLoginService.getRequireLoginUserId());
|
|
||||||
revoke.setDeliveredAt(TimiJava.defaultIfNull(request.getDeliveredAt(), Time.now()));
|
|
||||||
revoke.setVerifierUserId(userLoginService.getRequireLoginUserId());
|
|
||||||
revoke.setVerifiedAt(Time.now());
|
|
||||||
revoke.setSourceDeliveryId(source.getId());
|
|
||||||
revoke.setReason(request.getReason().trim());
|
|
||||||
revoke.setRemark(request.getRemark());
|
|
||||||
super.create(revoke);
|
|
||||||
for (GaoPackageDeliveryItem sourceItem : sourceItemList) {
|
|
||||||
GaoCustomerPackageItem packageItem = customerPackageService.getItemForUpdate(sourceItem.getCustomerPackageItemId());
|
|
||||||
TimiException.required(packageItem, "not found customer package item");
|
|
||||||
BigDecimal deliveredBefore = decimal(packageItem.getDeliveredQuantity());
|
|
||||||
TimiException.requiredTrue(0 < deliveredBefore.compareTo(sourceItem.getQuantity()) || deliveredBefore.compareTo(sourceItem.getQuantity()) == 0, "已发数量不足以冲正");
|
|
||||||
TimiException.requiredTrue(0 < customerPackageService.updateItemDeliveredQuantity(packageItem.getId(), sourceItem.getQuantity().negate()), "发放数量冲正失败");
|
|
||||||
GaoPackageDeliveryItem revokeItem = copyDeliveryItem(sourceItem);
|
|
||||||
revokeItem.setDeliveryId(revoke.getId());
|
|
||||||
revokeItem.setReservedBefore(packageItem.getReservedQuantity());
|
|
||||||
revokeItem.setReservedAfter(packageItem.getReservedQuantity());
|
|
||||||
revokeItem.setDeliveredBefore(deliveredBefore);
|
|
||||||
revokeItem.setDeliveredAfter(deliveredBefore.subtract(sourceItem.getQuantity()));
|
|
||||||
itemMapper.insert(revokeItem);
|
|
||||||
}
|
|
||||||
TimiException.requiredTrue(0 < mapper.updateStatusIf(source.getId(), GaoPackageDelivery.Status.VERIFIED, GaoPackageDelivery.Status.REVOKED, source.getVerifierUserId(), source.getVerifiedAt(), source.getReason()), "发放单状态已变化");
|
|
||||||
if (packageEntity.getStatus() == GaoCustomerPackage.Status.FULFILLED) {
|
|
||||||
packageEntity.setStatus(GaoCustomerPackage.Status.ACTIVE);
|
|
||||||
customerPackageService.updateAggregateState(packageEntity);
|
|
||||||
}
|
|
||||||
attachmentService.updateByBizId(Attachment.BizType.GAO_PACKAGE_DELIVERY, revoke.getId(), request.getAttachmentList());
|
|
||||||
return revoke;
|
|
||||||
}
|
|
||||||
|
|
||||||
private GaoPackageDelivery releasePending(GaoPackageDeliveryActionRequest request, GaoPackageDelivery.Status targetStatus) {
|
|
||||||
TimiException.required(request, "not found delivery request");
|
|
||||||
TimiException.required(request.getDeliveryId(), "not found deliveryId");
|
|
||||||
TimiException.required(hasReason(request.getReason()), "拒绝或撤销原因不能为空");
|
|
||||||
GaoPackageDelivery delivery = mapper.selectForUpdate(request.getDeliveryId());
|
|
||||||
TimiException.required(delivery, "not found delivery");
|
|
||||||
storeScopeService.checkStoreId(delivery.getStoreId());
|
|
||||||
TimiException.requiredTrue(delivery.getStatus() == GaoPackageDelivery.Status.PENDING && delivery.getOperationType() == GaoPackageDelivery.OperationType.DELIVER, "发放单不是待核销状态");
|
|
||||||
for (GaoPackageDeliveryItem item : itemMapper.selectByDeliveryId(delivery.getId())) {
|
|
||||||
TimiException.requiredTrue(0 < customerPackageService.updateItemReservedQuantity(item.getCustomerPackageItemId(), item.getQuantity().negate()), "发放占用数量异常");
|
|
||||||
}
|
|
||||||
String loginUserId = userLoginService.getRequireLoginUserId();
|
|
||||||
TimiException.requiredTrue(0 < mapper.updateStatusIf(delivery.getId(), GaoPackageDelivery.Status.PENDING, targetStatus, loginUserId, Time.now(), request.getReason().trim()), "发放单状态已变化");
|
|
||||||
delivery.setStatus(targetStatus);
|
|
||||||
delivery.setVerifierUserId(loginUserId);
|
|
||||||
delivery.setVerifiedAt(Time.now());
|
|
||||||
delivery.setReason(request.getReason().trim());
|
|
||||||
return delivery;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void refreshPackageStatus(GaoCustomerPackage packageEntity) {
|
|
||||||
List<GaoCustomerPackageItem> itemList = customerPackageService.listItemByCustomerPackageId(packageEntity.getId());
|
|
||||||
boolean fulfilled = !itemList.isEmpty();
|
|
||||||
for (GaoCustomerPackageItem item : itemList) {
|
|
||||||
if (decimal(item.getDeliveredQuantity()).compareTo(decimal(item.getTotalQuantity())) < 0) {
|
|
||||||
fulfilled = false;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (fulfilled && packageEntity.getStatus() == GaoCustomerPackage.Status.ACTIVE) {
|
|
||||||
packageEntity.setStatus(GaoCustomerPackage.Status.FULFILLED);
|
|
||||||
customerPackageService.updateAggregateState(packageEntity);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private List<GaoPackageDeliveryItem> validateRequestItems(List<GaoPackageDeliveryItem> sourceList) {
|
|
||||||
TimiException.requiredTrue(sourceList != null && !sourceList.isEmpty(), "发放至少需要一个产品");
|
|
||||||
Set<String> idSet = new HashSet<>();
|
|
||||||
List<GaoPackageDeliveryItem> result = new ArrayList<>();
|
|
||||||
for (GaoPackageDeliveryItem source : sourceList) {
|
|
||||||
TimiException.required(source, "发放产品明细不能为空");
|
|
||||||
TimiException.required(source.getCustomerPackageItemId(), "not found customerPackageItemId");
|
|
||||||
TimiException.required(source.getQuantity(), "发放数量不能为空");
|
|
||||||
TimiException.requiredTrue(0 < source.getQuantity().signum(), "发放数量必须大于 0");
|
|
||||||
TimiException.requiredTrue(3 >= source.getQuantity().scale(), "发放数量最多保留三位小数");
|
|
||||||
TimiException.requiredTrue(idSet.add(source.getCustomerPackageItemId()), "同一发放单产品不能重复");
|
|
||||||
result.add(source);
|
|
||||||
}
|
|
||||||
result.sort(Comparator.comparing(GaoPackageDeliveryItem::getCustomerPackageItemId));
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
private GaoPackageDeliveryItem copyDeliveryItem(GaoPackageDeliveryItem source) {
|
|
||||||
GaoPackageDeliveryItem result = new GaoPackageDeliveryItem();
|
|
||||||
result.setCustomerPackageItemId(source.getCustomerPackageItemId());
|
|
||||||
result.setQuantity(source.getQuantity());
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void verifyCreateIdempotency(GaoPackageDelivery existing, GaoPackageDeliveryCreateRequest request) {
|
|
||||||
TimiException.requiredTrue(existing.getCustomerPackageId().equals(request.getCustomerPackageId())
|
|
||||||
&& (request.getDeliveredAt() == null || request.getDeliveredAt().equals(existing.getDeliveredAt()))
|
|
||||||
&& sameText(existing.getRemark(), request.getRemark()), "requestNo 对应请求内容不一致");
|
|
||||||
List<GaoPackageDeliveryItem> existingItems = itemMapper.selectByDeliveryId(existing.getId());
|
|
||||||
List<GaoPackageDeliveryItem> requestItems = validateRequestItems(request.getItemList());
|
|
||||||
TimiException.requiredTrue(existingItems.size() == requestItems.size(), "requestNo 对应请求内容不一致");
|
|
||||||
Map<String, BigDecimal> requestMap = requestItems.stream().collect(java.util.stream.Collectors.toMap(GaoPackageDeliveryItem::getCustomerPackageItemId, GaoPackageDeliveryItem::getQuantity));
|
|
||||||
for (GaoPackageDeliveryItem item : existingItems) {
|
|
||||||
TimiException.requiredTrue(item.getQuantity().compareTo(requestMap.getOrDefault(item.getCustomerPackageItemId(), ZERO)) == 0, "requestNo 对应请求内容不一致");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean hasAttachment(List<Attachment> attachmentList) {
|
|
||||||
for (Attachment attachment : TimiJava.safeIterable(attachmentList)) {
|
|
||||||
if (attachment != null && (attachment.getAttachType() == null || "PHOTO".equalsIgnoreCase(attachment.getAttachType()))) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean hasReason(String reason) {
|
|
||||||
return reason != null && !reason.trim().isEmpty();
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean sameText(String left, String right) {
|
|
||||||
return left == null ? right == null : left.equals(right);
|
|
||||||
}
|
|
||||||
|
|
||||||
private BigDecimal decimal(BigDecimal value) {
|
|
||||||
return value == null ? ZERO : value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
-119
@@ -1,119 +0,0 @@
|
|||||||
package com.imyeyu.api.modules.gao.service.implement;
|
|
||||||
|
|
||||||
import com.imyeyu.api.config.dbsource.TimiServerDBConfig;
|
|
||||||
import com.imyeyu.api.modules.common.entity.Article;
|
|
||||||
import com.imyeyu.api.modules.common.entity.Attachment;
|
|
||||||
import com.imyeyu.api.modules.common.mapper.ArticleMapper;
|
|
||||||
import com.imyeyu.api.modules.common.service.ArticleService;
|
|
||||||
import com.imyeyu.api.modules.common.service.AttachmentService;
|
|
||||||
import com.imyeyu.api.modules.gao.service.GaoStoreDiaryService;
|
|
||||||
import com.imyeyu.api.modules.gao.mapper.GaoStoreDiaryMapper;
|
|
||||||
import com.imyeyu.api.modules.gao.vo.GaoStoreDiaryPage;
|
|
||||||
import com.imyeyu.java.TimiJava;
|
|
||||||
import com.imyeyu.java.bean.timi.TimiException;
|
|
||||||
import com.imyeyu.spring.bean.Page;
|
|
||||||
import com.imyeyu.spring.bean.PageResult;
|
|
||||||
import lombok.RequiredArgsConstructor;
|
|
||||||
import org.springframework.stereotype.Service;
|
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
|
||||||
|
|
||||||
/// GAO 门店日记服务实现
|
|
||||||
///
|
|
||||||
/// @author Codex
|
|
||||||
/// @since 2026-08-31
|
|
||||||
@Service
|
|
||||||
@RequiredArgsConstructor
|
|
||||||
public class GaoStoreDiaryServiceImplement implements GaoStoreDiaryService {
|
|
||||||
|
|
||||||
private final ArticleService articleService;
|
|
||||||
private final AttachmentService attachmentService;
|
|
||||||
private final ArticleMapper articleMapper;
|
|
||||||
private final GaoStoreDiaryMapper diaryMapper;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public PageResult<Article> page(GaoStoreDiaryPage page) {
|
|
||||||
PageResult<Article> result = new PageResult<>();
|
|
||||||
result.setTotal(diaryMapper.countByMonth(page));
|
|
||||||
result.setList(diaryMapper.selectByMonth(page));
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Article get(String id) {
|
|
||||||
Article article = articleService.get(id);
|
|
||||||
checkStoreDiary(article);
|
|
||||||
return article;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
@Transactional(TimiServerDBConfig.ROLLBACKER)
|
|
||||||
public void create(Article article, String userId) {
|
|
||||||
prepare(article, userId);
|
|
||||||
articleService.create(article);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
@Transactional(TimiServerDBConfig.ROLLBACKER)
|
|
||||||
public void update(Article article, String userId) {
|
|
||||||
TimiException.required(article, "未找到门店日记");
|
|
||||||
TimiException.required(article.getId(), "未找到门店日记 ID");
|
|
||||||
Article dbArticle = get(article.getId());
|
|
||||||
article.setBizType(dbArticle.getBizType());
|
|
||||||
article.setBizId(dbArticle.getBizId());
|
|
||||||
article.setCreatedAt(null);
|
|
||||||
article.setUpdatedAt(null);
|
|
||||||
article.setDeletedAt(null);
|
|
||||||
article.setReads(dbArticle.getReads());
|
|
||||||
article.setLikes(dbArticle.getLikes());
|
|
||||||
article.setUpdatedBy(userId);
|
|
||||||
articleService.update(article);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
@Transactional(TimiServerDBConfig.ROLLBACKER)
|
|
||||||
public void delete(String id) {
|
|
||||||
Article article = get(id);
|
|
||||||
attachmentService.deleteByBizId(Attachment.BizType.ARTICLE, article.getId());
|
|
||||||
articleService.delete(article.getId());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
@Transactional(TimiServerDBConfig.ROLLBACKER)
|
|
||||||
public void deleteByStoreId(String storeId) {
|
|
||||||
TimiException.required(storeId, "未找到门店 ID");
|
|
||||||
Article example = new Article();
|
|
||||||
example.setBizType(Article.BizType.GAO_STORE_DIARY);
|
|
||||||
example.setBizId(storeId);
|
|
||||||
for (Article article : articleMapper.selectAllByExample(example)) {
|
|
||||||
attachmentService.deleteByBizId(Attachment.BizType.ARTICLE, article.getId());
|
|
||||||
articleService.delete(article.getId());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// 固定门店日记业务类型并写入更新用户
|
|
||||||
///
|
|
||||||
/// @param article 门店日记
|
|
||||||
/// @param userId 操作用户 ID
|
|
||||||
private void prepare(Article article, String userId) {
|
|
||||||
TimiException.required(article, "未找到门店日记");
|
|
||||||
TimiException.required(article.getBizId(), "未找到门店 ID");
|
|
||||||
TimiException.required(userId, "未找到更新用户 ID");
|
|
||||||
article.setBizType(Article.BizType.GAO_STORE_DIARY);
|
|
||||||
article.setCreatedAt(null);
|
|
||||||
article.setUpdatedAt(null);
|
|
||||||
article.setDeletedAt(null);
|
|
||||||
article.setUpdatedBy(userId);
|
|
||||||
article.setReads(0);
|
|
||||||
article.setLikes(0);
|
|
||||||
article.setStatus(TimiJava.defaultIfNull(article.getStatus(), Article.Status.NORMAL));
|
|
||||||
}
|
|
||||||
|
|
||||||
/// 校验文章确实是门店日记
|
|
||||||
///
|
|
||||||
/// @param article 文章
|
|
||||||
private void checkStoreDiary(Article article) {
|
|
||||||
TimiException.required(article, "未找到门店日记");
|
|
||||||
TimiException.requiredTrue(article.getBizType() == Article.BizType.GAO_STORE_DIARY, "门店日记类型无效");
|
|
||||||
TimiException.required(article.getBizId(), "未找到门店 ID");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
-10
@@ -11,7 +11,6 @@ import com.imyeyu.api.modules.gao.service.GaoEventService;
|
|||||||
import com.imyeyu.api.modules.gao.service.GaoPointAccountService;
|
import com.imyeyu.api.modules.gao.service.GaoPointAccountService;
|
||||||
import com.imyeyu.api.modules.gao.service.GaoPointRuleService;
|
import com.imyeyu.api.modules.gao.service.GaoPointRuleService;
|
||||||
import com.imyeyu.api.modules.gao.service.GaoStoreBusinessDayService;
|
import com.imyeyu.api.modules.gao.service.GaoStoreBusinessDayService;
|
||||||
import com.imyeyu.api.modules.gao.service.GaoStoreDiaryService;
|
|
||||||
import com.imyeyu.api.modules.gao.service.GaoStoreService;
|
import com.imyeyu.api.modules.gao.service.GaoStoreService;
|
||||||
import com.imyeyu.api.modules.gao.service.GaoUserService;
|
import com.imyeyu.api.modules.gao.service.GaoUserService;
|
||||||
import com.imyeyu.api.modules.gao.util.StoreXSSFBuilder;
|
import com.imyeyu.api.modules.gao.util.StoreXSSFBuilder;
|
||||||
@@ -56,7 +55,6 @@ public class GaoStoreServiceImplement extends AbstractEntityService<GaoStore, St
|
|||||||
private final GaoPointAccountService pointAccountService;
|
private final GaoPointAccountService pointAccountService;
|
||||||
private final GaoPointRuleService pointRuleService;
|
private final GaoPointRuleService pointRuleService;
|
||||||
private final GaoStoreBusinessDayService businessDayService;
|
private final GaoStoreBusinessDayService businessDayService;
|
||||||
private final GaoStoreDiaryService storeDiaryService;
|
|
||||||
private final ObjectProvider<GaoUserService> gaoUserServiceProvider;
|
private final ObjectProvider<GaoUserService> gaoUserServiceProvider;
|
||||||
private final TagService tagService;
|
private final TagService tagService;
|
||||||
|
|
||||||
@@ -142,7 +140,6 @@ public class GaoStoreServiceImplement extends AbstractEntityService<GaoStore, St
|
|||||||
deleteGaoUsers(store.getId());
|
deleteGaoUsers(store.getId());
|
||||||
deletePointAccounts(store.getId());
|
deletePointAccounts(store.getId());
|
||||||
deleteStoreTags(store.getId());
|
deleteStoreTags(store.getId());
|
||||||
deleteStoreDiaries(store.getId());
|
|
||||||
store.setStatus(GaoStore.Status.DELETED);
|
store.setStatus(GaoStore.Status.DELETED);
|
||||||
super.update(store);
|
super.update(store);
|
||||||
super.delete(id);
|
super.delete(id);
|
||||||
@@ -211,13 +208,6 @@ public class GaoStoreServiceImplement extends AbstractEntityService<GaoStore, St
|
|||||||
tagService.deleteByOwner(Tag.OwnerType.GAO_STORE, storeId);
|
tagService.deleteByOwner(Tag.OwnerType.GAO_STORE, storeId);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// 删除门店日记及其附件
|
|
||||||
///
|
|
||||||
/// @param storeId 门店 ID
|
|
||||||
private void deleteStoreDiaries(String storeId) {
|
|
||||||
storeDiaryService.deleteByStoreId(storeId);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public GaoStore getByUserId(String userId) {
|
public GaoStore getByUserId(String userId) {
|
||||||
TimiException.required(userId, "not found userId");
|
TimiException.required(userId, "not found userId");
|
||||||
|
|||||||
@@ -1,17 +0,0 @@
|
|||||||
package com.imyeyu.api.modules.gao.vo;
|
|
||||||
|
|
||||||
import lombok.Data;
|
|
||||||
|
|
||||||
/// GAO 取消客户套餐请求
|
|
||||||
///
|
|
||||||
/// @author Codex
|
|
||||||
/// @since 2026-08-31
|
|
||||||
@Data
|
|
||||||
public class GaoCustomerPackageCancelRequest {
|
|
||||||
|
|
||||||
/// 客户套餐 ID
|
|
||||||
private String customerPackageId;
|
|
||||||
|
|
||||||
/// 取消原因
|
|
||||||
private String reason;
|
|
||||||
}
|
|
||||||
@@ -1,39 +0,0 @@
|
|||||||
package com.imyeyu.api.modules.gao.vo;
|
|
||||||
|
|
||||||
import com.imyeyu.api.modules.gao.entity.GaoCustomerPackage;
|
|
||||||
import com.imyeyu.java.bean.BasePage;
|
|
||||||
import lombok.Data;
|
|
||||||
import lombok.EqualsAndHashCode;
|
|
||||||
|
|
||||||
/// GAO 客户套餐分页查询请求
|
|
||||||
///
|
|
||||||
/// @author Codex
|
|
||||||
/// @since 2026-08-31
|
|
||||||
@Data
|
|
||||||
@EqualsAndHashCode(callSuper = true)
|
|
||||||
public class GaoCustomerPackagePage extends BasePage {
|
|
||||||
|
|
||||||
/// 门店 ID
|
|
||||||
private String storeId;
|
|
||||||
|
|
||||||
/// 客户 ID
|
|
||||||
private String customerId;
|
|
||||||
|
|
||||||
/// 客户或套餐关键词
|
|
||||||
private String keyword;
|
|
||||||
|
|
||||||
/// 套餐状态
|
|
||||||
private GaoCustomerPackage.Status status;
|
|
||||||
|
|
||||||
/// 付款状态
|
|
||||||
private GaoCustomerPackage.PaymentStatus paymentStatus;
|
|
||||||
|
|
||||||
/// 退款状态
|
|
||||||
private GaoCustomerPackage.RefundStatus refundStatus;
|
|
||||||
|
|
||||||
/// 购买开始时间
|
|
||||||
private Long beginAt;
|
|
||||||
|
|
||||||
/// 购买结束时间
|
|
||||||
private Long endAt;
|
|
||||||
}
|
|
||||||
@@ -1,28 +0,0 @@
|
|||||||
package com.imyeyu.api.modules.gao.vo;
|
|
||||||
|
|
||||||
import lombok.Data;
|
|
||||||
|
|
||||||
import java.math.BigDecimal;
|
|
||||||
|
|
||||||
/// GAO 客户套餐购买产品明细
|
|
||||||
///
|
|
||||||
/// @author Codex
|
|
||||||
/// @since 2026-08-31
|
|
||||||
@Data
|
|
||||||
public class GaoCustomerPackagePurchaseItem {
|
|
||||||
|
|
||||||
/// 产品名称
|
|
||||||
private String productName;
|
|
||||||
|
|
||||||
/// 产品单位
|
|
||||||
private String unit;
|
|
||||||
|
|
||||||
/// 总权益数量
|
|
||||||
private BigDecimal totalQuantity;
|
|
||||||
|
|
||||||
/// 排序值
|
|
||||||
private Integer sort;
|
|
||||||
|
|
||||||
/// 备注
|
|
||||||
private String remark;
|
|
||||||
}
|
|
||||||
@@ -1,38 +0,0 @@
|
|||||||
package com.imyeyu.api.modules.gao.vo;
|
|
||||||
|
|
||||||
import com.imyeyu.api.modules.common.entity.Attachment;
|
|
||||||
import lombok.Data;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
/// GAO 客户购买套餐请求
|
|
||||||
///
|
|
||||||
/// @author Codex
|
|
||||||
/// @since 2026-08-31
|
|
||||||
@Data
|
|
||||||
public class GaoCustomerPackagePurchaseRequest {
|
|
||||||
|
|
||||||
/// 客户端幂等请求号
|
|
||||||
private String requestNo;
|
|
||||||
|
|
||||||
/// 购买事件 ID
|
|
||||||
private String eventId;
|
|
||||||
|
|
||||||
/// 客户 ID
|
|
||||||
private String customerId;
|
|
||||||
|
|
||||||
/// 实际成交价,单位分,空为事件绑定套餐的标准价
|
|
||||||
private Long saleAmount;
|
|
||||||
|
|
||||||
/// 购买时间
|
|
||||||
private Long purchasedAt;
|
|
||||||
|
|
||||||
/// 最终产品明细,空为事件绑定套餐的默认产品明细
|
|
||||||
private List<GaoCustomerPackagePurchaseItem> itemList;
|
|
||||||
|
|
||||||
/// 购买照片
|
|
||||||
private List<Attachment> attachmentList;
|
|
||||||
|
|
||||||
/// 备注
|
|
||||||
private String remark;
|
|
||||||
}
|
|
||||||
@@ -1,17 +0,0 @@
|
|||||||
package com.imyeyu.api.modules.gao.vo;
|
|
||||||
|
|
||||||
import lombok.Data;
|
|
||||||
|
|
||||||
/// GAO 资金收款状态操作请求
|
|
||||||
///
|
|
||||||
/// @author Codex
|
|
||||||
/// @since 2026-08-31
|
|
||||||
@Data
|
|
||||||
public class GaoFundActionRequest {
|
|
||||||
|
|
||||||
/// 资金记录 ID
|
|
||||||
private String fundRecordId;
|
|
||||||
|
|
||||||
/// 拒绝或撤销原因
|
|
||||||
private String reason;
|
|
||||||
}
|
|
||||||
@@ -1,26 +0,0 @@
|
|||||||
package com.imyeyu.api.modules.gao.vo;
|
|
||||||
|
|
||||||
import lombok.Data;
|
|
||||||
|
|
||||||
/// GAO 确认无需退款请求
|
|
||||||
///
|
|
||||||
/// @author Codex
|
|
||||||
/// @since 2026-08-31
|
|
||||||
@Data
|
|
||||||
public class GaoFundConfirmNoRefundRequest {
|
|
||||||
|
|
||||||
/// 客户端幂等请求号
|
|
||||||
private String requestNo;
|
|
||||||
|
|
||||||
/// 客户套餐 ID
|
|
||||||
private String customerPackageId;
|
|
||||||
|
|
||||||
/// 确认时间
|
|
||||||
private Long occurredAt;
|
|
||||||
|
|
||||||
/// 确认原因
|
|
||||||
private String reason;
|
|
||||||
|
|
||||||
/// 备注
|
|
||||||
private String remark;
|
|
||||||
}
|
|
||||||
@@ -1,32 +0,0 @@
|
|||||||
package com.imyeyu.api.modules.gao.vo;
|
|
||||||
|
|
||||||
import com.imyeyu.api.modules.common.entity.Attachment;
|
|
||||||
import lombok.Data;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
/// GAO 线下收款登记请求
|
|
||||||
///
|
|
||||||
/// @author Codex
|
|
||||||
/// @since 2026-08-31
|
|
||||||
@Data
|
|
||||||
public class GaoFundReceiveRequest {
|
|
||||||
|
|
||||||
/// 客户端幂等请求号
|
|
||||||
private String requestNo;
|
|
||||||
|
|
||||||
/// 客户套餐 ID
|
|
||||||
private String customerPackageId;
|
|
||||||
|
|
||||||
/// 收款金额,单位分
|
|
||||||
private Long amount;
|
|
||||||
|
|
||||||
/// 收款发生时间
|
|
||||||
private Long occurredAt;
|
|
||||||
|
|
||||||
/// 收款照片
|
|
||||||
private List<Attachment> attachmentList;
|
|
||||||
|
|
||||||
/// 备注
|
|
||||||
private String remark;
|
|
||||||
}
|
|
||||||
@@ -1,36 +0,0 @@
|
|||||||
package com.imyeyu.api.modules.gao.vo;
|
|
||||||
|
|
||||||
import com.imyeyu.api.modules.gao.entity.GaoFundRecord;
|
|
||||||
import com.imyeyu.java.bean.BasePage;
|
|
||||||
import lombok.Data;
|
|
||||||
import lombok.EqualsAndHashCode;
|
|
||||||
|
|
||||||
/// GAO 资金流水分页查询请求
|
|
||||||
///
|
|
||||||
/// @author Codex
|
|
||||||
/// @since 2026-08-31
|
|
||||||
@Data
|
|
||||||
@EqualsAndHashCode(callSuper = true)
|
|
||||||
public class GaoFundRecordPage extends BasePage {
|
|
||||||
|
|
||||||
/// 门店 ID
|
|
||||||
private String storeId;
|
|
||||||
|
|
||||||
/// 客户套餐 ID
|
|
||||||
private String customerPackageId;
|
|
||||||
|
|
||||||
/// 客户 ID
|
|
||||||
private String customerId;
|
|
||||||
|
|
||||||
/// 操作类型
|
|
||||||
private GaoFundRecord.OperationType operationType;
|
|
||||||
|
|
||||||
/// 操作状态
|
|
||||||
private GaoFundRecord.Status status;
|
|
||||||
|
|
||||||
/// 操作开始时间
|
|
||||||
private Long beginAt;
|
|
||||||
|
|
||||||
/// 操作结束时间
|
|
||||||
private Long endAt;
|
|
||||||
}
|
|
||||||
@@ -1,35 +0,0 @@
|
|||||||
package com.imyeyu.api.modules.gao.vo;
|
|
||||||
|
|
||||||
import com.imyeyu.api.modules.common.entity.Attachment;
|
|
||||||
import lombok.Data;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
/// GAO 退款登记请求
|
|
||||||
///
|
|
||||||
/// @author Codex
|
|
||||||
/// @since 2026-08-31
|
|
||||||
@Data
|
|
||||||
public class GaoFundRefundRequest {
|
|
||||||
|
|
||||||
/// 客户端幂等请求号
|
|
||||||
private String requestNo;
|
|
||||||
|
|
||||||
/// 客户套餐 ID
|
|
||||||
private String customerPackageId;
|
|
||||||
|
|
||||||
/// 退款金额,单位分
|
|
||||||
private Long amount;
|
|
||||||
|
|
||||||
/// 退款发生时间
|
|
||||||
private Long occurredAt;
|
|
||||||
|
|
||||||
/// 退款原因
|
|
||||||
private String reason;
|
|
||||||
|
|
||||||
/// 退款照片
|
|
||||||
private List<Attachment> attachmentList;
|
|
||||||
|
|
||||||
/// 备注
|
|
||||||
private String remark;
|
|
||||||
}
|
|
||||||
@@ -1,32 +0,0 @@
|
|||||||
package com.imyeyu.api.modules.gao.vo;
|
|
||||||
|
|
||||||
import com.imyeyu.api.modules.common.entity.Attachment;
|
|
||||||
import lombok.Data;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
/// GAO 资金流水冲正请求
|
|
||||||
///
|
|
||||||
/// @author Codex
|
|
||||||
/// @since 2026-08-31
|
|
||||||
@Data
|
|
||||||
public class GaoFundRevokeRequest {
|
|
||||||
|
|
||||||
/// 客户端幂等请求号
|
|
||||||
private String requestNo;
|
|
||||||
|
|
||||||
/// 原资金记录 ID
|
|
||||||
private String fundRecordId;
|
|
||||||
|
|
||||||
/// 冲正发生时间
|
|
||||||
private Long occurredAt;
|
|
||||||
|
|
||||||
/// 冲正原因
|
|
||||||
private String reason;
|
|
||||||
|
|
||||||
/// 冲正照片
|
|
||||||
private List<Attachment> attachmentList;
|
|
||||||
|
|
||||||
/// 备注
|
|
||||||
private String remark;
|
|
||||||
}
|
|
||||||
@@ -1,24 +0,0 @@
|
|||||||
package com.imyeyu.api.modules.gao.vo;
|
|
||||||
|
|
||||||
import com.imyeyu.api.modules.gao.entity.GaoPackageConfig;
|
|
||||||
import com.imyeyu.java.bean.BasePage;
|
|
||||||
import lombok.Data;
|
|
||||||
import lombok.EqualsAndHashCode;
|
|
||||||
|
|
||||||
/// GAO 套餐配置分页查询请求
|
|
||||||
///
|
|
||||||
/// @author Codex
|
|
||||||
/// @since 2026-08-31
|
|
||||||
@Data
|
|
||||||
@EqualsAndHashCode(callSuper = true)
|
|
||||||
public class GaoPackageConfigPage extends BasePage {
|
|
||||||
|
|
||||||
/// 门店 ID
|
|
||||||
private String storeId;
|
|
||||||
|
|
||||||
/// 套餐名称关键词
|
|
||||||
private String keyword;
|
|
||||||
|
|
||||||
/// 套餐状态
|
|
||||||
private GaoPackageConfig.Status status;
|
|
||||||
}
|
|
||||||
@@ -1,17 +0,0 @@
|
|||||||
package com.imyeyu.api.modules.gao.vo;
|
|
||||||
|
|
||||||
import lombok.Data;
|
|
||||||
|
|
||||||
/// GAO 套餐发放状态操作请求
|
|
||||||
///
|
|
||||||
/// @author Codex
|
|
||||||
/// @since 2026-08-31
|
|
||||||
@Data
|
|
||||||
public class GaoPackageDeliveryActionRequest {
|
|
||||||
|
|
||||||
/// 发放单 ID
|
|
||||||
private String deliveryId;
|
|
||||||
|
|
||||||
/// 拒绝或撤销原因
|
|
||||||
private String reason;
|
|
||||||
}
|
|
||||||
@@ -1,33 +0,0 @@
|
|||||||
package com.imyeyu.api.modules.gao.vo;
|
|
||||||
|
|
||||||
import com.imyeyu.api.modules.common.entity.Attachment;
|
|
||||||
import com.imyeyu.api.modules.gao.entity.GaoPackageDeliveryItem;
|
|
||||||
import lombok.Data;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
/// GAO 套餐发放请求
|
|
||||||
///
|
|
||||||
/// @author Codex
|
|
||||||
/// @since 2026-08-31
|
|
||||||
@Data
|
|
||||||
public class GaoPackageDeliveryCreateRequest {
|
|
||||||
|
|
||||||
/// 客户端幂等请求号
|
|
||||||
private String requestNo;
|
|
||||||
|
|
||||||
/// 客户套餐 ID
|
|
||||||
private String customerPackageId;
|
|
||||||
|
|
||||||
/// 实际发放时间
|
|
||||||
private Long deliveredAt;
|
|
||||||
|
|
||||||
/// 发放产品明细
|
|
||||||
private List<GaoPackageDeliveryItem> itemList;
|
|
||||||
|
|
||||||
/// 发放照片
|
|
||||||
private List<Attachment> attachmentList;
|
|
||||||
|
|
||||||
/// 备注
|
|
||||||
private String remark;
|
|
||||||
}
|
|
||||||
@@ -1,36 +0,0 @@
|
|||||||
package com.imyeyu.api.modules.gao.vo;
|
|
||||||
|
|
||||||
import com.imyeyu.api.modules.gao.entity.GaoPackageDelivery;
|
|
||||||
import com.imyeyu.java.bean.BasePage;
|
|
||||||
import lombok.Data;
|
|
||||||
import lombok.EqualsAndHashCode;
|
|
||||||
|
|
||||||
/// GAO 套餐发放分页查询请求
|
|
||||||
///
|
|
||||||
/// @author Codex
|
|
||||||
/// @since 2026-08-31
|
|
||||||
@Data
|
|
||||||
@EqualsAndHashCode(callSuper = true)
|
|
||||||
public class GaoPackageDeliveryPage extends BasePage {
|
|
||||||
|
|
||||||
/// 门店 ID
|
|
||||||
private String storeId;
|
|
||||||
|
|
||||||
/// 客户套餐 ID
|
|
||||||
private String customerPackageId;
|
|
||||||
|
|
||||||
/// 客户 ID
|
|
||||||
private String customerId;
|
|
||||||
|
|
||||||
/// 发放状态
|
|
||||||
private GaoPackageDelivery.Status status;
|
|
||||||
|
|
||||||
/// 操作类型
|
|
||||||
private GaoPackageDelivery.OperationType operationType;
|
|
||||||
|
|
||||||
/// 发放开始时间
|
|
||||||
private Long beginAt;
|
|
||||||
|
|
||||||
/// 发放结束时间
|
|
||||||
private Long endAt;
|
|
||||||
}
|
|
||||||
@@ -1,32 +0,0 @@
|
|||||||
package com.imyeyu.api.modules.gao.vo;
|
|
||||||
|
|
||||||
import com.imyeyu.api.modules.common.entity.Attachment;
|
|
||||||
import lombok.Data;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
/// GAO 已核销发放整单冲正请求
|
|
||||||
///
|
|
||||||
/// @author Codex
|
|
||||||
/// @since 2026-08-31
|
|
||||||
@Data
|
|
||||||
public class GaoPackageDeliveryRevokeRequest {
|
|
||||||
|
|
||||||
/// 客户端幂等请求号
|
|
||||||
private String requestNo;
|
|
||||||
|
|
||||||
/// 原发放单 ID
|
|
||||||
private String deliveryId;
|
|
||||||
|
|
||||||
/// 冲正发生时间
|
|
||||||
private Long deliveredAt;
|
|
||||||
|
|
||||||
/// 冲正原因
|
|
||||||
private String reason;
|
|
||||||
|
|
||||||
/// 冲正照片
|
|
||||||
private List<Attachment> attachmentList;
|
|
||||||
|
|
||||||
/// 备注
|
|
||||||
private String remark;
|
|
||||||
}
|
|
||||||
@@ -1,23 +0,0 @@
|
|||||||
package com.imyeyu.api.modules.gao.vo;
|
|
||||||
|
|
||||||
import com.imyeyu.java.bean.BasePage;
|
|
||||||
import lombok.Data;
|
|
||||||
import lombok.EqualsAndHashCode;
|
|
||||||
|
|
||||||
/// GAO 门店日记月份分页查询请求
|
|
||||||
///
|
|
||||||
/// @author Codex
|
|
||||||
/// @since 2026-08-31
|
|
||||||
@Data
|
|
||||||
@EqualsAndHashCode(callSuper = true)
|
|
||||||
public class GaoStoreDiaryPage extends BasePage {
|
|
||||||
|
|
||||||
/// 门店 ID
|
|
||||||
private String storeId;
|
|
||||||
|
|
||||||
/// 创建时间起点,包含
|
|
||||||
private Long beginCreatedAt;
|
|
||||||
|
|
||||||
/// 创建时间终点,不包含
|
|
||||||
private Long endCreatedAt;
|
|
||||||
}
|
|
||||||
@@ -6,8 +6,6 @@ import com.imyeyu.spring.service.DestroyableService;
|
|||||||
import com.imyeyu.spring.service.GettableService;
|
import com.imyeyu.spring.service.GettableService;
|
||||||
import com.imyeyu.spring.service.PageableService;
|
import com.imyeyu.spring.service.PageableService;
|
||||||
|
|
||||||
import java.util.function.Supplier;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 日志服务
|
* 日志服务
|
||||||
*
|
*
|
||||||
@@ -18,51 +16,6 @@ public interface LoggerService extends GettableService<Logger, String>, Pageable
|
|||||||
|
|
||||||
void createSync(Logger logger);
|
void createSync(Logger logger);
|
||||||
|
|
||||||
/// 执行并记录有返回值的业务操作
|
|
||||||
///
|
|
||||||
/// @param logger 日志对象,调用方负责设置模块、操作和请求内容
|
|
||||||
/// @param action 业务操作
|
|
||||||
/// @param <T> 返回值类型
|
|
||||||
/// @return 业务操作返回值
|
|
||||||
<T> T execute(Logger logger, Supplier<T> action);
|
|
||||||
|
|
||||||
/// 执行并记录无返回值的业务操作
|
|
||||||
///
|
|
||||||
/// @param logger 日志对象,调用方负责设置模块、操作和请求内容
|
|
||||||
/// @param action 业务操作
|
|
||||||
default void execute(Logger logger, Runnable action) {
|
|
||||||
execute(logger, () -> {
|
|
||||||
action.run();
|
|
||||||
return null;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/// 创建日志并执行有返回值的业务操作
|
|
||||||
///
|
|
||||||
/// @param module 日志模块
|
|
||||||
/// @param operation 操作描述
|
|
||||||
/// @param content 请求内容
|
|
||||||
/// @param action 业务操作
|
|
||||||
/// @param <T> 返回值类型
|
|
||||||
/// @return 业务操作返回值
|
|
||||||
default <T> T execute(Logger.Module module, String operation, Object content, Supplier<T> action) {
|
|
||||||
Logger logger = new Logger(module, operation);
|
|
||||||
logger.setContent(content == null ? null : content.toString());
|
|
||||||
return execute(logger, action);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// 创建日志并执行无返回值的业务操作
|
|
||||||
///
|
|
||||||
/// @param module 日志模块
|
|
||||||
/// @param operation 操作描述
|
|
||||||
/// @param content 请求内容
|
|
||||||
/// @param action 业务操作
|
|
||||||
default void execute(Logger.Module module, String operation, Object content, Runnable action) {
|
|
||||||
Logger logger = new Logger(module, operation);
|
|
||||||
logger.setContent(content == null ? null : content.toString());
|
|
||||||
execute(logger, action);
|
|
||||||
}
|
|
||||||
|
|
||||||
void create(Logger.Module module, Logger.Level level, String operation, String content, String result);
|
void create(Logger.Module module, Logger.Level level, String operation, String content, String result);
|
||||||
|
|
||||||
default void info(Logger.Module module, String operation) {
|
default void info(Logger.Module module, String operation) {
|
||||||
|
|||||||
-30
@@ -6,17 +6,13 @@ import com.imyeyu.api.modules.system.service.LoggerService;
|
|||||||
import com.imyeyu.api.modules.user.entity.User;
|
import com.imyeyu.api.modules.user.entity.User;
|
||||||
import com.imyeyu.api.modules.user.service.UserLoginService;
|
import com.imyeyu.api.modules.user.service.UserLoginService;
|
||||||
import com.imyeyu.java.TimiJava;
|
import com.imyeyu.java.TimiJava;
|
||||||
import com.imyeyu.java.bean.timi.TimiException;
|
|
||||||
import com.imyeyu.spring.TimiSpring;
|
import com.imyeyu.spring.TimiSpring;
|
||||||
import com.imyeyu.spring.entity.IDEntity;
|
|
||||||
import com.imyeyu.spring.mapper.BaseMapper;
|
import com.imyeyu.spring.mapper.BaseMapper;
|
||||||
import com.imyeyu.spring.service.AbstractEntityService;
|
import com.imyeyu.spring.service.AbstractEntityService;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
import java.util.function.Supplier;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 日志服务实现
|
* 日志服务实现
|
||||||
*
|
*
|
||||||
@@ -50,32 +46,6 @@ public class LoggerServiceImplement extends AbstractEntityService<Logger, String
|
|||||||
super.create(logger);
|
super.create(logger);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public <T> T execute(Logger logger, Supplier<T> action) {
|
|
||||||
try {
|
|
||||||
T result = action.get();
|
|
||||||
logger.setLevel(Logger.Level.INFO);
|
|
||||||
if (result instanceof IDEntity<?> entity) {
|
|
||||||
logger.setResult(String.valueOf(entity.getId()));
|
|
||||||
} else if (result != null) {
|
|
||||||
logger.setResult(result.toString());
|
|
||||||
}
|
|
||||||
create(logger);
|
|
||||||
return result;
|
|
||||||
} catch (TimiException e) {
|
|
||||||
logger.setLevel(Logger.Level.WARN);
|
|
||||||
logger.setException(e.getMessage());
|
|
||||||
create(logger);
|
|
||||||
throw e;
|
|
||||||
} catch (RuntimeException e) {
|
|
||||||
logger.setLevel(Logger.Level.ERROR);
|
|
||||||
logger.setException(TimiJava.serializeThrowable(e));
|
|
||||||
log.error("业务操作失败: {}", logger.getOperation(), e);
|
|
||||||
create(logger);
|
|
||||||
throw e;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void create(Logger.Module module, Logger.Level level, String operation, String content, String result) {
|
public void create(Logger.Module module, Logger.Level level, String operation, String content, String result) {
|
||||||
Logger log = new Logger(module, level, operation);
|
Logger log = new Logger(module, level, operation);
|
||||||
log.setContent(content);
|
log.setContent(content);
|
||||||
|
|||||||
@@ -1,76 +0,0 @@
|
|||||||
package db.migration.timiserver;
|
|
||||||
|
|
||||||
import org.flywaydb.core.api.migration.BaseJavaMigration;
|
|
||||||
import org.flywaydb.core.api.migration.Context;
|
|
||||||
|
|
||||||
import java.sql.Connection;
|
|
||||||
import java.sql.PreparedStatement;
|
|
||||||
import java.sql.ResultSet;
|
|
||||||
import java.sql.SQLException;
|
|
||||||
import java.sql.Statement;
|
|
||||||
|
|
||||||
/// 对账附件名称字段长度
|
|
||||||
///
|
|
||||||
/// 生产环境可能已经紧急扩容,达到目标长度时不重复执行 DDL
|
|
||||||
public class V50__reconcile_attachment_name_length extends BaseJavaMigration {
|
|
||||||
|
|
||||||
private static final int NAME_LENGTH = 255;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void migrate(Context context) throws Exception {
|
|
||||||
Connection connection = context.getConnection();
|
|
||||||
int attachmentNameLength = queryCurrentLength(connection, "attachment");
|
|
||||||
int variantNameLength = queryCurrentLength(connection, "attachment_variant");
|
|
||||||
reconcile(connection, "attachment", attachmentNameLength);
|
|
||||||
reconcile(connection, "attachment_variant", variantNameLength);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// 将名称字段扩容到目标长度
|
|
||||||
///
|
|
||||||
/// @param connection Flyway 数据库连接
|
|
||||||
/// @param tableName 表名
|
|
||||||
/// @param currentLength 当前字符长度
|
|
||||||
/// @throws SQLException DDL 执行失败
|
|
||||||
private void reconcile(Connection connection, String tableName, int currentLength) throws SQLException {
|
|
||||||
if (NAME_LENGTH <= currentLength) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
String sql = """
|
|
||||||
ALTER TABLE `%s`
|
|
||||||
MODIFY COLUMN `name` VARCHAR(%d) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL
|
|
||||||
""".formatted(tableName, NAME_LENGTH);
|
|
||||||
try (Statement statement = connection.createStatement()) {
|
|
||||||
statement.executeUpdate(sql);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// 查询名称字段当前长度
|
|
||||||
///
|
|
||||||
/// @param connection Flyway 数据库连接
|
|
||||||
/// @param tableName 表名
|
|
||||||
/// @return 当前字符长度
|
|
||||||
/// @throws SQLException 表或字段不存在、字段类型不正确或查询失败
|
|
||||||
private int queryCurrentLength(Connection connection, String tableName) throws SQLException {
|
|
||||||
String sql = """
|
|
||||||
SELECT `DATA_TYPE`, `CHARACTER_MAXIMUM_LENGTH`
|
|
||||||
FROM `INFORMATION_SCHEMA`.`COLUMNS`
|
|
||||||
WHERE `TABLE_SCHEMA` = DATABASE()
|
|
||||||
AND `TABLE_NAME` = ?
|
|
||||||
AND `COLUMN_NAME` = 'name'
|
|
||||||
""";
|
|
||||||
try (PreparedStatement statement = connection.prepareStatement(sql)) {
|
|
||||||
statement.setString(1, tableName);
|
|
||||||
try (ResultSet resultSet = statement.executeQuery()) {
|
|
||||||
if (!resultSet.next()) {
|
|
||||||
throw new SQLException("表 %s 的 name 字段不存在".formatted(tableName));
|
|
||||||
}
|
|
||||||
String dataType = resultSet.getString("DATA_TYPE");
|
|
||||||
if (!"varchar".equalsIgnoreCase(dataType)) {
|
|
||||||
throw new SQLException("表 %s 的 name 字段类型不是 VARCHAR,而是 %s".formatted(tableName, dataType));
|
|
||||||
}
|
|
||||||
return resultSet.getInt("CHARACTER_MAXIMUM_LENGTH");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
ALTER TABLE `article`
|
|
||||||
ADD COLUMN `updated_by` VARCHAR(36) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci COMMENT '最后更新用户 ID' AFTER `updated_at`;
|
|
||||||
@@ -1,157 +0,0 @@
|
|||||||
ALTER TABLE `gao_event`
|
|
||||||
ADD COLUMN `biz_type` VARCHAR(32) NOT NULL DEFAULT 'GENERAL' COMMENT '业务类型,GENERAL 普通登记,PACKAGE_PURCHASE 购买产品套餐' AFTER `id`;
|
|
||||||
|
|
||||||
CREATE TABLE IF NOT EXISTS `gao_package_config` (
|
|
||||||
`id` VARCHAR(36) NOT NULL,
|
|
||||||
`store_id` VARCHAR(36) NOT NULL COMMENT '所属门店 ID',
|
|
||||||
`name` VARCHAR(128) NOT NULL COMMENT '套餐名称',
|
|
||||||
`description` VARCHAR(255) NULL COMMENT '套餐说明',
|
|
||||||
`standard_amount` BIGINT NOT NULL DEFAULT 0 COMMENT '标准总价,单位分',
|
|
||||||
`status` VARCHAR(32) NOT NULL COMMENT 'DRAFT 草稿,ACTIVE 启用,INACTIVE 停用',
|
|
||||||
`begin_at` BIGINT NULL COMMENT '有效期开始时间戳,毫秒',
|
|
||||||
`end_at` BIGINT NULL COMMENT '有效期结束时间戳,毫秒',
|
|
||||||
`sort` INT NOT NULL DEFAULT 0 COMMENT '排序值',
|
|
||||||
`updated_by` VARCHAR(36) NOT NULL COMMENT '最后修改用户 ID',
|
|
||||||
`created_at` BIGINT NOT NULL,
|
|
||||||
`updated_at` BIGINT NULL,
|
|
||||||
`deleted_at` BIGINT NULL,
|
|
||||||
PRIMARY KEY (`id`),
|
|
||||||
KEY `idx_gao_package_config_store_status` (`store_id`, `status`, `deleted_at`, `begin_at`, `end_at`, `sort`)
|
|
||||||
) COMMENT='GAO 套餐配置';
|
|
||||||
|
|
||||||
CREATE TABLE IF NOT EXISTS `gao_package_config_item` (
|
|
||||||
`id` VARCHAR(36) NOT NULL,
|
|
||||||
`package_config_id` VARCHAR(36) NOT NULL COMMENT '套餐配置 ID',
|
|
||||||
`product_name` VARCHAR(128) NOT NULL COMMENT '产品名称',
|
|
||||||
`unit` VARCHAR(32) NOT NULL COMMENT '产品单位',
|
|
||||||
`default_quantity` DECIMAL(18,3) NOT NULL COMMENT '默认数量',
|
|
||||||
`sort` INT NOT NULL DEFAULT 0 COMMENT '排序值',
|
|
||||||
`remark` VARCHAR(255) NULL COMMENT '备注',
|
|
||||||
`created_at` BIGINT NOT NULL,
|
|
||||||
`updated_at` BIGINT NULL,
|
|
||||||
`deleted_at` BIGINT NULL,
|
|
||||||
PRIMARY KEY (`id`),
|
|
||||||
KEY `idx_gao_package_config_item_config` (`package_config_id`, `deleted_at`, `sort`, `created_at`)
|
|
||||||
) COMMENT='GAO 套餐配置产品明细';
|
|
||||||
|
|
||||||
CREATE TABLE IF NOT EXISTS `gao_customer_package` (
|
|
||||||
`id` VARCHAR(36) NOT NULL,
|
|
||||||
`store_id` VARCHAR(36) NOT NULL COMMENT '门店 ID',
|
|
||||||
`customer_id` VARCHAR(36) NOT NULL COMMENT '客户 ID',
|
|
||||||
`package_config_id` VARCHAR(36) NOT NULL COMMENT '来源套餐配置 ID',
|
|
||||||
`purchase_event_record_id` VARCHAR(36) NOT NULL COMMENT '购买事件登记 ID',
|
|
||||||
`request_no` VARCHAR(128) NOT NULL COMMENT '购买幂等请求号',
|
|
||||||
`package_name_snapshot` VARCHAR(128) NOT NULL COMMENT '套餐名称快照',
|
|
||||||
`standard_amount_snapshot` BIGINT NOT NULL COMMENT '标准价快照,单位分',
|
|
||||||
`sale_amount` BIGINT NOT NULL COMMENT '实际成交价,单位分',
|
|
||||||
`pending_paid_amount` BIGINT NOT NULL DEFAULT 0 COMMENT '待核销收款合计,单位分',
|
|
||||||
`paid_amount` BIGINT NOT NULL DEFAULT 0 COMMENT '累计有效收款,单位分',
|
|
||||||
`refunded_amount` BIGINT NOT NULL DEFAULT 0 COMMENT '累计有效退款,单位分',
|
|
||||||
`status` VARCHAR(32) NOT NULL COMMENT '套餐状态',
|
|
||||||
`payment_status` VARCHAR(32) NOT NULL COMMENT '付款状态',
|
|
||||||
`refund_status` VARCHAR(32) NOT NULL COMMENT '退款状态',
|
|
||||||
`purchased_at` BIGINT NOT NULL COMMENT '购买时间',
|
|
||||||
`operator_user_id` VARCHAR(36) NOT NULL COMMENT '购买登记人',
|
|
||||||
`cancelled_at` BIGINT NULL COMMENT '取消时间',
|
|
||||||
`cancel_operator_user_id` VARCHAR(36) NULL COMMENT '取消操作人',
|
|
||||||
`cancel_reason` TEXT NULL COMMENT '取消原因',
|
|
||||||
`remark` TEXT NULL COMMENT '备注',
|
|
||||||
`created_at` BIGINT NOT NULL,
|
|
||||||
`updated_at` BIGINT NULL,
|
|
||||||
`deleted_at` BIGINT NULL,
|
|
||||||
PRIMARY KEY (`id`),
|
|
||||||
UNIQUE KEY `uk_gao_customer_package_purchase_event` (`purchase_event_record_id`),
|
|
||||||
UNIQUE KEY `uk_gao_customer_package_request` (`store_id`, `request_no`),
|
|
||||||
KEY `idx_gao_customer_package_customer` (`store_id`, `customer_id`, `status`, `deleted_at`, `purchased_at`),
|
|
||||||
KEY `idx_gao_customer_package_payment` (`store_id`, `payment_status`, `refund_status`, `deleted_at`, `purchased_at`)
|
|
||||||
) COMMENT='GAO 客户套餐';
|
|
||||||
|
|
||||||
CREATE TABLE IF NOT EXISTS `gao_customer_package_item` (
|
|
||||||
`id` VARCHAR(36) NOT NULL,
|
|
||||||
`customer_package_id` VARCHAR(36) NOT NULL COMMENT '客户套餐 ID',
|
|
||||||
`product_name_snapshot` VARCHAR(128) NOT NULL COMMENT '产品名称快照',
|
|
||||||
`unit_snapshot` VARCHAR(32) NOT NULL COMMENT '产品单位快照',
|
|
||||||
`total_quantity` DECIMAL(18,3) NOT NULL COMMENT '总权益数量',
|
|
||||||
`reserved_quantity` DECIMAL(18,3) NOT NULL DEFAULT 0 COMMENT '待核销占用数量',
|
|
||||||
`delivered_quantity` DECIMAL(18,3) NOT NULL DEFAULT 0 COMMENT '已核销净发放数量',
|
|
||||||
`sort` INT NOT NULL DEFAULT 0 COMMENT '排序值',
|
|
||||||
`remark` VARCHAR(255) NULL COMMENT '备注',
|
|
||||||
`created_at` BIGINT NOT NULL,
|
|
||||||
`updated_at` BIGINT NULL,
|
|
||||||
`deleted_at` BIGINT NULL,
|
|
||||||
PRIMARY KEY (`id`),
|
|
||||||
KEY `idx_gao_customer_package_item_package` (`customer_package_id`, `deleted_at`, `sort`, `created_at`)
|
|
||||||
) COMMENT='GAO 客户套餐产品权益快照';
|
|
||||||
|
|
||||||
CREATE TABLE IF NOT EXISTS `gao_package_delivery` (
|
|
||||||
`id` VARCHAR(36) NOT NULL,
|
|
||||||
`customer_package_id` VARCHAR(36) NOT NULL COMMENT '客户套餐 ID',
|
|
||||||
`store_id` VARCHAR(36) NOT NULL COMMENT '门店 ID',
|
|
||||||
`customer_id` VARCHAR(36) NOT NULL COMMENT '客户 ID',
|
|
||||||
`operation_type` VARCHAR(32) NOT NULL COMMENT 'DELIVER 正常发放,REVOKE 整单冲正',
|
|
||||||
`status` VARCHAR(32) NOT NULL COMMENT '发放状态',
|
|
||||||
`request_no` VARCHAR(128) NOT NULL COMMENT '客户端幂等请求号',
|
|
||||||
`operator_user_id` VARCHAR(36) NOT NULL COMMENT '提交人',
|
|
||||||
`delivered_at` BIGINT NOT NULL COMMENT '实际发放时间',
|
|
||||||
`verifier_user_id` VARCHAR(36) NULL COMMENT '核销或拒绝操作人',
|
|
||||||
`verified_at` BIGINT NULL COMMENT '核销或拒绝时间',
|
|
||||||
`source_delivery_id` VARCHAR(36) NULL COMMENT '冲正单指向原发放单',
|
|
||||||
`reason` TEXT NULL COMMENT '拒绝、撤销或冲正原因',
|
|
||||||
`remark` TEXT NULL COMMENT '备注',
|
|
||||||
`created_at` BIGINT NOT NULL,
|
|
||||||
`updated_at` BIGINT NULL,
|
|
||||||
`deleted_at` BIGINT NULL,
|
|
||||||
PRIMARY KEY (`id`),
|
|
||||||
UNIQUE KEY `uk_gao_package_delivery_request` (`store_id`, `request_no`),
|
|
||||||
UNIQUE KEY `uk_gao_package_delivery_revoke_source` (`source_delivery_id`),
|
|
||||||
KEY `idx_gao_package_delivery_package_time` (`customer_package_id`, `delivered_at`, `id`),
|
|
||||||
KEY `idx_gao_package_delivery_customer_time` (`store_id`, `customer_id`, `delivered_at`, `id`),
|
|
||||||
KEY `idx_gao_package_delivery_status` (`store_id`, `status`, `delivered_at`, `id`)
|
|
||||||
) COMMENT='GAO 套餐发放操作';
|
|
||||||
|
|
||||||
CREATE TABLE IF NOT EXISTS `gao_package_delivery_item` (
|
|
||||||
`id` VARCHAR(36) NOT NULL,
|
|
||||||
`delivery_id` VARCHAR(36) NOT NULL COMMENT '发放单 ID',
|
|
||||||
`customer_package_item_id` VARCHAR(36) NOT NULL COMMENT '客户套餐产品 ID',
|
|
||||||
`quantity` DECIMAL(18,3) NOT NULL COMMENT '本次数量',
|
|
||||||
`reserved_before` DECIMAL(18,3) NOT NULL COMMENT '操作前占用数量快照',
|
|
||||||
`reserved_after` DECIMAL(18,3) NOT NULL COMMENT '操作后占用数量快照',
|
|
||||||
`delivered_before` DECIMAL(18,3) NOT NULL COMMENT '操作前已发数量快照',
|
|
||||||
`delivered_after` DECIMAL(18,3) NOT NULL COMMENT '操作后已发数量快照',
|
|
||||||
`product_name_snapshot` VARCHAR(128) NOT NULL COMMENT '产品名称快照',
|
|
||||||
`unit_snapshot` VARCHAR(32) NOT NULL COMMENT '产品单位快照',
|
|
||||||
`created_at` BIGINT NOT NULL,
|
|
||||||
`updated_at` BIGINT NULL,
|
|
||||||
`deleted_at` BIGINT NULL,
|
|
||||||
PRIMARY KEY (`id`),
|
|
||||||
UNIQUE KEY `uk_gao_package_delivery_item` (`delivery_id`, `customer_package_item_id`),
|
|
||||||
KEY `idx_gao_package_delivery_item_package_item` (`customer_package_item_id`, `created_at`, `id`)
|
|
||||||
) COMMENT='GAO 套餐发放产品明细';
|
|
||||||
|
|
||||||
CREATE TABLE IF NOT EXISTS `gao_fund_record` (
|
|
||||||
`id` VARCHAR(36) NOT NULL,
|
|
||||||
`store_id` VARCHAR(36) NOT NULL COMMENT '门店 ID',
|
|
||||||
`customer_id` VARCHAR(36) NULL COMMENT '客户 ID',
|
|
||||||
`biz_type` VARCHAR(32) NOT NULL COMMENT '业务类型',
|
|
||||||
`biz_id` VARCHAR(36) NOT NULL COMMENT '业务对象 ID',
|
|
||||||
`operation_type` VARCHAR(32) NOT NULL COMMENT '资金操作类型',
|
|
||||||
`status` VARCHAR(32) NOT NULL COMMENT '资金操作状态',
|
|
||||||
`amount` BIGINT NOT NULL COMMENT '金额,单位分',
|
|
||||||
`source_record_id` VARCHAR(36) NULL COMMENT '冲正时关联原资金记录',
|
|
||||||
`request_no` VARCHAR(128) NOT NULL COMMENT '幂等请求号',
|
|
||||||
`operator_user_id` VARCHAR(36) NOT NULL COMMENT '提交操作用户 ID',
|
|
||||||
`verifier_user_id` VARCHAR(36) NULL COMMENT '收款核销用户 ID',
|
|
||||||
`verified_at` BIGINT NULL COMMENT '收款核销时间',
|
|
||||||
`occurred_at` BIGINT NOT NULL COMMENT '线下操作发生时间',
|
|
||||||
`reason` TEXT NULL COMMENT '原因',
|
|
||||||
`remark` TEXT NULL COMMENT '备注',
|
|
||||||
`created_at` BIGINT NOT NULL,
|
|
||||||
`updated_at` BIGINT NULL,
|
|
||||||
`deleted_at` BIGINT NULL,
|
|
||||||
PRIMARY KEY (`id`),
|
|
||||||
UNIQUE KEY `uk_gao_fund_record_request` (`store_id`, `request_no`),
|
|
||||||
UNIQUE KEY `uk_gao_fund_record_revoke_source` (`source_record_id`),
|
|
||||||
KEY `idx_gao_fund_record_biz_time` (`store_id`, `biz_type`, `biz_id`, `occurred_at`, `id`),
|
|
||||||
KEY `idx_gao_fund_record_customer_time` (`store_id`, `customer_id`, `occurred_at`, `id`),
|
|
||||||
KEY `idx_gao_fund_record_status` (`store_id`, `status`, `operation_type`, `occurred_at`, `id`)
|
|
||||||
) COMMENT='GAO 通用资金操作流水';
|
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
ALTER TABLE `gao_event_record`
|
|
||||||
ADD COLUMN `updated_by` VARCHAR(36) NULL COMMENT '最后修改用户 ID' AFTER `updated_at`;
|
|
||||||
|
|
||||||
UPDATE `gao_event_record`
|
|
||||||
SET `updated_by` = `operator_user_id`
|
|
||||||
WHERE `updated_by` IS NULL;
|
|
||||||
|
|
||||||
ALTER TABLE `gao_event_record`
|
|
||||||
MODIFY COLUMN `updated_by` VARCHAR(36) NOT NULL COMMENT '最后修改用户 ID';
|
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
ALTER TABLE `gao_event`
|
|
||||||
ADD COLUMN `package_config_id` VARCHAR(36) NULL COMMENT '购买套餐事件绑定的套餐配置 ID' AFTER `biz_type`,
|
|
||||||
ADD KEY `idx_gao_event_package_config` (`package_config_id`, `deleted_at`);
|
|
||||||
-10
@@ -1,10 +0,0 @@
|
|||||||
UPDATE `role_permission_inherit` inherit
|
|
||||||
JOIN `role` parent_role ON parent_role.id = inherit.parent_role_id
|
|
||||||
JOIN `role` child_role ON child_role.id = inherit.child_role_id
|
|
||||||
SET inherit.deleted_at = UNIX_TIMESTAMP() * 1000
|
|
||||||
WHERE
|
|
||||||
inherit.deleted_at IS NULL
|
|
||||||
AND parent_role.module_code = 'GAO'
|
|
||||||
AND parent_role.code = 'GLOBAL_MANAGER'
|
|
||||||
AND child_role.module_code = 'GAO'
|
|
||||||
AND child_role.code = 'STORE_MANAGER';
|
|
||||||
@@ -1,39 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8" ?>
|
|
||||||
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
|
|
||||||
<mapper namespace="com.imyeyu.api.modules.gao.mapper.GaoCustomerPackageItemMapper">
|
|
||||||
<select id="selectByCustomerPackageId" resultType="com.imyeyu.api.modules.gao.entity.GaoCustomerPackageItem">
|
|
||||||
SELECT * FROM `gao_customer_package_item`
|
|
||||||
WHERE `customer_package_id` = #{customerPackageId} AND `deleted_at` IS NULL
|
|
||||||
ORDER BY `sort`, `created_at`
|
|
||||||
</select>
|
|
||||||
<select id="selectByCustomerPackageIdList" resultType="com.imyeyu.api.modules.gao.entity.GaoCustomerPackageItem">
|
|
||||||
SELECT * FROM `gao_customer_package_item`
|
|
||||||
WHERE `deleted_at` IS NULL
|
|
||||||
<choose>
|
|
||||||
<when test="customerPackageIdList != null and !customerPackageIdList.isEmpty()">
|
|
||||||
AND `customer_package_id` IN <foreach collection="customerPackageIdList" item="id" open="(" separator="," close=")">#{id}</foreach>
|
|
||||||
</when>
|
|
||||||
<otherwise>AND FALSE</otherwise>
|
|
||||||
</choose>
|
|
||||||
ORDER BY `customer_package_id`, `sort`, `created_at`
|
|
||||||
</select>
|
|
||||||
<select id="selectForUpdate" resultType="com.imyeyu.api.modules.gao.entity.GaoCustomerPackageItem">
|
|
||||||
SELECT * FROM `gao_customer_package_item`
|
|
||||||
WHERE `id` = #{id} AND `deleted_at` IS NULL
|
|
||||||
FOR UPDATE
|
|
||||||
</select>
|
|
||||||
<update id="updateReservedQuantity">
|
|
||||||
UPDATE `gao_customer_package_item`
|
|
||||||
SET `reserved_quantity` = `reserved_quantity` + #{delta}, `updated_at` = FLOOR(UNIX_TIMESTAMP(NOW(3)) * 1000)
|
|
||||||
WHERE `id` = #{id} AND `deleted_at` IS NULL
|
|
||||||
AND `reserved_quantity` + #{delta} >= 0
|
|
||||||
AND `reserved_quantity` + `delivered_quantity` + #{delta} <= `total_quantity`
|
|
||||||
</update>
|
|
||||||
<update id="updateDeliveredQuantity">
|
|
||||||
UPDATE `gao_customer_package_item`
|
|
||||||
SET `delivered_quantity` = `delivered_quantity` + #{delta}, `updated_at` = FLOOR(UNIX_TIMESTAMP(NOW(3)) * 1000)
|
|
||||||
WHERE `id` = #{id} AND `deleted_at` IS NULL
|
|
||||||
AND `delivered_quantity` + #{delta} >= 0
|
|
||||||
AND `reserved_quantity` + `delivered_quantity` + #{delta} <= `total_quantity`
|
|
||||||
</update>
|
|
||||||
</mapper>
|
|
||||||
@@ -1,62 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8" ?>
|
|
||||||
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
|
|
||||||
<mapper namespace="com.imyeyu.api.modules.gao.mapper.GaoCustomerPackageMapper">
|
|
||||||
<select id="selectByRequestNo" resultType="com.imyeyu.api.modules.gao.entity.GaoCustomerPackage">
|
|
||||||
SELECT * FROM `gao_customer_package`
|
|
||||||
WHERE `store_id` = #{storeId} AND `request_no` = #{requestNo}
|
|
||||||
LIMIT 1
|
|
||||||
</select>
|
|
||||||
<select id="selectByRequestNoAnyStore" resultType="com.imyeyu.api.modules.gao.entity.GaoCustomerPackage">
|
|
||||||
SELECT * FROM `gao_customer_package`
|
|
||||||
WHERE `request_no` = #{requestNo}
|
|
||||||
LIMIT 1
|
|
||||||
</select>
|
|
||||||
<select id="selectForUpdate" resultType="com.imyeyu.api.modules.gao.entity.GaoCustomerPackage">
|
|
||||||
SELECT * FROM `gao_customer_package`
|
|
||||||
WHERE `id` = #{id} AND `deleted_at` IS NULL
|
|
||||||
FOR UPDATE
|
|
||||||
</select>
|
|
||||||
<select id="selectByPurchaseEventRecordId" resultType="com.imyeyu.api.modules.gao.entity.GaoCustomerPackage">
|
|
||||||
SELECT * FROM `gao_customer_package`
|
|
||||||
WHERE `purchase_event_record_id` = #{purchaseEventRecordId}
|
|
||||||
LIMIT 1
|
|
||||||
</select>
|
|
||||||
<sql id="queryWhere">
|
|
||||||
p.`deleted_at` IS NULL
|
|
||||||
<if test="storeId != null and storeId != ''">AND p.`store_id` = #{storeId}</if>
|
|
||||||
<if test="customerId != null and customerId != ''">AND p.`customer_id` = #{customerId}</if>
|
|
||||||
<if test="status != null">AND p.`status` = #{status}</if>
|
|
||||||
<if test="paymentStatus != null">AND p.`payment_status` = #{paymentStatus}</if>
|
|
||||||
<if test="refundStatus != null">AND p.`refund_status` = #{refundStatus}</if>
|
|
||||||
<if test="beginAt != null">AND p.`purchased_at` >= #{beginAt}</if>
|
|
||||||
<if test="endAt != null">AND p.`purchased_at` <= #{endAt}</if>
|
|
||||||
<if test="keyword != null and keyword.trim() != ''">AND (p.`package_name_snapshot` LIKE CONCAT('%', #{keyword}, '%') OR c.`name` LIKE CONCAT('%', #{keyword}, '%') OR c.`code` LIKE CONCAT('%', #{keyword}, '%'))</if>
|
|
||||||
</sql>
|
|
||||||
<select id="countByQuery" resultType="long">
|
|
||||||
SELECT COUNT(1) FROM `gao_customer_package` p
|
|
||||||
LEFT JOIN `gao_customer` c ON c.`id` = p.`customer_id`
|
|
||||||
WHERE <include refid="queryWhere"/>
|
|
||||||
</select>
|
|
||||||
<select id="selectByQuery" resultType="com.imyeyu.api.modules.gao.entity.GaoCustomerPackage">
|
|
||||||
SELECT p.* FROM `gao_customer_package` p
|
|
||||||
LEFT JOIN `gao_customer` c ON c.`id` = p.`customer_id`
|
|
||||||
WHERE <include refid="queryWhere"/>
|
|
||||||
ORDER BY p.`purchased_at` DESC, p.`created_at` DESC
|
|
||||||
LIMIT #{offset}, #{limit}
|
|
||||||
</select>
|
|
||||||
<update id="updatePendingPaidAmountDelta">
|
|
||||||
UPDATE `gao_customer_package`
|
|
||||||
SET `pending_paid_amount` = `pending_paid_amount` + #{delta}, `updated_at` = FLOOR(UNIX_TIMESTAMP(NOW(3)) * 1000)
|
|
||||||
WHERE `id` = #{id} AND `deleted_at` IS NULL AND `pending_paid_amount` + #{delta} >= 0
|
|
||||||
</update>
|
|
||||||
<update id="updatePaidAmountDelta">
|
|
||||||
UPDATE `gao_customer_package`
|
|
||||||
SET `paid_amount` = `paid_amount` + #{delta}, `updated_at` = FLOOR(UNIX_TIMESTAMP(NOW(3)) * 1000)
|
|
||||||
WHERE `id` = #{id} AND `deleted_at` IS NULL AND `paid_amount` + #{delta} >= 0
|
|
||||||
</update>
|
|
||||||
<update id="updateStatusIf">
|
|
||||||
UPDATE `gao_customer_package`
|
|
||||||
SET `status` = #{toStatus}, `cancelled_at` = #{cancelledAt}, `cancel_operator_user_id` = #{cancelOperatorUserId}, `cancel_reason` = #{cancelReason}, `refund_status` = #{refundStatus}, `updated_at` = FLOOR(UNIX_TIMESTAMP(NOW(3)) * 1000)
|
|
||||||
WHERE `id` = #{id} AND `status` = #{fromStatus} AND `deleted_at` IS NULL
|
|
||||||
</update>
|
|
||||||
</mapper>
|
|
||||||
@@ -65,7 +65,6 @@
|
|||||||
`verification_status` = 'VERIFIED',
|
`verification_status` = 'VERIFIED',
|
||||||
`verifier_user_id` = #{verifierUserId},
|
`verifier_user_id` = #{verifierUserId},
|
||||||
`verified_at` = #{verifiedAt},
|
`verified_at` = #{verifiedAt},
|
||||||
`updated_by` = #{updatedBy},
|
|
||||||
`updated_at` = ROUND(UNIX_TIMESTAMP(CURRENT_TIMESTAMP(3)) * 1000)
|
`updated_at` = ROUND(UNIX_TIMESTAMP(CURRENT_TIMESTAMP(3)) * 1000)
|
||||||
WHERE
|
WHERE
|
||||||
`id` = #{id}
|
`id` = #{id}
|
||||||
@@ -137,9 +136,6 @@
|
|||||||
AND (
|
AND (
|
||||||
c.`code` LIKE CONCAT('%', #{keyword}, '%')
|
c.`code` LIKE CONCAT('%', #{keyword}, '%')
|
||||||
OR c.`name` LIKE CONCAT('%', #{keyword}, '%')
|
OR c.`name` LIKE CONCAT('%', #{keyword}, '%')
|
||||||
OR c.`name_pinyin_full` LIKE CONCAT(#{keyword}, '%')
|
|
||||||
OR c.`name_pinyin_initial` LIKE CONCAT(#{keyword}, '%')
|
|
||||||
OR c.`name_pinyin_mixed` LIKE CONCAT(#{keyword}, '%')
|
|
||||||
OR r.`remark` LIKE CONCAT('%', #{keyword}, '%')
|
OR r.`remark` LIKE CONCAT('%', #{keyword}, '%')
|
||||||
OR r.`operator_user_id` LIKE CONCAT('%', #{keyword}, '%')
|
OR r.`operator_user_id` LIKE CONCAT('%', #{keyword}, '%')
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -1,51 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8" ?>
|
|
||||||
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
|
|
||||||
<mapper namespace="com.imyeyu.api.modules.gao.mapper.GaoFundRecordMapper">
|
|
||||||
<select id="selectByRequestNo" resultType="com.imyeyu.api.modules.gao.entity.GaoFundRecord">
|
|
||||||
SELECT * FROM `gao_fund_record`
|
|
||||||
WHERE `store_id` = #{storeId} AND `request_no` = #{requestNo}
|
|
||||||
LIMIT 1
|
|
||||||
</select>
|
|
||||||
<select id="selectForUpdate" resultType="com.imyeyu.api.modules.gao.entity.GaoFundRecord">
|
|
||||||
SELECT * FROM `gao_fund_record`
|
|
||||||
WHERE `id` = #{id} AND `deleted_at` IS NULL
|
|
||||||
FOR UPDATE
|
|
||||||
</select>
|
|
||||||
<select id="selectRevokeBySourceRecordId" resultType="com.imyeyu.api.modules.gao.entity.GaoFundRecord">
|
|
||||||
SELECT * FROM `gao_fund_record`
|
|
||||||
WHERE `source_record_id` = #{sourceRecordId} AND `deleted_at` IS NULL
|
|
||||||
LIMIT 1
|
|
||||||
</select>
|
|
||||||
<select id="countPendingReceiveByBizId" resultType="long">
|
|
||||||
SELECT COUNT(1) FROM `gao_fund_record`
|
|
||||||
WHERE `biz_id` = #{bizId} AND `operation_type` = 'RECEIVE' AND `status` = 'PENDING' AND `deleted_at` IS NULL
|
|
||||||
</select>
|
|
||||||
<select id="selectByBizId" resultType="com.imyeyu.api.modules.gao.entity.GaoFundRecord">
|
|
||||||
SELECT * FROM `gao_fund_record`
|
|
||||||
WHERE `biz_id` = #{bizId} AND `deleted_at` IS NULL
|
|
||||||
ORDER BY `occurred_at` DESC, `created_at` DESC
|
|
||||||
</select>
|
|
||||||
<sql id="queryWhere">
|
|
||||||
f.`deleted_at` IS NULL
|
|
||||||
<if test="storeId != null and storeId != ''">AND f.`store_id` = #{storeId}</if>
|
|
||||||
<if test="customerPackageId != null and customerPackageId != ''">AND f.`biz_id` = #{customerPackageId}</if>
|
|
||||||
<if test="customerId != null and customerId != ''">AND f.`customer_id` = #{customerId}</if>
|
|
||||||
<if test="operationType != null">AND f.`operation_type` = #{operationType}</if>
|
|
||||||
<if test="status != null">AND f.`status` = #{status}</if>
|
|
||||||
<if test="beginAt != null">AND f.`occurred_at` >= #{beginAt}</if>
|
|
||||||
<if test="endAt != null">AND f.`occurred_at` <= #{endAt}</if>
|
|
||||||
</sql>
|
|
||||||
<select id="countByQuery" resultType="long">
|
|
||||||
SELECT COUNT(1) FROM `gao_fund_record` f WHERE <include refid="queryWhere"/>
|
|
||||||
</select>
|
|
||||||
<select id="selectByQuery" resultType="com.imyeyu.api.modules.gao.entity.GaoFundRecord">
|
|
||||||
SELECT f.* FROM `gao_fund_record` f WHERE <include refid="queryWhere"/>
|
|
||||||
ORDER BY f.`occurred_at` DESC, f.`created_at` DESC
|
|
||||||
LIMIT #{offset}, #{limit}
|
|
||||||
</select>
|
|
||||||
<update id="updateStatusIf">
|
|
||||||
UPDATE `gao_fund_record`
|
|
||||||
SET `status` = #{toStatus}, `verifier_user_id` = #{verifierUserId}, `verified_at` = #{verifiedAt}, `reason` = #{reason}, `updated_at` = FLOOR(UNIX_TIMESTAMP(NOW(3)) * 1000)
|
|
||||||
WHERE `id` = #{id} AND `status` = #{fromStatus} AND `deleted_at` IS NULL
|
|
||||||
</update>
|
|
||||||
</mapper>
|
|
||||||
@@ -1,20 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8" ?>
|
|
||||||
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
|
|
||||||
<mapper namespace="com.imyeyu.api.modules.gao.mapper.GaoPackageConfigItemMapper">
|
|
||||||
<select id="selectByPackageConfigId" resultType="com.imyeyu.api.modules.gao.entity.GaoPackageConfigItem">
|
|
||||||
SELECT * FROM `gao_package_config_item`
|
|
||||||
WHERE `package_config_id` = #{packageConfigId} AND `deleted_at` IS NULL
|
|
||||||
ORDER BY `sort`, `created_at`
|
|
||||||
</select>
|
|
||||||
<select id="selectByPackageConfigIdList" resultType="com.imyeyu.api.modules.gao.entity.GaoPackageConfigItem">
|
|
||||||
SELECT * FROM `gao_package_config_item`
|
|
||||||
WHERE `deleted_at` IS NULL
|
|
||||||
<choose>
|
|
||||||
<when test="packageConfigIdList != null and !packageConfigIdList.isEmpty()">
|
|
||||||
AND `package_config_id` IN <foreach collection="packageConfigIdList" item="id" open="(" separator="," close=")">#{id}</foreach>
|
|
||||||
</when>
|
|
||||||
<otherwise>AND FALSE</otherwise>
|
|
||||||
</choose>
|
|
||||||
ORDER BY `package_config_id`, `sort`, `created_at`
|
|
||||||
</select>
|
|
||||||
</mapper>
|
|
||||||
@@ -1,45 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8" ?>
|
|
||||||
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
|
|
||||||
<mapper namespace="com.imyeyu.api.modules.gao.mapper.GaoPackageConfigMapper">
|
|
||||||
<select id="selectByIdList" resultType="com.imyeyu.api.modules.gao.entity.GaoPackageConfig">
|
|
||||||
SELECT * FROM `gao_package_config`
|
|
||||||
WHERE `deleted_at` IS NULL
|
|
||||||
<choose>
|
|
||||||
<when test="idList != null and !idList.isEmpty()">
|
|
||||||
AND `id` IN <foreach collection="idList" item="id" open="(" separator="," close=")">#{id}</foreach>
|
|
||||||
</when>
|
|
||||||
<otherwise>AND FALSE</otherwise>
|
|
||||||
</choose>
|
|
||||||
</select>
|
|
||||||
<select id="selectValidList" resultType="com.imyeyu.api.modules.gao.entity.GaoPackageConfig">
|
|
||||||
SELECT * FROM `gao_package_config`
|
|
||||||
WHERE `store_id` = #{storeId}
|
|
||||||
AND `status` = 'ACTIVE'
|
|
||||||
AND (`begin_at` IS NULL OR `begin_at` <= #{now})
|
|
||||||
AND (`end_at` IS NULL OR #{now} <= `end_at`)
|
|
||||||
AND `deleted_at` IS NULL
|
|
||||||
ORDER BY `sort`, `created_at`
|
|
||||||
</select>
|
|
||||||
<select id="countByQuery" resultType="long">
|
|
||||||
SELECT COUNT(1) FROM `gao_package_config`
|
|
||||||
WHERE `deleted_at` IS NULL
|
|
||||||
<if test="storeId != null and storeId != ''">AND `store_id` = #{storeId}</if>
|
|
||||||
<if test="status != null">AND `status` = #{status}</if>
|
|
||||||
<if test="keyword != null and keyword.trim() != ''">AND (`name` LIKE CONCAT('%', #{keyword}, '%') OR `description` LIKE CONCAT('%', #{keyword}, '%'))</if>
|
|
||||||
</select>
|
|
||||||
<select id="selectByQuery" resultType="com.imyeyu.api.modules.gao.entity.GaoPackageConfig">
|
|
||||||
SELECT * FROM `gao_package_config`
|
|
||||||
WHERE `deleted_at` IS NULL
|
|
||||||
<if test="storeId != null and storeId != ''">AND `store_id` = #{storeId}</if>
|
|
||||||
<if test="status != null">AND `status` = #{status}</if>
|
|
||||||
<if test="keyword != null and keyword.trim() != ''">AND (`name` LIKE CONCAT('%', #{keyword}, '%') OR `description` LIKE CONCAT('%', #{keyword}, '%'))</if>
|
|
||||||
ORDER BY `sort`, `created_at` DESC
|
|
||||||
LIMIT #{offset}, #{limit}
|
|
||||||
</select>
|
|
||||||
<select id="selectByStoreIdAndName" resultType="com.imyeyu.api.modules.gao.entity.GaoPackageConfig">
|
|
||||||
SELECT * FROM `gao_package_config`
|
|
||||||
WHERE `store_id` = #{storeId} AND `name` = #{name} AND `deleted_at` IS NULL
|
|
||||||
<if test="excludeId != null">AND `id` != #{excludeId}</if>
|
|
||||||
LIMIT 1
|
|
||||||
</select>
|
|
||||||
</mapper>
|
|
||||||
@@ -1,20 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8" ?>
|
|
||||||
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
|
|
||||||
<mapper namespace="com.imyeyu.api.modules.gao.mapper.GaoPackageDeliveryItemMapper">
|
|
||||||
<select id="selectByDeliveryId" resultType="com.imyeyu.api.modules.gao.entity.GaoPackageDeliveryItem">
|
|
||||||
SELECT * FROM `gao_package_delivery_item`
|
|
||||||
WHERE `delivery_id` = #{deliveryId} AND `deleted_at` IS NULL
|
|
||||||
ORDER BY `created_at`, `id`
|
|
||||||
</select>
|
|
||||||
<select id="selectByDeliveryIdList" resultType="com.imyeyu.api.modules.gao.entity.GaoPackageDeliveryItem">
|
|
||||||
SELECT * FROM `gao_package_delivery_item`
|
|
||||||
WHERE `deleted_at` IS NULL
|
|
||||||
<choose>
|
|
||||||
<when test="deliveryIdList != null and !deliveryIdList.isEmpty()">
|
|
||||||
AND `delivery_id` IN <foreach collection="deliveryIdList" item="id" open="(" separator="," close=")">#{id}</foreach>
|
|
||||||
</when>
|
|
||||||
<otherwise>AND FALSE</otherwise>
|
|
||||||
</choose>
|
|
||||||
ORDER BY `delivery_id`, `created_at`, `id`
|
|
||||||
</select>
|
|
||||||
</mapper>
|
|
||||||
@@ -1,55 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8" ?>
|
|
||||||
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
|
|
||||||
<mapper namespace="com.imyeyu.api.modules.gao.mapper.GaoPackageDeliveryMapper">
|
|
||||||
<select id="selectByRequestNo" resultType="com.imyeyu.api.modules.gao.entity.GaoPackageDelivery">
|
|
||||||
SELECT * FROM `gao_package_delivery`
|
|
||||||
WHERE `store_id` = #{storeId} AND `request_no` = #{requestNo}
|
|
||||||
LIMIT 1
|
|
||||||
</select>
|
|
||||||
<select id="selectForUpdate" resultType="com.imyeyu.api.modules.gao.entity.GaoPackageDelivery">
|
|
||||||
SELECT * FROM `gao_package_delivery`
|
|
||||||
WHERE `id` = #{id} AND `deleted_at` IS NULL
|
|
||||||
FOR UPDATE
|
|
||||||
</select>
|
|
||||||
<select id="selectRevokeBySourceDeliveryId" resultType="com.imyeyu.api.modules.gao.entity.GaoPackageDelivery">
|
|
||||||
SELECT * FROM `gao_package_delivery`
|
|
||||||
WHERE `source_delivery_id` = #{sourceDeliveryId} AND `deleted_at` IS NULL
|
|
||||||
LIMIT 1
|
|
||||||
</select>
|
|
||||||
<select id="countPendingByCustomerPackageId" resultType="long">
|
|
||||||
SELECT COUNT(1) FROM `gao_package_delivery`
|
|
||||||
WHERE `customer_package_id` = #{customerPackageId} AND `status` = 'PENDING' AND `operation_type` = 'DELIVER' AND `deleted_at` IS NULL
|
|
||||||
</select>
|
|
||||||
<select id="countVerifiedByCustomerPackageId" resultType="long">
|
|
||||||
SELECT COUNT(1) FROM `gao_package_delivery`
|
|
||||||
WHERE `customer_package_id` = #{customerPackageId} AND `status` = 'VERIFIED' AND `operation_type` = 'DELIVER' AND `deleted_at` IS NULL
|
|
||||||
</select>
|
|
||||||
<select id="selectByCustomerPackageId" resultType="com.imyeyu.api.modules.gao.entity.GaoPackageDelivery">
|
|
||||||
SELECT * FROM `gao_package_delivery`
|
|
||||||
WHERE `customer_package_id` = #{customerPackageId} AND `deleted_at` IS NULL
|
|
||||||
ORDER BY `delivered_at` DESC, `created_at` DESC
|
|
||||||
</select>
|
|
||||||
<sql id="queryWhere">
|
|
||||||
d.`deleted_at` IS NULL
|
|
||||||
<if test="storeId != null and storeId != ''">AND d.`store_id` = #{storeId}</if>
|
|
||||||
<if test="customerPackageId != null and customerPackageId != ''">AND d.`customer_package_id` = #{customerPackageId}</if>
|
|
||||||
<if test="customerId != null and customerId != ''">AND d.`customer_id` = #{customerId}</if>
|
|
||||||
<if test="status != null">AND d.`status` = #{status}</if>
|
|
||||||
<if test="operationType != null">AND d.`operation_type` = #{operationType}</if>
|
|
||||||
<if test="beginAt != null">AND d.`delivered_at` >= #{beginAt}</if>
|
|
||||||
<if test="endAt != null">AND d.`delivered_at` <= #{endAt}</if>
|
|
||||||
</sql>
|
|
||||||
<select id="countByQuery" resultType="long">
|
|
||||||
SELECT COUNT(1) FROM `gao_package_delivery` d WHERE <include refid="queryWhere"/>
|
|
||||||
</select>
|
|
||||||
<select id="selectByQuery" resultType="com.imyeyu.api.modules.gao.entity.GaoPackageDelivery">
|
|
||||||
SELECT d.* FROM `gao_package_delivery` d WHERE <include refid="queryWhere"/>
|
|
||||||
ORDER BY d.`delivered_at` DESC, d.`created_at` DESC
|
|
||||||
LIMIT #{offset}, #{limit}
|
|
||||||
</select>
|
|
||||||
<update id="updateStatusIf">
|
|
||||||
UPDATE `gao_package_delivery`
|
|
||||||
SET `status` = #{toStatus}, `verifier_user_id` = #{verifierUserId}, `verified_at` = #{verifiedAt}, `reason` = #{reason}, `updated_at` = FLOOR(UNIX_TIMESTAMP(NOW(3)) * 1000)
|
|
||||||
WHERE `id` = #{id} AND `status` = #{fromStatus} AND `deleted_at` IS NULL
|
|
||||||
</update>
|
|
||||||
</mapper>
|
|
||||||
@@ -1,40 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8" ?>
|
|
||||||
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
|
|
||||||
<mapper namespace="com.imyeyu.api.modules.gao.mapper.GaoStoreDiaryMapper">
|
|
||||||
<sql id="monthWhere">
|
|
||||||
`biz_type` = 'GAO_STORE_DIARY'
|
|
||||||
AND `biz_id` = #{storeId}
|
|
||||||
AND `created_at` >= #{beginCreatedAt}
|
|
||||||
AND `created_at` < #{endCreatedAt}
|
|
||||||
AND (`deleted_at` IS NULL OR FLOOR(UNIX_TIMESTAMP(CURRENT_TIMESTAMP(3)) * 1000) < `deleted_at`)
|
|
||||||
</sql>
|
|
||||||
|
|
||||||
<select id="selectByMonth" resultType="com.imyeyu.api.modules.common.entity.Article">
|
|
||||||
SELECT
|
|
||||||
`id`,
|
|
||||||
`biz_type`,
|
|
||||||
`biz_id`,
|
|
||||||
`title`,
|
|
||||||
`description`,
|
|
||||||
`content_type`,
|
|
||||||
`reads`,
|
|
||||||
`likes`,
|
|
||||||
`status`,
|
|
||||||
`updated_by`,
|
|
||||||
`created_at`,
|
|
||||||
`updated_at`,
|
|
||||||
`deleted_at`
|
|
||||||
FROM `article`
|
|
||||||
WHERE
|
|
||||||
<include refid="monthWhere"/>
|
|
||||||
ORDER BY `created_at` DESC, `id` DESC
|
|
||||||
LIMIT #{offset}, #{limit}
|
|
||||||
</select>
|
|
||||||
|
|
||||||
<select id="countByMonth" resultType="long">
|
|
||||||
SELECT COUNT(1)
|
|
||||||
FROM `article`
|
|
||||||
WHERE
|
|
||||||
<include refid="monthWhere"/>
|
|
||||||
</select>
|
|
||||||
</mapper>
|
|
||||||
@@ -16,7 +16,7 @@
|
|||||||
SELECT DISTINCT
|
SELECT DISTINCT
|
||||||
permission.*
|
permission.*
|
||||||
FROM `role_permission`
|
FROM `role_permission`
|
||||||
INNER JOIN `permission` ON permission.id = role_permission.permission_id
|
LEFT JOIN `permission` ON permission.id = role_permission.permission_id
|
||||||
WHERE
|
WHERE
|
||||||
`role_permission`.`role_id` IN
|
`role_permission`.`role_id` IN
|
||||||
<foreach collection="roleIdList" item="item" separator="," open="(" close=")">
|
<foreach collection="roleIdList" item="item" separator="," open="(" close=")">
|
||||||
|
|||||||
Reference in New Issue
Block a user