package com.ruoyi.app.unifiedorder; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.ruoyi.system.domain.PosOrder; import com.ruoyi.system.domain.flash.FlashDeliveryOrder; import com.ruoyi.system.domain.flash.FlashDeliveryStatus; import java.util.List; import java.util.Objects; /** * 统一订单列表 tab 枚举:SQL 条件构造与内存判定共用同一组常量,是归类语义的唯一事实源。 * 外卖条件照抄用户端订单列表现行实现(UserOrderController.orderList); * 空值字段不匹配任何受限 tab(与 SQL NULL 比较语义一致),all 不过滤。 */ public enum UnifiedOrderTab { /** 全部:不过滤。 */ ALL("all"), /** 待付款:仅在线支付未付(货到付款创建即视为已付,不在此列)。 */ UNPAID("unpaid"), /** 进行中:外卖履约中且无售后;闪送非终态。 */ ACTIVE("active"), /** 已完成:外卖 state=3 且无售后;闪送 COMPLETED。 */ COMPLETED("completed"), /** 已取消:外卖 state=4 且无售后;闪送 CANCELLED。 */ CANCELLED("cancelled"), /** 退款·售后:外卖售后标记大于 0;闪送恒空。 */ REFUND("refund"); /** 在线支付方式(OMG、LINE Pay),待付款 tab 仅认这两种。 */ private static final List ONLINE_PAY_TYPES = List.of("2", "3"); /** 货到付款支付方式标记。 */ private static final String CASH_PAY_TYPE = "1"; /** 货到付款可线下收款的订单类型:自取、堂食。 */ private static final List CASH_PAYABLE_TYPES = List.of(1L, 2L); /** 进行中的外卖订单状态:待处理、已接单、已出餐。 */ private static final List ACTIVE_STATES = List.of(0L, 1L, 2L); /** 已完成的外卖订单状态。 */ private static final long COMPLETED_STATE = 3L; /** 已取消的外卖订单状态。 */ private static final long CANCELLED_STATE = 4L; /** 无售后标记。 */ private static final long NO_AFTER_SALE = 0L; /** 已支付的支付状态。 */ private static final long PAID = 1L; /** 未支付的支付状态。 */ private static final long UNPAID_STATUS = 0L; /** 进行中的闪送状态:非终态四枚举。 */ private static final List FLASH_ACTIVE_STATUSES = List.of( FlashDeliveryStatus.WAITING_ACCEPTANCE, FlashDeliveryStatus.ACCEPTED, FlashDeliveryStatus.PICKED_UP, FlashDeliveryStatus.DELIVERED); private final String code; UnifiedOrderTab(String code) { this.code = code; } /** 前端契约中的 tab 编码。 */ public String code() { return code; } /** 按契约编码解析;空值默认 all,非法值返回 null 由 Controller 统一转参数错误。 */ public static UnifiedOrderTab fromCode(String code) { if (code == null || code.isBlank()) { return ALL; } for (UnifiedOrderTab tab : values()) { if (tab.code.equals(code)) { return tab; } } return null; } /** 待付款与退款·售后 tab 闪送侧恒空,查询层应直接跳过闪送路。 */ public boolean queriesFlash() { return this != UNPAID && this != REFUND; } /** 构造外卖 tab 条件(仅 tab 谓词,不含用户、游标与排序,由查询层追加)。 */ public LambdaQueryWrapper posOrderWrapper() { LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); switch (this) { case UNPAID: wrapper.eq(PosOrder::getPayStatus, UNPAID_STATUS) .in(PosOrder::getPayType, ONLINE_PAY_TYPES) .ne(PosOrder::getState, CANCELLED_STATE) .eq(PosOrder::getAfterSaleStatus, NO_AFTER_SALE); break; case ACTIVE: wrapper.in(PosOrder::getState, ACTIVE_STATES) .eq(PosOrder::getAfterSaleStatus, NO_AFTER_SALE) // 现金自取/堂食可以线下收款;在线订单必须已付款才能履约。 .and(w -> w.eq(PosOrder::getPayStatus, PAID) .or(cash -> cash.eq(PosOrder::getPayType, CASH_PAY_TYPE) .in(PosOrder::getType, CASH_PAYABLE_TYPES))); break; case COMPLETED: wrapper.eq(PosOrder::getState, COMPLETED_STATE) .eq(PosOrder::getAfterSaleStatus, NO_AFTER_SALE); break; case CANCELLED: wrapper.eq(PosOrder::getState, CANCELLED_STATE) .eq(PosOrder::getAfterSaleStatus, NO_AFTER_SALE); break; case REFUND: wrapper.gt(PosOrder::getAfterSaleStatus, NO_AFTER_SALE); break; case ALL: default: break; } return wrapper; } /** 外卖订单内存判定,与 posOrderWrapper 的 SQL 条件同源同语义。 */ public boolean matches(PosOrder order) { switch (this) { case UNPAID: return longEq(order.getPayStatus(), UNPAID_STATUS) && order.getPayType() != null && ONLINE_PAY_TYPES.contains(order.getPayType()) && longNotEq(order.getState(), CANCELLED_STATE) && longEq(order.getAfterSaleStatus(), NO_AFTER_SALE); case ACTIVE: return order.getState() != null && ACTIVE_STATES.contains(order.getState()) && longEq(order.getAfterSaleStatus(), NO_AFTER_SALE) && (longEq(order.getPayStatus(), PAID) || (CASH_PAY_TYPE.equals(order.getPayType()) && order.getType() != null && CASH_PAYABLE_TYPES.contains(order.getType()))); case COMPLETED: return longEq(order.getState(), COMPLETED_STATE) && longEq(order.getAfterSaleStatus(), NO_AFTER_SALE); case CANCELLED: return longEq(order.getState(), CANCELLED_STATE) && longEq(order.getAfterSaleStatus(), NO_AFTER_SALE); case REFUND: return order.getAfterSaleStatus() != null && order.getAfterSaleStatus() > NO_AFTER_SALE; case ALL: default: return true; } } /** 构造闪送 tab 条件;待付款与退款·售后闪送侧恒空,调用即视为程序错误。 */ public LambdaQueryWrapper flashWrapper() { if (!queriesFlash()) { throw new IllegalStateException("闪送无 " + code + " tab,查询层应跳过闪送路"); } LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); switch (this) { case ACTIVE: wrapper.in(FlashDeliveryOrder::getStatus, FLASH_ACTIVE_STATUSES); break; case COMPLETED: wrapper.eq(FlashDeliveryOrder::getStatus, FlashDeliveryStatus.COMPLETED); break; case CANCELLED: wrapper.eq(FlashDeliveryOrder::getStatus, FlashDeliveryStatus.CANCELLED); break; case ALL: default: break; } return wrapper; } /** 闪送订单内存判定,与 flashWrapper 的 SQL 条件同源同语义。 */ public boolean matches(FlashDeliveryOrder order) { switch (this) { case ACTIVE: return order.getStatus() != null && FLASH_ACTIVE_STATUSES.contains(order.getStatus()); case COMPLETED: return Objects.equals(order.getStatus(), FlashDeliveryStatus.COMPLETED); case CANCELLED: return Objects.equals(order.getStatus(), FlashDeliveryStatus.CANCELLED); case UNPAID: case REFUND: return false; case ALL: default: return true; } } private static boolean longEq(Long value, long expected) { return value != null && value == expected; } private static boolean longNotEq(Long value, long unexpected) { return value != null && value != unexpected; } }