Compare commits
2 Commits
a06962d1dd
...
2430e344a0
| Author | SHA1 | Date | |
|---|---|---|---|
| 2430e344a0 | |||
| 5db27e00ba |
+17
-27
@@ -152,8 +152,8 @@ public class BillingController extends BaseController
|
|||||||
{
|
{
|
||||||
query = new PrcOrderBill();
|
query = new PrcOrderBill();
|
||||||
}
|
}
|
||||||
// Billing list only shows success and the three soft misses.
|
// Billing list only shows successfully billed orders.
|
||||||
query.setBillingFailStatuses(limitBillingListFailStatus(query.getBillingFailStatuses()));
|
query.setBillingFailStatuses(limitBillingListFailStatus());
|
||||||
query.setBillingFailStatus(null);
|
query.setBillingFailStatus(null);
|
||||||
startPage();
|
startPage();
|
||||||
List<PrcOrderBill> list = prcOrderBillService.selectBillList(query);
|
List<PrcOrderBill> list = prcOrderBillService.selectBillList(query);
|
||||||
@@ -161,7 +161,7 @@ public class BillingController extends BaseController
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Async export billing list by current filters (status limited to 0-3).
|
* Async export billing list by current filters (status limited to success=0).
|
||||||
* Requires at least one meaningful filter. Poll task then download.
|
* Requires at least one meaningful filter. Poll task then download.
|
||||||
*/
|
*/
|
||||||
@PreAuthorize("@ss.hasPermi('price:billing:export')")
|
@PreAuthorize("@ss.hasPermi('price:billing:export')")
|
||||||
@@ -178,7 +178,7 @@ public class BillingController extends BaseController
|
|||||||
{
|
{
|
||||||
return error(MessageUtils.message("price.bill.export.filterRequired"));
|
return error(MessageUtils.message("price.bill.export.filterRequired"));
|
||||||
}
|
}
|
||||||
query.setBillingFailStatuses(limitBillingListFailStatus(query.getBillingFailStatuses()));
|
query.setBillingFailStatuses(limitBillingListFailStatus());
|
||||||
query.setBillingFailStatus(null);
|
query.setBillingFailStatus(null);
|
||||||
return successTask(prcOrderBillService.submitOrderBillExport(
|
return successTask(prcOrderBillService.submitOrderBillExport(
|
||||||
PrcOrderBillExportTask.TYPE_BILLING, query));
|
PrcOrderBillExportTask.TYPE_BILLING, query));
|
||||||
@@ -204,32 +204,13 @@ public class BillingController extends BaseController
|
|||||||
prcOrderBillService.downloadOrderBillExport(taskId, response);
|
prcOrderBillService.downloadOrderBillExport(taskId, response);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static List<Integer> limitBillingListFailStatus(List<Integer> requested)
|
private static List<Integer> limitBillingListFailStatus()
|
||||||
{
|
{
|
||||||
// Soft-fail list: success + sales 1/2/3 + product-catalog 23/24/25
|
// Billing list is success-only (billing_fail_status = 0).
|
||||||
List<Integer> allowed = Arrays.asList(
|
return new ArrayList<Integer>(Arrays.asList(Integer.valueOf(0)));
|
||||||
Integer.valueOf(0), Integer.valueOf(1), Integer.valueOf(2), Integer.valueOf(3),
|
|
||||||
Integer.valueOf(23), Integer.valueOf(24), Integer.valueOf(25));
|
|
||||||
if (requested == null || requested.isEmpty())
|
|
||||||
{
|
|
||||||
return new ArrayList<Integer>(allowed);
|
|
||||||
}
|
|
||||||
List<Integer> kept = new ArrayList<Integer>();
|
|
||||||
for (Integer status : requested)
|
|
||||||
{
|
|
||||||
if (status != null && allowed.contains(status) && !kept.contains(status))
|
|
||||||
{
|
|
||||||
kept.add(status);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (kept.isEmpty())
|
|
||||||
{
|
|
||||||
kept.add(Integer.valueOf(-1));
|
|
||||||
}
|
|
||||||
return kept;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** All prc_order_bill rows. Billing list stays limited to status 0-3. */
|
/** All prc_order_bill rows. Billing list stays limited to status 0. */
|
||||||
@PreAuthorize("@ss.hasPermi('price:orderBill:list')")
|
@PreAuthorize("@ss.hasPermi('price:orderBill:list')")
|
||||||
@GetMapping("/orderBill/list")
|
@GetMapping("/orderBill/list")
|
||||||
public TableDataInfo orderBillList(PrcOrderBill query)
|
public TableDataInfo orderBillList(PrcOrderBill query)
|
||||||
@@ -239,6 +220,15 @@ public class BillingController extends BaseController
|
|||||||
return getDataTable(list);
|
return getDataTable(list);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/** Order-list popup: billing fail reason by billId (data-scoped). */
|
||||||
|
@PreAuthorize("@ss.hasPermi('price:orderBill:list')")
|
||||||
|
@GetMapping("/orderBill/{billId}/failReason")
|
||||||
|
public AjaxResult orderBillFailReason(@PathVariable("billId") String billId)
|
||||||
|
{
|
||||||
|
return success(prcOrderBillService.getBillingFailReason(billId));
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Async export order list by current filters.
|
* Async export order list by current filters.
|
||||||
* Requires at least one meaningful filter (default orderStatuses alone is not enough).
|
* Requires at least one meaningful filter (default orderStatuses alone is not enough).
|
||||||
|
|||||||
@@ -0,0 +1,61 @@
|
|||||||
|
package com.bms.price.domain.vo;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
import java.util.Date;
|
||||||
|
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Order-list billing fail reason popup payload.
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class OrderBillFailReasonVo implements Serializable
|
||||||
|
{
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
private String billId;
|
||||||
|
private String orderNo;
|
||||||
|
private String transferNo;
|
||||||
|
private String trackingNo;
|
||||||
|
|
||||||
|
private String customerCode;
|
||||||
|
private String customerName;
|
||||||
|
private String productCode;
|
||||||
|
private String productName;
|
||||||
|
private String countryCode;
|
||||||
|
private String countryName;
|
||||||
|
private String zoneCode;
|
||||||
|
private String zoneName;
|
||||||
|
private String destPostcode;
|
||||||
|
|
||||||
|
private Long priceSetId;
|
||||||
|
private String priceSetCode;
|
||||||
|
private String priceSetName;
|
||||||
|
private String setType;
|
||||||
|
private Long psvId;
|
||||||
|
private String versionNo;
|
||||||
|
private Long psdId;
|
||||||
|
|
||||||
|
private BigDecimal weight;
|
||||||
|
private BigDecimal chargeWeight;
|
||||||
|
private BigDecimal weightMin;
|
||||||
|
private BigDecimal weightMax;
|
||||||
|
private String weightLabel;
|
||||||
|
private BigDecimal freightRate;
|
||||||
|
private BigDecimal freightAmount;
|
||||||
|
private BigDecimal incomeTotal;
|
||||||
|
private String currency;
|
||||||
|
|
||||||
|
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||||
|
private Date bizDate;
|
||||||
|
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||||
|
private Date pickupDate;
|
||||||
|
|
||||||
|
private Integer billingFailStatus;
|
||||||
|
private String billingFailStatusLabel;
|
||||||
|
/** Raw persisted fail text. */
|
||||||
|
private String errorMessage;
|
||||||
|
/** Templated human-readable fail reason. */
|
||||||
|
private String failReasonDetail;
|
||||||
|
}
|
||||||
@@ -13,6 +13,7 @@ import com.bms.price.domain.vo.BatchAddIncomeBillFeeRequest;
|
|||||||
import com.bms.price.domain.vo.ChargeWeightImportRow;
|
import com.bms.price.domain.vo.ChargeWeightImportRow;
|
||||||
import com.bms.price.domain.vo.ChargeWeightTemplateRequest;
|
import com.bms.price.domain.vo.ChargeWeightTemplateRequest;
|
||||||
import com.bms.price.domain.vo.LocalRebillRequest;
|
import com.bms.price.domain.vo.LocalRebillRequest;
|
||||||
|
import com.bms.price.domain.vo.OrderBillFailReasonVo;
|
||||||
import com.bms.price.domain.vo.RecalcBillPriceRequest;
|
import com.bms.price.domain.vo.RecalcBillPriceRequest;
|
||||||
import com.bms.price.domain.vo.UpdateIncomeBillFeeRequest;
|
import com.bms.price.domain.vo.UpdateIncomeBillFeeRequest;
|
||||||
import com.bms.price.domain.vo.TmsPriceBillRequest;
|
import com.bms.price.domain.vo.TmsPriceBillRequest;
|
||||||
@@ -60,6 +61,9 @@ public interface IPrcOrderBillService
|
|||||||
|
|
||||||
TmsPriceQuoteResult getBill(String billId);
|
TmsPriceQuoteResult getBill(String billId);
|
||||||
|
|
||||||
|
/** Billing fail reason for order-list popup (data-scoped). */
|
||||||
|
OrderBillFailReasonVo getBillingFailReason(String billId);
|
||||||
|
|
||||||
TmsPriceQuoteResult getBillByOrderNo(String orderNo);
|
TmsPriceQuoteResult getBillByOrderNo(String orderNo);
|
||||||
|
|
||||||
/** Manual add income fee from surcharge config; refresh receivable totals. */
|
/** Manual add income fee from surcharge config; refresh receivable totals. */
|
||||||
|
|||||||
+92
@@ -62,6 +62,7 @@ import com.bms.price.domain.vo.BatchAddIncomeBillFeeRequest;
|
|||||||
import com.bms.price.domain.vo.ChargeWeightImportRow;
|
import com.bms.price.domain.vo.ChargeWeightImportRow;
|
||||||
import com.bms.price.domain.vo.ChargeWeightTemplateRequest;
|
import com.bms.price.domain.vo.ChargeWeightTemplateRequest;
|
||||||
import com.bms.price.domain.vo.LocalRebillRequest;
|
import com.bms.price.domain.vo.LocalRebillRequest;
|
||||||
|
import com.bms.price.domain.vo.OrderBillFailReasonVo;
|
||||||
import com.bms.price.domain.vo.RecalcBillPriceRequest;
|
import com.bms.price.domain.vo.RecalcBillPriceRequest;
|
||||||
import com.bms.price.domain.vo.UpdateIncomeBillFeeRequest;
|
import com.bms.price.domain.vo.UpdateIncomeBillFeeRequest;
|
||||||
import com.bms.price.task.PrcBatchAddIncomeFeeAsyncRunner;
|
import com.bms.price.task.PrcBatchAddIncomeFeeAsyncRunner;
|
||||||
@@ -70,6 +71,7 @@ import com.bms.price.task.PrcChargeWeightImportAsyncRunner.ChargeWeightImportWor
|
|||||||
import com.bms.price.task.PrcOrderBillExportAsyncRunner;
|
import com.bms.price.task.PrcOrderBillExportAsyncRunner;
|
||||||
import com.bms.price.task.PrcOrderBillLocalRebillAsyncRunner;
|
import com.bms.price.task.PrcOrderBillLocalRebillAsyncRunner;
|
||||||
import com.bms.price.task.PrcRecalcBillPriceAsyncRunner;
|
import com.bms.price.task.PrcRecalcBillPriceAsyncRunner;
|
||||||
|
import com.bms.price.service.support.BillingFailReasonSupport;
|
||||||
import com.bms.price.service.support.OrderBillExportSupport;
|
import com.bms.price.service.support.OrderBillExportSupport;
|
||||||
import com.bms.price.domain.vo.TmsPriceBillRequest;
|
import com.bms.price.domain.vo.TmsPriceBillRequest;
|
||||||
import com.bms.price.domain.vo.TmsOrderBillStatusResult;
|
import com.bms.price.domain.vo.TmsOrderBillStatusResult;
|
||||||
@@ -85,6 +87,10 @@ import com.bms.price.mapper.PrcIncomeBillFeeMapper;
|
|||||||
import com.bms.price.mapper.PrcIncomeBillMapper;
|
import com.bms.price.mapper.PrcIncomeBillMapper;
|
||||||
import com.bms.price.mapper.PrcOrderBillExtMapper;
|
import com.bms.price.mapper.PrcOrderBillExtMapper;
|
||||||
import com.bms.price.mapper.PrcOrderBillMapper;
|
import com.bms.price.mapper.PrcOrderBillMapper;
|
||||||
|
import com.bms.price.mapper.PrcPriceSetDetailMapper;
|
||||||
|
import com.bms.price.mapper.PrcPriceSetVersionMapper;
|
||||||
|
import com.bms.price.domain.PrcPriceSetDetail;
|
||||||
|
import com.bms.price.domain.PrcPriceSetVersion;
|
||||||
import com.bms.price.mapper.PrcPayBillFeeMapper;
|
import com.bms.price.mapper.PrcPayBillFeeMapper;
|
||||||
import com.bms.price.mapper.PrcPayBillMapper;
|
import com.bms.price.mapper.PrcPayBillMapper;
|
||||||
import com.bms.price.oracle.OracleOrderBillExtFiller;
|
import com.bms.price.oracle.OracleOrderBillExtFiller;
|
||||||
@@ -120,6 +126,12 @@ public class PrcOrderBillServiceImpl implements IPrcOrderBillService
|
|||||||
@Autowired
|
@Autowired
|
||||||
private PrcOrderBillMapper orderBillMapper;
|
private PrcOrderBillMapper orderBillMapper;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private PrcPriceSetVersionMapper priceSetVersionMapper;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private PrcPriceSetDetailMapper priceSetDetailMapper;
|
||||||
|
|
||||||
/** TMS 实时状态查询使用客户主档案,不读取订单上的历史状态快照。 */
|
/** TMS 实时状态查询使用客户主档案,不读取订单上的历史状态快照。 */
|
||||||
@Autowired
|
@Autowired
|
||||||
private BmsCustomerMapper bmsCustomerMapper;
|
private BmsCustomerMapper bmsCustomerMapper;
|
||||||
@@ -432,6 +444,86 @@ public class PrcOrderBillServiceImpl implements IPrcOrderBillService
|
|||||||
payBillFeeMapper.selectByBillId(bill.getBillId()));
|
payBillFeeMapper.selectByBillId(bill.getBillId()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public OrderBillFailReasonVo getBillingFailReason(String billId)
|
||||||
|
{
|
||||||
|
if (StringUtils.isEmpty(billId))
|
||||||
|
{
|
||||||
|
throw new ServiceException(MessageUtils.message("price.bill.billIdRequired"));
|
||||||
|
}
|
||||||
|
PrcOrderBill query = new PrcOrderBill();
|
||||||
|
query.setBillId(billId.trim());
|
||||||
|
List<PrcOrderBill> list = self.selectBillList(query);
|
||||||
|
if (list == null || list.isEmpty())
|
||||||
|
{
|
||||||
|
throw new ServiceException(MessageUtils.message("price.bill.notFound"));
|
||||||
|
}
|
||||||
|
PrcOrderBill bill = list.get(0);
|
||||||
|
OrderBillFailReasonVo vo = new OrderBillFailReasonVo();
|
||||||
|
vo.setBillId(bill.getBillId());
|
||||||
|
vo.setOrderNo(bill.getOrderNo());
|
||||||
|
vo.setTransferNo(bill.getTransferNo());
|
||||||
|
vo.setTrackingNo(bill.getTrackingNo());
|
||||||
|
vo.setCustomerCode(bill.getCustomerCode());
|
||||||
|
vo.setCustomerName(bill.getCustomerName());
|
||||||
|
vo.setProductCode(bill.getProductCode());
|
||||||
|
vo.setProductName(bill.getProductName());
|
||||||
|
vo.setCountryCode(bill.getCountryCode());
|
||||||
|
vo.setCountryName(bill.getCountryName());
|
||||||
|
vo.setDestPostcode(bill.getDestPostcode());
|
||||||
|
vo.setPriceSetId(bill.getPriceSetId());
|
||||||
|
vo.setPriceSetCode(bill.getPriceSetCode());
|
||||||
|
vo.setPriceSetName(bill.getPriceSetName());
|
||||||
|
vo.setSetType(bill.getSetType());
|
||||||
|
vo.setPsvId(bill.getPsvId());
|
||||||
|
vo.setPsdId(bill.getPsdId());
|
||||||
|
vo.setWeight(bill.getWeight());
|
||||||
|
vo.setChargeWeight(bill.getChargeWeight());
|
||||||
|
vo.setWeightMin(bill.getWeightMin());
|
||||||
|
vo.setWeightMax(bill.getWeightMax());
|
||||||
|
vo.setWeightLabel(bill.getWeightLabel());
|
||||||
|
vo.setFreightRate(bill.getFreightRate());
|
||||||
|
vo.setFreightAmount(bill.getFreightAmount());
|
||||||
|
vo.setIncomeTotal(bill.getIncomeTotal());
|
||||||
|
vo.setCurrency(bill.getCurrency());
|
||||||
|
vo.setBizDate(bill.getBizDate());
|
||||||
|
vo.setPickupDate(bill.getPickupDate());
|
||||||
|
Integer status = bill.getBillingFailStatus() == null
|
||||||
|
? Integer.valueOf(BillBillingFailStatus.SUCCESS.getCode()) : bill.getBillingFailStatus();
|
||||||
|
vo.setBillingFailStatus(status);
|
||||||
|
vo.setBillingFailStatusLabel(OrderBillExportSupport.billingFailStatusLabel(status));
|
||||||
|
if (bill.getPsvId() != null && priceSetVersionMapper != null)
|
||||||
|
{
|
||||||
|
PrcPriceSetVersion ver = priceSetVersionMapper.selectPrcPriceSetVersionById(bill.getPsvId());
|
||||||
|
if (ver != null)
|
||||||
|
{
|
||||||
|
vo.setVersionNo(ver.getVersionNo());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (bill.getPsdId() != null && priceSetDetailMapper != null)
|
||||||
|
{
|
||||||
|
PrcPriceSetDetail detail = priceSetDetailMapper.selectPrcPriceSetDetailById(bill.getPsdId());
|
||||||
|
if (detail != null)
|
||||||
|
{
|
||||||
|
vo.setZoneCode(detail.getZoneCode());
|
||||||
|
vo.setZoneName(detail.getZoneName());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
String reason = bill.getErrorMessage();
|
||||||
|
if (StringUtils.isEmpty(reason))
|
||||||
|
{
|
||||||
|
reason = bill.getMatchMessage();
|
||||||
|
}
|
||||||
|
if (StringUtils.isEmpty(reason))
|
||||||
|
{
|
||||||
|
reason = vo.getBillingFailStatusLabel();
|
||||||
|
}
|
||||||
|
vo.setErrorMessage(reason);
|
||||||
|
vo.setFailReasonDetail(BillingFailReasonSupport.buildDetail(vo, reason));
|
||||||
|
return vo;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public TmsPriceQuoteResult getBillByOrderNo(String orderNo)
|
public TmsPriceQuoteResult getBillByOrderNo(String orderNo)
|
||||||
{
|
{
|
||||||
|
|||||||
+114
@@ -0,0 +1,114 @@
|
|||||||
|
package com.bms.price.service.support;
|
||||||
|
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
import java.text.SimpleDateFormat;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
import com.bms.common.utils.StringUtils;
|
||||||
|
import com.bms.price.domain.vo.OrderBillFailReasonVo;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Build templated billing-fail reason text for order-list popup.
|
||||||
|
*/
|
||||||
|
public final class BillingFailReasonSupport
|
||||||
|
{
|
||||||
|
private BillingFailReasonSupport() {}
|
||||||
|
|
||||||
|
private static final Map<Integer, String> TEMPLATES = new HashMap<Integer, String>();
|
||||||
|
|
||||||
|
static
|
||||||
|
{
|
||||||
|
TEMPLATES.put(Integer.valueOf(1), "\u3010\u9500\u552e\u4ef7\u672a\u5339\u914d\u4ea7\u54c1\u3011\n\u8ba2\u5355 {orderNo}\uff08\u8f6c\u5355\u53f7 {transferNo}\uff09\uff0c\u5ba2\u6237 {customer}\uff0c\u4ea7\u54c1 {product}\uff0c\u56fd\u5bb6 {country}\uff0c\u8ba1\u8d39\u65f6\u95f4 {bizDate}\u3002\n\u5728\u5ba2\u6237\u9500\u552e\u4ef7\u5957\u9910\u300c{priceSet}\u300d\u4e2d\u672a\u627e\u5230\u8be5\u4ea7\u54c1\uff0c\u8bf7\u68c0\u67e5\u5957\u9910\u4ea7\u54c1\u8303\u56f4\u6216\u4ea7\u54c1\u4ee3\u7801\u6620\u5c04\u3002");
|
||||||
|
TEMPLATES.put(Integer.valueOf(2), "\u3010\u9500\u552e\u4ef7\u672a\u5339\u914d\u56fd\u5bb6\u3011\n\u8ba2\u5355 {orderNo}\uff08\u8f6c\u5355\u53f7 {transferNo}\uff09\uff0c\u5ba2\u6237 {customer}\uff0c\u4ea7\u54c1 {product}\uff0c\u76ee\u7684\u56fd\u5bb6 {country}\uff0c\u90ae\u7f16 {postcode}\uff0c\u8ba1\u8d39\u65f6\u95f4 {bizDate}\u3002\n\u5957\u9910\u300c{priceSet}\u300d\u7248\u672c {version}\u5df2\u547d\u4e2d\u4ea7\u54c1\uff0c\u4f46\u672a\u547d\u4e2d\u56fd\u5bb6/\u5206\u533a\uff0c\u8bf7\u8865\u9f50\u56fd\u5bb6\u4e0e\u5206\u533a\u4ef7\u683c\u3002");
|
||||||
|
TEMPLATES.put(Integer.valueOf(3), "\u3010\u9500\u552e\u4ef7\u672a\u5339\u914d\u91cd\u91cf\u6bb5\u3011\n\u8ba2\u5355 {orderNo}\uff08\u8f6c\u5355\u53f7 {transferNo}\uff09\uff0c\u5ba2\u6237 {customer}\uff0c\u4ea7\u54c1 {product}\uff0c\u56fd\u5bb6 {country}\uff0c\u5206\u533a {zone}\uff0c\u8ba1\u8d39\u91cd {chargeWeight} kg\uff0c\u8ba1\u8d39\u65f6\u95f4 {bizDate}\u3002\n\u5957\u9910\u300c{priceSet}\u300d\u7248\u672c {version}\u5df2\u547d\u4e2d\u4ea7\u54c1\u4e0e\u56fd\u5bb6\uff0c\u4f46\u8ba1\u8d39\u91cd\u672a\u843d\u5728\u4ef7\u683c\u91cd\u91cf\u6bb5\u5185\uff0c\u8bf7\u68c0\u67e5\u91cd\u91cf\u6bb5\u8bbe\u7f6e\u3002");
|
||||||
|
TEMPLATES.put(Integer.valueOf(23), "\u3010\u4ea7\u54c1\u4ef7\u672a\u5339\u914d\u4ea7\u54c1\u3011\n\u8ba2\u5355 {orderNo}\uff08\u8f6c\u5355\u53f7 {transferNo}\uff09\uff0c\u5ba2\u6237 {customer}\uff0c\u4ea7\u54c1 {product}\uff0c\u56fd\u5bb6 {country}\uff0c\u8ba1\u8d39\u65f6\u95f4 {bizDate}\u3002\n\u4ea7\u54c1\u4ef7\u76ee\u5f55\u4e2d\u672a\u627e\u5230\u8be5\u4ea7\u54c1\uff0c\u8bf7\u68c0\u67e5\u4ea7\u54c1\u4ef7\u6863\u6848\u662f\u5426\u5df2\u7ef4\u62a4\u3002");
|
||||||
|
TEMPLATES.put(Integer.valueOf(24), "\u3010\u4ea7\u54c1\u4ef7\u672a\u5339\u914d\u56fd\u5bb6\u3011\n\u8ba2\u5355 {orderNo}\uff08\u8f6c\u5355\u53f7 {transferNo}\uff09\uff0c\u4ea7\u54c1 {product}\uff0c\u76ee\u7684\u56fd\u5bb6 {country}\uff0c\u90ae\u7f16 {postcode}\uff0c\u8ba1\u8d39\u65f6\u95f4 {bizDate}\u3002\n\u4ea7\u54c1\u4ef7\u5df2\u547d\u4e2d\u4ea7\u54c1\uff0c\u4f46\u672a\u547d\u4e2d\u56fd\u5bb6/\u5206\u533a\uff0c\u8bf7\u8865\u9f50\u4ea7\u54c1\u4ef7\u56fd\u5bb6\u4ef7\u683c\u3002");
|
||||||
|
TEMPLATES.put(Integer.valueOf(25), "\u3010\u4ea7\u54c1\u4ef7\u672a\u5339\u914d\u91cd\u91cf\u6bb5\u3011\n\u8ba2\u5355 {orderNo}\uff08\u8f6c\u5355\u53f7 {transferNo}\uff09\uff0c\u4ea7\u54c1 {product}\uff0c\u56fd\u5bb6 {country}\uff0c\u5206\u533a {zone}\uff0c\u8ba1\u8d39\u91cd {chargeWeight} kg\uff0c\u8ba1\u8d39\u65f6\u95f4 {bizDate}\u3002\n\u4ea7\u54c1\u4ef7\u5df2\u547d\u4e2d\u4ea7\u54c1\u4e0e\u56fd\u5bb6\uff0c\u4f46\u8ba1\u8d39\u91cd\u672a\u843d\u5728\u91cd\u91cf\u6bb5\u5185\uff0c\u8bf7\u68c0\u67e5\u4ea7\u54c1\u4ef7\u91cd\u91cf\u6bb5\u3002");
|
||||||
|
TEMPLATES.put(Integer.valueOf(4), "\u3010\u672a\u7ed1\u5b9a\u5957\u9910\u3011\n\u8ba2\u5355 {orderNo}\uff08\u8f6c\u5355\u53f7 {transferNo}\uff09\uff0c\u5ba2\u6237 {customer}\uff0c\u8ba1\u8d39\u65f6\u95f4 {bizDate}\u3002\n\u8be5\u5ba2\u6237\u672a\u7ed1\u5b9a\u9500\u552e\u4ef7\u5957\u9910\uff0c\u65e0\u6cd5\u6309\u5957\u9910\u53d6\u4ef7\uff0c\u8bf7\u5148\u5728\u5ba2\u6237/\u5957\u9910\u7ed1\u5b9a\u540e\u518d\u8ba1\u8d39\u3002");
|
||||||
|
TEMPLATES.put(Integer.valueOf(5), "\u3010\u5957\u9910\u672a\u542f\u7528/\u65e0\u751f\u6548\u7248\u672c\u3011\n\u8ba2\u5355 {orderNo}\uff08\u8f6c\u5355\u53f7 {transferNo}\uff09\uff0c\u5ba2\u6237 {customer}\uff0c\u5957\u9910\u300c{priceSet}\u300d\uff0c\u8ba1\u8d39\u65f6\u95f4 {bizDate}\u3002\n\u8ba1\u8d39\u65e5\u6ca1\u6709\u53ef\u7528\u7684\u5957\u9910\u751f\u6548\u7248\u672c\uff0c\u8bf7\u68c0\u67e5\u5957\u9910\u542f\u7528\u72b6\u6001\u4e0e\u7248\u672c\u751f\u6548\u671f\u3002");
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String buildDetail(OrderBillFailReasonVo vo, String fallback)
|
||||||
|
{
|
||||||
|
if (vo == null)
|
||||||
|
{
|
||||||
|
return fallback;
|
||||||
|
}
|
||||||
|
Integer status = vo.getBillingFailStatus();
|
||||||
|
String tpl = status == null ? null : TEMPLATES.get(status);
|
||||||
|
if (StringUtils.isEmpty(tpl))
|
||||||
|
{
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
sb.append("\u3010").append(nz(vo.getBillingFailStatusLabel(), "\u8ba1\u8d39\u5931\u8d25")).append("\u3011\n");
|
||||||
|
sb.append("\u8ba2\u5355 ").append(nz(vo.getOrderNo(), "-"));
|
||||||
|
sb.append("\uff08\u8f6c\u5355\u53f7 ").append(nz(vo.getTransferNo(), "-")).append("\uff09");
|
||||||
|
sb.append("\uff0c\u5ba2\u6237 ").append(joinCodeName(vo.getCustomerCode(), vo.getCustomerName()));
|
||||||
|
sb.append("\uff0c\u4ea7\u54c1 ").append(joinCodeName(vo.getProductCode(), vo.getProductName()));
|
||||||
|
sb.append("\uff0c\u56fd\u5bb6 ").append(joinCodeName(vo.getCountryCode(), vo.getCountryName()));
|
||||||
|
sb.append("\uff0c\u8ba1\u8d39\u65f6\u95f4 ").append(fmtDate(vo.getBizDate())).append("\u3002\n");
|
||||||
|
sb.append(nz(fallback, nz(vo.getErrorMessage(), vo.getBillingFailStatusLabel())));
|
||||||
|
return sb.toString();
|
||||||
|
}
|
||||||
|
Map<String, String> ctx = new HashMap<String, String>();
|
||||||
|
ctx.put("orderNo", nz(vo.getOrderNo(), "-"));
|
||||||
|
ctx.put("transferNo", nz(vo.getTransferNo(), "-"));
|
||||||
|
ctx.put("trackingNo", nz(vo.getTrackingNo(), "-"));
|
||||||
|
ctx.put("customer", joinCodeName(vo.getCustomerCode(), vo.getCustomerName()));
|
||||||
|
ctx.put("product", joinCodeName(vo.getProductCode(), vo.getProductName()));
|
||||||
|
ctx.put("country", joinCodeName(vo.getCountryCode(), vo.getCountryName()));
|
||||||
|
ctx.put("zone", joinCodeName(vo.getZoneCode(), vo.getZoneName()));
|
||||||
|
ctx.put("postcode", nz(vo.getDestPostcode(), "-"));
|
||||||
|
ctx.put("priceSet", joinCodeName(vo.getPriceSetCode(), vo.getPriceSetName()));
|
||||||
|
ctx.put("version", nz(vo.getVersionNo(), "-"));
|
||||||
|
ctx.put("chargeWeight", fmtNum(vo.getChargeWeight()));
|
||||||
|
ctx.put("bizDate", fmtDate(vo.getBizDate()));
|
||||||
|
ctx.put("pickupDate", fmtDate(vo.getPickupDate()));
|
||||||
|
String out = tpl;
|
||||||
|
for (Map.Entry<String, String> e : ctx.entrySet())
|
||||||
|
{
|
||||||
|
out = out.replace("{" + e.getKey() + "}", e.getValue());
|
||||||
|
}
|
||||||
|
if (StringUtils.isNotEmpty(fallback) && !fallback.equals(vo.getBillingFailStatusLabel()))
|
||||||
|
{
|
||||||
|
out = out + "\n\u8be6\u60c5\uff1a" + fallback;
|
||||||
|
}
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String joinCodeName(String code, String name)
|
||||||
|
{
|
||||||
|
if (StringUtils.isEmpty(code) && StringUtils.isEmpty(name))
|
||||||
|
{
|
||||||
|
return "-";
|
||||||
|
}
|
||||||
|
if (StringUtils.isEmpty(code))
|
||||||
|
{
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
if (StringUtils.isEmpty(name) || name.equals(code))
|
||||||
|
{
|
||||||
|
return code;
|
||||||
|
}
|
||||||
|
return code + "/" + name;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String fmtDate(Date d)
|
||||||
|
{
|
||||||
|
if (d == null)
|
||||||
|
{
|
||||||
|
return "-";
|
||||||
|
}
|
||||||
|
return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(d);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String fmtNum(BigDecimal n)
|
||||||
|
{
|
||||||
|
return n == null ? "-" : n.stripTrailingZeros().toPlainString();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String nz(String v, String def)
|
||||||
|
{
|
||||||
|
return StringUtils.isEmpty(v) ? def : v;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -65,6 +65,15 @@ export function listOrderBill(query) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Order-list: billing fail reason popup */
|
||||||
|
export function getOrderBillFailReason(billId) {
|
||||||
|
return request({
|
||||||
|
url: '/price/billing/orderBill/' + billId + '/failReason',
|
||||||
|
method: 'get'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/** Order-bill product check: package sales products missing from catalog */
|
/** Order-bill product check: package sales products missing from catalog */
|
||||||
export function checkOrderBillProducts(data) {
|
export function checkOrderBillProducts(data) {
|
||||||
return request({
|
return request({
|
||||||
|
|||||||
@@ -106,9 +106,6 @@
|
|||||||
<template #col-chargeWeight="{ row }">
|
<template #col-chargeWeight="{ row }">
|
||||||
{{ formatWeight(row.chargeWeight) }}
|
{{ formatWeight(row.chargeWeight) }}
|
||||||
</template>
|
</template>
|
||||||
<template #col-matchSource="{ row }">
|
|
||||||
<el-tag size="small" :type="sourceTagType(row.matchSource)">{{ sourceLabel(row.matchSource) }}</el-tag>
|
|
||||||
</template>
|
|
||||||
<template #col-orderStatus="{ row }">
|
<template #col-orderStatus="{ row }">
|
||||||
{{ orderStatusLabel(row.orderStatus) }}
|
{{ orderStatusLabel(row.orderStatus) }}
|
||||||
</template>
|
</template>
|
||||||
@@ -565,7 +562,6 @@ const columns = [
|
|||||||
{ label: '收货重', prop: 'receiveWeight', align: 'center', width: 90, slot: 'chargeWeight' },
|
{ label: '收货重', prop: 'receiveWeight', align: 'center', width: 90, slot: 'chargeWeight' },
|
||||||
{ label: '应收总额', prop: 'incomeTotal', align: 'right', width: 120, slot: 'incomeTotal' },
|
{ label: '应收总额', prop: 'incomeTotal', align: 'right', width: 120, slot: 'incomeTotal' },
|
||||||
{ label: '应付总额', prop: 'payTotal', align: 'right', width: 120, slot: 'payTotal' },
|
{ label: '应付总额', prop: 'payTotal', align: 'right', width: 120, slot: 'payTotal' },
|
||||||
{ label: '计价来源', prop: 'matchSource', align: 'center', width: 130, slot: 'matchSource' },
|
|
||||||
{ label: '订单状态', prop: 'orderStatus', align: 'center', width: 110, slot: 'orderStatus' },
|
{ label: '订单状态', prop: 'orderStatus', align: 'center', width: 110, slot: 'orderStatus' },
|
||||||
{ label: '计费状态', prop: 'billingFailStatus', align: 'center', width: 120, slot: 'billingFailStatus' },
|
{ label: '计费状态', prop: 'billingFailStatus', align: 'center', width: 120, slot: 'billingFailStatus' },
|
||||||
{ label: '客户状态', prop: 'customerActiveStatus', align: 'center', width: 100, slot: 'customerActiveStatus' },
|
{ label: '客户状态', prop: 'customerActiveStatus', align: 'center', width: 100, slot: 'customerActiveStatus' },
|
||||||
@@ -643,19 +639,6 @@ const searchColumns = [
|
|||||||
defaultTime: [new Date(2000, 0, 1, 0, 0, 0), new Date(2000, 0, 1, 23, 59, 59)]
|
defaultTime: [new Date(2000, 0, 1, 0, 0, 0), new Date(2000, 0, 1, 23, 59, 59)]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
|
||||||
label: '\u8ba1\u8d39\u5931\u8d25',
|
|
||||||
prop: 'billingFailStatuses',
|
|
||||||
component: 'select',
|
|
||||||
options: billingFailStatusOptions,
|
|
||||||
placeholder: '\u8bf7\u9009\u62e9',
|
|
||||||
props: {
|
|
||||||
multiple: true,
|
|
||||||
clearable: true,
|
|
||||||
collapseTags: true,
|
|
||||||
collapseTagsTooltip: true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
]
|
||||||
|
|
||||||
function buildBillQuery(params) {
|
function buildBillQuery(params) {
|
||||||
|
|||||||
@@ -186,7 +186,13 @@
|
|||||||
{{ orderStatusLabel(row.orderStatus) }}
|
{{ orderStatusLabel(row.orderStatus) }}
|
||||||
</template>
|
</template>
|
||||||
<template #col-billingFailStatus="{ row }">
|
<template #col-billingFailStatus="{ row }">
|
||||||
<el-tag size="small" :type="billingFailTagType(row.billingFailStatus)">{{ billingFailLabel(row.billingFailStatus) }}</el-tag>
|
<el-tag
|
||||||
|
size="small"
|
||||||
|
:type="billingFailTagType(row.billingFailStatus)"
|
||||||
|
class="billing-fail-tag"
|
||||||
|
:class="{ 'is-clickable': Number(row.billingFailStatus) !== 0 }"
|
||||||
|
@click="openFailReason(row)"
|
||||||
|
>{{ billingFailLabel(row.billingFailStatus) }}</el-tag>
|
||||||
</template>
|
</template>
|
||||||
</basic-table>
|
</basic-table>
|
||||||
<el-dialog
|
<el-dialog
|
||||||
@@ -294,12 +300,92 @@
|
|||||||
:fields="ORDER_BILL_EXPORT_FIELDS"
|
:fields="ORDER_BILL_EXPORT_FIELDS"
|
||||||
storage-key="exportFields:orderBill"
|
storage-key="exportFields:orderBill"
|
||||||
/>
|
/>
|
||||||
|
<el-dialog
|
||||||
|
v-model="failReasonVisible"
|
||||||
|
title="计费失败详情"
|
||||||
|
width="780px"
|
||||||
|
append-to-body
|
||||||
|
destroy-on-close
|
||||||
|
class="fail-reason-dialog"
|
||||||
|
>
|
||||||
|
<div v-loading="failReasonLoading" class="fail-reason-body">
|
||||||
|
<div v-if="failReason.failReasonDetail || failReason.errorMessage" class="fail-reason-banner">
|
||||||
|
<div class="fail-reason-banner__badge">{{ failReason.billingFailStatusLabel || billingFailLabel(failReason.billingFailStatus) }}</div>
|
||||||
|
<div class="fail-reason-text">{{ failReason.failReasonDetail || failReason.errorMessage }}</div>
|
||||||
|
</div>
|
||||||
|
<el-descriptions :column="2" border size="small" class="fail-reason-desc">
|
||||||
|
<el-descriptions-item label="订单号">
|
||||||
|
<span class="fr-val">{{ failReason.orderNo || '-' }}</span>
|
||||||
|
</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="转单号">
|
||||||
|
<span class="fr-val">{{ failReason.transferNo || '-' }}</span>
|
||||||
|
</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="运单号">
|
||||||
|
<span class="fr-val">{{ failReason.trackingNo || '-' }}</span>
|
||||||
|
</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="计费状态">
|
||||||
|
<el-tag size="small" type="danger" effect="dark">{{ failReason.billingFailStatusLabel || billingFailLabel(failReason.billingFailStatus) }}</el-tag>
|
||||||
|
</el-descriptions-item>
|
||||||
|
<el-descriptions-item label-class-name="fr-label-key" class-name="fr-cell-key" label="客户">
|
||||||
|
<span :class="frValueClass(joinCodeName(failReason.customerCode, failReason.customerName), true)">{{ joinCodeName(failReason.customerCode, failReason.customerName) }}</span>
|
||||||
|
</el-descriptions-item>
|
||||||
|
<el-descriptions-item label-class-name="fr-label-key" class-name="fr-cell-key" label="产品">
|
||||||
|
<span :class="frValueClass(joinCodeName(failReason.productCode, failReason.productName), true)">{{ joinCodeName(failReason.productCode, failReason.productName) }}</span>
|
||||||
|
</el-descriptions-item>
|
||||||
|
<el-descriptions-item label-class-name="fr-label-key" class-name="fr-cell-key" label="国家">
|
||||||
|
<span :class="frValueClass(joinCodeName(failReason.countryCode, failReason.countryName), true)">{{ joinCodeName(failReason.countryCode, failReason.countryName) }}</span>
|
||||||
|
</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="分区">
|
||||||
|
<span :class="frValueClass(joinCodeName(failReason.zoneCode, failReason.zoneName))">{{ joinCodeName(failReason.zoneCode, failReason.zoneName) }}</span>
|
||||||
|
</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="收件人邮编">
|
||||||
|
<span :class="frValueClass(failReason.destPostcode || '-')">{{ failReason.destPostcode || '-' }}</span>
|
||||||
|
</el-descriptions-item>
|
||||||
|
<el-descriptions-item label-class-name="fr-label-key" class-name="fr-cell-key" label="套餐">
|
||||||
|
<span :class="frValueClass(joinCodeName(failReason.priceSetCode, failReason.priceSetName), true)">{{ joinCodeName(failReason.priceSetCode, failReason.priceSetName) }}</span>
|
||||||
|
</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="套餐版本">
|
||||||
|
<span :class="frValueClass(failReason.versionNo || '-')">{{ failReason.versionNo || '-' }}</span>
|
||||||
|
</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="重量段">
|
||||||
|
<span :class="frValueClass(failReason.weightLabel || formatWeightRange(failReason.weightMin, failReason.weightMax))">{{ failReason.weightLabel || formatWeightRange(failReason.weightMin, failReason.weightMax) }}</span>
|
||||||
|
</el-descriptions-item>
|
||||||
|
<el-descriptions-item label-class-name="fr-label-key" class-name="fr-cell-key" label="计费重">
|
||||||
|
<span :class="frValueClass(formatWeight(failReason.chargeWeight), true)">{{ formatWeight(failReason.chargeWeight) }}</span>
|
||||||
|
</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="原计费重">
|
||||||
|
<span class="fr-val">{{ formatWeight(failReason.weight) }}</span>
|
||||||
|
</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="单价">
|
||||||
|
<span class="fr-val fr-val-money">{{ formatMoney(failReason.freightRate, failReason.currency) }}</span>
|
||||||
|
</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="运费金额">
|
||||||
|
<span class="fr-val fr-val-money">{{ formatMoney(failReason.freightAmount, failReason.currency) }}</span>
|
||||||
|
</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="应收总额">
|
||||||
|
<span class="fr-val fr-val-money">{{ formatMoney(failReason.incomeTotal, failReason.currency) }}</span>
|
||||||
|
</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="计费时间">
|
||||||
|
<span class="fr-val">{{ formatDateTime(failReason.bizDate) }}</span>
|
||||||
|
</el-descriptions-item>
|
||||||
|
<el-descriptions-item label-class-name="fr-label-key" class-name="fr-cell-key" label="收货时间">
|
||||||
|
<span :class="frValueClass(formatDateTime(failReason.pickupDate), true)">{{ formatDateTime(failReason.pickupDate) }}</span>
|
||||||
|
</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="原始失败信息" :span="2">
|
||||||
|
<span class="fr-val fr-val-raw">{{ failReason.errorMessage || '-' }}</span>
|
||||||
|
</el-descriptions-item>
|
||||||
|
</el-descriptions>
|
||||||
|
</div>
|
||||||
|
<template #footer>
|
||||||
|
<el-button type="primary" @click="failReasonVisible = false">关闭</el-button>
|
||||||
|
</template>
|
||||||
|
</el-dialog>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup name="OrderBillQuery">
|
<script setup name="OrderBillQuery">
|
||||||
import { ElMessage, ElMessageBox } from 'element-plus'
|
import { ElMessage, ElMessageBox } from 'element-plus'
|
||||||
import { listOrderBill, localRebillAsync, pollLocalRebillTask, cancelLocalRebill, getLocalRebillTask } from '@/api/price/billing'
|
import { listOrderBill, localRebillAsync, pollLocalRebillTask, cancelLocalRebill, getLocalRebillTask, getOrderBillFailReason } from '@/api/price/billing'
|
||||||
import { exportAsyncFromTable } from '@/utils/excelExport'
|
import { exportAsyncFromTable } from '@/utils/excelExport'
|
||||||
import ExcelExportFieldDialog from '@/components/ExcelExportFieldDialog/index.vue'
|
import ExcelExportFieldDialog from '@/components/ExcelExportFieldDialog/index.vue'
|
||||||
import { ORDER_BILL_EXPORT_FIELDS } from '@/utils/exportFieldDefs'
|
import { ORDER_BILL_EXPORT_FIELDS } from '@/utils/exportFieldDefs'
|
||||||
@@ -1068,6 +1154,133 @@ function orderStatusLabel(status) {
|
|||||||
return String(status)
|
return String(status)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const failReasonVisible = ref(false)
|
||||||
|
const failReasonLoading = ref(false)
|
||||||
|
const failReason = reactive({
|
||||||
|
billId: '',
|
||||||
|
orderNo: '',
|
||||||
|
transferNo: '',
|
||||||
|
trackingNo: '',
|
||||||
|
customerCode: '',
|
||||||
|
customerName: '',
|
||||||
|
productCode: '',
|
||||||
|
productName: '',
|
||||||
|
countryCode: '',
|
||||||
|
countryName: '',
|
||||||
|
zoneCode: '',
|
||||||
|
zoneName: '',
|
||||||
|
destPostcode: '',
|
||||||
|
priceSetCode: '',
|
||||||
|
priceSetName: '',
|
||||||
|
versionNo: '',
|
||||||
|
weightLabel: '',
|
||||||
|
weightMin: null,
|
||||||
|
weightMax: null,
|
||||||
|
chargeWeight: null,
|
||||||
|
weight: null,
|
||||||
|
freightRate: null,
|
||||||
|
freightAmount: null,
|
||||||
|
incomeTotal: null,
|
||||||
|
currency: '',
|
||||||
|
bizDate: null,
|
||||||
|
pickupDate: null,
|
||||||
|
billingFailStatus: null,
|
||||||
|
billingFailStatusLabel: '',
|
||||||
|
errorMessage: '',
|
||||||
|
failReasonDetail: ''
|
||||||
|
})
|
||||||
|
|
||||||
|
function joinCodeName(code, name) {
|
||||||
|
if (!code && !name) return '-'
|
||||||
|
if (!code) return name
|
||||||
|
if (!name || name === code) return code
|
||||||
|
return code + ' / ' + name
|
||||||
|
}
|
||||||
|
|
||||||
|
function frValueClass(text, keyField) {
|
||||||
|
const empty = text == null || text === '' || text === '-'
|
||||||
|
if (empty) return 'fr-val fr-val-empty'
|
||||||
|
return keyField ? 'fr-val fr-val-key' : 'fr-val'
|
||||||
|
}
|
||||||
|
|
||||||
|
function formatWeightRange(min, max) {
|
||||||
|
if (min == null && max == null) return '-'
|
||||||
|
return (min == null ? '-' : formatWeight(min)) + ' ~ ' + (max == null ? '-' : formatWeight(max))
|
||||||
|
}
|
||||||
|
|
||||||
|
function formatMoney(val, currency) {
|
||||||
|
if (val == null || val === '') return '-'
|
||||||
|
const num = Number(val)
|
||||||
|
if (Number.isNaN(num)) return String(val)
|
||||||
|
return (currency ? (currency + ' ') : '') + num.toFixed(4)
|
||||||
|
}
|
||||||
|
|
||||||
|
function formatDateTime(val) {
|
||||||
|
if (!val) return '-'
|
||||||
|
const d = new Date(val)
|
||||||
|
if (Number.isNaN(d.getTime())) return String(val)
|
||||||
|
const pad = (n) => String(n).padStart(2, '0')
|
||||||
|
return d.getFullYear() + '-' + pad(d.getMonth() + 1) + '-' + pad(d.getDate()) +
|
||||||
|
' ' + pad(d.getHours()) + ':' + pad(d.getMinutes()) + ':' + pad(d.getSeconds())
|
||||||
|
}
|
||||||
|
|
||||||
|
function applyFailReason(data, row) {
|
||||||
|
const src = data || {}
|
||||||
|
const base = row || {}
|
||||||
|
failReason.billId = src.billId || base.billId || ''
|
||||||
|
failReason.orderNo = src.orderNo || base.orderNo || ''
|
||||||
|
failReason.transferNo = src.transferNo || base.transferNo || ''
|
||||||
|
failReason.trackingNo = src.trackingNo || base.trackingNo || ''
|
||||||
|
failReason.customerCode = src.customerCode || base.customerCode || ''
|
||||||
|
failReason.customerName = src.customerName || base.customerName || ''
|
||||||
|
failReason.productCode = src.productCode || base.productCode || ''
|
||||||
|
failReason.productName = src.productName || base.productName || ''
|
||||||
|
failReason.countryCode = src.countryCode || base.countryCode || ''
|
||||||
|
failReason.countryName = src.countryName || base.countryName || ''
|
||||||
|
failReason.zoneCode = src.zoneCode || ''
|
||||||
|
failReason.zoneName = src.zoneName || ''
|
||||||
|
failReason.destPostcode = src.destPostcode || base.destPostcode || ''
|
||||||
|
failReason.priceSetCode = src.priceSetCode || base.priceSetCode || ''
|
||||||
|
failReason.priceSetName = src.priceSetName || base.priceSetName || ''
|
||||||
|
failReason.versionNo = src.versionNo || ''
|
||||||
|
failReason.weightLabel = src.weightLabel || base.weightLabel || ''
|
||||||
|
failReason.weightMin = src.weightMin != null ? src.weightMin : base.weightMin
|
||||||
|
failReason.weightMax = src.weightMax != null ? src.weightMax : base.weightMax
|
||||||
|
failReason.chargeWeight = src.chargeWeight != null ? src.chargeWeight : base.chargeWeight
|
||||||
|
failReason.weight = src.weight != null ? src.weight : base.weight
|
||||||
|
failReason.freightRate = src.freightRate != null ? src.freightRate : base.freightRate
|
||||||
|
failReason.freightAmount = src.freightAmount != null ? src.freightAmount : base.freightAmount
|
||||||
|
failReason.incomeTotal = src.incomeTotal != null ? src.incomeTotal : base.incomeTotal
|
||||||
|
failReason.currency = src.currency || base.currency || ''
|
||||||
|
failReason.bizDate = src.bizDate || base.bizDate || null
|
||||||
|
failReason.pickupDate = src.pickupDate || base.pickupDate || null
|
||||||
|
failReason.billingFailStatus = src.billingFailStatus != null ? src.billingFailStatus : base.billingFailStatus
|
||||||
|
failReason.billingFailStatusLabel = src.billingFailStatusLabel || billingFailLabel(failReason.billingFailStatus)
|
||||||
|
failReason.errorMessage = src.errorMessage || ''
|
||||||
|
failReason.failReasonDetail = src.failReasonDetail || src.errorMessage || billingFailLabel(failReason.billingFailStatus)
|
||||||
|
}
|
||||||
|
|
||||||
|
async function openFailReason(row) {
|
||||||
|
if (!row || !row.billId) return
|
||||||
|
const code = row.billingFailStatus == null ? 0 : Number(row.billingFailStatus)
|
||||||
|
if (code === 0) return
|
||||||
|
failReasonVisible.value = true
|
||||||
|
failReasonLoading.value = true
|
||||||
|
applyFailReason({}, row)
|
||||||
|
failReason.errorMessage = ''
|
||||||
|
failReason.failReasonDetail = ''
|
||||||
|
try {
|
||||||
|
const res = await getOrderBillFailReason(row.billId)
|
||||||
|
applyFailReason((res && res.data) || {}, row)
|
||||||
|
} catch (e) {
|
||||||
|
failReason.errorMessage = (e && e.message) || '查询失败原因失败'
|
||||||
|
failReason.failReasonDetail = failReason.errorMessage
|
||||||
|
} finally {
|
||||||
|
failReasonLoading.value = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function billingFailLabel(status) {
|
function billingFailLabel(status) {
|
||||||
const code = status == null ? 0 : Number(status)
|
const code = status == null ? 0 : Number(status)
|
||||||
const hit = billingFailStatusOptions.find(item => item.value === code)
|
const hit = billingFailStatusOptions.find(item => item.value === code)
|
||||||
@@ -1222,4 +1435,74 @@ onBeforeUnmount(() => {
|
|||||||
color: var(--el-text-color-secondary);
|
color: var(--el-text-color-secondary);
|
||||||
font-size: 11px;
|
font-size: 11px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.billing-fail-tag.is-clickable {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
.fail-reason-body {
|
||||||
|
min-height: 180px;
|
||||||
|
}
|
||||||
|
.fail-reason-banner {
|
||||||
|
margin-bottom: 14px;
|
||||||
|
padding: 12px 14px;
|
||||||
|
border-radius: 8px;
|
||||||
|
border: 1px solid #f3a5a5;
|
||||||
|
background: linear-gradient(180deg, #fff5f5 0%, #ffecec 100%);
|
||||||
|
}
|
||||||
|
.fail-reason-banner__badge {
|
||||||
|
display: inline-block;
|
||||||
|
margin-bottom: 8px;
|
||||||
|
padding: 2px 10px;
|
||||||
|
border-radius: 999px;
|
||||||
|
font-size: 12px;
|
||||||
|
font-weight: 600;
|
||||||
|
color: #fff;
|
||||||
|
background: #e11d48;
|
||||||
|
}
|
||||||
|
.fail-reason-text {
|
||||||
|
white-space: pre-wrap;
|
||||||
|
word-break: break-word;
|
||||||
|
line-height: 1.65;
|
||||||
|
font-size: 13px;
|
||||||
|
color: #9f1239;
|
||||||
|
}
|
||||||
|
.fail-reason-desc {
|
||||||
|
margin-top: 4px;
|
||||||
|
}
|
||||||
|
.fail-reason-desc :deep(.el-descriptions__label) {
|
||||||
|
width: 110px;
|
||||||
|
color: #64748b;
|
||||||
|
background: #f8fafc;
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
.fail-reason-desc :deep(.fr-label-key) {
|
||||||
|
color: #9a3412;
|
||||||
|
background: #fff7ed;
|
||||||
|
font-weight: 700;
|
||||||
|
}
|
||||||
|
.fail-reason-desc :deep(.fr-cell-key) {
|
||||||
|
background: #fffbeb;
|
||||||
|
}
|
||||||
|
.fr-val {
|
||||||
|
color: #0f172a;
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
.fr-val-key {
|
||||||
|
color: #c2410c;
|
||||||
|
font-weight: 700;
|
||||||
|
}
|
||||||
|
.fr-val-empty {
|
||||||
|
color: #dc2626;
|
||||||
|
font-weight: 700;
|
||||||
|
background: #fee2e2;
|
||||||
|
padding: 1px 8px;
|
||||||
|
border-radius: 4px;
|
||||||
|
}
|
||||||
|
.fr-val-money {
|
||||||
|
color: #b91c1c;
|
||||||
|
font-variant-numeric: tabular-nums;
|
||||||
|
}
|
||||||
|
.fr-val-raw {
|
||||||
|
color: #7f1d1d;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
Reference in New Issue
Block a user