UnifiedOrderTabTest.java 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284
  1. package com.ruoyi.app.unifiedorder;
  2. import com.baomidou.mybatisplus.core.MybatisConfiguration;
  3. import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
  4. import com.baomidou.mybatisplus.core.metadata.TableInfoHelper;
  5. import com.ruoyi.system.domain.PosOrder;
  6. import com.ruoyi.system.domain.flash.FlashDeliveryOrder;
  7. import com.ruoyi.system.domain.flash.FlashDeliveryStatus;
  8. import org.apache.ibatis.builder.MapperBuilderAssistant;
  9. import org.junit.jupiter.api.BeforeAll;
  10. import org.junit.jupiter.api.Test;
  11. import java.util.Collection;
  12. import java.util.List;
  13. import static org.junit.jupiter.api.Assertions.assertEquals;
  14. import static org.junit.jupiter.api.Assertions.assertFalse;
  15. import static org.junit.jupiter.api.Assertions.assertNull;
  16. import static org.junit.jupiter.api.Assertions.assertSame;
  17. import static org.junit.jupiter.api.Assertions.assertThrows;
  18. import static org.junit.jupiter.api.Assertions.assertTrue;
  19. /** 统一订单列表 tab 归类:两域内存判定全覆盖,规则照抄用户端订单列表现行语义。 */
  20. class UnifiedOrderTabTest {
  21. @BeforeAll
  22. static void initializeTableMetadata() {
  23. TableInfoHelper.initTableInfo(
  24. new MapperBuilderAssistant(new MybatisConfiguration(), ""), PosOrder.class);
  25. TableInfoHelper.initTableInfo(
  26. new MapperBuilderAssistant(new MybatisConfiguration(), ""), FlashDeliveryOrder.class);
  27. }
  28. // ---------- fromCode / queriesFlash ----------
  29. @Test
  30. void fromCodeDefaultsToAllAndRejectsUnknownValues() {
  31. assertSame(UnifiedOrderTab.ALL, UnifiedOrderTab.fromCode(null));
  32. assertSame(UnifiedOrderTab.ALL, UnifiedOrderTab.fromCode(""));
  33. assertSame(UnifiedOrderTab.ALL, UnifiedOrderTab.fromCode(" "));
  34. assertSame(UnifiedOrderTab.ALL, UnifiedOrderTab.fromCode("all"));
  35. assertSame(UnifiedOrderTab.UNPAID, UnifiedOrderTab.fromCode("unpaid"));
  36. assertSame(UnifiedOrderTab.ACTIVE, UnifiedOrderTab.fromCode("active"));
  37. assertSame(UnifiedOrderTab.COMPLETED, UnifiedOrderTab.fromCode("completed"));
  38. assertSame(UnifiedOrderTab.CANCELLED, UnifiedOrderTab.fromCode("cancelled"));
  39. assertSame(UnifiedOrderTab.REFUND, UnifiedOrderTab.fromCode("refund"));
  40. assertNull(UnifiedOrderTab.fromCode("bogus"));
  41. assertNull(UnifiedOrderTab.fromCode("ALL"));
  42. }
  43. @Test
  44. void unpaidAndRefundTabsNeverQueryFlash() {
  45. assertFalse(UnifiedOrderTab.UNPAID.queriesFlash());
  46. assertFalse(UnifiedOrderTab.REFUND.queriesFlash());
  47. assertTrue(UnifiedOrderTab.ALL.queriesFlash());
  48. assertTrue(UnifiedOrderTab.ACTIVE.queriesFlash());
  49. assertTrue(UnifiedOrderTab.COMPLETED.queriesFlash());
  50. assertTrue(UnifiedOrderTab.CANCELLED.queriesFlash());
  51. }
  52. // ---------- 外卖内存判定 ----------
  53. @Test
  54. void unpaidMatchesOnlyUnpaidOnlineOrders() {
  55. // 在线支付未付
  56. assertTrue(UnifiedOrderTab.UNPAID.matches(pos(0L, 0L, 0L, "2", 0L)));
  57. assertTrue(UnifiedOrderTab.UNPAID.matches(pos(3L, 2L, 0L, "3", 0L)));
  58. // 已付不进待付款
  59. assertFalse(UnifiedOrderTab.UNPAID.matches(pos(0L, 0L, 1L, "2", 0L)));
  60. // 货到付款/现金不进待付款(沿用现有语义:仅在线支付未付)
  61. assertFalse(UnifiedOrderTab.UNPAID.matches(pos(0L, 0L, 0L, "1", 0L)));
  62. assertFalse(UnifiedOrderTab.UNPAID.matches(pos(0L, 0L, 0L, "4", 0L)));
  63. // 已取消不进待付款
  64. assertFalse(UnifiedOrderTab.UNPAID.matches(pos(4L, 0L, 0L, "2", 0L)));
  65. // 售后中不进待付款
  66. assertFalse(UnifiedOrderTab.UNPAID.matches(pos(0L, 0L, 0L, "2", 1L)));
  67. }
  68. @Test
  69. void activeMatchesFulfillingOrdersWithoutAfterSale() {
  70. // 在线已付履约中
  71. assertTrue(UnifiedOrderTab.ACTIVE.matches(pos(0L, 0L, 1L, "2", 0L)));
  72. assertTrue(UnifiedOrderTab.ACTIVE.matches(pos(2L, 0L, 1L, "3", 0L)));
  73. // 货到付款(payType=1)/现金(payType=4)仅自取/堂食可履约
  74. assertTrue(UnifiedOrderTab.ACTIVE.matches(pos(1L, 1L, 0L, "1", 0L)));
  75. assertTrue(UnifiedOrderTab.ACTIVE.matches(pos(2L, 2L, 0L, "1", 0L)));
  76. assertFalse(UnifiedOrderTab.ACTIVE.matches(pos(0L, 0L, 0L, "1", 0L)));
  77. assertTrue(UnifiedOrderTab.ACTIVE.matches(pos(1L, 1L, 0L, "4", 0L)));
  78. assertTrue(UnifiedOrderTab.ACTIVE.matches(pos(2L, 2L, 0L, "4", 0L)));
  79. assertFalse(UnifiedOrderTab.ACTIVE.matches(pos(0L, 0L, 0L, "4", 0L)));
  80. // 在线未付不履约
  81. assertFalse(UnifiedOrderTab.ACTIVE.matches(pos(0L, 0L, 0L, "2", 0L)));
  82. // 终态不进进行中
  83. assertFalse(UnifiedOrderTab.ACTIVE.matches(pos(3L, 0L, 1L, "2", 0L)));
  84. assertFalse(UnifiedOrderTab.ACTIVE.matches(pos(4L, 0L, 1L, "2", 0L)));
  85. // 售后单从进行中剔除
  86. assertFalse(UnifiedOrderTab.ACTIVE.matches(pos(1L, 0L, 1L, "2", 2L)));
  87. }
  88. @Test
  89. void completedMatchesStateThreeWithoutAfterSale() {
  90. assertTrue(UnifiedOrderTab.COMPLETED.matches(pos(3L, 0L, 1L, "2", 0L)));
  91. assertFalse(UnifiedOrderTab.COMPLETED.matches(pos(2L, 0L, 1L, "2", 0L)));
  92. assertFalse(UnifiedOrderTab.COMPLETED.matches(pos(3L, 0L, 1L, "2", 1L)));
  93. }
  94. @Test
  95. void cancelledMatchesStateFourWithoutAfterSale() {
  96. assertTrue(UnifiedOrderTab.CANCELLED.matches(pos(4L, 0L, 0L, "2", 0L)));
  97. assertFalse(UnifiedOrderTab.CANCELLED.matches(pos(3L, 0L, 1L, "2", 0L)));
  98. assertFalse(UnifiedOrderTab.CANCELLED.matches(pos(4L, 0L, 0L, "2", 1L)));
  99. }
  100. @Test
  101. void refundMatchesAnyAfterSaleMark() {
  102. assertTrue(UnifiedOrderTab.REFUND.matches(pos(1L, 0L, 1L, "2", 1L)));
  103. // payStatus=2 已退款必然带售后标记,归退款 tab
  104. assertTrue(UnifiedOrderTab.REFUND.matches(pos(4L, 0L, 2L, "2", 3L)));
  105. assertFalse(UnifiedOrderTab.REFUND.matches(pos(4L, 0L, 1L, "2", 0L)));
  106. }
  107. @Test
  108. void allTabNeverFiltersTakeawayOrders() {
  109. for (long state = 0; state <= 4; state++) {
  110. for (long afterSale = 0; afterSale <= 3; afterSale++) {
  111. assertTrue(UnifiedOrderTab.ALL.matches(pos(state, 0L, 0L, "2", afterSale)),
  112. "state=" + state + ", afterSale=" + afterSale);
  113. }
  114. }
  115. }
  116. @Test
  117. void nullFieldsNeverMatchConstrainedTabs() {
  118. PosOrder sparse = new PosOrder();
  119. assertFalse(UnifiedOrderTab.UNPAID.matches(sparse));
  120. assertFalse(UnifiedOrderTab.ACTIVE.matches(sparse));
  121. assertFalse(UnifiedOrderTab.COMPLETED.matches(sparse));
  122. assertFalse(UnifiedOrderTab.CANCELLED.matches(sparse));
  123. assertFalse(UnifiedOrderTab.REFUND.matches(sparse));
  124. assertTrue(UnifiedOrderTab.ALL.matches(sparse));
  125. }
  126. // ---------- 闪送内存判定 ----------
  127. @Test
  128. void flashNonFinalStatusesMapToActive() {
  129. for (String status : new String[]{FlashDeliveryStatus.WAITING_ACCEPTANCE,
  130. FlashDeliveryStatus.ACCEPTED, FlashDeliveryStatus.PICKED_UP,
  131. FlashDeliveryStatus.DELIVERED}) {
  132. FlashDeliveryOrder order = flash(status);
  133. assertTrue(UnifiedOrderTab.ACTIVE.matches(order), status);
  134. assertFalse(UnifiedOrderTab.COMPLETED.matches(order), status);
  135. assertFalse(UnifiedOrderTab.CANCELLED.matches(order), status);
  136. assertFalse(UnifiedOrderTab.UNPAID.matches(order), status);
  137. assertFalse(UnifiedOrderTab.REFUND.matches(order), status);
  138. assertTrue(UnifiedOrderTab.ALL.matches(order), status);
  139. }
  140. }
  141. @Test
  142. void flashCompletedMapsOnlyToCompleted() {
  143. FlashDeliveryOrder order = flash(FlashDeliveryStatus.COMPLETED);
  144. assertTrue(UnifiedOrderTab.COMPLETED.matches(order));
  145. assertFalse(UnifiedOrderTab.ACTIVE.matches(order));
  146. assertFalse(UnifiedOrderTab.CANCELLED.matches(order));
  147. }
  148. @Test
  149. void flashCancelledMapsOnlyToCancelled() {
  150. FlashDeliveryOrder order = flash(FlashDeliveryStatus.CANCELLED);
  151. assertTrue(UnifiedOrderTab.CANCELLED.matches(order));
  152. assertFalse(UnifiedOrderTab.ACTIVE.matches(order));
  153. assertFalse(UnifiedOrderTab.COMPLETED.matches(order));
  154. }
  155. @Test
  156. void flashStatusNullFailsAllConstrainedTabs() {
  157. FlashDeliveryOrder order = flash(null);
  158. assertFalse(UnifiedOrderTab.ACTIVE.matches(order));
  159. assertFalse(UnifiedOrderTab.COMPLETED.matches(order));
  160. assertFalse(UnifiedOrderTab.CANCELLED.matches(order));
  161. assertTrue(UnifiedOrderTab.ALL.matches(order));
  162. }
  163. // ---------- wrapper SQL 片段断言(防 SQL 构造与 matches 内存判定漂移) ----------
  164. @Test
  165. void unpaidWrapperCarriesOnlineUnpaidConditions() {
  166. LambdaQueryWrapper<PosOrder> wrapper = UnifiedOrderTab.UNPAID.posOrderWrapper();
  167. String sql = wrapper.getSqlSegment();
  168. assertTrue(sql.contains("pay_status ="), sql);
  169. assertTrue(sql.contains("pay_type IN"), sql);
  170. assertTrue(sql.contains("state <>"), sql);
  171. assertTrue(sql.contains("after_sale_status ="), sql);
  172. Collection<Object> params = wrapper.getParamNameValuePairs().values();
  173. assertTrue(params.containsAll(List.of("2", "3")), params.toString());
  174. }
  175. @Test
  176. void activeWrapperCarriesStateAndPaymentConditions() {
  177. LambdaQueryWrapper<PosOrder> wrapper = UnifiedOrderTab.ACTIVE.posOrderWrapper();
  178. String sql = wrapper.getSqlSegment();
  179. assertTrue(sql.contains("state IN"), sql);
  180. assertTrue(sql.contains("after_sale_status ="), sql);
  181. assertTrue(sql.contains("(pay_status ="), sql);
  182. assertTrue(sql.contains("OR (pay_type IN"), sql);
  183. assertTrue(sql.contains("type IN"), sql);
  184. assertTrue(wrapper.getParamNameValuePairs().values()
  185. .containsAll(java.util.List.of("1", "4")), wrapper.getParamNameValuePairs().toString());
  186. }
  187. @Test
  188. void terminalTabWrappersCarryStateAndAfterSaleConditions() {
  189. LambdaQueryWrapper<PosOrder> completedWrapper = UnifiedOrderTab.COMPLETED.posOrderWrapper();
  190. String completed = completedWrapper.getSqlSegment();
  191. assertTrue(completed.contains("state ="), completed);
  192. assertTrue(completed.contains("after_sale_status ="), completed);
  193. assertTrue(completedWrapper.getParamNameValuePairs().containsValue(3L),
  194. completedWrapper.getParamNameValuePairs().toString());
  195. LambdaQueryWrapper<PosOrder> cancelledWrapper = UnifiedOrderTab.CANCELLED.posOrderWrapper();
  196. String cancelled = cancelledWrapper.getSqlSegment();
  197. assertTrue(cancelled.contains("state ="), cancelled);
  198. assertTrue(cancelledWrapper.getParamNameValuePairs().containsValue(4L),
  199. cancelledWrapper.getParamNameValuePairs().toString());
  200. }
  201. @Test
  202. void refundWrapperFiltersAfterSaleMark() {
  203. String sql = UnifiedOrderTab.REFUND.posOrderWrapper().getSqlSegment();
  204. assertTrue(sql.contains("after_sale_status >"), sql);
  205. }
  206. @Test
  207. void allTabWrapperHasNoConditions() {
  208. String takeawaySql = UnifiedOrderTab.ALL.posOrderWrapper().getSqlSegment();
  209. assertTrue(takeawaySql == null || takeawaySql.isBlank(), String.valueOf(takeawaySql));
  210. String flashSql = UnifiedOrderTab.ALL.flashWrapper().getSqlSegment();
  211. assertTrue(flashSql == null || flashSql.isBlank(), String.valueOf(flashSql));
  212. }
  213. @Test
  214. void flashActiveWrapperContainsFourNonFinalStatuses() {
  215. LambdaQueryWrapper<FlashDeliveryOrder> wrapper = UnifiedOrderTab.ACTIVE.flashWrapper();
  216. assertTrue(wrapper.getSqlSegment().contains("status IN"), wrapper.getSqlSegment());
  217. Collection<Object> params = wrapper.getParamNameValuePairs().values();
  218. assertTrue(params.containsAll(List.of(FlashDeliveryStatus.WAITING_ACCEPTANCE,
  219. FlashDeliveryStatus.ACCEPTED, FlashDeliveryStatus.PICKED_UP,
  220. FlashDeliveryStatus.DELIVERED)), params.toString());
  221. }
  222. @Test
  223. void flashTerminalTabWrappersMatchExactStatus() {
  224. LambdaQueryWrapper<FlashDeliveryOrder> completed = UnifiedOrderTab.COMPLETED.flashWrapper();
  225. assertTrue(completed.getSqlSegment().contains("status ="), completed.getSqlSegment());
  226. assertTrue(completed.getParamNameValuePairs().containsValue(FlashDeliveryStatus.COMPLETED));
  227. LambdaQueryWrapper<FlashDeliveryOrder> cancelled = UnifiedOrderTab.CANCELLED.flashWrapper();
  228. assertTrue(cancelled.getSqlSegment().contains("status ="), cancelled.getSqlSegment());
  229. assertTrue(cancelled.getParamNameValuePairs().containsValue(FlashDeliveryStatus.CANCELLED));
  230. }
  231. @Test
  232. void flashWrapperForAlwaysEmptyTabsThrows() {
  233. assertThrows(IllegalStateException.class, () -> UnifiedOrderTab.UNPAID.flashWrapper());
  234. assertThrows(IllegalStateException.class, () -> UnifiedOrderTab.REFUND.flashWrapper());
  235. }
  236. // ---------- helpers ----------
  237. private static PosOrder pos(Long state, Long type, Long payStatus, String payType, Long afterSaleStatus) {
  238. PosOrder order = new PosOrder();
  239. order.setState(state);
  240. order.setType(type);
  241. order.setPayStatus(payStatus);
  242. order.setPayType(payType);
  243. order.setAfterSaleStatus(afterSaleStatus);
  244. return order;
  245. }
  246. private static FlashDeliveryOrder flash(String status) {
  247. FlashDeliveryOrder order = new FlashDeliveryOrder();
  248. order.setStatus(status);
  249. return order;
  250. }
  251. }