临时提交

This commit is contained in:
墨大叔 2024-09-14 18:04:35 +08:00
parent a5ed55768c
commit dba95cd81f
23 changed files with 341 additions and 148 deletions

View File

@ -181,4 +181,8 @@ public class SmUser extends BaseEntity
@ApiModelProperty("用户类型")
private String type;
@Excel(name = "代理商服务费比例")
@ApiModelProperty("代理商服务费比例")
private BigDecimal agentServiceRate;
}

View File

@ -56,13 +56,13 @@ public class Bonus extends BaseEntity
@JsonView(JsonViewProfile.AppMch.class)
private String arrivalType;
@Excel(name = "分成比例")
@ApiModelProperty("分成比例")
@Excel(name = "收款比例")
@ApiModelProperty("收款比例")
@JsonView(JsonViewProfile.AppMch.class)
private BigDecimal point;
@Excel(name = "分成金额")
@ApiModelProperty("分成金额")
@Excel(name = "收款金额")
@ApiModelProperty("收款金额")
@JsonView(JsonViewProfile.AppMch.class)
private BigDecimal amount;

View File

@ -11,8 +11,9 @@ import lombok.Getter;
@AllArgsConstructor
public enum BonusStatus {
UN_DIVIDEND("1", "未分成"),
DIVIDEND("2", "已分成");
UN_DIVIDEND("1", "未出账"),
WAIT_DIVIDE("2", "待分成"),
DIVIDEND("3", "已分成");
private final String status;
private final String msg;

View File

@ -2,8 +2,10 @@ package com.ruoyi.ss.bonus.service;
import com.ruoyi.common.core.domain.entity.SysDept;
import com.ruoyi.ss.bonus.domain.Bonus;
import com.ruoyi.ss.channel.domain.ChannelVO;
import com.ruoyi.ss.device.domain.vo.DeviceVO;
import com.ruoyi.ss.transactionBill.domain.bo.RechargeBO;
import com.ruoyi.ss.transactionBill.domain.dto.RechargePayBO;
import com.ruoyi.ss.user.domain.SmUserVo;
import java.util.List;
@ -14,6 +16,11 @@ import java.util.List;
*/
public interface BonusConverter {
/**
* 支付转为分成明细
*/
List<Bonus> toPo(RechargePayBO bo);
/**
* 订单转为分成明细
*/
@ -26,7 +33,9 @@ public interface BonusConverter {
* @param agent
* @param platform
* @param device
* @param channel
* @return
*/
List<Bonus> genBonusList(SmUserVo mch, SmUserVo agent, SysDept platform, DeviceVO device);
List<Bonus> genBonusList(SmUserVo mch, SmUserVo agent, SysDept platform, DeviceVO device, ChannelVO channel);
}

View File

@ -1,7 +1,6 @@
package com.ruoyi.ss.bonus.service;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.util.List;
import com.ruoyi.common.domain.vo.CommonCountVO;
@ -77,11 +76,18 @@ public interface BonusService
/**
* 处理分成支付
*
* @param bonusList 分成列表
* @param money 总金额
* @return 处理数量
*/
int payBonus(List<BonusVO> bonusList, BigDecimal money);
int payBonus(List<BonusVO> bonusList);
/**
* 处理分成按照比例分出金额
* @param bonusList 分成列表
* @param money 总金额
*/
int partBonus(List<BonusVO> bonusList, BigDecimal money);
/**
* 根据到账方统计

View File

@ -2,23 +2,32 @@ package com.ruoyi.ss.bonus.service.impl;
import com.ruoyi.common.constant.Constants;
import com.ruoyi.common.core.domain.entity.SysDept;
import com.ruoyi.common.enums.ServiceType;
import com.ruoyi.common.utils.ServiceUtil;
import com.ruoyi.ss.bonus.domain.Bonus;
import com.ruoyi.ss.bonus.domain.enums.BonusArrivalType;
import com.ruoyi.ss.bonus.domain.enums.BonusStatus;
import com.ruoyi.ss.bonus.service.BonusConverter;
import com.ruoyi.ss.channel.domain.ChannelVO;
import com.ruoyi.ss.device.domain.enums.DeviceServiceMode;
import com.ruoyi.ss.device.domain.vo.DeviceVO;
import com.ruoyi.ss.store.service.StoreService;
import com.ruoyi.ss.transactionBill.domain.TransactionBill;
import com.ruoyi.ss.transactionBill.domain.bo.RechargeBO;
import com.ruoyi.ss.transactionBill.domain.dto.RechargePayBO;
import com.ruoyi.ss.transactionBill.domain.vo.UserRechargeServiceVO;
import com.ruoyi.ss.transactionBill.service.TransactionBillService;
import com.ruoyi.ss.user.domain.SmUserVo;
import com.ruoyi.ss.user.service.ISmUserService;
import com.ruoyi.system.service.ISysConfigService;
import com.ruoyi.system.service.ISysDeptService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;
/**
* @author wjh
@ -39,23 +48,27 @@ public class BonusConverterImpl implements BonusConverter {
@Autowired
private TransactionBillService transactionBillService;
@Autowired
private ISysConfigService sysConfigService;
/**
* 订单转为分成明细
*
* @param bo
*/
@Override
public List<Bonus> toPo(RechargeBO bo) {
public List<Bonus> toPo(RechargePayBO bo) {
if (bo == null) {
return Collections.emptyList();
}
TransactionBill bill = bo.getOrder();
if (bill == null) {
return null;
return Collections.emptyList();
}
List<Bonus> result = bo.getBonusList();
List<Bonus> result = genBonusList(bo.getMch(), null, bo.getPlatform(), bo.getDevice(), bo.getChannel());
for (Bonus bonus : result) {
bonus.setBillId(bill.getBillId());
bonus.setBillNo(bill.getBillNo());
@ -65,63 +78,67 @@ public class BonusConverterImpl implements BonusConverter {
}
@Override
public List<Bonus> genBonusList(SmUserVo mch, SmUserVo agent, SysDept platform, DeviceVO device) {
List<Bonus> result = new ArrayList<>();
public List<Bonus> toPo(RechargeBO bo) {
if (bo == null) {
return Collections.emptyList();
}
TransactionBill bill = bo.getOrder();
if (bill == null) {
return Collections.emptyList();
}
List<Bonus> result = genBonusList(bo.getMch(), bo.getAgent(), bo.getPlatform(), bo.getDevice(), null);
for (Bonus bonus : result) {
bonus.setBillId(bill.getBillId());
bonus.setBillNo(bill.getBillNo());
}
return result;
}
@Override
public List<Bonus> genBonusList(SmUserVo mch, SmUserVo agent, SysDept platform, DeviceVO device, ChannelVO channel) {
List<Bonus> result = new ArrayList<>();
if (mch == null || platform == null || device == null) {
return result;
}
// 剩余可分配的分成比例
BigDecimal point = BigDecimal.valueOf(100);
// TODO 平台收取服务费
// 直营模式
if (DeviceServiceMode.DIRECT.getMode().equals(device.getServiceMode())) {
// 平台收取服务费
UserRechargeServiceVO userRechargeService = transactionBillService.getMchRechargeService(channel, mch, device);
String serviceType = userRechargeService.getServiceType(); // 服务费类型
BigDecimal serviceRate = userRechargeService.getServiceRate(); // 服务费
// 如果按照百分比收取服务费
if(ServiceType.PERCENT.getType().equals(serviceType)) {
result.add(this.toPo(platform, serviceRate));
point = point.subtract(serviceRate);
}
}
// 代理模式
else if (DeviceServiceMode.AGENT.getMode().equals(device.getServiceMode())) {
// 平台收取服务费
ServiceUtil.assertion(agent.getAgentServiceRate() == null, "代理商服务费未配置");
ServiceUtil.assertion(device.getAgentServiceRate() == null, "代理商设备服务费未配置");
// TODO 代理商收取服务费
result.add(this.toPo(platform, agent.getAgentServiceRate()));
point = point.subtract(agent.getAgentServiceRate());
// TODO 剩余的给商户
// 代理商收取服务费
result.add(this.toPo(agent, device.getAgentServiceRate(), agent.getUserId().toString()));
point = point.subtract(device.getAgentServiceRate());
}
//
// // 根据设备的投资人经营场所获取各自的分成比例
// result.add(this.toPo(store, storeInvestor, mch));
// result.add(this.toPo(mch, mch.getPoint()));
// BigDecimal lastPoint = mch.getPoint().add(storeInvestor.getPoint()); // 上一次的分成比例
//
// // 投资人上级
// if (StringUtils.hasText(mch.getAncestors()) && CollectionUtils.isNotEmpty(agent)) {
// List<Long> collect = Arrays.stream(mch.getAncestors().split(",")).map(Long::valueOf).collect(Collectors.toList());
// for (int i = collect.size() - 1; i >= 0; i --) {
// Long id = collect.get(i);
// SmUserVo investorAncestor = agent.stream().filter(item -> item.getUserId().equals(id)).findFirst().orElse(null);
// if (investorAncestor != null) {
// result.add(this.toPo(investorAncestor, investorAncestor.getPoint().subtract(lastPoint)));
// lastPoint = investorAncestor.getPoint();
// }
// }
// }
//
// // 直属部门
// result.add(this.toPo(platform, platform.getPoint().subtract(lastPoint)));
// lastPoint = platform.getPoint();
//
// // 直属部门的祖级列表
// if (StringUtils.hasText(platform.getAncestors()) && CollectionUtils.isNotEmpty(investorDeptList)) {
// List<Long> collect = Arrays.stream(platform.getAncestors().split(",")).map(Long::valueOf).collect(Collectors.toList());
// for (int i = collect.size() - 1; i >= 0; i --) {
// Long id = collect.get(i);
// SysDept d = investorDeptList.stream().filter(item -> item.getDeptId().equals(id)).findFirst().orElse(null);
// if (d != null) {
// result.add(this.toPo(d, d.getPoint().subtract(lastPoint)));
// lastPoint = d.getPoint();
// }
// }
// }
ServiceUtil.assertion(point.compareTo(BigDecimal.ZERO) < 0, "商户剩余分成不允许小于0");
ServiceUtil.assertion(point.compareTo(BigDecimal.valueOf(100)) > 0, "商户剩余分成不允许大于100");
// 校验分成比例
// ServiceUtil.assertion(lastPoint.compareTo(BigDecimal.valueOf(100)) != 0, "分成计算失败最终分成比例不等于100");
// BigDecimal total = BigDecimal.ZERO;
// BigDecimal decimal100 = BigDecimal.valueOf(100);
// for (Bonus bonus : result) {
// ServiceUtil.assertion(bonus.getPoint().compareTo(BigDecimal.ZERO) < 0, "分成计算失败分成比例小于0");
// ServiceUtil.assertion(bonus.getPoint().compareTo(decimal100) > 0, "分成计算失败分成比例大于100");
// total = total.add(bonus.getPoint());
// }
// ServiceUtil.assertion(total.compareTo(decimal100) > 0, "分成计算失败分成比例总和大于100");
// 剩余的给商户
String ancestors = Stream.of(device.getAgentId(), device.getUserId()).map(Object::toString).collect(Collectors.joining(","));
result.add(this.toPo(mch, point, ancestors));
return result;
}
@ -146,7 +163,7 @@ public class BonusConverterImpl implements BonusConverter {
return po;
}
private Bonus toPo(SmUserVo user, BigDecimal point, DeviceVO device) {
private Bonus toPo(SmUserVo user, BigDecimal point, String ancestors) {
if (user == null || point == null) {
return null;
}
@ -160,7 +177,7 @@ public class BonusConverterImpl implements BonusConverter {
po.setArrivalType(arrivalType.getType());
}
po.setPoint(point);
// po.setAncestors(Arrays.asList(device.getAgentId(), device.getUserId()));
po.setAncestors(ancestors);
po.setDeptId(Constants.ROOT_DEPT);
return po;

View File

@ -2,10 +2,7 @@ package com.ruoyi.ss.bonus.service.impl;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;
@ -149,22 +146,50 @@ public class BonusServiceImpl implements BonusService
return bonusMapper.batchInsert(bonusList);
}
@Override
public int payBonus(List<BonusVO> bonusList, BigDecimal money) {
public int payBonus(List<BonusVO> bonusList) {
int total = 0;
// 循环遍历添加金额到账户上
for (BonusVO bonus : bonusList) {
Integer result = transactionTemplate.execute(status -> {
int add = 0;
// 根据类型添加金额
if (BonusArrivalType.userList().contains(bonus.getArrivalType())) {
add = userService.addBalance(bonus.getArrivalId(), bonus.getAmount(), String.format("订单分成:%s", bonus.getBillNo()), RecordBalanceBstType.RECHARGE, bonus.getBillId());
} else if (BonusArrivalType.deptList().contains(bonus.getArrivalType())) {
// add = deptService.addBalance(bonus.getArrivalId(), bonus.getAmount(), String.format("订单分成:%s", bonus.getBillNo()), RecordBalanceBstType.RECHARGE, bonus.getBillId());
}
ServiceUtil.assertion(add != 1, "增加账户金额失败");
// TODO 更新分成状态为已分成
return add;
});
total += (result == null ? 0 : 1);
}
return total;
}
@Override
public int partBonus(List<BonusVO> bonusList, BigDecimal money) {
if (CollectionUtils.isEmptyElement(bonusList)) {
return 0;
}
BigDecimal decimal100 = new BigDecimal(100);
BigDecimal dividedAmount = BigDecimal.ZERO; // 已分配金额
LocalDateTime now = LocalDateTime.now();
// 循环遍历构造分成金额
for (BonusVO bonus : bonusList) {
BigDecimal amount = money.multiply(bonus.getPoint()).divide(decimal100, 2, RoundingMode.HALF_UP);
bonus.setAmount(amount);
bonus.setStatus(BonusStatus.DIVIDEND.getStatus());
bonus.setPayTime(now);
bonus.setStatus(BonusStatus.WAIT_DIVIDE.getStatus());
// TODO 预计分成时间
dividedAmount = dividedAmount.add(amount);
}
// 平台吃掉误差
@ -176,19 +201,6 @@ public class BonusServiceImpl implements BonusService
}
Integer result = transactionTemplate.execute(status -> {
// 循环遍历添加金额到账户上
for (BonusVO bonus : bonusList) {
int add = 0;
// 根据类型添加金额
if (BonusArrivalType.userList().contains(bonus.getArrivalType())) {
add = userService.addBalance(bonus.getArrivalId(), bonus.getAmount(), String.format("订单分成:%s", bonus.getBillNo()), RecordBalanceBstType.RECHARGE, bonus.getBillId());
} else if (BonusArrivalType.deptList().contains(bonus.getArrivalType())) {
// add = deptService.addBalance(bonus.getArrivalId(), bonus.getAmount(), String.format("订单分成:%s", bonus.getBillNo()), RecordBalanceBstType.RECHARGE, bonus.getBillId());
}
ServiceUtil.assertion(add != 1, "增加账户金额失败");
}
// 批量更新分成金额
int updateAmount = this.batchUpdateAmount(bonusList);
ServiceUtil.assertion(updateAmount != bonusList.size(), "更新分成金额失败");

View File

@ -208,4 +208,16 @@ public class Device extends BaseEntity
@ApiModelProperty("上次恢复余额的时间戳")
private Long lastRecoverTime;
@Excel(name = "代理商收取服务费费率")
@ApiModelProperty("代理商收取服务费费率")
private BigDecimal agentServiceRate;
@Excel(name = "代理商ID")
@ApiModelProperty("代理商ID")
private Long agentId;
@Excel(name = "服务模式1-直营模式2-代理模式")
@ApiModelProperty("服务模式")
private String serviceMode;
}

View File

@ -0,0 +1,20 @@
package com.ruoyi.ss.device.domain.enums;
import lombok.AllArgsConstructor;
import lombok.Getter;
/**
* @author wjh
* 2024/9/14
*/
@Getter
@AllArgsConstructor
public enum DeviceServiceMode {
DIRECT("1", "直营模式"),
AGENT("2", "代理模式");
private final String mode;
private final String msg;
}

View File

@ -27,6 +27,8 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<if test="endRentTime != null"> and sd.device_id &lt;= #{endRentTime}</if>
<if test="deviceNo != null"> and sd.device_no like concat('%', #{deviceNo}, '%')</if>
<if test="lockUserId != null"> and sd.lock_user_id = #{lockUserId}</if>
<if test="agentId != null "> and agent_id = #{agentId}</if>
<if test="serviceMode != null and serviceMode != ''"> and service_mode = #{serviceMode}</if>
<if test="isArrears != null">
<if test="isArrears">
and (sd.rent_time is null or sd.rent_time &lt;= now())
@ -127,6 +129,9 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
sd.surplus_ele,
sd.limit_recharge_time,
sd.limit_recharge_reason,
sd.agent_service_rate,
sd.agent_id,
sd.service_mode,
sm.model_name as model,
sm.picture as picture,
sm.tags as model_tags,
@ -295,6 +300,9 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<if test="surplusEle != null">surplus_ele,</if>
<if test="limitRechargeTime != null">limit_recharge_time,</if>
<if test="limitRechargeReason != null">limit_recharge_reason,</if>
<if test="agentServiceRate != null">agent_service_rate,</if>
<if test="agentId != null">agent_id,</if>
<if test="serviceMode != null">service_mode,</if>
</trim>
<trim prefix="values (" suffix=")" suffixOverrides=",">
<if test="storeId != null">#{storeId},</if>
@ -337,6 +345,9 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<if test="surplusEle != null">#{surplusEle},</if>
<if test="limitRechargeTime != null">#{limitRechargeTime},</if>
<if test="limitRechargeReason != null">#{limitRechargeReason},</if>
<if test="agentServiceRate != null">#{agentServiceRate},</if>
<if test="agentId != null">#{agentId},</if>
<if test="serviceMode != null">#{serviceMode},</if>
</trim>
</insert>
@ -400,6 +411,9 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<if test="surplusEle != null">surplus_ele = #{surplusEle},</if>
<if test="limitRechargeTime != null">limit_recharge_time = #{limitRechargeTime},</if>
<if test="limitRechargeReason != null">limit_recharge_reason = #{limitRechargeReason},</if>
<if test="agentServiceRate != null">agent_service_rate = #{agentServiceRate},</if>
<if test="agentId != null">agent_id = #{agentId},</if>
<if test="serviceMode != null">service_mode = #{serviceMode},</if>
</trim>
where device_id = #{deviceId}
</update>

View File

@ -29,7 +29,7 @@ public enum PayBillBstType {
private final String type;
private final String msg;
private final Class<? extends AfterPay> afterPay; // 支付回调处理器
private final Class<? extends AfterRefund> afterRefund;
private final Class<? extends AfterRefund> afterRefund; // 退款回调处理器
public static PayBillBstType parse(String type) {
for (PayBillBstType value : PayBillBstType.values()) {

View File

@ -3,11 +3,12 @@ package com.ruoyi.ss.receiveBill.service;
import java.math.BigDecimal;
import java.util.List;
import com.ruoyi.ss.device.domain.vo.DeviceVO;
import com.ruoyi.ss.receiveBill.domain.ReceiveBill;
import com.ruoyi.ss.receiveBill.domain.ReceiveBillVO;
import com.ruoyi.ss.receiveBill.domain.ReceiveBillQuery;
import com.ruoyi.ss.receiveBill.domain.vo.ReceiveAmountVO;
import com.ruoyi.ss.transactionBill.domain.dto.RechargePayBO;
import com.ruoyi.ss.user.domain.SmUserVo;
/**
* 应收账单Service接口
@ -68,10 +69,12 @@ public interface ReceiveBillService
/**
* 月费商户出账
*
* @param bo 充值BO
* @param amount 收取的金额
* @param mch 商户信息
* @param device 设备信息
* @param orderArrivalAmount 订单到账金额
* @param amount 月费收取的金额
*/
int genBillByMonthAndPay(RechargePayBO bo, BigDecimal amount);
int genBillByMonthAndPay(SmUserVo mch, DeviceVO device, BigDecimal orderArrivalAmount, BigDecimal amount);
/**
* 查询数量

View File

@ -2,7 +2,6 @@ package com.ruoyi.ss.receiveBill.service.impl;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.TimeUnit;
@ -14,8 +13,6 @@ import com.ruoyi.ss.receiveBill.domain.enums.ReceiveBillStatus;
import com.ruoyi.ss.receiveBill.domain.enums.ReceiveBillType;
import com.ruoyi.ss.receiveBill.domain.vo.ReceiveAmountVO;
import com.ruoyi.ss.recordBalance.domain.enums.RecordBalanceBstType;
import com.ruoyi.ss.transactionBill.domain.TransactionBill;
import com.ruoyi.ss.transactionBill.domain.dto.RechargePayBO;
import com.ruoyi.ss.transactionBill.service.impl.TransactionBillServiceImpl;
import com.ruoyi.ss.user.domain.SmUserVo;
import com.ruoyi.ss.user.service.ISmUserService;
@ -125,22 +122,17 @@ public class ReceiveBillServiceImpl implements ReceiveBillService
}
@Override
public int genBillByMonthAndPay(RechargePayBO bo, BigDecimal amount) {
SmUserVo mch = bo.getMch();
DeviceVO device = bo.getDevice();
TransactionBill order = bo.getOrder();
public int genBillByMonthAndPay(SmUserVo mch, DeviceVO device, BigDecimal orderArrivalAmount, BigDecimal amount) {
LocalDateTime billTime = LocalDateTime.now();
ServiceUtil.assertion(mch == null || mch.getUserId() == null, "用户不存在");
ServiceUtil.assertion(device == null || device.getDeviceId() == null, "设备不存在");
ServiceUtil.assertion(order == null, "订单不存在");
// 设备未过期则不生成账单
if (device.getRentTime() != null && device.getRentTime().isAfter(billTime)) {
return 1;
}
// 判断商户余额 + 订单金额是否足够账单金额
ServiceUtil.assertion(mch.getBalance().add(order.getArrivalAmount()).compareTo(amount) < 0, "设备到期,商家余额不足,请联系商家处理");
ServiceUtil.assertion(mch.getBalance().add(orderArrivalAmount).compareTo(amount) < 0, "设备到期,商家余额不足,请联系商家处理");
// 生成账单
ReceiveBill bill = new ReceiveBill();

View File

@ -210,14 +210,22 @@ public class TransactionBill extends BaseEntity implements Payable
@JsonView(JsonViewProfile.App.class)
private String deviceName;
@ApiModelProperty("套餐名称")
@JsonView(JsonViewProfile.App.class)
private String suitName;
@ApiModelProperty("设备MAC")
@JsonView(JsonViewProfile.App.class)
private String deviceMac;
@Excel(name = "设备产品ID")
@ApiModelProperty("设备产品ID")
private String deviceProductId;
@Excel(name = "设备服务费模式", readConverterExp = "1=-直营模式2-代理模式")
@ApiModelProperty("设备服务费模式")
private String deviceServiceMode;
@ApiModelProperty("套餐名称")
@JsonView(JsonViewProfile.App.class)
private String suitName;
@ApiModelProperty("总计退款金额")
@JsonView(JsonViewProfile.App.class)
private BigDecimal refundAmount;

View File

@ -1,5 +1,6 @@
package com.ruoyi.ss.transactionBill.domain.bo;
import com.ruoyi.common.core.domain.entity.SysDept;
import com.ruoyi.ss.bonus.domain.Bonus;
import com.ruoyi.ss.channel.domain.ChannelVO;
import com.ruoyi.ss.device.domain.vo.DeviceVO;
@ -44,4 +45,9 @@ public class RechargeBO {
// 分成详情
private List<Bonus> bonusList;
// 平台
private SysDept platform;
// 代理商
private SmUserVo agent;
}

View File

@ -1,5 +1,7 @@
package com.ruoyi.ss.transactionBill.domain.dto;
import com.ruoyi.common.core.domain.entity.SysDept;
import com.ruoyi.ss.bonus.domain.Bonus;
import com.ruoyi.ss.channel.domain.ChannelVO;
import com.ruoyi.ss.device.domain.vo.DeviceVO;
import com.ruoyi.ss.transactionBill.domain.TransactionBill;
@ -8,6 +10,8 @@ import com.ruoyi.ss.user.domain.SmUserVo;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.util.List;
/**
* 充值订单支付BO
* @author wjh
@ -30,4 +34,10 @@ public class RechargePayBO {
// 设备
private DeviceVO device;
// 平台
private SysDept platform;
// 分成列表
private List<Bonus> bonusList;
}

View File

@ -2,6 +2,8 @@ package com.ruoyi.ss.transactionBill.domain.vo;
import com.fasterxml.jackson.annotation.JsonView;
import com.ruoyi.common.core.domain.JsonViewProfile;
import com.ruoyi.ss.bonus.domain.Bonus;
import com.ruoyi.ss.bonus.domain.BonusVO;
import com.ruoyi.ss.suit.domain.enums.SuitTimeUnit;
import com.ruoyi.ss.transactionBill.domain.TransactionBill;
import io.swagger.annotations.ApiModel;
@ -9,6 +11,7 @@ import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.math.BigDecimal;
import java.util.List;
/**
* @author
@ -53,6 +56,9 @@ public class TransactionBillVO extends TransactionBill {
@JsonView(JsonViewProfile.App.class)
private BigDecimal suitSurplus;
@ApiModelProperty("分成列表")
private List<BonusVO> bonusList;
/**
* 获取套餐时长
*/

View File

@ -61,6 +61,8 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
stb.offline_image,
stb.deposit_pay_id,
stb.pay_id,
stb.device_product_id,
stb.device_service_mode,
</sql>
<sql id="selectSmTransactionBillVo">
@ -171,6 +173,8 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<if test="query.userMobile != null and query.userMobile != ''"> and su.phonenumber like concat('%', #{query.userMobile}, '%')</if>
<if test="query.suitFeeMode != null and query.suitFeeMode != ''"> and suit_fee_mode = #{query.suitFeeMode}</if>
<if test="query.suitFeeType != null and query.suitFeeType != ''"> and suit_fee_type = #{query.suitFeeType}</if>
<if test="query.deviceProductId != null "> and device_product_id = #{query.deviceProductId}</if>
<if test="query.deviceServiceMode != null and query.deviceServiceMode != ''"> and device_service_mode = #{query.deviceServiceMode}</if>
<if test="query.isUsing != null">
<if test="query.isUsing">
and <include refid="isUsing"/>
@ -414,6 +418,8 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<if test="deviceNo != null ">device_no,</if>
<if test="suitName != null ">suit_name,</if>
<if test="deviceMac != null ">device_mac,</if>
<if test="deviceProductId != null">device_product_id,</if>
<if test="deviceServiceMode != null">device_service_mode,</if>
<if test="refundAmount != null">refund_amount,</if>
<if test="refundMchAmount != null">refund_mch_amount,</if>
<if test="refundServiceAmount != null">refund_service_amount,</if>
@ -464,6 +470,8 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<if test="deviceNo != null ">#{deviceNo},</if>
<if test="suitName != null ">#{suitName},</if>
<if test="deviceMac != null ">#{deviceMac},</if>
<if test="deviceProductId != null">#{deviceProductId},</if>
<if test="deviceServiceMode != null">#{deviceServiceMode},</if>
<if test="refundAmount != null">#{refundAmount},</if>
<if test="refundMchAmount != null">#{refundMchAmount},</if>
<if test="refundServiceAmount != null">#{refundServiceAmount},</if>
@ -531,6 +539,8 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<if test="data.deviceNo != null ">device_no = #{data.deviceNo},</if>
<if test="data.suitName != null ">suit_name = #{data.suitName},</if>
<if test="data.deviceMac != null ">device_mac = #{data.deviceMac},</if>
<if test="data.deviceProductId != null">device_product_id = #{data.deviceProductId},</if>
<if test="data.deviceServiceMode != null">device_service_mode = #{data.deviceServiceMode},</if>
<if test="data.refundAmount != null">refund_amount = #{data.refundAmount},</if>
<if test="data.refundMchAmount != null">refund_mch_amount = #{data.refundMchAmount},</if>
<if test="data.refundServiceAmount != null">refund_service_amount = #{data.refundServiceAmount},</if>

View File

@ -94,6 +94,7 @@ public interface TransactionBillService
* @return 新增的数据订单编号
*/
String addOrder(RechargeBO bo);
/**
* 取消充值订单
* @param billNo 订单编号

View File

@ -2,14 +2,13 @@ package com.ruoyi.ss.transactionBill.service.impl;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.ServiceUtil;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.ss.bonus.service.BonusService;
import com.ruoyi.ss.payBill.domain.PayBillVO;
import com.ruoyi.ss.payBill.domain.bo.RefundSuccessBO;
import com.ruoyi.ss.payBill.domain.dto.PayBillRefundDTO;
import com.ruoyi.ss.payBill.interfaces.AfterPay;
import com.ruoyi.ss.payBill.interfaces.AfterRefund;
import com.ruoyi.ss.payBill.service.PayBillService;
import com.ruoyi.ss.recordBalance.domain.enums.RecordBalanceBstType;
import com.ruoyi.ss.suit.domain.enums.SuitFeeType;
import com.ruoyi.ss.transactionBill.domain.TransactionBill;
import com.ruoyi.ss.transactionBill.domain.TransactionBillQuery;
@ -45,6 +44,9 @@ public class RechargePayHandler implements AfterPay, AfterRefund {
@Autowired
private ISmUserService userService;
@Autowired
private BonusService bonusService;
@Override
public int onPaySuccess(PayBillVO payBill) {
TransactionBillVO bill = transactionBillService.selectSmTransactionBillByBillId(payBill.getBstId());
@ -92,7 +94,10 @@ public class RechargePayHandler implements AfterPay, AfterRefund {
ServiceUtil.assertion(update != 1, "修改订单状态失败");
// 商户余额增加
userService.addBalance(order.getMchId(), order.getArrivalAmount(), StringUtils.format("分时段订单%s", order.getBillNo()), RecordBalanceBstType.RECHARGE, order.getBillId());
// userService.addBalance(order.getMchId(), order.getArrivalAmount(), StringUtils.format("分时段订单%s", order.getBillNo()), RecordBalanceBstType.RECHARGE, order.getBillId());
// 处理分成
bonusService.partBonus(order.getBonusList(), order.getMoney());
// 如果有押金则申请押金退款
if (order.getSuitPrice() != null && order.getSuitPrice().compareTo(BigDecimal.ZERO) > 0 && order.getDepositPayId() != null) {

View File

@ -1,5 +1,6 @@
package com.ruoyi.ss.transactionBill.service.impl;
import com.ruoyi.common.constant.Constants;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.common.utils.ServiceUtil;
import com.ruoyi.common.utils.StringUtils;
@ -22,6 +23,7 @@ import com.ruoyi.ss.transactionBill.domain.vo.TransactionBillVO;
import com.ruoyi.ss.transactionBill.service.TransactionBillConverter;
import com.ruoyi.ss.user.domain.SmUserVo;
import com.ruoyi.ss.user.service.ISmUserService;
import com.ruoyi.system.service.ISysDeptService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@ -57,9 +59,13 @@ public class TransactionBillConverterImpl implements TransactionBillConverter {
@Autowired
private ChannelWithdrawService channelWithdrawService;
@Autowired
private TransactionBillServiceImpl transactionBillService;
@Autowired
private ISysDeptService deptService;
/**
* 将参数转为充值BO
*
@ -94,6 +100,8 @@ public class TransactionBillConverterImpl implements TransactionBillConverter {
bo.setMch(mch);
bo.setParams(dto);
bo.setStore(store);
bo.setPlatform(deptService.selectDeptById(Constants.ROOT_DEPT));
bo.setAgent(userService.selectSmUserByUserId(device.getAgentId()));
return bo;
}

View File

@ -11,11 +11,15 @@ import com.ruoyi.common.utils.collection.CollectionUtils;
import com.ruoyi.iot.domain.response.CommandResponse;
import com.ruoyi.iot.service.IotService;
import com.ruoyi.ss.account.domain.AccountVO;
import com.ruoyi.ss.bonus.domain.Bonus;
import com.ruoyi.ss.bonus.service.BonusConverter;
import com.ruoyi.ss.bonus.service.BonusService;
import com.ruoyi.ss.channel.domain.ChannelVO;
import com.ruoyi.ss.channelWithdraw.domain.ChannelWithdrawVO;
import com.ruoyi.ss.channelWithdraw.service.ChannelWithdrawService;
import com.ruoyi.ss.dashboard.vo.BillCountVo;
import com.ruoyi.ss.device.domain.enums.DeviceOnlineStatus;
import com.ruoyi.ss.device.domain.enums.DeviceServiceMode;
import com.ruoyi.ss.device.domain.vo.DeviceVO;
import com.ruoyi.ss.device.service.DeviceService;
import com.ruoyi.ss.payBill.domain.PayBillQuery;
@ -54,7 +58,6 @@ import com.ruoyi.ss.transfer.interfaces.AfterTransfer;
import com.ruoyi.ss.transfer.service.TransferConverter;
import com.ruoyi.ss.transfer.service.TransferService;
import com.ruoyi.ss.user.domain.SmUserVo;
import com.ruoyi.common.enums.ServiceType;
import com.ruoyi.ss.user.service.ISmUserService;
import com.ruoyi.common.pay.wx.service.WxPayService;
import com.ruoyi.system.domain.enums.config.ConfigKey;
@ -154,6 +157,12 @@ public class TransactionBillServiceImpl implements TransactionBillService, After
@Autowired
private TransactionBillConverter transactionBillConverter;
@Autowired
private BonusConverter bonusConverter;
@Autowired
private BonusService bonusService;
/**
* 查询充值记录
*
@ -252,10 +261,23 @@ public class TransactionBillServiceImpl implements TransactionBillService, After
// 下单
TransactionBill order = parseToOrder(bo);
// 代理商模式生成分成列表
if (DeviceServiceMode.AGENT.getMode().equals(order.getDeviceServiceMode())) {
List<Bonus> bonusList = bonusConverter.toPo(bo);
bo.setBonusList(bonusList);
}
transactionTemplate.execute(status -> {
// 插入数据库
int insert = this.insertSmTransactionBill(order);
ServiceUtil.assertion(insert != 1, "下单失败");
// 代理商模式插入分成列表
if (DeviceServiceMode.AGENT.getMode().equals(order.getDeviceServiceMode())) {
int bonusInsert = bonusService.batchInsert(bo.getBonusList());
ServiceUtil.assertion(bonusInsert != bo.getBonusList().size(), "创建分成失败");
}
return insert;
});
@ -270,46 +292,57 @@ public class TransactionBillServiceImpl implements TransactionBillService, After
// 处理充值服务费
private void handleRechargeService(RechargePayBO bo) {
TransactionBillVO order = bo.getOrder();
List<Bonus> bonusList = bonusConverter.toPo(bo);
// 获取商户的服务费配置
UserRechargeServiceVO userRechargeService = this.getMchRechargeService(bo.getChannel(), bo.getMch(), bo.getDevice());
String serviceType = userRechargeService.getServiceType(); // 服务费类型
BigDecimal serviceRate = userRechargeService.getServiceRate(); // 服务费
// UserRechargeServiceVO userRechargeService = this.getMchRechargeService(bo.getChannel(), bo.getMch(), bo.getDevice());
// String serviceType = userRechargeService.getServiceType(); // 服务费类型
// BigDecimal serviceRate = userRechargeService.getServiceRate(); // 服务费
// 根据服务费类型进行对应操作
// 月费
if (ServiceType.MONTH.getType().equals(serviceType)) {
// 服务费 = 0
order.setServiceCharge(BigDecimal.ZERO);
// 商户到账金额 = 交易金额
order.setArrivalAmount(order.getMoney());
int count = receiveBillService.genBillByMonthAndPay(bo, serviceRate);
ServiceUtil.assertion(count == 0, "商户出账失败,请刷新后重试");
}
// 若收取月费
// if (ServiceType.MONTH.getType().equals(serviceType)) {
// // 商户的分成
// Bonus mchBonus = bonusList.stream()
// .filter(item -> item.getArrivalId().equals(bo.getMch().getUserId())
// && BonusArrivalType.userList().contains(item.getArrivalType()))
// .findFirst().orElse(null);
// // 服务费 = 0
// order.setServiceCharge(BigDecimal.ZERO);
// // 商户到账金额 = 交易金额
// order.setArrivalAmount(order.getMoney());
// int count = receiveBillService.genBillByMonthAndPay(bo.getMch(), bo.getDevice(), bo.getOrder().getArrivalAmount() , serviceRate);
// ServiceUtil.assertion(count == 0, "商户出账失败,请刷新后重试");
// }
// 设备订单比例
else if(ServiceType.PERCENT.getType().equals(serviceType)){
// 服务费
BigDecimal serviceCharge = serviceRate.multiply(order.getMoney()).divide(new BigDecimal(100), 2, RoundingMode.HALF_UP);
// 非分时订单处理最低服务费
if (!SuitFeeType.timingList().contains(order.getSuitFeeType())) {
BigDecimal minService = sysConfigService.getBigDecimal(ConfigKey.RECHARGE_MIN_SERVICE);
// ServiceUtil.assertion(order.getMoney().compareTo(minService) < 0, "当前套餐金额小于最低服务费,请联系商户处理");
// 当服务费不满足最低服务费时设置为最低服务费
if (serviceCharge.compareTo(minService) < 0) {
serviceCharge = minService;
}
// 当金额不满足服务费时将全收
if (order.getMoney().compareTo(serviceCharge) < 0) {
serviceCharge = order.getMoney();
}
}
order.setServiceCharge(serviceCharge);
// 商户最终到账的金额 = 交易金额 - 服务费
order.setArrivalAmount(order.getMoney().subtract(serviceCharge));
} else {
throw new ServiceException("未知的服务费类型");
}
// else if(ServiceType.PERCENT.getType().equals(serviceType)){
//
// bonusConverter.toPo(bo);
//
// // 服务费
// BigDecimal serviceCharge = serviceRate.multiply(order.getMoney()).divide(new BigDecimal(100), 2, RoundingMode.HALF_UP);
// // 非分时订单处理最低服务费
// if (!SuitFeeType.timingList().contains(order.getSuitFeeType())) {
// BigDecimal minService = sysConfigService.getBigDecimal(ConfigKey.RECHARGE_MIN_SERVICE);
//// ServiceUtil.assertion(order.getMoney().compareTo(minService) < 0, "当前套餐金额小于最低服务费,请联系商户处理");
// // 当服务费不满足最低服务费时设置为最低服务费
// if (serviceCharge.compareTo(minService) < 0) {
// serviceCharge = minService;
// }
// // 当金额不满足服务费时将全收
// if (order.getMoney().compareTo(serviceCharge) < 0) {
// serviceCharge = order.getMoney();
// }
// }
// order.setServiceCharge(serviceCharge);
//
// // 商户最终到账的金额 = 交易金额 - 服务费
// order.setArrivalAmount(order.getMoney().subtract(serviceCharge));
// } else {
// throw new ServiceException("未知的服务费类型");
// }
}
@ -381,6 +414,8 @@ public class TransactionBillServiceImpl implements TransactionBillService, After
order.setMchId(mch.getUserId());
order.setDeviceName(device.getDeviceName());
order.setDeviceMac(device.getMac());
order.setDeviceProductId(device.getModelProductId());
order.setDeviceServiceMode(device.getServiceMode());
// 店铺信息
if (store != null) {
@ -836,8 +871,8 @@ public class TransactionBillServiceImpl implements TransactionBillService, After
int updateCount = this.updateByQuery(data, query);
ServiceUtil.assertion(updateCount != 1, "订单状态已发生变化,请刷新后重试");
// 商户余额增加
userService.addBalance(bill.getMchId(), bill.getArrivalAmount(), String.format("订单充值:%s", bill.getBillNo()), RecordBalanceBstType.RECHARGE, bill.getBillId());
// 处理分成
bonusService.partBonus(bill.getBonusList(), bill.getMoney());
// 记录下充值后的余额
SmUserVo user = userService.selectSmUserByUserId(bill.getMchId());
@ -1641,8 +1676,12 @@ public class TransactionBillServiceImpl implements TransactionBillService, After
Long lockKey = order.getBillId();
ServiceUtil.assertion(!redisLock.lock(RedisLockKey.PREPAY, lockKey), "当前订单正在支付,请稍后重试");
try {
// 处理服务费
this.handleRechargeService(bo);
// 直营计算分成
if (DeviceServiceMode.DIRECT.getMode().equals(order.getDeviceServiceMode())) {
List<Bonus> bonusList = bonusConverter.toPo(bo);
bo.setBonusList(bonusList);
}
return transactionTemplate.execute(status -> {
// 修改订单信息
@ -1655,6 +1694,12 @@ public class TransactionBillServiceImpl implements TransactionBillService, After
int paying = this.updateByQuery(data, query);
ServiceUtil.assertion(paying != 1, "订单状态已发生变化,更新失败");
// 直营,新增分成信息
if (DeviceServiceMode.DIRECT.getMode().equals(order.getDeviceServiceMode())) {
int bonusInsert = bonusService.batchInsert(bo.getBonusList());
ServiceUtil.assertion(bonusInsert != bo.getBonusList().size(), "新增分成失败");
}
// 创建支付订单并发起支付
return payBillService.createPayBill(payBillConverter.toPoByRechargeMoney(bo));
});

View File

@ -47,6 +47,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
su.is_real,
su.limit_withdraw,
su.limit_withdraw_reason,
su.agent_service_rate,
if(su.is_real, su.real_name, su.user_name) as real_or_user_name,
(select sum(stb.money) from sm_transaction_bill stb where stb.user_id = su.user_id and stb.type = '1' and stb.status = '2') as recharge_amount,
(select sum(stb.arrival_amount) from sm_transaction_bill stb where stb.user_id = su.user_id and stb.type = '2' and stb.status = '14') as with_drawl_amount,
@ -165,6 +166,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<if test="isReal != null">is_real,</if>
<if test="limitWithdraw != null">limit_withdraw,</if>
<if test="limitWithdrawReason != null">limit_withdraw_reason,</if>
<if test="agentServiceRate != null">agent_service_rate,</if>
</trim>
<trim prefix="values (" suffix=")" suffixOverrides=",">
<if test="userName != null and userName != ''">#{userName},</if>
@ -200,6 +202,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<if test="isReal != null">#{isReal},</if>
<if test="limitWithdraw != null">#{limitWithdraw},</if>
<if test="limitWithdrawReason != null">#{limitWithdrawReason},</if>
<if test="agentServiceRate != null">#{agentServiceRate},</if>
</trim>
</insert>
@ -245,6 +248,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<if test="isReal != null">is_real = #{isReal},</if>
<if test="limitWithdraw != null">limit_withdraw = #{limitWithdraw},</if>
<if test="limitWithdrawReason != null">limit_withdraw_reason = #{limitWithdrawReason},</if>
<if test="agentServiceRate != null">agent_service_rate = #{agentServiceRate},</if>
</trim>
where user_id = #{userId}
</update>