diff --git a/jsowell-admin/src/test/java/SpringBootTestController.java b/jsowell-admin/src/test/java/SpringBootTestController.java index c67d9d93f..0e06325e1 100644 --- a/jsowell-admin/src/test/java/SpringBootTestController.java +++ b/jsowell-admin/src/test/java/SpringBootTestController.java @@ -17,7 +17,6 @@ import com.huifu.adapay.model.Payment; import com.huifu.adapay.model.PaymentReverse; import com.huifu.adapay.model.Refund; import com.jsowell.JsowellApplication; -import com.jsowell.adapay.common.DivMember; import com.jsowell.adapay.common.PaymentConfirmInfo; import com.jsowell.adapay.config.AbstractAdapayConfig; import com.jsowell.adapay.dto.*; @@ -110,7 +109,7 @@ import java.text.SimpleDateFormat; import java.util.*; import java.util.stream.Collectors; -@ActiveProfiles("pre") +@ActiveProfiles("dev") @SpringBootTest(classes = JsowellApplication.class, webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) @RunWith(SpringRunner.class) public class SpringBootTestController { @@ -3951,10 +3950,10 @@ public class SpringBootTestController { afterSettleOrderDTO.setOrderElectricityDiscountAmount(new BigDecimal("6")); // 电费优惠金额 afterSettleOrderDTO.setOrderServiceAmount(new BigDecimal("10")); // 服务费金额 afterSettleOrderDTO.setOrderServiceDiscountAmount(new BigDecimal("2")); // 服务费优惠金额 - afterSettleOrderDTO.setOrderRefundAmount(new BigDecimal("21")); // 退款金额 + afterSettleOrderDTO.setOrderRefundAmount(new BigDecimal("20")); // 退款金额 List stationSplitConfigList = stationSplitConfigService.queryByStationId(afterSettleOrderDTO.getStationId()); - List divMemberList = orderBasicInfoService.calculationOfSplitAmount(stationSplitConfigList, afterSettleOrderDTO, null); + List divMemberList = orderBasicInfoService.calculationSplitDataList(stationSplitConfigList, afterSettleOrderDTO); System.out.println(JSON.toJSONString(divMemberList)); } diff --git a/jsowell-pile/src/main/java/com/jsowell/adapay/dto/SplitData.java b/jsowell-pile/src/main/java/com/jsowell/adapay/dto/SplitData.java new file mode 100644 index 000000000..e9b56ea0c --- /dev/null +++ b/jsowell-pile/src/main/java/com/jsowell/adapay/dto/SplitData.java @@ -0,0 +1,43 @@ +package com.jsowell.adapay.dto; + +import lombok.Data; + +import java.math.BigDecimal; + +/** + * 订单分账数据 + */ +@Data +public class SplitData { + // 分账用户 Member对象 的 id;若是商户本身时,传入0 + private String memberId; + + // 分账金额,精确到分,如0.50,1.00等,分账总金额必须等于主交易金额,金额不能为0.00 + private String amount; + + // 是否手续费承担方,N-否,Y-是,手续费承担方有且只能有一个 + private String feeFlag; + + // 控制台 主页面应用的app_id,不上送默认取商户自身app_id + private String appId; + + /** + * 电费分账比例 + */ + private BigDecimal elecRatio; + + /** + * 电费分账金额 + */ + private BigDecimal elecAmount; + + /** + * 服务费分账比例 + */ + private BigDecimal serviceRatio; + + /** + * 服务费分账金额 + */ + private BigDecimal serviceAmount; +} diff --git a/jsowell-pile/src/main/java/com/jsowell/pile/service/OrderBasicInfoService.java b/jsowell-pile/src/main/java/com/jsowell/pile/service/OrderBasicInfoService.java index b701b9186..08769c3b0 100644 --- a/jsowell-pile/src/main/java/com/jsowell/pile/service/OrderBasicInfoService.java +++ b/jsowell-pile/src/main/java/com/jsowell/pile/service/OrderBasicInfoService.java @@ -2,6 +2,7 @@ package com.jsowell.pile.service; import com.huifu.adapay.core.exception.BaseAdaPayException; import com.jsowell.adapay.common.DivMember; +import com.jsowell.adapay.dto.SplitData; import com.jsowell.adapay.response.PaymentReverseResponse; import com.jsowell.adapay.vo.OrderSplitResult; import com.jsowell.adapay.vo.PaymentInfo; @@ -206,6 +207,8 @@ public interface OrderBasicInfoService{ OrderSplitResult realTimeOrderSplit(AfterSettleOrderDTO afterSettleOrderDTO) throws BaseAdaPayException; + List calculationSplitDataList(List stationSplitConfigList, AfterSettleOrderDTO afterSettleOrderDTO); + List calculationOfSplitAmount(List stationSplitConfigList, AfterSettleOrderDTO afterSettleOrderDTO); List calculationOfSplitAmount(List stationSplitConfigList, AfterSettleOrderDTO afterSettleOrderDTO, List paymentInfos); diff --git a/jsowell-pile/src/main/java/com/jsowell/pile/service/OrderSplitRecordService.java b/jsowell-pile/src/main/java/com/jsowell/pile/service/OrderSplitRecordService.java index bc3ce28f1..3075c460a 100644 --- a/jsowell-pile/src/main/java/com/jsowell/pile/service/OrderSplitRecordService.java +++ b/jsowell-pile/src/main/java/com/jsowell/pile/service/OrderSplitRecordService.java @@ -1,5 +1,7 @@ package com.jsowell.pile.service; +import com.jsowell.adapay.dto.PaymentConfirmParam; +import com.jsowell.adapay.dto.SplitData; import com.jsowell.pile.domain.OrderSplitRecord; import java.util.List; @@ -21,5 +23,10 @@ public interface OrderSplitRecordService { int updateBatchSelective(List list); int batchInsert(List list); + + /** + * 保存订单分账记录 + */ + void saveOrderSplitRecord(PaymentConfirmParam param, String id, List stationSplitConfigList); } diff --git a/jsowell-pile/src/main/java/com/jsowell/pile/service/impl/OrderBasicInfoServiceImpl.java b/jsowell-pile/src/main/java/com/jsowell/pile/service/impl/OrderBasicInfoServiceImpl.java index 4c3c661e1..7eb23692e 100644 --- a/jsowell-pile/src/main/java/com/jsowell/pile/service/impl/OrderBasicInfoServiceImpl.java +++ b/jsowell-pile/src/main/java/com/jsowell/pile/service/impl/OrderBasicInfoServiceImpl.java @@ -11,6 +11,7 @@ import com.jsowell.adapay.dto.PaymentConfirmParam; import com.jsowell.adapay.common.PaymentConfirmInfo; import com.jsowell.adapay.dto.QueryConfirmReverseDTO; import com.jsowell.adapay.dto.QueryPaymentConfirmDTO; +import com.jsowell.adapay.dto.SplitData; import com.jsowell.adapay.operation.PaymentReverseOperation; import com.jsowell.adapay.response.*; import com.jsowell.adapay.service.AdapayService; @@ -190,6 +191,9 @@ public class OrderBasicInfoServiceImpl implements OrderBasicInfoService { @Autowired private StationSplitConfigService stationSplitConfigService; + @Autowired + private OrderSplitRecordService orderSplitRecordService; + @Override public int deleteByPrimaryKey(Integer id) { return orderBasicInfoMapper.deleteByPrimaryKey(id); @@ -1734,7 +1738,9 @@ public class OrderBasicInfoServiceImpl implements OrderBasicInfoService { List stationSplitConfigList = stationSplitConfigService.queryByStationId(afterSettleOrderDTO.getStationId()); // 计算每个参与分账的用户, 应分多少钱 - List divMemberList = calculationOfSplitAmount(stationSplitConfigList, afterSettleOrderDTO); + List splitDataList = calculationSplitDataList(stationSplitConfigList, afterSettleOrderDTO); + List divMemberList = transformDivMemberList(splitDataList); + // List divMemberList = calculationOfSplitAmount(stationSplitConfigList, afterSettleOrderDTO); // 执行分账 if (CollectionUtils.isEmpty(divMemberList)) { @@ -1776,9 +1782,101 @@ public class OrderBasicInfoServiceImpl implements OrderBasicInfoService { .wechatAppId(appId) .build(); PaymentConfirmResponse paymentConfirmRequest = adapayService.createPaymentConfirmRequest(param); + + // 保存订单分账记录 + orderSplitRecordService.saveOrderSplitRecord(param, paymentConfirmRequest.getId(), splitDataList); + return paymentConfirmRequest; } + /** + * 计算每个账户需要分账的金额 + * @param stationSplitConfigList 参与分账的账户信息 + * @param afterSettleOrderDTO 订单结算信息 + * @return + */ + @Override + public List calculationSplitDataList(List stationSplitConfigList, AfterSettleOrderDTO afterSettleOrderDTO) { + List resultList = Lists.newArrayList(); + BigDecimal totalElecSplitRatio = stationSplitConfigList.stream().map(StationSplitConfig::getElectricitySplitRatio).reduce(BigDecimal.ZERO, BigDecimal::add); + BigDecimal totalServiceSplitRatio = stationSplitConfigList.stream().map(StationSplitConfig::getServiceSplitRatio).reduce(BigDecimal.ZERO, BigDecimal::add); + // totalElecSplitRatio和totalServiceSplitRatio 都等于100%, 才进行后续操作 + if (totalElecSplitRatio.compareTo(BigDecimal.valueOf(100)) != 0 || totalServiceSplitRatio.compareTo(BigDecimal.valueOf(100)) != 0) { + logger.info("站点:{}, 分成配置中的电费分成比例相加必须为100.0%, 实际值:{}, 服务费分成比例相加必须为100.0%, 实际值:{}", stationSplitConfigList.get(0).getStationId(), totalElecSplitRatio, totalServiceSplitRatio); + return resultList; + } + + // 需要分成的电费金额 = 总电费金额 - 电费优惠金额 + BigDecimal orderElectricityAmount = afterSettleOrderDTO.getOrderElectricityAmount().subtract(afterSettleOrderDTO.getOrderElectricityDiscountAmount()); + // 需要分成的服务费金额 = 总服务费金额 - 服务费优惠金额 + BigDecimal orderServiceAmount = afterSettleOrderDTO.getOrderServiceAmount().subtract(afterSettleOrderDTO.getOrderServiceDiscountAmount()); + // 校验 结算金额 = 需要分成的电费金额 + 需要分成的服务费金额 + if (orderElectricityAmount.add(orderServiceAmount).compareTo(afterSettleOrderDTO.getOrderSettleAmount()) != 0) { + logger.info("订单结算金额:{}与需要分成的电费金额:{}+需要分成的服务费金额:{}不相等", afterSettleOrderDTO.getOrderSettleAmount(), orderElectricityAmount, orderServiceAmount); + return resultList; + } + + // 定义两个变量, 分别保存剩余电费金额, 剩余服务费金额, 原始值需要分成的金额相等, 分账后减去响应金额, 最后剩余的金额分给手续费承担者 + BigDecimal remainElectricityAmount = orderElectricityAmount; + BigDecimal remainServiceAmount = orderServiceAmount; + for (StationSplitConfig stationSplitConfig : stationSplitConfigList) { + BigDecimal electricitySplitRatio = stationSplitConfig.getElectricitySplitRatio(); + BigDecimal serviceSplitRatio = stationSplitConfig.getServiceSplitRatio(); + SplitData splitData = new SplitData(); + splitData.setMemberId(stationSplitConfig.getAdapayMemberId()); + splitData.setElecRatio(electricitySplitRatio); + splitData.setServiceRatio(serviceSplitRatio); + if (stationSplitConfig.getFeeFlag().equals(Constants.ZERO)) { + // 该用户分到的电费金额 保留两位小数, 后面的舍弃 + BigDecimal elecAmt = electricitySplitRatio.divide(BigDecimal.valueOf(100)).multiply(orderElectricityAmount).setScale(2, RoundingMode.DOWN); + splitData.setElecAmount(elecAmt); + remainElectricityAmount = remainElectricityAmount.subtract(elecAmt); + // 该用户分到的服务费金额 + BigDecimal servAmt = serviceSplitRatio.divide(BigDecimal.valueOf(100)).multiply(orderServiceAmount).setScale(2, RoundingMode.DOWN); + splitData.setServiceAmount(servAmt); + remainServiceAmount = remainServiceAmount.subtract(servAmt); + splitData.setAmount(AdapayUtil.formatAmount(elecAmt.add(servAmt))); + } else { + // 最后剩余的金额分给手续费承担者 + splitData.setElecAmount(remainElectricityAmount); + splitData.setServiceAmount(remainServiceAmount); + splitData.setAmount(AdapayUtil.formatAmount(remainElectricityAmount.add(remainServiceAmount))); + } + splitData.setFeeFlag(StringUtils.equals(Constants.ONE, stationSplitConfig.getFeeFlag()) ? Constants.Y : Constants.N); + resultList.add(splitData); + } + + // 所有用户电费分账之和 + BigDecimal totalAmt = resultList.stream().map(SplitData::getAmount).map(BigDecimal::new).reduce(BigDecimal.ZERO, BigDecimal::add); + if ((totalAmt).compareTo(afterSettleOrderDTO.getOrderSettleAmount()) != 0 ) { + logger.info("订单结算金额:{}, 与分账后所有用户分到金额总和:{}不相等", afterSettleOrderDTO.getOrderSettleAmount(), totalAmt); + return resultList; + } + + return resultList; + } + + /** + * 转换分账对象 + * @param list + * @return + */ + private List transformDivMemberList(List list) { + List resultList = Lists.newArrayList(); + if (CollectionUtils.isEmpty(list)) { + return resultList; + } + for (SplitData splitData : list) { + DivMember divMember = new DivMember(); + divMember.setMemberId(splitData.getMemberId()); + divMember.setAmount(splitData.getAmount()); + divMember.setFeeFlag(splitData.getFeeFlag()); + divMember.setAppId(splitData.getAppId()); + resultList.add(divMember); + } + return resultList; + } + /** * 计算每个账户需要分账的金额 * @param stationSplitConfigList 参与分账的账户信息 diff --git a/jsowell-pile/src/main/java/com/jsowell/pile/service/impl/OrderSplitRecordServiceImpl.java b/jsowell-pile/src/main/java/com/jsowell/pile/service/impl/OrderSplitRecordServiceImpl.java index 0fe9ff755..0edd4f868 100644 --- a/jsowell-pile/src/main/java/com/jsowell/pile/service/impl/OrderSplitRecordServiceImpl.java +++ b/jsowell-pile/src/main/java/com/jsowell/pile/service/impl/OrderSplitRecordServiceImpl.java @@ -1,11 +1,16 @@ package com.jsowell.pile.service.impl; +import com.google.common.collect.Lists; +import com.jsowell.adapay.dto.PaymentConfirmParam; +import com.jsowell.adapay.dto.SplitData; +import com.jsowell.common.enums.DelFlagEnum; import com.jsowell.pile.domain.OrderSplitRecord; import com.jsowell.pile.mapper.OrderSplitRecordMapper; import com.jsowell.pile.service.OrderSplitRecordService; import org.springframework.stereotype.Service; import javax.annotation.Resource; +import java.math.BigDecimal; import java.util.List; @Service @@ -53,5 +58,49 @@ public class OrderSplitRecordServiceImpl implements OrderSplitRecordService { public int batchInsert(List list) { return orderSplitRecordMapper.batchInsert(list); } + + @Override + public void saveOrderSplitRecord(PaymentConfirmParam param, String paymentConfirmId, List splitDataList) { + List list = Lists.newArrayList(); + + String orderCode = param.getOrderCode(); + BigDecimal settleAmount = param.getConfirmAmt(); + String paymentId = param.getPaymentId(); + // List divMemberList = param.getDivMemberList(); + // for (DivMember divMember : divMemberList) { + // OrderSplitRecord orderSplitRecord = new OrderSplitRecord(); + // orderSplitRecord.setOrderCode(orderCode); + // orderSplitRecord.setStatus(""); + // orderSplitRecord.setSettleAmount(settleAmount); + // orderSplitRecord.setAdapayMemberId(divMember.getMemberId()); + // orderSplitRecord.setPaymentId(paymentId); + // orderSplitRecord.setPaymentConfirmId(paymentConfirmId); + // // orderSplitRecord.setElectricitySplitRatio(divMember.getElectricitySplitRatio()); + // // orderSplitRecord.setElectricitySplitAmount(divMember.getElectricitySplitAmount()); + // // orderSplitRecord.setServiceSplitRatio(divMember.getServiceSplitRatio()); + // // orderSplitRecord.setServiceSplitAmount(divMember.getServiceSplitAmount()); + // orderSplitRecord.setRemark(""); + // orderSplitRecord.setDelFlag(DelFlagEnum.NORMAL.getValue()); + // list.add(orderSplitRecord); + // } + + for (SplitData splitData : splitDataList) { + OrderSplitRecord orderSplitRecord = new OrderSplitRecord(); + orderSplitRecord.setOrderCode(orderCode); + orderSplitRecord.setStatus(""); + orderSplitRecord.setSettleAmount(settleAmount); + orderSplitRecord.setAdapayMemberId(splitData.getMemberId()); + orderSplitRecord.setPaymentId(paymentId); + orderSplitRecord.setPaymentConfirmId(paymentConfirmId); + orderSplitRecord.setElectricitySplitRatio(splitData.getElecRatio()); + orderSplitRecord.setElectricitySplitAmount(splitData.getElecAmount()); + orderSplitRecord.setServiceSplitRatio(splitData.getServiceRatio()); + orderSplitRecord.setServiceSplitAmount(splitData.getServiceAmount()); + orderSplitRecord.setRemark(""); + orderSplitRecord.setDelFlag(DelFlagEnum.NORMAL.getValue()); + list.add(orderSplitRecord); + } + this.batchInsert(list); + } }