Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2b4089ef59 | ||
|
|
cdf8a426e9 | ||
|
|
a2d69fe721 | ||
|
|
19db357b44 | ||
|
|
07ffef3e2a | ||
|
|
20c3e1f422 | ||
|
|
f93ec3cd4d | ||
|
|
3cdac98832 | ||
|
|
c122c35376 |
Generated
-6
@@ -1,6 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<project version="4">
|
|
||||||
<component name="DataSourcePerFileMappings">
|
|
||||||
<file url="file://$PROJECT_DIR$/src/main/java/com/imyeyu/api/modules/common/mapper/GroovyScriptVersionMapper.java" value="05742bdc-a11a-4147-9168-ef976a70258a" />
|
|
||||||
</component>
|
|
||||||
</project>
|
|
||||||
@@ -11,7 +11,7 @@
|
|||||||
|
|
||||||
<groupId>com.imyeyu.timiserverapi</groupId>
|
<groupId>com.imyeyu.timiserverapi</groupId>
|
||||||
<artifactId>TimiServerAPI</artifactId>
|
<artifactId>TimiServerAPI</artifactId>
|
||||||
<version>1.0.36</version>
|
<version>1.0.38</version>
|
||||||
<packaging>jar</packaging>
|
<packaging>jar</packaging>
|
||||||
<name>TimiServerAPI</name>
|
<name>TimiServerAPI</name>
|
||||||
<description>imyeyu.com API</description>
|
<description>imyeyu.com API</description>
|
||||||
|
|||||||
@@ -45,6 +45,11 @@ public enum CorePermissionCode implements BuiltinPermissionCode {
|
|||||||
TAG_UPDATE("TAG:UPDATE", "标签修改", false, true),
|
TAG_UPDATE("TAG:UPDATE", "标签修改", false, true),
|
||||||
TAG_DELETE("TAG:DELETE", "标签删除", false, true),
|
TAG_DELETE("TAG:DELETE", "标签删除", false, true),
|
||||||
|
|
||||||
|
ARTICLE_CREATE("ARTICLE:CREATE", "文章创建", false, true),
|
||||||
|
ARTICLE_READ("ARTICLE:READ", "文章读取", false, true),
|
||||||
|
ARTICLE_UPDATE("ARTICLE:UPDATE", "文章修改", false, true),
|
||||||
|
ARTICLE_DELETE("ARTICLE:DELETE", "文章删除", false, true),
|
||||||
|
|
||||||
USER_CREATE("USER:CREATE", "用户创建", false, true),
|
USER_CREATE("USER:CREATE", "用户创建", false, true),
|
||||||
USER_READ("USER:READ", "用户读取", false, true),
|
USER_READ("USER:READ", "用户读取", false, true),
|
||||||
USER_UPDATE("USER:UPDATE", "用户修改", false, true),
|
USER_UPDATE("USER:UPDATE", "用户修改", false, true),
|
||||||
|
|||||||
@@ -32,4 +32,22 @@ public class ThreadPoolConfig {
|
|||||||
executor.initialize();
|
executor.initialize();
|
||||||
return executor;
|
return executor;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// 创建操作审计线程池
|
||||||
|
///
|
||||||
|
/// @return 操作审计线程池
|
||||||
|
@Bean(name = "auditTaskExecutor")
|
||||||
|
public ThreadPoolTaskExecutor auditTaskExecutor() {
|
||||||
|
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
|
||||||
|
executor.setCorePoolSize(4);
|
||||||
|
executor.setMaxPoolSize(8);
|
||||||
|
executor.setQueueCapacity(2000);
|
||||||
|
executor.setKeepAliveSeconds(60);
|
||||||
|
executor.setWaitForTasksToCompleteOnShutdown(true);
|
||||||
|
executor.setAwaitTerminationSeconds(60);
|
||||||
|
executor.setThreadNamePrefix("audit-task-executor-");
|
||||||
|
executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
|
||||||
|
executor.initialize();
|
||||||
|
return executor;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,95 @@
|
|||||||
|
package com.imyeyu.api.modules.common.controller;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonView;
|
||||||
|
import com.imyeyu.api.annotation.RequireCorePermission;
|
||||||
|
import com.imyeyu.api.bean.CorePermissionCode;
|
||||||
|
import com.imyeyu.api.modules.common.entity.Article;
|
||||||
|
import com.imyeyu.api.modules.common.entity.Attachment;
|
||||||
|
import com.imyeyu.api.modules.common.service.ArticleService;
|
||||||
|
import com.imyeyu.api.modules.common.service.AttachmentService;
|
||||||
|
import com.imyeyu.spring.annotation.AOPLog;
|
||||||
|
import com.imyeyu.spring.annotation.RequestRateLimit;
|
||||||
|
import com.imyeyu.spring.bean.Page;
|
||||||
|
import com.imyeyu.spring.bean.PageResult;
|
||||||
|
import com.imyeyu.spring.util.ResponseView;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.web.bind.annotation.PostMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RequestBody;
|
||||||
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RequestParam;
|
||||||
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
|
||||||
|
/// 文章接口
|
||||||
|
///
|
||||||
|
/// @author Codex
|
||||||
|
/// @since 2026-09-09
|
||||||
|
@Slf4j
|
||||||
|
@RestController
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
@RequestMapping("/article")
|
||||||
|
public class ArticleController {
|
||||||
|
|
||||||
|
private final ArticleService service;
|
||||||
|
private final AttachmentService attachmentService;
|
||||||
|
|
||||||
|
/// 查询文章列表
|
||||||
|
///
|
||||||
|
/// @param page 分页参数
|
||||||
|
/// @return 文章分页
|
||||||
|
@JsonView(ResponseView.Public.class)
|
||||||
|
@RequestRateLimit
|
||||||
|
@PostMapping("/list")
|
||||||
|
public PageResult<Article> list(@RequestBody Page<Article> page) {
|
||||||
|
return service.page(page);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 查询文章详情
|
||||||
|
///
|
||||||
|
/// @param id 文章 ID
|
||||||
|
/// @return 文章详情
|
||||||
|
@JsonView(ResponseView.Public.class)
|
||||||
|
@RequestRateLimit
|
||||||
|
@PostMapping("/detail")
|
||||||
|
public Article detail(@RequestParam String id) {
|
||||||
|
Article article = service.get(id);
|
||||||
|
article.setAttachmentList(attachmentService.listByBizId(Attachment.BizType.ARTICLE, article.getId()));
|
||||||
|
return article;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 创建文章
|
||||||
|
///
|
||||||
|
/// @param article 文章
|
||||||
|
/// @return 创建后的文章
|
||||||
|
@AOPLog
|
||||||
|
@JsonView(ResponseView.Public.class)
|
||||||
|
@RequestRateLimit
|
||||||
|
@RequireCorePermission(CorePermissionCode.ARTICLE_CREATE)
|
||||||
|
@PostMapping("/create")
|
||||||
|
public Article create(@RequestBody Article article) {
|
||||||
|
service.create(article);
|
||||||
|
return article;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 更新文章
|
||||||
|
///
|
||||||
|
/// @param article 文章
|
||||||
|
@AOPLog
|
||||||
|
@RequestRateLimit
|
||||||
|
@RequireCorePermission(CorePermissionCode.ARTICLE_UPDATE)
|
||||||
|
@PostMapping("/update")
|
||||||
|
public void update(@RequestBody Article article) {
|
||||||
|
service.update(article);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 删除文章
|
||||||
|
///
|
||||||
|
/// @param id 文章 ID
|
||||||
|
@AOPLog
|
||||||
|
@RequestRateLimit
|
||||||
|
@RequireCorePermission(CorePermissionCode.ARTICLE_DELETE)
|
||||||
|
@PostMapping("/delete")
|
||||||
|
public void delete(@RequestParam String id) {
|
||||||
|
service.delete(id);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,5 +1,6 @@
|
|||||||
package com.imyeyu.api.modules.common.controller;
|
package com.imyeyu.api.modules.common.controller;
|
||||||
|
|
||||||
|
import com.imyeyu.api.modules.common.vo.ClientLogRequest;
|
||||||
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.spring.annotation.AOPLog;
|
import com.imyeyu.spring.annotation.AOPLog;
|
||||||
@@ -29,7 +30,9 @@ public class LoggerController {
|
|||||||
@AOPLog
|
@AOPLog
|
||||||
@RequiredToken
|
@RequiredToken
|
||||||
@PostMapping("/create")
|
@PostMapping("/create")
|
||||||
public void create(@Valid @RequestBody Logger logger) {
|
public void create(@Valid @RequestBody ClientLogRequest request) {
|
||||||
|
Logger logger = Logger.info(Logger.Module.COMMON, "CLIENT_LOG");
|
||||||
|
logger.setContent(request.getContent());
|
||||||
service.create(logger);
|
service.create(logger);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -34,6 +34,8 @@ public class Article extends UUIDEntity implements SettingSupport {
|
|||||||
/// GAO 门店日记
|
/// GAO 门店日记
|
||||||
GAO_STORE_DIARY,
|
GAO_STORE_DIARY,
|
||||||
|
|
||||||
|
GAO_SYSTEM,
|
||||||
|
|
||||||
/// 反馈
|
/// 反馈
|
||||||
FEEDBACK
|
FEEDBACK
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,18 @@
|
|||||||
|
package com.imyeyu.api.modules.common.vo;
|
||||||
|
|
||||||
|
import jakarta.validation.constraints.Size;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
/// 客户端诊断日志请求
|
||||||
|
///
|
||||||
|
/// 客户端日志不是操作审计,操作编码、模块、级别、用户和 IP 均由服务端决定
|
||||||
|
///
|
||||||
|
/// @author Codex
|
||||||
|
/// @since 2026-09-09
|
||||||
|
@Data
|
||||||
|
public class ClientLogRequest {
|
||||||
|
|
||||||
|
/// 日志内容
|
||||||
|
@Size(max = 32768, message = "日志内容不能超过 32 KB")
|
||||||
|
private String content;
|
||||||
|
}
|
||||||
@@ -111,6 +111,8 @@ public enum GaoPermissionCode implements BuiltinPermissionCode {
|
|||||||
|
|
||||||
CUSTOMER_PACKAGE_PRICE_OVERRIDE("CUSTOMER_PACKAGE:PRICE_OVERRIDE", "客户套餐成交价和权益配额调整", true, true),
|
CUSTOMER_PACKAGE_PRICE_OVERRIDE("CUSTOMER_PACKAGE:PRICE_OVERRIDE", "客户套餐成交价和权益配额调整", true, true),
|
||||||
|
|
||||||
|
CUSTOMER_PACKAGE_GIFT_CREATE("CUSTOMER_PACKAGE:GIFT_CREATE", "客户套餐创建赠送", true, true),
|
||||||
|
|
||||||
FUND_RECORD_READ("FUND_RECORD:READ", "资金流水读取", true, true),
|
FUND_RECORD_READ("FUND_RECORD:READ", "资金流水读取", true, true),
|
||||||
|
|
||||||
FUND_RECEIVE_CREATE("FUND_RECEIVE:CREATE", "线下收款创建", true, true),
|
FUND_RECEIVE_CREATE("FUND_RECEIVE:CREATE", "线下收款创建", true, true),
|
||||||
|
|||||||
@@ -0,0 +1,27 @@
|
|||||||
|
package com.imyeyu.api.modules.gao.bean;
|
||||||
|
|
||||||
|
import com.imyeyu.api.annotation.SettingBizType;
|
||||||
|
import com.imyeyu.api.bean.SettingEnum;
|
||||||
|
import com.imyeyu.api.modules.common.entity.Setting;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Getter;
|
||||||
|
|
||||||
|
///
|
||||||
|
///
|
||||||
|
/// @author 夜雨
|
||||||
|
/// @since 2026-09-09 16:11
|
||||||
|
@Getter
|
||||||
|
@SettingBizType("GAO_SYSTEM")
|
||||||
|
@AllArgsConstructor
|
||||||
|
public enum GaoSystemSetting implements SettingEnum {
|
||||||
|
|
||||||
|
SERVICE_LICENSE(null, Setting.ValueType.STRING),
|
||||||
|
|
||||||
|
PRIVACY_LICENSE(null, Setting.ValueType.STRING),
|
||||||
|
|
||||||
|
OPEN_SOURCE_LICENSE(null, Setting.ValueType.STRING);
|
||||||
|
|
||||||
|
final String defaultValue;
|
||||||
|
|
||||||
|
final Setting.ValueType valueType;
|
||||||
|
}
|
||||||
@@ -1,8 +1,8 @@
|
|||||||
package com.imyeyu.api.modules.gao.controller;
|
package com.imyeyu.api.modules.gao.controller;
|
||||||
|
|
||||||
|
import com.imyeyu.api.bean.PermissionMatchMode;
|
||||||
import com.imyeyu.api.modules.gao.annotation.RequireGaoPermission;
|
import com.imyeyu.api.modules.gao.annotation.RequireGaoPermission;
|
||||||
import com.imyeyu.api.modules.gao.bean.GaoPermissionCode;
|
import com.imyeyu.api.modules.gao.bean.GaoPermissionCode;
|
||||||
import com.imyeyu.api.bean.PermissionMatchMode;
|
|
||||||
import com.imyeyu.api.modules.gao.entity.GaoFundRecord;
|
import com.imyeyu.api.modules.gao.entity.GaoFundRecord;
|
||||||
import com.imyeyu.api.modules.gao.entity.GaoSalesOrder;
|
import com.imyeyu.api.modules.gao.entity.GaoSalesOrder;
|
||||||
import com.imyeyu.api.modules.gao.service.GaoOrderPaymentService;
|
import com.imyeyu.api.modules.gao.service.GaoOrderPaymentService;
|
||||||
@@ -17,6 +17,8 @@ import com.imyeyu.api.modules.gao.vo.GaoOrderPaymentRevokeRequest;
|
|||||||
import com.imyeyu.api.modules.gao.vo.GaoSalesOrderCancelRequest;
|
import com.imyeyu.api.modules.gao.vo.GaoSalesOrderCancelRequest;
|
||||||
import com.imyeyu.api.modules.gao.vo.GaoSalesOrderPage;
|
import com.imyeyu.api.modules.gao.vo.GaoSalesOrderPage;
|
||||||
import com.imyeyu.api.modules.gao.vo.GaoSalesOrderUpdateRequest;
|
import com.imyeyu.api.modules.gao.vo.GaoSalesOrderUpdateRequest;
|
||||||
|
import com.imyeyu.api.modules.user.service.UserService;
|
||||||
|
import com.imyeyu.java.TimiJava;
|
||||||
import com.imyeyu.java.bean.timi.TimiException;
|
import com.imyeyu.java.bean.timi.TimiException;
|
||||||
import com.imyeyu.spring.annotation.AOPLog;
|
import com.imyeyu.spring.annotation.AOPLog;
|
||||||
import com.imyeyu.spring.annotation.RequestRateLimit;
|
import com.imyeyu.spring.annotation.RequestRateLimit;
|
||||||
@@ -40,6 +42,7 @@ public class GaoSalesOrderController {
|
|||||||
private final GaoSalesOrderService service;
|
private final GaoSalesOrderService service;
|
||||||
private final GaoOrderPaymentService paymentService;
|
private final GaoOrderPaymentService paymentService;
|
||||||
private final GaoStoreScopeService storeScopeService;
|
private final GaoStoreScopeService storeScopeService;
|
||||||
|
private final UserService userService;
|
||||||
|
|
||||||
@AOPLog
|
@AOPLog
|
||||||
@RequestRateLimit
|
@RequestRateLimit
|
||||||
@@ -56,7 +59,11 @@ public class GaoSalesOrderController {
|
|||||||
@RequireGaoPermission(GaoPermissionCode.SALES_ORDER_READ)
|
@RequireGaoPermission(GaoPermissionCode.SALES_ORDER_READ)
|
||||||
@PostMapping("/detail")
|
@PostMapping("/detail")
|
||||||
public GaoSalesOrder detail(@RequestParam String id) {
|
public GaoSalesOrder detail(@RequestParam String id) {
|
||||||
return service.detail(id);
|
GaoSalesOrder result = service.detail(id);
|
||||||
|
if (TimiJava.isNotEmpty(result.getCancelOperatorUserId())) {
|
||||||
|
result.setCancelOperator(userService.get(result.getCancelOperatorUserId()));
|
||||||
|
}
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@AOPLog
|
@AOPLog
|
||||||
|
|||||||
@@ -34,6 +34,9 @@ public class GaoSalesOrderItem extends UUIDEntity {
|
|||||||
/// 订单项类型
|
/// 订单项类型
|
||||||
private ItemType itemType;
|
private ItemType itemType;
|
||||||
|
|
||||||
|
/// true 为赠送权益
|
||||||
|
private Boolean gifted;
|
||||||
|
|
||||||
/// SKU ID
|
/// SKU ID
|
||||||
private String skuId;
|
private String skuId;
|
||||||
|
|
||||||
@@ -68,6 +71,14 @@ public class GaoSalesOrderItem extends UUIDEntity {
|
|||||||
/// 基础单位数量系数快照
|
/// 基础单位数量系数快照
|
||||||
private BigDecimal baseQuantityPerUnitSnapshot;
|
private BigDecimal baseQuantityPerUnitSnapshot;
|
||||||
|
|
||||||
|
/// 当前 SKU 是否允许业务数量保留小数
|
||||||
|
@Transient
|
||||||
|
private Boolean allowDecimalQuantity;
|
||||||
|
|
||||||
|
/// 当前 SKU 基础单位名称
|
||||||
|
@Transient
|
||||||
|
private String baseUnitName;
|
||||||
|
|
||||||
/// 购买数量
|
/// 购买数量
|
||||||
private BigDecimal quantity;
|
private BigDecimal quantity;
|
||||||
|
|
||||||
|
|||||||
@@ -13,6 +13,12 @@ import java.util.List;
|
|||||||
/// @since 2026-09-06
|
/// @since 2026-09-06
|
||||||
public interface GaoProductSkuMapper extends BaseMapper<GaoProductSku, String> {
|
public interface GaoProductSkuMapper extends BaseMapper<GaoProductSku, String> {
|
||||||
|
|
||||||
|
/// 批量查询 SKU
|
||||||
|
///
|
||||||
|
/// @param idList SKU ID 集合
|
||||||
|
/// @return SKU 列表
|
||||||
|
List<GaoProductSku> selectByIdList(@Param("idList") Collection<String> idList);
|
||||||
|
|
||||||
/// 按产品查询 SKU
|
/// 按产品查询 SKU
|
||||||
List<GaoProductSku> selectByProductId(@Param("productId") String productId);
|
List<GaoProductSku> selectByProductId(@Param("productId") String productId);
|
||||||
|
|
||||||
|
|||||||
@@ -15,6 +15,12 @@ import java.util.List;
|
|||||||
/// @since 2026-09-06
|
/// @since 2026-09-06
|
||||||
public interface GaoProductSkuService extends BaseService<GaoProductSku, String> {
|
public interface GaoProductSkuService extends BaseService<GaoProductSku, String> {
|
||||||
|
|
||||||
|
/// 批量查询 SKU
|
||||||
|
///
|
||||||
|
/// @param idList SKU ID 集合
|
||||||
|
/// @return SKU 列表,包含单位、规格和附件临时数据
|
||||||
|
List<GaoProductSku> listByIdList(Collection<String> idList);
|
||||||
|
|
||||||
/// 查询 SKU 详情
|
/// 查询 SKU 详情
|
||||||
GaoProductSku detail(String id);
|
GaoProductSku detail(String id);
|
||||||
|
|
||||||
|
|||||||
+69
-18
@@ -4,6 +4,7 @@ import com.imyeyu.api.bean.ModuleCode;
|
|||||||
import com.imyeyu.api.config.dbsource.TimiServerDBConfig;
|
import com.imyeyu.api.config.dbsource.TimiServerDBConfig;
|
||||||
import com.imyeyu.api.modules.common.entity.Attachment;
|
import com.imyeyu.api.modules.common.entity.Attachment;
|
||||||
import com.imyeyu.api.modules.common.service.AttachmentService;
|
import com.imyeyu.api.modules.common.service.AttachmentService;
|
||||||
|
import com.imyeyu.api.modules.gao.bean.GaoPermissionCode;
|
||||||
import com.imyeyu.api.modules.gao.entity.GaoCustomer;
|
import com.imyeyu.api.modules.gao.entity.GaoCustomer;
|
||||||
import com.imyeyu.api.modules.gao.entity.GaoCustomerPackage;
|
import com.imyeyu.api.modules.gao.entity.GaoCustomerPackage;
|
||||||
import com.imyeyu.api.modules.gao.entity.GaoPackageConfig;
|
import com.imyeyu.api.modules.gao.entity.GaoPackageConfig;
|
||||||
@@ -24,8 +25,8 @@ import com.imyeyu.api.modules.gao.vo.GaoCustomerPackagePurchaseItem;
|
|||||||
import com.imyeyu.api.modules.gao.vo.GaoPackageOrderCreateData;
|
import com.imyeyu.api.modules.gao.vo.GaoPackageOrderCreateData;
|
||||||
import com.imyeyu.api.modules.gao.vo.GaoProductSkuUnitSelection;
|
import com.imyeyu.api.modules.gao.vo.GaoProductSkuUnitSelection;
|
||||||
import com.imyeyu.api.modules.gao.vo.GaoSalesOrderCancelRequest;
|
import com.imyeyu.api.modules.gao.vo.GaoSalesOrderCancelRequest;
|
||||||
import com.imyeyu.api.modules.system.entity.Logger;
|
import com.imyeyu.api.modules.system.audit.AuditOperation;
|
||||||
import com.imyeyu.api.modules.system.service.LoggerService;
|
import com.imyeyu.api.modules.system.audit.OperationAudit;
|
||||||
import com.imyeyu.api.modules.user.service.PermissionChecker;
|
import com.imyeyu.api.modules.user.service.PermissionChecker;
|
||||||
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;
|
||||||
@@ -44,6 +45,7 @@ import java.util.ArrayList;
|
|||||||
import java.util.Comparator;
|
import java.util.Comparator;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
|
import java.util.LinkedHashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
@@ -69,7 +71,6 @@ public class GaoCustomerPackageServiceImplement extends AbstractEntityService<Ga
|
|||||||
private final AttachmentService attachmentService;
|
private final AttachmentService attachmentService;
|
||||||
private final UserLoginService userLoginService;
|
private final UserLoginService userLoginService;
|
||||||
private final PermissionChecker permissionChecker;
|
private final PermissionChecker permissionChecker;
|
||||||
private final LoggerService loggerService;
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected BaseMapper<GaoCustomerPackage, String> mapper() {
|
protected BaseMapper<GaoCustomerPackage, String> mapper() {
|
||||||
@@ -128,10 +129,11 @@ public class GaoCustomerPackageServiceImplement extends AbstractEntityService<Ga
|
|||||||
return super.get(id);
|
return super.get(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@OperationAudit(AuditOperation.GAO_CUSTOMER_PACKAGE_PURCHASE)
|
||||||
@Transactional(TimiServerDBConfig.ROLLBACKER)
|
@Transactional(TimiServerDBConfig.ROLLBACKER)
|
||||||
@Override
|
@Override
|
||||||
public GaoCustomerPackage purchase(GaoCustomerPackagePurchaseRequest request) {
|
public GaoCustomerPackage purchase(GaoCustomerPackagePurchaseRequest request) {
|
||||||
return loggerService.execute(Logger.Module.GAO, "GAO_CUSTOMER_PACKAGE_PURCHASE", request, () -> purchaseInternal(request));
|
return purchaseInternal(request);
|
||||||
}
|
}
|
||||||
|
|
||||||
private GaoCustomerPackage purchaseInternal(GaoCustomerPackagePurchaseRequest request) {
|
private GaoCustomerPackage purchaseInternal(GaoCustomerPackagePurchaseRequest request) {
|
||||||
@@ -151,10 +153,13 @@ public class GaoCustomerPackageServiceImplement extends AbstractEntityService<Ga
|
|||||||
request.setItemList(defaultPurchaseItems(configItemList));
|
request.setItemList(defaultPurchaseItems(configItemList));
|
||||||
}
|
}
|
||||||
List<GaoCustomerPackagePurchaseItem> requestItemList = new ArrayList<>(request.getItemList());
|
List<GaoCustomerPackagePurchaseItem> requestItemList = new ArrayList<>(request.getItemList());
|
||||||
|
normalizePurchaseItems(requestItemList);
|
||||||
verifyPurchaseItems(requestItemList);
|
verifyPurchaseItems(requestItemList);
|
||||||
boolean canOverridePriceAndQuantity = permissionChecker.hasAny(ModuleCode.GAO,
|
boolean canOverridePriceAndQuantity = permissionChecker.hasAny(ModuleCode.GAO,
|
||||||
com.imyeyu.api.modules.gao.bean.GaoPermissionCode.CUSTOMER_PACKAGE_PRICE_OVERRIDE.getValue());
|
GaoPermissionCode.CUSTOMER_PACKAGE_PRICE_OVERRIDE.getValue());
|
||||||
List<GaoCustomerPackagePurchaseItem> itemList = resolvePurchaseItems(config.getStoreId(), requestItemList, configItemList, canOverridePriceAndQuantity);
|
boolean canCreateGift = permissionChecker.hasAny(ModuleCode.GAO, GaoPermissionCode.CUSTOMER_PACKAGE_GIFT_CREATE.getValue());
|
||||||
|
List<GaoCustomerPackagePurchaseItem> itemList = resolvePurchaseItems(config.getStoreId(), requestItemList, configItemList,
|
||||||
|
canOverridePriceAndQuantity, canCreateGift);
|
||||||
itemList.sort(Comparator.comparing(GaoCustomerPackagePurchaseItem::getSort).thenComparing(GaoCustomerPackagePurchaseItem::getSkuId)
|
itemList.sort(Comparator.comparing(GaoCustomerPackagePurchaseItem::getSort).thenComparing(GaoCustomerPackagePurchaseItem::getSkuId)
|
||||||
.thenComparing(GaoCustomerPackagePurchaseItem::getSkuUnitId));
|
.thenComparing(GaoCustomerPackagePurchaseItem::getSkuUnitId));
|
||||||
request.setItemList(itemList);
|
request.setItemList(itemList);
|
||||||
@@ -206,10 +211,11 @@ public class GaoCustomerPackageServiceImplement extends AbstractEntityService<Ga
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@OperationAudit(AuditOperation.GAO_CUSTOMER_PACKAGE_CANCEL)
|
||||||
@Transactional(TimiServerDBConfig.ROLLBACKER)
|
@Transactional(TimiServerDBConfig.ROLLBACKER)
|
||||||
@Override
|
@Override
|
||||||
public GaoCustomerPackage cancel(GaoCustomerPackageCancelRequest request) {
|
public GaoCustomerPackage cancel(GaoCustomerPackageCancelRequest request) {
|
||||||
return loggerService.execute(Logger.Module.GAO, "GAO_CUSTOMER_PACKAGE_CANCEL", request, () -> cancelInternal(request));
|
return cancelInternal(request);
|
||||||
}
|
}
|
||||||
|
|
||||||
private GaoCustomerPackage cancelInternal(GaoCustomerPackageCancelRequest request) {
|
private GaoCustomerPackage cancelInternal(GaoCustomerPackageCancelRequest request) {
|
||||||
@@ -245,6 +251,7 @@ public class GaoCustomerPackageServiceImplement extends AbstractEntityService<Ga
|
|||||||
GaoCustomerPackagePurchaseItem item = new GaoCustomerPackagePurchaseItem();
|
GaoCustomerPackagePurchaseItem item = new GaoCustomerPackagePurchaseItem();
|
||||||
item.setSkuId(configItem.getSkuId());
|
item.setSkuId(configItem.getSkuId());
|
||||||
item.setSkuUnitId(configItem.getSkuUnitId());
|
item.setSkuUnitId(configItem.getSkuUnitId());
|
||||||
|
item.setGifted(false);
|
||||||
item.setProductNameSnapshot(configItem.getProductNameSnapshot());
|
item.setProductNameSnapshot(configItem.getProductNameSnapshot());
|
||||||
item.setProductIdSnapshot(configItem.getProductIdSnapshot());
|
item.setProductIdSnapshot(configItem.getProductIdSnapshot());
|
||||||
item.setSkuCodeSnapshot(configItem.getSkuCodeSnapshot());
|
item.setSkuCodeSnapshot(configItem.getSkuCodeSnapshot());
|
||||||
@@ -264,6 +271,7 @@ public class GaoCustomerPackageServiceImplement extends AbstractEntityService<Ga
|
|||||||
item.setItemType(GaoSalesOrderItem.ItemType.PACKAGE_ENTITLEMENT);
|
item.setItemType(GaoSalesOrderItem.ItemType.PACKAGE_ENTITLEMENT);
|
||||||
item.setSkuId(source.getSkuId());
|
item.setSkuId(source.getSkuId());
|
||||||
item.setSkuUnitId(source.getSkuUnitId());
|
item.setSkuUnitId(source.getSkuUnitId());
|
||||||
|
item.setGifted(Boolean.TRUE.equals(source.getGifted()));
|
||||||
item.setProductNameSnapshot(source.getProductNameSnapshot());
|
item.setProductNameSnapshot(source.getProductNameSnapshot());
|
||||||
item.setProductIdSnapshot(source.getProductIdSnapshot());
|
item.setProductIdSnapshot(source.getProductIdSnapshot());
|
||||||
item.setSkuCodeSnapshot(source.getSkuCodeSnapshot());
|
item.setSkuCodeSnapshot(source.getSkuCodeSnapshot());
|
||||||
@@ -283,6 +291,32 @@ public class GaoCustomerPackageServiceImplement extends AbstractEntityService<Ga
|
|||||||
return item;
|
return item;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void normalizePurchaseItems(List<GaoCustomerPackagePurchaseItem> itemList) {
|
||||||
|
Map<String, Integer> indexMap = new LinkedHashMap<>();
|
||||||
|
for (int i = 0; i < itemList.size(); i++) {
|
||||||
|
GaoCustomerPackagePurchaseItem item = itemList.get(i);
|
||||||
|
if (item == null) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
item.setGifted(Boolean.TRUE.equals(item.getGifted()));
|
||||||
|
if (item.getSkuId() == null || item.getSkuUnitId() == null || item.getTotalQuantity() == null) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
String key = item.getSkuId() + "|" + item.getSkuUnitId() + "|" + item.getGifted();
|
||||||
|
Integer existingIndex = indexMap.putIfAbsent(key, i);
|
||||||
|
if (existingIndex == null) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
GaoCustomerPackagePurchaseItem existingItem = itemList.get(existingIndex);
|
||||||
|
if (existingItem == null || existingItem.getTotalQuantity() == null) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
existingItem.setTotalQuantity(existingItem.getTotalQuantity().add(item.getTotalQuantity()));
|
||||||
|
itemList.set(i, null);
|
||||||
|
}
|
||||||
|
itemList.removeIf(item -> item == null);
|
||||||
|
}
|
||||||
|
|
||||||
private void verifyPurchaseItems(List<GaoCustomerPackagePurchaseItem> itemList) {
|
private void verifyPurchaseItems(List<GaoCustomerPackagePurchaseItem> itemList) {
|
||||||
Set<String> keySet = new HashSet<>();
|
Set<String> keySet = new HashSet<>();
|
||||||
for (int i = 0; i < itemList.size(); i++) {
|
for (int i = 0; i < itemList.size(); i++) {
|
||||||
@@ -293,14 +327,15 @@ public class GaoCustomerPackageServiceImplement extends AbstractEntityService<Ga
|
|||||||
TimiException.required(item.getTotalQuantity(), "购买产品数量不能为空");
|
TimiException.required(item.getTotalQuantity(), "购买产品数量不能为空");
|
||||||
TimiException.requiredTrue(0 <= item.getTotalQuantity().signum(), "购买产品数量不能为负数");
|
TimiException.requiredTrue(0 <= item.getTotalQuantity().signum(), "购买产品数量不能为负数");
|
||||||
TimiException.requiredTrue(3 >= item.getTotalQuantity().stripTrailingZeros().scale(), "购买产品数量最多保留三位小数");
|
TimiException.requiredTrue(3 >= item.getTotalQuantity().stripTrailingZeros().scale(), "购买产品数量最多保留三位小数");
|
||||||
String key = item.getSkuId() + "|" + item.getSkuUnitId();
|
item.setGifted(Boolean.TRUE.equals(item.getGifted()));
|
||||||
|
String key = item.getSkuId() + "|" + item.getSkuUnitId() + "|" + item.getGifted();
|
||||||
TimiException.requiredTrue(keySet.add(key), "购买套餐内 SKU 和单位不能重复");
|
TimiException.requiredTrue(keySet.add(key), "购买套餐内 SKU 和单位不能重复");
|
||||||
item.setSort(TimiJava.defaultIfNull(item.getSort(), i));
|
item.setSort(TimiJava.defaultIfNull(item.getSort(), i));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<GaoCustomerPackagePurchaseItem> resolvePurchaseItems(String storeId, List<GaoCustomerPackagePurchaseItem> requestItemList,
|
private List<GaoCustomerPackagePurchaseItem> resolvePurchaseItems(String storeId, List<GaoCustomerPackagePurchaseItem> requestItemList,
|
||||||
List<GaoPackageConfigItem> configItemList, boolean canOverridePriceAndQuantity) {
|
List<GaoPackageConfigItem> configItemList, boolean canOverridePriceAndQuantity, boolean canCreateGift) {
|
||||||
Map<String, List<GaoPackageConfigItem>> configItemMap = configItemList.stream()
|
Map<String, List<GaoPackageConfigItem>> configItemMap = configItemList.stream()
|
||||||
.collect(Collectors.groupingBy(GaoPackageConfigItem::getSkuId));
|
.collect(Collectors.groupingBy(GaoPackageConfigItem::getSkuId));
|
||||||
Map<String, BigDecimal> configBaseQuantityMap = new HashMap<>();
|
Map<String, BigDecimal> configBaseQuantityMap = new HashMap<>();
|
||||||
@@ -311,23 +346,32 @@ public class GaoCustomerPackageServiceImplement extends AbstractEntityService<Ga
|
|||||||
Map<String, BigDecimal> requestBaseQuantityMap = new HashMap<>();
|
Map<String, BigDecimal> requestBaseQuantityMap = new HashMap<>();
|
||||||
List<GaoCustomerPackagePurchaseItem> result = new ArrayList<>();
|
List<GaoCustomerPackagePurchaseItem> result = new ArrayList<>();
|
||||||
for (GaoCustomerPackagePurchaseItem requestItem : requestItemList) {
|
for (GaoCustomerPackagePurchaseItem requestItem : requestItemList) {
|
||||||
|
boolean gifted = Boolean.TRUE.equals(requestItem.getGifted());
|
||||||
List<GaoPackageConfigItem> skuConfigItemList = configItemMap.get(requestItem.getSkuId());
|
List<GaoPackageConfigItem> skuConfigItemList = configItemMap.get(requestItem.getSkuId());
|
||||||
TimiException.requiredTrue(skuConfigItemList != null && !skuConfigItemList.isEmpty(), "购买 SKU 不属于套餐配置");
|
if (gifted) {
|
||||||
|
TimiException.requiredTrue(canCreateGift, "没有客户套餐创建赠送权限");
|
||||||
|
} else {
|
||||||
|
TimiException.requiredTrue(skuConfigItemList != null && !skuConfigItemList.isEmpty(), "购买 SKU 不属于套餐配置");
|
||||||
|
}
|
||||||
GaoProductSkuUnitSelection selection = skuService.getSellableSkuUnit(storeId, requestItem.getSkuId(), requestItem.getSkuUnitId());
|
GaoProductSkuUnitSelection selection = skuService.getSellableSkuUnit(storeId, requestItem.getSkuId(), requestItem.getSkuUnitId());
|
||||||
TimiException.requiredTrue(skuConfigItemList.stream().anyMatch(configItem -> 0 <= configItem.getBaseQuantityPerUnitSnapshot()
|
if (!gifted) {
|
||||||
.compareTo(selection.getUnit().getBaseQuantityPerUnit())), "套餐权益单位不能高于配置单位");
|
TimiException.requiredTrue(skuConfigItemList.stream().anyMatch(configItem -> 0 <= configItem.getBaseQuantityPerUnitSnapshot()
|
||||||
|
.compareTo(selection.getUnit().getBaseQuantityPerUnit())), "套餐权益单位不能高于配置单位");
|
||||||
|
}
|
||||||
BigDecimal requestBaseQuantity = toBaseQuantity(requestItem.getTotalQuantity(), selection.getUnit().getBaseQuantityPerUnit(), "套餐权益基础数量最多保留三位小数");
|
BigDecimal requestBaseQuantity = toBaseQuantity(requestItem.getTotalQuantity(), selection.getUnit().getBaseQuantityPerUnit(), "套餐权益基础数量最多保留三位小数");
|
||||||
requestBaseQuantityMap.merge(requestItem.getSkuId(), requestBaseQuantity, BigDecimal::add);
|
if (!gifted) {
|
||||||
|
requestBaseQuantityMap.merge(requestItem.getSkuId(), requestBaseQuantity, BigDecimal::add);
|
||||||
|
}
|
||||||
if (requestItem.getTotalQuantity().signum() == 0) {
|
if (requestItem.getTotalQuantity().signum() == 0) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (!Boolean.TRUE.equals(selection.getSku().getAllowDecimalQuantity())) {
|
if (!Boolean.TRUE.equals(selection.getSku().getAllowDecimalQuantity())) {
|
||||||
TimiException.requiredTrue(requestItem.getTotalQuantity().stripTrailingZeros().scale() <= 0, "该 SKU 不允许小数数量");
|
TimiException.requiredTrue(requestItem.getTotalQuantity().stripTrailingZeros().scale() <= 0, "该 SKU 不允许小数数量");
|
||||||
}
|
}
|
||||||
GaoPackageConfigItem template = resolveItemTemplate(skuConfigItemList, selection.getUnit().getId());
|
|
||||||
GaoCustomerPackagePurchaseItem item = new GaoCustomerPackagePurchaseItem();
|
GaoCustomerPackagePurchaseItem item = new GaoCustomerPackagePurchaseItem();
|
||||||
item.setSkuId(selection.getSku().getId());
|
item.setSkuId(selection.getSku().getId());
|
||||||
item.setSkuUnitId(selection.getUnit().getId());
|
item.setSkuUnitId(selection.getUnit().getId());
|
||||||
|
item.setGifted(gifted);
|
||||||
item.setProductNameSnapshot(selection.getProduct().getName());
|
item.setProductNameSnapshot(selection.getProduct().getName());
|
||||||
item.setProductIdSnapshot(selection.getProduct().getId());
|
item.setProductIdSnapshot(selection.getProduct().getId());
|
||||||
item.setSkuCodeSnapshot(selection.getSku().getCode());
|
item.setSkuCodeSnapshot(selection.getSku().getCode());
|
||||||
@@ -336,8 +380,14 @@ public class GaoCustomerPackageServiceImplement extends AbstractEntityService<Ga
|
|||||||
item.setUnitSnapshot(selection.getUnit().getName());
|
item.setUnitSnapshot(selection.getUnit().getName());
|
||||||
item.setBaseQuantityPerUnitSnapshot(selection.getUnit().getBaseQuantityPerUnit());
|
item.setBaseQuantityPerUnitSnapshot(selection.getUnit().getBaseQuantityPerUnit());
|
||||||
item.setTotalQuantity(requestItem.getTotalQuantity());
|
item.setTotalQuantity(requestItem.getTotalQuantity());
|
||||||
item.setSort(template.getSort());
|
if (gifted) {
|
||||||
item.setRemark(template.getRemark());
|
item.setSort(requestItem.getSort());
|
||||||
|
item.setRemark(requestItem.getRemark());
|
||||||
|
} else {
|
||||||
|
GaoPackageConfigItem template = resolveItemTemplate(skuConfigItemList, selection.getUnit().getId());
|
||||||
|
item.setSort(template.getSort());
|
||||||
|
item.setRemark(template.getRemark());
|
||||||
|
}
|
||||||
result.add(item);
|
result.add(item);
|
||||||
}
|
}
|
||||||
TimiException.requiredTrue(!result.isEmpty(), "购买套餐至少需要一个产品");
|
TimiException.requiredTrue(!result.isEmpty(), "购买套餐至少需要一个产品");
|
||||||
@@ -377,9 +427,10 @@ public class GaoCustomerPackageServiceImplement extends AbstractEntityService<Ga
|
|||||||
List<GaoCustomerPackagePurchaseItem> requestItemList = TimiJava.defaultIfNull(request.getItemList(), List.of());
|
List<GaoCustomerPackagePurchaseItem> requestItemList = TimiJava.defaultIfNull(request.getItemList(), List.of());
|
||||||
verifyPurchaseItems(requestItemList);
|
verifyPurchaseItems(requestItemList);
|
||||||
TimiException.requiredTrue(existingItemList.size() == requestItemList.size(), "requestNo 对应购买请求内容不一致");
|
TimiException.requiredTrue(existingItemList.size() == requestItemList.size(), "requestNo 对应购买请求内容不一致");
|
||||||
Map<String, GaoSalesOrderItem> existingItemMap = existingItemList.stream().collect(Collectors.toMap(item -> item.getSkuId() + "|" + item.getSkuUnitId(), Function.identity()));
|
Map<String, GaoSalesOrderItem> existingItemMap = existingItemList.stream().collect(Collectors.toMap(item -> item.getSkuId() + "|" + item.getSkuUnitId() + "|"
|
||||||
|
+ Boolean.TRUE.equals(item.getGifted()), Function.identity()));
|
||||||
for (GaoCustomerPackagePurchaseItem item : requestItemList) {
|
for (GaoCustomerPackagePurchaseItem item : requestItemList) {
|
||||||
GaoSalesOrderItem existingItem = existingItemMap.get(item.getSkuId() + "|" + item.getSkuUnitId());
|
GaoSalesOrderItem existingItem = existingItemMap.get(item.getSkuId() + "|" + item.getSkuUnitId() + "|" + Boolean.TRUE.equals(item.getGifted()));
|
||||||
TimiException.required(existingItem, "requestNo 对应购买请求内容不一致");
|
TimiException.required(existingItem, "requestNo 对应购买请求内容不一致");
|
||||||
TimiException.requiredTrue(existingItem.getItemType() == GaoSalesOrderItem.ItemType.PACKAGE_ENTITLEMENT
|
TimiException.requiredTrue(existingItem.getItemType() == GaoSalesOrderItem.ItemType.PACKAGE_ENTITLEMENT
|
||||||
&& existingItem.getQuantity().compareTo(item.getTotalQuantity()) == 0
|
&& existingItem.getQuantity().compareTo(item.getTotalQuantity()) == 0
|
||||||
|
|||||||
+14
-9
@@ -31,8 +31,8 @@ import com.imyeyu.api.modules.gao.vo.GaoOrderFulfillmentPrepareStockRequest;
|
|||||||
import com.imyeyu.api.modules.gao.vo.GaoOrderFulfillmentRevokeRequest;
|
import com.imyeyu.api.modules.gao.vo.GaoOrderFulfillmentRevokeRequest;
|
||||||
import com.imyeyu.api.modules.gao.vo.GaoProductSkuUnitSelection;
|
import com.imyeyu.api.modules.gao.vo.GaoProductSkuUnitSelection;
|
||||||
import com.imyeyu.api.modules.gao.vo.GaoStockChangeItem;
|
import com.imyeyu.api.modules.gao.vo.GaoStockChangeItem;
|
||||||
import com.imyeyu.api.modules.system.entity.Logger;
|
import com.imyeyu.api.modules.system.audit.AuditOperation;
|
||||||
import com.imyeyu.api.modules.system.service.LoggerService;
|
import com.imyeyu.api.modules.system.audit.OperationAudit;
|
||||||
import com.imyeyu.api.modules.user.service.RoleChecker;
|
import com.imyeyu.api.modules.user.service.RoleChecker;
|
||||||
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;
|
||||||
@@ -79,7 +79,6 @@ public class GaoOrderFulfillmentServiceImplement extends AbstractEntityService<G
|
|||||||
private final RoleChecker roleChecker;
|
private final RoleChecker roleChecker;
|
||||||
private final UserLoginService userLoginService;
|
private final UserLoginService userLoginService;
|
||||||
private final AttachmentService attachmentService;
|
private final AttachmentService attachmentService;
|
||||||
private final LoggerService loggerService;
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected BaseMapper<GaoOrderFulfillment, String> mapper() {
|
protected BaseMapper<GaoOrderFulfillment, String> mapper() {
|
||||||
@@ -147,10 +146,11 @@ public class GaoOrderFulfillmentServiceImplement extends AbstractEntityService<G
|
|||||||
return mapper.countPendingBySalesOrderId(salesOrderId);
|
return mapper.countPendingBySalesOrderId(salesOrderId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@OperationAudit(AuditOperation.GAO_ORDER_FULFILLMENT_CREATE)
|
||||||
@Transactional(TimiServerDBConfig.ROLLBACKER)
|
@Transactional(TimiServerDBConfig.ROLLBACKER)
|
||||||
@Override
|
@Override
|
||||||
public GaoOrderFulfillment create(GaoOrderFulfillmentCreateRequest request) {
|
public GaoOrderFulfillment create(GaoOrderFulfillmentCreateRequest request) {
|
||||||
return loggerService.execute(Logger.Module.GAO, "GAO_ORDER_FULFILLMENT_CREATE", request, () -> createInternal(request));
|
return createInternal(request);
|
||||||
}
|
}
|
||||||
|
|
||||||
private GaoOrderFulfillment createInternal(GaoOrderFulfillmentCreateRequest request) {
|
private GaoOrderFulfillment createInternal(GaoOrderFulfillmentCreateRequest request) {
|
||||||
@@ -183,10 +183,11 @@ public class GaoOrderFulfillmentServiceImplement extends AbstractEntityService<G
|
|||||||
return detail(fulfillment.getId());
|
return detail(fulfillment.getId());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@OperationAudit(AuditOperation.GAO_ORDER_FULFILLMENT_PREPARE_STOCK)
|
||||||
@Transactional(TimiServerDBConfig.ROLLBACKER)
|
@Transactional(TimiServerDBConfig.ROLLBACKER)
|
||||||
@Override
|
@Override
|
||||||
public GaoOrderFulfillment prepareStock(GaoOrderFulfillmentPrepareStockRequest request) {
|
public GaoOrderFulfillment prepareStock(GaoOrderFulfillmentPrepareStockRequest request) {
|
||||||
return loggerService.execute(Logger.Module.GAO, "GAO_ORDER_FULFILLMENT_PREPARE_STOCK", request, () -> prepareStockInternal(request));
|
return prepareStockInternal(request);
|
||||||
}
|
}
|
||||||
|
|
||||||
private GaoOrderFulfillment prepareStockInternal(GaoOrderFulfillmentPrepareStockRequest request) {
|
private GaoOrderFulfillment prepareStockInternal(GaoOrderFulfillmentPrepareStockRequest request) {
|
||||||
@@ -217,10 +218,11 @@ public class GaoOrderFulfillmentServiceImplement extends AbstractEntityService<G
|
|||||||
return detail(fulfillment.getId());
|
return detail(fulfillment.getId());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@OperationAudit(AuditOperation.GAO_ORDER_FULFILLMENT_VERIFY)
|
||||||
@Transactional(TimiServerDBConfig.ROLLBACKER)
|
@Transactional(TimiServerDBConfig.ROLLBACKER)
|
||||||
@Override
|
@Override
|
||||||
public GaoOrderFulfillment verify(GaoOrderFulfillmentActionRequest request) {
|
public GaoOrderFulfillment verify(GaoOrderFulfillmentActionRequest request) {
|
||||||
return loggerService.execute(Logger.Module.GAO, "GAO_ORDER_FULFILLMENT_VERIFY", request, () -> verifyInternal(request));
|
return verifyInternal(request);
|
||||||
}
|
}
|
||||||
|
|
||||||
private GaoOrderFulfillment verifyInternal(GaoOrderFulfillmentActionRequest request) {
|
private GaoOrderFulfillment verifyInternal(GaoOrderFulfillmentActionRequest request) {
|
||||||
@@ -254,16 +256,18 @@ public class GaoOrderFulfillmentServiceImplement extends AbstractEntityService<G
|
|||||||
return detail(fulfillment.getId());
|
return detail(fulfillment.getId());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@OperationAudit(AuditOperation.GAO_ORDER_FULFILLMENT_REJECT)
|
||||||
@Transactional(TimiServerDBConfig.ROLLBACKER)
|
@Transactional(TimiServerDBConfig.ROLLBACKER)
|
||||||
@Override
|
@Override
|
||||||
public GaoOrderFulfillment reject(GaoOrderFulfillmentActionRequest request) {
|
public GaoOrderFulfillment reject(GaoOrderFulfillmentActionRequest request) {
|
||||||
return loggerService.execute(Logger.Module.GAO, "GAO_ORDER_FULFILLMENT_REJECT", request, () -> releaseInternal(request, GaoOrderFulfillment.Status.REJECTED));
|
return releaseInternal(request, GaoOrderFulfillment.Status.REJECTED);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@OperationAudit(AuditOperation.GAO_ORDER_FULFILLMENT_CANCEL)
|
||||||
@Transactional(TimiServerDBConfig.ROLLBACKER)
|
@Transactional(TimiServerDBConfig.ROLLBACKER)
|
||||||
@Override
|
@Override
|
||||||
public GaoOrderFulfillment cancel(GaoOrderFulfillmentActionRequest request) {
|
public GaoOrderFulfillment cancel(GaoOrderFulfillmentActionRequest request) {
|
||||||
return loggerService.execute(Logger.Module.GAO, "GAO_ORDER_FULFILLMENT_CANCEL", request, () -> cancelInternal(request));
|
return cancelInternal(request);
|
||||||
}
|
}
|
||||||
|
|
||||||
private GaoOrderFulfillment cancelInternal(GaoOrderFulfillmentActionRequest request) {
|
private GaoOrderFulfillment cancelInternal(GaoOrderFulfillmentActionRequest request) {
|
||||||
@@ -306,10 +310,11 @@ public class GaoOrderFulfillmentServiceImplement extends AbstractEntityService<G
|
|||||||
return detail(fulfillment.getId());
|
return detail(fulfillment.getId());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@OperationAudit(AuditOperation.GAO_ORDER_FULFILLMENT_REVOKE)
|
||||||
@Transactional(TimiServerDBConfig.ROLLBACKER)
|
@Transactional(TimiServerDBConfig.ROLLBACKER)
|
||||||
@Override
|
@Override
|
||||||
public GaoOrderFulfillment revoke(GaoOrderFulfillmentRevokeRequest request) {
|
public GaoOrderFulfillment revoke(GaoOrderFulfillmentRevokeRequest request) {
|
||||||
return loggerService.execute(Logger.Module.GAO, "GAO_ORDER_FULFILLMENT_REVOKE", request, () -> revokeInternal(request));
|
return revokeInternal(request);
|
||||||
}
|
}
|
||||||
|
|
||||||
private GaoOrderFulfillment revokeInternal(GaoOrderFulfillmentRevokeRequest request) {
|
private GaoOrderFulfillment revokeInternal(GaoOrderFulfillmentRevokeRequest request) {
|
||||||
|
|||||||
+12
-12
@@ -16,8 +16,8 @@ import com.imyeyu.api.modules.gao.vo.GaoOrderPaymentNoRefundRequest;
|
|||||||
import com.imyeyu.api.modules.gao.vo.GaoOrderPaymentReceiveRequest;
|
import com.imyeyu.api.modules.gao.vo.GaoOrderPaymentReceiveRequest;
|
||||||
import com.imyeyu.api.modules.gao.vo.GaoOrderPaymentRefundRequest;
|
import com.imyeyu.api.modules.gao.vo.GaoOrderPaymentRefundRequest;
|
||||||
import com.imyeyu.api.modules.gao.vo.GaoOrderPaymentRevokeRequest;
|
import com.imyeyu.api.modules.gao.vo.GaoOrderPaymentRevokeRequest;
|
||||||
import com.imyeyu.api.modules.system.entity.Logger;
|
import com.imyeyu.api.modules.system.audit.AuditOperation;
|
||||||
import com.imyeyu.api.modules.system.service.LoggerService;
|
import com.imyeyu.api.modules.system.audit.OperationAudit;
|
||||||
import com.imyeyu.api.modules.user.service.UserLoginService;
|
import com.imyeyu.api.modules.user.service.UserLoginService;
|
||||||
import com.imyeyu.api.modules.user.service.PermissionChecker;
|
import com.imyeyu.api.modules.user.service.PermissionChecker;
|
||||||
import com.imyeyu.java.TimiJava;
|
import com.imyeyu.java.TimiJava;
|
||||||
@@ -44,12 +44,12 @@ public class GaoOrderPaymentServiceImplement implements GaoOrderPaymentService {
|
|||||||
private final AttachmentService attachmentService;
|
private final AttachmentService attachmentService;
|
||||||
private final UserLoginService userLoginService;
|
private final UserLoginService userLoginService;
|
||||||
private final PermissionChecker permissionChecker;
|
private final PermissionChecker permissionChecker;
|
||||||
private final LoggerService loggerService;
|
|
||||||
|
|
||||||
|
@OperationAudit(AuditOperation.GAO_SALES_ORDER_PAYMENT_RECEIVE)
|
||||||
@Transactional(TimiServerDBConfig.ROLLBACKER)
|
@Transactional(TimiServerDBConfig.ROLLBACKER)
|
||||||
@Override
|
@Override
|
||||||
public GaoFundRecord receive(GaoOrderPaymentReceiveRequest request) {
|
public GaoFundRecord receive(GaoOrderPaymentReceiveRequest request) {
|
||||||
return loggerService.execute(Logger.Module.GAO, "GAO_SALES_ORDER_PAYMENT_RECEIVE", request, () -> receiveInternal(request));
|
return receiveInternal(request);
|
||||||
}
|
}
|
||||||
|
|
||||||
private GaoFundRecord receiveInternal(GaoOrderPaymentReceiveRequest request) {
|
private GaoFundRecord receiveInternal(GaoOrderPaymentReceiveRequest request) {
|
||||||
@@ -80,11 +80,11 @@ public class GaoOrderPaymentServiceImplement implements GaoOrderPaymentService {
|
|||||||
return record;
|
return record;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@OperationAudit(AuditOperation.GAO_SALES_ORDER_PAYMENT_VERIFY)
|
||||||
@Transactional(TimiServerDBConfig.ROLLBACKER)
|
@Transactional(TimiServerDBConfig.ROLLBACKER)
|
||||||
@Override
|
@Override
|
||||||
public GaoFundRecord verify(String fundRecordId) {
|
public GaoFundRecord verify(String fundRecordId) {
|
||||||
return loggerService.execute(Logger.Module.GAO, "GAO_SALES_ORDER_PAYMENT_VERIFY", fundRecordId, () -> {
|
GaoFundRecord record = lockOrderRecord(fundRecordId);
|
||||||
GaoFundRecord record = lockOrderRecord(fundRecordId);
|
|
||||||
TimiException.requiredTrue(record.getOperationType() == GaoFundRecord.OperationType.RECEIVE && record.getStatus() == GaoFundRecord.Status.PENDING, "收款记录不是待核销状态");
|
TimiException.requiredTrue(record.getOperationType() == GaoFundRecord.OperationType.RECEIVE && record.getStatus() == GaoFundRecord.Status.PENDING, "收款记录不是待核销状态");
|
||||||
GaoSalesOrder order = orderService.getForUpdate(record.getBizId());
|
GaoSalesOrder order = orderService.getForUpdate(record.getBizId());
|
||||||
Long paidAtBefore = order.getPaidAt();
|
Long paidAtBefore = order.getPaidAt();
|
||||||
@@ -102,7 +102,6 @@ public class GaoOrderPaymentServiceImplement implements GaoOrderPaymentService {
|
|||||||
pointTriggerService.onSalesOrderPaid(order);
|
pointTriggerService.onSalesOrderPaid(order);
|
||||||
}
|
}
|
||||||
return record;
|
return record;
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Transactional(TimiServerDBConfig.ROLLBACKER)
|
@Transactional(TimiServerDBConfig.ROLLBACKER)
|
||||||
@@ -140,10 +139,11 @@ public class GaoOrderPaymentServiceImplement implements GaoOrderPaymentService {
|
|||||||
return record;
|
return record;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@OperationAudit(AuditOperation.GAO_SALES_ORDER_REFUND)
|
||||||
@Transactional(TimiServerDBConfig.ROLLBACKER)
|
@Transactional(TimiServerDBConfig.ROLLBACKER)
|
||||||
@Override
|
@Override
|
||||||
public GaoFundRecord refund(GaoOrderPaymentRefundRequest request) {
|
public GaoFundRecord refund(GaoOrderPaymentRefundRequest request) {
|
||||||
return loggerService.execute(Logger.Module.GAO, "GAO_SALES_ORDER_REFUND", request, () -> refundInternal(request));
|
return refundInternal(request);
|
||||||
}
|
}
|
||||||
|
|
||||||
private GaoFundRecord refundInternal(GaoOrderPaymentRefundRequest request) {
|
private GaoFundRecord refundInternal(GaoOrderPaymentRefundRequest request) {
|
||||||
@@ -177,11 +177,11 @@ public class GaoOrderPaymentServiceImplement implements GaoOrderPaymentService {
|
|||||||
return record;
|
return record;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@OperationAudit(AuditOperation.GAO_SALES_ORDER_CONFIRM_NO_REFUND)
|
||||||
@Transactional(TimiServerDBConfig.ROLLBACKER)
|
@Transactional(TimiServerDBConfig.ROLLBACKER)
|
||||||
@Override
|
@Override
|
||||||
public GaoFundRecord confirmNoRefund(GaoOrderPaymentNoRefundRequest request) {
|
public GaoFundRecord confirmNoRefund(GaoOrderPaymentNoRefundRequest request) {
|
||||||
return loggerService.execute(Logger.Module.GAO, "GAO_SALES_ORDER_CONFIRM_NO_REFUND", request, () -> {
|
TimiException.required(request, "not found no refund request");
|
||||||
TimiException.required(request, "not found no refund request");
|
|
||||||
GaoSalesOrder order = orderService.getForUpdate(request.getSalesOrderId());
|
GaoSalesOrder order = orderService.getForUpdate(request.getSalesOrderId());
|
||||||
String requestNo = requiredText(request.getRequestNo(), "not found requestNo");
|
String requestNo = requiredText(request.getRequestNo(), "not found requestNo");
|
||||||
String reason = requiredText(request.getReason(), "确认无需退款原因不能为空");
|
String reason = requiredText(request.getReason(), "确认无需退款原因不能为空");
|
||||||
@@ -199,13 +199,13 @@ public class GaoOrderPaymentServiceImplement implements GaoOrderPaymentService {
|
|||||||
order.setRefundStatus(GaoSalesOrder.RefundStatus.REFUNDED);
|
order.setRefundStatus(GaoSalesOrder.RefundStatus.REFUNDED);
|
||||||
orderService.updatePayment(order);
|
orderService.updatePayment(order);
|
||||||
return record;
|
return record;
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@OperationAudit(AuditOperation.GAO_SALES_ORDER_FUND_REVOKE)
|
||||||
@Transactional(TimiServerDBConfig.ROLLBACKER)
|
@Transactional(TimiServerDBConfig.ROLLBACKER)
|
||||||
@Override
|
@Override
|
||||||
public GaoFundRecord revoke(GaoOrderPaymentRevokeRequest request) {
|
public GaoFundRecord revoke(GaoOrderPaymentRevokeRequest request) {
|
||||||
return loggerService.execute(Logger.Module.GAO, "GAO_SALES_ORDER_FUND_REVOKE", request, () -> revokeInternal(request));
|
return revokeInternal(request);
|
||||||
}
|
}
|
||||||
|
|
||||||
private GaoFundRecord revokeInternal(GaoOrderPaymentRevokeRequest request) {
|
private GaoFundRecord revokeInternal(GaoOrderPaymentRevokeRequest request) {
|
||||||
|
|||||||
+10
-17
@@ -6,8 +6,8 @@ import com.imyeyu.api.modules.gao.entity.GaoPackageConfigItem;
|
|||||||
import com.imyeyu.api.modules.gao.entity.GaoProduct;
|
import com.imyeyu.api.modules.gao.entity.GaoProduct;
|
||||||
import com.imyeyu.api.modules.gao.entity.GaoProductSku;
|
import com.imyeyu.api.modules.gao.entity.GaoProductSku;
|
||||||
import com.imyeyu.api.modules.gao.entity.GaoProductSkuUnit;
|
import com.imyeyu.api.modules.gao.entity.GaoProductSkuUnit;
|
||||||
import com.imyeyu.api.modules.system.entity.Logger;
|
import com.imyeyu.api.modules.system.audit.AuditOperation;
|
||||||
import com.imyeyu.api.modules.system.service.LoggerService;
|
import com.imyeyu.api.modules.system.audit.OperationAudit;
|
||||||
import com.imyeyu.api.modules.gao.mapper.GaoPackageConfigItemMapper;
|
import com.imyeyu.api.modules.gao.mapper.GaoPackageConfigItemMapper;
|
||||||
import com.imyeyu.api.modules.gao.mapper.GaoPackageConfigMapper;
|
import com.imyeyu.api.modules.gao.mapper.GaoPackageConfigMapper;
|
||||||
import com.imyeyu.api.modules.gao.service.GaoPackageConfigService;
|
import com.imyeyu.api.modules.gao.service.GaoPackageConfigService;
|
||||||
@@ -44,7 +44,6 @@ public class GaoPackageConfigServiceImplement extends AbstractEntityService<GaoP
|
|||||||
private final GaoPackageConfigItemMapper itemMapper;
|
private final GaoPackageConfigItemMapper itemMapper;
|
||||||
private final GaoProductSkuService skuService;
|
private final GaoProductSkuService skuService;
|
||||||
private final UserLoginService userLoginService;
|
private final UserLoginService userLoginService;
|
||||||
private final LoggerService loggerService;
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected BaseMapper<GaoPackageConfig, String> mapper() {
|
protected BaseMapper<GaoPackageConfig, String> mapper() {
|
||||||
@@ -90,13 +89,11 @@ public class GaoPackageConfigServiceImplement extends AbstractEntityService<GaoP
|
|||||||
.collect(java.util.stream.Collectors.groupingBy(GaoPackageConfigItem::getPackageConfigId));
|
.collect(java.util.stream.Collectors.groupingBy(GaoPackageConfigItem::getPackageConfigId));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@OperationAudit(AuditOperation.GAO_PACKAGE_CONFIG_CREATE)
|
||||||
@Transactional(TimiServerDBConfig.ROLLBACKER)
|
@Transactional(TimiServerDBConfig.ROLLBACKER)
|
||||||
@Override
|
@Override
|
||||||
public void create(GaoPackageConfig config) {
|
public void create(GaoPackageConfig config) {
|
||||||
loggerService.execute(Logger.Module.GAO, "GAO_PACKAGE_CONFIG_CREATE", config, () -> {
|
createInternal(config);
|
||||||
createInternal(config);
|
|
||||||
return config;
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void createInternal(GaoPackageConfig config) {
|
private void createInternal(GaoPackageConfig config) {
|
||||||
@@ -109,13 +106,11 @@ public class GaoPackageConfigServiceImplement extends AbstractEntityService<GaoP
|
|||||||
saveItems(config.getId(), config.getItemList());
|
saveItems(config.getId(), config.getItemList());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@OperationAudit(AuditOperation.GAO_PACKAGE_CONFIG_UPDATE)
|
||||||
@Transactional(TimiServerDBConfig.ROLLBACKER)
|
@Transactional(TimiServerDBConfig.ROLLBACKER)
|
||||||
@Override
|
@Override
|
||||||
public void update(GaoPackageConfig request) {
|
public void update(GaoPackageConfig request) {
|
||||||
loggerService.execute(Logger.Module.GAO, "GAO_PACKAGE_CONFIG_UPDATE", request, () -> {
|
updateInternal(request);
|
||||||
updateInternal(request);
|
|
||||||
return request;
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updateInternal(GaoPackageConfig request) {
|
private void updateInternal(GaoPackageConfig request) {
|
||||||
@@ -141,15 +136,13 @@ public class GaoPackageConfigServiceImplement extends AbstractEntityService<GaoP
|
|||||||
saveItems(dbConfig.getId(), request.getItemList());
|
saveItems(dbConfig.getId(), request.getItemList());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@OperationAudit(AuditOperation.GAO_PACKAGE_CONFIG_DELETE)
|
||||||
@Transactional(TimiServerDBConfig.ROLLBACKER)
|
@Transactional(TimiServerDBConfig.ROLLBACKER)
|
||||||
@Override
|
@Override
|
||||||
public void delete(String id) {
|
public void delete(String id) {
|
||||||
loggerService.execute(Logger.Module.GAO, "GAO_PACKAGE_CONFIG_DELETE", id, () -> {
|
GaoPackageConfig config = get(id);
|
||||||
GaoPackageConfig config = get(id);
|
TimiException.required(config, "not found package config");
|
||||||
TimiException.required(config, "not found package config");
|
super.delete(id);
|
||||||
super.delete(id);
|
|
||||||
return id;
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// 套餐配置只允许逻辑删除
|
/// 套餐配置只允许逻辑删除
|
||||||
|
|||||||
+32
-40
@@ -6,8 +6,8 @@ import com.imyeyu.api.modules.gao.mapper.GaoProductCategoryMapper;
|
|||||||
import com.imyeyu.api.modules.gao.service.GaoProductCategoryService;
|
import com.imyeyu.api.modules.gao.service.GaoProductCategoryService;
|
||||||
import com.imyeyu.api.modules.gao.service.GaoStoreScopeService;
|
import com.imyeyu.api.modules.gao.service.GaoStoreScopeService;
|
||||||
import com.imyeyu.api.modules.gao.vo.GaoProductCategoryPage;
|
import com.imyeyu.api.modules.gao.vo.GaoProductCategoryPage;
|
||||||
import com.imyeyu.api.modules.system.entity.Logger;
|
import com.imyeyu.api.modules.system.audit.AuditOperation;
|
||||||
import com.imyeyu.api.modules.system.service.LoggerService;
|
import com.imyeyu.api.modules.system.audit.OperationAudit;
|
||||||
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.java.bean.timi.TimiException;
|
||||||
@@ -37,7 +37,6 @@ public class GaoProductCategoryServiceImplement extends AbstractEntityService<Ga
|
|||||||
private final GaoProductCategoryMapper mapper;
|
private final GaoProductCategoryMapper mapper;
|
||||||
private final GaoStoreScopeService storeScopeService;
|
private final GaoStoreScopeService storeScopeService;
|
||||||
private final UserLoginService userLoginService;
|
private final UserLoginService userLoginService;
|
||||||
private final LoggerService loggerService;
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected BaseMapper<GaoProductCategory, String> mapper() {
|
protected BaseMapper<GaoProductCategory, String> mapper() {
|
||||||
@@ -59,6 +58,7 @@ public class GaoProductCategoryServiceImplement extends AbstractEntityService<Ga
|
|||||||
return mapper.selectByStoreId(storeId);
|
return mapper.selectByStoreId(storeId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@OperationAudit(AuditOperation.GAO_PRODUCT_CATEGORY_SORT)
|
||||||
@Transactional(TimiServerDBConfig.ROLLBACKER)
|
@Transactional(TimiServerDBConfig.ROLLBACKER)
|
||||||
@Override
|
@Override
|
||||||
public void sort(List<String> idList) {
|
public void sort(List<String> idList) {
|
||||||
@@ -66,58 +66,50 @@ public class GaoProductCategoryServiceImplement extends AbstractEntityService<Ga
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
List<String> distinctIdList = new ArrayList<>(new LinkedHashSet<>(idList));
|
List<String> distinctIdList = new ArrayList<>(new LinkedHashSet<>(idList));
|
||||||
loggerService.execute(Logger.Module.GAO, "GAO_PRODUCT_CATEGORY_SORT", distinctIdList, () -> {
|
Map<String, GaoProductCategory> categoryMap = mapper.selectByIdList(new LinkedHashSet<>(distinctIdList)).stream()
|
||||||
Map<String, GaoProductCategory> categoryMap = mapper.selectByIdList(new LinkedHashSet<>(distinctIdList)).stream()
|
.collect(Collectors.toMap(GaoProductCategory::getId, Function.identity()));
|
||||||
.collect(Collectors.toMap(GaoProductCategory::getId, Function.identity()));
|
TimiException.requiredTrue(categoryMap.size() == distinctIdList.size(), "产品分类列表包含不存在的分类");
|
||||||
TimiException.requiredTrue(categoryMap.size() == distinctIdList.size(), "产品分类列表包含不存在的分类");
|
for (GaoProductCategory category : categoryMap.values()) {
|
||||||
for (GaoProductCategory category : categoryMap.values()) {
|
storeScopeService.checkStoreId(category.getStoreId());
|
||||||
storeScopeService.checkStoreId(category.getStoreId());
|
}
|
||||||
}
|
mapper.updateSort(distinctIdList, Time.now());
|
||||||
mapper.updateSort(distinctIdList, Time.now());
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@OperationAudit(AuditOperation.GAO_PRODUCT_CATEGORY_CREATE)
|
||||||
@Transactional(TimiServerDBConfig.ROLLBACKER)
|
@Transactional(TimiServerDBConfig.ROLLBACKER)
|
||||||
@Override
|
@Override
|
||||||
public void create(GaoProductCategory category) {
|
public void create(GaoProductCategory category) {
|
||||||
loggerService.execute(Logger.Module.GAO, "GAO_PRODUCT_CATEGORY_CREATE", category, () -> {
|
prepare(category, null);
|
||||||
prepare(category, null);
|
super.create(category);
|
||||||
super.create(category);
|
|
||||||
return category;
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@OperationAudit(AuditOperation.GAO_PRODUCT_CATEGORY_UPDATE)
|
||||||
@Transactional(TimiServerDBConfig.ROLLBACKER)
|
@Transactional(TimiServerDBConfig.ROLLBACKER)
|
||||||
@Override
|
@Override
|
||||||
public void update(GaoProductCategory request) {
|
public void update(GaoProductCategory request) {
|
||||||
loggerService.execute(Logger.Module.GAO, "GAO_PRODUCT_CATEGORY_UPDATE", request, () -> {
|
TimiException.required(request, "not found category");
|
||||||
TimiException.required(request, "not found category");
|
TimiException.required(request.getId(), "not found category.id");
|
||||||
TimiException.required(request.getId(), "not found category.id");
|
GaoProductCategory category = get(request.getId());
|
||||||
GaoProductCategory category = get(request.getId());
|
TimiException.required(category, "not found category");
|
||||||
TimiException.required(category, "not found category");
|
storeScopeService.checkStoreId(category.getStoreId());
|
||||||
storeScopeService.checkStoreId(category.getStoreId());
|
category.setName(request.getName());
|
||||||
category.setName(request.getName());
|
category.setSort(request.getSort());
|
||||||
category.setSort(request.getSort());
|
category.setStatus(request.getStatus());
|
||||||
category.setStatus(request.getStatus());
|
prepare(category, category.getId());
|
||||||
prepare(category, category.getId());
|
super.update(category);
|
||||||
super.update(category);
|
|
||||||
return category;
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@OperationAudit(AuditOperation.GAO_PRODUCT_CATEGORY_DISABLE)
|
||||||
@Transactional(TimiServerDBConfig.ROLLBACKER)
|
@Transactional(TimiServerDBConfig.ROLLBACKER)
|
||||||
@Override
|
@Override
|
||||||
public void disable(String id) {
|
public void disable(String id) {
|
||||||
loggerService.execute(Logger.Module.GAO, "GAO_PRODUCT_CATEGORY_DISABLE", id, () -> {
|
GaoProductCategory category = get(id);
|
||||||
GaoProductCategory category = get(id);
|
TimiException.required(category, "not found category");
|
||||||
TimiException.required(category, "not found category");
|
storeScopeService.checkStoreId(category.getStoreId());
|
||||||
storeScopeService.checkStoreId(category.getStoreId());
|
category.setStatus(GaoProductCategory.Status.INACTIVE);
|
||||||
category.setStatus(GaoProductCategory.Status.INACTIVE);
|
category.setUpdatedAt(Time.now());
|
||||||
category.setUpdatedAt(Time.now());
|
category.setSort(TimiJava.defaultIfNull(category.getSort(), 0));
|
||||||
category.setSort(TimiJava.defaultIfNull(category.getSort(), 0));
|
super.update(category);
|
||||||
super.update(category);
|
|
||||||
return category;
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
+39
-46
@@ -14,8 +14,8 @@ import com.imyeyu.api.modules.gao.service.GaoProductService;
|
|||||||
import com.imyeyu.api.modules.gao.service.GaoProductSkuService;
|
import com.imyeyu.api.modules.gao.service.GaoProductSkuService;
|
||||||
import com.imyeyu.api.modules.gao.service.GaoProductSpecService;
|
import com.imyeyu.api.modules.gao.service.GaoProductSpecService;
|
||||||
import com.imyeyu.api.modules.gao.vo.GaoProductPage;
|
import com.imyeyu.api.modules.gao.vo.GaoProductPage;
|
||||||
import com.imyeyu.api.modules.system.entity.Logger;
|
import com.imyeyu.api.modules.system.audit.AuditOperation;
|
||||||
import com.imyeyu.api.modules.system.service.LoggerService;
|
import com.imyeyu.api.modules.system.audit.OperationAudit;
|
||||||
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.TimiCode;
|
import com.imyeyu.java.bean.timi.TimiCode;
|
||||||
@@ -52,7 +52,6 @@ public class GaoProductServiceImplement extends AbstractEntityService<GaoProduct
|
|||||||
private final ObjectProvider<GaoProductSkuService> skuServiceProvider;
|
private final ObjectProvider<GaoProductSkuService> skuServiceProvider;
|
||||||
private final ObjectProvider<GaoProductSpecService> specServiceProvider;
|
private final ObjectProvider<GaoProductSpecService> specServiceProvider;
|
||||||
private final UserLoginService userLoginService;
|
private final UserLoginService userLoginService;
|
||||||
private final LoggerService loggerService;
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected BaseMapper<GaoProduct, String> mapper() {
|
protected BaseMapper<GaoProduct, String> mapper() {
|
||||||
@@ -100,62 +99,56 @@ public class GaoProductServiceImplement extends AbstractEntityService<GaoProduct
|
|||||||
return list.stream().filter(product -> !product.getSkuList().isEmpty()).toList();
|
return list.stream().filter(product -> !product.getSkuList().isEmpty()).toList();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@OperationAudit(AuditOperation.GAO_PRODUCT_CREATE)
|
||||||
@Transactional(TimiServerDBConfig.ROLLBACKER)
|
@Transactional(TimiServerDBConfig.ROLLBACKER)
|
||||||
@Override
|
@Override
|
||||||
public void create(GaoProduct product) {
|
public void create(GaoProduct product) {
|
||||||
loggerService.execute(Logger.Module.GAO, "GAO_PRODUCT_CREATE", product, () -> {
|
prepare(product, null);
|
||||||
prepare(product, null);
|
super.create(product);
|
||||||
super.create(product);
|
Map<String, String> specValueIdMap = saveSpecs(product, product.getSpecList());
|
||||||
Map<String, String> specValueIdMap = saveSpecs(product, product.getSpecList());
|
normalizeSkuSpecValueIds(product.getSkuList(), specValueIdMap);
|
||||||
normalizeSkuSpecValueIds(product.getSkuList(), specValueIdMap);
|
saveSkus(product, product.getSkuList());
|
||||||
saveSkus(product, product.getSkuList());
|
attachmentService.updateByBizId(Attachment.BizType.GAO_PRODUCT, product.getId(), product.getAttachmentList());
|
||||||
attachmentService.updateByBizId(Attachment.BizType.GAO_PRODUCT, product.getId(), product.getAttachmentList());
|
|
||||||
return product;
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@OperationAudit(AuditOperation.GAO_PRODUCT_UPDATE)
|
||||||
@Transactional(TimiServerDBConfig.ROLLBACKER)
|
@Transactional(TimiServerDBConfig.ROLLBACKER)
|
||||||
@Override
|
@Override
|
||||||
public void update(GaoProduct request) {
|
public void update(GaoProduct request) {
|
||||||
loggerService.execute(Logger.Module.GAO, "GAO_PRODUCT_UPDATE", request, () -> {
|
TimiException.required(request, "not found product");
|
||||||
TimiException.required(request, "not found product");
|
TimiException.required(request.getId(), "not found product.id");
|
||||||
TimiException.required(request.getId(), "not found product.id");
|
GaoProduct product = get(request.getId());
|
||||||
GaoProduct product = get(request.getId());
|
TimiException.required(product, "not found product");
|
||||||
TimiException.required(product, "not found product");
|
product.setCategoryId(request.getCategoryId());
|
||||||
product.setCategoryId(request.getCategoryId());
|
product.setCode(TimiJava.defaultIfNull(request.getCode(), product.getCode()));
|
||||||
product.setCode(TimiJava.defaultIfNull(request.getCode(), product.getCode()));
|
product.setName(TimiJava.defaultIfNull(request.getName(), product.getName()));
|
||||||
product.setName(TimiJava.defaultIfNull(request.getName(), product.getName()));
|
product.setProductType(TimiJava.defaultIfNull(request.getProductType(), product.getProductType()));
|
||||||
product.setProductType(TimiJava.defaultIfNull(request.getProductType(), product.getProductType()));
|
product.setStockEnabled(TimiJava.defaultIfNull(request.getStockEnabled(), product.getStockEnabled()));
|
||||||
product.setStockEnabled(TimiJava.defaultIfNull(request.getStockEnabled(), product.getStockEnabled()));
|
product.setStatus(TimiJava.defaultIfNull(request.getStatus(), product.getStatus()));
|
||||||
product.setStatus(TimiJava.defaultIfNull(request.getStatus(), product.getStatus()));
|
product.setSort(TimiJava.defaultIfNull(request.getSort(), product.getSort()));
|
||||||
product.setSort(TimiJava.defaultIfNull(request.getSort(), product.getSort()));
|
product.setRemark(request.getRemark());
|
||||||
product.setRemark(request.getRemark());
|
product.setSkuList(request.getSkuList() == null ? skuServiceProvider.getObject().listByProductId(product.getId()) : request.getSkuList());
|
||||||
product.setSkuList(request.getSkuList() == null ? skuServiceProvider.getObject().listByProductId(product.getId()) : request.getSkuList());
|
prepare(product, product.getId());
|
||||||
prepare(product, product.getId());
|
super.update(product);
|
||||||
super.update(product);
|
if (request.getSkuList() != null) {
|
||||||
if (request.getSkuList() != null) {
|
saveSkus(product, request.getSkuList());
|
||||||
saveSkus(product, request.getSkuList());
|
}
|
||||||
}
|
if (request.getAttachmentList() != null) {
|
||||||
if (request.getAttachmentList() != null) {
|
attachmentService.updateByBizId(Attachment.BizType.GAO_PRODUCT, product.getId(), request.getAttachmentList());
|
||||||
attachmentService.updateByBizId(Attachment.BizType.GAO_PRODUCT, product.getId(), request.getAttachmentList());
|
}
|
||||||
}
|
|
||||||
return product;
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@OperationAudit(AuditOperation.GAO_PRODUCT_DISABLE)
|
||||||
@Transactional(TimiServerDBConfig.ROLLBACKER)
|
@Transactional(TimiServerDBConfig.ROLLBACKER)
|
||||||
@Override
|
@Override
|
||||||
public void disable(String id) {
|
public void disable(String id) {
|
||||||
loggerService.execute(Logger.Module.GAO, "GAO_PRODUCT_DISABLE", id, () -> {
|
GaoProduct product = get(id);
|
||||||
GaoProduct product = get(id);
|
TimiException.required(product, "not found product");
|
||||||
TimiException.required(product, "not found product");
|
TimiException.requiredTrue(skuServiceProvider.getObject().listByProductId(id).stream().noneMatch(sku -> sku.getStatus() == com.imyeyu.api.modules.gao.entity.GaoProductSku.Status.ACTIVE), "请先停用产品的全部 SKU");
|
||||||
TimiException.requiredTrue(skuServiceProvider.getObject().listByProductId(id).stream().noneMatch(sku -> sku.getStatus() == com.imyeyu.api.modules.gao.entity.GaoProductSku.Status.ACTIVE), "请先停用产品的全部 SKU");
|
product.setStatus(GaoProduct.Status.INACTIVE);
|
||||||
product.setStatus(GaoProduct.Status.INACTIVE);
|
product.setUpdatedBy(userLoginService.getRequireLoginUserId());
|
||||||
product.setUpdatedBy(userLoginService.getRequireLoginUserId());
|
product.setUpdatedAt(Time.now());
|
||||||
product.setUpdatedAt(Time.now());
|
super.update(product);
|
||||||
super.update(product);
|
|
||||||
return product;
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
+10
@@ -76,6 +76,16 @@ public class GaoProductSkuServiceImplement extends AbstractEntityService<GaoProd
|
|||||||
return sku;
|
return sku;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<GaoProductSku> listByIdList(Collection<String> idList) {
|
||||||
|
if (idList == null || idList.isEmpty()) {
|
||||||
|
return List.of();
|
||||||
|
}
|
||||||
|
List<GaoProductSku> result = mapper.selectByIdList(idList);
|
||||||
|
fillTransient(result);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<GaoProductSku> listByProductId(String productId) {
|
public List<GaoProductSku> listByProductId(String productId) {
|
||||||
TimiException.required(productId, "not found productId");
|
TimiException.required(productId, "not found productId");
|
||||||
|
|||||||
+21
-16
@@ -4,24 +4,24 @@ import com.imyeyu.api.config.dbsource.TimiServerDBConfig;
|
|||||||
import com.imyeyu.api.modules.common.entity.Attachment;
|
import com.imyeyu.api.modules.common.entity.Attachment;
|
||||||
import com.imyeyu.api.modules.common.service.AttachmentService;
|
import com.imyeyu.api.modules.common.service.AttachmentService;
|
||||||
import com.imyeyu.api.modules.gao.entity.GaoProduct;
|
import com.imyeyu.api.modules.gao.entity.GaoProduct;
|
||||||
import com.imyeyu.api.modules.gao.entity.GaoProductStock;
|
|
||||||
import com.imyeyu.api.modules.gao.entity.GaoProductSku;
|
import com.imyeyu.api.modules.gao.entity.GaoProductSku;
|
||||||
import com.imyeyu.api.modules.gao.entity.GaoProductSkuUnit;
|
import com.imyeyu.api.modules.gao.entity.GaoProductSkuUnit;
|
||||||
|
import com.imyeyu.api.modules.gao.entity.GaoProductStock;
|
||||||
import com.imyeyu.api.modules.gao.entity.GaoProductStockRecord;
|
import com.imyeyu.api.modules.gao.entity.GaoProductStockRecord;
|
||||||
import com.imyeyu.api.modules.gao.mapper.GaoProductStockMapper;
|
import com.imyeyu.api.modules.gao.mapper.GaoProductStockMapper;
|
||||||
import com.imyeyu.api.modules.gao.service.GaoProductService;
|
import com.imyeyu.api.modules.gao.service.GaoProductService;
|
||||||
import com.imyeyu.api.modules.gao.service.GaoProductStockService;
|
|
||||||
import com.imyeyu.api.modules.gao.service.GaoProductSkuService;
|
import com.imyeyu.api.modules.gao.service.GaoProductSkuService;
|
||||||
import com.imyeyu.api.modules.gao.service.GaoProductStockRecordService;
|
import com.imyeyu.api.modules.gao.service.GaoProductStockRecordService;
|
||||||
|
import com.imyeyu.api.modules.gao.service.GaoProductStockService;
|
||||||
import com.imyeyu.api.modules.gao.service.GaoStoreScopeService;
|
import com.imyeyu.api.modules.gao.service.GaoStoreScopeService;
|
||||||
|
import com.imyeyu.api.modules.gao.vo.GaoProductSkuUnitSelection;
|
||||||
import com.imyeyu.api.modules.gao.vo.GaoProductStockChangeRequest;
|
import com.imyeyu.api.modules.gao.vo.GaoProductStockChangeRequest;
|
||||||
import com.imyeyu.api.modules.gao.vo.GaoProductStockManualRevokeRequest;
|
import com.imyeyu.api.modules.gao.vo.GaoProductStockManualRevokeRequest;
|
||||||
import com.imyeyu.api.modules.gao.vo.GaoProductStockPage;
|
import com.imyeyu.api.modules.gao.vo.GaoProductStockPage;
|
||||||
import com.imyeyu.api.modules.gao.vo.GaoProductStockProductView;
|
import com.imyeyu.api.modules.gao.vo.GaoProductStockProductView;
|
||||||
import com.imyeyu.api.modules.gao.vo.GaoProductSkuUnitSelection;
|
|
||||||
import com.imyeyu.api.modules.gao.vo.GaoStockChangeItem;
|
import com.imyeyu.api.modules.gao.vo.GaoStockChangeItem;
|
||||||
import com.imyeyu.api.modules.system.entity.Logger;
|
import com.imyeyu.api.modules.system.audit.AuditOperation;
|
||||||
import com.imyeyu.api.modules.system.service.LoggerService;
|
import com.imyeyu.api.modules.system.audit.OperationAudit;
|
||||||
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.TimiCode;
|
import com.imyeyu.java.bean.timi.TimiCode;
|
||||||
@@ -59,7 +59,6 @@ public class GaoProductStockServiceImplement implements GaoProductStockService {
|
|||||||
private final GaoProductSkuService skuService;
|
private final GaoProductSkuService skuService;
|
||||||
private final GaoStoreScopeService storeScopeService;
|
private final GaoStoreScopeService storeScopeService;
|
||||||
private final UserLoginService userLoginService;
|
private final UserLoginService userLoginService;
|
||||||
private final LoggerService loggerService;
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public PageResult<GaoProductStock> pageByQuery(GaoProductStockPage page) {
|
public PageResult<GaoProductStock> pageByQuery(GaoProductStockPage page) {
|
||||||
@@ -112,40 +111,46 @@ public class GaoProductStockServiceImplement implements GaoProductStockService {
|
|||||||
return stock;
|
return stock;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@OperationAudit(AuditOperation.GAO_PRODUCT_STOCK_INITIAL_IN)
|
||||||
@Transactional(TimiServerDBConfig.ROLLBACKER)
|
@Transactional(TimiServerDBConfig.ROLLBACKER)
|
||||||
@Override
|
@Override
|
||||||
public GaoProductStock initialIn(GaoProductStockChangeRequest request) {
|
public GaoProductStock initialIn(GaoProductStockChangeRequest request) {
|
||||||
return loggerService.execute(Logger.Module.GAO, "GAO_PRODUCT_STOCK_INITIAL_IN", request, () -> change(request, GaoProductStockRecord.OperationType.INITIAL_IN));
|
return change(request, GaoProductStockRecord.OperationType.INITIAL_IN);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@OperationAudit(AuditOperation.GAO_PRODUCT_STOCK_MANUAL_IN)
|
||||||
@Transactional(TimiServerDBConfig.ROLLBACKER)
|
@Transactional(TimiServerDBConfig.ROLLBACKER)
|
||||||
@Override
|
@Override
|
||||||
public GaoProductStock manualIn(GaoProductStockChangeRequest request) {
|
public GaoProductStock manualIn(GaoProductStockChangeRequest request) {
|
||||||
return loggerService.execute(Logger.Module.GAO, "GAO_PRODUCT_STOCK_MANUAL_IN", request, () -> change(request, GaoProductStockRecord.OperationType.MANUAL_IN));
|
return change(request, GaoProductStockRecord.OperationType.MANUAL_IN);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@OperationAudit(AuditOperation.GAO_PRODUCT_STOCK_MANUAL_OUT)
|
||||||
@Transactional(TimiServerDBConfig.ROLLBACKER)
|
@Transactional(TimiServerDBConfig.ROLLBACKER)
|
||||||
@Override
|
@Override
|
||||||
public GaoProductStock manualOut(GaoProductStockChangeRequest request) {
|
public GaoProductStock manualOut(GaoProductStockChangeRequest request) {
|
||||||
return loggerService.execute(Logger.Module.GAO, "GAO_PRODUCT_STOCK_MANUAL_OUT", request, () -> change(request, GaoProductStockRecord.OperationType.MANUAL_OUT));
|
return change(request, GaoProductStockRecord.OperationType.MANUAL_OUT);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@OperationAudit(AuditOperation.GAO_PRODUCT_STOCK_MANUAL_REVOKE)
|
||||||
@Transactional(TimiServerDBConfig.ROLLBACKER)
|
@Transactional(TimiServerDBConfig.ROLLBACKER)
|
||||||
@Override
|
@Override
|
||||||
public GaoProductStock manualRevoke(GaoProductStockManualRevokeRequest request) {
|
public GaoProductStock manualRevoke(GaoProductStockManualRevokeRequest request) {
|
||||||
return loggerService.execute(Logger.Module.GAO, "GAO_PRODUCT_STOCK_MANUAL_REVOKE", request, () -> manualRevokeInternal(request));
|
return manualRevokeInternal(request);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@OperationAudit(AuditOperation.GAO_PRODUCT_STOCK_STOCKTAKE_GAIN)
|
||||||
@Transactional(TimiServerDBConfig.ROLLBACKER)
|
@Transactional(TimiServerDBConfig.ROLLBACKER)
|
||||||
@Override
|
@Override
|
||||||
public GaoProductStock stocktakeGain(GaoProductStockChangeRequest request) {
|
public GaoProductStock stocktakeGain(GaoProductStockChangeRequest request) {
|
||||||
return loggerService.execute(Logger.Module.GAO, "GAO_PRODUCT_STOCK_STOCKTAKE_GAIN", request, () -> change(request, GaoProductStockRecord.OperationType.STOCKTAKE_GAIN));
|
return change(request, GaoProductStockRecord.OperationType.STOCKTAKE_GAIN);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@OperationAudit(AuditOperation.GAO_PRODUCT_STOCK_STOCKTAKE_LOSS)
|
||||||
@Transactional(TimiServerDBConfig.ROLLBACKER)
|
@Transactional(TimiServerDBConfig.ROLLBACKER)
|
||||||
@Override
|
@Override
|
||||||
public GaoProductStock stocktakeLoss(GaoProductStockChangeRequest request) {
|
public GaoProductStock stocktakeLoss(GaoProductStockChangeRequest request) {
|
||||||
return loggerService.execute(Logger.Module.GAO, "GAO_PRODUCT_STOCK_STOCKTAKE_LOSS", request, () -> change(request, GaoProductStockRecord.OperationType.STOCKTAKE_LOSS));
|
return change(request, GaoProductStockRecord.OperationType.STOCKTAKE_LOSS);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -216,7 +221,7 @@ public class GaoProductStockServiceImplement implements GaoProductStockService {
|
|||||||
GaoStockChangeItem item = GaoStockChangeItem.of(product, sku, unit, quantity, baseQuantity);
|
GaoStockChangeItem item = GaoStockChangeItem.of(product, sku, unit, quantity, baseQuantity);
|
||||||
item.setSkuSpecSnapshot(skuService.getSkuSpecSnapshot(sku));
|
item.setSkuSpecSnapshot(skuService.getSkuSpecSnapshot(sku));
|
||||||
List<GaoProductStock> result = executeInternal(storeId, sku.getId(), List.of(item), requestNo,
|
List<GaoProductStock> result = executeInternal(storeId, sku.getId(), List.of(item), requestNo,
|
||||||
userLoginService.getRequireLoginUserId(), operationType, request.getRemark(), request.getAttachmentList());
|
userLoginService.getRequireLoginUserId(), operationType, request.getOccurredAt(), request.getRemark(), request.getAttachmentList());
|
||||||
return result.getFirst();
|
return result.getFirst();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -295,11 +300,11 @@ public class GaoProductStockServiceImplement implements GaoProductStockService {
|
|||||||
|
|
||||||
private List<GaoProductStock> executeInternal(String storeId, String bizId, List<GaoStockChangeItem> sourceList, String requestNo,
|
private List<GaoProductStock> executeInternal(String storeId, String bizId, List<GaoStockChangeItem> sourceList, String requestNo,
|
||||||
String operatorUserId, GaoProductStockRecord.OperationType operationType, String remark) {
|
String operatorUserId, GaoProductStockRecord.OperationType operationType, String remark) {
|
||||||
return executeInternal(storeId, bizId, sourceList, requestNo, operatorUserId, operationType, remark, null);
|
return executeInternal(storeId, bizId, sourceList, requestNo, operatorUserId, operationType, null, remark, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<GaoProductStock> executeInternal(String storeId, String bizId, List<GaoStockChangeItem> sourceList, String requestNo,
|
private List<GaoProductStock> executeInternal(String storeId, String bizId, List<GaoStockChangeItem> sourceList, String requestNo,
|
||||||
String operatorUserId, GaoProductStockRecord.OperationType operationType, String remark, List<Attachment> attachmentList) {
|
String operatorUserId, GaoProductStockRecord.OperationType operationType, Long occurredAt, String remark, List<Attachment> attachmentList) {
|
||||||
TimiException.required(storeId, "not found storeId");
|
TimiException.required(storeId, "not found storeId");
|
||||||
TimiException.required(bizId, "not found stock bizId");
|
TimiException.required(bizId, "not found stock bizId");
|
||||||
TimiException.requiredTrue(sourceList != null && !sourceList.isEmpty(), "库存变更至少需要一个产品");
|
TimiException.requiredTrue(sourceList != null && !sourceList.isEmpty(), "库存变更至少需要一个产品");
|
||||||
@@ -360,7 +365,7 @@ public class GaoProductStockServiceImplement implements GaoProductStockService {
|
|||||||
record.setSourceRecordId(item.getSourceRecordId());
|
record.setSourceRecordId(item.getSourceRecordId());
|
||||||
record.setRequestNo(normalizedRequestNo);
|
record.setRequestNo(normalizedRequestNo);
|
||||||
record.setOperatorUserId(operatorUserId);
|
record.setOperatorUserId(operatorUserId);
|
||||||
record.setOccurredAt(Time.now());
|
record.setOccurredAt(TimiJava.defaultIfNull(occurredAt, Time.now()));
|
||||||
record.setRemark(remark);
|
record.setRemark(remark);
|
||||||
recordService.createOperationRecord(record, attachmentList);
|
recordService.createOperationRecord(record, attachmentList);
|
||||||
stock.setOnHandQuantity(onHandAfter);
|
stock.setOnHandQuantity(onHandAfter);
|
||||||
|
|||||||
+53
-16
@@ -34,8 +34,8 @@ import com.imyeyu.api.modules.gao.vo.GaoSalesOrderCancelRequest;
|
|||||||
import com.imyeyu.api.modules.gao.vo.GaoSalesOrderItemRequest;
|
import com.imyeyu.api.modules.gao.vo.GaoSalesOrderItemRequest;
|
||||||
import com.imyeyu.api.modules.gao.vo.GaoSalesOrderPage;
|
import com.imyeyu.api.modules.gao.vo.GaoSalesOrderPage;
|
||||||
import com.imyeyu.api.modules.gao.vo.GaoSalesOrderUpdateRequest;
|
import com.imyeyu.api.modules.gao.vo.GaoSalesOrderUpdateRequest;
|
||||||
import com.imyeyu.api.modules.system.entity.Logger;
|
import com.imyeyu.api.modules.system.audit.AuditOperation;
|
||||||
import com.imyeyu.api.modules.system.service.LoggerService;
|
import com.imyeyu.api.modules.system.audit.OperationAudit;
|
||||||
import com.imyeyu.api.modules.user.service.PermissionChecker;
|
import com.imyeyu.api.modules.user.service.PermissionChecker;
|
||||||
import com.imyeyu.api.modules.user.service.RoleChecker;
|
import com.imyeyu.api.modules.user.service.RoleChecker;
|
||||||
import com.imyeyu.api.modules.user.service.UserLoginService;
|
import com.imyeyu.api.modules.user.service.UserLoginService;
|
||||||
@@ -91,7 +91,6 @@ public class GaoSalesOrderServiceImplement extends AbstractEntityService<GaoSale
|
|||||||
private final PermissionChecker permissionChecker;
|
private final PermissionChecker permissionChecker;
|
||||||
private final RoleChecker roleChecker;
|
private final RoleChecker roleChecker;
|
||||||
private final UserLoginService userLoginService;
|
private final UserLoginService userLoginService;
|
||||||
private final LoggerService loggerService;
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected BaseMapper<GaoSalesOrder, String> mapper() {
|
protected BaseMapper<GaoSalesOrder, String> mapper() {
|
||||||
@@ -116,6 +115,7 @@ public class GaoSalesOrderServiceImplement extends AbstractEntityService<GaoSale
|
|||||||
TimiException.required(order, "not found sales order");
|
TimiException.required(order, "not found sales order");
|
||||||
storeScopeService.checkStoreId(order.getStoreId());
|
storeScopeService.checkStoreId(order.getStoreId());
|
||||||
List<GaoSalesOrderItem> itemList = itemMapper.selectBySalesOrderId(order.getId());
|
List<GaoSalesOrderItem> itemList = itemMapper.selectBySalesOrderId(order.getId());
|
||||||
|
fillItemDisplayInfo(itemList);
|
||||||
for (GaoSalesOrderItem item : itemList) {
|
for (GaoSalesOrderItem item : itemList) {
|
||||||
fillItemBalance(item);
|
fillItemBalance(item);
|
||||||
}
|
}
|
||||||
@@ -139,23 +139,23 @@ public class GaoSalesOrderServiceImplement extends AbstractEntityService<GaoSale
|
|||||||
return order;
|
return order;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@OperationAudit(AuditOperation.GAO_SALES_ORDER_DIRECT_PRODUCT_CREATE)
|
||||||
@Transactional(TimiServerDBConfig.ROLLBACKER)
|
@Transactional(TimiServerDBConfig.ROLLBACKER)
|
||||||
@Override
|
@Override
|
||||||
public GaoSalesOrder createDirectProductOrder(GaoDirectProductOrderCreateRequest request) {
|
public GaoSalesOrder createDirectProductOrder(GaoDirectProductOrderCreateRequest request) {
|
||||||
return loggerService.execute(Logger.Module.GAO, "GAO_SALES_ORDER_DIRECT_PRODUCT_CREATE", request, () -> createDirectInternal(request));
|
return createDirectInternal(request);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@OperationAudit(AuditOperation.GAO_SALES_ORDER_UPDATE)
|
||||||
@Transactional(TimiServerDBConfig.ROLLBACKER)
|
@Transactional(TimiServerDBConfig.ROLLBACKER)
|
||||||
@Override
|
@Override
|
||||||
public GaoSalesOrder updateRemarkAndAttachments(GaoSalesOrderUpdateRequest request) {
|
public GaoSalesOrder updateRemarkAndAttachments(GaoSalesOrderUpdateRequest request) {
|
||||||
return loggerService.execute(Logger.Module.GAO, "GAO_SALES_ORDER_UPDATE", request, () -> {
|
TimiException.required(request, "not found sales order update request");
|
||||||
TimiException.required(request, "not found sales order update request");
|
TimiException.required(request.getId(), "not found sales order.id");
|
||||||
TimiException.required(request.getId(), "not found sales order.id");
|
GaoSalesOrder order = getForUpdate(request.getId());
|
||||||
GaoSalesOrder order = getForUpdate(request.getId());
|
TimiException.requiredTrue(1 == mapper.updateRemark(order.getId(), request.getRemark()), "订单备注更新失败");
|
||||||
TimiException.requiredTrue(1 == mapper.updateRemark(order.getId(), request.getRemark()), "订单备注更新失败");
|
attachmentService.updateByBizId(Attachment.BizType.GAO_SALES_ORDER, order.getId(), request.getAttachmentList());
|
||||||
attachmentService.updateByBizId(Attachment.BizType.GAO_SALES_ORDER, order.getId(), request.getAttachmentList());
|
return detail(order.getId());
|
||||||
return detail(order.getId());
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private GaoSalesOrder createDirectInternal(GaoDirectProductOrderCreateRequest request) {
|
private GaoSalesOrder createDirectInternal(GaoDirectProductOrderCreateRequest request) {
|
||||||
@@ -222,10 +222,11 @@ public class GaoSalesOrderServiceImplement extends AbstractEntityService<GaoSale
|
|||||||
data.getSaleAmount(), data.getItemList());
|
data.getSaleAmount(), data.getItemList());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@OperationAudit(AuditOperation.GAO_SALES_ORDER_CANCEL)
|
||||||
@Transactional(TimiServerDBConfig.ROLLBACKER)
|
@Transactional(TimiServerDBConfig.ROLLBACKER)
|
||||||
@Override
|
@Override
|
||||||
public GaoSalesOrder cancel(GaoSalesOrderCancelRequest request) {
|
public GaoSalesOrder cancel(GaoSalesOrderCancelRequest request) {
|
||||||
return loggerService.execute(Logger.Module.GAO, "GAO_SALES_ORDER_CANCEL", request, () -> cancelInternal(request));
|
return cancelInternal(request);
|
||||||
}
|
}
|
||||||
|
|
||||||
private GaoSalesOrder cancelInternal(GaoSalesOrderCancelRequest request) {
|
private GaoSalesOrder cancelInternal(GaoSalesOrderCancelRequest request) {
|
||||||
@@ -452,9 +453,11 @@ public class GaoSalesOrderServiceImplement extends AbstractEntityService<GaoSale
|
|||||||
for (GaoSalesOrderItem item : itemList) {
|
for (GaoSalesOrderItem item : itemList) {
|
||||||
TimiException.required(item, "销售订单明细不能为空");
|
TimiException.required(item, "销售订单明细不能为空");
|
||||||
TimiException.requiredTrue(item.getItemType() == expectedItemType, "订单项类型与订单类型不匹配");
|
TimiException.requiredTrue(item.getItemType() == expectedItemType, "订单项类型与订单类型不匹配");
|
||||||
|
item.setGifted(Boolean.TRUE.equals(item.getGifted()));
|
||||||
TimiException.required(item.getSkuId(), "订单项 SKU 不能为空");
|
TimiException.required(item.getSkuId(), "订单项 SKU 不能为空");
|
||||||
TimiException.required(item.getSkuUnitId(), "订单项 SKU 单位不能为空");
|
TimiException.required(item.getSkuUnitId(), "订单项 SKU 单位不能为空");
|
||||||
TimiException.requiredTrue(skuUnitKeySet.add(item.getSkuId() + "|" + item.getSkuUnitId()),
|
String skuUnitKey = item.getSkuId() + "|" + item.getSkuUnitId() + "|" + item.getGifted();
|
||||||
|
TimiException.requiredTrue(skuUnitKeySet.add(skuUnitKey),
|
||||||
"同一订单不能重复 SKU 和单位");
|
"同一订单不能重复 SKU 和单位");
|
||||||
TimiException.required(item.getQuantity(), "订单项数量不能为空");
|
TimiException.required(item.getQuantity(), "订单项数量不能为空");
|
||||||
TimiException.requiredTrue(0 < item.getQuantity().signum(), "订单项数量必须大于 0");
|
TimiException.requiredTrue(0 < item.getQuantity().signum(), "订单项数量必须大于 0");
|
||||||
@@ -510,11 +513,14 @@ public class GaoSalesOrderServiceImplement extends AbstractEntityService<GaoSale
|
|||||||
List<GaoSalesOrderItem> existingItemList = itemMapper.selectBySalesOrderId(existing.getId());
|
List<GaoSalesOrderItem> existingItemList = itemMapper.selectBySalesOrderId(existing.getId());
|
||||||
TimiException.requiredTrue(existingItemList.size() == requestItemList.size(), "requestNo 对应订单内容不一致");
|
TimiException.requiredTrue(existingItemList.size() == requestItemList.size(), "requestNo 对应订单内容不一致");
|
||||||
Map<String, GaoSalesOrderItem> existingItemMap = existingItemList.stream()
|
Map<String, GaoSalesOrderItem> existingItemMap = existingItemList.stream()
|
||||||
.collect(java.util.stream.Collectors.toMap(item -> item.getSkuId() + "|" + item.getSkuUnitId(), java.util.function.Function.identity()));
|
.collect(java.util.stream.Collectors.toMap(item -> item.getSkuId() + "|" + item.getSkuUnitId() + "|" + Boolean.TRUE.equals(item.getGifted()),
|
||||||
|
java.util.function.Function.identity()));
|
||||||
for (GaoSalesOrderItem requestItem : requestItemList) {
|
for (GaoSalesOrderItem requestItem : requestItemList) {
|
||||||
GaoSalesOrderItem existingItem = existingItemMap.get(requestItem.getSkuId() + "|" + requestItem.getSkuUnitId());
|
GaoSalesOrderItem existingItem = existingItemMap.get(requestItem.getSkuId() + "|" + requestItem.getSkuUnitId() + "|"
|
||||||
|
+ Boolean.TRUE.equals(requestItem.getGifted()));
|
||||||
TimiException.required(existingItem, "requestNo 对应订单内容不一致");
|
TimiException.required(existingItem, "requestNo 对应订单内容不一致");
|
||||||
TimiException.requiredTrue(existingItem.getItemType() == GaoSalesOrderItem.ItemType.PACKAGE_ENTITLEMENT
|
TimiException.requiredTrue(existingItem.getItemType() == GaoSalesOrderItem.ItemType.PACKAGE_ENTITLEMENT
|
||||||
|
&& Boolean.TRUE.equals(existingItem.getGifted()) == Boolean.TRUE.equals(requestItem.getGifted())
|
||||||
&& existingItem.getQuantity().compareTo(requestItem.getQuantity()) == 0
|
&& existingItem.getQuantity().compareTo(requestItem.getQuantity()) == 0
|
||||||
&& existingItem.getSort().equals(requestItem.getSort())
|
&& existingItem.getSort().equals(requestItem.getSort())
|
||||||
&& sameText(existingItem.getRemark(), requestItem.getRemark()), "requestNo 对应订单内容不一致");
|
&& sameText(existingItem.getRemark(), requestItem.getRemark()), "requestNo 对应订单内容不一致");
|
||||||
@@ -562,6 +568,37 @@ public class GaoSalesOrderServiceImplement extends AbstractEntityService<GaoSale
|
|||||||
item.setRemainingBaseQuantity(baseQuantity.subtract(fulfilledBaseQuantity));
|
item.setRemainingBaseQuantity(baseQuantity.subtract(fulfilledBaseQuantity));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// 填充订单项数量展示所需的 SKU 信息
|
||||||
|
///
|
||||||
|
/// @param itemList 订单项列表
|
||||||
|
private void fillItemDisplayInfo(List<GaoSalesOrderItem> itemList) {
|
||||||
|
if (itemList == null || itemList.isEmpty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
List<String> skuIdList = itemList.stream()
|
||||||
|
.map(GaoSalesOrderItem::getSkuId)
|
||||||
|
.filter(value -> value != null && !value.isBlank())
|
||||||
|
.distinct()
|
||||||
|
.toList();
|
||||||
|
if (skuIdList.isEmpty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Map<String, GaoProductSku> skuMap = skuService.listByIdList(skuIdList).stream()
|
||||||
|
.collect(java.util.stream.Collectors.toMap(GaoProductSku::getId, java.util.function.Function.identity()));
|
||||||
|
for (GaoSalesOrderItem item : itemList) {
|
||||||
|
GaoProductSku sku = skuMap.get(item.getSkuId());
|
||||||
|
if (sku == null) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
item.setAllowDecimalQuantity(sku.getAllowDecimalQuantity());
|
||||||
|
item.setBaseUnitName(sku.getUnitList().stream()
|
||||||
|
.filter(unit -> Boolean.TRUE.equals(unit.getIsBase()))
|
||||||
|
.map(GaoProductSkuUnit::getName)
|
||||||
|
.findFirst()
|
||||||
|
.orElse(null));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void fillItemAttachments(List<GaoSalesOrderItem> itemList) {
|
private void fillItemAttachments(List<GaoSalesOrderItem> itemList) {
|
||||||
if (itemList == null || itemList.isEmpty()) {
|
if (itemList == null || itemList.isEmpty()) {
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -17,6 +17,9 @@ public class GaoCustomerPackagePurchaseItem {
|
|||||||
/// SKU 单位 ID
|
/// SKU 单位 ID
|
||||||
private String skuUnitId;
|
private String skuUnitId;
|
||||||
|
|
||||||
|
/// true 表示请求将该明细作为赠送权益创建
|
||||||
|
private Boolean gifted;
|
||||||
|
|
||||||
/// 产品名称快照,由后端生成
|
/// 产品名称快照,由后端生成
|
||||||
private String productNameSnapshot;
|
private String productNameSnapshot;
|
||||||
|
|
||||||
|
|||||||
@@ -28,6 +28,9 @@ public class GaoProductStockChangeRequest {
|
|||||||
/// 业务数量
|
/// 业务数量
|
||||||
private BigDecimal quantity;
|
private BigDecimal quantity;
|
||||||
|
|
||||||
|
/// 库存发生时间,毫秒时间戳
|
||||||
|
private Long occurredAt;
|
||||||
|
|
||||||
/// 备注
|
/// 备注
|
||||||
private String remark;
|
private String remark;
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,66 @@
|
|||||||
|
package com.imyeyu.api.modules.system.audit;
|
||||||
|
|
||||||
|
import com.imyeyu.api.modules.system.entity.Logger;
|
||||||
|
|
||||||
|
/// 操作审计编码
|
||||||
|
///
|
||||||
|
/// @author Codex
|
||||||
|
/// @since 2026-09-09
|
||||||
|
public enum AuditOperation {
|
||||||
|
|
||||||
|
GAO_CUSTOMER_PACKAGE_PURCHASE(Logger.Module.GAO, "GAO_CUSTOMER_PACKAGE_PURCHASE"),
|
||||||
|
GAO_CUSTOMER_PACKAGE_CANCEL(Logger.Module.GAO, "GAO_CUSTOMER_PACKAGE_CANCEL"),
|
||||||
|
GAO_SALES_ORDER_PAYMENT_RECEIVE(Logger.Module.GAO, "GAO_SALES_ORDER_PAYMENT_RECEIVE"),
|
||||||
|
GAO_SALES_ORDER_PAYMENT_VERIFY(Logger.Module.GAO, "GAO_SALES_ORDER_PAYMENT_VERIFY"),
|
||||||
|
GAO_SALES_ORDER_REFUND(Logger.Module.GAO, "GAO_SALES_ORDER_REFUND"),
|
||||||
|
GAO_SALES_ORDER_CONFIRM_NO_REFUND(Logger.Module.GAO, "GAO_SALES_ORDER_CONFIRM_NO_REFUND"),
|
||||||
|
GAO_SALES_ORDER_FUND_REVOKE(Logger.Module.GAO, "GAO_SALES_ORDER_FUND_REVOKE"),
|
||||||
|
GAO_ORDER_FULFILLMENT_CREATE(Logger.Module.GAO, "GAO_ORDER_FULFILLMENT_CREATE"),
|
||||||
|
GAO_ORDER_FULFILLMENT_PREPARE_STOCK(Logger.Module.GAO, "GAO_ORDER_FULFILLMENT_PREPARE_STOCK"),
|
||||||
|
GAO_ORDER_FULFILLMENT_VERIFY(Logger.Module.GAO, "GAO_ORDER_FULFILLMENT_VERIFY"),
|
||||||
|
GAO_ORDER_FULFILLMENT_REJECT(Logger.Module.GAO, "GAO_ORDER_FULFILLMENT_REJECT"),
|
||||||
|
GAO_ORDER_FULFILLMENT_CANCEL(Logger.Module.GAO, "GAO_ORDER_FULFILLMENT_CANCEL"),
|
||||||
|
GAO_ORDER_FULFILLMENT_REVOKE(Logger.Module.GAO, "GAO_ORDER_FULFILLMENT_REVOKE"),
|
||||||
|
GAO_PACKAGE_CONFIG_CREATE(Logger.Module.GAO, "GAO_PACKAGE_CONFIG_CREATE"),
|
||||||
|
GAO_PACKAGE_CONFIG_UPDATE(Logger.Module.GAO, "GAO_PACKAGE_CONFIG_UPDATE"),
|
||||||
|
GAO_PACKAGE_CONFIG_DELETE(Logger.Module.GAO, "GAO_PACKAGE_CONFIG_DELETE"),
|
||||||
|
GAO_PRODUCT_CATEGORY_SORT(Logger.Module.GAO, "GAO_PRODUCT_CATEGORY_SORT"),
|
||||||
|
GAO_PRODUCT_CATEGORY_CREATE(Logger.Module.GAO, "GAO_PRODUCT_CATEGORY_CREATE"),
|
||||||
|
GAO_PRODUCT_CATEGORY_UPDATE(Logger.Module.GAO, "GAO_PRODUCT_CATEGORY_UPDATE"),
|
||||||
|
GAO_PRODUCT_CATEGORY_DISABLE(Logger.Module.GAO, "GAO_PRODUCT_CATEGORY_DISABLE"),
|
||||||
|
GAO_PRODUCT_CREATE(Logger.Module.GAO, "GAO_PRODUCT_CREATE"),
|
||||||
|
GAO_PRODUCT_UPDATE(Logger.Module.GAO, "GAO_PRODUCT_UPDATE"),
|
||||||
|
GAO_PRODUCT_DISABLE(Logger.Module.GAO, "GAO_PRODUCT_DISABLE"),
|
||||||
|
GAO_PRODUCT_STOCK_INITIAL_IN(Logger.Module.GAO, "GAO_PRODUCT_STOCK_INITIAL_IN"),
|
||||||
|
GAO_PRODUCT_STOCK_MANUAL_IN(Logger.Module.GAO, "GAO_PRODUCT_STOCK_MANUAL_IN"),
|
||||||
|
GAO_PRODUCT_STOCK_MANUAL_OUT(Logger.Module.GAO, "GAO_PRODUCT_STOCK_MANUAL_OUT"),
|
||||||
|
GAO_PRODUCT_STOCK_MANUAL_REVOKE(Logger.Module.GAO, "GAO_PRODUCT_STOCK_MANUAL_REVOKE"),
|
||||||
|
GAO_PRODUCT_STOCK_STOCKTAKE_GAIN(Logger.Module.GAO, "GAO_PRODUCT_STOCK_STOCKTAKE_GAIN"),
|
||||||
|
GAO_PRODUCT_STOCK_STOCKTAKE_LOSS(Logger.Module.GAO, "GAO_PRODUCT_STOCK_STOCKTAKE_LOSS"),
|
||||||
|
GAO_SALES_ORDER_DIRECT_PRODUCT_CREATE(Logger.Module.GAO, "GAO_SALES_ORDER_DIRECT_PRODUCT_CREATE"),
|
||||||
|
GAO_SALES_ORDER_UPDATE(Logger.Module.GAO, "GAO_SALES_ORDER_UPDATE"),
|
||||||
|
GAO_SALES_ORDER_CANCEL(Logger.Module.GAO, "GAO_SALES_ORDER_CANCEL");
|
||||||
|
|
||||||
|
private final Logger.Module module;
|
||||||
|
|
||||||
|
private final String code;
|
||||||
|
|
||||||
|
AuditOperation(Logger.Module module, String code) {
|
||||||
|
this.module = module;
|
||||||
|
this.code = code;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 获取日志模块
|
||||||
|
///
|
||||||
|
/// @return 日志模块
|
||||||
|
public Logger.Module getModule() {
|
||||||
|
return module;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 获取操作编码
|
||||||
|
///
|
||||||
|
/// @return 操作编码
|
||||||
|
public String getCode() {
|
||||||
|
return code;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,128 @@
|
|||||||
|
package com.imyeyu.api.modules.system.audit;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.databind.JsonNode;
|
||||||
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
|
import com.fasterxml.jackson.databind.node.ObjectNode;
|
||||||
|
import com.imyeyu.spring.entity.IDEntity;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import java.lang.reflect.Array;
|
||||||
|
import java.util.Locale;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
/// 操作审计参数和结果序列化器
|
||||||
|
///
|
||||||
|
/// @author Codex
|
||||||
|
/// @since 2026-09-09
|
||||||
|
@Component
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public class AuditPayloadSerializer {
|
||||||
|
|
||||||
|
private static final int MAX_LENGTH = 32 * 1024;
|
||||||
|
|
||||||
|
private static final Set<String> SECRET_FIELD_SET = Set.of(
|
||||||
|
"password",
|
||||||
|
"passwordconfirm",
|
||||||
|
"token",
|
||||||
|
"accesstoken",
|
||||||
|
"refreshtoken",
|
||||||
|
"secret",
|
||||||
|
"credential",
|
||||||
|
"authorization"
|
||||||
|
);
|
||||||
|
|
||||||
|
private final ObjectMapper objectMapper;
|
||||||
|
|
||||||
|
/// 序列化方法参数
|
||||||
|
///
|
||||||
|
/// @param arguments 方法参数
|
||||||
|
/// @return 脱敏后的参数 JSON
|
||||||
|
public String serializeArguments(Object[] arguments) {
|
||||||
|
if (arguments == null || 0 == arguments.length) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return serialize(arguments.length == 1 ? arguments[0] : arguments);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 序列化业务结果
|
||||||
|
///
|
||||||
|
/// @param result 方法返回值
|
||||||
|
/// @param arguments 方法参数
|
||||||
|
/// @return 结果摘要
|
||||||
|
public String serializeResult(Object result, Object[] arguments) {
|
||||||
|
if (result instanceof IDEntity<?> entity && entity.getId() != null) {
|
||||||
|
return truncate(String.valueOf(entity.getId()));
|
||||||
|
}
|
||||||
|
if (result != null) {
|
||||||
|
return summarize(result);
|
||||||
|
}
|
||||||
|
if (arguments != null) {
|
||||||
|
for (Object argument : arguments) {
|
||||||
|
if (argument instanceof IDEntity<?> entity && entity.getId() != null) {
|
||||||
|
return truncate(String.valueOf(entity.getId()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (1 == arguments.length && arguments[0] instanceof CharSequence value) {
|
||||||
|
return truncate(value.toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private String serialize(Object value) {
|
||||||
|
try {
|
||||||
|
JsonNode node = objectMapper.valueToTree(value);
|
||||||
|
mask(node);
|
||||||
|
return truncate(objectMapper.writeValueAsString(node));
|
||||||
|
} catch (Exception e) {
|
||||||
|
return value == null ? null : truncate(value.getClass().getName());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void mask(JsonNode node) {
|
||||||
|
if (node == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (node.isObject()) {
|
||||||
|
ObjectNode objectNode = (ObjectNode) node;
|
||||||
|
objectNode.fieldNames().forEachRemaining(fieldName -> {
|
||||||
|
JsonNode field = objectNode.get(fieldName);
|
||||||
|
if (SECRET_FIELD_SET.contains(fieldName.toLowerCase(Locale.ROOT))) {
|
||||||
|
objectNode.put(fieldName, "***");
|
||||||
|
} else {
|
||||||
|
mask(field);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} else if (node.isArray()) {
|
||||||
|
node.forEach(this::mask);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private String summarize(Object value) {
|
||||||
|
if (value instanceof CharSequence || value instanceof Number || value instanceof Boolean || value instanceof Enum<?>) {
|
||||||
|
return truncate(String.valueOf(value));
|
||||||
|
}
|
||||||
|
if (value instanceof Iterable<?> iterable) {
|
||||||
|
int size = 0;
|
||||||
|
for (Object ignored : iterable) {
|
||||||
|
size++;
|
||||||
|
}
|
||||||
|
return "%s[%s]".formatted(value.getClass().getSimpleName(), size);
|
||||||
|
}
|
||||||
|
if (value instanceof java.util.Map<?, ?> map) {
|
||||||
|
return "%s[%s]".formatted(value.getClass().getSimpleName(), map.size());
|
||||||
|
}
|
||||||
|
if (value.getClass().isArray()) {
|
||||||
|
return "%s[%s]".formatted(value.getClass().getComponentType().getSimpleName(), Array.getLength(value));
|
||||||
|
}
|
||||||
|
return value.getClass().getSimpleName();
|
||||||
|
}
|
||||||
|
|
||||||
|
private String truncate(String value) {
|
||||||
|
if (value == null || value.length() <= MAX_LENGTH) {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
return value.substring(0, MAX_LENGTH) + "...";
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
package com.imyeyu.api.modules.system.audit;
|
||||||
|
|
||||||
|
import com.imyeyu.api.modules.system.entity.Logger;
|
||||||
|
|
||||||
|
/// 操作审计记录器
|
||||||
|
///
|
||||||
|
/// 业务切面只依赖该写入端口,不直接依赖日志查询服务
|
||||||
|
///
|
||||||
|
/// @author Codex
|
||||||
|
/// @since 2026-09-09
|
||||||
|
public interface AuditRecorder {
|
||||||
|
|
||||||
|
/// 记录操作审计
|
||||||
|
///
|
||||||
|
/// @param logger 审计记录
|
||||||
|
void record(Logger logger);
|
||||||
|
}
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
package com.imyeyu.api.modules.system.audit;
|
||||||
|
|
||||||
|
import java.lang.annotation.ElementType;
|
||||||
|
import java.lang.annotation.Retention;
|
||||||
|
import java.lang.annotation.RetentionPolicy;
|
||||||
|
import java.lang.annotation.Target;
|
||||||
|
|
||||||
|
/// 标记需要记录操作审计的应用服务方法
|
||||||
|
///
|
||||||
|
/// 只应标记对外的业务操作入口,不要标记被入口调用的内部方法
|
||||||
|
///
|
||||||
|
/// @author Codex
|
||||||
|
/// @since 2026-09-09
|
||||||
|
@Target(ElementType.METHOD)
|
||||||
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
|
public @interface OperationAudit {
|
||||||
|
|
||||||
|
/// 操作编码
|
||||||
|
///
|
||||||
|
/// @return 操作编码
|
||||||
|
AuditOperation value();
|
||||||
|
}
|
||||||
@@ -0,0 +1,90 @@
|
|||||||
|
package com.imyeyu.api.modules.system.audit;
|
||||||
|
|
||||||
|
import com.imyeyu.api.modules.system.entity.Logger;
|
||||||
|
import com.imyeyu.java.bean.timi.TimiException;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.aspectj.lang.ProceedingJoinPoint;
|
||||||
|
import org.aspectj.lang.annotation.Around;
|
||||||
|
import org.aspectj.lang.annotation.Aspect;
|
||||||
|
import org.springframework.core.Ordered;
|
||||||
|
import org.springframework.core.annotation.Order;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
/// 操作审计切面
|
||||||
|
///
|
||||||
|
/// 该切面放在事务拦截器外层,确保成功日志只在事务提交成功后生成
|
||||||
|
///
|
||||||
|
/// @author Codex
|
||||||
|
/// @since 2026-09-09
|
||||||
|
@Aspect
|
||||||
|
@Component
|
||||||
|
@Order(Ordered.LOWEST_PRECEDENCE - 100)
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
@Slf4j
|
||||||
|
public class OperationAuditAspect {
|
||||||
|
|
||||||
|
private final AuditRecorder auditRecorder;
|
||||||
|
|
||||||
|
private final AuditPayloadSerializer payloadSerializer;
|
||||||
|
|
||||||
|
/// 执行并记录操作审计
|
||||||
|
///
|
||||||
|
/// @param joinPoint 连接点
|
||||||
|
/// @param operationAudit 审计配置
|
||||||
|
/// @return 业务返回值
|
||||||
|
/// @throws Throwable 业务异常
|
||||||
|
@Around("@annotation(operationAudit)")
|
||||||
|
public Object around(ProceedingJoinPoint joinPoint, OperationAudit operationAudit) throws Throwable {
|
||||||
|
AuditOperation operation = operationAudit.value();
|
||||||
|
Object[] arguments = joinPoint.getArgs();
|
||||||
|
Logger logger = new Logger(operation.getModule(), operation.getCode());
|
||||||
|
logger.setContent(payloadSerializer.serializeArguments(arguments));
|
||||||
|
long startNanos = System.nanoTime();
|
||||||
|
try {
|
||||||
|
Object result = joinPoint.proceed();
|
||||||
|
logger.setLevel(Logger.Level.INFO);
|
||||||
|
logger.setResult(payloadSerializer.serializeResult(result, arguments));
|
||||||
|
logger.setDuration(duration(startNanos));
|
||||||
|
record(logger);
|
||||||
|
return result;
|
||||||
|
} catch (TimiException e) {
|
||||||
|
logger.setLevel(Logger.Level.WARN);
|
||||||
|
logger.setException(e.getMessage());
|
||||||
|
logger.setDuration(duration(startNanos));
|
||||||
|
record(logger);
|
||||||
|
throw e;
|
||||||
|
} catch (Throwable e) {
|
||||||
|
logger.setLevel(Logger.Level.ERROR);
|
||||||
|
logger.setException(serializeThrowable(e));
|
||||||
|
logger.setDuration(duration(startNanos));
|
||||||
|
log.error("业务操作失败: {}", operation.getCode(), e);
|
||||||
|
record(logger);
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void record(Logger logger) {
|
||||||
|
try {
|
||||||
|
auditRecorder.record(logger);
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("记录操作审计失败: {}", logger.getOperation(), e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private int duration(long startNanos) {
|
||||||
|
long millis = (System.nanoTime() - startNanos) / 1_000_000L;
|
||||||
|
if (Integer.MAX_VALUE < millis) {
|
||||||
|
return Integer.MAX_VALUE;
|
||||||
|
}
|
||||||
|
return (int) Math.max(0L, millis);
|
||||||
|
}
|
||||||
|
|
||||||
|
private String serializeThrowable(Throwable throwable) {
|
||||||
|
java.io.StringWriter stringWriter = new java.io.StringWriter();
|
||||||
|
try (java.io.PrintWriter printWriter = new java.io.PrintWriter(stringWriter)) {
|
||||||
|
throwable.printStackTrace(printWriter);
|
||||||
|
}
|
||||||
|
return stringWriter.toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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) {
|
||||||
|
|||||||
+19
-37
@@ -1,37 +1,41 @@
|
|||||||
package com.imyeyu.api.modules.system.service.implement;
|
package com.imyeyu.api.modules.system.service.implement;
|
||||||
|
|
||||||
import com.imyeyu.api.modules.system.entity.Logger;
|
import com.imyeyu.api.modules.system.entity.Logger;
|
||||||
|
import com.imyeyu.api.modules.system.audit.AuditRecorder;
|
||||||
import com.imyeyu.api.modules.system.mapper.LoggerMapper;
|
import com.imyeyu.api.modules.system.mapper.LoggerMapper;
|
||||||
import com.imyeyu.api.modules.system.service.LoggerService;
|
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 org.springframework.beans.factory.annotation.Qualifier;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
import java.util.function.Supplier;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 日志服务实现
|
* 日志服务实现
|
||||||
*
|
*
|
||||||
* @author 夜雨
|
* @author 夜雨
|
||||||
* @since 2026-05-13 14:46
|
* @since 2026-05-13 14:46
|
||||||
*/
|
*/
|
||||||
@Slf4j
|
|
||||||
@Service
|
@Service
|
||||||
@RequiredArgsConstructor
|
public class LoggerServiceImplement extends AbstractEntityService<Logger, String> implements LoggerService, AuditRecorder {
|
||||||
public class LoggerServiceImplement extends AbstractEntityService<Logger, String> implements LoggerService {
|
|
||||||
|
|
||||||
private final UserLoginService userLoginService;
|
private final UserLoginService userLoginService;
|
||||||
|
|
||||||
private final LoggerMapper mapper;
|
private final LoggerMapper mapper;
|
||||||
|
|
||||||
|
private final ThreadPoolTaskExecutor auditTaskExecutor;
|
||||||
|
|
||||||
|
public LoggerServiceImplement(UserLoginService userLoginService, LoggerMapper mapper,
|
||||||
|
@Qualifier("auditTaskExecutor") ThreadPoolTaskExecutor auditTaskExecutor) {
|
||||||
|
this.userLoginService = userLoginService;
|
||||||
|
this.mapper = mapper;
|
||||||
|
this.auditTaskExecutor = auditTaskExecutor;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected BaseMapper<Logger, String> mapper() {
|
protected BaseMapper<Logger, String> mapper() {
|
||||||
return mapper;
|
return mapper;
|
||||||
@@ -39,9 +43,13 @@ public class LoggerServiceImplement extends AbstractEntityService<Logger, String
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void create(Logger logger) {
|
public void create(Logger logger) {
|
||||||
// 默认异步
|
|
||||||
fillContext(logger);
|
fillContext(logger);
|
||||||
Thread.startVirtualThread(() -> createSync(logger));
|
auditTaskExecutor.execute(() -> createSync(logger));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void record(Logger logger) {
|
||||||
|
create(logger);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -50,32 +58,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);
|
||||||
|
|||||||
@@ -0,0 +1,5 @@
|
|||||||
|
ALTER TABLE `gao_sales_order_item`
|
||||||
|
ADD COLUMN `gifted` TINYINT(1) NOT NULL DEFAULT 0 COMMENT 'true 为赠送权益' AFTER `item_type`,
|
||||||
|
DROP KEY `uk_gao_sales_order_item_sku_unit`,
|
||||||
|
ADD UNIQUE KEY `uk_gao_sales_order_item_sku_unit_gifted` (`sales_order_id`, `sku_id`, `sku_unit_id`, `gifted`),
|
||||||
|
ADD KEY `idx_gao_sales_order_item_order_gifted` (`sales_order_id`, `gifted`, `sort`, `created_at`);
|
||||||
@@ -1,6 +1,11 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8" ?>
|
<?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" >
|
<!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.GaoProductSkuMapper">
|
<mapper namespace="com.imyeyu.api.modules.gao.mapper.GaoProductSkuMapper">
|
||||||
|
<select id="selectByIdList" resultType="com.imyeyu.api.modules.gao.entity.GaoProductSku">
|
||||||
|
SELECT * FROM `gao_product_sku` 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>
|
||||||
|
ORDER BY `id`
|
||||||
|
</select>
|
||||||
<select id="selectByProductId" resultType="com.imyeyu.api.modules.gao.entity.GaoProductSku">
|
<select id="selectByProductId" resultType="com.imyeyu.api.modules.gao.entity.GaoProductSku">
|
||||||
SELECT * FROM `gao_product_sku` WHERE `product_id` = #{productId} AND `deleted_at` IS NULL ORDER BY `sort`, `created_at`
|
SELECT * FROM `gao_product_sku` WHERE `product_id` = #{productId} AND `deleted_at` IS NULL ORDER BY `sort`, `created_at`
|
||||||
</select>
|
</select>
|
||||||
|
|||||||
Reference in New Issue
Block a user