修改产品功能
This commit is contained in:
@@ -60,7 +60,7 @@ public class TmsPriceController extends BaseController
|
||||
|
||||
/**
|
||||
* Quote by customer + product + country + weight (+ destPostcode when country has zones).
|
||||
* Zone resolve: destPostcode -> prc_zone_detail/prc_zone -> bms_product_country.zone_code.
|
||||
* Zone resolve: destPostcode -> prc_zone_detail/prc_zone -> product_country.zone_code.
|
||||
* Match: customer package FIXED > DISCOUNT > product default.
|
||||
*/
|
||||
@PostMapping("/quote")
|
||||
|
||||
@@ -22,7 +22,6 @@ import com.bms.common.core.page.TableDataInfo;
|
||||
import com.bms.common.enums.BusinessType;
|
||||
import com.bms.price.domain.BmsProduct;
|
||||
import com.bms.price.domain.BmsProductCountry;
|
||||
import com.bms.price.domain.BmsProductPriceVersion;
|
||||
import com.bms.price.service.IBmsProductService;
|
||||
|
||||
/**
|
||||
@@ -46,13 +45,6 @@ public class ProductController extends BaseController
|
||||
return getDataTable(list);
|
||||
}
|
||||
|
||||
@PreAuthorize("@ss.hasPermi('price:product:query') or @ss.hasPermi('price:product:list') or @ss.hasPermi('price:set:add') or @ss.hasPermi('price:set:query')")
|
||||
@GetMapping("/priceVersions")
|
||||
public AjaxResult priceVersions()
|
||||
{
|
||||
List<BmsProductPriceVersion> list = productService.selectPriceVersionOptions();
|
||||
return success(list);
|
||||
}
|
||||
|
||||
@PreAuthorize("@ss.hasPermi('price:product:query')")
|
||||
@GetMapping("/{productCode}/countries")
|
||||
|
||||
@@ -53,7 +53,6 @@ price.set.name.empty=套餐名称不能为空
|
||||
price.set.name.exists=套餐名称已存在
|
||||
price.set.effectiveDate.empty=生效日期不能为空
|
||||
price.set.date.invalid=生效日期不能晚于失效日期
|
||||
price.set.baseVersionNo.empty=请选择基础价格版本
|
||||
price.set.discount.range=折扣模式默认折扣需在 1~99
|
||||
price.set.delete.statusNotAllowed=仅待启用或驳回状态的套餐允许删除:{0}
|
||||
price.set.delete.boundCustomer=套餐【{0}】已绑定客户,请先解绑后再删除
|
||||
@@ -114,7 +113,6 @@ price.product.import.regionEmpty=bms_region 无可用国家数据,请先同步
|
||||
price.product.import.partialFail=导入完成但存在失败项:新增 {0},跳过 {1};失败明细:{2}
|
||||
price.product.import.effTooEarly=生效日期 {0} 早于当前开放版 {1},请使用更晚的生效日期导入
|
||||
price.product.import.needFeeAlter=请先执行 SQL:bms-back/sql/price/product_country_fee_alter.sql(缺少运费/挂号费字段)
|
||||
price.product.import.needVersionAlter=请先执行 SQL:bms-back/sql/price/product_price_version_alter.sql(缺少产品基础价格版本表/字段)
|
||||
price.product.import.needExpireAlter=请先执行 SQL:bms-back/sql/price/product_country_expire_alter.sql(缺少失效日期/版本唯一键)
|
||||
price.product.import.needCodeEffUnique=无法新增「同代码、不同生效日」的产品。请先执行 SQL:bms-back/sql/price/product_code_eff_unique_alter.sql(去掉 product_code 单列唯一,改为代码+生效日唯一)
|
||||
price.product.import.success=导入成功:新增 {0} 个产品,跳过 {1} 个(同代码同生效日不覆盖);写入国家/重量段明细 {2} 行。
|
||||
|
||||
@@ -7,7 +7,7 @@ import com.bms.common.core.domain.BaseEntity;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
/** BMS产品主表 bms_product */
|
||||
/** BMS产品主表 product */
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
public class BmsProduct extends BaseEntity
|
||||
|
||||
@@ -6,19 +6,15 @@ import java.util.Date;
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import lombok.Data;
|
||||
|
||||
/** 产品国家服务明细 bms_product_country */
|
||||
/** 产品国家服务明细 product_country */
|
||||
@Data
|
||||
public class BmsProductCountry implements Serializable
|
||||
{
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private Long detailId;
|
||||
/** FK to bms_product.product_id (one country version belongs to one product row) */
|
||||
/** FK to product.product_id */
|
||||
private Long productId;
|
||||
/** FK to bms_product_price_version.ppv_id */
|
||||
private Long ppvId;
|
||||
/** Display only: joined from bms_product_price_version.version_no */
|
||||
private String versionNo;
|
||||
private String productCode;
|
||||
private String countryName;
|
||||
private String countryCode;
|
||||
|
||||
@@ -1,32 +0,0 @@
|
||||
package com.bms.price.domain;
|
||||
|
||||
import java.util.Date;
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import com.bms.common.core.domain.BaseEntity;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
/** Product base price version bms_product_price_version */
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
public class BmsProductPriceVersion extends BaseEntity
|
||||
{
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private Long ppvId;
|
||||
private String productCode;
|
||||
/** Linked bms_product.product_id for this version row */
|
||||
private Long productId;
|
||||
/** V1 / V2 */
|
||||
private String versionNo;
|
||||
private Integer versionSeq;
|
||||
@JsonFormat(pattern = "yyyy-MM-dd")
|
||||
private Date effectiveDate;
|
||||
/** null = open; set to next version effective_date when that version starts */
|
||||
@JsonFormat(pattern = "yyyy-MM-dd")
|
||||
private Date expireDate;
|
||||
/** 0 pending / 1 active / 2 expired */
|
||||
private String status;
|
||||
/** query only: product count for this effective_date option */
|
||||
private Integer productCount;
|
||||
}
|
||||
@@ -30,16 +30,16 @@ public class PrcPriceSetDetail implements Serializable
|
||||
private Long zdId;
|
||||
private Long wsdId;
|
||||
private String weightLabel;
|
||||
/** KG inclusive, same as bms_product_country */
|
||||
/** KG inclusive, same as product_country */
|
||||
private BigDecimal weightMin;
|
||||
private BigDecimal weightMax;
|
||||
/** bms_product_country.detail_id */
|
||||
/** product_country.detail_id */
|
||||
private Long productCountryId;
|
||||
private BigDecimal fvValue;
|
||||
private BigDecimal fvRegistrationFee;
|
||||
/** product base freight from bms_product_country (display only) */
|
||||
/** product base freight from product_country (display only) */
|
||||
private BigDecimal baseFreightPrice;
|
||||
/** product base registration from bms_product_country (display only) */
|
||||
/** product base registration from product_country (display only) */
|
||||
private BigDecimal baseRegistrationFee;
|
||||
private BigDecimal discountValue;
|
||||
/** UP / DOWN / HALF_UP */
|
||||
|
||||
@@ -52,6 +52,10 @@ public class PrcQuote extends BaseEntity
|
||||
private BigDecimal freightAmount;
|
||||
private BigDecimal surchargeAmount;
|
||||
private BigDecimal payableTotal;
|
||||
private BigDecimal productAmount;
|
||||
private BigDecimal redlineAmount;
|
||||
private BigDecimal costAmount;
|
||||
private BigDecimal payTotal;
|
||||
private String currency;
|
||||
private String roundMode;
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@ import lombok.EqualsAndHashCode;
|
||||
|
||||
/**
|
||||
* 附加费与产品/明细关联 prc_surcharge_rel
|
||||
* 同时携带附加费展示字段(JOIN prc_surcharge)与明细展示字段(LEFT JOIN bms_product_country),
|
||||
* 同时携带附加费展示字段(JOIN prc_surcharge)与明细展示字段(LEFT JOIN product_country),
|
||||
* 便于产品列表抽屉直接渲染。
|
||||
*
|
||||
* 语义:
|
||||
|
||||
@@ -44,7 +44,7 @@ public class TmsPriceQuoteResult implements Serializable
|
||||
private BigDecimal weightMax;
|
||||
private String weightLabel;
|
||||
private Date bizDate;
|
||||
/** bms_product_country.effective_date */
|
||||
/** product_country.effective_date */
|
||||
private Date effectiveDate;
|
||||
|
||||
private BigDecimal weight;
|
||||
@@ -56,6 +56,12 @@ public class TmsPriceQuoteResult implements Serializable
|
||||
private BigDecimal freightAmount;
|
||||
/** 附加费合计(按产品关联命中后汇总) */
|
||||
private BigDecimal surchargeAmount;
|
||||
/** product catalog total: base freight*weight + base registration (no package surcharge) */
|
||||
private BigDecimal productAmount;
|
||||
/** redline total reserved */
|
||||
private BigDecimal redlineAmount;
|
||||
/** cost total (currently = product catalog amount) */
|
||||
private BigDecimal costAmount;
|
||||
/** receivable total (order bill) */
|
||||
private BigDecimal incomeTotal;
|
||||
/** payable total (order bill); also quote payable */
|
||||
|
||||
+2
-18
@@ -23,9 +23,6 @@ public interface BmsProductCountryMapper
|
||||
/** Import overlay: update price/zone/attrs on matched country row */
|
||||
public int updateBmsProductCountryImport(BmsProductCountry country);
|
||||
|
||||
/** Bind legacy open row to a version */
|
||||
public int updatePpvId(@Param("detailId") Long detailId, @Param("ppvId") Long ppvId);
|
||||
|
||||
public int deleteByProductId(Long productId);
|
||||
|
||||
public int deleteByProductCode(String productCode);
|
||||
@@ -53,22 +50,9 @@ public interface BmsProductCountryMapper
|
||||
/** Open country rows (expire_date is null) for product */
|
||||
public List<BmsProductCountry> selectOpenByProductCode(@Param("productCode") String productCode);
|
||||
|
||||
/** Country rows under a price version */
|
||||
public List<BmsProductCountry> selectByPpvId(@Param("ppvId") Long ppvId);
|
||||
|
||||
/** Copy open/source version rows into a new version (new ppv_id / product_id / effective_date) */
|
||||
public int copyCountriesFromVersion(
|
||||
@Param("srcPpvId") Long srcPpvId,
|
||||
@Param("newPpvId") Long newPpvId,
|
||||
@Param("productId") Long productId,
|
||||
/** Copy previously open rows into a new effective_date (caller must expire first) */
|
||||
public int copyOpenCountries(
|
||||
@Param("productCode") String productCode,
|
||||
@Param("effectiveDate") Date effectiveDate,
|
||||
@Param("status") String status);
|
||||
|
||||
/** Copy currently open rows (legacy / no ppv_id) into a new version */
|
||||
public int copyOpenCountriesToVersion(
|
||||
@Param("productCode") String productCode,
|
||||
@Param("newPpvId") Long newPpvId,
|
||||
@Param("productId") Long productId,
|
||||
@Param("effectiveDate") Date effectiveDate,
|
||||
@Param("status") String status);
|
||||
|
||||
-38
@@ -1,38 +0,0 @@
|
||||
package com.bms.price.mapper;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
import com.bms.price.domain.BmsProductPriceVersion;
|
||||
|
||||
/**
|
||||
* Product base price version
|
||||
*/
|
||||
public interface BmsProductPriceVersionMapper
|
||||
{
|
||||
public BmsProductPriceVersion selectBmsProductPriceVersionById(Long ppvId);
|
||||
|
||||
/** Open version (expire_date is null), prefer latest effective_date */
|
||||
public BmsProductPriceVersion selectOpenByProductCode(@Param("productCode") String productCode);
|
||||
|
||||
public BmsProductPriceVersion selectByProductCodeAndEffectiveDate(
|
||||
@Param("productCode") String productCode,
|
||||
@Param("effectiveDate") Date effectiveDate);
|
||||
|
||||
public Integer selectMaxVersionSeq(@Param("productCode") String productCode);
|
||||
|
||||
/** Distinct effective_date options for package create dropdown (desc) */
|
||||
public List<BmsProductPriceVersion> selectVersionOptions();
|
||||
|
||||
public int insertBmsProductPriceVersion(BmsProductPriceVersion version);
|
||||
|
||||
public int updateBmsProductPriceVersion(BmsProductPriceVersion version);
|
||||
|
||||
/** Close open versions: set expire_date = newEffectiveDate where effective_date < newEffectiveDate */
|
||||
public int expireOpenByProductCode(
|
||||
@Param("productCode") String productCode,
|
||||
@Param("newEffectiveDate") Date newEffectiveDate);
|
||||
|
||||
/** Recompute status from effective_date / expire_date vs today */
|
||||
public int refreshStatusByDates();
|
||||
}
|
||||
+4
-10
@@ -42,23 +42,17 @@ public interface PrcPriceSetDetailMapper
|
||||
/** Copy all details from src version into new version (new psd_id, same price_set_id) */
|
||||
public int copyDetailsFromVersion(@Param("srcPsvId") Long srcPsvId, @Param("newPsvId") Long newPsvId);
|
||||
|
||||
/**
|
||||
* FIXED: insert details from product country library.
|
||||
* When baseVersionNo is set, pull that base-price version only;
|
||||
* otherwise asOf window or openOnly fallback.
|
||||
*/
|
||||
/** FIXED: insert details from product country library (asOf window or openOnly). */
|
||||
public int insertFixedDetailsFromLibrary(
|
||||
@Param("priceSetId") Long priceSetId,
|
||||
@Param("psvId") Long psvId,
|
||||
@Param("asOf") Date asOf,
|
||||
@Param("openOnly") boolean openOnly,
|
||||
@Param("baseVersionNo") String baseVersionNo);
|
||||
@Param("openOnly") boolean openOnly);
|
||||
|
||||
/** DISCOUNT: one detail row per product (optionally scoped to base version_no) */
|
||||
/** DISCOUNT: one detail row per effective product */
|
||||
public int insertDiscountDetailsFromLibrary(
|
||||
@Param("priceSetId") Long priceSetId,
|
||||
@Param("psvId") Long psvId,
|
||||
@Param("baseVersionNo") String baseVersionNo);
|
||||
@Param("psvId") Long psvId);
|
||||
|
||||
/** FIXED: product + country + zone + productCountryId / weight; optional psvId scopes to version */
|
||||
public PrcPriceSetDetail selectFixedMatch(
|
||||
|
||||
@@ -18,5 +18,8 @@ public interface PrcQuoteMapper
|
||||
|
||||
public int updateQuoteAmounts(@Param("quoteId") String quoteId,
|
||||
@Param("surchargeAmount") BigDecimal surchargeAmount,
|
||||
@Param("payableTotal") BigDecimal payableTotal);
|
||||
@Param("payableTotal") BigDecimal payableTotal,
|
||||
@Param("productAmount") BigDecimal productAmount,
|
||||
@Param("costAmount") BigDecimal costAmount,
|
||||
@Param("payTotal") BigDecimal payTotal);
|
||||
}
|
||||
|
||||
@@ -5,7 +5,6 @@ import java.util.List;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
import com.bms.price.domain.BmsProduct;
|
||||
import com.bms.price.domain.BmsProductCountry;
|
||||
import com.bms.price.domain.BmsProductPriceVersion;
|
||||
|
||||
/**
|
||||
* 产品列表 服务层
|
||||
@@ -56,8 +55,6 @@ public interface IBmsProductService
|
||||
*/
|
||||
public String importCountryProductExcel(MultipartFile file, String countryCode, String operName) throws Exception;
|
||||
|
||||
/** Distinct base-price version options (by effective_date desc) for package create */
|
||||
public List<BmsProductPriceVersion> selectPriceVersionOptions();
|
||||
|
||||
/**
|
||||
* Parse Weishi B2C quote Excel into productCode -> country/zone/weight price rows (no persist).
|
||||
|
||||
+22
-143
@@ -35,11 +35,9 @@ import com.bms.common.utils.MessageUtils;
|
||||
import com.bms.common.utils.StringUtils;
|
||||
import com.bms.price.domain.BmsProduct;
|
||||
import com.bms.price.domain.BmsProductCountry;
|
||||
import com.bms.price.domain.BmsProductPriceVersion;
|
||||
import com.bms.price.domain.PrcZone;
|
||||
import com.bms.price.mapper.BmsProductCountryMapper;
|
||||
import com.bms.price.mapper.BmsProductMapper;
|
||||
import com.bms.price.mapper.BmsProductPriceVersionMapper;
|
||||
import com.bms.price.mapper.PrcZoneMapper;
|
||||
import com.bms.price.service.IBmsProductService;
|
||||
import com.bms.price.service.IPrcSurchargeRelService;
|
||||
@@ -77,8 +75,6 @@ public class BmsProductServiceImpl implements IBmsProductService
|
||||
@Autowired
|
||||
private BmsProductCountryMapper countryMapper;
|
||||
|
||||
@Autowired
|
||||
private BmsProductPriceVersionMapper priceVersionMapper;
|
||||
|
||||
@Autowired
|
||||
private BmsRegionMapper regionMapper;
|
||||
@@ -103,7 +99,6 @@ public class BmsProductServiceImpl implements IBmsProductService
|
||||
{
|
||||
productMapper.refreshStatusByDates();
|
||||
countryMapper.refreshStatusByDates();
|
||||
priceVersionMapper.refreshStatusByDates();
|
||||
if (product != null)
|
||||
{
|
||||
product.setStatus(normalizeStatusCode(product.getStatus()));
|
||||
@@ -489,12 +484,6 @@ public class BmsProductServiceImpl implements IBmsProductService
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<BmsProductPriceVersion> selectPriceVersionOptions()
|
||||
{
|
||||
List<BmsProductPriceVersion> list = priceVersionMapper.selectVersionOptions();
|
||||
return list == null ? new ArrayList<>() : list;
|
||||
}
|
||||
|
||||
/** @return int[]{added, skipped, countryRows} */
|
||||
private int[] importOneProduct(Workbook workbook, BmsProduct product, String operName,
|
||||
@@ -532,7 +521,7 @@ public class BmsProductServiceImpl implements IBmsProductService
|
||||
if (existing != null)
|
||||
{
|
||||
product.setProductId(existing.getProductId());
|
||||
int countryRows = saveCountriesVersioned(product, countries);
|
||||
int countryRows = saveCountries(product, countries);
|
||||
return new int[] { 0, 1, countryRows };
|
||||
}
|
||||
|
||||
@@ -551,19 +540,18 @@ public class BmsProductServiceImpl implements IBmsProductService
|
||||
}
|
||||
productMapper.expireOpenByProductCode(product.getProductCode(), newEff, product.getProductId());
|
||||
productMapper.refreshStatusByDates();
|
||||
int countryRows = saveCountriesVersioned(product, countries);
|
||||
int countryRows = saveCountries(product, countries);
|
||||
return new int[] { 1, 0, countryRows };
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Versioned country save:
|
||||
* - require effective_date
|
||||
* - newEff > last open: expire previous version (expire_date = newEff), create new version,
|
||||
* copy previous country rows, then match import (hit=update, miss=insert)
|
||||
* - newEff equals last open: reuse open version, match update/insert (no full replace)
|
||||
* Save country rows by effective_date:
|
||||
* - newEff > last open: expire previous open rows, copy them to newEff, then match import (hit=update, miss=insert)
|
||||
* - newEff equals last open: match update/insert on open rows
|
||||
* - newEff < last open: reject
|
||||
*/
|
||||
private int saveCountriesVersioned(BmsProduct product, List<BmsProductCountry> countries)
|
||||
private int saveCountries(BmsProduct product, List<BmsProductCountry> countries)
|
||||
{
|
||||
if (product == null || countries == null || countries.isEmpty())
|
||||
{
|
||||
@@ -581,72 +569,36 @@ public class BmsProductServiceImpl implements IBmsProductService
|
||||
throw new ServiceException(MessageUtils.message("price.product.import.effEmpty"));
|
||||
}
|
||||
|
||||
BmsProductPriceVersion openVer = priceVersionMapper.selectOpenByProductCode(productCode);
|
||||
Date lastOpenEff = openVer != null ? toDateOnly(openVer.getEffectiveDate())
|
||||
: toDateOnly(countryMapper.selectMaxOpenEffectiveDate(productCode));
|
||||
|
||||
Date lastOpenEff = toDateOnly(countryMapper.selectMaxOpenEffectiveDate(productCode));
|
||||
if (lastOpenEff != null && newEff.before(lastOpenEff))
|
||||
{
|
||||
throw new ServiceException(MessageUtils.message("price.product.import.effTooEarly",
|
||||
formatDate(newEff), formatDate(lastOpenEff)));
|
||||
}
|
||||
|
||||
BmsProductPriceVersion targetVer;
|
||||
boolean newVersionDay = lastOpenEff == null || newEff.after(lastOpenEff);
|
||||
|
||||
if (newVersionDay)
|
||||
if (newVersionDay && lastOpenEff != null)
|
||||
{
|
||||
List<BmsProductCountry> prevSnapshot = null;
|
||||
Long srcPpvId = openVer != null ? openVer.getPpvId() : null;
|
||||
if (lastOpenEff != null)
|
||||
{
|
||||
if (srcPpvId != null)
|
||||
{
|
||||
prevSnapshot = null; // copy via SQL by ppv_id after expire
|
||||
}
|
||||
else
|
||||
{
|
||||
prevSnapshot = countryMapper.selectOpenByProductCode(productCode);
|
||||
}
|
||||
priceVersionMapper.expireOpenByProductCode(productCode, newEff);
|
||||
countryMapper.expireOpenByProductCode(productCode, newEff);
|
||||
}
|
||||
targetVer = createPriceVersion(product, newEff);
|
||||
String newStatus = resolveStoredStatus(newEff, null);
|
||||
if (srcPpvId != null)
|
||||
{
|
||||
countryMapper.copyCountriesFromVersion(srcPpvId, targetVer.getPpvId(), productId,
|
||||
productCode, newEff, newStatus);
|
||||
}
|
||||
else if (prevSnapshot != null && !prevSnapshot.isEmpty())
|
||||
{
|
||||
insertCountryCopies(prevSnapshot, targetVer.getPpvId(), productId, productCode, newEff, newStatus);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
targetVer = priceVersionMapper.selectByProductCodeAndEffectiveDate(productCode, newEff);
|
||||
if (targetVer == null)
|
||||
{
|
||||
targetVer = openVer != null ? openVer : createPriceVersion(product, newEff);
|
||||
}
|
||||
else if (targetVer.getProductId() == null && productId != null)
|
||||
{
|
||||
targetVer.setProductId(productId);
|
||||
targetVer.setUpdateBy(product.getUpdateBy());
|
||||
priceVersionMapper.updateBmsProductPriceVersion(targetVer);
|
||||
}
|
||||
assignOpenRowsToVersion(productCode, targetVer.getPpvId());
|
||||
// Copy open rows first (effective_date < newEff), then expire the previous open set.
|
||||
countryMapper.copyOpenCountries(productCode, productId, newEff, newStatus);
|
||||
countryMapper.expireOpenByProductCode(productCode, newEff);
|
||||
}
|
||||
|
||||
List<BmsProductCountry> baseRows = countryMapper.selectByPpvId(targetVer.getPpvId());
|
||||
List<BmsProductCountry> baseRows = countryMapper.selectOpenByProductCode(productCode);
|
||||
if (baseRows == null)
|
||||
{
|
||||
baseRows = new ArrayList<>();
|
||||
}
|
||||
// keep only rows for this effective date when same-day / after copy
|
||||
Map<String, BmsProductCountry> byKey = new HashMap<>();
|
||||
for (BmsProductCountry row : baseRows)
|
||||
{
|
||||
Date rowEff = toDateOnly(row.getEffectiveDate());
|
||||
if (rowEff != null && !rowEff.equals(newEff))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
byKey.put(countryMatchKey(row), row);
|
||||
}
|
||||
|
||||
@@ -655,7 +607,6 @@ public class BmsProductServiceImpl implements IBmsProductService
|
||||
{
|
||||
incoming.setProductId(productId);
|
||||
incoming.setProductCode(productCode);
|
||||
incoming.setPpvId(targetVer.getPpvId());
|
||||
incoming.setEffectiveDate(newEff);
|
||||
incoming.setExpireDate(null);
|
||||
incoming.setStatus(resolveStoredStatus(newEff, null));
|
||||
@@ -667,7 +618,6 @@ public class BmsProductServiceImpl implements IBmsProductService
|
||||
if (existing != null)
|
||||
{
|
||||
existing.setProductId(productId);
|
||||
existing.setPpvId(targetVer.getPpvId());
|
||||
existing.setCountryCode(incoming.getCountryCode());
|
||||
existing.setZoneId(incoming.getZoneId());
|
||||
existing.setZoneCode(incoming.getZoneCode());
|
||||
@@ -698,10 +648,6 @@ public class BmsProductServiceImpl implements IBmsProductService
|
||||
{
|
||||
throw new ServiceException(MessageUtils.message("price.product.import.needFeeAlter"));
|
||||
}
|
||||
if (tip.contains("ppv_id") || tip.contains("bms_product_price_version"))
|
||||
{
|
||||
throw new ServiceException(MessageUtils.message("price.product.import.needVersionAlter"));
|
||||
}
|
||||
if (tip.contains("expire_date") || tip.contains("uk_product_country_weight")
|
||||
|| tip.contains("uk_product_country_zone_weight"))
|
||||
{
|
||||
@@ -711,76 +657,9 @@ public class BmsProductServiceImpl implements IBmsProductService
|
||||
}
|
||||
}
|
||||
countryMapper.refreshStatusByDates();
|
||||
priceVersionMapper.refreshStatusByDates();
|
||||
return touched;
|
||||
}
|
||||
|
||||
private BmsProductPriceVersion createPriceVersion(BmsProduct product, Date effectiveDate)
|
||||
{
|
||||
Integer maxSeq = priceVersionMapper.selectMaxVersionSeq(product.getProductCode());
|
||||
int seq = maxSeq == null ? 1 : maxSeq.intValue() + 1;
|
||||
BmsProductPriceVersion ver = new BmsProductPriceVersion();
|
||||
ver.setProductCode(product.getProductCode());
|
||||
ver.setProductId(product.getProductId());
|
||||
ver.setVersionSeq(Integer.valueOf(seq));
|
||||
ver.setVersionNo("V" + seq);
|
||||
ver.setEffectiveDate(effectiveDate);
|
||||
ver.setExpireDate(null);
|
||||
ver.setStatus(resolveStoredStatus(effectiveDate, null));
|
||||
ver.setCreateBy(product.getCreateBy() != null ? product.getCreateBy() : product.getUpdateBy());
|
||||
priceVersionMapper.insertBmsProductPriceVersion(ver);
|
||||
return ver;
|
||||
}
|
||||
|
||||
/** After expire, insert in-memory previous open rows into the new version */
|
||||
private void insertCountryCopies(List<BmsProductCountry> prevSnapshot, Long newPpvId, Long productId,
|
||||
String productCode, Date newEff, String status)
|
||||
{
|
||||
for (BmsProductCountry src : prevSnapshot)
|
||||
{
|
||||
BmsProductCountry copy = new BmsProductCountry();
|
||||
copy.setProductId(productId);
|
||||
copy.setPpvId(newPpvId);
|
||||
copy.setProductCode(productCode);
|
||||
copy.setCountryName(src.getCountryName());
|
||||
copy.setCountryCode(src.getCountryCode());
|
||||
copy.setZoneId(src.getZoneId());
|
||||
copy.setZoneCode(src.getZoneCode());
|
||||
copy.setZoneName(src.getZoneName());
|
||||
copy.setWeightMin(src.getWeightMin());
|
||||
copy.setWeightMax(src.getWeightMax());
|
||||
copy.setFreightPrice(src.getFreightPrice());
|
||||
copy.setRegistrationFee(src.getRegistrationFee());
|
||||
copy.setSizeLimit(src.getSizeLimit());
|
||||
copy.setLastMile(src.getLastMile());
|
||||
copy.setLeadTime(src.getLeadTime());
|
||||
copy.setEffectiveDate(newEff);
|
||||
copy.setExpireDate(null);
|
||||
copy.setStatus(status);
|
||||
countryMapper.insertBmsProductCountry(copy);
|
||||
}
|
||||
}
|
||||
|
||||
private void assignOpenRowsToVersion(String productCode, Long ppvId)
|
||||
{
|
||||
if (ppvId == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
List<BmsProductCountry> openRows = countryMapper.selectOpenByProductCode(productCode);
|
||||
if (openRows == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
for (BmsProductCountry row : openRows)
|
||||
{
|
||||
if (row.getPpvId() == null)
|
||||
{
|
||||
countryMapper.updatePpvId(row.getDetailId(), ppvId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** Match key: country + zone + weight band */
|
||||
private String countryMatchKey(BmsProductCountry row)
|
||||
{
|
||||
@@ -912,7 +791,7 @@ public class BmsProductServiceImpl implements IBmsProductService
|
||||
{
|
||||
BmsProduct p = new BmsProduct();
|
||||
p.setProductCode(productCode);
|
||||
saveCountriesVersioned(p, countries);
|
||||
saveCountries(p, countries);
|
||||
}
|
||||
|
||||
private List<BmsProduct> parseCatalog(Sheet sheet)
|
||||
@@ -1936,7 +1815,7 @@ public class BmsProductServiceImpl implements IBmsProductService
|
||||
if (existing != null)
|
||||
{
|
||||
product.setProductId(existing.getProductId());
|
||||
int countryRows = saveCountriesVersioned(product, countries);
|
||||
int countryRows = saveCountries(product, countries);
|
||||
return new int[] { 0, 1, countryRows };
|
||||
}
|
||||
applyProductStatus(product);
|
||||
@@ -1954,7 +1833,7 @@ public class BmsProductServiceImpl implements IBmsProductService
|
||||
}
|
||||
productMapper.expireOpenByProductCode(product.getProductCode(), newEff, product.getProductId());
|
||||
productMapper.refreshStatusByDates();
|
||||
int countryRows = saveCountriesVersioned(product, countries);
|
||||
int countryRows = saveCountries(product, countries);
|
||||
return new int[] { 1, 0, countryRows };
|
||||
}
|
||||
|
||||
|
||||
+18
-10
@@ -187,7 +187,7 @@ public class PrcOrderBillServiceImpl implements IPrcOrderBillService
|
||||
PrcIncomeBill incomeBill = incomeBillMapper.selectByBillId(bill.getBillId());
|
||||
if (incomeBill == null)
|
||||
{
|
||||
incomeBill = persistIncomeBill(bill);
|
||||
incomeBill = persistIncomeBill(bill, null);
|
||||
}
|
||||
|
||||
PrcIncomeBillFee refundFee = new PrcIncomeBillFee();
|
||||
@@ -854,7 +854,12 @@ public class PrcOrderBillServiceImpl implements IPrcOrderBillService
|
||||
bill.setFreightAmount(result.getFreightAmount());
|
||||
bill.setSurchargeAmount(result.getSurchargeAmount());
|
||||
bill.setIncomeTotal(result.getPayableTotal());
|
||||
bill.setPayTotal(result.getPayTotal() == null ? BigDecimal.ZERO : result.getPayTotal());
|
||||
BigDecimal payTotal = result.getPayTotal();
|
||||
if (payTotal == null)
|
||||
{
|
||||
payTotal = result.getProductAmount();
|
||||
}
|
||||
bill.setPayTotal(payTotal == null ? BigDecimal.ZERO : payTotal);
|
||||
bill.setCurrency(result.getCurrency());
|
||||
bill.setRoundMode(result.getRoundMode());
|
||||
// Credit soft-fail before persist so insert/update stores arrears flag in one write.
|
||||
@@ -883,7 +888,7 @@ public class PrcOrderBillServiceImpl implements IPrcOrderBillService
|
||||
incomeBillFeeMapper.deleteByBillId(bill.getBillId());
|
||||
payBillFeeMapper.deleteByBillId(bill.getBillId());
|
||||
}
|
||||
PrcIncomeBill incomeBill = persistIncomeBill(bill);
|
||||
PrcIncomeBill incomeBill = persistIncomeBill(bill, result);
|
||||
List<PrcIncomeBillFee> fees = toFeeRows(bill.getBillId(),
|
||||
incomeBill == null ? null : incomeBill.getIncomeBillId(), result);
|
||||
if (!fees.isEmpty())
|
||||
@@ -891,7 +896,7 @@ public class PrcOrderBillServiceImpl implements IPrcOrderBillService
|
||||
incomeBillFeeMapper.insertBatch(fees);
|
||||
}
|
||||
orderBillMapper.refreshArBillStatusByBillIds(Arrays.asList(bill.getBillId()));
|
||||
PrcPayBill payBill = persistPayBill(bill);
|
||||
PrcPayBill payBill = persistPayBill(bill, result);
|
||||
List<PrcPayBillFee> payFees = toPayFeeRows(bill.getBillId(),
|
||||
payBill == null ? null : payBill.getPayBillId(), result);
|
||||
if (!payFees.isEmpty())
|
||||
@@ -1101,8 +1106,8 @@ public class PrcOrderBillServiceImpl implements IPrcOrderBillService
|
||||
return fees;
|
||||
}
|
||||
|
||||
/** 应收主表与订单计费一对一落库;当前写入销售价/应收合计,产品价/红线价预留。 */
|
||||
private PrcIncomeBill persistIncomeBill(PrcOrderBill bill)
|
||||
/** 应收主表与订单计费一对一落库;销售价=套餐计费,产品价=产品目录价;红线价预留。 */
|
||||
private PrcIncomeBill persistIncomeBill(PrcOrderBill bill, TmsPriceQuoteResult result)
|
||||
{
|
||||
if (bill == null || StringUtils.isEmpty(bill.getBillId()))
|
||||
{
|
||||
@@ -1118,7 +1123,8 @@ public class PrcOrderBillServiceImpl implements IPrcOrderBillService
|
||||
row.setCreateBy(bill.getCreateBy());
|
||||
}
|
||||
row.setCurrency(StringUtils.isEmpty(bill.getCurrency()) ? "CNY" : bill.getCurrency());
|
||||
// 产品价/红线价预留
|
||||
// 产品价=目录价;红线价预留
|
||||
row.setProductAmount(result == null ? null : result.getProductAmount());
|
||||
row.setSalesAmount(sales);
|
||||
row.setIncomeTotal(sales);
|
||||
row.setBelongSaler(bill.getBelongSaler());
|
||||
@@ -1163,8 +1169,8 @@ public class PrcOrderBillServiceImpl implements IPrcOrderBillService
|
||||
return fees;
|
||||
}
|
||||
|
||||
/** 应付主表与订单计费一对一落库;当前写入成本价/应付合计,产品价/红线价预留。 */
|
||||
private PrcPayBill persistPayBill(PrcOrderBill bill)
|
||||
/** 应付主表与订单计费一对一落库;成本价/应付=产品目录价,同步写入 product_amount;红线价预留。 */
|
||||
private PrcPayBill persistPayBill(PrcOrderBill bill, TmsPriceQuoteResult result)
|
||||
{
|
||||
if (bill == null || StringUtils.isEmpty(bill.getBillId()))
|
||||
{
|
||||
@@ -1180,7 +1186,9 @@ public class PrcOrderBillServiceImpl implements IPrcOrderBillService
|
||||
row.setCreateBy(bill.getCreateBy());
|
||||
}
|
||||
row.setCurrency(StringUtils.isEmpty(bill.getCurrency()) ? "CNY" : bill.getCurrency());
|
||||
// 产品价/红线价预留
|
||||
// 产品价/成本价=目录价;红线价预留
|
||||
BigDecimal product = result == null ? null : result.getProductAmount();
|
||||
row.setProductAmount(product);
|
||||
row.setCostAmount(pay);
|
||||
row.setPayTotal(pay);
|
||||
row.setBelongSaler(bill.getBelongSaler());
|
||||
|
||||
+9
-9
@@ -577,7 +577,7 @@ public class PrcPriceSetServiceImpl implements IPrcPriceSetService
|
||||
for (PrcPriceSetDetail d : details)
|
||||
{
|
||||
boolean noCountry = StringUtils.isEmpty(d.getCountryCode()) && StringUtils.isEmpty(d.getCountryName());
|
||||
// 运费单价 / 挂号费不参与完整性校验:原基础表 bms_product_country 可能没有值,
|
||||
// 运费单价 / 挂号费不参与完整性校验:原基础表 product_country 可能没有值,
|
||||
// 留空表示该条明细不覆盖该项,计费回退产品默认价(见 TmsPriceQuoteServiceImpl.tryFixed)。
|
||||
if (StringUtils.isEmpty(d.getProductCode()) || noCountry
|
||||
|| (d.getWsdId() == null && StringUtils.isEmpty(d.getWeightLabel())))
|
||||
@@ -588,7 +588,7 @@ public class PrcPriceSetServiceImpl implements IPrcPriceSetService
|
||||
if (details.isEmpty())
|
||||
{
|
||||
items.add(new PrcPriceSetCheckItem("FIXED 明细完整性", "PASS",
|
||||
"\u65e0\u5957\u9910\u660e\u7ec6\uff1a\u8ba1\u8d39\u53d6 bms_product / bms_product_country \u9ed8\u8ba4\u8fd0\u8d39\u4e0e\u6302\u53f7\u8d39"));
|
||||
"\u65e0\u5957\u9910\u660e\u7ec6\uff1a\u8ba1\u8d39\u53d6 product / product_country \u9ed8\u8ba4\u8fd0\u8d39\u4e0e\u6302\u53f7\u8d39"));
|
||||
}
|
||||
else if (incomplete > 0)
|
||||
{
|
||||
@@ -673,11 +673,11 @@ public class PrcPriceSetServiceImpl implements IPrcPriceSetService
|
||||
|
||||
if (TYPE_FIXED.equals(setType) && !details.isEmpty())
|
||||
{
|
||||
items.add(new PrcPriceSetCheckItem("\u8fd0\u8d39\u5355\u4ef7 vs \u9ed8\u8ba4\u7b49\u7ea7\u4ef7\u504f\u5dee", "INFO", "\u6709\u8986\u76d6\u660e\u7ec6\u65f6\u4f18\u5148\u53d6\u5957\u9910\u56fa\u5b9a\u4ef7\uff1b\u672a\u547d\u4e2d\u5219\u56de\u9000 bms_product_country"));
|
||||
items.add(new PrcPriceSetCheckItem("\u8fd0\u8d39\u5355\u4ef7 vs \u9ed8\u8ba4\u7b49\u7ea7\u4ef7\u504f\u5dee", "INFO", "\u6709\u8986\u76d6\u660e\u7ec6\u65f6\u4f18\u5148\u53d6\u5957\u9910\u56fa\u5b9a\u4ef7\uff1b\u672a\u547d\u4e2d\u5219\u56de\u9000 product_country"));
|
||||
}
|
||||
else if (TYPE_FIXED.equals(setType))
|
||||
{
|
||||
items.add(new PrcPriceSetCheckItem("\u8fd0\u8d39\u5355\u4ef7 vs \u9ed8\u8ba4\u7b49\u7ea7\u4ef7\u504f\u5dee", "INFO", "\u65e0\u5957\u9910\u660e\u7ec6\uff0c\u5168\u90e8\u8d70 bms_product_country \u9ed8\u8ba4\u8fd0\u8d39/\u6302\u53f7\u8d39"));
|
||||
items.add(new PrcPriceSetCheckItem("\u8fd0\u8d39\u5355\u4ef7 vs \u9ed8\u8ba4\u7b49\u7ea7\u4ef7\u504f\u5dee", "INFO", "\u65e0\u5957\u9910\u660e\u7ec6\uff0c\u5168\u90e8\u8d70 product_country \u9ed8\u8ba4\u8fd0\u8d39/\u6302\u53f7\u8d39"));
|
||||
}
|
||||
else if (TYPE_DISCOUNT.equals(setType))
|
||||
{
|
||||
@@ -1337,7 +1337,7 @@ public class PrcPriceSetServiceImpl implements IPrcPriceSetService
|
||||
{
|
||||
throw new ServiceException(MessageUtils.message("price.set.detail.weight.empty"));
|
||||
}
|
||||
// 运费单价 / 挂号费不做必填校验:原基础表 bms_product_country 可能没有值,
|
||||
// 运费单价 / 挂号费不做必填校验:原基础表 product_country 可能没有值,
|
||||
// 前端对应单元格会禁用(PriceEditDrawer.isBaseMissing)。
|
||||
// 任一为空时该条明细不参与覆盖,计费按「未命中」回退产品默认价
|
||||
// (见 TmsPriceQuoteServiceImpl.tryFixed)。
|
||||
@@ -1466,7 +1466,7 @@ public class PrcPriceSetServiceImpl implements IPrcPriceSetService
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolve / verify product_country_id from bms_product_country when missing.
|
||||
* Resolve / verify product_country_id from product_country when missing.
|
||||
*/
|
||||
private void fillProductCountryId(PrcPriceSetDetail detail)
|
||||
{
|
||||
@@ -2100,17 +2100,17 @@ public class PrcPriceSetServiceImpl implements IPrcPriceSetService
|
||||
if (TYPE_DISCOUNT.equals(set.getSetType()))
|
||||
{
|
||||
inserted = detailMapper.insertDiscountDetailsFromLibrary(
|
||||
set.getPriceSetId(), version.getPsvId(), null);
|
||||
set.getPriceSetId(), version.getPsvId());
|
||||
}
|
||||
else
|
||||
{
|
||||
// Prefer currently effective open country rows; fallback asOf window if needed
|
||||
inserted = detailMapper.insertFixedDetailsFromLibrary(
|
||||
set.getPriceSetId(), version.getPsvId(), null, true, null);
|
||||
set.getPriceSetId(), version.getPsvId(), null, true);
|
||||
if (inserted <= 0)
|
||||
{
|
||||
inserted = detailMapper.insertFixedDetailsFromLibrary(
|
||||
set.getPriceSetId(), version.getPsvId(), new Date(), false, null);
|
||||
set.getPriceSetId(), version.getPsvId(), new Date(), false);
|
||||
}
|
||||
}
|
||||
if (inserted <= 0)
|
||||
|
||||
+46
-1
@@ -645,9 +645,35 @@ public class TmsPriceQuoteServiceImpl implements ITmsPriceQuoteService
|
||||
r.setCurrency("CNY");
|
||||
r.setRoundMode(mode);
|
||||
r.setFromCache(false);
|
||||
fillProductAmountAndPay(r, base, weight, rm, mode);
|
||||
return r;
|
||||
}
|
||||
|
||||
/**
|
||||
* Product catalog amount (product_amount) and payable cost (pay_total / payFeeDetails).
|
||||
* Formula: product_country.freight_price * weight + registration_fee.
|
||||
* Cost currently equals product catalog amount (no separate cost table yet).
|
||||
*/
|
||||
private void fillProductAmountAndPay(TmsPriceQuoteResult r, BmsProductCountry base,
|
||||
BigDecimal weight, RoundingMode rm, String roundMode)
|
||||
{
|
||||
if (r == null || base == null || weight == null || base.getFreightPrice() == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
BigDecimal baseReg = base.getRegistrationFee() == null ? BigDecimal.ZERO : base.getRegistrationFee();
|
||||
BigDecimal productFreight = base.getFreightPrice().multiply(weight).setScale(2, rm);
|
||||
BigDecimal productAmount = productFreight.add(baseReg).setScale(2, rm);
|
||||
r.setProductAmount(productAmount);
|
||||
r.setCostAmount(productAmount);
|
||||
r.setPayTotal(productAmount);
|
||||
String currency = normalizeCurrency(r.getCurrency());
|
||||
List<TmsPriceQuoteFeeLine> payLines = new ArrayList<TmsPriceQuoteFeeLine>();
|
||||
payLines.add(feeLine(FEE_BASIC, feeNameOf(FEE_BASIC), 0L, productFreight, currency, roundMode, null));
|
||||
payLines.add(feeLine(FEE_REG, feeNameOf(FEE_REG), 0L, baseReg, currency, roundMode, null));
|
||||
r.setPayFeeDetails(payLines);
|
||||
}
|
||||
|
||||
private void applySurchargesAndFees(TmsPriceQuoteResult result)
|
||||
{
|
||||
BigDecimal freightAmount = nvl(result.getFreightAmount());
|
||||
@@ -691,6 +717,7 @@ public class TmsPriceQuoteServiceImpl implements ITmsPriceQuoteService
|
||||
surchargeTotal = surchargeTotal.setScale(2, rm);
|
||||
result.setSurchargeAmount(surchargeTotal);
|
||||
result.setPayableTotal(freightAmount.add(registrationFee).add(surchargeTotal).setScale(2, rm));
|
||||
result.setIncomeTotal(result.getPayableTotal());
|
||||
result.setFeeDetails(lines);
|
||||
}
|
||||
|
||||
@@ -839,6 +866,10 @@ public class TmsPriceQuoteServiceImpl implements ITmsPriceQuoteService
|
||||
quote.setFreightAmount(result.getFreightAmount());
|
||||
quote.setSurchargeAmount(result.getSurchargeAmount());
|
||||
quote.setPayableTotal(result.getPayableTotal());
|
||||
quote.setProductAmount(result.getProductAmount());
|
||||
quote.setRedlineAmount(result.getRedlineAmount());
|
||||
quote.setCostAmount(result.getCostAmount() != null ? result.getCostAmount() : result.getProductAmount());
|
||||
quote.setPayTotal(result.getPayTotal() != null ? result.getPayTotal() : result.getProductAmount());
|
||||
quote.setCurrency(result.getCurrency());
|
||||
quote.setRoundMode(result.getRoundMode());
|
||||
try
|
||||
@@ -901,7 +932,10 @@ public class TmsPriceQuoteServiceImpl implements ITmsPriceQuoteService
|
||||
{
|
||||
quoteFeeMapper.insertBatch(fees);
|
||||
}
|
||||
quoteMapper.updateQuoteAmounts(quoteId, result.getSurchargeAmount(), result.getPayableTotal());
|
||||
BigDecimal cost = result.getCostAmount() != null ? result.getCostAmount() : result.getProductAmount();
|
||||
BigDecimal pay = result.getPayTotal() != null ? result.getPayTotal() : cost;
|
||||
quoteMapper.updateQuoteAmounts(quoteId, result.getSurchargeAmount(), result.getPayableTotal(),
|
||||
result.getProductAmount(), cost, pay);
|
||||
}
|
||||
|
||||
private List<PrcQuoteFee> toFeeRows(String quoteId, TmsPriceQuoteResult result)
|
||||
@@ -962,6 +996,11 @@ public class TmsPriceQuoteServiceImpl implements ITmsPriceQuoteService
|
||||
r.setFreightAmount(quote.getFreightAmount());
|
||||
r.setSurchargeAmount(quote.getSurchargeAmount());
|
||||
r.setPayableTotal(quote.getPayableTotal());
|
||||
r.setProductAmount(quote.getProductAmount());
|
||||
r.setRedlineAmount(quote.getRedlineAmount());
|
||||
r.setCostAmount(quote.getCostAmount());
|
||||
r.setPayTotal(quote.getPayTotal());
|
||||
r.setIncomeTotal(quote.getPayableTotal());
|
||||
r.setCurrency(normalizeCurrency(quote.getCurrency()));
|
||||
r.setRoundMode(quote.getRoundMode());
|
||||
List<TmsPriceQuoteFeeLine> lines = new ArrayList<TmsPriceQuoteFeeLine>();
|
||||
@@ -1013,9 +1052,15 @@ public class TmsPriceQuoteServiceImpl implements ITmsPriceQuoteService
|
||||
to.setFreightAmount(from.getFreightAmount());
|
||||
to.setSurchargeAmount(from.getSurchargeAmount());
|
||||
to.setPayableTotal(from.getPayableTotal());
|
||||
to.setProductAmount(from.getProductAmount());
|
||||
to.setRedlineAmount(from.getRedlineAmount());
|
||||
to.setCostAmount(from.getCostAmount());
|
||||
to.setIncomeTotal(from.getIncomeTotal());
|
||||
to.setPayTotal(from.getPayTotal());
|
||||
to.setCurrency(from.getCurrency());
|
||||
to.setRoundMode(from.getRoundMode());
|
||||
to.setFeeDetails(from.getFeeDetails());
|
||||
to.setPayFeeDetails(from.getPayFeeDetails());
|
||||
}
|
||||
|
||||
private String buildQuoteKey(TmsPriceQuoteRequest request, BigDecimal weight, Date bizDate)
|
||||
|
||||
@@ -7,8 +7,6 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
<resultMap type="BmsProductCountry" id="BmsProductCountryResult">
|
||||
<id property="detailId" column="detail_id" />
|
||||
<result property="productId" column="product_id" />
|
||||
<result property="ppvId" column="ppv_id" />
|
||||
<result property="versionNo" column="version_no" />
|
||||
<result property="productCode" column="product_code" />
|
||||
<result property="countryName" column="country_name" />
|
||||
<result property="countryCode" column="country_code" />
|
||||
@@ -31,13 +29,12 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
</resultMap>
|
||||
|
||||
<sql id="selectVo">
|
||||
select c.detail_id, c.product_id, c.ppv_id, v.version_no, c.product_code, c.country_name, c.country_code,
|
||||
select c.detail_id, c.product_id, c.product_code, c.country_name, c.country_code,
|
||||
c.zone_id, c.zone_code, c.zone_name,
|
||||
c.weight_min, c.weight_max,
|
||||
c.freight_price, c.registration_fee, c.size_limit, c.last_mile, c.lead_time,
|
||||
c.effective_date, c.expire_date, c.status, c.create_time, c.update_time
|
||||
from bms_product_country c
|
||||
left join bms_product_price_version v on v.ppv_id = c.ppv_id
|
||||
from product_country c
|
||||
</sql>
|
||||
|
||||
<select id="selectBmsProductCountryList" parameterType="BmsProductCountry" resultMap="BmsProductCountryResult">
|
||||
@@ -46,9 +43,6 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
<if test="productId != null">
|
||||
AND c.product_id = #{productId}
|
||||
</if>
|
||||
<if test="ppvId != null">
|
||||
AND c.ppv_id = #{ppvId}
|
||||
</if>
|
||||
<if test="productCode != null and productCode != ''">
|
||||
AND c.product_code = #{productCode}
|
||||
</if>
|
||||
@@ -87,23 +81,23 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
</select>
|
||||
|
||||
<insert id="insertBmsProductCountry" parameterType="BmsProductCountry" useGeneratedKeys="true" keyProperty="detailId">
|
||||
insert into bms_product_country (
|
||||
product_id, ppv_id, product_code, country_name, country_code, zone_id, zone_code, zone_name,
|
||||
insert into product_country (
|
||||
product_id, product_code, country_name, country_code, zone_id, zone_code, zone_name,
|
||||
weight_min, weight_max,
|
||||
freight_price, registration_fee, size_limit, last_mile, lead_time,
|
||||
effective_date, expire_date, status, create_time
|
||||
) values (
|
||||
#{productId}, #{ppvId}, #{productCode}, #{countryName}, #{countryCode}, #{zoneId}, #{zoneCode}, #{zoneName},
|
||||
#{productId}, #{productCode}, #{countryName}, #{countryCode}, #{zoneId}, #{zoneCode}, #{zoneName},
|
||||
#{weightMin}, #{weightMax},
|
||||
#{freightPrice}, #{registrationFee}, #{sizeLimit}, #{lastMile}, #{leadTime},
|
||||
#{effectiveDate}, #{expireDate}, IFNULL(#{status}, '0'), sysdate()
|
||||
)
|
||||
</insert>
|
||||
|
||||
<!-- 仅服务于明细编辑弹窗:前端每次提交全量可编辑字段,
|
||||
重量上限/失效日期允许写 null(= 不封顶 / 长期),故不用 <if> 守卫 -->
|
||||
<!-- Detail edit dialog: frontend submits full editable fields;
|
||||
weight_max / expire_date may be null (= open-ended) -->
|
||||
<update id="updateBmsProductCountry" parameterType="BmsProductCountry">
|
||||
update bms_product_country
|
||||
update product_country
|
||||
set weight_min = #{weightMin},
|
||||
weight_max = #{weightMax},
|
||||
freight_price = #{freightPrice},
|
||||
@@ -118,9 +112,8 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
</update>
|
||||
|
||||
<update id="updateBmsProductCountryImport" parameterType="BmsProductCountry">
|
||||
update bms_product_country
|
||||
update product_country
|
||||
set product_id = #{productId},
|
||||
ppv_id = #{ppvId},
|
||||
country_code = #{countryCode},
|
||||
zone_id = #{zoneId},
|
||||
zone_code = #{zoneCode},
|
||||
@@ -139,30 +132,23 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
where detail_id = #{detailId}
|
||||
</update>
|
||||
|
||||
<update id="updatePpvId">
|
||||
update bms_product_country
|
||||
set ppv_id = #{ppvId},
|
||||
update_time = sysdate()
|
||||
where detail_id = #{detailId}
|
||||
</update>
|
||||
|
||||
<delete id="deleteByProductId" parameterType="Long">
|
||||
delete from bms_product_country where product_id = #{productId}
|
||||
delete from product_country where product_id = #{productId}
|
||||
</delete>
|
||||
|
||||
<delete id="deleteByProductCode" parameterType="String">
|
||||
delete from bms_product_country where product_code = #{productCode}
|
||||
delete from product_country where product_code = #{productCode}
|
||||
</delete>
|
||||
|
||||
<delete id="deleteByProductCodes">
|
||||
delete from bms_product_country where product_code in
|
||||
delete from product_country where product_code in
|
||||
<foreach item="code" collection="array" open="(" separator="," close=")">
|
||||
#{code}
|
||||
</foreach>
|
||||
</delete>
|
||||
|
||||
<delete id="deleteByProductCodeAndEffectiveDate">
|
||||
delete from bms_product_country
|
||||
delete from product_country
|
||||
where product_code = #{productCode}
|
||||
and (
|
||||
(#{effectiveDate} is null and effective_date is null)
|
||||
@@ -171,13 +157,13 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
</delete>
|
||||
|
||||
<select id="selectMaxOpenEffectiveDate" resultType="java.util.Date">
|
||||
select max(effective_date) from bms_product_country
|
||||
select max(effective_date) from product_country
|
||||
where product_code = #{productCode}
|
||||
and expire_date is null
|
||||
</select>
|
||||
|
||||
<update id="expireOpenByProductCode">
|
||||
update bms_product_country
|
||||
update product_country
|
||||
set expire_date = #{newEffectiveDate},
|
||||
update_time = sysdate()
|
||||
where product_code = #{productCode}
|
||||
@@ -186,7 +172,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
</update>
|
||||
|
||||
<update id="refreshStatusByDates">
|
||||
update bms_product_country
|
||||
update product_country
|
||||
set status = case
|
||||
when expire_date is not null and expire_date <= curdate() then '2'
|
||||
when effective_date is null or effective_date > curdate() then '0'
|
||||
@@ -195,7 +181,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
</update>
|
||||
|
||||
<delete id="deleteOpenByProductCodeAndEffectiveDate">
|
||||
delete from bms_product_country
|
||||
delete from product_country
|
||||
where product_code = #{productCode}
|
||||
and expire_date is null
|
||||
and (
|
||||
@@ -241,7 +227,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
|
||||
<select id="countZonedByProductCountry" resultType="int">
|
||||
select count(1)
|
||||
from bms_product_country
|
||||
from product_country
|
||||
where product_code = #{productCode}
|
||||
and zone_code is not null and zone_code <> ''
|
||||
<choose>
|
||||
@@ -271,40 +257,20 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
order by c.country_name asc, c.zone_code asc, c.weight_min asc, c.detail_id asc
|
||||
</select>
|
||||
|
||||
<select id="selectByPpvId" resultMap="BmsProductCountryResult">
|
||||
<include refid="selectVo"/>
|
||||
where c.ppv_id = #{ppvId}
|
||||
order by c.country_name asc, c.zone_code asc, c.weight_min asc, c.detail_id asc
|
||||
</select>
|
||||
|
||||
<insert id="copyCountriesFromVersion">
|
||||
insert into bms_product_country (
|
||||
product_id, ppv_id, product_code, country_name, country_code, zone_id, zone_code, zone_name,
|
||||
<insert id="copyOpenCountries">
|
||||
insert into product_country (
|
||||
product_id, product_code, country_name, country_code, zone_id, zone_code, zone_name,
|
||||
weight_min, weight_max, freight_price, registration_fee, size_limit, last_mile, lead_time,
|
||||
effective_date, expire_date, status, create_time
|
||||
)
|
||||
select
|
||||
#{productId}, #{newPpvId}, #{productCode}, country_name, country_code, zone_id, zone_code, zone_name,
|
||||
#{productId}, product_code, country_name, country_code, zone_id, zone_code, zone_name,
|
||||
weight_min, weight_max, freight_price, registration_fee, size_limit, last_mile, lead_time,
|
||||
#{effectiveDate}, null, IFNULL(#{status}, '0'), sysdate()
|
||||
from bms_product_country
|
||||
where ppv_id = #{srcPpvId}
|
||||
order by detail_id asc
|
||||
</insert>
|
||||
|
||||
<insert id="copyOpenCountriesToVersion">
|
||||
insert into bms_product_country (
|
||||
product_id, ppv_id, product_code, country_name, country_code, zone_id, zone_code, zone_name,
|
||||
weight_min, weight_max, freight_price, registration_fee, size_limit, last_mile, lead_time,
|
||||
effective_date, expire_date, status, create_time
|
||||
)
|
||||
select
|
||||
#{productId}, #{newPpvId}, product_code, country_name, country_code, zone_id, zone_code, zone_name,
|
||||
weight_min, weight_max, freight_price, registration_fee, size_limit, last_mile, lead_time,
|
||||
#{effectiveDate}, null, IFNULL(#{status}, '0'), sysdate()
|
||||
from bms_product_country
|
||||
from product_country
|
||||
where product_code = #{productCode}
|
||||
and expire_date is null
|
||||
and (effective_date is null or effective_date < #{effectiveDate})
|
||||
order by detail_id asc
|
||||
</insert>
|
||||
|
||||
|
||||
@@ -31,7 +31,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
select p.product_id, p.product_code, p.product_name, p.service_level, p.cargo_attr,
|
||||
p.dest_region, p.update_note, p.tax_mode, p.effective_date, p.expire_date, p.status,
|
||||
p.source_sheet, p.remark, p.tms_id, p.created_by, p.create_time, p.updated_by, p.update_time,
|
||||
(select count(distinct c.country_name) from bms_product_country c
|
||||
(select count(distinct c.country_name) from product_country c
|
||||
where c.product_id = p.product_id
|
||||
or (c.product_id is null and c.product_code = p.product_code
|
||||
and (
|
||||
@@ -40,7 +40,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
))
|
||||
) as country_count,
|
||||
(select count(*) from prc_surcharge_rel r where r.product_id = p.product_id) as surcharge_count
|
||||
from bms_product p
|
||||
from product p
|
||||
</sql>
|
||||
|
||||
<select id="selectBmsProductById" parameterType="Long" resultMap="BmsProductResult">
|
||||
@@ -127,7 +127,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
</select>
|
||||
|
||||
<insert id="insertBmsProduct" parameterType="BmsProduct" useGeneratedKeys="true" keyProperty="productId">
|
||||
insert into bms_product (
|
||||
insert into product (
|
||||
<if test="productCode != null and productCode != ''">product_code,</if>
|
||||
<if test="productName != null and productName != ''">product_name,</if>
|
||||
<if test="serviceLevel != null">service_level,</if>
|
||||
@@ -163,7 +163,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
</insert>
|
||||
|
||||
<update id="updateBmsProduct" parameterType="BmsProduct">
|
||||
update bms_product
|
||||
update product
|
||||
<set>
|
||||
<if test="productCode != null and productCode != ''">product_code = #{productCode},</if>
|
||||
<if test="productName != null and productName != ''">product_name = #{productName},</if>
|
||||
@@ -185,14 +185,14 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
</update>
|
||||
|
||||
<delete id="deleteBmsProductByIds" parameterType="Long">
|
||||
delete from bms_product where product_id in
|
||||
delete from product where product_id in
|
||||
<foreach item="productId" collection="array" open="(" separator="," close=")">
|
||||
#{productId}
|
||||
</foreach>
|
||||
</delete>
|
||||
|
||||
<update id="expireOpenByProductCode">
|
||||
update bms_product
|
||||
update product
|
||||
set expire_date = #{newEffectiveDate},
|
||||
update_time = sysdate()
|
||||
where product_code = #{productCode}
|
||||
@@ -204,7 +204,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
</update>
|
||||
|
||||
<update id="refreshStatusByDates">
|
||||
update bms_product
|
||||
update product
|
||||
set status = case
|
||||
when expire_date is not null and expire_date <= curdate() then '2'
|
||||
when effective_date is null or effective_date > curdate() then '0'
|
||||
|
||||
@@ -1,123 +0,0 @@
|
||||
<?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.bms.price.mapper.BmsProductPriceVersionMapper">
|
||||
|
||||
<resultMap type="BmsProductPriceVersion" id="BmsProductPriceVersionResult">
|
||||
<id property="ppvId" column="ppv_id" />
|
||||
<result property="productCode" column="product_code" />
|
||||
<result property="productId" column="product_id" />
|
||||
<result property="versionNo" column="version_no" />
|
||||
<result property="versionSeq" column="version_seq" />
|
||||
<result property="effectiveDate" column="effective_date" />
|
||||
<result property="expireDate" column="expire_date" />
|
||||
<result property="status" column="status" />
|
||||
<result property="productCount" column="product_count" />
|
||||
<result property="createBy" column="created_by" />
|
||||
<result property="createTime" column="create_time" />
|
||||
<result property="updateBy" column="updated_by" />
|
||||
<result property="updateTime" column="update_time" />
|
||||
</resultMap>
|
||||
|
||||
<sql id="selectVo">
|
||||
select ppv_id, product_code, product_id, version_no, version_seq,
|
||||
effective_date, expire_date, status,
|
||||
created_by, create_time, updated_by, update_time
|
||||
from bms_product_price_version
|
||||
</sql>
|
||||
|
||||
<select id="selectBmsProductPriceVersionById" parameterType="Long" resultMap="BmsProductPriceVersionResult">
|
||||
<include refid="selectVo"/>
|
||||
where ppv_id = #{ppvId}
|
||||
</select>
|
||||
|
||||
<select id="selectOpenByProductCode" resultMap="BmsProductPriceVersionResult">
|
||||
<include refid="selectVo"/>
|
||||
where product_code = #{productCode}
|
||||
and expire_date is null
|
||||
order by effective_date desc, version_seq desc, ppv_id desc
|
||||
limit 1
|
||||
</select>
|
||||
|
||||
<select id="selectByProductCodeAndEffectiveDate" resultMap="BmsProductPriceVersionResult">
|
||||
<include refid="selectVo"/>
|
||||
where product_code = #{productCode}
|
||||
and effective_date = #{effectiveDate}
|
||||
limit 1
|
||||
</select>
|
||||
|
||||
<select id="selectMaxVersionSeq" resultType="java.lang.Integer">
|
||||
select max(version_seq) from bms_product_price_version where product_code = #{productCode}
|
||||
</select>
|
||||
|
||||
<select id="selectVersionOptions" resultMap="BmsProductPriceVersionResult">
|
||||
select
|
||||
min(ppv_id) as ppv_id,
|
||||
null as product_code,
|
||||
null as product_id,
|
||||
version_no,
|
||||
max(version_seq) as version_seq,
|
||||
max(effective_date) as effective_date,
|
||||
max(expire_date) as expire_date,
|
||||
case
|
||||
when sum(case when expire_date is null then 1 else 0 end) > 0
|
||||
and max(effective_date) <= curdate() then '1'
|
||||
when max(effective_date) > curdate() then '0'
|
||||
else '2'
|
||||
end as status,
|
||||
count(distinct product_code) as product_count,
|
||||
null as created_by,
|
||||
null as create_time,
|
||||
null as updated_by,
|
||||
null as update_time
|
||||
from bms_product_price_version
|
||||
where version_no is not null and version_no <> ''
|
||||
group by version_no
|
||||
order by max(version_seq) desc, version_no desc
|
||||
</select>
|
||||
|
||||
<insert id="insertBmsProductPriceVersion" parameterType="BmsProductPriceVersion" useGeneratedKeys="true" keyProperty="ppvId">
|
||||
insert into bms_product_price_version (
|
||||
product_code, product_id, version_no, version_seq,
|
||||
effective_date, expire_date, status, created_by, create_time
|
||||
) values (
|
||||
#{productCode}, #{productId}, #{versionNo}, #{versionSeq},
|
||||
#{effectiveDate}, #{expireDate}, IFNULL(#{status}, '0'), #{createBy}, sysdate()
|
||||
)
|
||||
</insert>
|
||||
|
||||
<update id="updateBmsProductPriceVersion" parameterType="BmsProductPriceVersion">
|
||||
update bms_product_price_version
|
||||
<set>
|
||||
<if test="productId != null">product_id = #{productId},</if>
|
||||
<if test="versionNo != null and versionNo != ''">version_no = #{versionNo},</if>
|
||||
<if test="versionSeq != null">version_seq = #{versionSeq},</if>
|
||||
<if test="effectiveDate != null">effective_date = #{effectiveDate},</if>
|
||||
expire_date = #{expireDate},
|
||||
<if test="status != null and status != ''">status = #{status},</if>
|
||||
<if test="updateBy != null and updateBy != ''">updated_by = #{updateBy},</if>
|
||||
update_time = sysdate()
|
||||
</set>
|
||||
where ppv_id = #{ppvId}
|
||||
</update>
|
||||
|
||||
<update id="expireOpenByProductCode">
|
||||
update bms_product_price_version
|
||||
set expire_date = #{newEffectiveDate},
|
||||
update_time = sysdate()
|
||||
where product_code = #{productCode}
|
||||
and expire_date is null
|
||||
and (effective_date is null or effective_date < #{newEffectiveDate})
|
||||
</update>
|
||||
|
||||
<update id="refreshStatusByDates">
|
||||
update bms_product_price_version
|
||||
set status = case
|
||||
when expire_date is not null and expire_date <= curdate() then '2'
|
||||
when effective_date is null or effective_date > curdate() then '0'
|
||||
else '1'
|
||||
end
|
||||
</update>
|
||||
|
||||
</mapper>
|
||||
@@ -56,7 +56,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
c.registration_fee as base_registration_fee,
|
||||
d.discount_value, d.round_mode, d.pr_id, d.effective_date, d.expire_date, d.create_time, d.update_time
|
||||
from prc_price_set_detail d
|
||||
left join bms_product_country c on c.detail_id = d.product_country_id
|
||||
left join product_country c on c.detail_id = d.product_country_id
|
||||
<where>
|
||||
<if test="priceSetId != null">
|
||||
AND d.price_set_id = #{priceSetId}
|
||||
@@ -161,21 +161,12 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
c.effective_date,
|
||||
c.expire_date,
|
||||
sysdate()
|
||||
from bms_product_country c
|
||||
inner join bms_product p on p.product_id = c.product_id
|
||||
from product_country c
|
||||
inner join product p on p.product_id = c.product_id
|
||||
<where>
|
||||
<choose>
|
||||
<when test="baseVersionNo != null and baseVersionNo != ''">
|
||||
and exists (
|
||||
select 1 from bms_product_price_version v
|
||||
where v.ppv_id = c.ppv_id
|
||||
and v.version_no = #{baseVersionNo}
|
||||
)
|
||||
</when>
|
||||
<otherwise>
|
||||
and p.status = '1'
|
||||
and p.product_id = (
|
||||
select max(p2.product_id) from bms_product p2
|
||||
select max(p2.product_id) from product p2
|
||||
where p2.product_code = p.product_code and p2.status = '1'
|
||||
)
|
||||
and ifnull(c.status, '1') <> '2'
|
||||
@@ -189,9 +180,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
and (c.expire_date is null or date(c.expire_date) > date(#{asOf}))
|
||||
</otherwise>
|
||||
</choose>
|
||||
</otherwise>
|
||||
</choose>
|
||||
</where>
|
||||
</where>
|
||||
order by p.product_code asc, c.country_name asc, c.zone_code asc, c.weight_min asc, c.detail_id asc
|
||||
</insert>
|
||||
|
||||
@@ -206,26 +195,14 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
p.product_name,
|
||||
'HALF_UP',
|
||||
sysdate()
|
||||
from bms_product p
|
||||
from product p
|
||||
<where>
|
||||
<choose>
|
||||
<when test="baseVersionNo != null and baseVersionNo != ''">
|
||||
and exists (
|
||||
select 1 from bms_product_country c
|
||||
inner join bms_product_price_version v on v.ppv_id = c.ppv_id
|
||||
where c.product_id = p.product_id
|
||||
and v.version_no = #{baseVersionNo}
|
||||
)
|
||||
</when>
|
||||
<otherwise>
|
||||
and p.status = '1'
|
||||
and p.product_id = (
|
||||
select max(p2.product_id) from bms_product p2
|
||||
select max(p2.product_id) from product p2
|
||||
where p2.product_code = p.product_code and p2.status = '1'
|
||||
)
|
||||
</otherwise>
|
||||
</choose>
|
||||
</where>
|
||||
</where>
|
||||
order by p.product_code asc
|
||||
</insert>
|
||||
|
||||
|
||||
@@ -38,6 +38,10 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
<result property="freightAmount" column="freight_amount" />
|
||||
<result property="surchargeAmount" column="surcharge_amount" />
|
||||
<result property="payableTotal" column="payable_total" />
|
||||
<result property="productAmount" column="product_amount" />
|
||||
<result property="redlineAmount" column="redline_amount" />
|
||||
<result property="costAmount" column="cost_amount" />
|
||||
<result property="payTotal" column="pay_total" />
|
||||
<result property="currency" column="currency" />
|
||||
<result property="roundMode" column="round_mode" />
|
||||
<result property="createBy" column="created_by" />
|
||||
@@ -53,7 +57,8 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
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,
|
||||
freight_amount, surcharge_amount, payable_total,
|
||||
product_amount, redline_amount, cost_amount, pay_total, currency, round_mode,
|
||||
created_by, create_time, updated_by, update_time
|
||||
from prc_quote
|
||||
</sql>
|
||||
@@ -113,7 +118,8 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
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,
|
||||
freight_amount, surcharge_amount, payable_total,
|
||||
product_amount, redline_amount, cost_amount, pay_total, currency, round_mode,
|
||||
create_time
|
||||
) values (
|
||||
#{quoteId}, #{quoteKey}, #{customerId}, #{customerCode}, #{productCode}, #{productName},
|
||||
@@ -122,7 +128,8 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
#{setType}, #{bindPriority}, #{customerPricesetId}, #{productCountryId},
|
||||
#{weightMin}, #{weightMax}, #{weightLabel}, #{effectiveDate}, #{chargeWeight},
|
||||
#{freightRate}, #{baseFreightRate}, #{discountPercent}, #{registrationFee},
|
||||
#{freightAmount}, #{surchargeAmount}, #{payableTotal}, #{currency}, #{roundMode},
|
||||
#{freightAmount}, #{surchargeAmount}, #{payableTotal},
|
||||
#{productAmount}, #{redlineAmount}, #{costAmount}, #{payTotal}, #{currency}, #{roundMode},
|
||||
sysdate()
|
||||
)
|
||||
</insert>
|
||||
@@ -131,6 +138,9 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
update prc_quote
|
||||
set surcharge_amount = #{surchargeAmount},
|
||||
payable_total = #{payableTotal},
|
||||
product_amount = #{productAmount},
|
||||
cost_amount = #{costAmount},
|
||||
pay_total = #{payTotal},
|
||||
update_time = sysdate()
|
||||
where quote_id = #{quoteId}
|
||||
</update>
|
||||
|
||||
@@ -36,7 +36,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
c.country_name, c.weight_min, c.weight_max
|
||||
from prc_surcharge_rel r
|
||||
join prc_surcharge s on s.sc_id = r.sc_id
|
||||
left join bms_product_country c on c.detail_id = r.detail_id
|
||||
left join product_country c on c.detail_id = r.detail_id
|
||||
</sql>
|
||||
|
||||
<select id="selectPrcSurchargeRelList" parameterType="PrcSurchargeRel" resultMap="PrcSurchargeRelResult">
|
||||
|
||||
+20
-40
@@ -279,9 +279,9 @@ CREATE TABLE `ar_export_template` (
|
||||
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='应收账单导出模板管理';
|
||||
|
||||
-- ----------------------------
|
||||
-- 表结构:`bms_product`
|
||||
-- 表结构:`product`
|
||||
-- ----------------------------
|
||||
CREATE TABLE `bms_product` (
|
||||
CREATE TABLE `product` (
|
||||
`product_id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '产品ID',
|
||||
`product_code` varchar(20) COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '产品对接代码,如 WSP037',
|
||||
`product_name` varchar(100) COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '产品名称',
|
||||
@@ -304,39 +304,16 @@ CREATE TABLE `bms_product` (
|
||||
UNIQUE KEY `uk_product_code_eff` (`product_code`,`effective_date`),
|
||||
KEY `idx_tax_status` (`tax_mode`,`status`) USING BTREE,
|
||||
KEY `idx_product_code` (`product_code`)
|
||||
) ENGINE=InnoDB AUTO_INCREMENT=28 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='BMS产品主表-来自产品目录';
|
||||
) ENGINE=InnoDB AUTO_INCREMENT=28 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='产品主表-来自产品目录';
|
||||
|
||||
|
||||
|
||||
-- ----------------------------
|
||||
-- 表结构:`bms_product_price_version`
|
||||
-- 表结构:`product_country`
|
||||
-- ----------------------------
|
||||
CREATE TABLE `bms_product_price_version` (
|
||||
`ppv_id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '产品基础价格版本ID',
|
||||
`product_code` varchar(20) COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '产品代码',
|
||||
`product_id` bigint(20) DEFAULT NULL COMMENT '对应 bms_product.product_id(该版本产品行)',
|
||||
`version_no` varchar(20) COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '版本号 V1/V2',
|
||||
`version_seq` int(11) NOT NULL COMMENT '版本序号,用于自动+1',
|
||||
`effective_date` date NOT NULL COMMENT '生效日期',
|
||||
`expire_date` date DEFAULT NULL COMMENT '失效日期(空=长期;下一版生效日=本版失效日)',
|
||||
`status` char(1) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '0' COMMENT '0待生效 1已生效 2已失效',
|
||||
`created_by` varchar(64) COLLATE utf8mb4_unicode_ci DEFAULT '' COMMENT '创建人',
|
||||
`create_time` datetime DEFAULT NULL COMMENT '创建时间',
|
||||
`updated_by` varchar(64) COLLATE utf8mb4_unicode_ci DEFAULT '' COMMENT '更新人',
|
||||
`update_time` datetime DEFAULT NULL COMMENT '更新时间',
|
||||
PRIMARY KEY (`ppv_id`),
|
||||
UNIQUE KEY `uk_ppv_code_seq` (`product_code`,`version_seq`),
|
||||
UNIQUE KEY `uk_ppv_code_eff` (`product_code`,`effective_date`),
|
||||
KEY `idx_ppv_code_status` (`product_code`,`status`),
|
||||
KEY `idx_ppv_product_id` (`product_id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='产品基础价格版本';
|
||||
|
||||
-- ----------------------------
|
||||
-- 表结构:`bms_product_country`
|
||||
-- ----------------------------
|
||||
CREATE TABLE `bms_product_country` (
|
||||
CREATE TABLE `product_country` (
|
||||
`detail_id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '明细ID',
|
||||
`product_id` bigint(20) DEFAULT NULL COMMENT '产品ID(bms_product.product_id,绑定具体产品版本行)',
|
||||
`ppv_id` bigint(20) DEFAULT NULL COMMENT '产品基础价格版本ID bms_product_price_version.ppv_id',
|
||||
`product_id` bigint(20) DEFAULT NULL COMMENT '产品ID(product.product_id,绑定具体产品版本行)',
|
||||
`product_code` varchar(20) COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '产品代码',
|
||||
`country_name` varchar(50) COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '国家中文名',
|
||||
`country_code` char(2) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT 'ISO2,可空待补齐',
|
||||
@@ -361,10 +338,9 @@ CREATE TABLE `bms_product_country` (
|
||||
KEY `idx_weight_match` (`product_code`,`country_code`,`weight_min`,`weight_max`) USING BTREE,
|
||||
KEY `idx_product_eff` (`product_code`,`effective_date`,`expire_date`),
|
||||
KEY `idx_product_country_pid` (`product_id`),
|
||||
KEY `idx_product_country_ppv` (`ppv_id`),
|
||||
KEY `idx_product_country_zone` (`zone_id`),
|
||||
KEY `idx_product_country_zone_code` (`country_code`,`zone_code`),
|
||||
CONSTRAINT `fk_product_country_pid` FOREIGN KEY (`product_id`) REFERENCES `bms_product` (`product_id`) ON DELETE CASCADE
|
||||
CONSTRAINT `fk_product_country_pid` FOREIGN KEY (`product_id`) REFERENCES `product` (`product_id`) ON DELETE CASCADE
|
||||
) ENGINE=InnoDB AUTO_INCREMENT=1609 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='产品国家服务明细-重量段+尺寸/尾程/时效(不含运费)';
|
||||
|
||||
-- ----------------------------
|
||||
@@ -978,7 +954,7 @@ CREATE TABLE `prc_order_bill` (
|
||||
`customer_priceset_id` bigint(20) DEFAULT NULL COMMENT '客户套餐绑定ID',
|
||||
`psv_id` bigint(20) DEFAULT NULL COMMENT '套餐版本ID,对应 prc_price_set_version.psv_id',
|
||||
`psd_id` bigint(20) DEFAULT NULL COMMENT '套餐明细ID,对应 prc_price_set_detail.psd_id',
|
||||
`product_country_id` bigint(20) DEFAULT NULL COMMENT '关联 bms_product_country.detail_id',
|
||||
`product_country_id` bigint(20) DEFAULT NULL COMMENT '关联 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 '重量段展示',
|
||||
@@ -1291,7 +1267,7 @@ CREATE TABLE `prc_price_set_detail` (
|
||||
`weight_label` varchar(50) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '重量段展示',
|
||||
`weight_min` decimal(10,3) DEFAULT NULL COMMENT '重量段最小值KG(含)',
|
||||
`weight_max` decimal(10,3) DEFAULT NULL COMMENT '重量段最大值KG(含)',
|
||||
`product_country_id` bigint(20) DEFAULT NULL COMMENT 'bms_product_country.detail_id',
|
||||
`product_country_id` bigint(20) DEFAULT NULL COMMENT 'product_country.detail_id',
|
||||
`fv_value` decimal(10,4) DEFAULT NULL COMMENT '运费单价 RMB/KG',
|
||||
`fv_registration_fee` decimal(10,2) DEFAULT NULL COMMENT '挂号费 RMB/票',
|
||||
`discount_value` decimal(5,2) DEFAULT NULL COMMENT '明细折扣百分数,DISCOUNT 可覆盖默认',
|
||||
@@ -1392,7 +1368,7 @@ CREATE TABLE `prc_quote` (
|
||||
`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',
|
||||
`product_country_id` bigint(20) DEFAULT NULL COMMENT '关联 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 '重量段展示',
|
||||
@@ -1404,7 +1380,11 @@ CREATE TABLE `prc_quote` (
|
||||
`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 '应付总额',
|
||||
`payable_total` decimal(10,2) DEFAULT NULL COMMENT '销售价/应收试算合计',
|
||||
`product_amount` decimal(18,4) DEFAULT NULL COMMENT '产品价合计',
|
||||
`redline_amount` decimal(18,4) DEFAULT NULL COMMENT '红线价合计',
|
||||
`cost_amount` decimal(18,4) DEFAULT NULL COMMENT '成本价合计(当前等于产品目录价)',
|
||||
`pay_total` decimal(18,4) 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 '创建人',
|
||||
@@ -1470,9 +1450,9 @@ CREATE TABLE `prc_surcharge` (
|
||||
CREATE TABLE `prc_surcharge_rel` (
|
||||
`rel_id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '关联ID',
|
||||
`sc_id` bigint(20) NOT NULL COMMENT '附加费配置ID prc_surcharge.sc_id',
|
||||
`product_id` bigint(20) NOT NULL COMMENT '产品ID bms_product.product_id',
|
||||
`product_code` varchar(20) COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '产品对接代码 bms_product.product_code',
|
||||
`detail_id` bigint(20) DEFAULT NULL COMMENT '产品明细ID bms_product_country.detail_id(空=作用于产品全部明细)',
|
||||
`product_id` bigint(20) NOT NULL COMMENT '产品ID product.product_id',
|
||||
`product_code` varchar(20) COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '产品对接代码 product.product_code',
|
||||
`detail_id` bigint(20) DEFAULT NULL COMMENT '产品明细ID product_country.detail_id(空=作用于产品全部明细)',
|
||||
`created_by` varchar(64) COLLATE utf8mb4_unicode_ci DEFAULT '' COMMENT '创建人',
|
||||
`create_time` datetime DEFAULT NULL,
|
||||
`updated_by` varchar(64) COLLATE utf8mb4_unicode_ci DEFAULT '' COMMENT '更新人',
|
||||
@@ -1483,7 +1463,7 @@ CREATE TABLE `prc_surcharge_rel` (
|
||||
KEY `idx_rel_product` (`product_id`),
|
||||
KEY `idx_rel_product_code` (`product_code`),
|
||||
KEY `idx_rel_detail` (`detail_id`),
|
||||
CONSTRAINT `fk_rel_product` FOREIGN KEY (`product_id`) REFERENCES `bms_product` (`product_id`) ON DELETE CASCADE,
|
||||
CONSTRAINT `fk_rel_product` FOREIGN KEY (`product_id`) REFERENCES `product` (`product_id`) ON DELETE CASCADE,
|
||||
CONSTRAINT `fk_rel_sc` FOREIGN KEY (`sc_id`) REFERENCES `prc_surcharge` (`sc_id`) ON DELETE CASCADE
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='附加费与产品/明细关联表';
|
||||
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
-- prc_quote: product / cost amounts (run once on existing DB)
|
||||
SET @col_exists := (
|
||||
SELECT COUNT(1) FROM information_schema.COLUMNS
|
||||
WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'prc_quote' AND COLUMN_NAME = 'product_amount'
|
||||
);
|
||||
SET @sql := IF(@col_exists = 0,
|
||||
CONCAT(
|
||||
'ALTER TABLE `prc_quote` ',
|
||||
'ADD COLUMN `product_amount` decimal(18,4) DEFAULT NULL COMMENT ''产品价合计'' AFTER `payable_total`, ',
|
||||
'ADD COLUMN `redline_amount` decimal(18,4) DEFAULT NULL COMMENT ''红线价合计'' AFTER `product_amount`, ',
|
||||
'ADD COLUMN `cost_amount` decimal(18,4) DEFAULT NULL COMMENT ''成本价合计(当前等于产品目录价)'' AFTER `redline_amount`, ',
|
||||
'ADD COLUMN `pay_total` decimal(18,4) DEFAULT NULL COMMENT ''应付合计(当前等于成本价)'' AFTER `cost_amount`'
|
||||
),
|
||||
'SELECT 1');
|
||||
PREPARE stmt FROM @sql;
|
||||
EXECUTE stmt;
|
||||
DEALLOCATE PREPARE stmt;
|
||||
@@ -1,98 +0,0 @@
|
||||
-- Product base price version: table + bms_product_country.ppv_id
|
||||
-- Run once on existing DB. New installs: see bms_init.sql
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `bms_product_price_version` (
|
||||
`ppv_id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '产品基础价格版本ID',
|
||||
`product_code` varchar(20) COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '产品代码',
|
||||
`product_id` bigint(20) DEFAULT NULL COMMENT '对应 bms_product.product_id(该版本产品行)',
|
||||
`version_no` varchar(20) COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '版本号 V1/V2',
|
||||
`version_seq` int(11) NOT NULL COMMENT '版本序号,用于自动+1',
|
||||
`effective_date` date NOT NULL COMMENT '生效日期',
|
||||
`expire_date` date DEFAULT NULL COMMENT '失效日期(空=长期;下一版生效日=本版失效日)',
|
||||
`status` char(1) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '0' COMMENT '0待生效 1已生效 2已失效',
|
||||
`created_by` varchar(64) COLLATE utf8mb4_unicode_ci DEFAULT '' COMMENT '创建人',
|
||||
`create_time` datetime DEFAULT NULL COMMENT '创建时间',
|
||||
`updated_by` varchar(64) COLLATE utf8mb4_unicode_ci DEFAULT '' COMMENT '更新人',
|
||||
`update_time` datetime DEFAULT NULL COMMENT '更新时间',
|
||||
PRIMARY KEY (`ppv_id`),
|
||||
UNIQUE KEY `uk_ppv_code_seq` (`product_code`,`version_seq`),
|
||||
UNIQUE KEY `uk_ppv_code_eff` (`product_code`,`effective_date`),
|
||||
KEY `idx_ppv_code_status` (`product_code`,`status`),
|
||||
KEY `idx_ppv_product_id` (`product_id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='产品基础价格版本';
|
||||
|
||||
SET @col_exists := (
|
||||
SELECT COUNT(1) FROM information_schema.COLUMNS
|
||||
WHERE TABLE_SCHEMA = DATABASE()
|
||||
AND TABLE_NAME = 'bms_product_country'
|
||||
AND COLUMN_NAME = 'ppv_id'
|
||||
);
|
||||
SET @sql := IF(@col_exists = 0,
|
||||
'ALTER TABLE `bms_product_country` ADD COLUMN `ppv_id` bigint(20) DEFAULT NULL COMMENT ''产品基础价格版本ID bms_product_price_version.ppv_id'' AFTER `product_id`, ADD KEY `idx_product_country_ppv` (`ppv_id`)',
|
||||
'SELECT 1');
|
||||
PREPARE stmt FROM @sql;
|
||||
EXECUTE stmt;
|
||||
DEALLOCATE PREPARE stmt;
|
||||
|
||||
INSERT INTO `bms_product_price_version` (
|
||||
product_code, product_id, version_no, version_seq, effective_date, expire_date, status, created_by, create_time
|
||||
)
|
||||
SELECT
|
||||
t.product_code,
|
||||
(
|
||||
SELECT p.product_id FROM bms_product p
|
||||
WHERE p.product_code = t.product_code
|
||||
AND p.effective_date = t.effective_date
|
||||
ORDER BY p.product_id ASC
|
||||
LIMIT 1
|
||||
) AS product_id,
|
||||
CONCAT('V', t.version_seq) AS version_no,
|
||||
t.version_seq,
|
||||
t.effective_date,
|
||||
t.expire_date,
|
||||
CASE
|
||||
WHEN t.expire_date IS NOT NULL AND t.expire_date <= CURDATE() THEN '2'
|
||||
WHEN t.effective_date > CURDATE() THEN '0'
|
||||
ELSE '1'
|
||||
END AS status,
|
||||
'migrate' AS created_by,
|
||||
NOW() AS create_time
|
||||
FROM (
|
||||
SELECT
|
||||
g.product_code,
|
||||
g.effective_date,
|
||||
g.expire_date,
|
||||
(
|
||||
SELECT COUNT(1)
|
||||
FROM (
|
||||
SELECT product_code, effective_date
|
||||
FROM bms_product_country
|
||||
WHERE effective_date IS NOT NULL
|
||||
GROUP BY product_code, effective_date
|
||||
) earlier
|
||||
WHERE earlier.product_code = g.product_code
|
||||
AND earlier.effective_date <= g.effective_date
|
||||
) AS version_seq
|
||||
FROM (
|
||||
SELECT
|
||||
product_code,
|
||||
effective_date,
|
||||
MAX(expire_date) AS expire_date
|
||||
FROM bms_product_country
|
||||
WHERE effective_date IS NOT NULL
|
||||
GROUP BY product_code, effective_date
|
||||
) g
|
||||
) t
|
||||
WHERE NOT EXISTS (
|
||||
SELECT 1 FROM bms_product_price_version v
|
||||
WHERE v.product_code = t.product_code
|
||||
AND v.effective_date = t.effective_date
|
||||
);
|
||||
|
||||
UPDATE bms_product_country c
|
||||
INNER JOIN bms_product_price_version v
|
||||
ON v.product_code = c.product_code
|
||||
AND v.effective_date = c.effective_date
|
||||
SET c.ppv_id = v.ppv_id
|
||||
WHERE c.ppv_id IS NULL
|
||||
AND c.effective_date IS NOT NULL;
|
||||
@@ -0,0 +1,91 @@
|
||||
-- Rename product tables (drop bms_ prefix) and remove base price version
|
||||
SET NAMES utf8mb4;
|
||||
|
||||
-- 1) Drop FK from country -> product if present
|
||||
SET @fk := (
|
||||
SELECT CONSTRAINT_NAME FROM information_schema.TABLE_CONSTRAINTS
|
||||
WHERE TABLE_SCHEMA = DATABASE()
|
||||
AND TABLE_NAME = 'bms_product_country'
|
||||
AND CONSTRAINT_TYPE = 'FOREIGN KEY'
|
||||
AND CONSTRAINT_NAME = 'fk_product_country_pid'
|
||||
LIMIT 1
|
||||
);
|
||||
SET @sql := IF(@fk IS NULL, 'SELECT 1', CONCAT('ALTER TABLE bms_product_country DROP FOREIGN KEY ', @fk));
|
||||
PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;
|
||||
|
||||
-- 2) Drop version index / column on country
|
||||
SET @idx := (
|
||||
SELECT INDEX_NAME FROM information_schema.STATISTICS
|
||||
WHERE TABLE_SCHEMA = DATABASE()
|
||||
AND TABLE_NAME = 'bms_product_country'
|
||||
AND INDEX_NAME = 'idx_product_country_ppv'
|
||||
LIMIT 1
|
||||
);
|
||||
SET @sql := IF(@idx IS NULL, 'SELECT 1', 'ALTER TABLE bms_product_country DROP INDEX idx_product_country_ppv');
|
||||
PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;
|
||||
|
||||
SET @col := (
|
||||
SELECT COLUMN_NAME FROM information_schema.COLUMNS
|
||||
WHERE TABLE_SCHEMA = DATABASE()
|
||||
AND TABLE_NAME = 'bms_product_country'
|
||||
AND COLUMN_NAME = 'ppv_id'
|
||||
LIMIT 1
|
||||
);
|
||||
SET @sql := IF(@col IS NULL, 'SELECT 1', 'ALTER TABLE bms_product_country DROP COLUMN ppv_id');
|
||||
PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;
|
||||
|
||||
-- Also handle already-renamed country table
|
||||
SET @idx := (
|
||||
SELECT INDEX_NAME FROM information_schema.STATISTICS
|
||||
WHERE TABLE_SCHEMA = DATABASE()
|
||||
AND TABLE_NAME = 'product_country'
|
||||
AND INDEX_NAME = 'idx_product_country_ppv'
|
||||
LIMIT 1
|
||||
);
|
||||
SET @sql := IF(@idx IS NULL, 'SELECT 1', 'ALTER TABLE product_country DROP INDEX idx_product_country_ppv');
|
||||
PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;
|
||||
|
||||
SET @col := (
|
||||
SELECT COLUMN_NAME FROM information_schema.COLUMNS
|
||||
WHERE TABLE_SCHEMA = DATABASE()
|
||||
AND TABLE_NAME = 'product_country'
|
||||
AND COLUMN_NAME = 'ppv_id'
|
||||
LIMIT 1
|
||||
);
|
||||
SET @sql := IF(@col IS NULL, 'SELECT 1', 'ALTER TABLE product_country DROP COLUMN ppv_id');
|
||||
PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;
|
||||
|
||||
-- 3) Drop version table
|
||||
DROP TABLE IF EXISTS bms_product_price_version;
|
||||
DROP TABLE IF EXISTS product_price_version;
|
||||
|
||||
-- 4) Rename tables (skip if already renamed)
|
||||
SET @t := (
|
||||
SELECT TABLE_NAME FROM information_schema.TABLES
|
||||
WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'bms_product' LIMIT 1
|
||||
);
|
||||
SET @sql := IF(@t IS NULL, 'SELECT 1', 'RENAME TABLE bms_product TO product');
|
||||
PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;
|
||||
|
||||
SET @t := (
|
||||
SELECT TABLE_NAME FROM information_schema.TABLES
|
||||
WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'bms_product_country' LIMIT 1
|
||||
);
|
||||
SET @sql := IF(@t IS NULL, 'SELECT 1', 'RENAME TABLE bms_product_country TO product_country');
|
||||
PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;
|
||||
|
||||
-- 5) Recreate FK product_country.product_id -> product.product_id
|
||||
SET @fk := (
|
||||
SELECT CONSTRAINT_NAME FROM information_schema.TABLE_CONSTRAINTS
|
||||
WHERE TABLE_SCHEMA = DATABASE()
|
||||
AND TABLE_NAME = 'product_country'
|
||||
AND CONSTRAINT_TYPE = 'FOREIGN KEY'
|
||||
AND CONSTRAINT_NAME = 'fk_product_country_pid'
|
||||
LIMIT 1
|
||||
);
|
||||
SET @sql := IF(
|
||||
@fk IS NOT NULL,
|
||||
'SELECT 1',
|
||||
'ALTER TABLE product_country ADD CONSTRAINT fk_product_country_pid FOREIGN KEY (product_id) REFERENCES product (product_id) ON DELETE CASCADE'
|
||||
);
|
||||
PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;
|
||||
@@ -113,9 +113,16 @@
|
||||
<el-descriptions-item label="运费金额">{{ formatMoney(result.freightAmount) }}</el-descriptions-item>
|
||||
<el-descriptions-item label="挂号费">{{ formatMoney(result.registrationFee) }}</el-descriptions-item>
|
||||
<el-descriptions-item label="附加费">{{ formatMoney(result.surchargeAmount) }}</el-descriptions-item>
|
||||
<el-descriptions-item label="应付总额">
|
||||
<el-descriptions-item label="产品价">{{ formatMoney(result.productAmount) }}</el-descriptions-item>
|
||||
<el-descriptions-item label="成本价">
|
||||
<span class="cost">{{ formatMoney(result.costAmount != null ? result.costAmount : result.payTotal) }}</span>
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="应收总额">
|
||||
<span class="payable">{{ formatMoney(result.payableTotal) }}</span>
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="应付总额">
|
||||
<span class="cost">{{ formatMoney(result.payTotal != null ? result.payTotal : result.costAmount) }}</span>
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="试算来源">
|
||||
<el-tag v-if="result.fromCache" size="small" type="success">命中历史试算</el-tag>
|
||||
<el-tag v-else size="small" type="primary">实时计算并落库</el-tag>
|
||||
@@ -152,7 +159,7 @@
|
||||
<template #default="{ row }">{{ row.remark || '-' }}</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<div class="formula-tip">计算公式:运费金额 = 运费单价 × 计费重量;应付总额 = 运费金额 + 挂号费 + 附加费。相同试算参数直接返回已落库费用明细。</div>
|
||||
<div class="formula-tip">销售试算:运费金额 = 套餐运费单价 × 计费重量;应收总额 = 运费金额 + 挂号费 + 附加费。产品价/成本价 = 目录运费单价 × 计费重量 + 目录挂号费。相同试算参数直接返回已落库明细。</div>
|
||||
</div>
|
||||
</el-card>
|
||||
</el-col>
|
||||
@@ -176,6 +183,9 @@
|
||||
<template #col-matchSource="{ row }">
|
||||
<el-tag size="small" :type="sourceTagType(row.matchSource)">{{ sourceLabel(row.matchSource) }}</el-tag>
|
||||
</template>
|
||||
<template #col-costAmount="{ row }">
|
||||
<span class="cost">{{ formatMoney(row.costAmount != null ? row.costAmount : row.payTotal) }}</span>
|
||||
</template>
|
||||
<template #col-payableTotal="{ row }">
|
||||
<span class="payable">{{ formatMoney(row.payableTotal) }}</span>
|
||||
</template>
|
||||
@@ -205,9 +215,16 @@
|
||||
<el-descriptions-item label="运费金额">{{ formatMoney(viewResult.freightAmount) }}</el-descriptions-item>
|
||||
<el-descriptions-item label="挂号费">{{ formatMoney(viewResult.registrationFee) }}</el-descriptions-item>
|
||||
<el-descriptions-item label="附加费">{{ formatMoney(viewResult.surchargeAmount) }}</el-descriptions-item>
|
||||
<el-descriptions-item label="应付总额">
|
||||
<el-descriptions-item label="产品价">{{ formatMoney(viewResult.productAmount) }}</el-descriptions-item>
|
||||
<el-descriptions-item label="成本价">
|
||||
<span class="cost">{{ formatMoney(viewResult.costAmount != null ? viewResult.costAmount : viewResult.payTotal) }}</span>
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="应收总额">
|
||||
<span class="payable">{{ formatMoney(viewResult.payableTotal) }}</span>
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="应付总额">
|
||||
<span class="cost">{{ formatMoney(viewResult.payTotal != null ? viewResult.payTotal : viewResult.costAmount) }}</span>
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="命中说明" :span="2">{{ viewResult.matchMessage || '-' }}</el-descriptions-item>
|
||||
</el-descriptions>
|
||||
<el-table
|
||||
@@ -269,7 +286,9 @@ const historyColumns = [
|
||||
{ label: '计费日期', prop: 'bizDate', align: 'center', width: 120 },
|
||||
{ label: '计价来源', prop: 'matchSource', align: 'center', width: 140, slot: 'matchSource' },
|
||||
{ label: '套餐', prop: 'priceSetName', minWidth: 120, showOverflowTooltip: true },
|
||||
{ label: '应付总额', prop: 'payableTotal', align: 'right', width: 120, slot: 'payableTotal' },
|
||||
{ label: '产品价', prop: 'productAmount', align: 'right', width: 110 },
|
||||
{ label: '成本价', prop: 'costAmount', align: 'right', width: 110, slot: 'costAmount' },
|
||||
{ label: '应收总额', prop: 'payableTotal', align: 'right', width: 120, slot: 'payableTotal' },
|
||||
{ label: '创建时间', prop: 'createTime', align: 'center', width: 170, parseTime: true },
|
||||
{ label: '操作', prop: 'action', align: 'center', width: 90, fixed: 'right', slot: 'action', showInToolbar: false }
|
||||
]
|
||||
@@ -505,7 +524,11 @@ loadProducts()
|
||||
font-size: 12px;
|
||||
line-height: 1.4;
|
||||
}
|
||||
.billing-quote .payable {
|
||||
.billing-quote .cost {
|
||||
color: #d48806;
|
||||
font-weight: 600;
|
||||
}
|
||||
.payable {
|
||||
color: #f56c6c;
|
||||
font-size: 18px;
|
||||
font-weight: 600;
|
||||
|
||||
@@ -24,7 +24,7 @@ import {
|
||||
export function usePriceSetRefData() {
|
||||
/** 产品下拉选项 */
|
||||
const productOptions = ref([])
|
||||
/** productCode -> bms_product_country 行 */
|
||||
/** productCode -> product_country 行 */
|
||||
const countryCache = reactive({})
|
||||
/** productCode -> 进行中的国家明细请求(去重,避免 hydrate 按行打爆接口) */
|
||||
const countryPending = {}
|
||||
@@ -323,7 +323,7 @@ export function useDetailCascade(refData) {
|
||||
row.weightLabel = formatWeightLabel(row.weightMin, row.weightMax)
|
||||
}
|
||||
row._countryKey = countryKeyOf(row)
|
||||
// Keep package prices in fv*; product base is stamped later from bms_product_country.
|
||||
// Keep package prices in fv*; product base is stamped later from product_country.
|
||||
return row
|
||||
}
|
||||
refData.ensureCountries(row.productCode).then(rows => {
|
||||
|
||||
@@ -178,7 +178,7 @@ export function matchCountryZone(detail, item) {
|
||||
|
||||
/**
|
||||
* 国家下拉选项(按产品的国家配置去重)
|
||||
* @param {Array} rows bms_product_country 行
|
||||
* @param {Array} rows product_country 行
|
||||
* @returns {Array<{key, code, name, label}>}
|
||||
*/
|
||||
export function buildCountryOptions(rows) {
|
||||
@@ -198,7 +198,7 @@ export function buildCountryOptions(rows) {
|
||||
|
||||
/**
|
||||
* 重量段下拉选项(按已选国家过滤去重)
|
||||
* @param {Array} rows bms_product_country 行
|
||||
* @param {Array} rows product_country 行
|
||||
* @param {Object} row 当前明细行(含国家)
|
||||
* @returns {Array<{value, label, detailId, freightPrice, registrationFee}>}
|
||||
*/
|
||||
@@ -311,7 +311,7 @@ export function createEmptyDetailRow() {
|
||||
productCountryId: undefined,
|
||||
fvValue: undefined,
|
||||
fvRegistrationFee: undefined,
|
||||
/** product default freight when copied from bms_product_country */
|
||||
/** product default freight when copied from product_country */
|
||||
_baseFreight: undefined,
|
||||
/** product default registration fee */
|
||||
_baseReg: undefined,
|
||||
|
||||
Reference in New Issue
Block a user