From 51c4a5438d0010ba17fd9e15fe0532c462eba49b Mon Sep 17 00:00:00 2001 From: irving Date: Tue, 11 Nov 2025 20:48:20 -0500 Subject: [PATCH] feat: improve wechat order query coverage --- .../impl/PlayOrderInfoServiceImpl.java | 5 + .../order/PlayCustomOrderDetailsReturnVo.java | 3 +- .../order/PlayCustomOrderInfoQueryVo.java | 7 +- .../order/PlayCustomOrderListReturnVo.java | 3 +- .../admin/api/WxCustomOrderQueryApiTest.java | 511 ++++++++++++++++++ 5 files changed, 524 insertions(+), 5 deletions(-) create mode 100644 play-admin/src/test/java/com/starry/admin/api/WxCustomOrderQueryApiTest.java diff --git a/play-admin/src/main/java/com/starry/admin/modules/order/service/impl/PlayOrderInfoServiceImpl.java b/play-admin/src/main/java/com/starry/admin/modules/order/service/impl/PlayOrderInfoServiceImpl.java index 62f0c2d..5a131b7 100644 --- a/play-admin/src/main/java/com/starry/admin/modules/order/service/impl/PlayOrderInfoServiceImpl.java +++ b/play-admin/src/main/java/com/starry/admin/modules/order/service/impl/PlayOrderInfoServiceImpl.java @@ -547,6 +547,11 @@ public class PlayOrderInfoServiceImpl extends ServiceImpl customSelectOrderInfoByPage(PlayCustomOrderInfoQueryVo vo) { MPJLambdaWrapper lambdaQueryWrapper = getCommonOrderQueryVo( ConvertUtil.entityToVo(vo, PlayOrderInfoEntity.class)); + if (StringUtils.isBlank(vo.getOrderType())) { + lambdaQueryWrapper.notIn(PlayOrderInfoEntity::getOrderType, + OrderConstant.OrderType.RECHARGE.getCode(), + OrderConstant.OrderType.WITHDRAWAL.getCode()); + } IPage page = this.baseMapper.selectJoinPage( new Page<>(vo.getPageNum(), vo.getPageSize()), PlayCustomOrderListReturnVo.class, lambdaQueryWrapper); // 获取当前顾客所有订单评价信息,将订单评价信息转化为 map<订单ID,订单ID>的结构 diff --git a/play-admin/src/main/java/com/starry/admin/modules/weichat/entity/order/PlayCustomOrderDetailsReturnVo.java b/play-admin/src/main/java/com/starry/admin/modules/weichat/entity/order/PlayCustomOrderDetailsReturnVo.java index 42988f6..563524b 100644 --- a/play-admin/src/main/java/com/starry/admin/modules/weichat/entity/order/PlayCustomOrderDetailsReturnVo.java +++ b/play-admin/src/main/java/com/starry/admin/modules/weichat/entity/order/PlayCustomOrderDetailsReturnVo.java @@ -25,7 +25,8 @@ public class PlayCustomOrderDetailsReturnVo { private String orderNo; /** - * 订单状态【0:1:2:3:4】 0:已下单(待接单) 1:已接单(待开始) 2:已开始(服务中) 3:已完成 4:已取消 + * 订单状态【0:1:2:3:4:5】 + * 0:已下单(待接单) 1:已接单(待开始) 2:已开始(服务中) 3:已完成 4:已取消 5:已撤销 */ private String orderStatus; diff --git a/play-admin/src/main/java/com/starry/admin/modules/weichat/entity/order/PlayCustomOrderInfoQueryVo.java b/play-admin/src/main/java/com/starry/admin/modules/weichat/entity/order/PlayCustomOrderInfoQueryVo.java index 843452a..5ea57bc 100644 --- a/play-admin/src/main/java/com/starry/admin/modules/weichat/entity/order/PlayCustomOrderInfoQueryVo.java +++ b/play-admin/src/main/java/com/starry/admin/modules/weichat/entity/order/PlayCustomOrderInfoQueryVo.java @@ -16,14 +16,15 @@ public class PlayCustomOrderInfoQueryVo extends BasePageEntity { private String id; /** - * 订单状态【0:1:2:3:4】 0:已下单 1:已接单 2:已开始 3:已完成 4:已取消 + * 订单状态【0:1:2:3:4:5】 + * 0:已下单 1:已接单 2:已开始 3:已完成 4:已取消 5:已撤销 */ private String orderStatus; /** - * 订单类型【0:充值订单;1:提现订单;2:普通订单】 + * 订单类型(为空时默认排除充值/提现) */ - private String orderType = "2"; + private String orderType; /** * 下单类型(0:指定单,1:随机单。2:打赏单) diff --git a/play-admin/src/main/java/com/starry/admin/modules/weichat/entity/order/PlayCustomOrderListReturnVo.java b/play-admin/src/main/java/com/starry/admin/modules/weichat/entity/order/PlayCustomOrderListReturnVo.java index 60f3eff..b70bd1e 100644 --- a/play-admin/src/main/java/com/starry/admin/modules/weichat/entity/order/PlayCustomOrderListReturnVo.java +++ b/play-admin/src/main/java/com/starry/admin/modules/weichat/entity/order/PlayCustomOrderListReturnVo.java @@ -25,7 +25,8 @@ public class PlayCustomOrderListReturnVo { private String orderNo; /** - * 订单状态【0:1:2:3:4】 0:已下单(待接单) 1:已接单(待开始) 2:已开始(服务中) 3:已完成 4:已取消 + * 订单状态【0:1:2:3:4:5】 + * 0:已下单(待接单) 1:已接单(待开始) 2:已开始(服务中) 3:已完成 4:已取消 5:已撤销 */ private String orderStatus; diff --git a/play-admin/src/test/java/com/starry/admin/api/WxCustomOrderQueryApiTest.java b/play-admin/src/test/java/com/starry/admin/api/WxCustomOrderQueryApiTest.java new file mode 100644 index 0000000..f3d52eb --- /dev/null +++ b/play-admin/src/test/java/com/starry/admin/api/WxCustomOrderQueryApiTest.java @@ -0,0 +1,511 @@ +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.ArrayNode; +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.PlayOrderComplaintInfoEntity; +import com.starry.admin.modules.order.module.entity.PlayOrderEvaluateInfoEntity; +import com.starry.admin.modules.order.module.entity.PlayOrderInfoEntity; +import com.starry.admin.modules.order.service.IPlayOrderComplaintInfoService; +import com.starry.admin.modules.order.service.IPlayOrderEvaluateInfoService; +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.time.LocalDateTime; +import java.util.ArrayList; +import java.util.List; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.MediaType; +import org.springframework.test.web.servlet.MvcResult; + +class WxCustomOrderQueryApiTest extends WxCustomOrderApiTestSupport { + + @Autowired + private IPlayOrderEvaluateInfoService playOrderEvaluateInfoService; + + @Autowired + private IPlayOrderComplaintInfoService playOrderComplaintInfoService; + + private final List orderIdsToCleanup = new ArrayList<>(); + private final List evalIdsToCleanup = new ArrayList<>(); + private final List complaintIdsToCleanup = new ArrayList<>(); + + @AfterEach + void cleanUpOrders() { + if (!orderIdsToCleanup.isEmpty()) { + playOrderInfoService.removeByIds(orderIdsToCleanup); + orderIdsToCleanup.clear(); + } + if (!evalIdsToCleanup.isEmpty()) { + playOrderEvaluateInfoService.removeByIds(evalIdsToCleanup); + evalIdsToCleanup.clear(); + } + if (!complaintIdsToCleanup.isEmpty()) { + playOrderComplaintInfoService.removeByIds(complaintIdsToCleanup); + complaintIdsToCleanup.clear(); + } + } + + @Test + void queryByPageFiltersRevokedOrdersAndDetailShowsReason() 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 = "revoked-flow-" + IdUtils.getUuid(); + placeRandomOrder(remark, customerToken); + + ensureTenantContext(); + PlayOrderInfoEntity createdOrder = playOrderInfoService.lambdaQuery() + .eq(PlayOrderInfoEntity::getPurchaserBy, ApiTestDataSeeder.DEFAULT_CUSTOMER_ID) + .eq(PlayOrderInfoEntity::getRemark, remark) + .orderByDesc(PlayOrderInfoEntity::getCreatedTime) + .last("limit 1") + .one(); + assertThat(createdOrder).as("Order with remark %s should exist", remark).isNotNull(); + + String orderId = createdOrder.getId(); + ensureTenantContext(); + playOrderInfoService.lambdaUpdate() + .set(PlayOrderInfoEntity::getOrderType, OrderConstant.OrderType.GIFT.getCode()) + .eq(PlayOrderInfoEntity::getId, orderId) + .update(); + ensureTenantContext(); + playOrderInfoService.updateStateTo1( + OrderConstant.OperatorType.CLERK.getCode(), + ApiTestDataSeeder.DEFAULT_CLERK_ID, + ApiTestDataSeeder.DEFAULT_CLERK_ID, + orderId); + ensureTenantContext(); + playOrderInfoService.updateStateTo23( + OrderConstant.OperatorType.CLERK.getCode(), + ApiTestDataSeeder.DEFAULT_CLERK_ID, + OrderConstant.OrderStatus.IN_PROGRESS.getCode(), + orderId); + ensureTenantContext(); + playOrderInfoService.updateStateTo23( + OrderConstant.OperatorType.ADMIN.getCode(), + ApiTestDataSeeder.DEFAULT_ADMIN_USER_ID, + OrderConstant.OrderStatus.COMPLETED.getCode(), + orderId); + + String revokeReason = "auto-revoke-" + IdUtils.getUuid(); + String revokePayload = "{" + + "\"orderId\":\"" + orderId + "\"," + + "\"refundToCustomer\":false," + + "\"refundReason\":\"" + revokeReason + "\"," + + "\"earningsStrategy\":\"NONE\"" + + "}"; + + mockMvc.perform(post("/order/order/revokeCompleted") + .header(USER_HEADER, DEFAULT_USER) + .header(TENANT_HEADER, DEFAULT_TENANT) + .contentType(MediaType.APPLICATION_JSON) + .content(revokePayload)) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.code").value(200)); + + ObjectNode filterPayload = basePayload(1, 10); + filterPayload.put("orderStatus", OrderConstant.OrderStatus.REVOKED.getCode()); + JsonNode listRoot = executeOrderQuery(customerToken, filterPayload); + JsonNode dataNode = listRoot.path("data"); + JsonNode records = dataNode.isArray() ? dataNode : dataNode.path("records"); + assertThat(records.isArray()).as("List response should contain records array").isTrue(); + assertThat(records.size()).as("Should return at least one revoked order").isGreaterThan(0); + boolean found = false; + for (JsonNode node : records) { + assertThat(node.path("orderStatus").asText()).isEqualTo("5"); + if (orderId.equals(node.path("id").asText())) { + found = true; + } + } + assertThat(found).as("Revoked order should be present in filter result").isTrue(); + + MvcResult detailResult = mockMvc.perform(get("/wx/custom/order/queryById") + .header(USER_HEADER, DEFAULT_USER) + .header(TENANT_HEADER, DEFAULT_TENANT) + .header(Constants.CUSTOM_USER_LOGIN_TOKEN, Constants.TOKEN_PREFIX + customerToken) + .param("id", orderId)) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.code").value(200)) + .andReturn(); + + JsonNode detailRoot = objectMapper.readTree(detailResult.getResponse().getContentAsString()); + JsonNode detail = detailRoot.path("data"); + assertThat(detail.path("orderStatus").asText()).isEqualTo("5"); + assertThat(detail.path("refundReason").asText()).isEqualTo(revokeReason); + } finally { + CustomSecurityContextHolder.remove(); + } + } + + @Test + void queryByPageSkipsRechargeOrdersByDefaultButAllowsExplicitFilter() 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 rechargeRemark = "recharge-like-" + IdUtils.getUuid(); + placeRandomOrder(rechargeRemark, customerToken); + PlayOrderInfoEntity rechargeOrder = playOrderInfoService.lambdaQuery() + .eq(PlayOrderInfoEntity::getPurchaserBy, ApiTestDataSeeder.DEFAULT_CUSTOMER_ID) + .eq(PlayOrderInfoEntity::getRemark, rechargeRemark) + .orderByDesc(PlayOrderInfoEntity::getCreatedTime) + .last("limit 1") + .one(); + assertThat(rechargeOrder).isNotNull(); + ensureTenantContext(); + playOrderInfoService.lambdaUpdate() + .set(PlayOrderInfoEntity::getOrderType, OrderConstant.OrderType.RECHARGE.getCode()) + .eq(PlayOrderInfoEntity::getId, rechargeOrder.getId()) + .update(); + + String giftRemark = "gift-like-" + IdUtils.getUuid(); + placeRandomOrder(giftRemark, customerToken); + PlayOrderInfoEntity giftOrder = playOrderInfoService.lambdaQuery() + .eq(PlayOrderInfoEntity::getPurchaserBy, ApiTestDataSeeder.DEFAULT_CUSTOMER_ID) + .eq(PlayOrderInfoEntity::getRemark, giftRemark) + .orderByDesc(PlayOrderInfoEntity::getCreatedTime) + .last("limit 1") + .one(); + assertThat(giftOrder).isNotNull(); + ensureTenantContext(); + playOrderInfoService.lambdaUpdate() + .set(PlayOrderInfoEntity::getOrderType, OrderConstant.OrderType.GIFT.getCode()) + .eq(PlayOrderInfoEntity::getId, giftOrder.getId()) + .update(); + + ObjectNode defaultPayload = basePayload(1, 20); + JsonNode defaultRecords = queryOrders(customerToken, defaultPayload); + assertThat(defaultRecords.size()).isGreaterThan(0); + assertThat(defaultRecords).noneMatch(node -> rechargeOrder.getId().equals(node.path("id").asText())); + + ObjectNode explicitPayload = basePayload(1, 20); + explicitPayload.put("orderType", OrderConstant.OrderType.GIFT.getCode()); + JsonNode filteredRecords = queryOrders(customerToken, explicitPayload); + assertThat(filteredRecords) + .anyMatch(node -> giftOrder.getId().equals(node.path("id").asText())); + } finally { + CustomSecurityContextHolder.remove(); + } + } + + @Test + void queryByPageReturnsOnlyOrdersBelongingToCurrentCustomer() throws Exception { + SecurityUtils.setTenantId(ApiTestDataSeeder.DEFAULT_TENANT_ID); + try { + String token = ensureCustomerToken(); + LocalDateTime base = LocalDateTime.now().minusMinutes(30); + PlayOrderInfoEntity own = persistOrder(base, order -> order.setOrderNo("OWN-" + IdUtils.getUuid().substring(0, 6))); + PlayOrderInfoEntity foreign = persistOrder(base.plusMinutes(5), order -> { + order.setPurchaserBy("other-customer"); + order.setOrderNo("FOREIGN-" + IdUtils.getUuid().substring(0, 6)); + }); + + ObjectNode payload = basePayload(1, 20); + JsonNode records = queryOrders(token, payload); + List ids = new ArrayList<>(); + records.forEach(node -> ids.add(node.path("id").asText())); + assertThat(ids).contains(own.getId()); + assertThat(ids).doesNotContain(foreign.getId()); + } finally { + CustomSecurityContextHolder.remove(); + } + } + + @Test + void queryByPageSupportsPagingMeta() throws Exception { + SecurityUtils.setTenantId(ApiTestDataSeeder.DEFAULT_TENANT_ID); + try { + String token = ensureCustomerToken(); + LocalDateTime now = LocalDateTime.now().minusMinutes(60); + PlayOrderInfoEntity first = persistOrder(now, order -> order.setOrderNo("PAGE-A")); + PlayOrderInfoEntity second = persistOrder(now.plusMinutes(2), order -> order.setOrderNo("PAGE-B")); + PlayOrderInfoEntity third = persistOrder(now.plusMinutes(4), order -> order.setOrderNo("PAGE-C")); + + ObjectNode pageOne = basePayload(1, 2); + JsonNode rootPageOne = executeOrderQuery(token, pageOne); + JsonNode dataOne = rootPageOne.path("data"); + JsonNode recordsOne = dataOne.path("records"); + assertThat(recordsOne.size()).isEqualTo(2); + assertThat(dataOne.path("total").asInt()).isEqualTo(3); + + ObjectNode pageTwo = basePayload(2, 2); + JsonNode rootPageTwo = executeOrderQuery(token, pageTwo); + JsonNode recordsTwo = rootPageTwo.path("data").path("records"); + assertThat(recordsTwo.size()).isEqualTo(1); + assertThat(recordsTwo.get(0).path("id").asText()).isIn(first.getId(), second.getId(), third.getId()); + } finally { + CustomSecurityContextHolder.remove(); + } + } + + @Test + void queryByPageFiltersByOrderStatus() throws Exception { + SecurityUtils.setTenantId(ApiTestDataSeeder.DEFAULT_TENANT_ID); + try { + String token = ensureCustomerToken(); + PlayOrderInfoEntity pending = persistOrder(LocalDateTime.now().minusMinutes(50), + order -> order.setOrderStatus(OrderConstant.OrderStatus.PENDING.getCode())); + PlayOrderInfoEntity completed = persistOrder(LocalDateTime.now().minusMinutes(40), + order -> order.setOrderStatus(OrderConstant.OrderStatus.COMPLETED.getCode())); + PlayOrderInfoEntity revoked = persistOrder(LocalDateTime.now().minusMinutes(30), + order -> order.setOrderStatus(OrderConstant.OrderStatus.REVOKED.getCode())); + + ObjectNode payload = basePayload(1, 10); + payload.put("orderStatus", OrderConstant.OrderStatus.REVOKED.getCode()); + JsonNode records = queryOrders(token, payload); + assertThat(records.size()).isEqualTo(1); + assertThat(records.get(0).path("id").asText()).isEqualTo(revoked.getId()); + } finally { + CustomSecurityContextHolder.remove(); + } + } + + @Test + void queryByPageFiltersByPlaceTypeAndCompositeCriteria() throws Exception { + SecurityUtils.setTenantId(ApiTestDataSeeder.DEFAULT_TENANT_ID); + try { + String token = ensureCustomerToken(); + LocalDateTime base = LocalDateTime.now().minusMinutes(90); + PlayOrderInfoEntity target = persistOrder(base, order -> { + order.setOrderStatus(OrderConstant.OrderStatus.IN_PROGRESS.getCode()); + order.setPlaceType(OrderConstant.PlaceType.SPECIFIED.getCode()); + order.setOrderNo("FOCUS-" + IdUtils.getUuid().substring(0, 4)); + order.setUseCoupon("1"); + order.setBackendEntry("1"); + order.setFirstOrder("1"); + order.setGroupId("group-focus"); + order.setSex("1"); + order.setPurchaserTime(base.plusMinutes(5)); + order.setAcceptTime(base.plusMinutes(10)); + order.setOrderEndTime(base.plusMinutes(50)); + }); + persistOrder(base.plusMinutes(5), order -> { + order.setOrderStatus(OrderConstant.OrderStatus.IN_PROGRESS.getCode()); + order.setPlaceType(OrderConstant.PlaceType.RANDOM.getCode()); + order.setUseCoupon("0"); + order.setBackendEntry("0"); + order.setFirstOrder("0"); + order.setGroupId("group-noise"); + order.setSex("2"); + }); + + ObjectNode payload = basePayload(1, 10); + payload.put("placeType", OrderConstant.PlaceType.SPECIFIED.getCode()); + payload.put("orderNo", target.getOrderNo().substring(0, 6)); + payload.put("useCoupon", "1"); + payload.put("backendEntry", "1"); + payload.put("firstOrder", "1"); + payload.put("groupId", "group-focus"); + payload.put("sex", "1"); + payload.set("purchaserTime", range(target.getPurchaserTime().minusMinutes(1), target.getPurchaserTime().plusMinutes(1))); + payload.set("acceptTime", range(target.getAcceptTime().minusMinutes(1), target.getAcceptTime().plusMinutes(1))); + payload.set("endOrderTime", range(target.getOrderEndTime().minusMinutes(1), target.getOrderEndTime().plusMinutes(1))); + + JsonNode records = queryOrders(token, payload); + assertThat(records.size()).isEqualTo(1); + assertThat(records.get(0).path("id").asText()).isEqualTo(target.getId()); + } finally { + CustomSecurityContextHolder.remove(); + } + } + + @Test + void queryByPageMarksEvaluateAndComplaintFlags() throws Exception { + SecurityUtils.setTenantId(ApiTestDataSeeder.DEFAULT_TENANT_ID); + try { + String token = ensureCustomerToken(); + PlayOrderInfoEntity evaluated = persistOrder(LocalDateTime.now().minusMinutes(10), + order -> order.setOrderNo("EVAL-" + IdUtils.getUuid().substring(0, 4))); + PlayOrderInfoEntity complained = persistOrder(LocalDateTime.now().minusMinutes(8), + order -> order.setOrderNo("COMP-" + IdUtils.getUuid().substring(0, 4))); + markEvaluated(evaluated.getId()); + markComplained(complained.getId()); + + ObjectNode payload = basePayload(1, 20); + JsonNode records = queryOrders(token, payload); + String evalFlag = findById(records, evaluated.getId()).path("evaluate").asText(); + String complaintFlag = findById(records, complained.getId()).path("complaint").asText(); + assertThat(evalFlag).isEqualTo("1"); + assertThat(complaintFlag).isEqualTo("1"); + } finally { + CustomSecurityContextHolder.remove(); + } + } + + private void placeRandomOrder(String remark, String customerToken) throws Exception { + String payload = "{" + + "\"sex\":\"2\"," + + "\"levelId\":\"" + ApiTestDataSeeder.DEFAULT_CLERK_LEVEL_ID + "\"," + + "\"commodityId\":\"" + ApiTestDataSeeder.DEFAULT_COMMODITY_ID + "\"," + + "\"commodityQuantity\":1," + + "\"weiChatCode\":\"apitest-customer-wx\"," + + "\"excludeHistory\":\"0\"," + + "\"couponIds\":[]," + + "\"remark\":\"" + remark + "\"" + + "}"; + + mockMvc.perform(post("/wx/custom/order/random") + .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("下单成功")); + } + + private PlayOrderInfoEntity persistOrder(LocalDateTime baseTime, java.util.function.Consumer customizer) { + PlayOrderInfoEntity order = new PlayOrderInfoEntity(); + order.setId("order-" + IdUtils.getUuid()); + order.setOrderNo("WXQ-" + IdUtils.getUuid().substring(0, 8)); + order.setTenantId(ApiTestDataSeeder.DEFAULT_TENANT_ID); + order.setOrderStatus(OrderConstant.OrderStatus.PENDING.getCode()); + order.setOrderType(OrderConstant.OrderType.NORMAL.getCode()); + order.setPlaceType(OrderConstant.PlaceType.SPECIFIED.getCode()); + order.setRewardType("0"); + order.setFirstOrder("0"); + order.setRefundType("0"); + order.setRefundAmount(BigDecimal.ZERO); + order.setOrderMoney(new BigDecimal("99.00")); + order.setFinalAmount(new BigDecimal("99.00")); + order.setDiscountAmount(BigDecimal.ZERO); + order.setEstimatedRevenue(new BigDecimal("40.00")); + order.setEstimatedRevenueRatio(40); + order.setUseCoupon("0"); + order.setBackendEntry("0"); + order.setCouponIds(java.util.Collections.emptyList()); + order.setPaymentSource("balance"); + order.setPayMethod("0"); + order.setPayState("1"); + order.setPurchaserBy(ApiTestDataSeeder.DEFAULT_CUSTOMER_ID); + order.setPurchaserTime(baseTime); + order.setAcceptBy(ApiTestDataSeeder.DEFAULT_CLERK_ID); + order.setAcceptTime(baseTime.plusMinutes(5)); + order.setGroupId(ApiTestDataSeeder.DEFAULT_GROUP_ID); + order.setOrderStartTime(baseTime.plusMinutes(10)); + order.setOrderEndTime(baseTime.plusMinutes(40)); + order.setOrdersExpiredState("0"); + order.setOrderSettlementState("0"); + order.setSex("2"); + order.setCommodityId(ApiTestDataSeeder.DEFAULT_COMMODITY_ID); + order.setCommodityType("1"); + order.setCommodityPrice(new BigDecimal("99.00")); + order.setCommodityName("Weixin Order"); + order.setServiceDuration("60min"); + order.setCommodityNumber("1"); + order.setRemark("auto"); + order.setBackendRemark("auto"); + order.setCreatedTime(baseTime); + order.setUpdatedTime(baseTime); + order.setCreatedBy("wx-test"); + order.setUpdatedBy("wx-test"); + customizer.accept(order); + ensureTenantContext(); + playOrderInfoService.save(order); + orderIdsToCleanup.add(order.getId()); + return order; + } + + private ObjectNode basePayload(int pageNum, int pageSize) { + ObjectNode node = objectMapper.createObjectNode(); + node.put("pageNum", pageNum); + node.put("pageSize", pageSize); + return node; + } + + private ArrayNode range(LocalDateTime start, LocalDateTime end) { + ArrayNode node = objectMapper.createArrayNode(); + node.add(DATE_TIME_FORMATTER.format(start)); + node.add(DATE_TIME_FORMATTER.format(end)); + return node; + } + + private String ensureCustomerToken() { + resetCustomerBalance(); + String customerToken = wxTokenService.createWxUserToken(ApiTestDataSeeder.DEFAULT_CUSTOMER_ID); + customUserInfoService.updateTokenById(ApiTestDataSeeder.DEFAULT_CUSTOMER_ID, customerToken); + return customerToken; + } + + private void markEvaluated(String orderId) { + PlayOrderEvaluateInfoEntity entity = new PlayOrderEvaluateInfoEntity(); + entity.setId("eval-" + IdUtils.getUuid()); + entity.setTenantId(ApiTestDataSeeder.DEFAULT_TENANT_ID); + entity.setOrderId(orderId); + entity.setCustomId(ApiTestDataSeeder.DEFAULT_CUSTOMER_ID); + entity.setClerkId(ApiTestDataSeeder.DEFAULT_CLERK_ID); + entity.setCommodityId(ApiTestDataSeeder.DEFAULT_COMMODITY_ID); + entity.setAnonymous("0"); + entity.setEvaluateType("0"); + entity.setEvaluateLevel(5); + entity.setEvaluateCon("Great job"); + entity.setEvaluateTime(java.sql.Timestamp.valueOf(LocalDateTime.now())); + entity.setHidden("0"); + ensureTenantContext(); + playOrderEvaluateInfoService.save(entity); + evalIdsToCleanup.add(entity.getId()); + } + + private void markComplained(String orderId) { + PlayOrderComplaintInfoEntity entity = new PlayOrderComplaintInfoEntity(); + entity.setId("complaint-" + IdUtils.getUuid()); + entity.setTenantId(ApiTestDataSeeder.DEFAULT_TENANT_ID); + entity.setOrderId(orderId); + entity.setCustomId(ApiTestDataSeeder.DEFAULT_CUSTOMER_ID); + entity.setClerkId(ApiTestDataSeeder.DEFAULT_CLERK_ID); + entity.setCommodityId(ApiTestDataSeeder.DEFAULT_COMMODITY_ID); + entity.setComplaintCon("Need assistance"); + entity.setComplaintTime(java.sql.Timestamp.valueOf(LocalDateTime.now())); + entity.setHidden("0"); + ensureTenantContext(); + playOrderComplaintInfoService.save(entity); + complaintIdsToCleanup.add(entity.getId()); + } + + private JsonNode findById(JsonNode records, String id) { + for (JsonNode node : records) { + if (id.equals(node.path("id").asText())) { + return node; + } + } + throw new AssertionError("Record with id " + id + " not found in response"); + } + + private JsonNode queryOrders(String customerToken, ObjectNode payload) throws Exception { + JsonNode root = executeOrderQuery(customerToken, payload); + JsonNode dataNode = root.path("data"); + return dataNode.isArray() ? dataNode : dataNode.path("records"); + } + + private JsonNode executeOrderQuery(String customerToken, ObjectNode payload) throws Exception { + MvcResult result = mockMvc.perform(post("/wx/custom/order/queryByPage") + .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.toString())) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.code").value(200)) + .andReturn(); + return objectMapper.readTree(result.getResponse().getContentAsString()); + } +}