- Add OrderRelationType enum (UNASSIGNED, LEGACY, FIRST, CONTINUED, NEUTRAL) - Create play_clerk_customer_relation table to track first-completed history - Add order_relation_type column to play_order_info - Migrate existing orders to set relation types based on completion history - Update order services to determine relation type on creation - Update order VOs and controllers to expose relation type in API responses - Update clerk performance calculations to account for relation types - Update revenue calculations to distinguish between first and continued orders - Add comprehensive API and unit tests for order relation functionality
198 lines
8.5 KiB
Java
198 lines
8.5 KiB
Java
package com.starry.admin.api;
|
|
|
|
import static org.assertj.core.api.Assertions.assertThat;
|
|
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.fasterxml.jackson.databind.JsonNode;
|
|
import com.fasterxml.jackson.databind.node.ObjectNode;
|
|
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.utils.SecurityUtils;
|
|
import com.starry.common.constant.Constants;
|
|
import com.starry.common.utils.IdUtils;
|
|
import java.math.BigDecimal;
|
|
import java.time.LocalDateTime;
|
|
import java.util.Date;
|
|
import org.junit.jupiter.api.AfterEach;
|
|
import org.junit.jupiter.api.Test;
|
|
import org.springframework.http.MediaType;
|
|
|
|
class LegacyOrderIntegrationTest extends WxCustomOrderApiTestSupport {
|
|
|
|
private String orderIdToCleanup;
|
|
|
|
@AfterEach
|
|
void tearDown() {
|
|
if (orderIdToCleanup != null) {
|
|
ensureTenantContext();
|
|
playOrderInfoService.removeById(orderIdToCleanup);
|
|
orderIdToCleanup = null;
|
|
}
|
|
}
|
|
|
|
@Test
|
|
void getLegacyOrderDetails_Admin_ShouldReturnLegacyType() throws Exception {
|
|
ensureTenantContext();
|
|
PlayOrderInfoEntity legacyOrder = createLegacyOrder();
|
|
|
|
mockMvc.perform(get("/order/order/" + legacyOrder.getId())
|
|
.header(TENANT_HEADER, DEFAULT_TENANT)
|
|
.header(USER_HEADER, DEFAULT_USER)
|
|
.contentType(MediaType.APPLICATION_JSON))
|
|
.andExpect(status().isOk())
|
|
.andExpect(jsonPath("$.code").value(200))
|
|
.andExpect(jsonPath("$.data.orderRelationType").value("LEGACY"));
|
|
}
|
|
|
|
@Test
|
|
void listByPage_Admin_ShouldReturnLegacyType() throws Exception {
|
|
ensureTenantContext();
|
|
PlayOrderInfoEntity legacyOrder = createLegacyOrder();
|
|
|
|
ObjectNode payload = objectMapper.createObjectNode();
|
|
payload.put("pageNum", 1);
|
|
payload.put("pageSize", 10);
|
|
payload.put("orderNo", legacyOrder.getOrderNo());
|
|
|
|
String response = mockMvc.perform(post("/order/order/listByPage")
|
|
.header(TENANT_HEADER, DEFAULT_TENANT)
|
|
.header(USER_HEADER, ApiTestDataSeeder.DEFAULT_ADMIN_USER_ID)
|
|
.contentType(MediaType.APPLICATION_JSON)
|
|
.content(payload.toString()))
|
|
.andExpect(status().isOk())
|
|
.andExpect(jsonPath("$.code").value(200))
|
|
.andReturn().getResponse().getContentAsString();
|
|
|
|
JsonNode root = objectMapper.readTree(response);
|
|
JsonNode data = root.path("data");
|
|
JsonNode records = data.isArray() ? data : data.path("records");
|
|
String type = records.get(0).path("orderRelationType").asText();
|
|
assertThat(type).isEqualTo("LEGACY");
|
|
}
|
|
private String ensureCustomerToken() {
|
|
resetCustomerBalance();
|
|
String customerToken = wxTokenService.createWxUserToken(ApiTestDataSeeder.DEFAULT_CUSTOMER_ID);
|
|
customUserInfoService.updateTokenById(ApiTestDataSeeder.DEFAULT_CUSTOMER_ID, customerToken);
|
|
return customerToken;
|
|
}
|
|
|
|
@Test
|
|
void queryById_WxCustom_ShouldReturnLegacyType() throws Exception {
|
|
ensureTenantContext();
|
|
PlayOrderInfoEntity legacyOrder = createLegacyOrder();
|
|
String customerToken = ensureCustomerToken();
|
|
|
|
mockMvc.perform(get("/wx/custom/order/queryById")
|
|
.header(TENANT_HEADER, DEFAULT_TENANT)
|
|
.header(Constants.CUSTOM_USER_LOGIN_TOKEN, Constants.TOKEN_PREFIX + customerToken)
|
|
.param("id", legacyOrder.getId()))
|
|
.andExpect(status().isOk())
|
|
.andExpect(jsonPath("$.code").value(200))
|
|
.andExpect(jsonPath("$.data.orderRelationType").value("LEGACY"));
|
|
}
|
|
|
|
@Test
|
|
void queryByPage_WxCustom_ShouldReturnLegacyType() throws Exception {
|
|
ensureTenantContext();
|
|
PlayOrderInfoEntity legacyOrder = createLegacyOrder();
|
|
String customerToken = ensureCustomerToken();
|
|
|
|
ObjectNode payload = objectMapper.createObjectNode();
|
|
payload.put("pageNum", 1);
|
|
payload.put("pageSize", 20);
|
|
|
|
String response = mockMvc.perform(post("/wx/custom/order/queryByPage")
|
|
.header(TENANT_HEADER, DEFAULT_TENANT)
|
|
.header(Constants.CUSTOM_USER_LOGIN_TOKEN, Constants.TOKEN_PREFIX + customerToken)
|
|
.contentType(MediaType.APPLICATION_JSON)
|
|
.content(payload.toString()))
|
|
.andExpect(status().isOk())
|
|
.andExpect(jsonPath("$.code").value(200))
|
|
.andReturn().getResponse().getContentAsString();
|
|
|
|
JsonNode root = objectMapper.readTree(response);
|
|
JsonNode records = root.path("data").isArray() ? root.path("data") : root.path("data").path("records");
|
|
boolean found = false;
|
|
for (JsonNode node : records) {
|
|
if (legacyOrder.getId().equals(node.path("id").asText())) {
|
|
assertThat(node.path("orderRelationType").asText()).isEqualTo("LEGACY");
|
|
found = true;
|
|
break;
|
|
}
|
|
}
|
|
assertThat(found).withFailMessage("Legacy order not found in customer list").isTrue();
|
|
}
|
|
|
|
@Test
|
|
void calculateEstimatedRevenue_ForLegacyOrder_ShouldNotFail() throws Exception {
|
|
ensureTenantContext();
|
|
PlayOrderInfoEntity legacyOrder = createLegacyOrder();
|
|
|
|
BigDecimal revenue = playOrderInfoService.getEstimatedRevenue(
|
|
legacyOrder.getAcceptBy(),
|
|
legacyOrder.getPlaceType(),
|
|
legacyOrder.getOrderRelationType(),
|
|
legacyOrder.getOrderMoney()
|
|
);
|
|
|
|
assertThat(revenue).isNotNull();
|
|
assertThat(revenue).isGreaterThanOrEqualTo(BigDecimal.ZERO);
|
|
}
|
|
|
|
@Test
|
|
void calculateEstimatedRevenue_ForUnassignedOrder_ShouldThrowException() {
|
|
ensureTenantContext();
|
|
try {
|
|
playOrderInfoService.getEstimatedRevenue(
|
|
ApiTestDataSeeder.DEFAULT_CLERK_ID,
|
|
"0", // Specified
|
|
OrderConstant.OrderRelationType.UNASSIGNED,
|
|
new BigDecimal("100.00")
|
|
);
|
|
assertThat(true).withFailMessage("Should have thrown exception for UNASSIGNED relation type").isFalse();
|
|
} catch (Exception e) {
|
|
assertThat(e).isInstanceOf(RuntimeException.class);
|
|
assertThat(e.getMessage()).contains("未分配订单不可计算预计收益");
|
|
}
|
|
}
|
|
|
|
private PlayOrderInfoEntity createLegacyOrder() {
|
|
PlayOrderInfoEntity order = new PlayOrderInfoEntity();
|
|
String id = "legacy-" + IdUtils.getUuid();
|
|
order.setId(id);
|
|
order.setOrderNo("LEGACY" + IdUtils.getUuid().substring(0, 6));
|
|
order.setTenantId(ApiTestDataSeeder.DEFAULT_TENANT_ID);
|
|
order.setOrderStatus("3"); // Completed
|
|
order.setOrderType("2"); // Normal
|
|
order.setPlaceType("0"); // Specified
|
|
order.setOrderRelationType(OrderConstant.OrderRelationType.LEGACY);
|
|
order.setOrderMoney(new BigDecimal("100.00"));
|
|
order.setFinalAmount(new BigDecimal("100.00"));
|
|
order.setAcceptBy(ApiTestDataSeeder.DEFAULT_CLERK_ID);
|
|
order.setPurchaserBy(ApiTestDataSeeder.DEFAULT_CUSTOMER_ID);
|
|
order.setPurchaserTime(LocalDateTime.now().minusDays(100));
|
|
order.setCreatedTime(new Date());
|
|
order.setUpdatedTime(new Date());
|
|
order.setDeleted(false);
|
|
order.setPayMethod("2");
|
|
order.setUseCoupon("0");
|
|
order.setBackendEntry("0");
|
|
order.setSex("2");
|
|
order.setCommodityType("1");
|
|
order.setCommodityId(ApiTestDataSeeder.DEFAULT_COMMODITY_ID);
|
|
order.setCommodityName("Legacy Service");
|
|
order.setCommodityPrice(new BigDecimal("100.00"));
|
|
order.setCommodityNumber("1");
|
|
order.setRefundType("0");
|
|
order.setRefundAmount(BigDecimal.ZERO);
|
|
|
|
playOrderInfoService.save(order);
|
|
orderIdToCleanup = id;
|
|
return order;
|
|
}
|
|
}
|