diff --git a/bms-back/bms-admin/src/main/java/com/bms/web/controller/ar/ArBillController.java b/bms-back/bms-admin/src/main/java/com/bms/web/controller/ar/ArBillController.java index a08821a4..b2595d2a 100644 --- a/bms-back/bms-admin/src/main/java/com/bms/web/controller/ar/ArBillController.java +++ b/bms-back/bms-admin/src/main/java/com/bms/web/controller/ar/ArBillController.java @@ -134,6 +134,23 @@ public class ArBillController extends BaseController { return result; } + /** 查询需要从全选结果中排除的订单;空条件不执行查询,避免返回全部订单。 */ + @PreAuthorize("@ss.hasPermi('ar:bill:generate')") + @PostMapping("/generate/exclusion-preview") + public AjaxResult previewExcluded(@RequestBody ArBillGenerateQuery query) { + if (query == null || StringUtils.isEmpty(StringUtils.trim(query.getExcludeOrderOrTrackingNo()))) { + throw new ServiceException("请输入订单号、运单号或转单号后再查询"); + } + PageHelper.startPage(query.getPageNum() == null ? 1 : query.getPageNum(), 20).setReasonable(true); + List list = billService.previewExcludedBill(query); + TableDataInfo pageData = getDataTable(list); + AjaxResult result = success(); + result.put("rows", pageData.getRows()); + result.put("total", pageData.getTotal()); + result.put("totalAmount", billService.sumPreviewBill(query)); + return result; + } + /** * 创建账单头和异步生成任务,接口不等待全部订单明细处理完成。 */ diff --git a/bms-back/bms-system/src/main/java/com/bms/ar/domain/vo/ArBillGenerateRequest.java b/bms-back/bms-system/src/main/java/com/bms/ar/domain/vo/ArBillGenerateRequest.java index a70e893a..bdf6e9b9 100644 --- a/bms-back/bms-system/src/main/java/com/bms/ar/domain/vo/ArBillGenerateRequest.java +++ b/bms-back/bms-system/src/main/java/com/bms/ar/domain/vo/ArBillGenerateRequest.java @@ -32,6 +32,8 @@ public class ArBillGenerateRequest private String selectionMode = ArBillSelectionMode.EXPLICIT.getCode(); /** 全选模式中用户明确排除的来源订单 ID。 */ private List excludedSourceBillIds; + /** 全选模式下按订单号、运单号或转单号排除;后台生成任务按批次应用该条件。 */ + private String excludedOrderOrTrackingNo; @JsonFormat(pattern = "yyyy-MM-dd") @JsonDeserialize(using = StrictDateDeserializer.class) private Date billDate; diff --git a/bms-back/bms-system/src/main/java/com/bms/ar/enums/ArBillSelectionMode.java b/bms-back/bms-system/src/main/java/com/bms/ar/enums/ArBillSelectionMode.java index 2bd1799c..fb4dc3d7 100644 --- a/bms-back/bms-system/src/main/java/com/bms/ar/enums/ArBillSelectionMode.java +++ b/bms-back/bms-system/src/main/java/com/bms/ar/enums/ArBillSelectionMode.java @@ -8,7 +8,7 @@ public enum ArBillSelectionMode { /** 手动选择当前预览结果中的订单。 */ EXPLICIT("EXPLICIT", "手动选择"), - /** 选择全部查询结果,仅排除用户明确勾选的订单。 */ + /** 选择全部查询结果,再按用户提供的排除条件移除匹配订单。 */ ALL_MATCHED("ALL_MATCHED", "全选查询结果"); private final String code; diff --git a/bms-back/bms-system/src/main/java/com/bms/ar/service/IArBillService.java b/bms-back/bms-system/src/main/java/com/bms/ar/service/IArBillService.java index 35e3b5b7..46fca5b6 100644 --- a/bms-back/bms-system/src/main/java/com/bms/ar/service/IArBillService.java +++ b/bms-back/bms-system/src/main/java/com/bms/ar/service/IArBillService.java @@ -37,6 +37,8 @@ public interface IArBillService List previewBill(ArBillGenerateQuery query); + List previewExcludedBill(ArBillGenerateQuery query); + BigDecimal sumPreviewBill(ArBillGenerateQuery query); ArBillGenerateTask generateBill(ArBillGenerateRequest request, String operator, String requestId); diff --git a/bms-back/bms-system/src/main/java/com/bms/ar/service/impl/ArBillServiceImpl.java b/bms-back/bms-system/src/main/java/com/bms/ar/service/impl/ArBillServiceImpl.java index 01bd583a..48d831d6 100644 --- a/bms-back/bms-system/src/main/java/com/bms/ar/service/impl/ArBillServiceImpl.java +++ b/bms-back/bms-system/src/main/java/com/bms/ar/service/impl/ArBillServiceImpl.java @@ -299,6 +299,15 @@ public class ArBillServiceImpl implements IArBillService { return result; } + /** 查询待排除的订单;必须带至少一个精确单号,避免空条件返回整个账单范围。 */ + @Override + public List previewExcludedBill(ArBillGenerateQuery query) { + if (query == null || normalizeOrderIdentifiers(query.getExcludeOrderOrTrackingNo()).isEmpty()) { + throw new ServiceException("请输入订单号、运单号或转单号后再查询"); + } + return previewBill(query); + } + /** * 汇总当前生成条件下的订单应收金额,用于弹窗顶部合计展示。 */ @@ -358,8 +367,18 @@ public class ArBillServiceImpl implements IArBillService { throw new ServiceException("全选模式最多排除 " + EXCLUDED_SOURCE_ID_LIMIT + " 条订单,请缩小查询条件后再生成"); } + List excludedOrderIdentifiers = allMatched + ? normalizeOrderIdentifiers(request.getExcludedOrderOrTrackingNo()) : new ArrayList<>(); + if (!allMatched) { + request.setExcludedOrderOrTrackingNo(null); + } + int orderIdentifierCount = normalizeOrderIdentifiers(request.getOrderOrTrackingNo()).size() + + excludedOrderIdentifiers.size(); + if (orderIdentifierCount > ORDER_IDENTIFIER_LIMIT) { + throw new ServiceException("筛选单号和排除单号合计最多输入 " + ORDER_IDENTIFIER_LIMIT + " 个"); + } validateOrderIdentifierParameterCount( - normalizeOrderIdentifiers(request.getOrderOrTrackingNo()).size(), + orderIdentifierCount, allMatched ? excludedSourceBillIds.size() : sourceBillIds.size()); request.setSelectionMode(selectionMode); @@ -535,6 +554,8 @@ public class ArBillServiceImpl implements IArBillService { ArBillGenerateRequest request = JSON.parseObject(task.getRequestPayload(), ArBillGenerateRequest.class); List sourceBillIds = normalizeSourceBillIds(request.getSourceBillIds()); List excludedSourceBillIds = normalizeSourceBillIds(request.getExcludedSourceBillIds()); + List excludedOrderIdentifiers = ArBillSelectionMode.ALL_MATCHED.getCode().equals(task.getSelectionMode()) + ? normalizeOrderIdentifiers(request.getExcludedOrderOrTrackingNo()) : new ArrayList<>(); TransactionTemplate transactionTemplate = new TransactionTemplate(transactionManager); transactionTemplate.setTimeout(300); @@ -544,8 +565,8 @@ public class ArBillServiceImpl implements IArBillService { request.getCustomerId(), request.getCustomerCode(), normalizeOrderIdentifiers(request.getOrderOrTrackingNo()), request.getBillPeriodEnd(), request.getCurrency(), eligibleOrderBillStatuses(), - ArIncomeBillFeeStatus.UNBILLED.getCode(), - task.getSnapshotCreateTime(), null, excludedSourceBillIds); + ArIncomeBillFeeStatus.UNBILLED.getCode(), task.getSnapshotCreateTime(), null, + excludedSourceBillIds, excludedOrderIdentifiers); if (totalCount <= 0) { throw new ServiceException("当前全选范围内没有可生成的订单"); } @@ -572,7 +593,7 @@ public class ArBillServiceImpl implements IArBillService { } ArBillGenerateTask currentTask = task; GenerateBatchResult result = transactionTemplate.execute(status -> processGenerateBatch( - currentTask, request, sourceBillIds, excludedSourceBillIds)); + currentTask, request, sourceBillIds, excludedSourceBillIds, excludedOrderIdentifiers)); if (result == null || result.finished) { transactionTemplate.execute(status -> { completeGenerateTask(taskId); @@ -659,7 +680,8 @@ public class ArBillServiceImpl implements IArBillService { * 每批最多 GENERATE_PAGE_SIZE 条,成功后原子更新任务进度。 */ private GenerateBatchResult processGenerateBatch(ArBillGenerateTask task, ArBillGenerateRequest request, - List sourceBillIds, List excludedSourceBillIds) { + List sourceBillIds, List excludedSourceBillIds, + List excludedOrderIdentifiers) { ArBillSelectionMode selectionMode = ArBillSelectionMode.of(task.getSelectionMode()); if (selectionMode == null) { throw new ServiceException("账单生成任务的订单选择模式无效"); @@ -673,6 +695,7 @@ public class ArBillServiceImpl implements IArBillService { eligibleOrderBillStatuses(), ArIncomeBillFeeStatus.UNBILLED.getCode(), task.getSnapshotCreateTime(), task.getLastSourceBillId(), explicitIds, selectionMode == ArBillSelectionMode.ALL_MATCHED ? excludedSourceBillIds : null, + selectionMode == ArBillSelectionMode.ALL_MATCHED ? excludedOrderIdentifiers : null, GENERATE_PAGE_SIZE); if (sources == null || sources.isEmpty()) { return new GenerateBatchResult(true); diff --git a/bms-back/bms-system/src/main/java/com/bms/price/mapper/PrcOrderBillMapper.java b/bms-back/bms-system/src/main/java/com/bms/price/mapper/PrcOrderBillMapper.java index 8952ffa3..60a06584 100644 --- a/bms-back/bms-system/src/main/java/com/bms/price/mapper/PrcOrderBillMapper.java +++ b/bms-back/bms-system/src/main/java/com/bms/price/mapper/PrcOrderBillMapper.java @@ -68,14 +68,16 @@ public interface PrcOrderBillMapper @Param("arBillStatuses") List arBillStatuses, @Param("feeArBillStatus") String feeArBillStatus, @Param("snapshotCreateTime") Date snapshotCreateTime, @Param("lastSourceBillId") String lastSourceBillId, @Param("billIds") List billIds, - @Param("excludedBillIds") List excludedBillIds, @Param("limit") int limit); + @Param("excludedBillIds") List excludedBillIds, + @Param("excludedOrderIdentifiers") List excludedOrderIdentifiers, @Param("limit") int limit); int countPrcOrderBillByCustomerPeriod(@Param("customerId") Long customerId, @Param("customerCode") String customerCode, @Param("orderIdentifiers") List orderIdentifiers, @Param("cutoffDate") Date cutoffDate, @Param("currency") String currency, @Param("arBillStatuses") List arBillStatuses, @Param("feeArBillStatus") String feeArBillStatus, @Param("snapshotCreateTime") Date snapshotCreateTime, - @Param("billIds") List billIds, @Param("excludedBillIds") List excludedBillIds); + @Param("billIds") List billIds, @Param("excludedBillIds") List excludedBillIds, + @Param("excludedOrderIdentifiers") List excludedOrderIdentifiers); /** 按生成账单时用户勾选的订单读取,并再次校验账单筛选条件。 */ public List selectPrcOrderBillByCustomerCutoffAndIds(@Param("customerId") Long customerId, diff --git a/bms-back/bms-system/src/main/resources/mapper/price/PrcOrderBillMapper.xml b/bms-back/bms-system/src/main/resources/mapper/price/PrcOrderBillMapper.xml index dbe1601d..5759a196 100644 --- a/bms-back/bms-system/src/main/resources/mapper/price/PrcOrderBillMapper.xml +++ b/bms-back/bms-system/src/main/resources/mapper/price/PrcOrderBillMapper.xml @@ -693,6 +693,22 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" #{excludedBillId} + + and not ( + coalesce(p.order_no, '') in + + #{excludedIdentifier} + + or coalesce(p.tracking_no, '') in + + #{excludedIdentifier} + + or coalesce(p.transfer_no, '') in + + #{excludedIdentifier} + + ) + diff --git a/bms-front/src/api/ar/bill.js b/bms-front/src/api/ar/bill.js index d995f845..bb82aee1 100644 --- a/bms-front/src/api/ar/bill.js +++ b/bms-front/src/api/ar/bill.js @@ -50,6 +50,15 @@ export function previewArBill(query) { }) } +export function previewExcludedArBill(query) { + return request({ + url: '/ar/bill/generate/exclusion-preview', + method: 'post', + data: query, + timeout: 60000 + }) +} + export function confirmArBill(arBillId, data = {}) { return request({ url: '/ar/bill/' + arBillId + '/confirm', method: 'put', data }) } diff --git a/bms-front/src/views/ar/bill/components/GenerateBillDialog.vue b/bms-front/src/views/ar/bill/components/GenerateBillDialog.vue index 5436b33e..d92c8136 100644 --- a/bms-front/src/views/ar/bill/components/GenerateBillDialog.vue +++ b/bms-front/src/views/ar/bill/components/GenerateBillDialog.vue @@ -51,17 +51,16 @@ - + -
- 排除订单: - - {{ row.orderNo || row.trackingNo || row.billId }} - +
+ 已排除 {{ confirmedExcludeCount }} 条订单,应收 {{ money(confirmedExcludeAmount) }}(按单号条件) + 修改 + 清除
@@ -96,13 +95,13 @@
- + 清空
- 查询 + 查询
- - +
输入单号并点击查询后显示匹配订单
+ @@ -112,7 +111,7 @@
@@ -143,7 +142,7 @@