修改测试
This commit is contained in:
+1
-1
@@ -47,7 +47,7 @@ public class BillingController extends BaseController
|
||||
*/
|
||||
@PreAuthorize("@ss.hasPermi('price:billing:quote')")
|
||||
@GetMapping("/quote/{quoteId}")
|
||||
public AjaxResult getInfo(@PathVariable Long quoteId)
|
||||
public AjaxResult getInfo(@PathVariable String quoteId)
|
||||
{
|
||||
return success(tmsPriceQuoteService.getQuote(quoteId));
|
||||
}
|
||||
|
||||
@@ -16,6 +16,7 @@ public class PrcCustomerPriceSet extends BaseEntity
|
||||
private Long customerPricesetId;
|
||||
private Long priceSetId;
|
||||
private Long customerId;
|
||||
private String customerCode;
|
||||
private String customerName;
|
||||
/** 数字越小越优先 */
|
||||
private Integer bindPriority;
|
||||
|
||||
@@ -15,7 +15,7 @@ public class PrcQuote extends BaseEntity
|
||||
{
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private Long quoteId;
|
||||
private String quoteId;
|
||||
private String quoteKey;
|
||||
private Long customerId;
|
||||
private String productCode;
|
||||
|
||||
@@ -12,8 +12,8 @@ public class PrcQuoteFee implements Serializable
|
||||
{
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private Long feeId;
|
||||
private Long quoteId;
|
||||
private String feeId;
|
||||
private String quoteId;
|
||||
/** bms_fee_type: BASIC_FREIGHT / REGISTRATION_FEE / SURCHARGE */
|
||||
private String feeType;
|
||||
private String feeName;
|
||||
|
||||
+2
-1
@@ -12,9 +12,10 @@ public class TmsPriceQuoteRequest implements Serializable
|
||||
{
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@NotNull(message = "customerId is required")
|
||||
private Long customerId;
|
||||
|
||||
private String customerCode;
|
||||
|
||||
@NotBlank(message = "productCode is required")
|
||||
private String productCode;
|
||||
|
||||
|
||||
+1
-1
@@ -52,7 +52,7 @@ public class TmsPriceQuoteResult implements Serializable
|
||||
private String roundMode;
|
||||
/** 费用明细:运费/挂号费各一行,附加费按具体名称各一行 */
|
||||
private List<TmsPriceQuoteFeeLine> feeDetails;
|
||||
private Long quoteId;
|
||||
private String quoteId;
|
||||
/** true=命中已落库试算 */
|
||||
private Boolean fromCache;
|
||||
}
|
||||
|
||||
+8
@@ -30,6 +30,10 @@ public interface PrcCustomerPriceSetMapper
|
||||
@Param("excludeId") Long excludeId,
|
||||
@Param("excludePriceSetId") Long excludePriceSetId);
|
||||
|
||||
public int countByCustomerCode(@Param("customerCode") String customerCode,
|
||||
@Param("excludeId") Long excludeId,
|
||||
@Param("excludePriceSetId") Long excludePriceSetId);
|
||||
|
||||
public int countOverlap(@Param("customerId") Long customerId,
|
||||
@Param("priceSetId") Long priceSetId,
|
||||
@Param("beginDate") java.util.Date beginDate,
|
||||
@@ -41,4 +45,8 @@ public interface PrcCustomerPriceSetMapper
|
||||
public java.util.List<PrcCustomerPriceSet> selectEffectiveByCustomer(
|
||||
@Param("customerId") Long customerId,
|
||||
@Param("bizDate") java.util.Date bizDate);
|
||||
|
||||
public java.util.List<PrcCustomerPriceSet> selectEffectiveByCustomerCode(
|
||||
@Param("customerCode") String customerCode,
|
||||
@Param("bizDate") java.util.Date bizDate);
|
||||
}
|
||||
|
||||
@@ -7,11 +7,11 @@ import com.ruoyi.price.domain.PrcQuoteFee;
|
||||
/** billing quote fee detail mapper */
|
||||
public interface PrcQuoteFeeMapper
|
||||
{
|
||||
public List<PrcQuoteFee> selectByQuoteId(Long quoteId);
|
||||
public List<PrcQuoteFee> selectByQuoteId(String quoteId);
|
||||
|
||||
public int insertPrcQuoteFee(PrcQuoteFee fee);
|
||||
|
||||
public int insertBatch(@Param("list") List<PrcQuoteFee> fees);
|
||||
|
||||
public int deleteByQuoteId(Long quoteId);
|
||||
public int deleteByQuoteId(String quoteId);
|
||||
}
|
||||
|
||||
@@ -10,13 +10,13 @@ public interface PrcQuoteMapper
|
||||
{
|
||||
public PrcQuote selectPrcQuoteByKey(String quoteKey);
|
||||
|
||||
public PrcQuote selectPrcQuoteById(Long quoteId);
|
||||
public PrcQuote selectPrcQuoteById(String quoteId);
|
||||
|
||||
public List<PrcQuote> selectPrcQuoteList(PrcQuote quote);
|
||||
|
||||
public int insertPrcQuote(PrcQuote quote);
|
||||
|
||||
public int updateQuoteAmounts(@Param("quoteId") Long quoteId,
|
||||
public int updateQuoteAmounts(@Param("quoteId") String quoteId,
|
||||
@Param("surchargeAmount") BigDecimal surchargeAmount,
|
||||
@Param("payableTotal") BigDecimal payableTotal);
|
||||
}
|
||||
|
||||
+1
-1
@@ -20,5 +20,5 @@ public interface ITmsPriceQuoteService
|
||||
|
||||
List<PrcQuote> selectQuoteList(PrcQuote query);
|
||||
|
||||
TmsPriceQuoteResult getQuote(Long quoteId);
|
||||
TmsPriceQuoteResult getQuote(String quoteId);
|
||||
}
|
||||
|
||||
+29
-9
@@ -1,11 +1,13 @@
|
||||
package com.ruoyi.price.service.impl;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.zip.CRC32;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
@@ -406,21 +408,21 @@ public class PrcPriceSetServiceImpl implements IPrcPriceSetService
|
||||
}
|
||||
|
||||
List<PrcCustomerPriceSet> customers = filterCustomers(set.getCustomers());
|
||||
Set<Long> seenCustomers = new HashSet<Long>();
|
||||
Set<String> seenCustomers = new HashSet<String>();
|
||||
int bound = 0;
|
||||
boolean dupInSet = false;
|
||||
for (PrcCustomerPriceSet c : customers)
|
||||
{
|
||||
if (c.getCustomerId() == null)
|
||||
if (StringUtils.isEmpty(c.getCustomerCode()))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (!seenCustomers.add(c.getCustomerId()))
|
||||
if (!seenCustomers.add(c.getCustomerCode()))
|
||||
{
|
||||
dupInSet = true;
|
||||
continue;
|
||||
}
|
||||
bound += customerMapper.countByCustomerId(c.getCustomerId(), c.getCustomerPricesetId(),
|
||||
bound += customerMapper.countByCustomerCode(c.getCustomerCode(), c.getCustomerPricesetId(),
|
||||
set.getPriceSetId());
|
||||
}
|
||||
if (dupInSet || bound > 0)
|
||||
@@ -581,10 +583,10 @@ public class PrcPriceSetServiceImpl implements IPrcPriceSetService
|
||||
if (set.getCustomers() != null)
|
||||
{
|
||||
customerMapper.deletePrcCustomerPriceSetByPriceSetId(set.getPriceSetId());
|
||||
Set<Long> seenCustomers = new HashSet<Long>();
|
||||
Set<String> seenCustomers = new HashSet<String>();
|
||||
for (PrcCustomerPriceSet c : filterCustomers(set.getCustomers()))
|
||||
{
|
||||
if (c.getCustomerId() != null && !seenCustomers.add(c.getCustomerId()))
|
||||
if (StringUtils.isNotEmpty(c.getCustomerCode()) && !seenCustomers.add(c.getCustomerCode()))
|
||||
{
|
||||
throw new ServiceException(MessageUtils.message("price.set.customer.alreadyBound"));
|
||||
}
|
||||
@@ -759,7 +761,7 @@ public class PrcPriceSetServiceImpl implements IPrcPriceSetService
|
||||
|
||||
private void validateCustomer(PrcCustomerPriceSet customer, PrcPriceSet set)
|
||||
{
|
||||
if (customer.getCustomerId() == null || customer.getCustomerId().longValue() <= 0)
|
||||
if (StringUtils.isEmpty(customer.getCustomerCode()))
|
||||
{
|
||||
throw new ServiceException(MessageUtils.message("price.set.customer.customerId.empty"));
|
||||
}
|
||||
@@ -779,12 +781,30 @@ public class PrcPriceSetServiceImpl implements IPrcPriceSetService
|
||||
{
|
||||
throw new ServiceException(MessageUtils.message("price.set.customer.priority.invalid"));
|
||||
}
|
||||
int exists = customerMapper.countByCustomerId(customer.getCustomerId(),
|
||||
int exists = customerMapper.countByCustomerCode(customer.getCustomerCode(),
|
||||
customer.getCustomerPricesetId(), null);
|
||||
if (exists > 0)
|
||||
{
|
||||
throw new ServiceException(MessageUtils.message("price.set.customer.alreadyBound"));
|
||||
}
|
||||
customer.setCustomerId(resolveNumericCustomerId(customer));
|
||||
}
|
||||
|
||||
private Long resolveNumericCustomerId(PrcCustomerPriceSet customer)
|
||||
{
|
||||
if (customer.getCustomerId() != null && customer.getCustomerId().longValue() > 0)
|
||||
{
|
||||
return customer.getCustomerId();
|
||||
}
|
||||
return hashCustomerCode(customer.getCustomerCode());
|
||||
}
|
||||
|
||||
private static Long hashCustomerCode(String customerCode)
|
||||
{
|
||||
CRC32 crc = new CRC32();
|
||||
crc.update(customerCode.getBytes(StandardCharsets.UTF_8));
|
||||
long v = crc.getValue();
|
||||
return v == 0L ? Long.valueOf(1L) : Long.valueOf(v);
|
||||
}
|
||||
|
||||
private void assertBasicEditable(PrcPriceSet db)
|
||||
@@ -882,7 +902,7 @@ public class PrcPriceSetServiceImpl implements IPrcPriceSetService
|
||||
}
|
||||
for (PrcCustomerPriceSet c : customers)
|
||||
{
|
||||
if (c != null && c.getCustomerId() != null && c.getCustomerId().longValue() > 0)
|
||||
if (c != null && StringUtils.isNotEmpty(c.getCustomerCode()))
|
||||
{
|
||||
list.add(c);
|
||||
}
|
||||
|
||||
+19
-7
@@ -9,6 +9,7 @@ import java.util.Date;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.dao.DuplicateKeyException;
|
||||
import org.springframework.stereotype.Service;
|
||||
@@ -119,7 +120,7 @@ public class TmsPriceQuoteServiceImpl implements ITmsPriceQuoteService
|
||||
}
|
||||
|
||||
@Override
|
||||
public TmsPriceQuoteResult getQuote(Long quoteId)
|
||||
public TmsPriceQuoteResult getQuote(String quoteId)
|
||||
{
|
||||
if (quoteId == null)
|
||||
{
|
||||
@@ -152,8 +153,17 @@ public class TmsPriceQuoteServiceImpl implements ITmsPriceQuoteService
|
||||
}
|
||||
|
||||
String productName = resolveProductName(productCode, bizDate);
|
||||
List<PrcCustomerPriceSet> binds = customerPriceSetMapper.selectEffectiveByCustomer(
|
||||
List<PrcCustomerPriceSet> binds;
|
||||
if (StringUtils.isNotEmpty(request.getCustomerCode()))
|
||||
{
|
||||
binds = customerPriceSetMapper.selectEffectiveByCustomerCode(
|
||||
request.getCustomerCode(), bizDate);
|
||||
}
|
||||
else
|
||||
{
|
||||
binds = customerPriceSetMapper.selectEffectiveByCustomer(
|
||||
request.getCustomerId(), bizDate);
|
||||
}
|
||||
|
||||
if (binds != null)
|
||||
{
|
||||
@@ -455,8 +465,9 @@ public class TmsPriceQuoteServiceImpl implements ITmsPriceQuoteService
|
||||
Date bizDate, TmsPriceQuoteResult result)
|
||||
{
|
||||
PrcQuote quote = new PrcQuote();
|
||||
quote.setQuoteId(UUID.randomUUID().toString());
|
||||
quote.setQuoteKey(quoteKey);
|
||||
quote.setCustomerId(request.getCustomerId());
|
||||
quote.setCustomerId(request.getCustomerId() == null ? Long.valueOf(0L) : request.getCustomerId());
|
||||
quote.setProductCode(result.getProductCode());
|
||||
quote.setProductName(result.getProductName());
|
||||
quote.setCountryCode(result.getCountryCode());
|
||||
@@ -538,7 +549,7 @@ public class TmsPriceQuoteServiceImpl implements ITmsPriceQuoteService
|
||||
return false;
|
||||
}
|
||||
|
||||
private void replaceQuoteFees(Long quoteId, TmsPriceQuoteResult result)
|
||||
private void replaceQuoteFees(String quoteId, TmsPriceQuoteResult result)
|
||||
{
|
||||
quoteFeeMapper.deleteByQuoteId(quoteId);
|
||||
List<PrcQuoteFee> fees = toFeeRows(quoteId, result);
|
||||
@@ -549,7 +560,7 @@ public class TmsPriceQuoteServiceImpl implements ITmsPriceQuoteService
|
||||
quoteMapper.updateQuoteAmounts(quoteId, result.getSurchargeAmount(), result.getPayableTotal());
|
||||
}
|
||||
|
||||
private List<PrcQuoteFee> toFeeRows(Long quoteId, TmsPriceQuoteResult result)
|
||||
private List<PrcQuoteFee> toFeeRows(String quoteId, TmsPriceQuoteResult result)
|
||||
{
|
||||
List<PrcQuoteFee> fees = new ArrayList<PrcQuoteFee>();
|
||||
if (result.getFeeDetails() == null)
|
||||
@@ -664,7 +675,8 @@ public class TmsPriceQuoteServiceImpl implements ITmsPriceQuoteService
|
||||
}
|
||||
String countryName = emptyToNull(request.getCountryName());
|
||||
String biz = new SimpleDateFormat("yyyy-MM-dd").format(bizDate);
|
||||
String raw = request.getCustomerId() + "|"
|
||||
String raw = (StringUtils.isNotEmpty(request.getCustomerCode())
|
||||
? request.getCustomerCode() : String.valueOf(request.getCustomerId())) + "|"
|
||||
+ request.getProductCode().trim() + "|"
|
||||
+ nvlStr(countryCode) + "|"
|
||||
+ nvlStr(countryName) + "|"
|
||||
@@ -758,7 +770,7 @@ public class TmsPriceQuoteServiceImpl implements ITmsPriceQuoteService
|
||||
{
|
||||
throw new ServiceException(MessageUtils.message("price.quote.requestBodyRequired"));
|
||||
}
|
||||
if (request.getCustomerId() == null)
|
||||
if (StringUtils.isEmpty(request.getCustomerCode()) && request.getCustomerId() == null)
|
||||
{
|
||||
throw new ServiceException(MessageUtils.message("price.quote.customerIdRequired"));
|
||||
}
|
||||
|
||||
+33
-2
@@ -8,6 +8,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
<id property="customerPricesetId" column="customer_priceset_id" />
|
||||
<result property="priceSetId" column="price_set_id" />
|
||||
<result property="customerId" column="customer_id" />
|
||||
<result property="customerCode" column="customer_code" />
|
||||
<result property="customerName" column="customer_name" />
|
||||
<result property="bindPriority" column="bind_priority" />
|
||||
<result property="prBegindate" column="pr_begindate" />
|
||||
@@ -20,7 +21,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
</resultMap>
|
||||
|
||||
<sql id="selectPrcCustomerPriceSetVo">
|
||||
select customer_priceset_id, price_set_id, customer_id, customer_name, bind_priority,
|
||||
select customer_priceset_id, price_set_id, customer_id, customer_code, customer_name, bind_priority,
|
||||
pr_begindate, pr_enddate, price_set_note,
|
||||
created_by, created_at, updated_by, updated_at
|
||||
from prc_customer_price_set
|
||||
@@ -40,6 +41,9 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
<if test="customerId != null">
|
||||
AND customer_id = #{customerId}
|
||||
</if>
|
||||
<if test="customerCode != null and customerCode != ''">
|
||||
AND customer_code = #{customerCode}
|
||||
</if>
|
||||
<if test="customerName != null and customerName != ''">
|
||||
AND customer_name like concat('%', #{customerName}, '%')
|
||||
</if>
|
||||
@@ -62,6 +66,17 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
</if>
|
||||
</select>
|
||||
|
||||
<select id="countByCustomerCode" resultType="int">
|
||||
select count(1) from prc_customer_price_set
|
||||
where customer_code = #{customerCode}
|
||||
<if test="excludeId != null">
|
||||
AND customer_priceset_id <> #{excludeId}
|
||||
</if>
|
||||
<if test="excludePriceSetId != null">
|
||||
AND price_set_id <> #{excludePriceSetId}
|
||||
</if>
|
||||
</select>
|
||||
|
||||
<select id="countOverlap" resultType="int">
|
||||
select count(1)
|
||||
from prc_customer_price_set c
|
||||
@@ -76,7 +91,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
</select>
|
||||
|
||||
<select id="selectEffectiveByCustomer" resultMap="PrcCustomerPriceSetResult">
|
||||
select c.customer_priceset_id, c.price_set_id, c.customer_id, c.customer_name, c.bind_priority,
|
||||
select c.customer_priceset_id, c.price_set_id, c.customer_id, c.customer_code, c.customer_name, c.bind_priority,
|
||||
c.pr_begindate, c.pr_enddate, c.price_set_note,
|
||||
c.created_by, c.created_at, c.updated_by, c.updated_at
|
||||
from prc_customer_price_set c
|
||||
@@ -88,10 +103,24 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
order by c.bind_priority asc, c.pr_begindate desc, c.customer_priceset_id asc
|
||||
</select>
|
||||
|
||||
<select id="selectEffectiveByCustomerCode" resultMap="PrcCustomerPriceSetResult">
|
||||
select c.customer_priceset_id, c.price_set_id, c.customer_id, c.customer_code, c.customer_name, c.bind_priority,
|
||||
c.pr_begindate, c.pr_enddate, c.price_set_note,
|
||||
c.created_by, c.created_at, c.updated_by, c.updated_at
|
||||
from prc_customer_price_set c
|
||||
inner join prc_price_set s on s.price_set_id = c.price_set_id
|
||||
where c.customer_code = #{customerCode}
|
||||
and s.status = 'E'
|
||||
and c.pr_begindate <= #{bizDate}
|
||||
and ifnull(c.pr_enddate, '9999-12-31') >= #{bizDate}
|
||||
order by c.bind_priority asc, c.pr_begindate desc, c.customer_priceset_id asc
|
||||
</select>
|
||||
|
||||
<insert id="insertPrcCustomerPriceSet" parameterType="PrcCustomerPriceSet" useGeneratedKeys="true" keyProperty="customerPricesetId">
|
||||
insert into prc_customer_price_set (
|
||||
<if test="priceSetId != null">price_set_id,</if>
|
||||
<if test="customerId != null">customer_id,</if>
|
||||
<if test="customerCode != null and customerCode != ''">customer_code,</if>
|
||||
<if test="customerName != null">customer_name,</if>
|
||||
<if test="bindPriority != null">bind_priority,</if>
|
||||
<if test="prBegindate != null">pr_begindate,</if>
|
||||
@@ -102,6 +131,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
) values (
|
||||
<if test="priceSetId != null">#{priceSetId},</if>
|
||||
<if test="customerId != null">#{customerId},</if>
|
||||
<if test="customerCode != null and customerCode != ''">#{customerCode},</if>
|
||||
<if test="customerName != null">#{customerName},</if>
|
||||
<if test="bindPriority != null">#{bindPriority},</if>
|
||||
<if test="prBegindate != null">#{prBegindate},</if>
|
||||
@@ -116,6 +146,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
update prc_customer_price_set
|
||||
<set>
|
||||
<if test="customerId != null">customer_id = #{customerId},</if>
|
||||
<if test="customerCode != null">customer_code = #{customerCode},</if>
|
||||
<if test="customerName != null">customer_name = #{customerName},</if>
|
||||
<if test="bindPriority != null">bind_priority = #{bindPriority},</if>
|
||||
<if test="prBegindate != null">pr_begindate = #{prBegindate},</if>
|
||||
|
||||
@@ -17,32 +17,32 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
<result property="createdAt" column="created_at" />
|
||||
</resultMap>
|
||||
|
||||
<select id="selectByQuoteId" parameterType="Long" resultMap="PrcQuoteFeeResult">
|
||||
<select id="selectByQuoteId" parameterType="String" resultMap="PrcQuoteFeeResult">
|
||||
select fee_id, quote_id, fee_type, fee_name, sc_id, amount, currency, round_mode, remark, created_at
|
||||
from prc_quote_fee
|
||||
where quote_id = #{quoteId}
|
||||
order by field(fee_type, 'BASIC_FREIGHT', 'REGISTRATION_FEE', 'SURCHARGE'), fee_id
|
||||
</select>
|
||||
|
||||
<insert id="insertPrcQuoteFee" parameterType="PrcQuoteFee" useGeneratedKeys="true" keyProperty="feeId">
|
||||
<insert id="insertPrcQuoteFee" parameterType="PrcQuoteFee">
|
||||
insert into prc_quote_fee (
|
||||
quote_id, fee_type, fee_name, sc_id, amount, currency, round_mode, remark, created_at
|
||||
fee_id, quote_id, fee_type, fee_name, sc_id, amount, currency, round_mode, remark, created_at
|
||||
) values (
|
||||
#{quoteId}, #{feeType}, #{feeName}, #{scId}, #{amount}, #{currency}, #{roundMode}, #{remark}, sysdate()
|
||||
#{feeId}, #{quoteId}, #{feeType}, #{feeName}, #{scId}, #{amount}, #{currency}, #{roundMode}, #{remark}, sysdate()
|
||||
)
|
||||
</insert>
|
||||
|
||||
<insert id="insertBatch" parameterType="java.util.List">
|
||||
insert into prc_quote_fee (
|
||||
quote_id, fee_type, fee_name, sc_id, amount, currency, round_mode, remark, created_at
|
||||
fee_id, quote_id, fee_type, fee_name, sc_id, amount, currency, round_mode, remark, created_at
|
||||
) values
|
||||
<foreach collection="list" item="item" separator=",">
|
||||
(#{item.quoteId}, #{item.feeType}, #{item.feeName}, #{item.scId}, #{item.amount},
|
||||
(#{item.feeId}, #{item.quoteId}, #{item.feeType}, #{item.feeName}, #{item.scId}, #{item.amount},
|
||||
#{item.currency}, #{item.roundMode}, #{item.remark}, sysdate())
|
||||
</foreach>
|
||||
</insert>
|
||||
|
||||
<delete id="deleteByQuoteId" parameterType="Long">
|
||||
<delete id="deleteByQuoteId" parameterType="String">
|
||||
delete from prc_quote_fee where quote_id = #{quoteId}
|
||||
</delete>
|
||||
</mapper>
|
||||
|
||||
@@ -61,7 +61,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
where quote_key = #{quoteKey}
|
||||
</select>
|
||||
|
||||
<select id="selectPrcQuoteById" parameterType="Long" resultMap="PrcQuoteResult">
|
||||
<select id="selectPrcQuoteById" parameterType="String" resultMap="PrcQuoteResult">
|
||||
<include refid="selectPrcQuoteVo"/>
|
||||
where quote_id = #{quoteId}
|
||||
</select>
|
||||
@@ -100,9 +100,9 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
order by quote_id desc
|
||||
</select>
|
||||
|
||||
<insert id="insertPrcQuote" parameterType="PrcQuote" useGeneratedKeys="true" keyProperty="quoteId">
|
||||
<insert id="insertPrcQuote" parameterType="PrcQuote">
|
||||
insert into prc_quote (
|
||||
quote_key, customer_id, product_code, product_name,
|
||||
quote_id, quote_key, customer_id, 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,
|
||||
@@ -111,7 +111,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
freight_amount, surcharge_amount, payable_total, currency, round_mode,
|
||||
created_at
|
||||
) values (
|
||||
#{quoteKey}, #{customerId}, #{productCode}, #{productName},
|
||||
#{quoteId}, #{quoteKey}, #{customerId}, #{productCode}, #{productName},
|
||||
#{countryCode}, #{countryName}, #{weight}, #{bizDate}, #{tmsId},
|
||||
#{matchSource}, #{matchMessage}, #{priceSetId}, #{priceSetCode}, #{priceSetName},
|
||||
#{setType}, #{bindPriority}, #{customerPricesetId}, #{productCountryId},
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
-- prc_customer_price_set add customer_code
|
||||
SET NAMES utf8mb4;
|
||||
|
||||
ALTER TABLE prc_customer_price_set
|
||||
ADD COLUMN customer_code varchar(50) DEFAULT NULL COMMENT '客户代码' AFTER customer_id;
|
||||
|
||||
UPDATE prc_customer_price_set cps
|
||||
INNER JOIN bms_customer c ON c.customer_id = cps.customer_id
|
||||
SET cps.customer_code = c.customer_code
|
||||
WHERE cps.customer_code IS NULL OR cps.customer_code = '';
|
||||
@@ -61,7 +61,8 @@ CREATE TABLE IF NOT EXISTS prc_price_set_detail (
|
||||
CREATE TABLE IF NOT EXISTS prc_customer_price_set (
|
||||
customer_priceset_id BIGINT(20) NOT NULL AUTO_INCREMENT COMMENT '客户价格套餐id',
|
||||
price_set_id BIGINT(20) NOT NULL COMMENT '价格套餐id',
|
||||
customer_id BIGINT(20) NOT NULL COMMENT '客户id',
|
||||
customer_id BIGINT(20) DEFAULT NULL COMMENT '客户id',
|
||||
customer_code VARCHAR(50) DEFAULT NULL COMMENT '客户代码',
|
||||
customer_name VARCHAR(100) DEFAULT NULL COMMENT '客户名称(展示)',
|
||||
bind_priority INT(11) NOT NULL DEFAULT 1 COMMENT '优先级,数字越小越优先',
|
||||
pr_begindate DATETIME NOT NULL COMMENT '价格开始生效日期',
|
||||
@@ -72,7 +73,7 @@ CREATE TABLE IF NOT EXISTS prc_customer_price_set (
|
||||
updated_by VARCHAR(64) DEFAULT '' COMMENT '更新人',
|
||||
updated_at DATETIME DEFAULT NULL COMMENT '更新时间',
|
||||
PRIMARY KEY (customer_priceset_id),
|
||||
UNIQUE KEY uk_customer_one_set (customer_id),
|
||||
UNIQUE KEY uk_customer_one_set (customer_code),
|
||||
INDEX idx_customer_set (customer_id, pr_begindate, pr_enddate),
|
||||
INDEX idx_cps_set (price_set_id),
|
||||
CONSTRAINT fk_customer_price_set FOREIGN KEY (price_set_id) REFERENCES prc_price_set (price_set_id) ON DELETE RESTRICT
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
-- ======================================================================
|
||||
-- prc_quote / prc_quote_fee 主键改 UUID 改造(VARCHAR(36))
|
||||
--
|
||||
-- 背景:测试大数据量场景下 UUID 主键的查询性能
|
||||
-- 风险:会清空 prc_quote / prc_quote_fee 全部数据
|
||||
-- 备份:quote_uuid_backup.sql(保留原始 schema)
|
||||
--
|
||||
-- 关键顺序(踩坑总结):
|
||||
-- 1. DROP FOREIGN KEY
|
||||
-- 2. TRUNCATE TABLE
|
||||
-- 3. **先 MODIFY 列去掉 AUTO_INCREMENT**,再 DROP PRIMARY KEY
|
||||
-- 否则 InnoDB 报 1075「auto column must be defined as a key」
|
||||
-- 4. 再 MODIFY quote_id 列 / ADD PRIMARY KEY
|
||||
-- 5. ADD FOREIGN KEY 时**会自动创建 quote_id 索引**,不要额外 ADD INDEX
|
||||
-- 否则报 1061「Duplicate key name」
|
||||
--
|
||||
-- 回滚:参考 quote_uuid_backup.sql,重建表结构即可
|
||||
-- ======================================================================
|
||||
|
||||
-- === 1. 解除外键 ===
|
||||
ALTER TABLE prc_quote_fee DROP FOREIGN KEY fk_quote_fee_quote;
|
||||
|
||||
-- === 2. 清空数据 ===
|
||||
TRUNCATE TABLE prc_quote_fee;
|
||||
TRUNCATE TABLE prc_quote;
|
||||
|
||||
-- === 3. prc_quote: PK 改 UUID ===
|
||||
-- 顺序很关键:先 MODIFY 列去掉 AUTO_INCREMENT
|
||||
ALTER TABLE prc_quote MODIFY quote_id VARCHAR(36) NOT NULL COMMENT '试算ID(UUID)';
|
||||
ALTER TABLE prc_quote DROP PRIMARY KEY;
|
||||
ALTER TABLE prc_quote ADD PRIMARY KEY (quote_id);
|
||||
|
||||
-- === 4. prc_quote_fee: PK 改 UUID; quote_id 列同步 ===
|
||||
ALTER TABLE prc_quote_fee MODIFY fee_id VARCHAR(36) NOT NULL COMMENT '费用明细ID(UUID)';
|
||||
ALTER TABLE prc_quote_fee DROP PRIMARY KEY;
|
||||
ALTER TABLE prc_quote_fee MODIFY quote_id VARCHAR(36) NOT NULL COMMENT '试算ID(UUID)';
|
||||
ALTER TABLE prc_quote_fee ADD PRIMARY KEY (fee_id);
|
||||
|
||||
-- === 5. 重建 FK(自动创建 idx_quote_fee_quote_id 索引,无需手动加) ===
|
||||
ALTER TABLE prc_quote_fee ADD CONSTRAINT fk_quote_fee_quote
|
||||
FOREIGN KEY (quote_id) REFERENCES prc_quote (quote_id) ON DELETE CASCADE;
|
||||
@@ -0,0 +1,61 @@
|
||||
CREATE TABLE `prc_quote` (
|
||||
`quote_id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '试算ID',
|
||||
`quote_key` char(32) COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '试算指纹 MD5(客户|产品|国家|重量|计费日期)',
|
||||
`customer_id` bigint(20) NOT NULL COMMENT '客户ID',
|
||||
`product_code` varchar(20) COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '产品代码',
|
||||
`product_name` varchar(100) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '产品名称',
|
||||
`country_code` char(2) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '国家二字码',
|
||||
`country_name` varchar(50) COLLATE utf8mb4_unicode_ci 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) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '命中来源 PACKAGE_FIXED/套餐固定价 PACKAGE_DISCOUNT/套餐折扣 PRODUCT_DEFAULT/产品默认价',
|
||||
`match_message` varchar(200) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '命中说明',
|
||||
`price_set_id` bigint(20) DEFAULT NULL COMMENT '价格套餐ID',
|
||||
`price_set_code` varchar(20) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '套餐编码',
|
||||
`price_set_name` varchar(50) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '套餐名称',
|
||||
`set_type` varchar(10) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '计价类型 FIXED=固定价 DISCOUNT=折扣',
|
||||
`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) COLLATE utf8mb4_unicode_ci 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) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT 'RMB' COMMENT '币种',
|
||||
`round_mode` varchar(20) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT 'HALF_UP' COMMENT '取值方式(字典bms_round_mode)',
|
||||
`created_by` varchar(64) COLLATE utf8mb4_unicode_ci DEFAULT '' COMMENT '创建人',
|
||||
`created_at` datetime DEFAULT NULL COMMENT '创建时间',
|
||||
`updated_by` varchar(64) COLLATE utf8mb4_unicode_ci DEFAULT '' COMMENT '更新人',
|
||||
`updated_at` datetime DEFAULT NULL COMMENT '更新时间',
|
||||
PRIMARY KEY (`quote_id`),
|
||||
UNIQUE KEY `uk_quote_key` (`quote_key`),
|
||||
KEY `idx_quote_customer` (`customer_id`,`biz_date`),
|
||||
KEY `idx_quote_product` (`product_code`,`country_code`)
|
||||
) ENGINE=InnoDB AUTO_INCREMENT=150000 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='计费试算主表';
|
||||
|
||||
CREATE TABLE `prc_quote_fee` (
|
||||
`fee_id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '费用明细ID',
|
||||
`quote_id` bigint(20) NOT NULL COMMENT '试算ID',
|
||||
`fee_type` varchar(30) COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '费用类型(字典bms_fee_type)',
|
||||
`fee_name` varchar(100) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '费用名称(附加费取配置名称)',
|
||||
`sc_id` bigint(20) NOT NULL DEFAULT '0' COMMENT '附加费配置ID,运费/挂号费为0',
|
||||
`amount` decimal(12,2) NOT NULL DEFAULT '0.00' COMMENT '金额',
|
||||
`currency` varchar(10) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT 'RMB' COMMENT '币种',
|
||||
`round_mode` varchar(20) COLLATE utf8mb4_unicode_ci DEFAULT 'HALF_UP' COMMENT '取值方式(字典bms_round_mode)',
|
||||
`remark` varchar(500) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '备注(附加费明细摘要)',
|
||||
`created_at` datetime DEFAULT NULL COMMENT '创建时间',
|
||||
PRIMARY KEY (`fee_id`),
|
||||
UNIQUE KEY `uk_quote_fee_item` (`quote_id`,`fee_type`,`sc_id`),
|
||||
KEY `idx_quote_fee_type` (`fee_type`),
|
||||
KEY `idx_quote_fee_quote_id` (`quote_id`),
|
||||
CONSTRAINT `fk_quote_fee_quote` FOREIGN KEY (`quote_id`) REFERENCES `prc_quote` (`quote_id`) ON DELETE CASCADE
|
||||
) ENGINE=InnoDB AUTO_INCREMENT=236791 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='计费试算费用明细-按费用类型一行';
|
||||
@@ -0,0 +1,190 @@
|
||||
<template>
|
||||
<el-dialog :title="title" v-model="visible" width="640px" append-to-body>
|
||||
<basic-form ref="formRef" v-model="form" :schemas="schemas" label-width="100px" />
|
||||
<template #footer>
|
||||
<el-button type="primary" @click="submitForm">确 定</el-button>
|
||||
<el-button @click="visible = false">取 消</el-button>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import BasicForm from '@/components/BasicForm'
|
||||
import { getSurcharge, addSurcharge, updateSurcharge } from '@/api/price/surcharge'
|
||||
import { listRegionOptions } from '@/api/data/region'
|
||||
|
||||
const emit = defineEmits(['success'])
|
||||
const { proxy } = getCurrentInstance()
|
||||
|
||||
const formRef = ref()
|
||||
const visible = ref(false)
|
||||
const title = ref('')
|
||||
const form = ref(emptyForm())
|
||||
const regionOptions = ref([])
|
||||
|
||||
const countrySelectOptions = computed(() => {
|
||||
const all = [{ label: "全部国家", value: '' }]
|
||||
return all.concat((regionOptions.value || []).map(r => ({
|
||||
label: regionLabel(r),
|
||||
value: r.countryCode2
|
||||
})))
|
||||
})
|
||||
|
||||
const schemas = computed(() => [
|
||||
{
|
||||
label: "附加费名称",
|
||||
prop: 'scName',
|
||||
component: 'input',
|
||||
placeholder: "如 燃油附加费",
|
||||
span: 12,
|
||||
width: '100%',
|
||||
props: { maxlength: 100 },
|
||||
rules: [{ required: true, message: "附加费名称不能为空", trigger: 'blur' }]
|
||||
},
|
||||
{
|
||||
label: "费用类型",
|
||||
prop: 'feeType',
|
||||
component: 'select',
|
||||
placeholder: "请选择",
|
||||
dict: 'bms_fee_type',
|
||||
span: 12,
|
||||
width: '100%',
|
||||
disabled: true,
|
||||
rules: [{ required: true, message: "请选择费用类型", trigger: 'change' }]
|
||||
},
|
||||
{
|
||||
label: "计费方式",
|
||||
prop: 'chargeType',
|
||||
component: 'select',
|
||||
placeholder: "请选择",
|
||||
dict: 'bms_charge_type',
|
||||
span: 12,
|
||||
width: '100%',
|
||||
rules: [{ required: true, message: "请选择计费方式", trigger: 'change' }]
|
||||
},
|
||||
{
|
||||
label: "计费数值",
|
||||
prop: 'chargeValue',
|
||||
component: 'inputNumber',
|
||||
span: 12,
|
||||
width: '100%',
|
||||
props: { min: 0, precision: 6, step: 1, controlsPosition: 'right' },
|
||||
rules: [{ required: true, message: "计费数值不能为空", trigger: 'blur' }]
|
||||
},
|
||||
{
|
||||
label: "币种",
|
||||
prop: 'currency',
|
||||
component: 'select',
|
||||
placeholder: "请选择",
|
||||
dict: 'bms_currency',
|
||||
span: 12,
|
||||
width: '100%'
|
||||
},
|
||||
{
|
||||
label: "取值方式",
|
||||
prop: 'roundMode',
|
||||
component: 'select',
|
||||
placeholder: "请选择",
|
||||
dict: 'bms_round_mode',
|
||||
span: 12,
|
||||
width: '100%',
|
||||
rules: [{ required: true, message: "请选择取值方式", trigger: 'change' }]
|
||||
},
|
||||
{
|
||||
label: "适用国家",
|
||||
prop: 'countryCode',
|
||||
component: 'select',
|
||||
placeholder: "全部国家",
|
||||
options: countrySelectOptions.value,
|
||||
span: 12,
|
||||
width: '100%',
|
||||
props: { filterable: true, clearable: true }
|
||||
},
|
||||
{
|
||||
label: "状态",
|
||||
prop: 'ssCode',
|
||||
component: 'radio',
|
||||
span: 12,
|
||||
options: [
|
||||
{ label: "有效", value: 'on' },
|
||||
{ label: "停用", value: 'of' }
|
||||
]
|
||||
},
|
||||
{
|
||||
label: "备注",
|
||||
prop: 'scNote',
|
||||
component: 'textarea',
|
||||
placeholder: "请输入备注",
|
||||
span: 24,
|
||||
width: '100%',
|
||||
props: { rows: 2, maxlength: 500 }
|
||||
}
|
||||
])
|
||||
|
||||
function emptyForm() {
|
||||
return {
|
||||
scId: undefined,
|
||||
scName: undefined,
|
||||
feeType: 'SURCHARGE',
|
||||
chargeType: 'FIXED',
|
||||
chargeValue: undefined,
|
||||
currency: 'CNY',
|
||||
roundMode: 'HALF_UP',
|
||||
ssCode: 'on',
|
||||
countryCode: undefined,
|
||||
scNote: undefined
|
||||
}
|
||||
}
|
||||
|
||||
function regionLabel(r) {
|
||||
const cn = r.countryNameCn || r.countryNameEn || ''
|
||||
return cn ? `${r.flagEmoji || ''} ${cn} (${r.countryCode2})`.trim() : r.countryCode2
|
||||
}
|
||||
|
||||
function ensureRegions() {
|
||||
if (regionOptions.value.length) return Promise.resolve()
|
||||
return listRegionOptions().then(res => {
|
||||
regionOptions.value = res.data || []
|
||||
})
|
||||
}
|
||||
|
||||
function reset() {
|
||||
form.value = emptyForm()
|
||||
nextTick(() => formRef.value?.clearValidate())
|
||||
}
|
||||
|
||||
function open(row) {
|
||||
reset()
|
||||
ensureRegions()
|
||||
if (!row) {
|
||||
title.value = "新建附加费"
|
||||
visible.value = true
|
||||
return
|
||||
}
|
||||
getSurcharge(row.scId).then(res => {
|
||||
const data = res.data || {}
|
||||
if (data.ssCode) data.ssCode = String(data.ssCode).toLowerCase()
|
||||
form.value = { ...emptyForm(), ...data }
|
||||
title.value = "修改附加费"
|
||||
visible.value = true
|
||||
nextTick(() => formRef.value?.clearValidate())
|
||||
})
|
||||
}
|
||||
|
||||
function submitForm() {
|
||||
formRef.value.validate(valid => {
|
||||
if (!valid) return
|
||||
const payload = { ...form.value }
|
||||
if (!payload.countryCode) payload.countryCode = undefined
|
||||
if (payload.chargeValue != null) payload.chargeValue = Number(payload.chargeValue)
|
||||
const req = payload.scId != null ? updateSurcharge(payload) : addSurcharge(payload)
|
||||
req.then(() => {
|
||||
proxy.$modal.msgSuccess(payload.scId != null ? "修改成功" : "新增成功")
|
||||
visible.value = false
|
||||
emit('success')
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
defineExpose({ open })
|
||||
</script>
|
||||
@@ -63,99 +63,24 @@
|
||||
</template>
|
||||
</basic-table>
|
||||
|
||||
<el-dialog :title="title" v-model="open" width="640px" append-to-body>
|
||||
<el-form ref="formRef" :model="form" :rules="rules" label-width="100px">
|
||||
<el-row>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="附加费名称" prop="scName">
|
||||
<el-input v-model="form.scName" placeholder="如 燃油附加费" maxlength="100" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="费用类型" prop="feeType">
|
||||
<el-select v-model="form.feeType" placeholder="请选择" style="width: 100%" disabled>
|
||||
<el-option v-for="d in bms_fee_type" :key="d.value" :label="d.label" :value="d.value" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="计费方式" prop="chargeType">
|
||||
<el-select v-model="form.chargeType" placeholder="请选择" style="width: 100%">
|
||||
<el-option v-for="c in bms_charge_type" :key="c.value" :label="c.label" :value="c.value" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="计费数值" prop="chargeValue">
|
||||
<el-input-number v-model="form.chargeValue" :min="0" :precision="6" :step="1" controls-position="right" style="width: 100%" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="币种" prop="currency">
|
||||
<el-select v-model="form.currency" placeholder="请选择" style="width: 100%">
|
||||
<el-option v-for="c in bms_currency" :key="c.value" :label="c.label" :value="c.value" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="取值方式" prop="roundMode">
|
||||
<el-select v-model="form.roundMode" placeholder="请选择" style="width: 100%">
|
||||
<el-option v-for="d in bms_round_mode" :key="d.value" :label="d.label" :value="d.value" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="适用国家" prop="countryCode">
|
||||
<el-select v-model="form.countryCode" placeholder="全部国家" clearable filterable style="width: 100%">
|
||||
<el-option label="全部国家" value="" />
|
||||
<el-option v-for="r in regionOptions" :key="r.countryCode2" :label="regionLabel(r)" :value="r.countryCode2" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="状态" prop="ssCode">
|
||||
<el-radio-group v-model="form.ssCode">
|
||||
<el-radio value="on">有效</el-radio>
|
||||
<el-radio value="of">停用</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-form-item label="备注" prop="scNote">
|
||||
<el-input v-model="form.scNote" type="textarea" :rows="2" placeholder="请输入备注" maxlength="500" />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<template #footer>
|
||||
<div class="dialog-footer">
|
||||
<el-button type="primary" @click="submitForm">确 定</el-button>
|
||||
<el-button @click="open = false">取 消</el-button>
|
||||
</div>
|
||||
</template>
|
||||
</el-dialog>
|
||||
<surcharge-form-dialog ref="formDialogRef" @success="() => tableRef.refresh()" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup name="PriceSurcharge">
|
||||
import { listSurcharge, getSurcharge, addSurcharge, updateSurcharge, delSurcharge } from '@/api/price/surcharge'
|
||||
import { listSurcharge, delSurcharge } from '@/api/price/surcharge'
|
||||
import SurchargeFormDialog from './components/SurchargeFormDialog.vue'
|
||||
import { listRegionOptions } from '@/api/data/region'
|
||||
import { onMounted } from 'vue'
|
||||
|
||||
const { proxy } = getCurrentInstance()
|
||||
const { bms_fee_type, bms_round_mode, bms_charge_type, bms_currency } = useDict('bms_fee_type', 'bms_round_mode', 'bms_charge_type', 'bms_currency')
|
||||
const { bms_charge_type } = useDict('bms_charge_type')
|
||||
|
||||
const tableRef = ref()
|
||||
const open = ref(false)
|
||||
const title = ref('')
|
||||
const formDialogRef = ref()
|
||||
const regionOptions = ref([])
|
||||
|
||||
const columns = [
|
||||
{ label: 'scId', prop: 'scId', align: 'center', width: 80 },
|
||||
{ label: '附加费名称', prop: 'scName', align: 'center', minWidth: 140, showOverflowTooltip: true },
|
||||
{ label: '费用类型', prop: 'feeType', align: 'center', width: 110, dict: 'bms_fee_type' },
|
||||
{ label: '计费方式', prop: 'chargeType', align: 'center', width: 130 },
|
||||
@@ -192,18 +117,6 @@ const searchColumns = [
|
||||
}
|
||||
]
|
||||
|
||||
const data = reactive({
|
||||
form: {},
|
||||
rules: {
|
||||
scName: [{ required: true, message: '附加费名称不能为空', trigger: 'blur' }],
|
||||
feeType: [{ required: true, message: '请选择费用类型', trigger: 'change' }],
|
||||
chargeType: [{ required: true, message: '请选择计费方式', trigger: 'change' }],
|
||||
chargeValue: [{ required: true, message: '计费数值不能为空', trigger: 'blur' }],
|
||||
roundMode: [{ required: true, message: '请选择取值方式', trigger: 'change' }]
|
||||
}
|
||||
})
|
||||
const { form, rules } = toRefs(data)
|
||||
|
||||
function queryList(params) {
|
||||
return listSurcharge(params)
|
||||
}
|
||||
@@ -213,11 +126,6 @@ function chargeTypeLabel(val) {
|
||||
return found ? found.label : (val || '-')
|
||||
}
|
||||
|
||||
function regionLabel(r) {
|
||||
const cn = r.countryNameCn || r.countryNameEn || ''
|
||||
return cn ? `${r.flagEmoji || ''} ${cn} (${r.countryCode2})`.trim() : r.countryCode2
|
||||
}
|
||||
|
||||
function countryLabel(code) {
|
||||
if (!code) return '全部'
|
||||
const found = regionOptions.value.find(r => r.countryCode2 === code)
|
||||
@@ -243,52 +151,12 @@ function formatChargeValue(row) {
|
||||
return v + ' ' + (row.currency || 'CNY')
|
||||
}
|
||||
|
||||
function reset() {
|
||||
form.value = {
|
||||
scId: undefined,
|
||||
scName: undefined,
|
||||
feeType: 'SURCHARGE',
|
||||
chargeType: 'FIXED',
|
||||
chargeValue: undefined,
|
||||
currency: 'CNY',
|
||||
roundMode: 'HALF_UP',
|
||||
ssCode: 'on',
|
||||
countryCode: undefined,
|
||||
scNote: undefined
|
||||
}
|
||||
proxy.resetForm('formRef')
|
||||
}
|
||||
|
||||
function handleAdd() {
|
||||
reset()
|
||||
open.value = true
|
||||
title.value = '新建附加费'
|
||||
formDialogRef.value.open()
|
||||
}
|
||||
|
||||
function handleUpdate(row) {
|
||||
reset()
|
||||
getSurcharge(row.scId).then(res => {
|
||||
const data = res.data || {}
|
||||
if (data.ssCode) data.ssCode = String(data.ssCode).toLowerCase()
|
||||
form.value = data
|
||||
open.value = true
|
||||
title.value = '修改附加费'
|
||||
})
|
||||
}
|
||||
|
||||
function submitForm() {
|
||||
proxy.$refs['formRef'].validate(valid => {
|
||||
if (!valid) return
|
||||
const payload = { ...form.value }
|
||||
if (!payload.countryCode) payload.countryCode = undefined
|
||||
if (payload.chargeValue != null) payload.chargeValue = Number(payload.chargeValue)
|
||||
const req = payload.scId != null ? updateSurcharge(payload) : addSurcharge(payload)
|
||||
req.then(() => {
|
||||
proxy.$modal.msgSuccess(payload.scId != null ? '修改成功' : '新增成功')
|
||||
open.value = false
|
||||
tableRef.value.refresh()
|
||||
})
|
||||
})
|
||||
formDialogRef.value.open(row)
|
||||
}
|
||||
|
||||
function handleDelete(ids) {
|
||||
|
||||
@@ -5,15 +5,9 @@
|
||||
<el-card shadow="never">
|
||||
<template #header><span>试算参数</span></template>
|
||||
<el-form ref="formRef" :model="form" :rules="rules" label-width="120px">
|
||||
<el-form-item label="客户ID" prop="customerId">
|
||||
<el-input-number
|
||||
v-model="form.customerId"
|
||||
:min="1"
|
||||
:controls="false"
|
||||
placeholder="请输入客户ID"
|
||||
style="width: 100%"
|
||||
/>
|
||||
<div class="form-hint">与套餐绑定客户ID一致;无套餐时走产品默认价</div>
|
||||
<el-form-item label="客户" prop="customerCode">
|
||||
<customer-select v-model="form.customerCode" value-key="customerCode" placeholder="请选择客户" />
|
||||
<div class="form-hint">与套餐绑定客户一致;无套餐时走产品默认价</div>
|
||||
</el-form-item>
|
||||
<el-form-item label="产品" prop="productCode">
|
||||
<el-select
|
||||
@@ -285,7 +279,7 @@ function handleViewHistory(row) {
|
||||
}
|
||||
|
||||
const form = reactive({
|
||||
customerId: undefined,
|
||||
customerCode: undefined,
|
||||
productCode: undefined,
|
||||
countryCode: undefined,
|
||||
weight: undefined,
|
||||
@@ -293,7 +287,7 @@ const form = reactive({
|
||||
})
|
||||
|
||||
const rules = {
|
||||
customerId: [{ required: true, message: '请输入客户ID', trigger: 'blur' }],
|
||||
customerCode: [{ required: true, message: '请选择客户', trigger: 'change' }],
|
||||
productCode: [{ required: true, message: '请选择产品', trigger: 'change' }],
|
||||
countryCode: [{ required: true, message: '请选择目的国/地区', trigger: 'change' }],
|
||||
weight: [{ required: true, message: '请输入计费重量', trigger: 'blur' }]
|
||||
@@ -340,7 +334,7 @@ function handleQuote() {
|
||||
result.value = null
|
||||
errorMsg.value = ''
|
||||
const payload = {
|
||||
customerId: form.customerId,
|
||||
customerCode: form.customerCode,
|
||||
productCode: form.productCode,
|
||||
countryCode: form.countryCode,
|
||||
weight: form.weight
|
||||
@@ -364,7 +358,7 @@ function handleQuote() {
|
||||
}
|
||||
|
||||
function resetForm() {
|
||||
form.customerId = undefined
|
||||
form.customerCode = undefined
|
||||
form.productCode = undefined
|
||||
form.countryCode = undefined
|
||||
form.weight = undefined
|
||||
|
||||
@@ -222,16 +222,18 @@
|
||||
title="套餐创建后处于草稿状态,可暂不绑定客户。一个客户只能绑定一个套餐。"
|
||||
/>
|
||||
<el-table :data="form.customers" border empty-text="暂未绑定客户">
|
||||
<el-table-column label="客户ID" min-width="120">
|
||||
<el-table-column label="客户" min-width="220">
|
||||
<template #default="{ row }">
|
||||
<el-input v-model="row.customerId" placeholder="客户ID" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="客户名称" min-width="140">
|
||||
<template #default="{ row }">
|
||||
<el-input v-model="row.customerName" placeholder="客户名称" />
|
||||
<customer-select
|
||||
v-model="row.customerCode"
|
||||
value-key="customerCode"
|
||||
placeholder="请选择客户"
|
||||
@change="(code, item) => onBindCustomerChange(row, code, item)"
|
||||
/>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="客户代码" prop="customerCode" min-width="120" show-overflow-tooltip />
|
||||
<el-table-column label="客户名称" prop="customerName" min-width="140" show-overflow-tooltip />
|
||||
<el-table-column label="优先级" width="110">
|
||||
<template #default="{ row }">
|
||||
<el-input-number v-model="row.bindPriority" :min="1" controls-position="right" style="width: 100%" />
|
||||
@@ -448,6 +450,7 @@ function emptyDetail() {
|
||||
function emptyCustomer() {
|
||||
return {
|
||||
customerId: undefined,
|
||||
customerCode: undefined,
|
||||
customerName: '',
|
||||
bindPriority: form.customers.length + 1,
|
||||
prBegindate: form.effectiveDate,
|
||||
@@ -463,6 +466,13 @@ function addCustomerRow() {
|
||||
form.customers.push(emptyCustomer())
|
||||
}
|
||||
|
||||
function onBindCustomerChange(row, code, item) {
|
||||
console.log('onBindCustomerChange', row, code, item)
|
||||
row.customerCode = code || undefined
|
||||
row.customerName = item ? item.customerName : ''
|
||||
row.customerId = item ? item.customerId : undefined
|
||||
}
|
||||
|
||||
function clearCascadeAfterProduct(row) {
|
||||
row.countryCode = undefined
|
||||
row.countryName = undefined
|
||||
@@ -545,10 +555,10 @@ function buildPayload(submitFlag) {
|
||||
roundMode: d.roundMode || 'HALF_UP'
|
||||
}))
|
||||
const customers = (form.customers || [])
|
||||
.filter(c => c.customerId)
|
||||
.filter(c => c.customerCode)
|
||||
.map(c => ({
|
||||
...c,
|
||||
customerId: Number(c.customerId)
|
||||
customerCode: c.customerCode
|
||||
}))
|
||||
console.log('details', details)
|
||||
|
||||
|
||||
@@ -142,6 +142,7 @@
|
||||
<el-table :data="set.customers || []" border empty-text="暂未绑定客户">
|
||||
<el-table-column label="绑定ID" prop="customerPricesetId" width="100" />
|
||||
<el-table-column label="客户ID" prop="customerId" width="110" />
|
||||
<el-table-column label="客户代码" prop="customerCode" min-width="120" show-overflow-tooltip />
|
||||
<el-table-column label="客户名称" prop="customerName" min-width="140" />
|
||||
<el-table-column label="优先级" width="110">
|
||||
<template #default="{ row }">{{ row.bindPriority }}{{ row.bindPriority === 1 ? '(最高)' : '' }}</template>
|
||||
@@ -241,11 +242,19 @@
|
||||
|
||||
<el-dialog :title="customerTitle" v-model="customerOpen" width="520px" append-to-body>
|
||||
<el-form ref="customerFormRef" :model="customerForm" :rules="customerRules" label-width="110px">
|
||||
<el-form-item label="客户ID" prop="customerId">
|
||||
<el-input v-model="customerForm.customerId" />
|
||||
<el-form-item label="客户" prop="customerCode">
|
||||
<customer-select
|
||||
v-model="customerForm.customerCode"
|
||||
value-key="customerCode"
|
||||
placeholder="请选择客户"
|
||||
@change="onCustomerSelectChange"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="客户名称" prop="customerName">
|
||||
<el-input v-model="customerForm.customerName" maxlength="100" />
|
||||
<el-form-item label="客户代码">
|
||||
<el-input v-model="customerForm.customerCode" disabled />
|
||||
</el-form-item>
|
||||
<el-form-item label="客户名称">
|
||||
<el-input v-model="customerForm.customerName" disabled />
|
||||
</el-form-item>
|
||||
<el-form-item label="优先级" prop="bindPriority">
|
||||
<el-input-number v-model="customerForm.bindPriority" :min="1" controls-position="right" />
|
||||
@@ -299,7 +308,7 @@ const customerTitle = ref('')
|
||||
const customerFormRef = ref()
|
||||
const customerForm = ref({})
|
||||
const customerRules = {
|
||||
customerId: [{ required: true, message: '客户ID不能为空', trigger: 'blur' }],
|
||||
customerCode: [{ required: true, message: '请选择客户', trigger: 'change' }],
|
||||
prBegindate: [{ required: true, message: '生效日期不能为空', trigger: 'change' }]
|
||||
}
|
||||
|
||||
@@ -605,10 +614,17 @@ function removeDetail(row) {
|
||||
}).catch(() => {})
|
||||
}
|
||||
|
||||
function onCustomerSelectChange(code, item) {
|
||||
customerForm.value.customerCode = code || undefined
|
||||
customerForm.value.customerName = item ? item.customerName : ''
|
||||
customerForm.value.customerId = undefined
|
||||
}
|
||||
|
||||
function openCustomerDialog(row) {
|
||||
customerForm.value = row ? { ...row } : {
|
||||
priceSetId: set.value.priceSetId,
|
||||
customerId: undefined,
|
||||
customerCode: undefined,
|
||||
customerName: '',
|
||||
bindPriority: 1,
|
||||
prBegindate: set.value.effectiveDate,
|
||||
@@ -624,7 +640,8 @@ function submitCustomer() {
|
||||
const payload = {
|
||||
...customerForm.value,
|
||||
priceSetId: set.value.priceSetId,
|
||||
customerId: Number(customerForm.value.customerId)
|
||||
customerId: customerForm.value.customerId,
|
||||
customerCode: customerForm.value.customerCode
|
||||
}
|
||||
const req = payload.customerPricesetId ? updateSetCustomer(payload) : addSetCustomer(payload)
|
||||
req.then(() => {
|
||||
|
||||
Reference in New Issue
Block a user