Merge branch 'master' of http://git.lionquexpress.com/wuweihua/BMS
This commit is contained in:
+13
@@ -35,6 +35,13 @@ public class CustomerReceipt extends BaseEntity
|
||||
/** 收款类型:混合 */
|
||||
public static final String TYPE_MIXED = "MIXED";
|
||||
|
||||
/** 汇率来源:系统默认(本币CNY 1:1) */
|
||||
public static final String RATE_SOURCE_SYSTEM = "SYSTEM";
|
||||
/** 汇率来源:汇率表(收款日即期汇率自动带出) */
|
||||
public static final String RATE_SOURCE_RATE_TABLE = "RATE_TABLE";
|
||||
/** 汇率来源:手工修改/手工录入 */
|
||||
public static final String RATE_SOURCE_MANUAL = "MANUAL";
|
||||
|
||||
/** 主键 */
|
||||
private Long id;
|
||||
|
||||
@@ -65,6 +72,12 @@ public class CustomerReceipt extends BaseEntity
|
||||
/** 对CNY汇率(1原币=?CNY,CNY为1;默认取汇率表,可手工修改) */
|
||||
private BigDecimal exchangeRate;
|
||||
|
||||
/** 汇率来源:SYSTEM系统默认(本币1:1)/RATE_TABLE汇率表/MANUAL手工修改 */
|
||||
private String rateSource;
|
||||
|
||||
/** 汇率来源说明(汇率表来源及命中路径,或手工录入说明) */
|
||||
private String rateSourceDesc;
|
||||
|
||||
/** 本位币金额(CNY,原币金额×汇率) */
|
||||
private BigDecimal baseAmount;
|
||||
|
||||
|
||||
+78
-5
@@ -130,25 +130,65 @@ public class CustomerMoneyServiceImpl implements ICustomerMoneyService
|
||||
{
|
||||
receipt.setCurrency(receipt.getCurrency().trim().toUpperCase());
|
||||
}
|
||||
// 汇率与本位币金额:CNY 固定 1:1;外币默认取汇率表即期汇率,也允许页面手工修改后传入
|
||||
// 汇率与本位币金额:CNY 固定 1:1;外币以收款日即期汇率表为基准,允许页面手工修改。
|
||||
// 汇率来源由后端权威判定(不信任前端标记):与汇率表一致=RATE_TABLE,不一致/表未配置=MANUAL。
|
||||
BigDecimal rate = receipt.getExchangeRate();
|
||||
if (BASE_CURRENCY.equals(receipt.getCurrency()))
|
||||
{
|
||||
rate = BigDecimal.ONE;
|
||||
receipt.setRateSource(CustomerReceipt.RATE_SOURCE_SYSTEM);
|
||||
receipt.setRateSourceDesc("系统默认(本位币1:1)");
|
||||
}
|
||||
else
|
||||
{
|
||||
Date bizDate = receipt.getReceivedAt() != null ? receipt.getReceivedAt() : new Date();
|
||||
BmsExchangeRate tableRate = null;
|
||||
try
|
||||
{
|
||||
tableRate = exchangeRateService.resolveRate(
|
||||
receipt.getCurrency(), BASE_CURRENCY, BmsExchangeRate.RATE_TYPE_SPOT, bizDate);
|
||||
}
|
||||
catch (ServiceException ex)
|
||||
{
|
||||
// 汇率表未配置:若页面手工录了有效汇率则放行,否则继续走下面的非空校验拦截
|
||||
tableRate = null;
|
||||
}
|
||||
|
||||
if (rate == null || rate.compareTo(BigDecimal.ZERO) <= 0)
|
||||
{
|
||||
Date bizDate = receipt.getReceivedAt() != null ? receipt.getReceivedAt() : new Date();
|
||||
BmsExchangeRate rateConfig = exchangeRateService.resolveRate(
|
||||
receipt.getCurrency(), BASE_CURRENCY, BmsExchangeRate.RATE_TYPE_SPOT, bizDate);
|
||||
rate = rateConfig.getExchangeRate();
|
||||
if (tableRate == null)
|
||||
{
|
||||
throw new ServiceException("汇率表未维护【" + receipt.getCurrency()
|
||||
+ " → CNY】收款日生效的即期汇率,请手工录入汇率");
|
||||
}
|
||||
rate = tableRate.getExchangeRate();
|
||||
}
|
||||
if (rate.compareTo(BigDecimal.ZERO) <= 0)
|
||||
{
|
||||
throw new ServiceException("汇率必须大于0,请检查录入的汇率");
|
||||
}
|
||||
rate = rate.setScale(8, RoundingMode.HALF_UP);
|
||||
|
||||
// 与汇率表汇率一致(8位精度)即认定为汇率表来源,否则为手工修改
|
||||
if (tableRate != null
|
||||
&& rate.compareTo(tableRate.getExchangeRate().setScale(8, RoundingMode.HALF_UP)) == 0)
|
||||
{
|
||||
receipt.setRateSource(CustomerReceipt.RATE_SOURCE_RATE_TABLE);
|
||||
receipt.setRateSourceDesc(buildRateTableSourceDesc(tableRate));
|
||||
}
|
||||
else
|
||||
{
|
||||
receipt.setRateSource(CustomerReceipt.RATE_SOURCE_MANUAL);
|
||||
if (tableRate != null)
|
||||
{
|
||||
receipt.setRateSourceDesc("手工修改(汇率表即期汇率 "
|
||||
+ tableRate.getExchangeRate().setScale(8, RoundingMode.HALF_UP).toPlainString() + ")");
|
||||
}
|
||||
else
|
||||
{
|
||||
receipt.setRateSourceDesc("手工录入(汇率表未维护该币种收款日汇率)");
|
||||
}
|
||||
}
|
||||
}
|
||||
receipt.setExchangeRate(rate.setScale(8, RoundingMode.HALF_UP));
|
||||
BigDecimal baseAmount = receipt.getAmount().multiply(rate).setScale(MONEY_SCALE, RoundingMode.HALF_UP);
|
||||
@@ -171,6 +211,39 @@ public class CustomerMoneyServiceImpl implements ICustomerMoneyService
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* 构造汇率表来源说明:汇率来源(中国银行/央行等)+ 命中路径(正向/反向取倒数/经CNY交叉)。
|
||||
* resolveRate 返回对象的 remark 带 __RATE_PATH__ 前缀标记命中路径。
|
||||
*/
|
||||
private String buildRateTableSourceDesc(BmsExchangeRate tableRate)
|
||||
{
|
||||
String source = StringUtils.hasText(tableRate.getSource()) ? tableRate.getSource() : "汇率表";
|
||||
String path = "DIRECT";
|
||||
String remark = tableRate.getRemark();
|
||||
if (StringUtils.hasText(remark) && remark.startsWith("__RATE_PATH__"))
|
||||
{
|
||||
path = remark.substring("__RATE_PATH__".length());
|
||||
}
|
||||
String pathText;
|
||||
switch (path)
|
||||
{
|
||||
case "REVERSE":
|
||||
pathText = "反向配置取倒数";
|
||||
break;
|
||||
case "CROSS":
|
||||
pathText = "经CNY交叉换算";
|
||||
break;
|
||||
case "SAME":
|
||||
pathText = "同币种";
|
||||
break;
|
||||
case "DIRECT":
|
||||
default:
|
||||
pathText = "正向配置";
|
||||
break;
|
||||
}
|
||||
return "汇率表·" + source + "(" + pathText + ")";
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public int confirmReceipt(Long id)
|
||||
|
||||
+13
-1
@@ -78,7 +78,7 @@ public class BmsExchangeRateServiceImpl implements IBmsExchangeRateService
|
||||
String from = normalizeCurrency(fromCurrency);
|
||||
String to = normalizeCurrency(toCurrency);
|
||||
String type = StringUtils.isNotEmpty(rateType) ? rateType : BmsExchangeRate.RATE_TYPE_SPOT;
|
||||
Date date = bizDate != null ? bizDate : DateUtils.getNowDate();
|
||||
Date date = truncateToDay(bizDate != null ? bizDate : DateUtils.getNowDate());
|
||||
|
||||
// 同币种
|
||||
if (from.equals(to))
|
||||
@@ -147,6 +147,18 @@ public class BmsExchangeRateServiceImpl implements IBmsExchangeRateService
|
||||
|
||||
/* ============================ 私有方法 ============================ */
|
||||
|
||||
/**
|
||||
* 截断到日历日 00:00:00。
|
||||
* 汇率表 effective_date/expire_date 为 date 类型(精确到天),业务时间(如收款时间带时分秒)
|
||||
* 直接参与比较时,"失效日当天"会因 expire_date 被提升为当天 00:00:00 而提前失效,
|
||||
* 故所有业务日统一按日历日落入 [生效日, 失效日] 闭区间。
|
||||
*/
|
||||
private Date truncateToDay(Date date)
|
||||
{
|
||||
return Date.from(date.toInstant().atZone(java.time.ZoneId.systemDefault())
|
||||
.toLocalDate().atStartOfDay(java.time.ZoneId.systemDefault()).toInstant());
|
||||
}
|
||||
|
||||
/**
|
||||
* 查找单跳汇率(先正向,再反向取倒数),查不到返回 null
|
||||
*/
|
||||
|
||||
Reference in New Issue
Block a user