提交第三方接口订单同步功能
This commit is contained in:
+35
@@ -2,10 +2,13 @@ package com.ruoyi.web.controller.api;
|
|||||||
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.validation.annotation.Validated;
|
import org.springframework.validation.annotation.Validated;
|
||||||
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
|
import org.springframework.web.bind.annotation.PathVariable;
|
||||||
import org.springframework.web.bind.annotation.PostMapping;
|
import org.springframework.web.bind.annotation.PostMapping;
|
||||||
import org.springframework.web.bind.annotation.RequestBody;
|
import org.springframework.web.bind.annotation.RequestBody;
|
||||||
import org.springframework.web.bind.annotation.RequestHeader;
|
import org.springframework.web.bind.annotation.RequestHeader;
|
||||||
import org.springframework.web.bind.annotation.RequestMapping;
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RequestParam;
|
||||||
import org.springframework.web.bind.annotation.RestController;
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
import com.ruoyi.common.annotation.Anonymous;
|
import com.ruoyi.common.annotation.Anonymous;
|
||||||
import com.ruoyi.common.core.controller.BaseController;
|
import com.ruoyi.common.core.controller.BaseController;
|
||||||
@@ -13,8 +16,10 @@ import com.ruoyi.common.core.domain.AjaxResult;
|
|||||||
import com.ruoyi.common.exception.ServiceException;
|
import com.ruoyi.common.exception.ServiceException;
|
||||||
import com.ruoyi.common.utils.StringUtils;
|
import com.ruoyi.common.utils.StringUtils;
|
||||||
import com.ruoyi.framework.config.properties.TmsApiProperties;
|
import com.ruoyi.framework.config.properties.TmsApiProperties;
|
||||||
|
import com.ruoyi.price.domain.vo.TmsPriceBillRequest;
|
||||||
import com.ruoyi.price.domain.vo.TmsPriceQuoteRequest;
|
import com.ruoyi.price.domain.vo.TmsPriceQuoteRequest;
|
||||||
import com.ruoyi.price.domain.vo.TmsPriceQuoteResult;
|
import com.ruoyi.price.domain.vo.TmsPriceQuoteResult;
|
||||||
|
import com.ruoyi.price.service.IPrcBillService;
|
||||||
import com.ruoyi.price.service.ITmsPriceQuoteService;
|
import com.ruoyi.price.service.ITmsPriceQuoteService;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -35,6 +40,9 @@ public class TmsPriceController extends BaseController
|
|||||||
@Autowired
|
@Autowired
|
||||||
private ITmsPriceQuoteService tmsPriceQuoteService;
|
private ITmsPriceQuoteService tmsPriceQuoteService;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private IPrcBillService prcBillService;
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private TmsApiProperties tmsApiProperties;
|
private TmsApiProperties tmsApiProperties;
|
||||||
|
|
||||||
@@ -52,6 +60,33 @@ public class TmsPriceController extends BaseController
|
|||||||
return success(result);
|
return success(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sync order and persist receivable bill (prc_bill / prc_bill_fee).
|
||||||
|
* Same price match as quote. Same orderNo upserts.
|
||||||
|
*/
|
||||||
|
@PostMapping("/bill")
|
||||||
|
public AjaxResult bill(
|
||||||
|
@RequestHeader(value = HEADER_API_CODE, required = false) String headerApiCode,
|
||||||
|
@Validated @RequestBody TmsPriceBillRequest request)
|
||||||
|
{
|
||||||
|
assertApiCode(headerApiCode, request == null ? null : request.getApiCode());
|
||||||
|
TmsPriceQuoteResult result = prcBillService.bill(request);
|
||||||
|
return success(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Query receivable bill by orderNo after sync.
|
||||||
|
*/
|
||||||
|
@GetMapping("/bill/by-order/{orderNo}")
|
||||||
|
public AjaxResult getBillByOrder(
|
||||||
|
@RequestHeader(value = HEADER_API_CODE, required = false) String headerApiCode,
|
||||||
|
@PathVariable("orderNo") String orderNo,
|
||||||
|
@RequestParam(value = "apiCode", required = false) String apiCode)
|
||||||
|
{
|
||||||
|
assertApiCode(headerApiCode, apiCode);
|
||||||
|
return success(prcBillService.getBillByOrderNo(orderNo));
|
||||||
|
}
|
||||||
|
|
||||||
private void assertApiCode(String headerApiCode, String bodyApiCode)
|
private void assertApiCode(String headerApiCode, String bodyApiCode)
|
||||||
{
|
{
|
||||||
String expected = tmsApiProperties.getApiCode();
|
String expected = tmsApiProperties.getApiCode();
|
||||||
|
|||||||
+30
@@ -13,9 +13,12 @@ import org.springframework.web.bind.annotation.RestController;
|
|||||||
import com.ruoyi.common.core.controller.BaseController;
|
import com.ruoyi.common.core.controller.BaseController;
|
||||||
import com.ruoyi.common.core.domain.AjaxResult;
|
import com.ruoyi.common.core.domain.AjaxResult;
|
||||||
import com.ruoyi.common.core.page.TableDataInfo;
|
import com.ruoyi.common.core.page.TableDataInfo;
|
||||||
|
import com.ruoyi.price.domain.PrcBill;
|
||||||
import com.ruoyi.price.domain.PrcQuote;
|
import com.ruoyi.price.domain.PrcQuote;
|
||||||
|
import com.ruoyi.price.domain.vo.TmsPriceBillRequest;
|
||||||
import com.ruoyi.price.domain.vo.TmsPriceQuoteRequest;
|
import com.ruoyi.price.domain.vo.TmsPriceQuoteRequest;
|
||||||
import com.ruoyi.price.domain.vo.TmsPriceQuoteResult;
|
import com.ruoyi.price.domain.vo.TmsPriceQuoteResult;
|
||||||
|
import com.ruoyi.price.service.IPrcBillService;
|
||||||
import com.ruoyi.price.service.ITmsPriceQuoteService;
|
import com.ruoyi.price.service.ITmsPriceQuoteService;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -30,6 +33,9 @@ public class BillingController extends BaseController
|
|||||||
@Autowired
|
@Autowired
|
||||||
private ITmsPriceQuoteService tmsPriceQuoteService;
|
private ITmsPriceQuoteService tmsPriceQuoteService;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private IPrcBillService prcBillService;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Historical quote list.
|
* Historical quote list.
|
||||||
*/
|
*/
|
||||||
@@ -62,4 +68,28 @@ public class BillingController extends BaseController
|
|||||||
TmsPriceQuoteResult result = tmsPriceQuoteService.quote(request);
|
TmsPriceQuoteResult result = tmsPriceQuoteService.quote(request);
|
||||||
return success(result);
|
return success(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@PreAuthorize("@ss.hasPermi('price:billing:bill')")
|
||||||
|
@GetMapping("/bill/list")
|
||||||
|
public TableDataInfo billList(PrcBill query)
|
||||||
|
{
|
||||||
|
startPage();
|
||||||
|
List<PrcBill> list = prcBillService.selectBillList(query);
|
||||||
|
return getDataTable(list);
|
||||||
|
}
|
||||||
|
|
||||||
|
@PreAuthorize("@ss.hasPermi('price:billing:bill')")
|
||||||
|
@GetMapping("/bill/{billId}")
|
||||||
|
public AjaxResult getBill(@PathVariable String billId)
|
||||||
|
{
|
||||||
|
return success(prcBillService.getBill(billId));
|
||||||
|
}
|
||||||
|
|
||||||
|
@PreAuthorize("@ss.hasPermi('price:billing:bill')")
|
||||||
|
@PostMapping("/bill")
|
||||||
|
public AjaxResult bill(@Validated @RequestBody TmsPriceBillRequest request)
|
||||||
|
{
|
||||||
|
TmsPriceQuoteResult result = prcBillService.bill(request);
|
||||||
|
return success(result);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -150,4 +150,4 @@ xss:
|
|||||||
bms:
|
bms:
|
||||||
tms:
|
tms:
|
||||||
# Agreed API identification code for TMS callers
|
# Agreed API identification code for TMS callers
|
||||||
api-code: BMS.TMS._Q2WnPXiXwGW2Dl-iSGNzLfrhUgQogNo
|
api-code: BMS.TMS.ZYaOvlQzpcfau8TUaCFfO3Hp8ieHIqGw
|
||||||
|
|||||||
@@ -77,6 +77,7 @@ price.set.customer.customerId.empty=客户ID不能为空
|
|||||||
price.set.customer.beginDate.empty=客户绑定生效日期不能为空
|
price.set.customer.beginDate.empty=客户绑定生效日期不能为空
|
||||||
price.set.customer.date.invalid=客户绑定生效日期不能晚于失效日期
|
price.set.customer.date.invalid=客户绑定生效日期不能晚于失效日期
|
||||||
price.set.customer.alreadyBound=该客户已绑定套餐,一个客户只能绑定一个套餐
|
price.set.customer.alreadyBound=该客户已绑定套餐,一个客户只能绑定一个套餐
|
||||||
|
price.set.customer.masterNotFound=客户主数据不存在
|
||||||
price.set.customer.priority.invalid=优先级必须大于等于 1
|
price.set.customer.priority.invalid=优先级必须大于等于 1
|
||||||
# 重量段 PrcWeight
|
# 重量段 PrcWeight
|
||||||
price.weight.range.empty=起始重量和结束重量不能为空
|
price.weight.range.empty=起始重量和结束重量不能为空
|
||||||
@@ -118,4 +119,9 @@ price.quote.quoteIdRequired=报价ID为空
|
|||||||
price.quote.hitCustomerFixedPackageDetail=命中客户套餐固定价格明细
|
price.quote.hitCustomerFixedPackageDetail=命中客户套餐固定价格明细
|
||||||
|
|
||||||
# ---- 状态自动刷新 ----
|
# ---- 状态自动刷新 ----
|
||||||
price.status.refresh.success=状态刷新完成:bms_product 更新 {0} 行,bms_product_country 更新 {1} 行
|
price.status.refresh.success=状态刷新完成:bms_product 更新 {0} 行,bms_product_country 更新 {1} 行
|
||||||
|
# receivable bill
|
||||||
|
price.bill.orderNoRequired=订单号为空
|
||||||
|
price.bill.billIdRequired=计费ID为空
|
||||||
|
price.bill.notFound=计费记录不存在
|
||||||
|
price.bill.bizDateRequired=业务日期为空
|
||||||
|
|||||||
+1
-1
@@ -15,7 +15,7 @@ public class TmsApiProperties
|
|||||||
/**
|
/**
|
||||||
* Agreed API identification code (header X-Api-Code or body apiCode).
|
* Agreed API identification code (header X-Api-Code or body apiCode).
|
||||||
*/
|
*/
|
||||||
private String apiCode = "BMS.TMS._Q2WnPXiXwGW2Dl-iSGNzLfrhUgQogNo";
|
private String apiCode = "BMS.TMS.ZYaOvlQzpcfau8TUaCFfO3Hp8ieHIqGw";
|
||||||
|
|
||||||
public String getApiCode()
|
public String getApiCode()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -0,0 +1,74 @@
|
|||||||
|
package com.ruoyi.price.domain;
|
||||||
|
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.List;
|
||||||
|
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||||
|
import com.ruoyi.common.core.domain.BaseEntity;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.EqualsAndHashCode;
|
||||||
|
|
||||||
|
/** receivable bill header prc_bill */
|
||||||
|
@Data
|
||||||
|
@EqualsAndHashCode(callSuper = true)
|
||||||
|
public class PrcBill extends BaseEntity
|
||||||
|
{
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
private String billId;
|
||||||
|
private String billKey;
|
||||||
|
private String orderNo;
|
||||||
|
private String trackingNo;
|
||||||
|
private Long customerId;
|
||||||
|
private String customerCode;
|
||||||
|
private String customerName;
|
||||||
|
private Integer pieces;
|
||||||
|
private BigDecimal actualWeight;
|
||||||
|
private BigDecimal volume;
|
||||||
|
private BigDecimal volumeWeight;
|
||||||
|
private BigDecimal pkgLength;
|
||||||
|
private BigDecimal pkgWidth;
|
||||||
|
private BigDecimal pkgHeight;
|
||||||
|
private String shipperName;
|
||||||
|
private String consigneeName;
|
||||||
|
private String destPostcode;
|
||||||
|
private String warehouseCode;
|
||||||
|
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||||
|
private Date orderTime;
|
||||||
|
private String orderRemark;
|
||||||
|
private String productCode;
|
||||||
|
private String productName;
|
||||||
|
private String countryCode;
|
||||||
|
private String countryName;
|
||||||
|
private BigDecimal weight;
|
||||||
|
@JsonFormat(pattern = "yyyy-MM-dd")
|
||||||
|
private Date bizDate;
|
||||||
|
private Long tmsId;
|
||||||
|
|
||||||
|
private String matchSource;
|
||||||
|
private String matchMessage;
|
||||||
|
private Long priceSetId;
|
||||||
|
private String priceSetCode;
|
||||||
|
private String priceSetName;
|
||||||
|
private String setType;
|
||||||
|
private Integer bindPriority;
|
||||||
|
private Long customerPricesetId;
|
||||||
|
private Long productCountryId;
|
||||||
|
private BigDecimal weightMin;
|
||||||
|
private BigDecimal weightMax;
|
||||||
|
private String weightLabel;
|
||||||
|
@JsonFormat(pattern = "yyyy-MM-dd")
|
||||||
|
private Date effectiveDate;
|
||||||
|
private BigDecimal chargeWeight;
|
||||||
|
private BigDecimal freightRate;
|
||||||
|
private BigDecimal baseFreightRate;
|
||||||
|
private BigDecimal discountPercent;
|
||||||
|
private BigDecimal registrationFee;
|
||||||
|
private BigDecimal freightAmount;
|
||||||
|
private BigDecimal surchargeAmount;
|
||||||
|
private BigDecimal payableTotal;
|
||||||
|
private String currency;
|
||||||
|
private String roundMode;
|
||||||
|
|
||||||
|
private List<PrcBillFee> fees;
|
||||||
|
}
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
package com.ruoyi.price.domain;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
import java.util.Date;
|
||||||
|
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
/** receivable bill fee detail prc_bill_fee */
|
||||||
|
@Data
|
||||||
|
public class PrcBillFee implements Serializable
|
||||||
|
{
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
private String feeId;
|
||||||
|
private String billId;
|
||||||
|
private String feeType;
|
||||||
|
private String feeName;
|
||||||
|
private Long scId;
|
||||||
|
private BigDecimal amount;
|
||||||
|
private String currency;
|
||||||
|
private String roundMode;
|
||||||
|
private String remark;
|
||||||
|
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||||
|
private Date createdAt;
|
||||||
|
}
|
||||||
+46
@@ -0,0 +1,46 @@
|
|||||||
|
package com.ruoyi.price.domain.vo;
|
||||||
|
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
import java.util.Date;
|
||||||
|
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||||
|
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||||
|
import jakarta.validation.constraints.AssertTrue;
|
||||||
|
import jakarta.validation.constraints.NotBlank;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.EqualsAndHashCode;
|
||||||
|
|
||||||
|
/** Sync order -> receivable bill. Quote fields plus order snapshot. */
|
||||||
|
@Data
|
||||||
|
@EqualsAndHashCode(callSuper = true)
|
||||||
|
public class TmsPriceBillRequest extends TmsPriceQuoteRequest
|
||||||
|
{
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
@NotBlank(message = "orderNo is required")
|
||||||
|
private String orderNo;
|
||||||
|
|
||||||
|
private String trackingNo;
|
||||||
|
private String customerName;
|
||||||
|
private Integer pieces;
|
||||||
|
private BigDecimal actualWeight;
|
||||||
|
private BigDecimal volume;
|
||||||
|
private BigDecimal volumeWeight;
|
||||||
|
private BigDecimal pkgLength;
|
||||||
|
private BigDecimal pkgWidth;
|
||||||
|
private BigDecimal pkgHeight;
|
||||||
|
private String shipperName;
|
||||||
|
private String consigneeName;
|
||||||
|
private String destPostcode;
|
||||||
|
private String warehouseCode;
|
||||||
|
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||||
|
private Date orderTime;
|
||||||
|
private String orderRemark;
|
||||||
|
|
||||||
|
@JsonIgnore
|
||||||
|
@AssertTrue(message = "bizDate is required")
|
||||||
|
public boolean isBizDatePresent()
|
||||||
|
{
|
||||||
|
String bizDate = getBizDate();
|
||||||
|
return bizDate != null && !bizDate.trim().isEmpty();
|
||||||
|
}
|
||||||
|
}
|
||||||
+19
-1
@@ -53,6 +53,24 @@ public class TmsPriceQuoteResult implements Serializable
|
|||||||
/** 费用明细:运费/挂号费各一行,附加费按具体名称各一行 */
|
/** 费用明细:运费/挂号费各一行,附加费按具体名称各一行 */
|
||||||
private List<TmsPriceQuoteFeeLine> feeDetails;
|
private List<TmsPriceQuoteFeeLine> feeDetails;
|
||||||
private String quoteId;
|
private String quoteId;
|
||||||
/** true=命中已落库试算 */
|
private String billId;
|
||||||
|
private String orderNo;
|
||||||
|
private String trackingNo;
|
||||||
|
private String customerCode;
|
||||||
|
private String customerName;
|
||||||
|
private Integer pieces;
|
||||||
|
private BigDecimal actualWeight;
|
||||||
|
private BigDecimal volume;
|
||||||
|
private BigDecimal volumeWeight;
|
||||||
|
private BigDecimal pkgLength;
|
||||||
|
private BigDecimal pkgWidth;
|
||||||
|
private BigDecimal pkgHeight;
|
||||||
|
private String shipperName;
|
||||||
|
private String consigneeName;
|
||||||
|
private String destPostcode;
|
||||||
|
private String warehouseCode;
|
||||||
|
private Date orderTime;
|
||||||
|
private String orderRemark;
|
||||||
|
/** true=hit stored quote */
|
||||||
private Boolean fromCache;
|
private Boolean fromCache;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,17 @@
|
|||||||
|
package com.ruoyi.price.mapper;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import org.apache.ibatis.annotations.Param;
|
||||||
|
import com.ruoyi.price.domain.PrcBillFee;
|
||||||
|
|
||||||
|
/** receivable bill fee detail mapper */
|
||||||
|
public interface PrcBillFeeMapper
|
||||||
|
{
|
||||||
|
public List<PrcBillFee> selectByBillId(String billId);
|
||||||
|
|
||||||
|
public int insertPrcBillFee(PrcBillFee fee);
|
||||||
|
|
||||||
|
public int insertBatch(@Param("list") List<PrcBillFee> fees);
|
||||||
|
|
||||||
|
public int deleteByBillId(String billId);
|
||||||
|
}
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
package com.ruoyi.price.mapper;
|
||||||
|
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
import java.util.List;
|
||||||
|
import org.apache.ibatis.annotations.Param;
|
||||||
|
import com.ruoyi.price.domain.PrcBill;
|
||||||
|
|
||||||
|
/** receivable bill header mapper */
|
||||||
|
public interface PrcBillMapper
|
||||||
|
{
|
||||||
|
public PrcBill selectPrcBillByOrderNo(String orderNo);
|
||||||
|
|
||||||
|
public PrcBill selectPrcBillById(String billId);
|
||||||
|
|
||||||
|
public List<PrcBill> selectPrcBillList(PrcBill bill);
|
||||||
|
|
||||||
|
public int insertPrcBill(PrcBill bill);
|
||||||
|
|
||||||
|
public int updatePrcBill(PrcBill bill);
|
||||||
|
|
||||||
|
public int updateBillAmounts(@Param("billId") String billId,
|
||||||
|
@Param("surchargeAmount") BigDecimal surchargeAmount,
|
||||||
|
@Param("payableTotal") BigDecimal payableTotal);
|
||||||
|
}
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
package com.ruoyi.price.service;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import com.ruoyi.price.domain.PrcBill;
|
||||||
|
import com.ruoyi.price.domain.vo.TmsPriceBillRequest;
|
||||||
|
import com.ruoyi.price.domain.vo.TmsPriceQuoteResult;
|
||||||
|
|
||||||
|
/** Receivable billing from synced orders. Same price match as quote, persist prc_bill. */
|
||||||
|
public interface IPrcBillService
|
||||||
|
{
|
||||||
|
TmsPriceQuoteResult bill(TmsPriceBillRequest request);
|
||||||
|
|
||||||
|
List<PrcBill> selectBillList(PrcBill query);
|
||||||
|
|
||||||
|
TmsPriceQuoteResult getBill(String billId);
|
||||||
|
|
||||||
|
TmsPriceQuoteResult getBillByOrderNo(String orderNo);
|
||||||
|
}
|
||||||
@@ -18,6 +18,9 @@ public interface ITmsPriceQuoteService
|
|||||||
{
|
{
|
||||||
TmsPriceQuoteResult quote(TmsPriceQuoteRequest request);
|
TmsPriceQuoteResult quote(TmsPriceQuoteRequest request);
|
||||||
|
|
||||||
|
/** Calc only, no prc_quote persist. Used by receivable billing. */
|
||||||
|
TmsPriceQuoteResult calculate(TmsPriceQuoteRequest request);
|
||||||
|
|
||||||
List<PrcQuote> selectQuoteList(PrcQuote query);
|
List<PrcQuote> selectQuoteList(PrcQuote query);
|
||||||
|
|
||||||
TmsPriceQuoteResult getQuote(String quoteId);
|
TmsPriceQuoteResult getQuote(String quoteId);
|
||||||
|
|||||||
+291
@@ -0,0 +1,291 @@
|
|||||||
|
package com.ruoyi.price.service.impl;
|
||||||
|
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
import java.text.ParseException;
|
||||||
|
import java.text.SimpleDateFormat;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.UUID;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
import com.ruoyi.common.exception.ServiceException;
|
||||||
|
import com.ruoyi.common.utils.MessageUtils;
|
||||||
|
import com.ruoyi.common.utils.StringUtils;
|
||||||
|
import com.ruoyi.common.utils.sign.Md5Utils;
|
||||||
|
import com.ruoyi.price.domain.PrcBill;
|
||||||
|
import com.ruoyi.price.domain.PrcBillFee;
|
||||||
|
import com.ruoyi.price.domain.vo.TmsPriceBillRequest;
|
||||||
|
import com.ruoyi.price.domain.vo.TmsPriceQuoteFeeLine;
|
||||||
|
import com.ruoyi.price.domain.vo.TmsPriceQuoteResult;
|
||||||
|
import com.ruoyi.price.mapper.PrcBillFeeMapper;
|
||||||
|
import com.ruoyi.price.mapper.PrcBillMapper;
|
||||||
|
import com.ruoyi.price.service.IPrcBillService;
|
||||||
|
import com.ruoyi.price.service.ITmsPriceQuoteService;
|
||||||
|
|
||||||
|
@Service
|
||||||
|
public class PrcBillServiceImpl implements IPrcBillService
|
||||||
|
{
|
||||||
|
@Autowired
|
||||||
|
private ITmsPriceQuoteService tmsPriceQuoteService;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private PrcBillMapper billMapper;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private PrcBillFeeMapper billFeeMapper;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@Transactional(rollbackFor = Exception.class)
|
||||||
|
public TmsPriceQuoteResult bill(TmsPriceBillRequest request)
|
||||||
|
{
|
||||||
|
if (request == null || StringUtils.isEmpty(request.getOrderNo()))
|
||||||
|
{
|
||||||
|
throw new ServiceException(MessageUtils.message("price.bill.orderNoRequired"));
|
||||||
|
}
|
||||||
|
request.setOrderNo(request.getOrderNo().trim());
|
||||||
|
if (StringUtils.isEmpty(request.getBizDate()))
|
||||||
|
{
|
||||||
|
throw new ServiceException(MessageUtils.message("price.bill.bizDateRequired"));
|
||||||
|
}
|
||||||
|
Date bizDate = resolveBizDate(request.getBizDate());
|
||||||
|
BigDecimal weight = request.getWeight();
|
||||||
|
TmsPriceQuoteResult result = tmsPriceQuoteService.calculate(request);
|
||||||
|
persistBill(request, weight, bizDate, result);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<PrcBill> selectBillList(PrcBill query)
|
||||||
|
{
|
||||||
|
return billMapper.selectPrcBillList(query);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public TmsPriceQuoteResult getBill(String billId)
|
||||||
|
{
|
||||||
|
if (billId == null)
|
||||||
|
{
|
||||||
|
throw new ServiceException(MessageUtils.message("price.bill.billIdRequired"));
|
||||||
|
}
|
||||||
|
PrcBill bill = billMapper.selectPrcBillById(billId);
|
||||||
|
if (bill == null)
|
||||||
|
{
|
||||||
|
throw new ServiceException(MessageUtils.message("price.bill.notFound"));
|
||||||
|
}
|
||||||
|
return toResult(bill, billFeeMapper.selectByBillId(billId));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public TmsPriceQuoteResult getBillByOrderNo(String orderNo)
|
||||||
|
{
|
||||||
|
if (StringUtils.isEmpty(orderNo))
|
||||||
|
{
|
||||||
|
throw new ServiceException(MessageUtils.message("price.bill.orderNoRequired"));
|
||||||
|
}
|
||||||
|
PrcBill bill = billMapper.selectPrcBillByOrderNo(orderNo.trim());
|
||||||
|
if (bill == null)
|
||||||
|
{
|
||||||
|
throw new ServiceException(MessageUtils.message("price.bill.notFound"));
|
||||||
|
}
|
||||||
|
return toResult(bill, billFeeMapper.selectByBillId(bill.getBillId()));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void persistBill(TmsPriceBillRequest request, BigDecimal weight, Date bizDate,
|
||||||
|
TmsPriceQuoteResult result)
|
||||||
|
{
|
||||||
|
String orderNo = request.getOrderNo();
|
||||||
|
String billKey = Md5Utils.hash(orderNo);
|
||||||
|
PrcBill existed = billMapper.selectPrcBillByOrderNo(orderNo);
|
||||||
|
PrcBill bill = existed == null ? new PrcBill() : existed;
|
||||||
|
if (existed == null)
|
||||||
|
{
|
||||||
|
bill.setBillId(UUID.randomUUID().toString());
|
||||||
|
}
|
||||||
|
bill.setBillKey(billKey);
|
||||||
|
bill.setOrderNo(orderNo);
|
||||||
|
bill.setCustomerId(request.getCustomerId() == null ? Long.valueOf(0L) : request.getCustomerId());
|
||||||
|
bill.setCustomerCode(request.getCustomerCode());
|
||||||
|
bill.setCustomerName(request.getCustomerName());
|
||||||
|
bill.setTrackingNo(request.getTrackingNo());
|
||||||
|
bill.setPieces(request.getPieces());
|
||||||
|
bill.setActualWeight(request.getActualWeight());
|
||||||
|
bill.setVolume(request.getVolume());
|
||||||
|
bill.setVolumeWeight(request.getVolumeWeight());
|
||||||
|
bill.setPkgLength(request.getPkgLength());
|
||||||
|
bill.setPkgWidth(request.getPkgWidth());
|
||||||
|
bill.setPkgHeight(request.getPkgHeight());
|
||||||
|
bill.setShipperName(request.getShipperName());
|
||||||
|
bill.setConsigneeName(request.getConsigneeName());
|
||||||
|
bill.setDestPostcode(request.getDestPostcode());
|
||||||
|
bill.setWarehouseCode(request.getWarehouseCode());
|
||||||
|
bill.setOrderTime(request.getOrderTime());
|
||||||
|
bill.setOrderRemark(request.getOrderRemark());
|
||||||
|
bill.setProductCode(result.getProductCode());
|
||||||
|
bill.setProductName(result.getProductName());
|
||||||
|
bill.setCountryCode(result.getCountryCode());
|
||||||
|
bill.setCountryName(result.getCountryName());
|
||||||
|
bill.setWeight(weight);
|
||||||
|
bill.setBizDate(bizDate);
|
||||||
|
bill.setTmsId(request.getTmsId() == null ? null : Long.valueOf(request.getTmsId()));
|
||||||
|
bill.setMatchSource(result.getMatchSource());
|
||||||
|
bill.setMatchMessage(result.getMatchMessage());
|
||||||
|
bill.setPriceSetId(result.getPriceSetId());
|
||||||
|
bill.setPriceSetCode(result.getPriceSetCode());
|
||||||
|
bill.setPriceSetName(result.getPriceSetName());
|
||||||
|
bill.setSetType(result.getSetType());
|
||||||
|
bill.setBindPriority(result.getBindPriority());
|
||||||
|
bill.setCustomerPricesetId(result.getCustomerPricesetId());
|
||||||
|
bill.setProductCountryId(result.getProductCountryId());
|
||||||
|
bill.setWeightMin(result.getWeightMin());
|
||||||
|
bill.setWeightMax(result.getWeightMax());
|
||||||
|
bill.setWeightLabel(result.getWeightLabel());
|
||||||
|
bill.setEffectiveDate(result.getEffectiveDate());
|
||||||
|
bill.setChargeWeight(result.getChargeWeight());
|
||||||
|
bill.setFreightRate(result.getFreightRate());
|
||||||
|
bill.setBaseFreightRate(result.getBaseFreightRate());
|
||||||
|
bill.setDiscountPercent(result.getDiscountPercent());
|
||||||
|
bill.setRegistrationFee(result.getRegistrationFee());
|
||||||
|
bill.setFreightAmount(result.getFreightAmount());
|
||||||
|
bill.setSurchargeAmount(result.getSurchargeAmount());
|
||||||
|
bill.setPayableTotal(result.getPayableTotal());
|
||||||
|
bill.setCurrency(result.getCurrency());
|
||||||
|
bill.setRoundMode(result.getRoundMode());
|
||||||
|
if (existed == null)
|
||||||
|
{
|
||||||
|
billMapper.insertPrcBill(bill);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
billMapper.updatePrcBill(bill);
|
||||||
|
billFeeMapper.deleteByBillId(bill.getBillId());
|
||||||
|
}
|
||||||
|
List<PrcBillFee> fees = toFeeRows(bill.getBillId(), result);
|
||||||
|
if (!fees.isEmpty())
|
||||||
|
{
|
||||||
|
billFeeMapper.insertBatch(fees);
|
||||||
|
}
|
||||||
|
result.setBillId(bill.getBillId());
|
||||||
|
result.setOrderNo(orderNo);
|
||||||
|
result.setCustomerCode(request.getCustomerCode());
|
||||||
|
fillResultOrder(result, bill);
|
||||||
|
result.setFromCache(Boolean.valueOf(existed != null));
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<PrcBillFee> toFeeRows(String billId, TmsPriceQuoteResult result)
|
||||||
|
{
|
||||||
|
List<PrcBillFee> fees = new ArrayList<PrcBillFee>();
|
||||||
|
if (result.getFeeDetails() == null)
|
||||||
|
{
|
||||||
|
return fees;
|
||||||
|
}
|
||||||
|
for (TmsPriceQuoteFeeLine line : result.getFeeDetails())
|
||||||
|
{
|
||||||
|
PrcBillFee fee = new PrcBillFee();
|
||||||
|
fee.setFeeId(UUID.randomUUID().toString());
|
||||||
|
fee.setBillId(billId);
|
||||||
|
fee.setFeeType(line.getFeeType());
|
||||||
|
fee.setFeeName(line.getFeeName());
|
||||||
|
fee.setScId(line.getScId() == null ? 0L : line.getScId());
|
||||||
|
fee.setAmount(line.getAmount() == null ? BigDecimal.ZERO : line.getAmount());
|
||||||
|
fee.setCurrency(line.getCurrency());
|
||||||
|
fee.setRoundMode(line.getRoundMode());
|
||||||
|
fee.setRemark(line.getRemark());
|
||||||
|
fees.add(fee);
|
||||||
|
}
|
||||||
|
return fees;
|
||||||
|
}
|
||||||
|
|
||||||
|
private TmsPriceQuoteResult toResult(PrcBill bill, List<PrcBillFee> fees)
|
||||||
|
{
|
||||||
|
TmsPriceQuoteResult r = new TmsPriceQuoteResult();
|
||||||
|
r.setBillId(bill.getBillId());
|
||||||
|
r.setOrderNo(bill.getOrderNo());
|
||||||
|
r.setCustomerCode(bill.getCustomerCode());
|
||||||
|
fillResultOrder(r, bill);
|
||||||
|
r.setFromCache(Boolean.TRUE);
|
||||||
|
r.setMatchSource(bill.getMatchSource());
|
||||||
|
r.setMatchMessage(bill.getMatchMessage());
|
||||||
|
r.setCustomerId(bill.getCustomerId());
|
||||||
|
r.setPriceSetId(bill.getPriceSetId());
|
||||||
|
r.setPriceSetCode(bill.getPriceSetCode());
|
||||||
|
r.setPriceSetName(bill.getPriceSetName());
|
||||||
|
r.setSetType(bill.getSetType());
|
||||||
|
r.setBindPriority(bill.getBindPriority());
|
||||||
|
r.setCustomerPricesetId(bill.getCustomerPricesetId());
|
||||||
|
r.setProductCode(bill.getProductCode());
|
||||||
|
r.setProductName(bill.getProductName());
|
||||||
|
r.setCountryCode(bill.getCountryCode());
|
||||||
|
r.setCountryName(bill.getCountryName());
|
||||||
|
r.setProductCountryId(bill.getProductCountryId());
|
||||||
|
r.setWeightMin(bill.getWeightMin());
|
||||||
|
r.setWeightMax(bill.getWeightMax());
|
||||||
|
r.setWeightLabel(bill.getWeightLabel());
|
||||||
|
r.setEffectiveDate(bill.getEffectiveDate());
|
||||||
|
r.setWeight(bill.getWeight());
|
||||||
|
r.setChargeWeight(bill.getChargeWeight());
|
||||||
|
r.setFreightRate(bill.getFreightRate());
|
||||||
|
r.setBaseFreightRate(bill.getBaseFreightRate());
|
||||||
|
r.setDiscountPercent(bill.getDiscountPercent());
|
||||||
|
r.setRegistrationFee(bill.getRegistrationFee());
|
||||||
|
r.setFreightAmount(bill.getFreightAmount());
|
||||||
|
r.setSurchargeAmount(bill.getSurchargeAmount());
|
||||||
|
r.setPayableTotal(bill.getPayableTotal());
|
||||||
|
r.setCurrency(bill.getCurrency());
|
||||||
|
r.setRoundMode(bill.getRoundMode());
|
||||||
|
List<TmsPriceQuoteFeeLine> lines = new ArrayList<TmsPriceQuoteFeeLine>();
|
||||||
|
if (fees != null)
|
||||||
|
{
|
||||||
|
for (PrcBillFee fee : fees)
|
||||||
|
{
|
||||||
|
TmsPriceQuoteFeeLine line = new TmsPriceQuoteFeeLine();
|
||||||
|
line.setFeeType(fee.getFeeType());
|
||||||
|
line.setFeeName(fee.getFeeName());
|
||||||
|
line.setScId(fee.getScId());
|
||||||
|
line.setAmount(fee.getAmount());
|
||||||
|
line.setCurrency(fee.getCurrency());
|
||||||
|
line.setRoundMode(fee.getRoundMode());
|
||||||
|
line.setRemark(fee.getRemark());
|
||||||
|
lines.add(line);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
r.setFeeDetails(lines);
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void fillResultOrder(TmsPriceQuoteResult r, PrcBill bill)
|
||||||
|
{
|
||||||
|
r.setTrackingNo(bill.getTrackingNo());
|
||||||
|
r.setCustomerName(bill.getCustomerName());
|
||||||
|
r.setPieces(bill.getPieces());
|
||||||
|
r.setActualWeight(bill.getActualWeight());
|
||||||
|
r.setVolume(bill.getVolume());
|
||||||
|
r.setVolumeWeight(bill.getVolumeWeight());
|
||||||
|
r.setPkgLength(bill.getPkgLength());
|
||||||
|
r.setPkgWidth(bill.getPkgWidth());
|
||||||
|
r.setPkgHeight(bill.getPkgHeight());
|
||||||
|
r.setShipperName(bill.getShipperName());
|
||||||
|
r.setConsigneeName(bill.getConsigneeName());
|
||||||
|
r.setDestPostcode(bill.getDestPostcode());
|
||||||
|
r.setWarehouseCode(bill.getWarehouseCode());
|
||||||
|
r.setOrderTime(bill.getOrderTime());
|
||||||
|
r.setOrderRemark(bill.getOrderRemark());
|
||||||
|
}
|
||||||
|
|
||||||
|
private Date resolveBizDate(String bizDate)
|
||||||
|
{
|
||||||
|
if (StringUtils.isEmpty(bizDate))
|
||||||
|
{
|
||||||
|
throw new ServiceException(MessageUtils.message("price.bill.bizDateRequired"));
|
||||||
|
}
|
||||||
|
try
|
||||||
|
{
|
||||||
|
return new SimpleDateFormat("yyyy-MM-dd").parse(bizDate.trim());
|
||||||
|
}
|
||||||
|
catch (ParseException e)
|
||||||
|
{
|
||||||
|
throw new ServiceException(MessageUtils.message("price.quote.bizDateInvalid"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+10
@@ -113,6 +113,16 @@ public class TmsPriceQuoteServiceImpl implements ITmsPriceQuoteService
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public TmsPriceQuoteResult calculate(TmsPriceQuoteRequest request)
|
||||||
|
{
|
||||||
|
validateRequest(request);
|
||||||
|
Date bizDate = resolveBizDate(request.getBizDate());
|
||||||
|
TmsPriceQuoteResult result = doQuote(request, bizDate);
|
||||||
|
applySurchargesAndFees(result);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<PrcQuote> selectQuoteList(PrcQuote query)
|
public List<PrcQuote> selectQuoteList(PrcQuote query)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -0,0 +1,48 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" ?>
|
||||||
|
<!DOCTYPE mapper
|
||||||
|
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||||
|
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||||
|
<mapper namespace="com.ruoyi.price.mapper.PrcBillFeeMapper">
|
||||||
|
|
||||||
|
<resultMap type="PrcBillFee" id="PrcBillFeeResult">
|
||||||
|
<id property="feeId" column="fee_id" />
|
||||||
|
<result property="billId" column="bill_id" />
|
||||||
|
<result property="feeType" column="fee_type" />
|
||||||
|
<result property="feeName" column="fee_name" />
|
||||||
|
<result property="scId" column="sc_id" />
|
||||||
|
<result property="amount" column="amount" />
|
||||||
|
<result property="currency" column="currency" />
|
||||||
|
<result property="roundMode" column="round_mode" />
|
||||||
|
<result property="remark" column="remark" />
|
||||||
|
<result property="createdAt" column="created_at" />
|
||||||
|
</resultMap>
|
||||||
|
|
||||||
|
<select id="selectByBillId" parameterType="String" resultMap="PrcBillFeeResult">
|
||||||
|
select fee_id, bill_id, fee_type, fee_name, sc_id, amount, currency, round_mode, remark, created_at
|
||||||
|
from prc_bill_fee
|
||||||
|
where bill_id = #{billId}
|
||||||
|
order by field(fee_type, 'BASIC_FREIGHT', 'REGISTRATION_FEE', 'SURCHARGE'), fee_id
|
||||||
|
</select>
|
||||||
|
|
||||||
|
<insert id="insertPrcBillFee" parameterType="PrcBillFee">
|
||||||
|
insert into prc_bill_fee (
|
||||||
|
fee_id, bill_id, fee_type, fee_name, sc_id, amount, currency, round_mode, remark, created_at
|
||||||
|
) values (
|
||||||
|
#{feeId}, #{billId}, #{feeType}, #{feeName}, #{scId}, #{amount}, #{currency}, #{roundMode}, #{remark}, sysdate()
|
||||||
|
)
|
||||||
|
</insert>
|
||||||
|
|
||||||
|
<insert id="insertBatch" parameterType="java.util.List">
|
||||||
|
insert into prc_bill_fee (
|
||||||
|
fee_id, bill_id, fee_type, fee_name, sc_id, amount, currency, round_mode, remark, created_at
|
||||||
|
) values
|
||||||
|
<foreach collection="list" item="item" separator=",">
|
||||||
|
(#{item.feeId}, #{item.billId}, #{item.feeType}, #{item.feeName}, #{item.scId}, #{item.amount},
|
||||||
|
#{item.currency}, #{item.roundMode}, #{item.remark}, sysdate())
|
||||||
|
</foreach>
|
||||||
|
</insert>
|
||||||
|
|
||||||
|
<delete id="deleteByBillId" parameterType="String">
|
||||||
|
delete from prc_bill_fee where bill_id = #{billId}
|
||||||
|
</delete>
|
||||||
|
</mapper>
|
||||||
@@ -0,0 +1,212 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" ?>
|
||||||
|
<!DOCTYPE mapper
|
||||||
|
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||||
|
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||||
|
<mapper namespace="com.ruoyi.price.mapper.PrcBillMapper">
|
||||||
|
|
||||||
|
<resultMap type="PrcBill" id="PrcBillResult">
|
||||||
|
<id property="billId" column="bill_id" />
|
||||||
|
<result property="billKey" column="bill_key" />
|
||||||
|
<result property="orderNo" column="order_no" />
|
||||||
|
<result property="trackingNo" column="tracking_no" />
|
||||||
|
<result property="customerId" column="customer_id" />
|
||||||
|
<result property="customerCode" column="customer_code" />
|
||||||
|
<result property="customerName" column="customer_name" />
|
||||||
|
<result property="pieces" column="pieces" />
|
||||||
|
<result property="actualWeight" column="actual_weight" />
|
||||||
|
<result property="volume" column="volume" />
|
||||||
|
<result property="volumeWeight" column="volume_weight" />
|
||||||
|
<result property="pkgLength" column="pkg_length" />
|
||||||
|
<result property="pkgWidth" column="pkg_width" />
|
||||||
|
<result property="pkgHeight" column="pkg_height" />
|
||||||
|
<result property="shipperName" column="shipper_name" />
|
||||||
|
<result property="consigneeName" column="consignee_name" />
|
||||||
|
<result property="destPostcode" column="dest_postcode" />
|
||||||
|
<result property="warehouseCode" column="warehouse_code" />
|
||||||
|
<result property="orderTime" column="order_time" />
|
||||||
|
<result property="orderRemark" column="order_remark" />
|
||||||
|
<result property="productCode" column="product_code" />
|
||||||
|
<result property="productName" column="product_name" />
|
||||||
|
<result property="countryCode" column="country_code" />
|
||||||
|
<result property="countryName" column="country_name" />
|
||||||
|
<result property="weight" column="weight" />
|
||||||
|
<result property="bizDate" column="biz_date" />
|
||||||
|
<result property="tmsId" column="tms_id" />
|
||||||
|
<result property="matchSource" column="match_source" />
|
||||||
|
<result property="matchMessage" column="match_message" />
|
||||||
|
<result property="priceSetId" column="price_set_id" />
|
||||||
|
<result property="priceSetCode" column="price_set_code" />
|
||||||
|
<result property="priceSetName" column="price_set_name" />
|
||||||
|
<result property="setType" column="set_type" />
|
||||||
|
<result property="bindPriority" column="bind_priority" />
|
||||||
|
<result property="customerPricesetId" column="customer_priceset_id" />
|
||||||
|
<result property="productCountryId" column="product_country_id" />
|
||||||
|
<result property="weightMin" column="weight_min" />
|
||||||
|
<result property="weightMax" column="weight_max" />
|
||||||
|
<result property="weightLabel" column="weight_label" />
|
||||||
|
<result property="effectiveDate" column="effective_date" />
|
||||||
|
<result property="chargeWeight" column="charge_weight" />
|
||||||
|
<result property="freightRate" column="freight_rate" />
|
||||||
|
<result property="baseFreightRate" column="base_freight_rate" />
|
||||||
|
<result property="discountPercent" column="discount_percent" />
|
||||||
|
<result property="registrationFee" column="registration_fee" />
|
||||||
|
<result property="freightAmount" column="freight_amount" />
|
||||||
|
<result property="surchargeAmount" column="surcharge_amount" />
|
||||||
|
<result property="payableTotal" column="payable_total" />
|
||||||
|
<result property="currency" column="currency" />
|
||||||
|
<result property="roundMode" column="round_mode" />
|
||||||
|
<result property="createBy" column="created_by" />
|
||||||
|
<result property="createTime" column="created_at" />
|
||||||
|
<result property="updateBy" column="updated_by" />
|
||||||
|
<result property="updateTime" column="updated_at" />
|
||||||
|
</resultMap>
|
||||||
|
|
||||||
|
<sql id="selectPrcBillVo">
|
||||||
|
select bill_id, bill_key, order_no, tracking_no, customer_id, customer_code, customer_name,
|
||||||
|
pieces, actual_weight, volume, volume_weight, pkg_length, pkg_width, pkg_height,
|
||||||
|
shipper_name, consignee_name, dest_postcode, warehouse_code, order_time, order_remark,
|
||||||
|
product_code, product_name, country_code, country_name, weight, biz_date, tms_id,
|
||||||
|
match_source, match_message, price_set_id, price_set_code, price_set_name,
|
||||||
|
set_type, bind_priority, customer_priceset_id, product_country_id,
|
||||||
|
weight_min, weight_max, weight_label, effective_date, charge_weight,
|
||||||
|
freight_rate, base_freight_rate, discount_percent, registration_fee,
|
||||||
|
freight_amount, surcharge_amount, payable_total, currency, round_mode,
|
||||||
|
created_by, created_at, updated_by, updated_at
|
||||||
|
from prc_bill
|
||||||
|
</sql>
|
||||||
|
|
||||||
|
<select id="selectPrcBillByOrderNo" parameterType="String" resultMap="PrcBillResult">
|
||||||
|
<include refid="selectPrcBillVo"/>
|
||||||
|
where order_no = #{orderNo}
|
||||||
|
</select>
|
||||||
|
|
||||||
|
<select id="selectPrcBillById" parameterType="String" resultMap="PrcBillResult">
|
||||||
|
<include refid="selectPrcBillVo"/>
|
||||||
|
where bill_id = #{billId}
|
||||||
|
</select>
|
||||||
|
|
||||||
|
<select id="selectPrcBillList" parameterType="PrcBill" resultMap="PrcBillResult">
|
||||||
|
<include refid="selectPrcBillVo"/>
|
||||||
|
<where>
|
||||||
|
<if test="orderNo != null and orderNo != ''">
|
||||||
|
AND order_no like concat('%', #{orderNo}, '%')
|
||||||
|
</if>
|
||||||
|
<if test="trackingNo != null and trackingNo != ''">
|
||||||
|
AND tracking_no like concat('%', #{trackingNo}, '%')
|
||||||
|
</if>
|
||||||
|
<if test="customerCode != null and customerCode != ''">
|
||||||
|
AND customer_code like concat('%', #{customerCode}, '%')
|
||||||
|
</if>
|
||||||
|
<if test="customerName != null and customerName != ''">
|
||||||
|
AND customer_name like concat('%', #{customerName}, '%')
|
||||||
|
</if>
|
||||||
|
<if test="productCode != null and productCode != ''">
|
||||||
|
AND product_code like concat('%', #{productCode}, '%')
|
||||||
|
</if>
|
||||||
|
<if test="countryCode != null and countryCode != ''">
|
||||||
|
AND country_code = #{countryCode}
|
||||||
|
</if>
|
||||||
|
<if test="matchSource != null and matchSource != ''">
|
||||||
|
AND match_source = #{matchSource}
|
||||||
|
</if>
|
||||||
|
<if test="bizDate != null">
|
||||||
|
AND biz_date = #{bizDate}
|
||||||
|
</if>
|
||||||
|
<if test="params.beginTime != null and params.beginTime != ''">
|
||||||
|
AND date_format(created_at,'%y%m%d') >= date_format(#{params.beginTime},'%y%m%d')
|
||||||
|
</if>
|
||||||
|
<if test="params.endTime != null and params.endTime != ''">
|
||||||
|
AND date_format(created_at,'%y%m%d') <= date_format(#{params.endTime},'%y%m%d')
|
||||||
|
</if>
|
||||||
|
</where>
|
||||||
|
order by created_at desc, bill_id desc
|
||||||
|
</select>
|
||||||
|
|
||||||
|
<insert id="insertPrcBill" parameterType="PrcBill">
|
||||||
|
insert into prc_bill (
|
||||||
|
bill_id, bill_key, order_no, tracking_no, customer_id, customer_code, customer_name,
|
||||||
|
pieces, actual_weight, volume, volume_weight, pkg_length, pkg_width, pkg_height,
|
||||||
|
shipper_name, consignee_name, dest_postcode, warehouse_code, order_time, order_remark,
|
||||||
|
product_code, product_name, country_code, country_name, weight, biz_date, tms_id,
|
||||||
|
match_source, match_message, price_set_id, price_set_code, price_set_name,
|
||||||
|
set_type, bind_priority, customer_priceset_id, product_country_id,
|
||||||
|
weight_min, weight_max, weight_label, effective_date, charge_weight,
|
||||||
|
freight_rate, base_freight_rate, discount_percent, registration_fee,
|
||||||
|
freight_amount, surcharge_amount, payable_total, currency, round_mode,
|
||||||
|
created_at
|
||||||
|
) values (
|
||||||
|
#{billId}, #{billKey}, #{orderNo}, #{trackingNo}, #{customerId}, #{customerCode}, #{customerName},
|
||||||
|
#{pieces}, #{actualWeight}, #{volume}, #{volumeWeight}, #{pkgLength}, #{pkgWidth}, #{pkgHeight},
|
||||||
|
#{shipperName}, #{consigneeName}, #{destPostcode}, #{warehouseCode}, #{orderTime}, #{orderRemark},
|
||||||
|
#{productCode}, #{productName}, #{countryCode}, #{countryName}, #{weight}, #{bizDate}, #{tmsId},
|
||||||
|
#{matchSource}, #{matchMessage}, #{priceSetId}, #{priceSetCode}, #{priceSetName},
|
||||||
|
#{setType}, #{bindPriority}, #{customerPricesetId}, #{productCountryId},
|
||||||
|
#{weightMin}, #{weightMax}, #{weightLabel}, #{effectiveDate}, #{chargeWeight},
|
||||||
|
#{freightRate}, #{baseFreightRate}, #{discountPercent}, #{registrationFee},
|
||||||
|
#{freightAmount}, #{surchargeAmount}, #{payableTotal}, #{currency}, #{roundMode},
|
||||||
|
sysdate()
|
||||||
|
)
|
||||||
|
</insert>
|
||||||
|
|
||||||
|
<update id="updatePrcBill" parameterType="PrcBill">
|
||||||
|
update prc_bill
|
||||||
|
set bill_key = #{billKey},
|
||||||
|
tracking_no = #{trackingNo},
|
||||||
|
customer_id = #{customerId},
|
||||||
|
customer_code = #{customerCode},
|
||||||
|
customer_name = #{customerName},
|
||||||
|
pieces = #{pieces},
|
||||||
|
actual_weight = #{actualWeight},
|
||||||
|
volume = #{volume},
|
||||||
|
volume_weight = #{volumeWeight},
|
||||||
|
pkg_length = #{pkgLength},
|
||||||
|
pkg_width = #{pkgWidth},
|
||||||
|
pkg_height = #{pkgHeight},
|
||||||
|
shipper_name = #{shipperName},
|
||||||
|
consignee_name = #{consigneeName},
|
||||||
|
dest_postcode = #{destPostcode},
|
||||||
|
warehouse_code = #{warehouseCode},
|
||||||
|
order_time = #{orderTime},
|
||||||
|
order_remark = #{orderRemark},
|
||||||
|
product_code = #{productCode},
|
||||||
|
product_name = #{productName},
|
||||||
|
country_code = #{countryCode},
|
||||||
|
country_name = #{countryName},
|
||||||
|
weight = #{weight},
|
||||||
|
biz_date = #{bizDate},
|
||||||
|
tms_id = #{tmsId},
|
||||||
|
match_source = #{matchSource},
|
||||||
|
match_message = #{matchMessage},
|
||||||
|
price_set_id = #{priceSetId},
|
||||||
|
price_set_code = #{priceSetCode},
|
||||||
|
price_set_name = #{priceSetName},
|
||||||
|
set_type = #{setType},
|
||||||
|
bind_priority = #{bindPriority},
|
||||||
|
customer_priceset_id = #{customerPricesetId},
|
||||||
|
product_country_id = #{productCountryId},
|
||||||
|
weight_min = #{weightMin},
|
||||||
|
weight_max = #{weightMax},
|
||||||
|
weight_label = #{weightLabel},
|
||||||
|
effective_date = #{effectiveDate},
|
||||||
|
charge_weight = #{chargeWeight},
|
||||||
|
freight_rate = #{freightRate},
|
||||||
|
base_freight_rate = #{baseFreightRate},
|
||||||
|
discount_percent = #{discountPercent},
|
||||||
|
registration_fee = #{registrationFee},
|
||||||
|
freight_amount = #{freightAmount},
|
||||||
|
surcharge_amount = #{surchargeAmount},
|
||||||
|
payable_total = #{payableTotal},
|
||||||
|
currency = #{currency},
|
||||||
|
round_mode = #{roundMode},
|
||||||
|
updated_at = sysdate()
|
||||||
|
where bill_id = #{billId}
|
||||||
|
</update>
|
||||||
|
|
||||||
|
<update id="updateBillAmounts">
|
||||||
|
update prc_bill
|
||||||
|
set surcharge_amount = #{surchargeAmount},
|
||||||
|
payable_total = #{payableTotal},
|
||||||
|
updated_at = sysdate()
|
||||||
|
where bill_id = #{billId}
|
||||||
|
</update>
|
||||||
|
</mapper>
|
||||||
@@ -0,0 +1,82 @@
|
|||||||
|
-- prc_bill / prc_bill_fee: receivable billing from synced orders
|
||||||
|
-- fields follow prc_quote / prc_quote_fee; extra order_no + customer_code
|
||||||
|
SET NAMES utf8mb4;
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS prc_bill (
|
||||||
|
bill_id VARCHAR(36) NOT NULL COMMENT '计费ID',
|
||||||
|
bill_key CHAR(32) NOT NULL COMMENT 'MD5(order_no)',
|
||||||
|
order_no VARCHAR(64) NOT NULL COMMENT '订单号',
|
||||||
|
tracking_no VARCHAR(64) DEFAULT NULL COMMENT '运单号',
|
||||||
|
customer_id BIGINT(20) NOT NULL DEFAULT 0 COMMENT '客户ID',
|
||||||
|
customer_code VARCHAR(50) DEFAULT NULL COMMENT '客户代码',
|
||||||
|
customer_name VARCHAR(100) DEFAULT NULL COMMENT '客户名称',
|
||||||
|
pieces INT(11) DEFAULT NULL COMMENT '件数',
|
||||||
|
actual_weight DECIMAL(10,3) DEFAULT NULL COMMENT '实际重量KG',
|
||||||
|
volume DECIMAL(12,4) DEFAULT NULL COMMENT '体积m3',
|
||||||
|
volume_weight DECIMAL(10,3) DEFAULT NULL COMMENT '材积重KG',
|
||||||
|
pkg_length DECIMAL(10,2) DEFAULT NULL COMMENT '长CM',
|
||||||
|
pkg_width DECIMAL(10,2) DEFAULT NULL COMMENT '宽CM',
|
||||||
|
pkg_height DECIMAL(10,2) DEFAULT NULL COMMENT '高CM',
|
||||||
|
shipper_name VARCHAR(100) DEFAULT NULL COMMENT '发件人',
|
||||||
|
consignee_name VARCHAR(100) DEFAULT NULL COMMENT '收件人',
|
||||||
|
dest_postcode VARCHAR(20) DEFAULT NULL COMMENT '目的邮编',
|
||||||
|
warehouse_code VARCHAR(50) DEFAULT NULL COMMENT '仓库',
|
||||||
|
order_time DATETIME DEFAULT NULL COMMENT '下单时间',
|
||||||
|
order_remark VARCHAR(500) DEFAULT NULL COMMENT '订单备注',
|
||||||
|
product_code VARCHAR(20) NOT NULL COMMENT '产品代码',
|
||||||
|
product_name VARCHAR(100) DEFAULT NULL COMMENT '产品名称',
|
||||||
|
country_code CHAR(2) DEFAULT NULL COMMENT '国家二字码',
|
||||||
|
country_name VARCHAR(50) DEFAULT NULL COMMENT '国家名称',
|
||||||
|
weight DECIMAL(10,3) NOT NULL COMMENT '计费重量KG',
|
||||||
|
biz_date DATE NOT NULL COMMENT '计费日期',
|
||||||
|
tms_id BIGINT(20) DEFAULT NULL COMMENT '多租户系统ID',
|
||||||
|
match_source VARCHAR(30) DEFAULT NULL COMMENT '命中来源',
|
||||||
|
match_message VARCHAR(200) DEFAULT NULL COMMENT '命中说明',
|
||||||
|
price_set_id BIGINT(20) DEFAULT NULL COMMENT '价格套餐ID',
|
||||||
|
price_set_code VARCHAR(20) DEFAULT NULL COMMENT '套餐编码',
|
||||||
|
price_set_name VARCHAR(50) DEFAULT NULL COMMENT '套餐名称',
|
||||||
|
set_type VARCHAR(10) DEFAULT NULL COMMENT '计价类型',
|
||||||
|
bind_priority INT(11) DEFAULT NULL COMMENT '客户套餐优先级',
|
||||||
|
customer_priceset_id BIGINT(20) DEFAULT NULL COMMENT '客户套餐绑定ID',
|
||||||
|
product_country_id BIGINT(20) DEFAULT NULL COMMENT '关联 bms_product_country.detail_id',
|
||||||
|
weight_min DECIMAL(10,4) DEFAULT NULL COMMENT '重量段下限',
|
||||||
|
weight_max DECIMAL(10,4) DEFAULT NULL COMMENT '重量段上限',
|
||||||
|
weight_label VARCHAR(50) DEFAULT NULL COMMENT '重量段展示',
|
||||||
|
effective_date DATE DEFAULT NULL COMMENT '产品明细生效日',
|
||||||
|
charge_weight DECIMAL(10,3) DEFAULT NULL COMMENT '计费重量',
|
||||||
|
freight_rate DECIMAL(10,4) DEFAULT NULL COMMENT '运费单价',
|
||||||
|
base_freight_rate DECIMAL(10,4) DEFAULT NULL COMMENT '折扣前单价',
|
||||||
|
discount_percent DECIMAL(5,2) DEFAULT NULL COMMENT '折扣百分数',
|
||||||
|
registration_fee DECIMAL(10,2) DEFAULT NULL COMMENT '挂号费',
|
||||||
|
freight_amount DECIMAL(10,2) DEFAULT NULL COMMENT '运费金额',
|
||||||
|
surcharge_amount DECIMAL(10,2) DEFAULT NULL COMMENT '附加费合计',
|
||||||
|
payable_total DECIMAL(10,2) DEFAULT NULL COMMENT '应收总额',
|
||||||
|
currency VARCHAR(10) NOT NULL DEFAULT 'CNY' COMMENT '币种',
|
||||||
|
round_mode VARCHAR(20) NOT NULL DEFAULT 'HALF_UP' COMMENT '取值方式',
|
||||||
|
created_by VARCHAR(64) DEFAULT '' COMMENT '创建人',
|
||||||
|
created_at DATETIME DEFAULT NULL COMMENT '创建时间',
|
||||||
|
updated_by VARCHAR(64) DEFAULT '' COMMENT '更新人',
|
||||||
|
updated_at DATETIME DEFAULT NULL COMMENT '更新时间',
|
||||||
|
PRIMARY KEY (bill_id),
|
||||||
|
UNIQUE KEY uk_bill_order (order_no),
|
||||||
|
UNIQUE KEY uk_bill_key (bill_key),
|
||||||
|
INDEX idx_bill_customer (customer_code, biz_date),
|
||||||
|
INDEX idx_bill_product (product_code, country_code)
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='计费应收主表-订单同步计费';
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS prc_bill_fee (
|
||||||
|
fee_id VARCHAR(36) NOT NULL COMMENT '费用明细ID',
|
||||||
|
bill_id VARCHAR(36) NOT NULL COMMENT '计费ID',
|
||||||
|
fee_type VARCHAR(30) NOT NULL COMMENT '费用类型(字典bms_fee_type)',
|
||||||
|
fee_name VARCHAR(100) DEFAULT NULL COMMENT '费用名称',
|
||||||
|
sc_id BIGINT(20) NOT NULL DEFAULT 0 COMMENT '附加费配置ID',
|
||||||
|
amount DECIMAL(12,2) NOT NULL DEFAULT 0 COMMENT '金额',
|
||||||
|
currency VARCHAR(10) NOT NULL DEFAULT 'CNY' COMMENT '币种',
|
||||||
|
round_mode VARCHAR(20) DEFAULT 'HALF_UP' COMMENT '取值方式',
|
||||||
|
remark VARCHAR(500) DEFAULT NULL COMMENT '备注',
|
||||||
|
created_at DATETIME DEFAULT NULL COMMENT '创建时间',
|
||||||
|
PRIMARY KEY (fee_id),
|
||||||
|
UNIQUE KEY uk_bill_fee_item (bill_id, fee_type, sc_id),
|
||||||
|
INDEX idx_bill_fee_type (fee_type),
|
||||||
|
CONSTRAINT fk_bill_fee_bill FOREIGN KEY (bill_id) REFERENCES prc_bill (bill_id) ON DELETE CASCADE
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='计费应收费用明细';
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
SET NAMES utf8mb4;
|
||||||
|
|
||||||
|
-- visible C menu under billing center (2300)
|
||||||
|
INSERT INTO sys_menu (menu_id, menu_name, parent_id, order_num, path, component, query, route_name, is_frame, is_cache, menu_type, visible, status, perms, icon, create_by, create_time, remark)
|
||||||
|
SELECT 2310, N'同步计费', 2300, 2, 'bill', 'price/billing/bill', '', 'BillingBill', 1, 0, 'C', '0', '0', 'price:billing:bill', 'list', 'admin', sysdate(), N'订单同步计费应收'
|
||||||
|
FROM DUAL WHERE NOT EXISTS (SELECT 1 FROM sys_menu WHERE menu_id = 2310);
|
||||||
|
|
||||||
|
UPDATE sys_menu SET menu_name = N'同步计费', parent_id = 2300, order_num = 2, path = 'bill', component = 'price/billing/bill', route_name = 'BillingBill', menu_type = 'C', visible = '0', perms = 'price:billing:bill', remark = N'订单同步计费应收'
|
||||||
|
WHERE menu_id = 2310;
|
||||||
|
|
||||||
|
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)
|
||||||
|
SELECT 2311, N'计费查询', 2310, 1, '', NULL, 1, 0, 'F', '0', '0', 'price:billing:bill', '#', 'admin', sysdate()
|
||||||
|
FROM DUAL WHERE NOT EXISTS (SELECT 1 FROM sys_menu WHERE menu_id = 2311);
|
||||||
|
|
||||||
|
UPDATE sys_menu SET menu_name = N'计费查询', parent_id = 2310, menu_type = 'F', path = '', component = NULL, perms = 'price:billing:bill' WHERE menu_id = 2311;
|
||||||
|
|
||||||
|
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)
|
||||||
|
SELECT 2312, N'计费详情', 2310, 2, '', NULL, 1, 0, 'F', '0', '0', 'price:billing:bill', '#', 'admin', sysdate()
|
||||||
|
FROM DUAL WHERE NOT EXISTS (SELECT 1 FROM sys_menu WHERE menu_id = 2312);
|
||||||
|
|
||||||
|
INSERT INTO sys_role_menu (role_id, menu_id)
|
||||||
|
SELECT 1, m.menu_id FROM (SELECT 2310 AS menu_id UNION SELECT 2311 UNION SELECT 2312) m
|
||||||
|
WHERE NOT EXISTS (SELECT 1 FROM sys_role_menu rm WHERE rm.role_id = 1 AND rm.menu_id = m.menu_id);
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
-- prc_bill add order snapshot columns
|
||||||
|
SET NAMES utf8mb4;
|
||||||
|
|
||||||
|
ALTER TABLE prc_bill
|
||||||
|
ADD COLUMN tracking_no VARCHAR(64) DEFAULT NULL COMMENT '运单号' AFTER order_no,
|
||||||
|
ADD COLUMN customer_name VARCHAR(100) DEFAULT NULL COMMENT '客户名称' AFTER customer_code,
|
||||||
|
ADD COLUMN pieces INT(11) DEFAULT NULL COMMENT '件数' AFTER customer_name,
|
||||||
|
ADD COLUMN actual_weight DECIMAL(10,3) DEFAULT NULL COMMENT '实际重量KG' AFTER pieces,
|
||||||
|
ADD COLUMN volume DECIMAL(12,4) DEFAULT NULL COMMENT '体积m3' AFTER actual_weight,
|
||||||
|
ADD COLUMN volume_weight DECIMAL(10,3) DEFAULT NULL COMMENT '材积重KG' AFTER volume,
|
||||||
|
ADD COLUMN pkg_length DECIMAL(10,2) DEFAULT NULL COMMENT '长CM' AFTER volume_weight,
|
||||||
|
ADD COLUMN pkg_width DECIMAL(10,2) DEFAULT NULL COMMENT '宽CM' AFTER pkg_length,
|
||||||
|
ADD COLUMN pkg_height DECIMAL(10,2) DEFAULT NULL COMMENT '高CM' AFTER pkg_width,
|
||||||
|
ADD COLUMN shipper_name VARCHAR(100) DEFAULT NULL COMMENT '发件人' AFTER pkg_height,
|
||||||
|
ADD COLUMN consignee_name VARCHAR(100) DEFAULT NULL COMMENT '收件人' AFTER shipper_name,
|
||||||
|
ADD COLUMN dest_postcode VARCHAR(20) DEFAULT NULL COMMENT '目的邮编' AFTER consignee_name,
|
||||||
|
ADD COLUMN warehouse_code VARCHAR(50) DEFAULT NULL COMMENT '仓库' AFTER dest_postcode,
|
||||||
|
ADD COLUMN order_time DATETIME DEFAULT NULL COMMENT '下单时间' AFTER warehouse_code,
|
||||||
|
ADD COLUMN order_remark VARCHAR(500) DEFAULT NULL COMMENT '订单备注' AFTER order_time;
|
||||||
|
|
||||||
|
ALTER TABLE prc_bill ADD INDEX idx_bill_tracking (tracking_no);
|
||||||
@@ -25,3 +25,29 @@ export function getQuote(quoteId) {
|
|||||||
method: 'get'
|
method: 'get'
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Sync order receivable bill */
|
||||||
|
export function billOrder(data) {
|
||||||
|
return request({
|
||||||
|
url: '/price/billing/bill',
|
||||||
|
method: 'post',
|
||||||
|
data
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Receivable bill list */
|
||||||
|
export function listBill(query) {
|
||||||
|
return request({
|
||||||
|
url: '/price/billing/bill/list',
|
||||||
|
method: 'get',
|
||||||
|
params: query
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Receivable bill detail */
|
||||||
|
export function getBill(billId) {
|
||||||
|
return request({
|
||||||
|
url: '/price/billing/bill/' + billId,
|
||||||
|
method: 'get'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|||||||
@@ -0,0 +1,244 @@
|
|||||||
|
<template>
|
||||||
|
<div class="app-container billing-bill">
|
||||||
|
<basic-table
|
||||||
|
ref="tableRef"
|
||||||
|
:columns="columns"
|
||||||
|
:search-columns="searchColumns"
|
||||||
|
:query="queryList"
|
||||||
|
row-key="billId"
|
||||||
|
>
|
||||||
|
<template #col-product="{ row }">
|
||||||
|
{{ row.productName || '-' }} ({{ row.productCode }})
|
||||||
|
</template>
|
||||||
|
<template #col-country="{ row }">
|
||||||
|
{{ row.countryName || '-' }} ({{ row.countryCode || '-' }})
|
||||||
|
</template>
|
||||||
|
<template #col-matchSource="{ row }">
|
||||||
|
<el-tag size="small" :type="sourceTagType(row.matchSource)">{{ sourceLabel(row.matchSource) }}</el-tag>
|
||||||
|
</template>
|
||||||
|
<template #col-payableTotal="{ row }">
|
||||||
|
<span class="payable">{{ formatMoney(row.payableTotal) }}</span>
|
||||||
|
</template>
|
||||||
|
<template #col-action="{ row }">
|
||||||
|
<el-button link type="primary" icon="View" @click="handleView(row)">查看</el-button>
|
||||||
|
</template>
|
||||||
|
</basic-table>
|
||||||
|
|
||||||
|
<el-drawer v-model="open" size="780px" :title="title" append-to-body>
|
||||||
|
<div v-loading="loading">
|
||||||
|
<el-empty v-if="!detail" description="暂无详情" />
|
||||||
|
<div v-else class="bill-detail">
|
||||||
|
<div class="sec-title">订单信息</div>
|
||||||
|
<el-descriptions :column="2" border size="small">
|
||||||
|
<el-descriptions-item label="订单号">{{ detail.orderNo || '-' }}</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="运单号">{{ detail.trackingNo || '-' }}</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="客户">{{ displayCustomer(detail) }}</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>
|
||||||
|
<el-descriptions-item label="目的国/地区">{{ (detail.countryName || '-') + ' (' + (detail.countryCode || '-') + ')' }}</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="目的邮编">{{ detail.destPostcode || '-' }}</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="件数">{{ detail.pieces != null ? detail.pieces : '-' }}</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="尺寸(cm)">{{ dimLabel(detail) }}</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="实重(kg)">{{ formatMoney(detail.actualWeight) }}</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="材积重(kg)">{{ formatMoney(detail.volumeWeight) }}</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="体积(m³)">{{ formatMoney(detail.volume) }}</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="下单时间">{{ formatDateTime(detail.orderTime) }}</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="订单备注" :span="2">{{ detail.orderRemark || '-' }}</el-descriptions-item>
|
||||||
|
</el-descriptions>
|
||||||
|
|
||||||
|
<div class="sec-title">计费信息</div>
|
||||||
|
<el-descriptions :column="2" border size="small">
|
||||||
|
<el-descriptions-item label="产品">{{ (detail.productName || '-') + ' (' + (detail.productCode || '-') + ')' }}</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="计费重量(kg)">{{ detail.chargeWeight ?? detail.weight ?? '-' }}</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="重量段">{{ detail.weightLabel || '-' }}</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="计费日期">{{ formatDate(detail.bizDate) }}</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="计价来源">
|
||||||
|
<el-tag size="small" :type="sourceTagType(detail.matchSource)">{{ sourceLabel(detail.matchSource) }}</el-tag>
|
||||||
|
</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="套餐">{{ detail.priceSetName || '-' }} {{ detail.priceSetCode ? '(' + detail.priceSetCode + ')' : '' }}</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="币种">
|
||||||
|
<dict-tag :options="bms_currency" :value="displayCurrency(detail.currency)" />
|
||||||
|
</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="取值方式">{{ roundModeLabel(detail.roundMode) }}</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="运费单价">{{ formatMoney(detail.freightRate) }}</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="运费金额">{{ formatMoney(detail.freightAmount) }}</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="挂号费">{{ formatMoney(detail.registrationFee) }}</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="附加费">{{ formatMoney(detail.surchargeAmount) }}</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="应收总额">
|
||||||
|
<span class="payable">{{ formatMoney(detail.payableTotal) }}</span>
|
||||||
|
</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="命中说明" :span="2">{{ detail.matchMessage || '-' }}</el-descriptions-item>
|
||||||
|
</el-descriptions>
|
||||||
|
|
||||||
|
<el-table
|
||||||
|
v-if="detail.feeDetails && detail.feeDetails.length"
|
||||||
|
:data="detail.feeDetails"
|
||||||
|
border
|
||||||
|
size="small"
|
||||||
|
class="fee-table"
|
||||||
|
>
|
||||||
|
<el-table-column label="费用名称" min-width="140" show-overflow-tooltip>
|
||||||
|
<template #default="{ row }">{{ displayFeeName(row) }}</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column label="费用类型" width="110" align="center">
|
||||||
|
<template #default="{ row }">{{ feeTypeLabel(row.feeType) || row.feeType }}</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column label="金额" min-width="120" align="right">
|
||||||
|
<template #default="{ row }">{{ formatMoney(row.amount) }}</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column label="币种" width="90" align="center">
|
||||||
|
<template #default="{ row }">
|
||||||
|
<dict-tag :options="bms_currency" :value="displayCurrency(row.currency)" />
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column label="说明" min-width="160" show-overflow-tooltip>
|
||||||
|
<template #default="{ row }">{{ row.remark || '-' }}</template>
|
||||||
|
</el-table-column>
|
||||||
|
</el-table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</el-drawer>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup name="BillingBill">
|
||||||
|
import { listBill, getBill } from '@/api/price/billing'
|
||||||
|
|
||||||
|
const { bms_fee_type, bms_currency } = useDict('bms_fee_type', 'bms_currency')
|
||||||
|
const tableRef = ref()
|
||||||
|
const open = ref(false)
|
||||||
|
const title = ref('计费详情')
|
||||||
|
const loading = ref(false)
|
||||||
|
const detail = ref(null)
|
||||||
|
|
||||||
|
const columns = [
|
||||||
|
{ label: '订单号', prop: 'orderNo', minWidth: 140, showOverflowTooltip: true },
|
||||||
|
{ label: '运单号', prop: 'trackingNo', minWidth: 140, showOverflowTooltip: true },
|
||||||
|
{ label: '客户', prop: 'customerName', minWidth: 140, showOverflowTooltip: true },
|
||||||
|
{ label: '客户代码', prop: 'customerCode', width: 120 },
|
||||||
|
{ label: '产品', prop: 'product', minWidth: 160, slot: 'product' },
|
||||||
|
{ label: '国家', prop: 'country', minWidth: 130, slot: 'country' },
|
||||||
|
{ label: '件数', prop: 'pieces', align: 'center', width: 70 },
|
||||||
|
{ label: '计费重', prop: 'chargeWeight', align: 'center', width: 90 },
|
||||||
|
{ label: '应收总额', prop: 'payableTotal', align: 'right', width: 120, slot: 'payableTotal' },
|
||||||
|
{ label: '计价来源', prop: 'matchSource', align: 'center', width: 130, slot: 'matchSource' },
|
||||||
|
{ label: '下单时间', prop: 'orderTime', align: 'center', width: 170, parseTime: true },
|
||||||
|
{ label: '操作', prop: 'action', align: 'center', width: 90, fixed: 'right', slot: 'action', showInToolbar: false }
|
||||||
|
]
|
||||||
|
|
||||||
|
const searchColumns = [
|
||||||
|
{ label: '订单号', prop: 'orderNo', component: 'input', placeholder: '订单号', width: '160px' },
|
||||||
|
{ label: '运单号', prop: 'trackingNo', component: 'input', placeholder: '运单号', width: '160px' },
|
||||||
|
{ label: '客户代码', prop: 'customerCode', component: 'input', placeholder: '客户代码', width: '140px' },
|
||||||
|
{ label: '产品代码', prop: 'productCode', component: 'input', placeholder: '产品代码', width: '140px' }
|
||||||
|
]
|
||||||
|
|
||||||
|
function queryList(params) {
|
||||||
|
return listBill(params)
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleView(row) {
|
||||||
|
title.value = '计费详情 #' + (row.orderNo || row.billId)
|
||||||
|
open.value = true
|
||||||
|
loading.value = true
|
||||||
|
detail.value = null
|
||||||
|
getBill(row.billId).then(res => {
|
||||||
|
detail.value = res.data || null
|
||||||
|
}).finally(() => {
|
||||||
|
loading.value = false
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
function displayCustomer(row) {
|
||||||
|
if (row.customerName && row.customerCode) return row.customerName + ' (' + row.customerCode + ')'
|
||||||
|
return row.customerName || row.customerCode || row.customerId || '-'
|
||||||
|
}
|
||||||
|
|
||||||
|
function dimLabel(row) {
|
||||||
|
if (row.pkgLength == null && row.pkgWidth == null && row.pkgHeight == null) return '-'
|
||||||
|
return [row.pkgLength, row.pkgWidth, row.pkgHeight].map(v => v == null ? '-' : v).join(' × ')
|
||||||
|
}
|
||||||
|
|
||||||
|
function formatMoney(val) {
|
||||||
|
if (val === null || val === undefined || val === '') return '-'
|
||||||
|
const num = Number(val)
|
||||||
|
if (Number.isNaN(num)) return val
|
||||||
|
return num.toFixed(4)
|
||||||
|
}
|
||||||
|
|
||||||
|
function formatDate(val) {
|
||||||
|
if (!val) return '-'
|
||||||
|
const d = new Date(val)
|
||||||
|
if (Number.isNaN(d.getTime())) return val
|
||||||
|
return d.toISOString().slice(0, 10)
|
||||||
|
}
|
||||||
|
|
||||||
|
function formatDateTime(val) {
|
||||||
|
if (!val) return '-'
|
||||||
|
const d = new Date(val)
|
||||||
|
if (Number.isNaN(d.getTime())) return 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 sourceLabel(source) {
|
||||||
|
const map = {
|
||||||
|
PACKAGE_FIXED: '客户固定价套餐',
|
||||||
|
PACKAGE_DISCOUNT: '客户折扣套餐',
|
||||||
|
PRODUCT_DEFAULT: '产品默认价',
|
||||||
|
FIXED: '客户固定价套餐',
|
||||||
|
DISCOUNT: '客户折扣套餐'
|
||||||
|
}
|
||||||
|
return map[source] || source || '-'
|
||||||
|
}
|
||||||
|
|
||||||
|
function roundModeLabel(mode) {
|
||||||
|
const map = { UP: '向上取值', DOWN: '向下取整', HALF_UP: '四舍五入' }
|
||||||
|
return map[mode] || mode || '四舍五入'
|
||||||
|
}
|
||||||
|
|
||||||
|
function feeTypeLabel(type) {
|
||||||
|
const found = (bms_fee_type.value || []).find(d => d.value === type)
|
||||||
|
return found ? found.label : ''
|
||||||
|
}
|
||||||
|
|
||||||
|
function displayCurrency(v) {
|
||||||
|
if (!v || v === 'RMB' || v === 'rmb') return 'CNY'
|
||||||
|
return v
|
||||||
|
}
|
||||||
|
|
||||||
|
function displayFeeName(row) {
|
||||||
|
const typeLabel = feeTypeLabel(row.feeType)
|
||||||
|
const name = String(row.feeName || row.fee_name || '').trim()
|
||||||
|
const isSurcharge = row.feeType === 'SURCHARGE' || row.feeType === '附加费'
|
||||||
|
if (isSurcharge && name && name !== typeLabel && name !== 'SURCHARGE' && name !== '附加费') {
|
||||||
|
return name
|
||||||
|
}
|
||||||
|
return name || typeLabel || row.feeType || '-'
|
||||||
|
}
|
||||||
|
|
||||||
|
function sourceTagType(source) {
|
||||||
|
if (source === 'PACKAGE_FIXED' || source === 'FIXED') return 'success'
|
||||||
|
if (source === 'PACKAGE_DISCOUNT' || source === 'DISCOUNT') return 'warning'
|
||||||
|
if (source === 'PRODUCT_DEFAULT') return 'info'
|
||||||
|
return ''
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.billing-bill .payable {
|
||||||
|
color: #f56c6c;
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
.billing-bill .sec-title {
|
||||||
|
margin: 12px 0 8px;
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
.billing-bill .sec-title:first-child {
|
||||||
|
margin-top: 0;
|
||||||
|
}
|
||||||
|
.billing-bill .fee-table {
|
||||||
|
margin-top: 12px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
Reference in New Issue
Block a user