API-test-in-progress
This commit is contained in:
@@ -0,0 +1,354 @@
|
||||
package com.starry.admin.api;
|
||||
|
||||
import static org.mockito.ArgumentMatchers.anyString;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.Mockito.reset;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
|
||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
|
||||
|
||||
import com.starry.admin.common.apitest.ApiTestDataSeeder;
|
||||
import com.starry.admin.modules.order.module.constant.OrderConstant;
|
||||
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.entity.PlayCouponDetailsEntity;
|
||||
import com.starry.admin.modules.shop.module.vo.PlayCouponDetailsReturnVo;
|
||||
import com.starry.admin.modules.weichat.service.WxCustomMpService;
|
||||
import com.starry.admin.utils.SecurityUtils;
|
||||
import com.starry.common.constant.Constants;
|
||||
import com.starry.common.context.CustomSecurityContextHolder;
|
||||
import com.starry.common.utils.IdUtils;
|
||||
import java.math.BigDecimal;
|
||||
import java.math.RoundingMode;
|
||||
import java.util.Collections;
|
||||
import org.assertj.core.api.Assertions;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.boot.test.mock.mockito.MockBean;
|
||||
import org.springframework.http.MediaType;
|
||||
|
||||
class WxCustomSpecifiedOrderApiTest extends WxCustomOrderApiTestSupport {
|
||||
|
||||
@MockBean
|
||||
private WxCustomMpService wxCustomMpService;
|
||||
|
||||
@org.springframework.beans.factory.annotation.Autowired
|
||||
private com.starry.admin.modules.order.service.IPlayOrderInfoService orderInfoService;
|
||||
|
||||
@org.springframework.beans.factory.annotation.Autowired
|
||||
private com.starry.admin.modules.weichat.service.WxTokenService clerkWxTokenService;
|
||||
|
||||
@Test
|
||||
// 测试用例:指定单取消后优惠券应恢复为未使用
|
||||
void specifiedOrderCancellationReleasesCoupon() throws Exception {
|
||||
SecurityUtils.setTenantId(ApiTestDataSeeder.DEFAULT_TENANT_ID);
|
||||
String remark = "API specified cancel " + IdUtils.getUuid();
|
||||
BigDecimal discount = new BigDecimal("10.00");
|
||||
try {
|
||||
resetCustomerBalance();
|
||||
String customerToken = wxTokenService.createWxUserToken(ApiTestDataSeeder.DEFAULT_CUSTOMER_ID);
|
||||
customUserInfoService.updateTokenById(ApiTestDataSeeder.DEFAULT_CUSTOMER_ID, customerToken);
|
||||
|
||||
String couponInfoId = createCouponId("cpn-sc-");
|
||||
ensureFixedReductionCoupon(
|
||||
couponInfoId,
|
||||
OrderConstant.PlaceType.SPECIFIED,
|
||||
discount,
|
||||
new BigDecimal("60.00"),
|
||||
"0");
|
||||
String couponDetailId = claimCouponForOrder(couponInfoId, OrderConstant.PlaceType.SPECIFIED, customerToken);
|
||||
|
||||
String payload = "{" +
|
||||
"\"clerkId\":\"" + ApiTestDataSeeder.DEFAULT_CLERK_ID + "\"," +
|
||||
"\"commodityId\":\"" + ApiTestDataSeeder.DEFAULT_COMMODITY_ID + "\"," +
|
||||
"\"commodityQuantity\":1," +
|
||||
"\"weiChatCode\":\"apitest-customer-wx\"," +
|
||||
"\"couponIds\":[\"" + couponDetailId + "\"]," +
|
||||
"\"remark\":\"" + remark + "\"" +
|
||||
"}";
|
||||
|
||||
mockMvc.perform(post("/wx/custom/order/commodity")
|
||||
.header(USER_HEADER, DEFAULT_USER)
|
||||
.header(TENANT_HEADER, DEFAULT_TENANT)
|
||||
.header(Constants.CUSTOM_USER_LOGIN_TOKEN, Constants.TOKEN_PREFIX + customerToken)
|
||||
.contentType(MediaType.APPLICATION_JSON)
|
||||
.content(payload))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(jsonPath("$.code").value(200));
|
||||
|
||||
ensureTenantContext();
|
||||
PlayOrderInfoEntity order = playOrderInfoService.lambdaQuery()
|
||||
.eq(PlayOrderInfoEntity::getPurchaserBy, ApiTestDataSeeder.DEFAULT_CUSTOMER_ID)
|
||||
.eq(PlayOrderInfoEntity::getRemark, remark)
|
||||
.orderByDesc(PlayOrderInfoEntity::getCreatedTime)
|
||||
.last("limit 1")
|
||||
.one();
|
||||
Assertions.assertThat(order).isNotNull();
|
||||
|
||||
String cancelPayload = "{" +
|
||||
"\"orderId\":\"" + order.getId() + "\"," +
|
||||
"\"refundReason\":\"测试取消\"," +
|
||||
"\"images\":[]" +
|
||||
"}";
|
||||
mockMvc.perform(post("/wx/custom/order/cancellation")
|
||||
.header(USER_HEADER, DEFAULT_USER)
|
||||
.header(TENANT_HEADER, DEFAULT_TENANT)
|
||||
.header(Constants.CUSTOM_USER_LOGIN_TOKEN, Constants.TOKEN_PREFIX + customerToken)
|
||||
.contentType(MediaType.APPLICATION_JSON)
|
||||
.content(cancelPayload))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(jsonPath("$.code").value(200))
|
||||
.andExpect(jsonPath("$.data").value("取消成功"));
|
||||
|
||||
ensureTenantContext();
|
||||
PlayOrderInfoEntity cancelled = playOrderInfoService.selectOrderInfoById(order.getId());
|
||||
Assertions.assertThat(cancelled.getOrderStatus()).isEqualTo(OrderConstant.OrderStatus.CANCELLED.getCode());
|
||||
|
||||
PlayCouponDetailsEntity detail = couponDetailsService.getById(couponDetailId);
|
||||
Assertions.assertThat(detail.getUseState())
|
||||
.as("取消指定单后优惠券应恢复为未使用")
|
||||
.isEqualTo(CouponUseState.UNUSED.getCode());
|
||||
} finally {
|
||||
CustomSecurityContextHolder.remove();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
// 测试用例:指定单使用满减券下单后,应按折后金额推送创建通知,
|
||||
// 并将预计收益扣除优惠金额,同时把优惠券详情标记为已使用。
|
||||
void specifiedOrderWithCouponAdjustsAmountAndRevenue() throws Exception {
|
||||
SecurityUtils.setTenantId(ApiTestDataSeeder.DEFAULT_TENANT_ID);
|
||||
String remark = "API specified coupon " + IdUtils.getUuid();
|
||||
BigDecimal discount = new BigDecimal("15.00");
|
||||
try {
|
||||
reset(wxCustomMpService);
|
||||
resetCustomerBalance();
|
||||
|
||||
String customerToken = wxTokenService.createWxUserToken(ApiTestDataSeeder.DEFAULT_CUSTOMER_ID);
|
||||
customUserInfoService.updateTokenById(ApiTestDataSeeder.DEFAULT_CUSTOMER_ID, customerToken);
|
||||
|
||||
BigDecimal grossAmount = ApiTestDataSeeder.DEFAULT_COMMODITY_PRICE;
|
||||
String couponInfoId = createCouponId("cpn-s-");
|
||||
ensureFixedReductionCoupon(
|
||||
couponInfoId,
|
||||
OrderConstant.PlaceType.SPECIFIED,
|
||||
discount,
|
||||
new BigDecimal("60.00"),
|
||||
"0");
|
||||
String couponDetailId = claimCouponForOrder(couponInfoId, OrderConstant.PlaceType.SPECIFIED, customerToken);
|
||||
|
||||
String payload = "{" +
|
||||
"\"clerkId\":\"" + ApiTestDataSeeder.DEFAULT_CLERK_ID + "\"," +
|
||||
"\"commodityId\":\"" + ApiTestDataSeeder.DEFAULT_COMMODITY_ID + "\"," +
|
||||
"\"commodityQuantity\":1," +
|
||||
"\"weiChatCode\":\"apitest-customer-wx\"," +
|
||||
"\"couponIds\":[\"" + couponDetailId + "\"]," +
|
||||
"\"remark\":\"" + remark + "\"" +
|
||||
"}";
|
||||
|
||||
mockMvc.perform(post("/wx/custom/order/commodity")
|
||||
.header(USER_HEADER, DEFAULT_USER)
|
||||
.header(TENANT_HEADER, DEFAULT_TENANT)
|
||||
.header(Constants.CUSTOM_USER_LOGIN_TOKEN, Constants.TOKEN_PREFIX + customerToken)
|
||||
.contentType(MediaType.APPLICATION_JSON)
|
||||
.content(payload))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(jsonPath("$.code").value(200))
|
||||
.andExpect(jsonPath("$.data").value("成功"));
|
||||
|
||||
ensureTenantContext();
|
||||
PlayOrderInfoEntity order = playOrderInfoService.lambdaQuery()
|
||||
.eq(PlayOrderInfoEntity::getPurchaserBy, ApiTestDataSeeder.DEFAULT_CUSTOMER_ID)
|
||||
.eq(PlayOrderInfoEntity::getRemark, remark)
|
||||
.orderByDesc(PlayOrderInfoEntity::getCreatedTime)
|
||||
.last("limit 1")
|
||||
.one();
|
||||
|
||||
Assertions.assertThat(order).isNotNull();
|
||||
Assertions.assertThat(order.getCouponIds()).contains(couponDetailId);
|
||||
|
||||
BigDecimal expectedNet = grossAmount.subtract(discount).setScale(2, RoundingMode.HALF_UP);
|
||||
Assertions.assertThat(order.getFinalAmount()).isEqualByComparingTo(expectedNet);
|
||||
Assertions.assertThat(order.getDiscountAmount()).isEqualByComparingTo(discount);
|
||||
|
||||
verify(wxCustomMpService).sendCreateOrderMessage(
|
||||
eq(ApiTestDataSeeder.DEFAULT_TENANT_ID),
|
||||
eq(ApiTestDataSeeder.DEFAULT_CLERK_OPEN_ID),
|
||||
anyString(),
|
||||
eq(expectedNet.toString()),
|
||||
eq(order.getCommodityName()),
|
||||
eq(order.getId()));
|
||||
|
||||
int ratio = order.getEstimatedRevenueRatio();
|
||||
BigDecimal baseRevenue = grossAmount
|
||||
.multiply(BigDecimal.valueOf(ratio))
|
||||
.divide(BigDecimal.valueOf(100), 2, RoundingMode.HALF_UP);
|
||||
PlayCouponDetailsReturnVo detail = couponDetailsService.selectPlayCouponDetailsById(couponDetailId);
|
||||
BigDecimal clerkDiscount = BigDecimal.ZERO;
|
||||
if (detail != null && "0".equals(detail.getAttributionDiscounts())) {
|
||||
BigDecimal discountAmount = detail.getDiscountAmount() == null ? BigDecimal.ZERO : detail.getDiscountAmount();
|
||||
clerkDiscount = discountAmount;
|
||||
}
|
||||
BigDecimal expectedRevenue = baseRevenue.subtract(clerkDiscount).max(BigDecimal.ZERO).setScale(2, RoundingMode.HALF_UP);
|
||||
Assertions.assertThat(order.getEstimatedRevenue()).isEqualByComparingTo(expectedRevenue);
|
||||
|
||||
assertCouponUsed(couponDetailId);
|
||||
} finally {
|
||||
CustomSecurityContextHolder.remove();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
// 测试用例:指定单在接单后由管理员强制取消时,优惠券应恢复为未使用
|
||||
void specifiedOrderForceCancelReleasesCoupon() throws Exception {
|
||||
SecurityUtils.setTenantId(ApiTestDataSeeder.DEFAULT_TENANT_ID);
|
||||
String remark = "API specified force cancel " + IdUtils.getUuid();
|
||||
BigDecimal discount = new BigDecimal("8.00");
|
||||
try {
|
||||
reset(wxCustomMpService);
|
||||
resetCustomerBalance();
|
||||
|
||||
String customerToken = wxTokenService.createWxUserToken(ApiTestDataSeeder.DEFAULT_CUSTOMER_ID);
|
||||
customUserInfoService.updateTokenById(ApiTestDataSeeder.DEFAULT_CUSTOMER_ID, customerToken);
|
||||
String clerkToken = wxTokenService.createWxUserToken(ApiTestDataSeeder.DEFAULT_CLERK_ID);
|
||||
clerkUserInfoService.updateTokenById(ApiTestDataSeeder.DEFAULT_CLERK_ID, clerkToken);
|
||||
|
||||
String couponInfoId = createCouponId("cpn-sf-");
|
||||
ensureFixedReductionCoupon(
|
||||
couponInfoId,
|
||||
OrderConstant.PlaceType.SPECIFIED,
|
||||
discount,
|
||||
new BigDecimal("60.00"),
|
||||
"0");
|
||||
String couponDetailId = claimCouponForOrder(couponInfoId, OrderConstant.PlaceType.SPECIFIED, customerToken);
|
||||
|
||||
String payload = "{" +
|
||||
"\"clerkId\":\"" + ApiTestDataSeeder.DEFAULT_CLERK_ID + "\"," +
|
||||
"\"commodityId\":\"" + ApiTestDataSeeder.DEFAULT_COMMODITY_ID + "\"," +
|
||||
"\"commodityQuantity\":1," +
|
||||
"\"weiChatCode\":\"apitest-customer-wx\"," +
|
||||
"\"couponIds\":[\"" + couponDetailId + "\"]," +
|
||||
"\"remark\":\"" + remark + "\"" +
|
||||
"}";
|
||||
|
||||
mockMvc.perform(post("/wx/custom/order/commodity")
|
||||
.header(USER_HEADER, DEFAULT_USER)
|
||||
.header(TENANT_HEADER, DEFAULT_TENANT)
|
||||
.header(Constants.CUSTOM_USER_LOGIN_TOKEN, Constants.TOKEN_PREFIX + customerToken)
|
||||
.contentType(MediaType.APPLICATION_JSON)
|
||||
.content(payload))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(jsonPath("$.code").value(200));
|
||||
|
||||
ensureTenantContext();
|
||||
PlayOrderInfoEntity order = playOrderInfoService.lambdaQuery()
|
||||
.eq(PlayOrderInfoEntity::getPurchaserBy, ApiTestDataSeeder.DEFAULT_CUSTOMER_ID)
|
||||
.eq(PlayOrderInfoEntity::getRemark, remark)
|
||||
.orderByDesc(PlayOrderInfoEntity::getCreatedTime)
|
||||
.last("limit 1")
|
||||
.one();
|
||||
Assertions.assertThat(order).isNotNull();
|
||||
|
||||
mockMvc.perform(get("/wx/clerk/order/accept")
|
||||
.param("id", order.getId())
|
||||
.header(USER_HEADER, DEFAULT_USER)
|
||||
.header(TENANT_HEADER, DEFAULT_TENANT)
|
||||
.header(Constants.CLERK_USER_LOGIN_TOKEN, Constants.TOKEN_PREFIX + clerkToken))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(jsonPath("$.code").value(200))
|
||||
.andExpect(jsonPath("$.data").value("成功"));
|
||||
|
||||
ensureTenantContext();
|
||||
orderInfoService.forceCancelOngoingOrder(
|
||||
"2",
|
||||
ApiTestDataSeeder.DEFAULT_ADMIN_USER_ID,
|
||||
order.getId(),
|
||||
order.getFinalAmount(),
|
||||
"管理员强制取消",
|
||||
java.util.Collections.emptyList());
|
||||
|
||||
ensureTenantContext();
|
||||
PlayOrderInfoEntity cancelled = playOrderInfoService.selectOrderInfoById(order.getId());
|
||||
Assertions.assertThat(cancelled.getOrderStatus()).isEqualTo(OrderConstant.OrderStatus.CANCELLED.getCode());
|
||||
|
||||
PlayCouponDetailsEntity detail = couponDetailsService.getById(couponDetailId);
|
||||
Assertions.assertThat(detail.getUseState())
|
||||
.as("强制取消指定单后优惠券应恢复为未使用")
|
||||
.isEqualTo(CouponUseState.UNUSED.getCode());
|
||||
} finally {
|
||||
CustomSecurityContextHolder.remove();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
// 测试用例:客户携带指定陪玩师和服务下单时,接口需返回成功,并生成待支付状态的指定订单,
|
||||
// 验证订单金额与种子服务价格一致、陪玩师被正确指派,同时触发微信创建订单通知。
|
||||
void specifiedOrderCreatesPendingOrder() throws Exception {
|
||||
SecurityUtils.setTenantId(ApiTestDataSeeder.DEFAULT_TENANT_ID);
|
||||
try {
|
||||
resetCustomerBalance();
|
||||
String customerToken = wxTokenService.createWxUserToken(ApiTestDataSeeder.DEFAULT_CUSTOMER_ID);
|
||||
customUserInfoService.updateTokenById(ApiTestDataSeeder.DEFAULT_CUSTOMER_ID, customerToken);
|
||||
|
||||
String remark = "API specified order " + IdUtils.getUuid();
|
||||
ensureTenantContext();
|
||||
long beforeCount = playOrderInfoService.lambdaQuery()
|
||||
.eq(PlayOrderInfoEntity::getPurchaserBy, ApiTestDataSeeder.DEFAULT_CUSTOMER_ID)
|
||||
.eq(PlayOrderInfoEntity::getPlaceType, OrderConstant.PlaceType.SPECIFIED.getCode())
|
||||
.count();
|
||||
|
||||
String payload = "{" +
|
||||
"\"clerkId\":\"" + ApiTestDataSeeder.DEFAULT_CLERK_ID + "\"," +
|
||||
"\"commodityId\":\"" + ApiTestDataSeeder.DEFAULT_COMMODITY_ID + "\"," +
|
||||
"\"commodityQuantity\":1," +
|
||||
"\"weiChatCode\":\"apitest-customer-wx\"," +
|
||||
"\"couponIds\":[]," +
|
||||
"\"remark\":\"" + remark + "\"" +
|
||||
"}";
|
||||
|
||||
reset(wxCustomMpService);
|
||||
|
||||
mockMvc.perform(post("/wx/custom/order/commodity")
|
||||
.header(USER_HEADER, DEFAULT_USER)
|
||||
.header(TENANT_HEADER, DEFAULT_TENANT)
|
||||
.header(Constants.CUSTOM_USER_LOGIN_TOKEN, Constants.TOKEN_PREFIX + customerToken)
|
||||
.contentType(MediaType.APPLICATION_JSON)
|
||||
.content(payload))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(jsonPath("$.code").value(200))
|
||||
.andExpect(jsonPath("$.data").value("成功"));
|
||||
|
||||
ensureTenantContext();
|
||||
PlayOrderInfoEntity order = playOrderInfoService.lambdaQuery()
|
||||
.eq(PlayOrderInfoEntity::getPurchaserBy, ApiTestDataSeeder.DEFAULT_CUSTOMER_ID)
|
||||
.eq(PlayOrderInfoEntity::getRemark, remark)
|
||||
.orderByDesc(PlayOrderInfoEntity::getCreatedTime)
|
||||
.last("limit 1")
|
||||
.one();
|
||||
|
||||
Assertions.assertThat(order).isNotNull();
|
||||
Assertions.assertThat(order.getPlaceType()).isEqualTo(OrderConstant.PlaceType.SPECIFIED.getCode());
|
||||
Assertions.assertThat(order.getOrderStatus()).isEqualTo(OrderConstant.OrderStatus.PENDING.getCode());
|
||||
Assertions.assertThat(order.getAcceptBy()).isEqualTo(ApiTestDataSeeder.DEFAULT_CLERK_ID);
|
||||
Assertions.assertThat(order.getFinalAmount()).isEqualByComparingTo(ApiTestDataSeeder.DEFAULT_COMMODITY_PRICE);
|
||||
|
||||
verify(wxCustomMpService).sendCreateOrderMessage(
|
||||
eq(ApiTestDataSeeder.DEFAULT_TENANT_ID),
|
||||
eq(ApiTestDataSeeder.DEFAULT_CLERK_OPEN_ID),
|
||||
anyString(),
|
||||
eq(order.getFinalAmount().toString()),
|
||||
eq(order.getCommodityName()),
|
||||
eq(order.getId()));
|
||||
|
||||
ensureTenantContext();
|
||||
long afterCount = playOrderInfoService.lambdaQuery()
|
||||
.eq(PlayOrderInfoEntity::getPurchaserBy, ApiTestDataSeeder.DEFAULT_CUSTOMER_ID)
|
||||
.eq(PlayOrderInfoEntity::getPlaceType, OrderConstant.PlaceType.SPECIFIED.getCode())
|
||||
.count();
|
||||
Assertions.assertThat(afterCount).isEqualTo(beforeCount + 1);
|
||||
} finally {
|
||||
CustomSecurityContextHolder.remove();
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user