diff --git a/bms-back/bms-admin/src/main/java/com/bms/web/controller/price/BillingController.java b/bms-back/bms-admin/src/main/java/com/bms/web/controller/price/BillingController.java index 785904fa..a211ecf6 100644 --- a/bms-back/bms-admin/src/main/java/com/bms/web/controller/price/BillingController.java +++ b/bms-back/bms-admin/src/main/java/com/bms/web/controller/price/BillingController.java @@ -25,14 +25,19 @@ import com.bms.common.utils.DateUtils; import com.bms.common.utils.MessageUtils; import com.bms.common.utils.StringUtils; import com.bms.price.domain.BatchAddIncomeBillFeeTask; +import com.bms.price.domain.PrcBillingTask; import com.bms.price.domain.PrcOrderBill; import com.bms.price.domain.PrcQuote; import com.bms.price.domain.vo.AddIncomeBillFeeRequest; import com.bms.price.domain.vo.BatchAddIncomeBillFeeRequest; +import com.bms.price.domain.vo.BillingTaskSubmitRequest; import com.bms.price.domain.vo.UpdateIncomeBillFeeRequest; import com.bms.price.domain.vo.TmsPriceBillRequest; import com.bms.price.domain.vo.TmsPriceQuoteRequest; import com.bms.price.domain.vo.TmsPriceQuoteResult; +import com.bms.price.enums.BillTaskSuccessStatus; +import com.bms.price.enums.BillTaskType; +import com.bms.price.service.IPrcBillingTaskService; import com.bms.price.service.IPrcOrderBillService; import com.bms.price.service.ITmsPriceQuoteService; @@ -51,6 +56,9 @@ public class BillingController extends BaseController @Autowired private IPrcOrderBillService prcOrderBillService; + @Autowired + private IPrcBillingTaskService prcBillingTaskService; + /** * Historical quote list. */ @@ -151,6 +159,43 @@ public class BillingController extends BaseController return success(prcOrderBillService.getBill(billId)); } + /** + * Refund one receivable bill via billing task billType=REFUND. + */ + @PreAuthorize("@ss.hasPermi('price:billing:refund')") + @Log(title = "Billing refund", businessType = BusinessType.UPDATE) + @PostMapping("/bill/{billId}/refund") + public AjaxResult refundBill(@PathVariable("billId") String billId) + { + if (StringUtils.isEmpty(billId)) + { + return error("billId required"); + } + TmsPriceQuoteResult bill = prcOrderBillService.getBill(billId.trim()); + if (bill == null || StringUtils.isEmpty(bill.getOrderNo())) + { + return error("bill not found"); + } + BillingTaskSubmitRequest req = new BillingTaskSubmitRequest(); + req.setOrderNo(bill.getOrderNo()); + req.setTrackingNo(bill.getTrackingNo()); + req.setTransferNo(bill.getTransferNo()); + req.setCustomerCode(bill.getCustomerCode()); + req.setBillTime(new Date()); + req.setBillType(BillTaskType.REFUND.getCode()); + PrcBillingTask task = prcBillingTaskService.submitAndProcess(req); + if (task == null) + { + return error("refund failed"); + } + if (!BillTaskSuccessStatus.SUCCESS.getCode().equals(task.getSuccessStatus())) + { + String msg = StringUtils.isNotEmpty(task.getErrorMessage()) ? task.getErrorMessage() : "refund failed"; + return error(msg); + } + return success(task); + } + /** * Batch update order credit arrears status (ARREARS -> NORMAL) with available-credit check. */ diff --git a/bms-back/bms-system/src/main/java/com/bms/price/domain/PrcOrderBill.java b/bms-back/bms-system/src/main/java/com/bms/price/domain/PrcOrderBill.java index afcccf00..eb8a620e 100644 --- a/bms-back/bms-system/src/main/java/com/bms/price/domain/PrcOrderBill.java +++ b/bms-back/bms-system/src/main/java/com/bms/price/domain/PrcOrderBill.java @@ -112,6 +112,8 @@ public class PrcOrderBill extends BaseEntity private String customerActiveStatus; /** NORMAL / ARREARS */ private String creditArrearsStatus; + /** NONE / REFUNDED */ + private String refundStatus; private String roundMode; private List incomeFees; diff --git a/bms-back/bms-system/src/main/java/com/bms/price/domain/vo/TmsPriceQuoteResult.java b/bms-back/bms-system/src/main/java/com/bms/price/domain/vo/TmsPriceQuoteResult.java index 3f23fa76..46f4011a 100644 --- a/bms-back/bms-system/src/main/java/com/bms/price/domain/vo/TmsPriceQuoteResult.java +++ b/bms-back/bms-system/src/main/java/com/bms/price/domain/vo/TmsPriceQuoteResult.java @@ -101,6 +101,8 @@ public class TmsPriceQuoteResult implements Serializable private String customerActiveStatus; /** NORMAL / ARREARS */ private String creditArrearsStatus; + /** NONE / REFUNDED */ + private String refundStatus; private Integer pieces; private BigDecimal actualWeight; private BigDecimal volume; diff --git a/bms-back/bms-system/src/main/java/com/bms/price/enums/BillRefundStatus.java b/bms-back/bms-system/src/main/java/com/bms/price/enums/BillRefundStatus.java new file mode 100644 index 00000000..a2a4e327 --- /dev/null +++ b/bms-back/bms-system/src/main/java/com/bms/price/enums/BillRefundStatus.java @@ -0,0 +1,39 @@ +package com.bms.price.enums; + +/** + * Refund status snapshot on prc_order_bill. + * NONE = not refunded; REFUNDED = has fee_type=REFUND line. + */ +public enum BillRefundStatus +{ + NONE("NONE"), + REFUNDED("REFUNDED"); + + private final String code; + + BillRefundStatus(String code) + { + this.code = code; + } + + public String getCode() + { + return code; + } + + public static BillRefundStatus of(String code) + { + if (code == null) + { + return null; + } + for (BillRefundStatus status : values()) + { + if (status.code.equalsIgnoreCase(code.trim())) + { + return status; + } + } + return null; + } +} diff --git a/bms-back/bms-system/src/main/java/com/bms/price/oracle/OracleOrderBillMapper.java b/bms-back/bms-system/src/main/java/com/bms/price/oracle/OracleOrderBillMapper.java index 97587f84..0a74ec5d 100644 --- a/bms-back/bms-system/src/main/java/com/bms/price/oracle/OracleOrderBillMapper.java +++ b/bms-back/bms-system/src/main/java/com/bms/price/oracle/OracleOrderBillMapper.java @@ -46,12 +46,8 @@ public class OracleOrderBillMapper String countryName = firstStr(row, "COUNTRY_NAME", "COUNTRY_EINGTH_NAME", "COUNTRY"); req.setCountryName(countryName); req.setDestPostcode(firstStr(row, "CONSIGNEE_POSTCODE")); - // TAB_ORDER.DIMENSIONAL_WEIGHT_FACTOR = billing weight (计费重) -> quote weight / prc_order_bill.charge_weight - BigDecimal chargeWeight = firstPositiveDecimal(row, "DIMENSIONAL_WEIGHT_FACTOR"); - BigDecimal weight = chargeWeight != null - ? chargeWeight - : firstPositiveDecimal(row, "ACTUAL_WEIGHT", "PUSH_WEIGHT", "WEIGHT", "VOLUME_WEIGHT"); - req.setWeight(weight); + // Quote / prc_order_bill.weight: use upstream TAB_ORDER.WEIGHT directly. + req.setWeight(firstPositiveDecimal(row, "WEIGHT")); req.setActualWeight(firstPositiveDecimal(row, "ACTUAL_WEIGHT", "PUSH_WEIGHT", "WEIGHT")); req.setPieces(firstInt(row, "ORDER_PIECE", "PACKAGE_NUM", "PRODUCT_SUM")); req.setVolume(toVolumeM3(firstDecimal(row, "VOLUME"))); diff --git a/bms-back/bms-system/src/main/java/com/bms/price/service/impl/PrcOrderBillServiceImpl.java b/bms-back/bms-system/src/main/java/com/bms/price/service/impl/PrcOrderBillServiceImpl.java index b9b9e08c..f2ba31bf 100644 --- a/bms-back/bms-system/src/main/java/com/bms/price/service/impl/PrcOrderBillServiceImpl.java +++ b/bms-back/bms-system/src/main/java/com/bms/price/service/impl/PrcOrderBillServiceImpl.java @@ -54,6 +54,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.BillRefundStatus; import com.bms.price.enums.TmsOrderBillMatchType; import com.bms.price.mapper.PrcIncomeBillFeeMapper; import com.bms.price.mapper.PrcIncomeBillMapper; @@ -184,6 +185,10 @@ public class PrcOrderBillServiceImpl implements IPrcOrderBillService } failReq.setTransferNo(bill.getTransferNo()); assertOrderBillEditable(bill); + if (BillRefundStatus.REFUNDED.getCode().equalsIgnoreCase(bill.getRefundStatus())) + { + throw new ServiceException("\u8ba2\u5355\u5df2\u9000\u8d39\uff0c\u4e0d\u53ef\u91cd\u590d\u9000\u8d39"); + } List fees = incomeBillFeeMapper.selectByBillId(bill.getBillId()); if (fees == null) @@ -194,7 +199,7 @@ public class PrcOrderBillServiceImpl implements IPrcOrderBillService { if (row != null && FEE_TYPE_REFUND.equalsIgnoreCase(row.getFeeType())) { - throw new ServiceException("订单已退费,不可重复退费"); + throw new ServiceException("\u8ba2\u5355\u5df2\u9000\u8d39\uff0c\u4e0d\u53ef\u91cd\u590d\u9000\u8d39"); } } @@ -234,6 +239,7 @@ public class PrcOrderBillServiceImpl implements IPrcOrderBillService refundFee.setArBillStatus(ArIncomeBillFeeStatus.UNBILLED.getCode()); refundFee.setManualFlag("0"); incomeBillFeeMapper.insertPrcIncomeBillFee(refundFee); + bill.setRefundStatus(BillRefundStatus.REFUNDED.getCode()); TmsPriceQuoteResult result = refreshBillIncomeTotals(bill); JSONObject req = new JSONObject(); @@ -243,6 +249,7 @@ public class PrcOrderBillServiceImpl implements IPrcOrderBillService req.put("billId", bill.getBillId()); req.put("refundAmount", feeSum.negate()); req.put("feeId", refundFee.getFeeId()); + req.put("refundStatus", bill.getRefundStatus()); if (billSearchStore != null) { billSearchStore.save(EsLogType.BILL, @@ -718,11 +725,27 @@ public class PrcOrderBillServiceImpl implements IPrcOrderBillService StringUtils.isEmpty(bill.getCustomerActiveStatus()) ? BillCustomerActiveStatus.ACTIVE.getCode() : bill.getCustomerActiveStatus()); bill.setCreditArrearsStatus(creditArrearsStatus); + bill.setRefundStatus(resolveRefundStatus(fees)); orderBillMapper.updatePrcOrderBill(bill); orderBillMapper.refreshArBillStatusByBillIds(Arrays.asList(bill.getBillId())); return toResult(bill, fees, payBillFeeMapper.selectByBillId(bill.getBillId())); } + private static String resolveRefundStatus(List fees) + { + if (fees != null) + { + for (PrcIncomeBillFee row : fees) + { + if (row != null && FEE_TYPE_REFUND.equalsIgnoreCase(row.getFeeType())) + { + return BillRefundStatus.REFUNDED.getCode(); + } + } + } + return BillRefundStatus.NONE.getCode(); + } + private BigDecimal calcManualSurchargeAmount(PrcSurcharge surcharge, BigDecimal weight, BigDecimal freightAmount) { if (surcharge == null || surcharge.getChargeValue() == null) @@ -1106,6 +1129,10 @@ public class PrcOrderBillServiceImpl implements IPrcOrderBillService // Credit soft-fail before persist so insert/update stores arrears flag in one write. String creditArrearsStatus = syncOrderCredit(bill, previousIncome, customerActiveStatus); bill.setCreditArrearsStatus(creditArrearsStatus); + if (existed == null || StringUtils.isEmpty(bill.getRefundStatus())) + { + bill.setRefundStatus(BillRefundStatus.NONE.getCode()); + } result.setBillId(bill.getBillId()); result.setOrderNo(orderNo); result.setTransferNo(bill.getTransferNo()); @@ -1113,6 +1140,7 @@ public class PrcOrderBillServiceImpl implements IPrcOrderBillService result.setCustomerCode(bill.getCustomerCode()); result.setCustomerActiveStatus(customerActiveStatus); result.setCreditArrearsStatus(creditArrearsStatus); + result.setRefundStatus(bill.getRefundStatus()); result.setIncomeTotal(bill.getIncomeTotal()); result.setPayTotal(bill.getPayTotal()); result.setPayableTotal(bill.getIncomeTotal()); @@ -1121,6 +1149,7 @@ public class PrcOrderBillServiceImpl implements IPrcOrderBillService if (existed == null) { bill.setArBillStatus(ArOrderBillStatus.UNBILLED.getCode()); + bill.setRefundStatus(BillRefundStatus.NONE.getCode()); orderBillMapper.insertPrcOrderBill(bill); } else @@ -1152,11 +1181,14 @@ public class PrcOrderBillServiceImpl implements IPrcOrderBillService result.setIncomeTotal(refreshed.getIncomeTotal()); result.setPayableTotal(refreshed.getPayableTotal()); result.setCreditArrearsStatus(refreshed.getCreditArrearsStatus()); + result.setRefundStatus(refreshed.getRefundStatus()); result.setFeeDetails(refreshed.getFeeDetails()); } } else { + bill.setRefundStatus(BillRefundStatus.NONE.getCode()); + result.setRefundStatus(bill.getRefundStatus()); orderBillMapper.refreshArBillStatusByBillIds(Arrays.asList(bill.getBillId())); } // Payable not in scope yet: do not write prc_pay_bill / prc_pay_bill_fee. @@ -1570,6 +1602,9 @@ public class PrcOrderBillServiceImpl implements IPrcOrderBillService r.setCurrency(bill.getCurrency()); r.setRoundMode(bill.getRoundMode()); r.setBizDate(bill.getBizDate()); + r.setCustomerActiveStatus(bill.getCustomerActiveStatus()); + r.setCreditArrearsStatus(bill.getCreditArrearsStatus()); + r.setRefundStatus(bill.getRefundStatus()); r.setFeeDetails(toIncomeFeeLines(incomeFees)); r.setPayFeeDetails(toPayFeeLines(payFees)); PrcIncomeBill incomeBill = incomeBillMapper.selectByBillId(bill.getBillId()); @@ -1661,6 +1696,7 @@ public class PrcOrderBillServiceImpl implements IPrcOrderBillService r.setCustomerName(bill.getCustomerName()); r.setCustomerActiveStatus(bill.getCustomerActiveStatus()); r.setCreditArrearsStatus(bill.getCreditArrearsStatus()); + r.setRefundStatus(bill.getRefundStatus()); r.setPieces(bill.getPieces()); r.setActualWeight(bill.getActualWeight()); r.setVolume(bill.getVolume()); diff --git a/bms-back/bms-system/src/main/java/com/bms/price/task/TabOrderSyncAsyncRunner.java b/bms-back/bms-system/src/main/java/com/bms/price/task/TabOrderSyncAsyncRunner.java index 5bf3bdcc..450b2cb7 100644 --- a/bms-back/bms-system/src/main/java/com/bms/price/task/TabOrderSyncAsyncRunner.java +++ b/bms-back/bms-system/src/main/java/com/bms/price/task/TabOrderSyncAsyncRunner.java @@ -160,6 +160,15 @@ public class TabOrderSyncAsyncRunner /** Sync selected rows with a short-lived worker pool (for HTTP syncSelected). */ public Map syncRowsParallel(List rows) + { + return syncRowsParallel(rows, null); + } + + /** + * Sync or refund selected rows. + * @param billType optional PENDING/REBILL/REFUND; null = auto PENDING/REBILL + */ + public Map syncRowsParallel(List rows, String billType) { Map data = new HashMap(); List> details = new ArrayList>(); @@ -170,6 +179,7 @@ public class TabOrderSyncAsyncRunner data.put("details", details); return data; } + final String fixedBillType = StringUtils.isEmpty(billType) ? null : billType.trim(); int threads = Math.min(clampThreads(billingProperties == null ? null : billingProperties.getOrderSourceSyncThreads()), Math.max(1, rows.size())); ExecutorService pool = newWorkerPool(threads, "order-source-sel"); @@ -187,9 +197,10 @@ public class TabOrderSyncAsyncRunner item.put("transferOrderId", one == null ? null : one.getTransferOrderId()); try { - PrcBillingTask task = billingTaskService.submitAndProcess(toSubmit(one)); + PrcBillingTask task = billingTaskService.submitAndProcess(toSubmit(one, fixedBillType)); item.put("successStatus", task == null ? null : task.getSuccessStatus()); item.put("errorMessage", task == null ? null : task.getErrorMessage()); + item.put("billType", task == null ? fixedBillType : task.getBillType()); if (task != null && BillTaskSuccessStatus.SUCCESS.getCode().equals(task.getSuccessStatus())) { ok.incrementAndGet(); @@ -204,6 +215,7 @@ public class TabOrderSyncAsyncRunner fail.incrementAndGet(); item.put("successStatus", "ERROR"); item.put("errorMessage", e.getMessage()); + item.put("billType", fixedBillType); } return item; }); @@ -357,6 +369,11 @@ public class TabOrderSyncAsyncRunner } public static BillingTaskSubmitRequest toSubmit(TabOrderMonitorVo row) + { + return toSubmit(row, null); + } + + public static BillingTaskSubmitRequest toSubmit(TabOrderMonitorVo row, String billType) { if (row == null) { @@ -368,6 +385,10 @@ public class TabOrderSyncAsyncRunner req.setOrderNo(row.getOrderId()); req.setCustomerCode(row.getCustomerCode()); req.setBillTime(row.getPickupDate()); + if (StringUtils.isNotEmpty(billType)) + { + req.setBillType(billType.trim()); + } return req; } } 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 0b5a12f4..a30666b5 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 @@ -69,6 +69,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" + @@ -92,7 +93,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" weight_min, weight_max, weight_label, effective_date, charge_weight, freight_rate, base_freight_rate, discount_percent, registration_fee, freight_amount, surcharge_amount, income_total, pay_total, currency, ar_bill_status, - customer_active_status, credit_arrears_status, round_mode, + customer_active_status, credit_arrears_status, refund_status, round_mode, created_by, create_time, updated_by, update_time from prc_order_bill p @@ -115,7 +116,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" where f.bill_id = p.bill_id and f.ar_bill_status = #{feeArBillStatus}) as income_total, p.pay_total, p.currency, p.ar_bill_status, - p.customer_active_status, p.credit_arrears_status, p.round_mode, + p.customer_active_status, p.credit_arrears_status, p.refund_status, p.round_mode, p.created_by, p.create_time, p.updated_by, p.update_time from prc_order_bill p left join prc_order_bill_ext e on e.bill_id = p.bill_id @@ -284,6 +285,9 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" AND p.credit_arrears_status = #{creditArrearsStatus} + + AND p.refund_status = #{refundStatus} + AND p.customer_code like concat('%', #{customerCode}, '%') @@ -525,7 +529,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" weight_min, weight_max, weight_label, effective_date, charge_weight, freight_rate, base_freight_rate, discount_percent, registration_fee, freight_amount, surcharge_amount, income_total, pay_total, currency, ar_bill_status, - customer_active_status, credit_arrears_status, round_mode, + customer_active_status, credit_arrears_status, refund_status, round_mode, create_time ) values ( #{billId}, #{billKey}, #{orderNo}, #{trackingNo}, #{transferNo}, @@ -539,7 +543,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" #{weightMin}, #{weightMax}, #{weightLabel}, #{effectiveDate}, #{chargeWeight}, #{freightRate}, #{baseFreightRate}, #{discountPercent}, #{registrationFee}, #{freightAmount}, #{surchargeAmount}, #{incomeTotal}, #{payTotal}, #{currency}, #{arBillStatus}, - #{customerActiveStatus}, #{creditArrearsStatus}, #{roundMode}, + #{customerActiveStatus}, #{creditArrearsStatus}, #{refundStatus}, #{roundMode}, sysdate() ) @@ -607,6 +611,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" currency = #{currency}, customer_active_status = #{customerActiveStatus}, credit_arrears_status = #{creditArrearsStatus}, + refund_status = #{refundStatus}, round_mode = #{roundMode}, update_time = sysdate() where bill_id = #{billId} diff --git a/bms-back/sql/bms_init.sql b/bms-back/sql/bms_init.sql index c74803b9..eb9718b0 100644 --- a/bms-back/sql/bms_init.sql +++ b/bms-back/sql/bms_init.sql @@ -1050,6 +1050,7 @@ CREATE TABLE `prc_order_bill` ( `ar_bill_status` varchar(20) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT 'UNBILLED' COMMENT '应收账单状态:UNBILLED未出账/PARTIAL部分出账/BILLED已出账', `customer_active_status` varchar(20) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '客户生效状态:ACTIVE正常 MISSING不存在 DISABLED停用', `credit_arrears_status` varchar(20) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '额度欠费状态:NORMAL正常 ARREARS欠费', + `refund_status` varchar(20) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT 'NONE' COMMENT '退费状态:NONE未退费/REFUNDED已退费', `round_mode` varchar(20) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT 'HALF_UP' COMMENT '取值方式', `created_by` varchar(64) COLLATE utf8mb4_unicode_ci DEFAULT '' COMMENT '创建人', `create_time` datetime DEFAULT NULL, @@ -1065,6 +1066,7 @@ CREATE TABLE `prc_order_bill` ( KEY `idx_order_bill_transfer_no` (`transfer_no`), KEY `idx_order_bill_customer_active` (`customer_active_status`), KEY `idx_order_bill_credit_arrears` (`credit_arrears_status`), + KEY `idx_order_bill_refund_status` (`refund_status`), KEY `idx_order_bill_psv` (`psv_id`), KEY `idx_order_bill_psd` (`psd_id`), KEY `idx_ar_order_bill_status_scope` (`customer_id`,`currency`,`ar_bill_status`,`biz_date`,`bill_id`) diff --git a/bms-back/sql/monitor/order_source_refund_menu.sql b/bms-back/sql/monitor/order_source_refund_menu.sql new file mode 100644 index 00000000..63bc4ff3 --- /dev/null +++ b/bms-back/sql/monitor/order_source_refund_menu.sql @@ -0,0 +1,4 @@ +-- deprecated: refund moved to billing list (see sql/price/billing_refund_menu.sql) +-- optional cleanup: +-- DELETE FROM sys_role_menu WHERE menu_id = 2328; +-- DELETE FROM sys_menu WHERE menu_id = 2328 OR perms = 'monitor:orderSource:refund'; diff --git a/bms-back/sql/price/billing_refund_menu.sql b/bms-back/sql/price/billing_refund_menu.sql new file mode 100644 index 00000000..a3362ae2 --- /dev/null +++ b/bms-back/sql/price/billing_refund_menu.sql @@ -0,0 +1,20 @@ +-- billing list refund button (billType=REFUND) +SET NAMES utf8mb4; + +INSERT INTO sys_menu (menu_id, menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_by, create_time, remark) +SELECT 2330, N'退费', m.menu_id, 20, '', NULL, 1, 0, 'F', '0', '0', 'price:billing:refund', '#', 'admin', sysdate(), N'计费列表单笔退费(billType=REFUND)' +FROM ( + SELECT menu_id FROM sys_menu + WHERE perms = 'price:billing:bill' AND menu_type = 'C' + UNION ALL + SELECT menu_id FROM sys_menu + WHERE component = 'price/billing/bill' AND menu_type = 'C' +) m +WHERE NOT EXISTS (SELECT 1 FROM sys_menu x WHERE x.menu_id = 2330 OR x.perms = 'price:billing:refund') +LIMIT 1; + +INSERT INTO sys_role_menu (role_id, menu_id) +SELECT 1, 2330 +FROM DUAL +WHERE EXISTS (SELECT 1 FROM sys_menu WHERE menu_id = 2330) + AND NOT EXISTS (SELECT 1 FROM sys_role_menu rm WHERE rm.role_id = 1 AND rm.menu_id = 2330); diff --git a/bms-back/sql/price/order_bill_refund_status_alter.sql b/bms-back/sql/price/order_bill_refund_status_alter.sql new file mode 100644 index 00000000..7be1dfac --- /dev/null +++ b/bms-back/sql/price/order_bill_refund_status_alter.sql @@ -0,0 +1,34 @@ +-- prc_order_bill.refund_status +SET NAMES utf8mb4; + +SET @col := ( + SELECT COLUMN_NAME FROM information_schema.COLUMNS + WHERE TABLE_SCHEMA = DATABASE() + AND TABLE_NAME = 'prc_order_bill' + AND COLUMN_NAME = 'refund_status' + LIMIT 1 +); +SET @sql := IF( + @col IS NULL, + 'ALTER TABLE prc_order_bill ADD COLUMN refund_status varchar(20) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT ''NONE'' COMMENT ''退费状态:NONE未退费/REFUNDED已退费'' AFTER credit_arrears_status, ADD KEY idx_order_bill_refund_status (refund_status)', + 'SELECT 1' +); +PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt; + +UPDATE prc_order_bill b +SET b.refund_status = 'REFUNDED' +WHERE EXISTS ( + SELECT 1 FROM prc_income_bill_fee f + WHERE f.bill_id = b.bill_id + AND UPPER(f.fee_type) = 'REFUND' +) +AND (b.refund_status IS NULL OR b.refund_status <> 'REFUNDED'); + +UPDATE prc_order_bill b +SET b.refund_status = 'NONE' +WHERE (b.refund_status IS NULL OR b.refund_status = '') + AND NOT EXISTS ( + SELECT 1 FROM prc_income_bill_fee f + WHERE f.bill_id = b.bill_id + AND UPPER(f.fee_type) = 'REFUND' + ); diff --git a/bms-front/src/api/monitor/orderSource.js b/bms-front/src/api/monitor/orderSource.js index 1a1fc831..820e6773 100644 --- a/bms-front/src/api/monitor/orderSource.js +++ b/bms-front/src/api/monitor/orderSource.js @@ -66,3 +66,4 @@ export function listOrderSourceOrdersByProduct(data) { timeout: 120000 }) } + diff --git a/bms-front/src/api/price/billing.js b/bms-front/src/api/price/billing.js index 8d68b9a4..96454daf 100644 --- a/bms-front/src/api/price/billing.js +++ b/bms-front/src/api/price/billing.js @@ -61,6 +61,15 @@ export function getBill(billId) { }) } +/** Refund receivable bill (billType=REFUND) */ +export function refundBill(billId) { + return request({ + url: '/price/billing/bill/' + encodeURIComponent(billId) + '/refund', + method: 'post', + timeout: 120000 + }) +} + /** Order no options for remote search (bill list multi search) */ export function listOrderNoOptions(keyword) { return request({ diff --git a/bms-front/src/views/monitor/orderSource/index.vue b/bms-front/src/views/monitor/orderSource/index.vue index f3adeb0a..575d13e9 100644 --- a/bms-front/src/views/monitor/orderSource/index.vue +++ b/bms-front/src/views/monitor/orderSource/index.vue @@ -280,6 +280,7 @@ function toSyncRow(row) { } } + function handleSyncOne(row) { proxy.$modal.confirm('确认同步计费该订单?', '二次确认').then(() => { syncingKey.value = rowKey(row) diff --git a/bms-front/src/views/price/billing/bill.vue b/bms-front/src/views/price/billing/bill.vue index fb727931..6e5a8605 100644 --- a/bms-front/src/views/price/billing/bill.vue +++ b/bms-front/src/views/price/billing/bill.vue @@ -64,6 +64,9 @@ + @@ -83,6 +86,15 @@ @@ -98,7 +110,7 @@