订单增加状态搜索

This commit is contained in:
wuweihua
2026-10-23 13:47:41 +08:00
parent fcebf9282c
commit 84939a8875
7 changed files with 212 additions and 20 deletions
@@ -38,6 +38,11 @@ public class TabOrderMonitorQuery implements Serializable
private List<String> orderIdentifiers;
/** 上游产品代码 LINE_CODE(产品比对点进订单号时使用) */
private String productCode;
/**
* 订单状态 ORDER_STATUS 多选。
* 空则服务端回落默认 3,4,5,6,7,8,11(与历史硬编码一致)。
*/
private List<Integer> orderStatuses;
/** 分批同步计费每批条数 */
private Integer batchSize;
}
@@ -0,0 +1,49 @@
package com.bms.price.enums;
/**
* Snapshot of prc_order_bill.order_status (aligned with upstream TAB_ORDER).
* Fee refund sets {@link #REFUNDED} (9 / 已退件).
*/
public enum BillOrderStatus
{
/** Upstream: returned package; also set after billing-list fee refund. */
REFUNDED(9);
private final int code;
BillOrderStatus(int code)
{
this.code = code;
}
public int getCode()
{
return code;
}
public Integer getCodeBoxed()
{
return Integer.valueOf(code);
}
public boolean matches(Integer status)
{
return status != null && status.intValue() == code;
}
public static BillOrderStatus of(Integer status)
{
if (status == null)
{
return null;
}
for (BillOrderStatus value : values())
{
if (value.code == status.intValue())
{
return value;
}
}
return null;
}
}
@@ -3,6 +3,7 @@ package com.bms.price.oracle;
import java.math.BigDecimal;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
@@ -71,6 +72,12 @@ public class TabOrderMonitorService
/** 单批 Oracle 查询最长等待(从库 socketTimeout 为 120s,留同样余量)。 */
private static final long COLLECT_BATCH_TIMEOUT_SECONDS = 120L;
/** Same default as historical hardcoded ORDER_STATUS IN (...). */
private static final List<Integer> DEFAULT_ORDER_STATUSES =
Collections.unmodifiableList(Arrays.asList(
Integer.valueOf(3), Integer.valueOf(4), Integer.valueOf(5), Integer.valueOf(6),
Integer.valueOf(7), Integer.valueOf(8), Integer.valueOf(11)));
@Autowired
private OracleUpstreamOrderMapper oracleUpstreamOrderMapper;
@@ -994,7 +1001,8 @@ public class TabOrderMonitorService
appendSorted(sb, q.getCustomerCodes());
sb.append('|').append(safe(q.getBeginTime())).append('|').append(safe(q.getEndTime()))
.append('|').append(safe(q.getOrderId())).append('|').append(safe(q.getOrgOrderId()))
.append('|').append(safe(q.getTransferOrderId()));
.append('|').append(safe(q.getTransferOrderId())).append('|');
appendSortedInts(sb, q.getOrderStatuses());
return Integer.toHexString(sb.toString().hashCode());
}
@@ -1012,6 +1020,20 @@ public class TabOrderMonitorService
}
}
private static void appendSortedInts(StringBuilder sb, List<Integer> values)
{
if (values == null || values.isEmpty())
{
return;
}
List<Integer> copy = new ArrayList<Integer>(values);
Collections.sort(copy);
for (Integer v : copy)
{
sb.append(v).append(',');
}
}
private static String safe(String s)
{
return s == null ? "" : s;
@@ -1152,6 +1174,25 @@ public class TabOrderMonitorService
query.setOrderId(trimToNull(query.getOrderId()));
query.setOrgOrderId(trimToNull(query.getOrgOrderId()));
query.setTransferOrderId(trimToNull(query.getTransferOrderId()));
normalizeOrderStatuses(query);
}
/** Empty/missing -> default 3,4,5,6,7,8,11 so SQL always has a status IN list. */
private static void normalizeOrderStatuses(TabOrderMonitorQuery query)
{
List<Integer> statuses = query.getOrderStatuses();
List<Integer> cleaned = new ArrayList<Integer>();
if (statuses != null)
{
for (Integer s : statuses)
{
if (s != null)
{
cleaned.add(s);
}
}
}
query.setOrderStatuses(cleaned.isEmpty() ? new ArrayList<Integer>(DEFAULT_ORDER_STATUSES) : cleaned);
}
/**
@@ -77,6 +77,7 @@ import com.bms.price.domain.vo.TmsPriceQuoteFeeLine;
import com.bms.price.domain.vo.TmsPriceQuoteResult;
import com.bms.price.enums.BillCreditArrearsStatus;
import com.bms.price.enums.BillCustomerActiveStatus;
import com.bms.price.enums.BillOrderStatus;
import com.bms.price.enums.BillRefundStatus;
import com.bms.price.enums.BillBillingFailStatus;
import com.bms.price.enums.TmsOrderBillMatchType;
@@ -300,6 +301,8 @@ public class PrcOrderBillServiceImpl implements IPrcOrderBillService
refundFee.setManualFlag("0");
incomeBillFeeMapper.insertPrcIncomeBillFee(refundFee);
bill.setRefundStatus(BillRefundStatus.REFUNDED.getCode());
// Align with upstream 已退件 after fee refund.
bill.setOrderStatus(BillOrderStatus.REFUNDED.getCodeBoxed());
if (incomeBill != null)
{
incomeBill.setRefundStatus(BillRefundStatus.REFUNDED.getCode());
@@ -315,6 +318,7 @@ public class PrcOrderBillServiceImpl implements IPrcOrderBillService
req.put("refundAmount", feeSum.negate());
req.put("feeId", refundFee.getFeeId());
req.put("refundStatus", bill.getRefundStatus());
req.put("orderStatus", bill.getOrderStatus());
if (billSearchStore != null)
{
billSearchStore.save(EsLogType.BILL,
@@ -762,6 +766,7 @@ public class PrcOrderBillServiceImpl implements IPrcOrderBillService
{
throw new ServiceException(MessageUtils.message("price.bill.bizDateRequired"));
}
assertOrderBillNotRefunded(bill);
TmsPriceBillRequest req = buildBillRequestFromBill(bill);
return billLocalWithDbRetry(billId.trim(), req);
}
@@ -1631,6 +1636,7 @@ public class PrcOrderBillServiceImpl implements IPrcOrderBillService
String billKey = Md5Utils.hash(orderNo);
PrcOrderBill existed = orderBillMapper.selectPrcOrderBillByOrderNo(orderNo);
assertOrderBillEditable(existed);
assertOrderBillNotRefunded(existed);
BigDecimal previousIncome = existed == null ? BigDecimal.ZERO : nz(existed.getIncomeTotal());
PrcOrderBill bill = existed == null ? new PrcOrderBill() : existed;
if (existed == null)
@@ -2087,6 +2093,15 @@ public class PrcOrderBillServiceImpl implements IPrcOrderBillService
}
}
/** Block rebill when refundStatus=REFUNDED (order_status=9 alone is logistics return, not fee refund). */
private void assertOrderBillNotRefunded(PrcOrderBill bill)
{
if (bill != null && BillRefundStatus.REFUNDED.getCode().equalsIgnoreCase(bill.getRefundStatus()))
{
throw new ServiceException("\u8ba2\u5355\u5df2\u9000\u8d39\uff0c\u4e0d\u53ef\u91cd\u65b0\u8ba1\u8d39");
}
}
private static BigDecimal nz(BigDecimal v)
{
return v == null ? BigDecimal.ZERO : v;
@@ -2931,7 +2946,12 @@ public class PrcOrderBillServiceImpl implements IPrcOrderBillService
{
return;
}
if (request.getOrderStatus() != null)
// Fee refund marks order_status=9 (已退件); do not let Oracle sync overwrite it.
if (BillRefundStatus.REFUNDED.getCode().equalsIgnoreCase(bill.getRefundStatus()))
{
bill.setOrderStatus(BillOrderStatus.REFUNDED.getCodeBoxed());
}
else if (request.getOrderStatus() != null)
{
bill.setOrderStatus(request.getOrderStatus());
}
@@ -67,7 +67,15 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
AND o.PICKUP_DATE &lt;= TO_DATE(#{query.endTime}, 'YYYY-MM-DD HH24:MI:SS')
</if>
AND o.BL_PICKUP = 1
AND o.ORDER_STATUS IN (3, 4, 5, 6, 7, 8, 11)
<if test="query.orderStatuses != null and query.orderStatuses.size() > 0">
AND o.ORDER_STATUS IN
<foreach collection="query.orderStatuses" item="st" open="(" separator="," close=")">
#{st}
</foreach>
</if>
<if test="query.orderStatuses == null or query.orderStatuses.size() == 0">
AND o.ORDER_STATUS IN (3, 4, 5, 6, 7, 8, 11)
</if>
<if test="query.orderId != null and query.orderId != ''">
AND o.ORDER_ID = #{query.orderId}
</if>
@@ -213,6 +213,7 @@ function submit(skipConfirm) {
orderId: q.orderId || undefined,
orgOrderId: q.orgOrderId || undefined,
transferOrderId: q.transferOrderId || undefined,
orderStatuses: Array.isArray(q.orderStatuses) && q.orderStatuses.length ? q.orderStatuses : undefined,
batchSize: 100
}).then(res => {
const asyncTaskId = res.data?.asyncTaskId || res.data
@@ -18,11 +18,11 @@
ref="tableRef"
:columns="columns"
:search-columns="searchColumns"
:default-params="defaultParams"
:query="queryList"
row-key="orderId"
:auto-load="false"
selection
search-action-align="center"
:search-per-row="4"
:page-sizes="[100, 200, 300, 400]"
:page-size="100"
@@ -83,6 +83,31 @@
<template #col-country="{ row }">
{{ row.countryName || '-' }} ({{ row.country || '-' }})
</template>
<template #search-orderStatuses="{ model }">
<el-select
v-model="model.orderStatuses"
multiple
clearable
collapse-tags
collapse-tags-tooltip
placeholder="请选择"
style="width: 100%"
>
<template #header>
<el-checkbox
:model-value="isAllOrderStatusSelected(model)"
:indeterminate="isOrderStatusIndeterminate(model)"
@change="(checked) => toggleAllOrderStatus(model, checked)"
>全选</el-checkbox>
</template>
<el-option
v-for="opt in orderStatusOptions"
:key="opt.value"
:label="opt.label"
:value="opt.value"
/>
</el-select>
</template>
<template #col-orderStatus="{ row }">
{{ orderStatusLabel(row.orderStatus) }}
</template>
@@ -130,6 +155,27 @@ const syncFloat = ref(null)
/** 比对回填搜索模式:走专用转单号接口,不影响普通列表 */
const transferFillMode = ref(false)
const orderStatusMap = {
0: '预报订单',
1: '确认订单',
2: '已中转',
3: '已收货',
4: '已装箱',
5: '已出库',
6: '转运中',
7: '已上网',
8: '已签收',
9: '已退件',
10: '已删除',
11: '已复核'
}
const orderStatusOptions = Object.keys(orderStatusMap).map(k => ({ label: orderStatusMap[k], value: Number(k) }))
const defaultParams = {
orderStatuses: [3, 4, 5, 6, 7, 8, 11]
}
const searchColumns = [
{
// 客户名称或客户代码混合录入,一行一个
@@ -164,7 +210,20 @@ const searchColumns = [
clearable: true,
defaultTime: [new Date(2000, 0, 1, 0, 0, 0), new Date(2000, 0, 1, 23, 59, 59)]
}
}
},
{
label: '订单状态',
prop: 'orderStatuses',
component: 'select',
options: orderStatusOptions,
placeholder: '请选择',
props: {
multiple: true,
clearable: true,
collapseTags: true,
collapseTagsTooltip: true
}
},
]
const columns = [
@@ -186,21 +245,6 @@ const columns = [
// { label: '操作', prop: 'action', align: 'center', width: 120, fixed: 'right', slot: 'action', showInToolbar: false }
]
const orderStatusMap = {
0: '预报订单',
1: '确认订单',
2: '已中转',
3: '已收货',
4: '已装箱',
5: '已出库',
6: '转运中',
7: '已上网',
8: '已签收',
9: '已退件',
10: '已删除',
11: '已复核'
}
const syncFloatVisible = computed(() => {
const p = syncFloat.value
return !!(p && (p.loading || p.finished))
@@ -220,6 +264,30 @@ const syncFloatSummary = computed(() => {
})
const syncFloatTooltip = computed(() => syncFloat.value?.message || '点击查看详情')
const orderStatusAllValues = computed(() => orderStatusOptions.map(o => o.value))
function selectedOrderStatuses(model) {
return Array.isArray(model?.orderStatuses) ? model.orderStatuses : []
}
function isAllOrderStatusSelected(model) {
const selected = selectedOrderStatuses(model)
const all = orderStatusAllValues.value
return all.length > 0 && selected.length === all.length
}
function isOrderStatusIndeterminate(model) {
const selected = selectedOrderStatuses(model)
const all = orderStatusAllValues.value
return selected.length > 0 && selected.length < all.length
}
function toggleAllOrderStatus(model, checked) {
if (!model) return
model.orderStatuses = checked ? [...orderStatusAllValues.value] : []
}
function orderStatusLabel(status) {
if (status === null || status === undefined || status === '') return '-'
const key = Number(status)