Compare commits
10 Commits
c7684e3199
...
7b9f1fd8c2
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7b9f1fd8c2 | ||
|
|
d01c8a4c6a | ||
|
|
9f83103189 | ||
|
|
60b4b0bd49 | ||
|
|
0faa7f2988 | ||
|
|
cf25e6b116 | ||
|
|
2706bfb3b6 | ||
|
|
2a820f113d | ||
|
|
e6ad24e015 | ||
|
|
4f4b2f9027 |
37
README.md
37
README.md
@@ -134,6 +134,43 @@ mvn spotless:apply compile
|
|||||||
mvn spotless:apply checkstyle:check compile
|
mvn spotless:apply checkstyle:check compile
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## API 集成测试指南
|
||||||
|
|
||||||
|
在 `play-admin` 模块内提供了基于 `apitest` Profile 的端到端测试套件。为了稳定跑通所有 API 场景,请按以下步骤准备环境:
|
||||||
|
|
||||||
|
1. **准备数据库**
|
||||||
|
默认连接信息为 `jdbc:mysql://127.0.0.1:33306/peipei_apitest`,账号密码均为 `apitest`。可通过以下命令初始化:
|
||||||
|
|
||||||
|
```sql
|
||||||
|
CREATE DATABASE IF NOT EXISTS peipei_apitest CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
|
||||||
|
CREATE USER IF NOT EXISTS 'apitest'@'%' IDENTIFIED BY 'apitest';
|
||||||
|
GRANT ALL PRIVILEGES ON peipei_apitest.* TO 'apitest'@'%';
|
||||||
|
FLUSH PRIVILEGES;
|
||||||
|
```
|
||||||
|
|
||||||
|
若端口或凭证不同,请同步修改 `play-admin/src/main/resources/application-apitest.yml`。
|
||||||
|
|
||||||
|
2. **准备 Redis(必需)**
|
||||||
|
测试依赖 Redis 记录幂等与缓存信息。可以执行 `docker compose up -d redis`(路径:`docker/docker-compose.yml`)快速启一个实例,默认映射端口为 `36379`。
|
||||||
|
|
||||||
|
3. **执行测试**
|
||||||
|
在仓库根目录运行:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
mvn -pl play-admin -am test
|
||||||
|
```
|
||||||
|
|
||||||
|
如需探查单个用例,可指定测试类:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
mvn -pl play-admin -Dtest=WxCustomRandomOrderApiTest test
|
||||||
|
```
|
||||||
|
|
||||||
|
4. **自动数据播种**
|
||||||
|
激活 `apitest` Profile 时,`ApiTestDataSeeder` 会自动创建默认租户、顾客、店员、商品、礼物、优惠券等基线数据,并在每次启动时重置关键计数,因此多次执行结果一致。如果需要彻底清理,可直接清空数据库后重新运行测试。
|
||||||
|
|
||||||
|
按照上述流程,即可可靠地复现订单、优惠券、礼物等核心链路的 API 行为。
|
||||||
|
|
||||||
## 部署说明
|
## 部署说明
|
||||||
|
|
||||||
### Docker 构建和推送
|
### Docker 构建和推送
|
||||||
|
|||||||
@@ -1,9 +1,20 @@
|
|||||||
version: "3.8"
|
|
||||||
|
|
||||||
services:
|
services:
|
||||||
|
redis:
|
||||||
|
image: redis:7-alpine
|
||||||
|
container_name: peipei-redis
|
||||||
|
ports:
|
||||||
|
- "36379:6379"
|
||||||
|
command: ["redis-server", "--save", "", "--appendonly", "no"]
|
||||||
|
restart: unless-stopped
|
||||||
|
networks:
|
||||||
|
- peipei-network
|
||||||
|
|
||||||
peipei-backend:
|
peipei-backend:
|
||||||
image: docker-registry.julyhaven.com/peipei/backend:latest
|
image: docker-registry.julyhaven.com/peipei/backend:latest
|
||||||
container_name: peipei-backend
|
container_name: peipei-backend
|
||||||
|
platform: linux/amd64
|
||||||
|
depends_on:
|
||||||
|
- redis
|
||||||
ports:
|
ports:
|
||||||
- "7003:7002"
|
- "7003:7002"
|
||||||
environment:
|
environment:
|
||||||
|
|||||||
@@ -7,13 +7,19 @@ import com.starry.admin.modules.clerk.module.entity.PlayClerkUserInfoEntity;
|
|||||||
import com.starry.admin.modules.clerk.service.IPlayClerkCommodityService;
|
import com.starry.admin.modules.clerk.service.IPlayClerkCommodityService;
|
||||||
import com.starry.admin.modules.clerk.service.IPlayClerkLevelInfoService;
|
import com.starry.admin.modules.clerk.service.IPlayClerkLevelInfoService;
|
||||||
import com.starry.admin.modules.clerk.service.IPlayClerkUserInfoService;
|
import com.starry.admin.modules.clerk.service.IPlayClerkUserInfoService;
|
||||||
|
import com.starry.admin.modules.custom.mapper.PlayCustomGiftInfoMapper;
|
||||||
|
import com.starry.admin.modules.custom.module.entity.PlayCustomGiftInfoEntity;
|
||||||
import com.starry.admin.modules.custom.module.entity.PlayCustomUserInfoEntity;
|
import com.starry.admin.modules.custom.module.entity.PlayCustomUserInfoEntity;
|
||||||
|
import com.starry.admin.modules.custom.service.IPlayCustomGiftInfoService;
|
||||||
import com.starry.admin.modules.custom.service.IPlayCustomUserInfoService;
|
import com.starry.admin.modules.custom.service.IPlayCustomUserInfoService;
|
||||||
import com.starry.admin.modules.personnel.module.entity.PlayPersonnelGroupInfoEntity;
|
import com.starry.admin.modules.personnel.module.entity.PlayPersonnelGroupInfoEntity;
|
||||||
import com.starry.admin.modules.personnel.service.IPlayPersonnelGroupInfoService;
|
import com.starry.admin.modules.personnel.service.IPlayPersonnelGroupInfoService;
|
||||||
|
import com.starry.admin.modules.shop.mapper.PlayClerkGiftInfoMapper;
|
||||||
|
import com.starry.admin.modules.shop.module.entity.PlayClerkGiftInfoEntity;
|
||||||
import com.starry.admin.modules.shop.module.entity.PlayCommodityAndLevelInfoEntity;
|
import com.starry.admin.modules.shop.module.entity.PlayCommodityAndLevelInfoEntity;
|
||||||
import com.starry.admin.modules.shop.module.entity.PlayCommodityInfoEntity;
|
import com.starry.admin.modules.shop.module.entity.PlayCommodityInfoEntity;
|
||||||
import com.starry.admin.modules.shop.module.entity.PlayGiftInfoEntity;
|
import com.starry.admin.modules.shop.module.entity.PlayGiftInfoEntity;
|
||||||
|
import com.starry.admin.modules.shop.service.IPlayClerkGiftInfoService;
|
||||||
import com.starry.admin.modules.shop.service.IPlayCommodityAndLevelInfoService;
|
import com.starry.admin.modules.shop.service.IPlayCommodityAndLevelInfoService;
|
||||||
import com.starry.admin.modules.shop.service.IPlayCommodityInfoService;
|
import com.starry.admin.modules.shop.service.IPlayCommodityInfoService;
|
||||||
import com.starry.admin.modules.shop.service.IPlayGiftInfoService;
|
import com.starry.admin.modules.shop.service.IPlayGiftInfoService;
|
||||||
@@ -78,7 +84,11 @@ public class ApiTestDataSeeder implements CommandLineRunner {
|
|||||||
private final IPlayCommodityAndLevelInfoService commodityAndLevelInfoService;
|
private final IPlayCommodityAndLevelInfoService commodityAndLevelInfoService;
|
||||||
private final IPlayGiftInfoService giftInfoService;
|
private final IPlayGiftInfoService giftInfoService;
|
||||||
private final IPlayClerkCommodityService clerkCommodityService;
|
private final IPlayClerkCommodityService clerkCommodityService;
|
||||||
|
private final IPlayClerkGiftInfoService playClerkGiftInfoService;
|
||||||
private final IPlayCustomUserInfoService customUserInfoService;
|
private final IPlayCustomUserInfoService customUserInfoService;
|
||||||
|
private final IPlayCustomGiftInfoService playCustomGiftInfoService;
|
||||||
|
private final PlayClerkGiftInfoMapper playClerkGiftInfoMapper;
|
||||||
|
private final PlayCustomGiftInfoMapper playCustomGiftInfoMapper;
|
||||||
private final PasswordEncoder passwordEncoder;
|
private final PasswordEncoder passwordEncoder;
|
||||||
private final WxTokenService wxTokenService;
|
private final WxTokenService wxTokenService;
|
||||||
|
|
||||||
@@ -93,7 +103,11 @@ public class ApiTestDataSeeder implements CommandLineRunner {
|
|||||||
IPlayCommodityAndLevelInfoService commodityAndLevelInfoService,
|
IPlayCommodityAndLevelInfoService commodityAndLevelInfoService,
|
||||||
IPlayGiftInfoService giftInfoService,
|
IPlayGiftInfoService giftInfoService,
|
||||||
IPlayClerkCommodityService clerkCommodityService,
|
IPlayClerkCommodityService clerkCommodityService,
|
||||||
|
IPlayClerkGiftInfoService playClerkGiftInfoService,
|
||||||
IPlayCustomUserInfoService customUserInfoService,
|
IPlayCustomUserInfoService customUserInfoService,
|
||||||
|
IPlayCustomGiftInfoService playCustomGiftInfoService,
|
||||||
|
PlayClerkGiftInfoMapper playClerkGiftInfoMapper,
|
||||||
|
PlayCustomGiftInfoMapper playCustomGiftInfoMapper,
|
||||||
PasswordEncoder passwordEncoder,
|
PasswordEncoder passwordEncoder,
|
||||||
WxTokenService wxTokenService) {
|
WxTokenService wxTokenService) {
|
||||||
this.tenantPackageService = tenantPackageService;
|
this.tenantPackageService = tenantPackageService;
|
||||||
@@ -106,7 +120,11 @@ public class ApiTestDataSeeder implements CommandLineRunner {
|
|||||||
this.commodityAndLevelInfoService = commodityAndLevelInfoService;
|
this.commodityAndLevelInfoService = commodityAndLevelInfoService;
|
||||||
this.giftInfoService = giftInfoService;
|
this.giftInfoService = giftInfoService;
|
||||||
this.clerkCommodityService = clerkCommodityService;
|
this.clerkCommodityService = clerkCommodityService;
|
||||||
|
this.playClerkGiftInfoService = playClerkGiftInfoService;
|
||||||
this.customUserInfoService = customUserInfoService;
|
this.customUserInfoService = customUserInfoService;
|
||||||
|
this.playCustomGiftInfoService = playCustomGiftInfoService;
|
||||||
|
this.playClerkGiftInfoMapper = playClerkGiftInfoMapper;
|
||||||
|
this.playCustomGiftInfoMapper = playCustomGiftInfoMapper;
|
||||||
this.passwordEncoder = passwordEncoder;
|
this.passwordEncoder = passwordEncoder;
|
||||||
this.wxTokenService = wxTokenService;
|
this.wxTokenService = wxTokenService;
|
||||||
}
|
}
|
||||||
@@ -128,6 +146,7 @@ public class ApiTestDataSeeder implements CommandLineRunner {
|
|||||||
seedClerk();
|
seedClerk();
|
||||||
seedClerkCommodity();
|
seedClerkCommodity();
|
||||||
seedGift();
|
seedGift();
|
||||||
|
resetGiftCounters();
|
||||||
seedCustomer();
|
seedCustomer();
|
||||||
} finally {
|
} finally {
|
||||||
if (Objects.nonNull(originalTenant)) {
|
if (Objects.nonNull(originalTenant)) {
|
||||||
@@ -257,10 +276,53 @@ public class ApiTestDataSeeder implements CommandLineRunner {
|
|||||||
parent.setSort(1);
|
parent.setSort(1);
|
||||||
commodityInfoService.save(parent);
|
commodityInfoService.save(parent);
|
||||||
log.info("Inserted API test commodity parent {}", DEFAULT_COMMODITY_PARENT_ID);
|
log.info("Inserted API test commodity parent {}", DEFAULT_COMMODITY_PARENT_ID);
|
||||||
|
} else {
|
||||||
|
boolean parentNeedsUpdate = false;
|
||||||
|
if (!"00".equals(parent.getPId())) {
|
||||||
|
parent.setPId("00");
|
||||||
|
parentNeedsUpdate = true;
|
||||||
|
}
|
||||||
|
if (!"service-category".equals(parent.getItemType())) {
|
||||||
|
parent.setItemType("service-category");
|
||||||
|
parentNeedsUpdate = true;
|
||||||
|
}
|
||||||
|
if (!DEFAULT_TENANT_ID.equals(parent.getTenantId())) {
|
||||||
|
parent.setTenantId(DEFAULT_TENANT_ID);
|
||||||
|
parentNeedsUpdate = true;
|
||||||
|
}
|
||||||
|
if (!"1".equals(parent.getEnableStace())) {
|
||||||
|
parent.setEnableStace("1");
|
||||||
|
parentNeedsUpdate = true;
|
||||||
|
}
|
||||||
|
if (parentNeedsUpdate) {
|
||||||
|
commodityInfoService.updateById(parent);
|
||||||
|
log.info("Normalized API test commodity parent {}", DEFAULT_COMMODITY_PARENT_ID);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
PlayCommodityInfoEntity child = commodityInfoService.getById(DEFAULT_COMMODITY_ID);
|
PlayCommodityInfoEntity child = commodityInfoService.getById(DEFAULT_COMMODITY_ID);
|
||||||
if (child != null) {
|
if (child != null) {
|
||||||
|
boolean childNeedsUpdate = false;
|
||||||
|
if (!DEFAULT_COMMODITY_PARENT_ID.equals(child.getPId())) {
|
||||||
|
child.setPId(DEFAULT_COMMODITY_PARENT_ID);
|
||||||
|
childNeedsUpdate = true;
|
||||||
|
}
|
||||||
|
if (!"service".equals(child.getItemType())) {
|
||||||
|
child.setItemType("service");
|
||||||
|
childNeedsUpdate = true;
|
||||||
|
}
|
||||||
|
if (!DEFAULT_TENANT_ID.equals(child.getTenantId())) {
|
||||||
|
child.setTenantId(DEFAULT_TENANT_ID);
|
||||||
|
childNeedsUpdate = true;
|
||||||
|
}
|
||||||
|
if (!"1".equals(child.getEnableStace())) {
|
||||||
|
child.setEnableStace("1");
|
||||||
|
childNeedsUpdate = true;
|
||||||
|
}
|
||||||
|
if (childNeedsUpdate) {
|
||||||
|
commodityInfoService.updateById(child);
|
||||||
|
log.info("Normalized API test commodity {}", DEFAULT_COMMODITY_ID);
|
||||||
|
}
|
||||||
log.info("API test commodity {} already exists", DEFAULT_COMMODITY_ID);
|
log.info("API test commodity {} already exists", DEFAULT_COMMODITY_ID);
|
||||||
return child;
|
return child;
|
||||||
}
|
}
|
||||||
@@ -386,6 +448,38 @@ public class ApiTestDataSeeder implements CommandLineRunner {
|
|||||||
log.info("Inserted API test gift {}", DEFAULT_GIFT_ID);
|
log.info("Inserted API test gift {}", DEFAULT_GIFT_ID);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void resetGiftCounters() {
|
||||||
|
int customerReset = playCustomGiftInfoMapper.resetGiftCount(DEFAULT_TENANT_ID, DEFAULT_CUSTOMER_ID, DEFAULT_GIFT_ID);
|
||||||
|
if (customerReset == 0) {
|
||||||
|
PlayCustomGiftInfoEntity entity = new PlayCustomGiftInfoEntity();
|
||||||
|
entity.setId(IdUtils.getUuid());
|
||||||
|
entity.setTenantId(DEFAULT_TENANT_ID);
|
||||||
|
entity.setCustomId(DEFAULT_CUSTOMER_ID);
|
||||||
|
entity.setGiffId(DEFAULT_GIFT_ID);
|
||||||
|
entity.setGiffNumber(0L);
|
||||||
|
try {
|
||||||
|
playCustomGiftInfoService.save(entity);
|
||||||
|
} catch (org.springframework.dao.DuplicateKeyException duplicateKeyException) {
|
||||||
|
playCustomGiftInfoMapper.resetGiftCount(DEFAULT_TENANT_ID, DEFAULT_CUSTOMER_ID, DEFAULT_GIFT_ID);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int clerkReset = playClerkGiftInfoMapper.resetGiftCount(DEFAULT_TENANT_ID, DEFAULT_CLERK_ID, DEFAULT_GIFT_ID);
|
||||||
|
if (clerkReset == 0) {
|
||||||
|
PlayClerkGiftInfoEntity entity = new PlayClerkGiftInfoEntity();
|
||||||
|
entity.setId(IdUtils.getUuid());
|
||||||
|
entity.setTenantId(DEFAULT_TENANT_ID);
|
||||||
|
entity.setClerkId(DEFAULT_CLERK_ID);
|
||||||
|
entity.setGiffId(DEFAULT_GIFT_ID);
|
||||||
|
entity.setGiffNumber(0L);
|
||||||
|
try {
|
||||||
|
playClerkGiftInfoService.save(entity);
|
||||||
|
} catch (org.springframework.dao.DuplicateKeyException duplicateKeyException) {
|
||||||
|
playClerkGiftInfoMapper.resetGiftCount(DEFAULT_TENANT_ID, DEFAULT_CLERK_ID, DEFAULT_GIFT_ID);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void seedCustomer() {
|
private void seedCustomer() {
|
||||||
PlayCustomUserInfoEntity customer = customUserInfoService.getById(DEFAULT_CUSTOMER_ID);
|
PlayCustomUserInfoEntity customer = customUserInfoService.getById(DEFAULT_CUSTOMER_ID);
|
||||||
String token = wxTokenService.createWxUserToken(DEFAULT_CUSTOMER_ID);
|
String token = wxTokenService.createWxUserToken(DEFAULT_CUSTOMER_ID);
|
||||||
|
|||||||
@@ -32,8 +32,10 @@ public class GlobalExceptionHandler {
|
|||||||
public R handleServiceException(ServiceException e, HttpServletRequest request) {
|
public R handleServiceException(ServiceException e, HttpServletRequest request) {
|
||||||
if ("token异常".equals(e.getMessage()) || "token为空".equals(e.getMessage())) {
|
if ("token异常".equals(e.getMessage()) || "token为空".equals(e.getMessage())) {
|
||||||
log.error("用户token异常");
|
log.error("用户token异常");
|
||||||
|
} else if (log.isDebugEnabled()) {
|
||||||
|
log.debug("业务异常", e);
|
||||||
} else {
|
} else {
|
||||||
log.error(e.getMessage(), e);
|
log.warn("业务异常: {}", e.getMessage());
|
||||||
}
|
}
|
||||||
Integer code = e.getCode();
|
Integer code = e.getCode();
|
||||||
return StringUtils.isNotNull(code) ? R.error(code, e.getMessage()) : R.error(e.getMessage());
|
return StringUtils.isNotNull(code) ? R.error(code, e.getMessage()) : R.error(e.getMessage());
|
||||||
@@ -111,10 +113,11 @@ public class GlobalExceptionHandler {
|
|||||||
public R customException(CustomException e) {
|
public R customException(CustomException e) {
|
||||||
if ("token异常".equals(e.getMessage()) || "token为空".equals(e.getMessage())) {
|
if ("token异常".equals(e.getMessage()) || "token为空".equals(e.getMessage())) {
|
||||||
log.error("用户token异常");
|
log.error("用户token异常");
|
||||||
|
} else if (log.isDebugEnabled()) {
|
||||||
|
log.debug("业务异常", e);
|
||||||
} else {
|
} else {
|
||||||
log.error(e.getMessage(), e);
|
log.warn("业务异常: {}", e.getMessage());
|
||||||
}
|
}
|
||||||
|
|
||||||
return R.error(e.getMessage());
|
return R.error(e.getMessage());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ import com.starry.admin.modules.clerk.service.IPlayClerkCommodityService;
|
|||||||
import com.starry.admin.modules.clerk.service.IPlayClerkUserInfoService;
|
import com.starry.admin.modules.clerk.service.IPlayClerkUserInfoService;
|
||||||
import com.starry.admin.modules.clerk.service.IPlayClerkUserReviewInfoService;
|
import com.starry.admin.modules.clerk.service.IPlayClerkUserReviewInfoService;
|
||||||
import com.starry.admin.modules.order.module.constant.OrderConstant;
|
import com.starry.admin.modules.order.module.constant.OrderConstant;
|
||||||
import com.starry.admin.modules.weichat.service.WxCustomMpService;
|
import com.starry.admin.modules.weichat.service.NotificationSender;
|
||||||
import com.starry.common.utils.IdUtils;
|
import com.starry.common.utils.IdUtils;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import javax.annotation.Resource;
|
import javax.annotation.Resource;
|
||||||
@@ -45,7 +45,7 @@ public class PlayClerkUserReviewInfoServiceImpl
|
|||||||
@Resource
|
@Resource
|
||||||
private IPlayClerkCommodityService clerkCommodityService;
|
private IPlayClerkCommodityService clerkCommodityService;
|
||||||
@Resource
|
@Resource
|
||||||
private WxCustomMpService wxCustomMpService;
|
private NotificationSender notificationSender;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public PlayClerkUserReviewInfoEntity queryByClerkId(String clerkId, String reviewState) {
|
public PlayClerkUserReviewInfoEntity queryByClerkId(String clerkId, String reviewState) {
|
||||||
@@ -186,7 +186,7 @@ public class PlayClerkUserReviewInfoServiceImpl
|
|||||||
this.update(entity);
|
this.update(entity);
|
||||||
|
|
||||||
// 发送消息
|
// 发送消息
|
||||||
wxCustomMpService.sendCheckMessage(entity, userInfo, vo.getReviewState());
|
notificationSender.sendCheckMessage(entity, userInfo, vo.getReviewState());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -29,4 +29,9 @@ public interface PlayCustomGiftInfoMapper extends MPJBaseMapper<PlayCustomGiftIn
|
|||||||
int incrementGiftCount(@Param("customId") String customId, @Param("giftId") String giftId,
|
int incrementGiftCount(@Param("customId") String customId, @Param("giftId") String giftId,
|
||||||
@Param("tenantId") String tenantId, @Param("delta") long delta);
|
@Param("tenantId") String tenantId, @Param("delta") long delta);
|
||||||
|
|
||||||
|
@Update("UPDATE play_custom_gift_info SET giff_number = 0, deleted = 0 "
|
||||||
|
+ "WHERE tenant_id = #{tenantId} AND custom_id = #{customId} AND giff_id = #{giftId}")
|
||||||
|
int resetGiftCount(@Param("tenantId") String tenantId, @Param("customId") String customId,
|
||||||
|
@Param("giftId") String giftId);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -47,7 +47,7 @@ import com.starry.admin.modules.shop.module.entity.PlayCouponInfoEntity;
|
|||||||
import com.starry.admin.modules.shop.module.enums.CouponDiscountType;
|
import com.starry.admin.modules.shop.module.enums.CouponDiscountType;
|
||||||
import com.starry.admin.modules.shop.service.IPlayCouponDetailsService;
|
import com.starry.admin.modules.shop.service.IPlayCouponDetailsService;
|
||||||
import com.starry.admin.modules.shop.service.IPlayCouponInfoService;
|
import com.starry.admin.modules.shop.service.IPlayCouponInfoService;
|
||||||
import com.starry.admin.modules.weichat.service.WxCustomMpService;
|
import com.starry.admin.modules.weichat.service.NotificationSender;
|
||||||
import com.starry.admin.modules.withdraw.entity.EarningsLineEntity;
|
import com.starry.admin.modules.withdraw.entity.EarningsLineEntity;
|
||||||
import com.starry.admin.modules.withdraw.service.IEarningsService;
|
import com.starry.admin.modules.withdraw.service.IEarningsService;
|
||||||
import com.starry.admin.utils.SecurityUtils;
|
import com.starry.admin.utils.SecurityUtils;
|
||||||
@@ -85,7 +85,7 @@ public class OrderLifecycleServiceImpl implements IOrderLifecycleService {
|
|||||||
private IEarningsService earningsService;
|
private IEarningsService earningsService;
|
||||||
|
|
||||||
@Resource
|
@Resource
|
||||||
private WxCustomMpService wxCustomMpService;
|
private NotificationSender notificationSender;
|
||||||
|
|
||||||
@Resource
|
@Resource
|
||||||
private IPlayOrderRefundInfoService orderRefundInfoService;
|
private IPlayOrderRefundInfoService orderRefundInfoService;
|
||||||
@@ -466,7 +466,7 @@ public class OrderLifecycleServiceImpl implements IOrderLifecycleService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (shouldNotify) {
|
if (shouldNotify) {
|
||||||
wxCustomMpService.sendOrderFinishMessageAsync(latest);
|
notificationSender.sendOrderFinishMessageAsync(latest);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ import com.starry.admin.modules.order.module.vo.PlayOrderComplaintQueryVo;
|
|||||||
import com.starry.admin.modules.order.module.vo.PlayOrderComplaintReturnVo;
|
import com.starry.admin.modules.order.module.vo.PlayOrderComplaintReturnVo;
|
||||||
import com.starry.admin.modules.order.service.IPlayOrderComplaintInfoService;
|
import com.starry.admin.modules.order.service.IPlayOrderComplaintInfoService;
|
||||||
import com.starry.admin.modules.personnel.service.IPlayPersonnelGroupInfoService;
|
import com.starry.admin.modules.personnel.service.IPlayPersonnelGroupInfoService;
|
||||||
import com.starry.admin.modules.weichat.service.WxCustomMpService;
|
import com.starry.admin.modules.weichat.service.NotificationSender;
|
||||||
import com.starry.admin.utils.SecurityUtils;
|
import com.starry.admin.utils.SecurityUtils;
|
||||||
import com.starry.common.utils.IdUtils;
|
import com.starry.common.utils.IdUtils;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
@@ -46,7 +46,7 @@ public class PlayOrderComplaintInfoServiceImpl
|
|||||||
@Resource
|
@Resource
|
||||||
private IPlayPersonnelGroupInfoService playClerkGroupInfoService;
|
private IPlayPersonnelGroupInfoService playClerkGroupInfoService;
|
||||||
@Resource
|
@Resource
|
||||||
private WxCustomMpService wxCustomMpService;
|
private NotificationSender notificationSender;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 查询订单投诉信息
|
* 查询订单投诉信息
|
||||||
@@ -169,7 +169,7 @@ public class PlayOrderComplaintInfoServiceImpl
|
|||||||
playOrderComplaintInfo.setClerkId(orderInfo.getAcceptBy());
|
playOrderComplaintInfo.setClerkId(orderInfo.getAcceptBy());
|
||||||
playOrderComplaintInfo.setCommodityId(orderInfo.getCommodityId());
|
playOrderComplaintInfo.setCommodityId(orderInfo.getCommodityId());
|
||||||
// 发送投诉消息给管理员以及客服
|
// 发送投诉消息给管理员以及客服
|
||||||
wxCustomMpService.sendComplaintMessage(playOrderComplaintInfo, orderInfo);
|
notificationSender.sendComplaintMessage(playOrderComplaintInfo, orderInfo);
|
||||||
return save(playOrderComplaintInfo);
|
return save(playOrderComplaintInfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
package com.starry.admin.modules.order.service.impl;
|
package com.starry.admin.modules.order.service.impl;
|
||||||
|
|
||||||
|
import cn.hutool.core.collection.CollectionUtil;
|
||||||
import cn.hutool.core.util.StrUtil;
|
import cn.hutool.core.util.StrUtil;
|
||||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||||
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
|
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
|
||||||
@@ -41,10 +42,11 @@ import com.starry.admin.modules.order.service.IPlayOrderRefundInfoService;
|
|||||||
import com.starry.admin.modules.order.service.support.ClerkRevenueCalculator;
|
import com.starry.admin.modules.order.service.support.ClerkRevenueCalculator;
|
||||||
import com.starry.admin.modules.personnel.module.entity.PlayPersonnelGroupInfoEntity;
|
import com.starry.admin.modules.personnel.module.entity.PlayPersonnelGroupInfoEntity;
|
||||||
import com.starry.admin.modules.personnel.service.IPlayPersonnelGroupInfoService;
|
import com.starry.admin.modules.personnel.service.IPlayPersonnelGroupInfoService;
|
||||||
|
import com.starry.admin.modules.shop.module.constant.CouponUseState;
|
||||||
import com.starry.admin.modules.shop.module.vo.PlayCouponDetailsReturnVo;
|
import com.starry.admin.modules.shop.module.vo.PlayCouponDetailsReturnVo;
|
||||||
import com.starry.admin.modules.shop.service.IPlayCouponDetailsService;
|
import com.starry.admin.modules.shop.service.IPlayCouponDetailsService;
|
||||||
import com.starry.admin.modules.weichat.entity.order.*;
|
import com.starry.admin.modules.weichat.entity.order.*;
|
||||||
import com.starry.admin.modules.weichat.service.WxCustomMpService;
|
import com.starry.admin.modules.weichat.service.NotificationSender;
|
||||||
import com.starry.admin.modules.withdraw.service.IEarningsService;
|
import com.starry.admin.modules.withdraw.service.IEarningsService;
|
||||||
import com.starry.admin.utils.DateRangeUtils;
|
import com.starry.admin.utils.DateRangeUtils;
|
||||||
import com.starry.admin.utils.SecurityUtils;
|
import com.starry.admin.utils.SecurityUtils;
|
||||||
@@ -95,7 +97,7 @@ public class PlayOrderInfoServiceImpl extends ServiceImpl<PlayOrderInfoMapper, P
|
|||||||
private IPlayCouponDetailsService playCouponDetailsService;
|
private IPlayCouponDetailsService playCouponDetailsService;
|
||||||
|
|
||||||
@Resource
|
@Resource
|
||||||
private WxCustomMpService wxCustomMpService;
|
private NotificationSender notificationSender;
|
||||||
|
|
||||||
@Resource
|
@Resource
|
||||||
private IPlayCustomUserInfoService customUserInfoService;
|
private IPlayCustomUserInfoService customUserInfoService;
|
||||||
@@ -644,7 +646,7 @@ public class PlayOrderInfoServiceImpl extends ServiceImpl<PlayOrderInfoMapper, P
|
|||||||
orderInfo.setFirstOrder(firstOrderFlag);
|
orderInfo.setFirstOrder(firstOrderFlag);
|
||||||
log.info("Order accepted successfully. orderId={}, orderNo={}, acceptBy={}, operatorByType={}",
|
log.info("Order accepted successfully. orderId={}, orderNo={}, acceptBy={}, operatorByType={}",
|
||||||
orderId, orderInfo.getOrderNo(), acceptBy, operatorByType);
|
orderId, orderInfo.getOrderNo(), acceptBy, operatorByType);
|
||||||
wxCustomMpService.sendOrderMessageAsync(orderInfo);
|
notificationSender.sendOrderMessageAsync(orderInfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void validateClerkQualificationForRandomOrder(PlayOrderInfoEntity orderInfo,
|
private void validateClerkQualificationForRandomOrder(PlayOrderInfoEntity orderInfo,
|
||||||
@@ -835,7 +837,8 @@ public class PlayOrderInfoServiceImpl extends ServiceImpl<PlayOrderInfoMapper, P
|
|||||||
playOrderRefundInfoService.add(orderInfo.getId(), orderInfo.getPurchaserBy(), orderInfo.getAcceptBy(),
|
playOrderRefundInfoService.add(orderInfo.getId(), orderInfo.getPurchaserBy(), orderInfo.getAcceptBy(),
|
||||||
orderInfo.getPayMethod(), OrderRefundRecordType.FULL.getCode(), orderInfo.getFinalAmount(), refundReason, operatorByType, operatorBy,
|
orderInfo.getPayMethod(), OrderRefundRecordType.FULL.getCode(), orderInfo.getFinalAmount(), refundReason, operatorByType, operatorBy,
|
||||||
OrderRefundState.PROCESSING.getCode(), ReviewRequirement.NOT_REQUIRED.getCode());
|
OrderRefundState.PROCESSING.getCode(), ReviewRequirement.NOT_REQUIRED.getCode());
|
||||||
wxCustomMpService.sendOrderCancelMessageAsync(orderInfo, refundReason);
|
restoreCouponsForOrder(orderInfo);
|
||||||
|
notificationSender.sendOrderCancelMessageAsync(orderInfo, refundReason);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -888,8 +891,10 @@ public class PlayOrderInfoServiceImpl extends ServiceImpl<PlayOrderInfoMapper, P
|
|||||||
orderInfo.getPayMethod(), forceCancelRefundType.getCode(), actualRefundAmount, refundReason, operatorByType, operatorBy,
|
orderInfo.getPayMethod(), forceCancelRefundType.getCode(), actualRefundAmount, refundReason, operatorByType, operatorBy,
|
||||||
OrderRefundState.PROCESSING.getCode(), ReviewRequirement.NOT_REQUIRED.getCode());
|
OrderRefundState.PROCESSING.getCode(), ReviewRequirement.NOT_REQUIRED.getCode());
|
||||||
|
|
||||||
|
restoreCouponsForOrder(orderInfo);
|
||||||
|
|
||||||
PlayOrderInfoEntity latest = this.selectOrderInfoById(orderId);
|
PlayOrderInfoEntity latest = this.selectOrderInfoById(orderId);
|
||||||
wxCustomMpService.sendOrderCancelMessageAsync(latest, refundReason);
|
notificationSender.sendOrderCancelMessageAsync(latest, refundReason);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -1038,4 +1043,11 @@ public class PlayOrderInfoServiceImpl extends ServiceImpl<PlayOrderInfoMapper, P
|
|||||||
return OrderTriggerSource.SYSTEM;
|
return OrderTriggerSource.SYSTEM;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void restoreCouponsForOrder(PlayOrderInfoEntity orderInfo) {
|
||||||
|
if (orderInfo == null || CollectionUtil.isEmpty(orderInfo.getCouponIds())) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
playCouponDetailsService.updateCouponUseStateByIds(orderInfo.getCouponIds(), CouponUseState.UNUSED.getCode());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -29,4 +29,9 @@ public interface PlayClerkGiftInfoMapper extends BaseMapper<PlayClerkGiftInfoEnt
|
|||||||
int incrementGiftCount(@Param("clerkId") String clerkId, @Param("giftId") String giftId,
|
int incrementGiftCount(@Param("clerkId") String clerkId, @Param("giftId") String giftId,
|
||||||
@Param("tenantId") String tenantId, @Param("delta") long delta);
|
@Param("tenantId") String tenantId, @Param("delta") long delta);
|
||||||
|
|
||||||
|
@Update("UPDATE play_clerk_gift_info SET giff_number = 0, deleted = 0 "
|
||||||
|
+ "WHERE tenant_id = #{tenantId} AND clerk_id = #{clerkId} AND giff_id = #{giftId}")
|
||||||
|
int resetGiftCount(@Param("tenantId") String tenantId, @Param("clerkId") String clerkId,
|
||||||
|
@Param("giftId") String giftId);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -103,7 +103,11 @@ public class PlayCommodityInfoServiceImpl extends ServiceImpl<PlayCommodityInfoM
|
|||||||
@Override
|
@Override
|
||||||
public List<PlayCommodityInfoEntity> selectByType() {
|
public List<PlayCommodityInfoEntity> selectByType() {
|
||||||
LambdaQueryWrapper<PlayCommodityInfoEntity> lambdaQueryWrapper = new LambdaQueryWrapper<>();
|
LambdaQueryWrapper<PlayCommodityInfoEntity> lambdaQueryWrapper = new LambdaQueryWrapper<>();
|
||||||
lambdaQueryWrapper.eq(PlayCommodityInfoEntity::getItemType, "服务类型");
|
String tenantId = SecurityUtils.getTenantId();
|
||||||
|
if (StrUtil.isNotBlank(tenantId)) {
|
||||||
|
lambdaQueryWrapper.eq(PlayCommodityInfoEntity::getTenantId, tenantId);
|
||||||
|
}
|
||||||
|
lambdaQueryWrapper.eq(PlayCommodityInfoEntity::getPId, "00");
|
||||||
lambdaQueryWrapper.orderByDesc(PlayCommodityInfoEntity::getSort);
|
lambdaQueryWrapper.orderByDesc(PlayCommodityInfoEntity::getSort);
|
||||||
return this.baseMapper.selectList(lambdaQueryWrapper);
|
return this.baseMapper.selectList(lambdaQueryWrapper);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ package com.starry.admin.modules.shop.service.impl;
|
|||||||
import cn.hutool.core.util.StrUtil;
|
import cn.hutool.core.util.StrUtil;
|
||||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||||
|
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
||||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||||
import com.github.yulichang.wrapper.MPJLambdaWrapper;
|
import com.github.yulichang.wrapper.MPJLambdaWrapper;
|
||||||
@@ -158,12 +159,12 @@ public class PlayCouponDetailsServiceImpl extends ServiceImpl<PlayCouponDetailsM
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void updateCouponUseStateByIds(List<String> ids, String useState) {
|
public void updateCouponUseStateByIds(List<String> ids, String useState) {
|
||||||
|
LocalDateTime useTime = CouponUseState.USED.getCode().equals(useState) ? LocalDateTime.now() : null;
|
||||||
for (String id : ids) {
|
for (String id : ids) {
|
||||||
PlayCouponDetailsEntity entity = new PlayCouponDetailsEntity();
|
baseMapper.update(null, com.baomidou.mybatisplus.core.toolkit.Wrappers.<PlayCouponDetailsEntity>lambdaUpdate()
|
||||||
entity.setId(id);
|
.eq(PlayCouponDetailsEntity::getId, id)
|
||||||
entity.setUseState(useState);
|
.set(PlayCouponDetailsEntity::getUseState, useState)
|
||||||
entity.setUseTime(LocalDateTime.now());
|
.set(PlayCouponDetailsEntity::getUseTime, useTime));
|
||||||
baseMapper.updateById(entity);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,45 @@
|
|||||||
|
package com.starry.admin.modules.weichat.service;
|
||||||
|
|
||||||
|
import com.starry.admin.modules.clerk.module.entity.PlayClerkUserInfoEntity;
|
||||||
|
import com.starry.admin.modules.clerk.module.entity.PlayClerkUserReviewInfoEntity;
|
||||||
|
import com.starry.admin.modules.order.module.entity.PlayOrderComplaintInfoEntity;
|
||||||
|
import com.starry.admin.modules.order.module.entity.PlayOrderInfoEntity;
|
||||||
|
import javax.annotation.Resource;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.context.annotation.Profile;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
|
@Component
|
||||||
|
@Profile("!apitest")
|
||||||
|
public class DefaultNotificationSender implements NotificationSender {
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private WxCustomMpService wxCustomMpService;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void sendOrderMessageAsync(PlayOrderInfoEntity orderInfo) {
|
||||||
|
wxCustomMpService.sendOrderMessageAsync(orderInfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void sendOrderFinishMessageAsync(PlayOrderInfoEntity order) {
|
||||||
|
wxCustomMpService.sendOrderFinishMessageAsync(order);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void sendOrderCancelMessageAsync(PlayOrderInfoEntity orderInfo, String refundReason) {
|
||||||
|
wxCustomMpService.sendOrderCancelMessageAsync(orderInfo, refundReason);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void sendComplaintMessage(PlayOrderComplaintInfoEntity info, PlayOrderInfoEntity orderInfo) {
|
||||||
|
wxCustomMpService.sendComplaintMessage(info, orderInfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void sendCheckMessage(PlayClerkUserReviewInfoEntity entity, PlayClerkUserInfoEntity userInfo,
|
||||||
|
String reviewState) {
|
||||||
|
wxCustomMpService.sendCheckMessage(entity, userInfo, reviewState);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,43 @@
|
|||||||
|
package com.starry.admin.modules.weichat.service;
|
||||||
|
|
||||||
|
import com.starry.admin.modules.clerk.module.entity.PlayClerkUserInfoEntity;
|
||||||
|
import com.starry.admin.modules.clerk.module.entity.PlayClerkUserReviewInfoEntity;
|
||||||
|
import com.starry.admin.modules.order.module.entity.PlayOrderComplaintInfoEntity;
|
||||||
|
import com.starry.admin.modules.order.module.entity.PlayOrderInfoEntity;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.context.annotation.Primary;
|
||||||
|
import org.springframework.context.annotation.Profile;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
|
@Primary
|
||||||
|
@Component
|
||||||
|
@Profile("apitest")
|
||||||
|
public class MockNotificationSender implements NotificationSender {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void sendOrderMessageAsync(PlayOrderInfoEntity orderInfo) {
|
||||||
|
log.debug("[wechat-mock] skip sendOrderMessageAsync orderId={}", orderInfo.getId());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void sendOrderFinishMessageAsync(PlayOrderInfoEntity order) {
|
||||||
|
log.debug("[wechat-mock] skip sendOrderFinishMessageAsync orderId={}", order.getId());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void sendOrderCancelMessageAsync(PlayOrderInfoEntity orderInfo, String refundReason) {
|
||||||
|
log.debug("[wechat-mock] skip sendOrderCancelMessageAsync orderId={}", orderInfo.getId());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void sendComplaintMessage(PlayOrderComplaintInfoEntity info, PlayOrderInfoEntity orderInfo) {
|
||||||
|
log.debug("[wechat-mock] skip sendComplaintMessage orderId={}", orderInfo.getId());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void sendCheckMessage(PlayClerkUserReviewInfoEntity entity, PlayClerkUserInfoEntity userInfo,
|
||||||
|
String reviewState) {
|
||||||
|
log.debug("[wechat-mock] skip sendCheckMessage clerkId={}", userInfo == null ? null : userInfo.getId());
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
package com.starry.admin.modules.weichat.service;
|
||||||
|
|
||||||
|
import com.starry.admin.modules.clerk.module.entity.PlayClerkUserInfoEntity;
|
||||||
|
import com.starry.admin.modules.clerk.module.entity.PlayClerkUserReviewInfoEntity;
|
||||||
|
import com.starry.admin.modules.order.module.entity.PlayOrderComplaintInfoEntity;
|
||||||
|
import com.starry.admin.modules.order.module.entity.PlayOrderInfoEntity;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 抽象出发送微信通知的接口,便于在测试环境下替换为 Mock 实现。
|
||||||
|
*/
|
||||||
|
public interface NotificationSender {
|
||||||
|
|
||||||
|
void sendOrderMessageAsync(PlayOrderInfoEntity orderInfo);
|
||||||
|
|
||||||
|
void sendOrderFinishMessageAsync(PlayOrderInfoEntity order);
|
||||||
|
|
||||||
|
void sendOrderCancelMessageAsync(PlayOrderInfoEntity orderInfo, String refundReason);
|
||||||
|
|
||||||
|
void sendComplaintMessage(PlayOrderComplaintInfoEntity info, PlayOrderInfoEntity orderInfo);
|
||||||
|
|
||||||
|
void sendCheckMessage(PlayClerkUserReviewInfoEntity entity, PlayClerkUserInfoEntity userInfo, String reviewState);
|
||||||
|
}
|
||||||
@@ -37,6 +37,7 @@ import me.chanjar.weixin.mp.bean.template.WxMpTemplateData;
|
|||||||
import me.chanjar.weixin.mp.bean.template.WxMpTemplateMessage;
|
import me.chanjar.weixin.mp.bean.template.WxMpTemplateMessage;
|
||||||
import me.chanjar.weixin.mp.config.impl.WxMpMapConfigImpl;
|
import me.chanjar.weixin.mp.config.impl.WxMpMapConfigImpl;
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
|
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
@@ -61,6 +62,7 @@ public class WxCustomMpService {
|
|||||||
@Resource
|
@Resource
|
||||||
private ThreadPoolTaskExecutor executor;
|
private ThreadPoolTaskExecutor executor;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 支付成功回调地址
|
* 支付成功回调地址
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -53,6 +53,7 @@ logging:
|
|||||||
level:
|
level:
|
||||||
root: info
|
root: info
|
||||||
com.starry: debug
|
com.starry: debug
|
||||||
|
business-error-as-warn: true
|
||||||
|
|
||||||
jwt:
|
jwt:
|
||||||
tokenHeader: X-Test-Token
|
tokenHeader: X-Test-Token
|
||||||
|
|||||||
@@ -210,6 +210,7 @@ class PlayCommodityInfoApiTest extends WxCustomOrderApiTestSupport {
|
|||||||
.andExpect(status().isOk())
|
.andExpect(status().isOk())
|
||||||
.andExpect(jsonPath("$.code").value(200));
|
.andExpect(jsonPath("$.code").value(200));
|
||||||
|
|
||||||
|
ensureTenantContext();
|
||||||
PlayCommodityAndLevelInfoEntity pricing = commodityAndLevelInfoService.lambdaQuery()
|
PlayCommodityAndLevelInfoEntity pricing = commodityAndLevelInfoService.lambdaQuery()
|
||||||
.eq(PlayCommodityAndLevelInfoEntity::getCommodityId, child.getId())
|
.eq(PlayCommodityAndLevelInfoEntity::getCommodityId, child.getId())
|
||||||
.eq(PlayCommodityAndLevelInfoEntity::getLevelId, ApiTestDataSeeder.DEFAULT_CLERK_LEVEL_ID)
|
.eq(PlayCommodityAndLevelInfoEntity::getLevelId, ApiTestDataSeeder.DEFAULT_CLERK_LEVEL_ID)
|
||||||
@@ -266,6 +267,7 @@ class PlayCommodityInfoApiTest extends WxCustomOrderApiTestSupport {
|
|||||||
.andExpect(status().isOk())
|
.andExpect(status().isOk())
|
||||||
.andExpect(jsonPath("$.code").value(200));
|
.andExpect(jsonPath("$.code").value(200));
|
||||||
|
|
||||||
|
ensureTenantContext();
|
||||||
PlayCommodityInfoEntity updated = commodityInfoService.getById(child.getId());
|
PlayCommodityInfoEntity updated = commodityInfoService.getById(child.getId());
|
||||||
assertThat(updated.getAutomaticSettlementDuration())
|
assertThat(updated.getAutomaticSettlementDuration())
|
||||||
.isEqualTo(AutomaticSettlementPolicy.TEN_MINUTES.getSeconds());
|
.isEqualTo(AutomaticSettlementPolicy.TEN_MINUTES.getSeconds());
|
||||||
|
|||||||
@@ -112,6 +112,7 @@ class WxCustomGiftOrderApiTest extends WxCustomOrderApiTestSupport {
|
|||||||
Assertions.assertThat(clerkGift).isNotNull();
|
Assertions.assertThat(clerkGift).isNotNull();
|
||||||
Assertions.assertThat(clerkGift.getGiffNumber()).isEqualTo((long) giftQuantity);
|
Assertions.assertThat(clerkGift.getGiffNumber()).isEqualTo((long) giftQuantity);
|
||||||
|
|
||||||
|
ensureTenantContext();
|
||||||
BigDecimal finalBalance = customUserInfoService.getById(ApiTestDataSeeder.DEFAULT_CUSTOMER_ID)
|
BigDecimal finalBalance = customUserInfoService.getById(ApiTestDataSeeder.DEFAULT_CUSTOMER_ID)
|
||||||
.getAccountBalance();
|
.getAccountBalance();
|
||||||
Assertions.assertThat(finalBalance).isEqualByComparingTo(initialBalance.subtract(totalAmount));
|
Assertions.assertThat(finalBalance).isEqualByComparingTo(initialBalance.subtract(totalAmount));
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ import com.starry.admin.modules.order.module.entity.PlayOrderInfoEntity;
|
|||||||
import com.starry.admin.modules.shop.module.constant.CouponUseState;
|
import com.starry.admin.modules.shop.module.constant.CouponUseState;
|
||||||
import com.starry.admin.modules.shop.module.entity.PlayCouponDetailsEntity;
|
import com.starry.admin.modules.shop.module.entity.PlayCouponDetailsEntity;
|
||||||
import com.starry.admin.modules.shop.module.vo.PlayCouponDetailsReturnVo;
|
import com.starry.admin.modules.shop.module.vo.PlayCouponDetailsReturnVo;
|
||||||
|
import com.starry.admin.modules.weichat.service.NotificationSender;
|
||||||
import com.starry.admin.modules.weichat.service.WxCustomMpService;
|
import com.starry.admin.modules.weichat.service.WxCustomMpService;
|
||||||
import com.starry.admin.modules.withdraw.entity.EarningsLineEntity;
|
import com.starry.admin.modules.withdraw.entity.EarningsLineEntity;
|
||||||
import com.starry.admin.modules.withdraw.enums.EarningsType;
|
import com.starry.admin.modules.withdraw.enums.EarningsType;
|
||||||
@@ -38,6 +39,9 @@ import org.springframework.test.web.servlet.MvcResult;
|
|||||||
|
|
||||||
class WxCustomRandomOrderApiTest extends WxCustomOrderApiTestSupport {
|
class WxCustomRandomOrderApiTest extends WxCustomOrderApiTestSupport {
|
||||||
|
|
||||||
|
@MockBean
|
||||||
|
private NotificationSender notificationSender;
|
||||||
|
|
||||||
@MockBean
|
@MockBean
|
||||||
private WxCustomMpService wxCustomMpService;
|
private WxCustomMpService wxCustomMpService;
|
||||||
|
|
||||||
@@ -158,6 +162,11 @@ class WxCustomRandomOrderApiTest extends WxCustomOrderApiTestSupport {
|
|||||||
.one();
|
.one();
|
||||||
Assertions.assertThat(order).isNotNull();
|
Assertions.assertThat(order).isNotNull();
|
||||||
|
|
||||||
|
PlayCouponDetailsEntity detailBeforeCancel = couponDetailsService.getById(couponDetailId);
|
||||||
|
Assertions.assertThat(detailBeforeCancel).isNotNull();
|
||||||
|
Assertions.assertThat(detailBeforeCancel.getUseState()).isEqualTo(CouponUseState.USED.getCode());
|
||||||
|
Assertions.assertThat(detailBeforeCancel.getUseTime()).isNotNull();
|
||||||
|
|
||||||
String cancelPayload = "{" +
|
String cancelPayload = "{" +
|
||||||
"\"orderId\":\"" + order.getId() + "\"," +
|
"\"orderId\":\"" + order.getId() + "\"," +
|
||||||
"\"refundReason\":\"测试取消\"," +
|
"\"refundReason\":\"测试取消\"," +
|
||||||
@@ -182,6 +191,7 @@ class WxCustomRandomOrderApiTest extends WxCustomOrderApiTestSupport {
|
|||||||
Assertions.assertThat(detail.getUseState())
|
Assertions.assertThat(detail.getUseState())
|
||||||
.as("取消订单后优惠券应恢复为未使用")
|
.as("取消订单后优惠券应恢复为未使用")
|
||||||
.isEqualTo(CouponUseState.UNUSED.getCode());
|
.isEqualTo(CouponUseState.UNUSED.getCode());
|
||||||
|
Assertions.assertThat(detail.getUseTime()).isNull();
|
||||||
} finally {
|
} finally {
|
||||||
CustomSecurityContextHolder.remove();
|
CustomSecurityContextHolder.remove();
|
||||||
}
|
}
|
||||||
@@ -194,7 +204,7 @@ class WxCustomRandomOrderApiTest extends WxCustomOrderApiTestSupport {
|
|||||||
String remark = "API random force cancel " + IdUtils.getUuid();
|
String remark = "API random force cancel " + IdUtils.getUuid();
|
||||||
BigDecimal discount = new BigDecimal("12.00");
|
BigDecimal discount = new BigDecimal("12.00");
|
||||||
try {
|
try {
|
||||||
reset(wxCustomMpService);
|
reset(notificationSender);
|
||||||
resetCustomerBalance();
|
resetCustomerBalance();
|
||||||
|
|
||||||
String customerToken = wxTokenService.createWxUserToken(ApiTestDataSeeder.DEFAULT_CUSTOMER_ID);
|
String customerToken = wxTokenService.createWxUserToken(ApiTestDataSeeder.DEFAULT_CUSTOMER_ID);
|
||||||
@@ -249,6 +259,12 @@ class WxCustomRandomOrderApiTest extends WxCustomOrderApiTestSupport {
|
|||||||
.andExpect(jsonPath("$.code").value(200))
|
.andExpect(jsonPath("$.code").value(200))
|
||||||
.andExpect(jsonPath("$.data").value("成功"));
|
.andExpect(jsonPath("$.data").value("成功"));
|
||||||
|
|
||||||
|
ensureTenantContext();
|
||||||
|
PlayCouponDetailsEntity detailBeforeForceCancel = couponDetailsService.getById(couponDetailId);
|
||||||
|
Assertions.assertThat(detailBeforeForceCancel).isNotNull();
|
||||||
|
Assertions.assertThat(detailBeforeForceCancel.getUseState()).isEqualTo(CouponUseState.USED.getCode());
|
||||||
|
Assertions.assertThat(detailBeforeForceCancel.getUseTime()).isNotNull();
|
||||||
|
|
||||||
ensureTenantContext();
|
ensureTenantContext();
|
||||||
orderInfoService.forceCancelOngoingOrder(
|
orderInfoService.forceCancelOngoingOrder(
|
||||||
"2",
|
"2",
|
||||||
@@ -267,6 +283,7 @@ class WxCustomRandomOrderApiTest extends WxCustomOrderApiTestSupport {
|
|||||||
Assertions.assertThat(detail.getUseState())
|
Assertions.assertThat(detail.getUseState())
|
||||||
.as("强制取消订单后优惠券应恢复为未使用")
|
.as("强制取消订单后优惠券应恢复为未使用")
|
||||||
.isEqualTo(CouponUseState.UNUSED.getCode());
|
.isEqualTo(CouponUseState.UNUSED.getCode());
|
||||||
|
Assertions.assertThat(detail.getUseTime()).isNull();
|
||||||
} finally {
|
} finally {
|
||||||
CustomSecurityContextHolder.remove();
|
CustomSecurityContextHolder.remove();
|
||||||
}
|
}
|
||||||
@@ -280,7 +297,7 @@ class WxCustomRandomOrderApiTest extends WxCustomOrderApiTestSupport {
|
|||||||
String remark = "API random coupon " + IdUtils.getUuid();
|
String remark = "API random coupon " + IdUtils.getUuid();
|
||||||
BigDecimal discount = new BigDecimal("20.00");
|
BigDecimal discount = new BigDecimal("20.00");
|
||||||
try {
|
try {
|
||||||
reset(wxCustomMpService);
|
reset(notificationSender);
|
||||||
resetCustomerBalance();
|
resetCustomerBalance();
|
||||||
|
|
||||||
String customerToken = wxTokenService.createWxUserToken(ApiTestDataSeeder.DEFAULT_CUSTOMER_ID);
|
String customerToken = wxTokenService.createWxUserToken(ApiTestDataSeeder.DEFAULT_CUSTOMER_ID);
|
||||||
@@ -334,15 +351,13 @@ class WxCustomRandomOrderApiTest extends WxCustomOrderApiTestSupport {
|
|||||||
Assertions.assertThat(order.getFinalAmount()).isEqualByComparingTo(expectedNet);
|
Assertions.assertThat(order.getFinalAmount()).isEqualByComparingTo(expectedNet);
|
||||||
Assertions.assertThat(order.getDiscountAmount()).isEqualByComparingTo(discount);
|
Assertions.assertThat(order.getDiscountAmount()).isEqualByComparingTo(discount);
|
||||||
|
|
||||||
verify(wxCustomMpService).sendCreateOrderMessageBatch(
|
|
||||||
anyList(),
|
|
||||||
eq(order.getOrderNo()),
|
|
||||||
eq(expectedNet.toString()),
|
|
||||||
eq(order.getCommodityName()),
|
|
||||||
eq(order.getId()));
|
|
||||||
|
|
||||||
String orderId = order.getId();
|
String orderId = order.getId();
|
||||||
|
|
||||||
|
PlayCouponDetailsEntity detailAfterOrderPlaced = couponDetailsService.getById(couponDetailId);
|
||||||
|
Assertions.assertThat(detailAfterOrderPlaced).isNotNull();
|
||||||
|
Assertions.assertThat(detailAfterOrderPlaced.getUseState()).isEqualTo(CouponUseState.USED.getCode());
|
||||||
|
Assertions.assertThat(detailAfterOrderPlaced.getUseTime()).isNotNull();
|
||||||
|
|
||||||
mockMvc.perform(get("/wx/clerk/order/accept")
|
mockMvc.perform(get("/wx/clerk/order/accept")
|
||||||
.param("id", orderId)
|
.param("id", orderId)
|
||||||
.header(USER_HEADER, DEFAULT_USER)
|
.header(USER_HEADER, DEFAULT_USER)
|
||||||
@@ -352,7 +367,8 @@ class WxCustomRandomOrderApiTest extends WxCustomOrderApiTestSupport {
|
|||||||
.andExpect(jsonPath("$.code").value(200))
|
.andExpect(jsonPath("$.code").value(200))
|
||||||
.andExpect(jsonPath("$.data").value("成功"));
|
.andExpect(jsonPath("$.data").value("成功"));
|
||||||
|
|
||||||
verify(wxCustomMpService).sendOrderMessageAsync(argThat(o -> orderId.equals(o.getId())));
|
verify(notificationSender).sendOrderMessageAsync(argThat(o -> o.getId().equals(orderId)));
|
||||||
|
|
||||||
|
|
||||||
mockMvc.perform(get("/wx/clerk/order/start")
|
mockMvc.perform(get("/wx/clerk/order/start")
|
||||||
.param("id", orderId)
|
.param("id", orderId)
|
||||||
@@ -372,7 +388,7 @@ class WxCustomRandomOrderApiTest extends WxCustomOrderApiTestSupport {
|
|||||||
.andExpect(jsonPath("$.code").value(200))
|
.andExpect(jsonPath("$.code").value(200))
|
||||||
.andExpect(jsonPath("$.data").value("成功"));
|
.andExpect(jsonPath("$.data").value("成功"));
|
||||||
|
|
||||||
verify(wxCustomMpService).sendOrderFinishMessageAsync(argThat(o -> orderId.equals(o.getId())));
|
verify(notificationSender).sendOrderFinishMessageAsync(argThat(o -> orderId.equals(o.getId())));
|
||||||
|
|
||||||
ensureTenantContext();
|
ensureTenantContext();
|
||||||
PlayOrderInfoEntity completedOrder = playOrderInfoService.selectOrderInfoById(orderId);
|
PlayOrderInfoEntity completedOrder = playOrderInfoService.selectOrderInfoById(orderId);
|
||||||
@@ -397,6 +413,11 @@ class WxCustomRandomOrderApiTest extends WxCustomOrderApiTestSupport {
|
|||||||
Assertions.assertThat(earningsLine.getAmount()).isEqualByComparingTo(expectedRevenue);
|
Assertions.assertThat(earningsLine.getAmount()).isEqualByComparingTo(expectedRevenue);
|
||||||
|
|
||||||
assertCouponUsed(couponDetailId);
|
assertCouponUsed(couponDetailId);
|
||||||
|
|
||||||
|
PlayCouponDetailsEntity detailAfterLifecycle = couponDetailsService.getById(couponDetailId);
|
||||||
|
Assertions.assertThat(detailAfterLifecycle).isNotNull();
|
||||||
|
Assertions.assertThat(detailAfterLifecycle.getUseState()).isEqualTo(CouponUseState.USED.getCode());
|
||||||
|
Assertions.assertThat(detailAfterLifecycle.getUseTime()).isNotNull();
|
||||||
} finally {
|
} finally {
|
||||||
CustomSecurityContextHolder.remove();
|
CustomSecurityContextHolder.remove();
|
||||||
}
|
}
|
||||||
@@ -421,7 +442,7 @@ class WxCustomRandomOrderApiTest extends WxCustomOrderApiTestSupport {
|
|||||||
|
|
||||||
String orderId = placeRandomOrder(remark, customerToken);
|
String orderId = placeRandomOrder(remark, customerToken);
|
||||||
|
|
||||||
reset(wxCustomMpService);
|
reset(notificationSender);
|
||||||
|
|
||||||
ensureTenantContext();
|
ensureTenantContext();
|
||||||
mockMvc.perform(get("/wx/clerk/order/accept")
|
mockMvc.perform(get("/wx/clerk/order/accept")
|
||||||
@@ -433,9 +454,9 @@ class WxCustomRandomOrderApiTest extends WxCustomOrderApiTestSupport {
|
|||||||
.andExpect(jsonPath("$.code").value(200))
|
.andExpect(jsonPath("$.code").value(200))
|
||||||
.andExpect(jsonPath("$.data").value("成功"));
|
.andExpect(jsonPath("$.data").value("成功"));
|
||||||
|
|
||||||
verify(wxCustomMpService).sendOrderMessageAsync(argThat(order -> order.getId().equals(orderId)));
|
verify(notificationSender).sendOrderMessageAsync(argThat(order -> order.getId().equals(orderId)));
|
||||||
|
|
||||||
reset(wxCustomMpService);
|
reset(notificationSender);
|
||||||
|
|
||||||
ensureTenantContext();
|
ensureTenantContext();
|
||||||
mockMvc.perform(get("/wx/clerk/order/start")
|
mockMvc.perform(get("/wx/clerk/order/start")
|
||||||
@@ -463,7 +484,7 @@ class WxCustomRandomOrderApiTest extends WxCustomOrderApiTestSupport {
|
|||||||
.andExpect(jsonPath("$.code").value(200))
|
.andExpect(jsonPath("$.code").value(200))
|
||||||
.andExpect(jsonPath("$.data").value("成功"));
|
.andExpect(jsonPath("$.data").value("成功"));
|
||||||
|
|
||||||
verify(wxCustomMpService).sendOrderFinishMessageAsync(argThat(order -> order.getId().equals(orderId)));
|
verify(notificationSender).sendOrderFinishMessageAsync(argThat(order -> order.getId().equals(orderId)));
|
||||||
|
|
||||||
ensureTenantContext();
|
ensureTenantContext();
|
||||||
long earningsAfter = earningsService.lambdaQuery()
|
long earningsAfter = earningsService.lambdaQuery()
|
||||||
|
|||||||
@@ -86,6 +86,16 @@ class WxCustomSpecifiedOrderApiTest extends WxCustomOrderApiTestSupport {
|
|||||||
.one();
|
.one();
|
||||||
Assertions.assertThat(order).isNotNull();
|
Assertions.assertThat(order).isNotNull();
|
||||||
|
|
||||||
|
PlayCouponDetailsEntity detailBeforeForceCancel = couponDetailsService.getById(couponDetailId);
|
||||||
|
Assertions.assertThat(detailBeforeForceCancel).isNotNull();
|
||||||
|
Assertions.assertThat(detailBeforeForceCancel.getUseState()).isEqualTo(CouponUseState.USED.getCode());
|
||||||
|
Assertions.assertThat(detailBeforeForceCancel.getUseTime()).isNotNull();
|
||||||
|
|
||||||
|
PlayCouponDetailsEntity detailBeforeCancel = couponDetailsService.getById(couponDetailId);
|
||||||
|
Assertions.assertThat(detailBeforeCancel).isNotNull();
|
||||||
|
Assertions.assertThat(detailBeforeCancel.getUseState()).isEqualTo(CouponUseState.USED.getCode());
|
||||||
|
Assertions.assertThat(detailBeforeCancel.getUseTime()).isNotNull();
|
||||||
|
|
||||||
String cancelPayload = "{" +
|
String cancelPayload = "{" +
|
||||||
"\"orderId\":\"" + order.getId() + "\"," +
|
"\"orderId\":\"" + order.getId() + "\"," +
|
||||||
"\"refundReason\":\"测试取消\"," +
|
"\"refundReason\":\"测试取消\"," +
|
||||||
@@ -106,9 +116,11 @@ class WxCustomSpecifiedOrderApiTest extends WxCustomOrderApiTestSupport {
|
|||||||
Assertions.assertThat(cancelled.getOrderStatus()).isEqualTo(OrderConstant.OrderStatus.CANCELLED.getCode());
|
Assertions.assertThat(cancelled.getOrderStatus()).isEqualTo(OrderConstant.OrderStatus.CANCELLED.getCode());
|
||||||
|
|
||||||
PlayCouponDetailsEntity detail = couponDetailsService.getById(couponDetailId);
|
PlayCouponDetailsEntity detail = couponDetailsService.getById(couponDetailId);
|
||||||
|
Assertions.assertThat(detail).isNotNull();
|
||||||
Assertions.assertThat(detail.getUseState())
|
Assertions.assertThat(detail.getUseState())
|
||||||
.as("取消指定单后优惠券应恢复为未使用")
|
.as("取消指定单后优惠券应恢复为未使用")
|
||||||
.isEqualTo(CouponUseState.UNUSED.getCode());
|
.isEqualTo(CouponUseState.UNUSED.getCode());
|
||||||
|
Assertions.assertThat(detail.getUseTime()).isNull();
|
||||||
} finally {
|
} finally {
|
||||||
CustomSecurityContextHolder.remove();
|
CustomSecurityContextHolder.remove();
|
||||||
}
|
}
|
||||||
@@ -172,6 +184,11 @@ class WxCustomSpecifiedOrderApiTest extends WxCustomOrderApiTestSupport {
|
|||||||
Assertions.assertThat(order.getFinalAmount()).isEqualByComparingTo(expectedNet);
|
Assertions.assertThat(order.getFinalAmount()).isEqualByComparingTo(expectedNet);
|
||||||
Assertions.assertThat(order.getDiscountAmount()).isEqualByComparingTo(discount);
|
Assertions.assertThat(order.getDiscountAmount()).isEqualByComparingTo(discount);
|
||||||
|
|
||||||
|
PlayCouponDetailsEntity detailAfterOrder = couponDetailsService.getById(couponDetailId);
|
||||||
|
Assertions.assertThat(detailAfterOrder).isNotNull();
|
||||||
|
Assertions.assertThat(detailAfterOrder.getUseState()).isEqualTo(CouponUseState.USED.getCode());
|
||||||
|
Assertions.assertThat(detailAfterOrder.getUseTime()).isNotNull();
|
||||||
|
|
||||||
verify(wxCustomMpService).sendCreateOrderMessage(
|
verify(wxCustomMpService).sendCreateOrderMessage(
|
||||||
eq(ApiTestDataSeeder.DEFAULT_TENANT_ID),
|
eq(ApiTestDataSeeder.DEFAULT_TENANT_ID),
|
||||||
eq(ApiTestDataSeeder.DEFAULT_CLERK_OPEN_ID),
|
eq(ApiTestDataSeeder.DEFAULT_CLERK_OPEN_ID),
|
||||||
@@ -194,6 +211,10 @@ class WxCustomSpecifiedOrderApiTest extends WxCustomOrderApiTestSupport {
|
|||||||
Assertions.assertThat(order.getEstimatedRevenue()).isEqualByComparingTo(expectedRevenue);
|
Assertions.assertThat(order.getEstimatedRevenue()).isEqualByComparingTo(expectedRevenue);
|
||||||
|
|
||||||
assertCouponUsed(couponDetailId);
|
assertCouponUsed(couponDetailId);
|
||||||
|
PlayCouponDetailsEntity detailAfterComplete = couponDetailsService.getById(couponDetailId);
|
||||||
|
Assertions.assertThat(detailAfterComplete).isNotNull();
|
||||||
|
Assertions.assertThat(detailAfterComplete.getUseState()).isEqualTo(CouponUseState.USED.getCode());
|
||||||
|
Assertions.assertThat(detailAfterComplete.getUseTime()).isNotNull();
|
||||||
} finally {
|
} finally {
|
||||||
CustomSecurityContextHolder.remove();
|
CustomSecurityContextHolder.remove();
|
||||||
}
|
}
|
||||||
@@ -273,9 +294,11 @@ class WxCustomSpecifiedOrderApiTest extends WxCustomOrderApiTestSupport {
|
|||||||
Assertions.assertThat(cancelled.getOrderStatus()).isEqualTo(OrderConstant.OrderStatus.CANCELLED.getCode());
|
Assertions.assertThat(cancelled.getOrderStatus()).isEqualTo(OrderConstant.OrderStatus.CANCELLED.getCode());
|
||||||
|
|
||||||
PlayCouponDetailsEntity detail = couponDetailsService.getById(couponDetailId);
|
PlayCouponDetailsEntity detail = couponDetailsService.getById(couponDetailId);
|
||||||
|
Assertions.assertThat(detail).isNotNull();
|
||||||
Assertions.assertThat(detail.getUseState())
|
Assertions.assertThat(detail.getUseState())
|
||||||
.as("强制取消指定单后优惠券应恢复为未使用")
|
.as("强制取消指定单后优惠券应恢复为未使用")
|
||||||
.isEqualTo(CouponUseState.UNUSED.getCode());
|
.isEqualTo(CouponUseState.UNUSED.getCode());
|
||||||
|
Assertions.assertThat(detail.getUseTime()).isNull();
|
||||||
} finally {
|
} finally {
|
||||||
CustomSecurityContextHolder.remove();
|
CustomSecurityContextHolder.remove();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -50,7 +50,7 @@ import com.starry.admin.modules.shop.module.entity.PlayCouponDetailsEntity;
|
|||||||
import com.starry.admin.modules.shop.module.entity.PlayCouponInfoEntity;
|
import com.starry.admin.modules.shop.module.entity.PlayCouponInfoEntity;
|
||||||
import com.starry.admin.modules.shop.service.IPlayCouponDetailsService;
|
import com.starry.admin.modules.shop.service.IPlayCouponDetailsService;
|
||||||
import com.starry.admin.modules.shop.service.IPlayCouponInfoService;
|
import com.starry.admin.modules.shop.service.IPlayCouponInfoService;
|
||||||
import com.starry.admin.modules.weichat.service.WxCustomMpService;
|
import com.starry.admin.modules.weichat.service.NotificationSender;
|
||||||
import com.starry.admin.modules.withdraw.entity.EarningsLineEntity;
|
import com.starry.admin.modules.withdraw.entity.EarningsLineEntity;
|
||||||
import com.starry.admin.modules.withdraw.service.IEarningsService;
|
import com.starry.admin.modules.withdraw.service.IEarningsService;
|
||||||
import java.math.BigDecimal;
|
import java.math.BigDecimal;
|
||||||
@@ -81,7 +81,7 @@ class OrderLifecycleServiceImplTest {
|
|||||||
private IEarningsService earningsService;
|
private IEarningsService earningsService;
|
||||||
|
|
||||||
@Mock
|
@Mock
|
||||||
private WxCustomMpService wxCustomMpService;
|
private NotificationSender notificationSender;
|
||||||
|
|
||||||
@Mock
|
@Mock
|
||||||
private IPlayOrderRefundInfoService orderRefundInfoService;
|
private IPlayOrderRefundInfoService orderRefundInfoService;
|
||||||
@@ -565,7 +565,7 @@ private PlayOrderLogInfoMapper orderLogInfoMapper;
|
|||||||
lifecycleService.placeOrder(command(context, null, false, null, null));
|
lifecycleService.placeOrder(command(context, null, false, null, null));
|
||||||
|
|
||||||
verify(orderInfoMapper, never()).selectById(anyString());
|
verify(orderInfoMapper, never()).selectById(anyString());
|
||||||
verify(wxCustomMpService, never()).sendOrderFinishMessageAsync(any());
|
verify(notificationSender, never()).sendOrderFinishMessageAsync(any());
|
||||||
verify(earningsService, never()).createFromOrder(any());
|
verify(earningsService, never()).createFromOrder(any());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -594,7 +594,7 @@ private PlayOrderLogInfoMapper orderLogInfoMapper;
|
|||||||
verify(orderInfoMapper, atLeastOnce()).selectById(anyString());
|
verify(orderInfoMapper, atLeastOnce()).selectById(anyString());
|
||||||
verify(customUserInfoService).handleOrderCompletion(any());
|
verify(customUserInfoService).handleOrderCompletion(any());
|
||||||
verify(earningsService).createFromOrder(completed);
|
verify(earningsService).createFromOrder(completed);
|
||||||
verify(wxCustomMpService).sendOrderFinishMessageAsync(completed);
|
verify(notificationSender).sendOrderFinishMessageAsync(completed);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -610,7 +610,7 @@ private PlayOrderLogInfoMapper orderLogInfoMapper;
|
|||||||
lifecycleService.placeOrder(command(context, null, false, null, null));
|
lifecycleService.placeOrder(command(context, null, false, null, null));
|
||||||
|
|
||||||
verify(orderInfoMapper, never()).selectById(anyString());
|
verify(orderInfoMapper, never()).selectById(anyString());
|
||||||
verify(wxCustomMpService, never()).sendOrderFinishMessageAsync(any());
|
verify(notificationSender, never()).sendOrderFinishMessageAsync(any());
|
||||||
verify(earningsService, never()).createFromOrder(any());
|
verify(earningsService, never()).createFromOrder(any());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -639,7 +639,7 @@ private PlayOrderLogInfoMapper orderLogInfoMapper;
|
|||||||
verify(orderInfoMapper, atLeastOnce()).selectById(anyString());
|
verify(orderInfoMapper, atLeastOnce()).selectById(anyString());
|
||||||
verify(customUserInfoService).handleOrderCompletion(any());
|
verify(customUserInfoService).handleOrderCompletion(any());
|
||||||
verify(earningsService).createFromOrder(completed);
|
verify(earningsService).createFromOrder(completed);
|
||||||
verify(wxCustomMpService).sendOrderFinishMessageAsync(completed);
|
verify(notificationSender).sendOrderFinishMessageAsync(completed);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -1031,7 +1031,7 @@ private PlayOrderLogInfoMapper orderLogInfoMapper;
|
|||||||
verify(orderInfoMapper).update(isNull(), any());
|
verify(orderInfoMapper).update(isNull(), any());
|
||||||
verify(customUserInfoService).handleOrderCompletion(completed);
|
verify(customUserInfoService).handleOrderCompletion(completed);
|
||||||
verify(earningsService).createFromOrder(completed);
|
verify(earningsService).createFromOrder(completed);
|
||||||
verify(wxCustomMpService).sendOrderFinishMessageAsync(completed);
|
verify(notificationSender).sendOrderFinishMessageAsync(completed);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -1052,7 +1052,7 @@ private PlayOrderLogInfoMapper orderLogInfoMapper;
|
|||||||
OrderTriggerSource.ADMIN_CONSOLE));
|
OrderTriggerSource.ADMIN_CONSOLE));
|
||||||
|
|
||||||
verify(earningsService, never()).createFromOrder(any());
|
verify(earningsService, never()).createFromOrder(any());
|
||||||
verify(wxCustomMpService, never()).sendOrderFinishMessageAsync(any());
|
verify(notificationSender, never()).sendOrderFinishMessageAsync(any());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -1074,7 +1074,7 @@ private PlayOrderLogInfoMapper orderLogInfoMapper;
|
|||||||
|
|
||||||
verify(customUserInfoService, never()).handleOrderCompletion(any());
|
verify(customUserInfoService, never()).handleOrderCompletion(any());
|
||||||
verify(earningsService, never()).createFromOrder(any());
|
verify(earningsService, never()).createFromOrder(any());
|
||||||
verify(wxCustomMpService, never()).sendOrderFinishMessageAsync(any());
|
verify(notificationSender, never()).sendOrderFinishMessageAsync(any());
|
||||||
verify(orderLogInfoMapper, never()).insert(any());
|
verify(orderLogInfoMapper, never()).insert(any());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -40,6 +40,9 @@ public class ThreadPoolConfig {
|
|||||||
executor.setCorePoolSize(corePoolSize);
|
executor.setCorePoolSize(corePoolSize);
|
||||||
executor.setQueueCapacity(queueCapacity);
|
executor.setQueueCapacity(queueCapacity);
|
||||||
executor.setKeepAliveSeconds(keepAliveSeconds);
|
executor.setKeepAliveSeconds(keepAliveSeconds);
|
||||||
|
executor.setThreadNamePrefix("async-pool-");
|
||||||
|
executor.setWaitForTasksToCompleteOnShutdown(true);
|
||||||
|
executor.setAwaitTerminationSeconds(30);
|
||||||
// 线程池对拒绝任务(无线程可用)的处理策略
|
// 线程池对拒绝任务(无线程可用)的处理策略
|
||||||
executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
|
executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
|
||||||
return executor;
|
return executor;
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import javax.servlet.http.HttpServletRequest;
|
|||||||
import javax.servlet.http.HttpServletResponse;
|
import javax.servlet.http.HttpServletResponse;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
import org.springframework.web.servlet.HandlerInterceptor;
|
import org.springframework.web.servlet.HandlerInterceptor;
|
||||||
|
|
||||||
@@ -25,6 +26,9 @@ public class RequestLoggingInterceptor implements HandlerInterceptor {
|
|||||||
private static final String START_TIME_ATTRIBUTE = "startTime";
|
private static final String START_TIME_ATTRIBUTE = "startTime";
|
||||||
public static final String BUSINESS_RESULT_ATTRIBUTE = "requestLoggingBusinessResult";
|
public static final String BUSINESS_RESULT_ATTRIBUTE = "requestLoggingBusinessResult";
|
||||||
|
|
||||||
|
@Value("${logging.business-error-as-warn:false}")
|
||||||
|
private boolean businessErrorAsWarn;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
|
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
|
||||||
throws Exception {
|
throws Exception {
|
||||||
@@ -208,8 +212,13 @@ public class RequestLoggingInterceptor implements HandlerInterceptor {
|
|||||||
long duration, BusinessResult businessResult) {
|
long duration, BusinessResult businessResult) {
|
||||||
String template = "Request completed: {} {} - {} {} ({}ms) businessCode={} success={} message={}";
|
String template = "Request completed: {} {} - {} {} ({}ms) businessCode={} success={} message={}";
|
||||||
if (isBusinessError(businessResult)) {
|
if (isBusinessError(businessResult)) {
|
||||||
|
if (businessErrorAsWarn) {
|
||||||
|
log.warn(template, method, uri, status, statusText, duration,
|
||||||
|
businessResult.getCode(), businessResult.isSuccess(), businessResult.getMessage());
|
||||||
|
} else {
|
||||||
log.error(template, method, uri, status, statusText, duration,
|
log.error(template, method, uri, status, statusText, duration,
|
||||||
businessResult.getCode(), businessResult.isSuccess(), businessResult.getMessage());
|
businessResult.getCode(), businessResult.isSuccess(), businessResult.getMessage());
|
||||||
|
}
|
||||||
} else if (isBusinessWarn(businessResult)) {
|
} else if (isBusinessWarn(businessResult)) {
|
||||||
log.warn(template, method, uri, status, statusText, duration,
|
log.warn(template, method, uri, status, statusText, duration,
|
||||||
businessResult.getCode(), businessResult.isSuccess(), businessResult.getMessage());
|
businessResult.getCode(), businessResult.isSuccess(), businessResult.getMessage());
|
||||||
|
|||||||
Reference in New Issue
Block a user