package org.xmx0632.deliciousfruit.service;
import java.math.BigDecimal;
import java.util.List;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.xmx0632.deliciousfruit.api.v1.bo.OrderRequest;
import org.xmx0632.deliciousfruit.api.v1.bo.OrderRequest.Payment;
import org.xmx0632.deliciousfruit.api.v1.bo.OrderRequest.Payment.CashCouponPay;
import org.xmx0632.deliciousfruit.api.v1.bo.OrderRequest.Payment.GiftCardPay;
import org.xmx0632.deliciousfruit.api.v1.bo.OrderResponse.DeductionPay;
import org.xmx0632.deliciousfruit.api.v1.bo.OrderResponse.PayByCashCoupon;
import org.xmx0632.deliciousfruit.api.v1.bo.OrderResponse.PayByGiftCard;
import org.xmx0632.deliciousfruit.erp.ErpApiService;
import org.xmx0632.deliciousfruit.erp.bo.DeductionMessage;
import org.xmx0632.deliciousfruit.erp.bo.ErpCard;
import org.xmx0632.deliciousfruit.erp.bo.ErpCash;
import org.xmx0632.deliciousfruit.erp.bo.ErpChangeCard;
import org.xmx0632.deliciousfruit.erp.bo.ErpChangeCash;
import org.xmx0632.deliciousfruit.erp.bo.ErpChangeCoin;
import org.xmx0632.deliciousfruit.erp.bo.ErpChangePoint;
import org.xmx0632.deliciousfruit.erp.bo.ErpCustomer;
import org.xmx0632.deliciousfruit.erp.bo.ErpMessage;
/**
* 客户端IOS订购商品时,使用的抵扣券/礼品卡/积分/账户余额等需要实时到ERP查询的信息,并扣除
*
* @author xmx0632
*
*/
// Spring Bean的标识.
@Component
public class DeductionPayService {
private static Logger log = LoggerFactory
.getLogger(DeductionPayService.class);
@Autowired
private ErpApiService erpApiService;
public DeductionPayService() {
}
/**
* 查询验证用户请求的抵扣信息
*
* @param orderRequest
* @param customerId
* @return
*/
public DeductionPay getDeductionPay(OrderRequest orderRequest,
String customerId) {
DeductionPay deductionPay = new DeductionPay();
DeductionMessage deductionMessage = new DeductionMessage();
try {
Payment payment = orderRequest.getPayment();
if (payment == null) {
return deductionPay;
}
// 现金券
List<CashCouponPay> cashCoupons = payment.getCashCoupons();
if (cashCoupons != null) {
for (CashCouponPay cashCouponPay : cashCoupons) {
// 发送消息到ERP查询现金券余额,检查是否可用
ErpCash erpCash = erpApiService.getCashBy(cashCouponPay
.getId());
log.debug("ErpCash:{}", erpCash);
if (erpCash == null) {
log.warn("can not find cashCoupon with id:{}!",
cashCouponPay.getId());
throw new ServiceException("can not find cashCoupon!");
}
int availableUseTime = erpCash.getIntUseStatus();
if (availableUseTime < 1) {
log.warn("ErpCash status abnormal! erpCash:{} ",
erpCash);
throw new ServiceException("erpCard status abnormal!");
}
String decValue = erpCash.getDecValue();
Double availableValue = Double.valueOf(decValue);
BigDecimal availableAmount = BigDecimal
.valueOf(availableValue);
// 检查请求抵扣的现金券金额与现金券的面值是否一致
BigDecimal payAmount = cashCouponPay.getPayAmount();
if (availableAmount.compareTo(payAmount) != 0) {
log.warn(
"ErpCash payAmount abnormal! availableAmount:{} payAmount:{}",
availableAmount, payAmount);
throw new ServiceException(
"ErpCash payAmount abnormal! availableAmount:"
+ availableAmount + " payAmount:"
+ payAmount);
}
// 如果可用,发送抵扣现金券消息到ERP
deductionMessage
.addErpChangeCash(new ErpMessage<ErpChangeCash>(
new ErpChangeCash(erpCash.getStrCashNo(),
availableUseTime)));
// 记录使用后的剩余使用次数
int leftTimes = availableUseTime - 1;
log.debug("leftTimes:{}", leftTimes);
PayByCashCoupon payByCashCoupon = new PayByCashCoupon();
payByCashCoupon.setPayLeftTimes(leftTimes);
payByCashCoupon.setDeductionAmount(payAmount);
payByCashCoupon.setId(cashCouponPay.getId());
deductionPay.getPayByCashCouponInfo().add(payByCashCoupon);
}
}
// 礼品卡
List<GiftCardPay> giftcards = payment.getGiftCards();
if (giftcards != null) {
for (GiftCardPay giftCardPay : giftcards) {
PayByGiftCard payByGiftCard = new PayByGiftCard();
// 发送消息到ERP查询礼品卡余额
ErpCard erpCard = erpApiService.getCardBy(giftCardPay
.getId());
log.debug("erpCard:{}", erpCard);
if (erpCard == null) {
log.warn("can not find giftCard with id:{}!",
giftCardPay.getId());
throw new ServiceException("can not find giftCard!");
}
if (!ErpCard.Status_NORMAL.equals(erpCard.getIntStatus())) {
log.warn("ErpCard status abnormal! erpCard:{} ",
erpCard);
throw new ServiceException(
"ErpCard status abnormal! erpCard:" + erpCard);
}
String decValue = erpCard.getDecValue();
Double availableValue = Double.valueOf(decValue);
BigDecimal currentGiftCardAvailableAmount = BigDecimal
.valueOf(availableValue);
// 验证礼品卡金额是否 > 请求扣除金额
BigDecimal payAmount = giftCardPay.getPayAmount();
if (currentGiftCardAvailableAmount.compareTo(payAmount) < 0) {
log.warn(
"ErpCard available amount is not enough! payAmount:{} but available amount:{}",
payAmount, currentGiftCardAvailableAmount);
throw new ServiceException(
"ErpCard available amount is not enough!payAmount:"
+ payAmount + " but available amount:"
+ currentGiftCardAvailableAmount);
}
// 发送抵扣礼品卡消息到ERP
deductionMessage
.addErpChangeCard(
new ErpMessage<ErpChangeCard>(
new ErpChangeCard(giftCardPay
.getId(), payAmount
.toString())));
BigDecimal leftBalance = currentGiftCardAvailableAmount
.subtract(payAmount);
payByGiftCard.setDeductionAmount(payAmount);
payByGiftCard.setBalance(leftBalance);
payByGiftCard.setId(giftCardPay.getId());
deductionPay.getPayByGiftCardInfo().add(payByGiftCard);
}
}
int payPoint = payment.getPayPonit();
BigDecimal payCoin = payment.getPayAmountFromAccount();
log.debug("payPoint:{} payCoin:{}", payPoint, payCoin);
boolean shouldPayByPoint = shouldPayByPoint(payPoint);
boolean shouldPayByCoin = shouldPayByCoin(payCoin);
log.debug("shouldPayByPoint:{} shouldPayByCoin:{}",
shouldPayByPoint, shouldPayByCoin);
ErpCustomer erpCustomer = getErpCustomerIfNeed(customerId,
shouldPayByPoint, shouldPayByCoin);
if (shouldPayByPoint) {
BigDecimal payAmountFromPonit = payment.getPayAmountFromPonit();
log.debug("payAmountFromPonit:{}", payAmountFromPonit);
// 验证客户端积分抵扣金额是否计算正确(100:1)
validatePointRatio(payPoint, payAmountFromPonit);
// 调用ERP接口查询用户当前可用的抵扣积分
Integer point = Integer.valueOf(erpCustomer.getIntPoint());
// 检查用户是否有足够的请求抵扣积分额度
if (pointNotEnough(payPoint, point)) {
log.warn(
"point not enough! payPoint:{} but available point:{}",
payPoint, point);
throw new ServiceException("point not enough! payPoint:"
+ payPoint + " but available point:" + point);
}
// 调用ERP接口抵扣用户积分
deductionMessage.setPayByPoint(new ErpChangePoint(customerId,
payAmountFromPonit.toString()));
deductionPay.setPayByPoint(payAmountFromPonit);
}
if (shouldPayByCoin) {
// 从ERP接口查询账户余额
BigDecimal coin = BigDecimal.valueOf(Double.valueOf(erpCustomer
.getDecCoin()));
// 检查用户是否有足够的请求抵扣账户余额
if (notEnoughCoin(payCoin, coin)) {
log.warn(
"coin not enough! payCoin:{} but available coin:{}",
payCoin, coin);
throw new ServiceException(
"coin not enough! payAmountFromAccount:" + payCoin
+ " but available coin:" + coin);
}
// 调用ERP接口抵扣账户余额
deductionMessage.setPayFromAccount(new ErpChangeCoin(
customerId, payCoin.toString()));
deductionPay.setPayFromAccount(payCoin);
}
// 下一步统一调用ERP抵扣接口,如果有任何失败,则回滚之前的抵扣操作
deductionPay.setDeductionMessage(deductionMessage);
return deductionPay;
} catch (Exception e) {
log.warn(e.getMessage(), e);
throw new ServiceException(e.getMessage(), e);
}
}
private boolean notEnoughCoin(BigDecimal payCoin, BigDecimal coin) {
return payCoin.compareTo(coin) > 0;
}
private ErpCustomer getErpCustomerIfNeed(String customerId,
boolean shouldPayByPoint, boolean shouldPayByCoin) {
if (!shouldPayByPoint && !shouldPayByCoin) {
return null;
}
ErpCustomer erpCustomer = erpApiService.getCustomerBy(customerId);
log.debug("erpCustomer:{}", erpCustomer);
if (erpCustomer == null) {
log.warn("can not find customer with id:{}", customerId);
throw new ServiceException("can not find customer with id:"
+ customerId);
}
return erpCustomer;
}
private boolean pointNotEnough(int payPoint, Integer point) {
return payPoint > point;
}
private void validatePointRatio(int payPoint, BigDecimal payAmountFromPonit) {
BigDecimal payAmount = BigDecimal.valueOf(payPoint).divide(
BigDecimal.valueOf(100.0).setScale(2));
log.debug("payAmount:{}", payAmount);
if (payAmount.compareTo(payAmountFromPonit) != 0) {
log.warn(
"calc PayAmountFromPonit error! payPoint:{} payAmountFromPonit:{}",
payPoint, payAmountFromPonit);
throw new ServiceException(
"calc PayAmountFromPonit error! payPoint:" + payPoint
+ " payAmountFromPonit:" + payAmountFromPonit
+ " must be " + payAmount);
}
}
private boolean shouldPayByPoint(int payPoint) {
return payPoint > 0;
}
private boolean shouldPayByCoin(BigDecimal payCoin) {
return payCoin.compareTo(BigDecimal.ZERO) == 1;
}
/**
* 发送抵扣消息到ERP
*
* @param deductionMessage
*/
public void sendDeductionPayMessage(DeductionMessage deductionMessage) {
List<ErpMessage<ErpChangeCard>> erpChangeCardList = deductionMessage
.getErpChangeCardList();
for (ErpMessage<ErpChangeCard> erpMessage : erpChangeCardList) {
boolean sentSuccess = erpApiService.changeCard(erpMessage
.getMessage());
erpMessage.setHasSent(sentSuccess);
log.debug("erpChangeCard message:{} sentSuccess:{}", sentSuccess,
erpMessage.getMessage());
if (!sentSuccess) {
return;
}
}
List<ErpMessage<ErpChangeCash>> erpChangeCashList = deductionMessage
.getErpChangeCashList();
for (ErpMessage<ErpChangeCash> erpMessage : erpChangeCashList) {
boolean sentSuccess = erpApiService.changeCash(erpMessage
.getMessage());
erpMessage.setHasSent(sentSuccess);
log.debug("erpChangeCash message:{} sentSuccess:{}", sentSuccess,
erpMessage.getMessage());
if (!sentSuccess) {
return;
}
}
ErpMessage<ErpChangePoint> erpChangePoint = deductionMessage
.getErpChangePoint();
if (erpChangePoint != null) {
boolean sentSuccess = erpApiService.changePoint(erpChangePoint
.getMessage());
erpChangePoint.setHasSent(sentSuccess);
log.debug("erpChangePoint message:{} sentSuccess:{}", sentSuccess,
erpChangePoint.getMessage());
if (!sentSuccess) {
return;
}
}
ErpMessage<ErpChangeCoin> erpChangeCoin = deductionMessage
.getErpChangeCoin();
if (erpChangeCoin != null) {
boolean sentSuccess = erpApiService.changeCoin(erpChangeCoin
.getMessage());
erpChangeCoin.setHasSent(sentSuccess);
log.debug("erpChangeCoin message:{} sentSuccess:{}", sentSuccess,
erpChangeCoin.getMessage());
if (!sentSuccess) {
return;
}
}
}
/**
* 回滚已经发送的抵扣消息
*
* @param deductionMessage
*/
public void rollbackDeductionPayMessage(DeductionMessage deductionMessage) {
List<ErpMessage<ErpChangeCard>> erpChangeCardList = deductionMessage
.getErpChangeCardList();
for (ErpMessage<ErpChangeCard> erpMessage : erpChangeCardList) {
if (erpMessage.hasSent()) {
ErpChangeCard rollbackMessage = erpMessage.getMessage()
.getRollback();
boolean sentSuccess = erpApiService.changeCard(rollbackMessage);
erpMessage.setHasRollback(sentSuccess);
log.debug("rollback message:[{}] result:[{}]", rollbackMessage,
sentSuccess);
}
}
List<ErpMessage<ErpChangeCash>> erpChangeCashList = deductionMessage
.getErpChangeCashList();
for (ErpMessage<ErpChangeCash> erpMessage : erpChangeCashList) {
if (erpMessage.hasSent()) {
ErpChangeCash rollbackMessage = erpMessage.getMessage()
.getRollback();
boolean sentSuccess = erpApiService.changeCash(rollbackMessage);
erpMessage.setHasRollback(sentSuccess);
log.debug("rollback message:[{}] result:[{}]", rollbackMessage,
sentSuccess);
}
}
ErpMessage<ErpChangeCoin> erpChangeCoin = deductionMessage
.getErpChangeCoin();
if (erpChangeCoin != null && erpChangeCoin.hasSent()) {
ErpChangeCoin rollbackMessage = erpChangeCoin.getMessage()
.getRollback();
boolean sentSuccess = erpApiService.changeCoin(rollbackMessage);
erpChangeCoin.setHasRollback(sentSuccess);
log.debug("rollback message:[{}] result:[{}]", rollbackMessage,
sentSuccess);
}
ErpMessage<ErpChangePoint> erpChangePoint = deductionMessage
.getErpChangePoint();
if (erpChangePoint != null && erpChangePoint.hasSent()) {
ErpChangePoint rollbackMessage = erpChangePoint.getMessage()
.getRollback();
boolean sentSuccess = erpApiService.changePoint(rollbackMessage);
erpChangePoint.setHasRollback(sentSuccess);
log.debug("rollback message:[{}] result:[{}]", rollbackMessage,
sentSuccess);
}
}
}