diff --git a/jsowell-admin/src/test/java/SpringBootTestController.java b/jsowell-admin/src/test/java/SpringBootTestController.java index f8f4de68e..385e634a7 100644 --- a/jsowell-admin/src/test/java/SpringBootTestController.java +++ b/jsowell-admin/src/test/java/SpringBootTestController.java @@ -17,6 +17,7 @@ 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.config.AbstractAdapayConfig; import com.jsowell.adapay.dto.*; import com.jsowell.adapay.factory.AdapayConfigFactory; @@ -108,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 { @@ -156,6 +157,9 @@ public class SpringBootTestController { @Autowired private MemberService memberService; + @Autowired + private StationSplitConfigService stationSplitConfigService; + @Autowired private OrderService orderService; @@ -3924,4 +3928,27 @@ public class SpringBootTestController { // rabbitTemplate.convertAndSend(RabbitConstants.YKC_EXCHANGE_NAME, RabbitConstants.QUEUE_CHARGE_ORDER_DATA, afterSettleOrderDTO); // } } + + /** + * 测试计算分账方法 + */ + @Test + public void calculationOfSplitAmountTest() { + AfterSettleOrderDTO afterSettleOrderDTO = AfterSettleOrderDTO.builder().build(); + afterSettleOrderDTO.setOrderCode("112233112233"); + afterSettleOrderDTO.setMerchantId("1"); + afterSettleOrderDTO.setStationId("2"); + afterSettleOrderDTO.setOrderPayAmount(new BigDecimal("50")); // 支付金额 + afterSettleOrderDTO.setOrderConsumeAmount(new BigDecimal("38")); // 消费金额 + afterSettleOrderDTO.setOrderSettleAmount(new BigDecimal("30")); // 结算金额 + afterSettleOrderDTO.setOrderElectricityAmount(new BigDecimal("28")); // 电费金额 + afterSettleOrderDTO.setOrderElectricityDiscountAmount(new BigDecimal("6")); // 电费优惠金额 + afterSettleOrderDTO.setOrderServiceAmount(new BigDecimal("10")); // 服务费金额 + afterSettleOrderDTO.setOrderServiceDiscountAmount(new BigDecimal("2")); // 服务费优惠金额 + afterSettleOrderDTO.setOrderRefundAmount(new BigDecimal("21")); // 退款金额 + + List stationSplitConfigList = stationSplitConfigService.queryByStationId(afterSettleOrderDTO.getStationId()); + List divMemberList = orderBasicInfoService.calculationOfSplitAmount(stationSplitConfigList, afterSettleOrderDTO, null); + System.out.println(JSON.toJSONString(divMemberList)); + } } diff --git a/jsowell-common/src/main/java/com/jsowell/common/util/AdapayUtil.java b/jsowell-common/src/main/java/com/jsowell/common/util/AdapayUtil.java index d614eb89c..36272985f 100644 --- a/jsowell-common/src/main/java/com/jsowell/common/util/AdapayUtil.java +++ b/jsowell-common/src/main/java/com/jsowell/common/util/AdapayUtil.java @@ -31,7 +31,7 @@ public class AdapayUtil { /** * 格式化数字 保留两位小数,不足补0 - * @param amount + * @param amount 单位:元 * @return */ public static String formatAmount(BigDecimal amount) { 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 8806efe55..979ede569 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 @@ -1,14 +1,13 @@ package com.jsowell.pile.service; import com.huifu.adapay.core.exception.BaseAdaPayException; +import com.jsowell.adapay.common.DivMember; import com.jsowell.adapay.response.PaymentReverseResponse; import com.jsowell.adapay.vo.OrderSplitResult; +import com.jsowell.adapay.vo.PaymentInfo; import com.jsowell.common.core.domain.ykc.RealTimeMonitorData; import com.jsowell.common.core.domain.ykc.TransactionRecordsData; -import com.jsowell.pile.domain.AdapayMemberAccount; -import com.jsowell.pile.domain.OrderBasicInfo; -import com.jsowell.pile.domain.OrderDetail; -import com.jsowell.pile.domain.SettleOrderReport; +import com.jsowell.pile.domain.*; import com.jsowell.pile.dto.*; import com.jsowell.pile.dto.nanrui.NRQueryOrderDTO; import com.jsowell.pile.dto.ningxiajiaotou.NXJTQueryOrdersInfoDTO; @@ -205,6 +204,8 @@ public interface OrderBasicInfoService{ OrderSplitResult realTimeOrderSplit(AfterSettleOrderDTO afterSettleOrderDTO) throws BaseAdaPayException; + List calculationOfSplitAmount(List stationSplitConfigList, AfterSettleOrderDTO afterSettleOrderDTO, List paymentInfos); + /** * 批量查询订单 * @param orderCodeList diff --git a/jsowell-pile/src/main/java/com/jsowell/pile/service/StationSplitConfigService.java b/jsowell-pile/src/main/java/com/jsowell/pile/service/StationSplitConfigService.java index 25ae2cf29..09eb01725 100644 --- a/jsowell-pile/src/main/java/com/jsowell/pile/service/StationSplitConfigService.java +++ b/jsowell-pile/src/main/java/com/jsowell/pile/service/StationSplitConfigService.java @@ -9,7 +9,9 @@ import java.util.List; /** * 站点分成配置service */ -public interface StationSplitConfigService{ +public interface StationSplitConfigService { + // 插入站点分账配置信息 + int settingSplitConfig(SplitConfigDTO splitConfigDTO); // 根据站点id查询站点分账配置信息 List queryByStationId(String stationId); @@ -18,12 +20,11 @@ public interface StationSplitConfigService{ * 根据站点id查询站点分成用户信息 * 如果没有配置分账用户,并且站点对应的运营商设置了结算账户, 返回本站对应的结算账户, 电费和服务费分成比例都为100% * 如果没有配置分账用户, 并且站点对应的运营商没有设置结算账户, 返回默认结算账户(举视的账户) + * * @param stationId * @return */ List queryShareMembersByStationId(String stationId); - // 插入站点分账配置信息 - int settingSplitConfig(SplitConfigDTO splitConfigDTO); } 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 bd25a28dc..bfb62b140 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 @@ -31,10 +31,7 @@ import com.jsowell.common.enums.thirdparty.ThirdPartyOperatorIdEnum; import com.jsowell.common.enums.thirdparty.ThirdPlatformTypeEnum; import com.jsowell.common.enums.ykc.*; import com.jsowell.common.exception.BusinessException; -import com.jsowell.common.util.DateUtils; -import com.jsowell.common.util.PageUtils; -import com.jsowell.common.util.StringUtils; -import com.jsowell.common.util.YKCUtils; +import com.jsowell.common.util.*; import com.jsowell.common.util.bean.BeanUtils; import com.jsowell.common.util.id.IdUtils; import com.jsowell.common.util.id.SnowflakeIdWorker; @@ -53,7 +50,9 @@ import com.jsowell.pile.transaction.dto.OrderTransactionDTO; import com.jsowell.pile.transaction.service.TransactionService; import com.jsowell.pile.util.UserUtils; import com.jsowell.pile.vo.SupStationStatsVO; -import com.jsowell.pile.vo.base.*; +import com.jsowell.pile.vo.base.MerchantOrderInfoVO; +import com.jsowell.pile.vo.base.OrderAmountDetailVO; +import com.jsowell.pile.vo.base.OrderPeriodAmountVO; import com.jsowell.pile.vo.base.PileInfoVO; import com.jsowell.pile.vo.lianlian.AccumulativeInfoVO; import com.jsowell.pile.vo.nanrui.JiangSuOrderInfoVO; @@ -1658,6 +1657,7 @@ public class OrderBasicInfoServiceImpl implements OrderBasicInfoService { return null; } + // 查询订单信息 OrderBasicInfo orderBasicInfo = this.getOrderInfoByOrderCode(afterSettleOrderDTO.getOrderCode()); afterSettleOrderDTO.setOrderBasicInfo(orderBasicInfo); @@ -1669,6 +1669,32 @@ public class OrderBasicInfoServiceImpl implements OrderBasicInfoService { return null; } + /** + * 校验金额方法 + */ + private boolean verifyOrderAllAmount(AfterSettleOrderDTO afterSettleOrderDTO) { + /* + 订单相关的所有金额需要满足一下规则 + 订单总消费金额 = 订单总电费金额 + 订单总服务费金额 + + 实际消费电费金额 = 订单总电费金额 - 电费优惠金额 + + 实际消费服务费金额 = 订单总服务费金额 - 服务费优惠金额 + + 订单总优惠金额 = 电费优惠金额 + 服务费优惠金额 + + 订单实际消费金额 = 订单总消费金额 - 订单总优惠金额 + + 实际消费总金额 = 订单总消费金额 - 订单总优惠金额 + + 订单退款金额 = 订单支付金额 - 实际消费总金额 + + 订单结算金额 = 实际消费电费金额 + 实际消费服务费金额 + + */ + return true; + } + /** * TODO 分账方法 * @param afterSettleOrderDTO @@ -1689,26 +1715,82 @@ public class OrderBasicInfoServiceImpl implements OrderBasicInfoService { /** * 计算每个账户需要分账的金额 * @param stationSplitConfigList 参与分账的账户信息 - * @param settleAmount 订单总结算金额 + * @param afterSettleOrderDTO 订单结算信息 * @param paymentInfos 支付记录信息 * @return */ - private List splitAmount(List stationSplitConfigList, BigDecimal settleAmount, List paymentInfos) { + @Override + public List calculationOfSplitAmount(List stationSplitConfigList, AfterSettleOrderDTO afterSettleOrderDTO, List paymentInfos) { + List resultList = Lists.newArrayList(); // 校验stationSplitConfigList中电费分成比例相加等于100% BigDecimal totalElecSplitRatio = stationSplitConfigList.stream().map(StationSplitConfig::getElectricitySplitRatio).reduce(BigDecimal.ZERO, BigDecimal::add); // 校验stationSplitConfigList中服务费分成比例相加等于100% 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) { - + 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; } - List resultList = Lists.newArrayList(); + // 需要分成的电费金额 = 总电费金额 - 电费优惠金额 + 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) { + DivMember divMember = new DivMember(); + divMember.setMemberId(stationSplitConfig.getAdapayMemberId()); + if (stationSplitConfig.getFeeFlag().equals(Constants.ZERO)) { + // 该用户分到的电费金额 保留两位小数, 后面的舍弃 + BigDecimal elecAmt = stationSplitConfig.getElectricitySplitRatio().divide(BigDecimal.valueOf(100)).multiply(orderElectricityAmount).setScale(2, RoundingMode.DOWN); + remainElectricityAmount = remainElectricityAmount.subtract(elecAmt); + // 该用户分到的服务费金额 + BigDecimal servAmt = stationSplitConfig.getServiceSplitRatio().divide(BigDecimal.valueOf(100)).multiply(orderServiceAmount).setScale(2, RoundingMode.DOWN); + remainServiceAmount = remainServiceAmount.subtract(servAmt); + divMember.setAmount(AdapayUtil.formatAmount(elecAmt.add(servAmt))); + } else { + // 最后剩余的金额分给手续费承担者 + divMember.setAmount(AdapayUtil.formatAmount(remainElectricityAmount.add(remainServiceAmount))); + } + divMember.setFeeFlag(StringUtils.equals(Constants.ONE, stationSplitConfig.getFeeFlag()) ? Constants.Y : Constants.N); + resultList.add(divMember); + } + + // 所有用户电费分账之和 + BigDecimal totalAmt = resultList.stream().map(DivMember::getAmount).map(BigDecimal::new).reduce(BigDecimal.ZERO, BigDecimal::add); + if ((totalAmt).compareTo(afterSettleOrderDTO.getOrderSettleAmount()) != 0 ) { + logger.info("订单结算金额:{}, 与分账后所有用户分到金额总和:{}不相等", afterSettleOrderDTO.getOrderSettleAmount(), totalAmt); + return resultList; + } return resultList; } + public static void main(String[] args) { + BigDecimal orderElectricityAmount = new BigDecimal("100"); + BigDecimal orderServiceAmount = new BigDecimal("50");; + + BigDecimal remainElectricityAmount = orderElectricityAmount; + BigDecimal remainServiceAmount = orderServiceAmount; + + for (int i = 0; i < 5; i++) { + remainElectricityAmount = remainElectricityAmount.subtract(BigDecimal.valueOf(20)); + remainServiceAmount = remainServiceAmount.subtract(BigDecimal.valueOf(10)); + } + System.out.println("需要分账的电费金额:" + orderElectricityAmount + ", 剩余电费金额" + remainElectricityAmount); + System.out.println("需要分账的服务费金额:" + orderServiceAmount + ", 剩余服务费金额" + remainServiceAmount); + } + /** * 执行订单退款 */