修改计费重

This commit is contained in:
wuweihua
2026-10-13 17:12:32 +08:00
parent 5c48717da2
commit d6a6ec4d53
17 changed files with 294 additions and 14 deletions
@@ -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.
*/
@@ -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<PrcIncomeBillFee> incomeFees;
@@ -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;
@@ -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;
}
}
@@ -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")));
@@ -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<PrcIncomeBillFee> 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<PrcIncomeBillFee> 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());
@@ -160,6 +160,15 @@ public class TabOrderSyncAsyncRunner
/** Sync selected rows with a short-lived worker pool (for HTTP syncSelected). */
public Map<String, Object> syncRowsParallel(List<TabOrderMonitorVo> rows)
{
return syncRowsParallel(rows, null);
}
/**
* Sync or refund selected rows.
* @param billType optional PENDING/REBILL/REFUND; null = auto PENDING/REBILL
*/
public Map<String, Object> syncRowsParallel(List<TabOrderMonitorVo> rows, String billType)
{
Map<String, Object> data = new HashMap<String, Object>();
List<Map<String, Object>> details = new ArrayList<Map<String, Object>>();
@@ -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;
}
}
@@ -69,6 +69,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<result property="arBillStatus" column="ar_bill_status" />
<result property="customerActiveStatus" column="customer_active_status" />
<result property="creditArrearsStatus" column="credit_arrears_status" />
<result property="refundStatus" column="refund_status" />
<result property="roundMode" column="round_mode" />
<result property="createBy" column="created_by" />
<result property="createTime" column="create_time" />
@@ -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
</sql>
@@ -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"
<if test="creditArrearsStatus != null and creditArrearsStatus != ''">
AND p.credit_arrears_status = #{creditArrearsStatus}
</if>
<if test="refundStatus != null and refundStatus != ''">
AND p.refund_status = #{refundStatus}
</if>
<if test="customerCode != null and customerCode != ''">
AND p.customer_code like concat('%', #{customerCode}, '%')
</if>
@@ -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()
)
</insert>
@@ -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}
+2
View File
@@ -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`)
@@ -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';
@@ -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);
@@ -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'
);
+1
View File
@@ -66,3 +66,4 @@ export function listOrderSourceOrdersByProduct(data) {
timeout: 120000
})
}
+9
View File
@@ -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({
@@ -280,6 +280,7 @@ function toSyncRow(row) {
}
}
function handleSyncOne(row) {
proxy.$modal.confirm('确认同步计费该订单?', '二次确认').then(() => {
syncingKey.value = rowKey(row)
+59 -2
View File
@@ -64,6 +64,9 @@
<template #col-creditArrearsStatus="{ row }">
<el-tag size="small" :type="creditArrearsTagType(row.creditArrearsStatus)">{{ creditArrearsLabel(row.creditArrearsStatus) }}</el-tag>
</template>
<template #col-refundStatus="{ row }">
<el-tag size="small" :type="refundTagType(row.refundStatus)">{{ refundLabel(row.refundStatus) }}</el-tag>
</template>
<template #col-incomeTotal="{ row }">
<span class="payable">{{ formatMoney(row.incomeTotal) }}</span>
</template>
@@ -83,6 +86,15 @@
</template>
<template #col-action="{ row }">
<el-button link type="primary" icon="View" @click="handleView(row)">查看</el-button>
<el-button
link
type="danger"
icon="RefreshLeft"
:loading="refundingKey === row.billId"
:disabled="row.refundStatus === 'REFUNDED'"
v-hasPermi="['price:billing:refund']"
@click="handleRefund(row)"
>退费</el-button>
</template>
</basic-table>
@@ -98,7 +110,7 @@
</template>
<script setup name="BillingBill">
import { listBill, getBill, listOrderNoOptions, listTrackingNoOptions, listTransferNoOptions, updateCreditArrears } from '@/api/price/billing'
import { listBill, getBill, refundBill, listOrderNoOptions, listTrackingNoOptions, listTransferNoOptions, updateCreditArrears } from '@/api/price/billing'
import { ElMessage, ElMessageBox } from 'element-plus'
import { useProducts } from '@/components/ProductSelect/useProducts'
import BillDetail from './components/BillDetail.vue'
@@ -136,6 +148,7 @@ const detail = ref(null)
const batchFeeOpen = ref(false)
const batchFeeListQuery = ref({})
const batchFeeSelectedIds = ref([])
const refundingKey = ref(null)
const columns = [
{ label: '订单号', prop: 'orderNo', minWidth: 140, showOverflowTooltip: true },
@@ -152,18 +165,23 @@ const columns = [
{ label: '计价来源', prop: 'matchSource', align: 'center', width: 130, slot: 'matchSource' },
{ label: '客户状态', prop: 'customerActiveStatus', align: 'center', width: 100, slot: 'customerActiveStatus' },
{ label: '额度欠费', prop: 'creditArrearsStatus', align: 'center', width: 100, slot: 'creditArrearsStatus' },
{ label: '退费状态', prop: 'refundStatus', align: 'center', width: 100, slot: 'refundStatus' },
{ label: '计费时间', prop: 'bizDate', align: 'center', width: 170, parseTime: true },
{ label: '下单时间', prop: 'orderTime', align: 'center', width: 170, parseTime: true },
{ label: '销售员', prop: 'belongSaler', minWidth: 100, showOverflowTooltip: true },
{ label: '结算员', prop: 'settlementMan', minWidth: 100, showOverflowTooltip: true },
// { label: '客服员', prop: 'serviceMan', minWidth: 100, showOverflowTooltip: true },
{ label: '操作', prop: 'action', align: 'center', width: 90, fixed: 'right', slot: 'action', showInToolbar: false }
{ label: '操作', prop: 'action', align: 'center', width: 160, fixed: 'right', slot: 'action', showInToolbar: false }
]
const arrearsStatusOptions = [
{ label: '正常', value: 'NORMAL' },
{ label: '欠费', value: 'ARREARS' }
]
const refundStatusOptions = [
{ label: '未退费', value: 'NONE' },
{ label: '已退费', value: 'REFUNDED' }
]
const searchColumns = [
{ label: '订单号', prop: 'orderNos', placeholder: '订单号' },
@@ -179,6 +197,14 @@ const searchColumns = [
placeholder: '请选择',
props: { clearable: true }
},
{
label: '退费状态',
prop: 'refundStatus',
component: 'select',
options: refundStatusOptions,
placeholder: '请选择',
props: { clearable: true }
},
{
label: '计费时间',
prop: 'bizDateRange',
@@ -227,6 +253,27 @@ function handleUpdateArrears(ids, selection) {
}).catch(() => {})
}
function handleRefund(row) {
if (!row || !row.billId) return
if (row.refundStatus === 'REFUNDED') {
ElMessage.warning('该订单已退费')
return
}
ElMessageBox.confirm(
'确认对订单 ' + (row.orderNo || '') + ' 发起退费?',
'退费确认',
{ type: 'warning' }
).then(() => {
refundingKey.value = row.billId
return refundBill(row.billId)
}).then(() => {
ElMessage.success('退费成功')
tableRef.value?.refresh?.()
}).catch(() => {}).finally(() => {
refundingKey.value = null
})
}
function handleView(row) {
title.value = '计费详情'
open.value = true
@@ -330,6 +377,16 @@ function creditArrearsTagType(status) {
if (status === 'ARREARS') return 'danger'
return 'info'
}
function refundLabel(status) {
const map = { NONE: '未退费', REFUNDED: '已退费' }
return map[status] || status || '未退费'
}
function refundTagType(status) {
if (status === 'REFUNDED') return 'danger'
return 'success'
}
</script>
<style scoped>
@@ -23,6 +23,7 @@
<el-descriptions-item label="客户">{{ displayCustomer(detail) }}</el-descriptions-item>
<el-descriptions-item label="客户状态">{{ customerActiveLabel(detail.customerActiveStatus) }}</el-descriptions-item>
<el-descriptions-item label="额度欠费">{{ creditArrearsLabel(detail.creditArrearsStatus) }}</el-descriptions-item>
<el-descriptions-item label="退费状态">{{ refundLabel(detail.refundStatus) }}</el-descriptions-item>
<el-descriptions-item label="仓库">{{ detail.warehouseCode || '-' }}</el-descriptions-item>
<el-descriptions-item label="发件人">{{ detail.shipperName || '-' }}</el-descriptions-item>
<el-descriptions-item label="收件人">{{ detail.consigneeName || '-' }}</el-descriptions-item>
@@ -357,6 +358,11 @@ function sourceTagType(source) {
if (source === 'PRODUCT_DEFAULT') return 'info'
return ''
}
function refundLabel(status) {
const map = { NONE: '未退费', REFUNDED: '已退费' }
return map[status] || status || '未退费'
}
</script>
<style scoped>