1.合伙人分账功能

This commit is contained in:
邱贞招 2024-10-18 10:18:17 +08:00
parent c11c2de893
commit ae3cea85b4
10 changed files with 361 additions and 94 deletions

View File

@ -127,6 +127,9 @@ public class AppVerifyController extends BaseController
@Autowired
private TmPayService tmPayService;
@Resource
private SysUserMapper userMapper;
/**
* 故障上报
@ -973,6 +976,22 @@ public class AppVerifyController extends BaseController
public AjaxResult getDept(Long areaId)
{
logger.info("【获取运营商信息】获取到areaId【{}】", areaId);
if(areaId == null){
AsUser asUser1 = asUserMapper.selectUserById(getUserId());
SysUser sysUser = userService.selectUserById(asUser1.getSysUserId());
if(sysUser == null){
throw new ServiceException("用户【"+asUser1.getUserName()+"】未绑定系统用户");
}
BigDecimal todayOrderAmount = getTodayOrderAmount(sysUser);
if (sysUser.getBalance() != null) {
sysUser.setSettlementAmount(todayOrderAmount);
sysUser.setWithdrawableAmount(sysUser.getBalance().subtract(todayOrderAmount));
SysDept sysDept = wxPayService.getDeptObjByAreaId(sysUser.getAreaId());
sysUser.setHandlingChargeType(sysDept.getHandlingChargeType());
sysUser.setWithdrawHandlingCharge(sysDept.getWithdrawHandlingCharge());
}
return success(sysUser);
}
SysDept sysDept = wxPayService.getDeptObjByAreaId(areaId);
if(ObjectUtil.isNotNull(sysDept)){
@ -1013,6 +1032,30 @@ public class AppVerifyController extends BaseController
return todayOrderAmount;
}
@NotNull
private BigDecimal getTodayOrderAmount(SysUser user) {
// 获取今天的日期字符串
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
String startDateStr = dateFormat.format(new Date()) + " 00:00:00";
String endDateStr = dateFormat.format(new Date()) + " 23:59:59";
//今日订单金额
BigDecimal todayOrderAmount = BigDecimal.ZERO;
Long areaId = user.getAreaId();
BigDecimal payFee = defaultIfNull(etOrderMapper.getPayFee(startDateStr, endDateStr, null, areaId), BigDecimal.ZERO);//新增
BigDecimal refundFee = defaultIfNull(etOrderMapper.getRefundFee(startDateStr, endDateStr, null, areaId), BigDecimal.ZERO);//退款
BigDecimal serviceFee = etCapitalFlowMapper.getHandlingFee(startDateStr, endDateStr, null, areaId);//手续费,扣除掉退款部分的
BigDecimal platformServiceFee = etCapitalFlowMapper.getServiceFee(startDateStr, endDateStr, null,areaId);//平台服务费 ,扣除掉退款部分的
BigDecimal areaOrderAmount = defaultIfNull(payFee.subtract(serviceFee).subtract(refundFee).subtract(platformServiceFee), BigDecimal.ZERO);//营收 = 新增 - 手续费 - 退款 - 平台服务费
if (areaOrderAmount != null) {
todayOrderAmount = todayOrderAmount.add(areaOrderAmount);
}
if(todayOrderAmount.compareTo(user.getBalance()) > 0){
todayOrderAmount = user.getBalance();
}
return todayOrderAmount;
}
private BigDecimal defaultIfNull(BigDecimal value, BigDecimal defaultValue) {
return value != null ? value : defaultValue;
}
@ -1176,6 +1219,17 @@ public class AppVerifyController extends BaseController
public AjaxResult add(@RequestBody EtWithdraw etWithdraw)
{
logger.info("管理员提现请求:【{}】", JSON.toJSON(etWithdraw));
if(etWithdraw.getAreaId() == null){
//合伙人提现
logger.info("合伙人提现userId=【{}】",getUserId());
AsUser asUser1 = asUserMapper.selectUserById(getUserId());
SysUser sysUser = userService.selectUserById(asUser1.getSysUserId());
if(sysUser == null){
throw new ServiceException("用户【"+asUser1.getUserName()+"】未绑定系统用户");
}
int i1 = userService.adminWithdraw(etWithdraw.getAmount(),sysUser);
return toAjax(i1);
}
SysDept sysDept = wxPayService.getDeptObjByAreaId(etWithdraw.getAreaId());
int i = deptService.adminWithdraw(etWithdraw.getAmount(),sysDept,"1");
return toAjax(i);
@ -1512,7 +1566,7 @@ public class AppVerifyController extends BaseController
* 3. 查询订单所属运营区
* 4. 查询运营区客服电话
*/
@Log(title = "", businessType = BusinessType.ZEROORDER)
@Log(title = "0元订单", businessType = BusinessType.ZEROORDER)
@GetMapping("/latestServicePhone")
public AjaxResult latestServicePhone(Long userId)
{
@ -1541,6 +1595,20 @@ public class AppVerifyController extends BaseController
@PostMapping("/uploadPaymentCode")
public AjaxResult edit(String collectionCode,Long deptId)
{
if(deptId ==null){
//合伙人提现
logger.info("合伙人提现userId=【{}】",getUserId());
AsUser asUser1 = asUserMapper.selectUserById(getUserId());
SysUser sysUser = userService.selectUserById(asUser1.getSysUserId());
if(sysUser == null){
throw new ServiceException("用户【"+asUser1.getUserName()+"】未绑定系统用户");
}
SysUser updateUser = new SysUser();
updateUser.setCollectionCode(collectionCode);
updateUser.setUserId(sysUser.getUserId());
int updateUser1 = userMapper.updateUser(updateUser);
return toAjax(updateUser1);
}
SysDept sysDept = new SysDept();
sysDept.setDeptId(deptId);
sysDept.setCollectionCode(collectionCode);

View File

@ -115,7 +115,7 @@ public class EtCapitalFlowController extends BaseController
*/
@Log(title = "管理员提现", businessType = BusinessType.ADMINWITHDRAW)
@PostMapping("/withdraw")
public AjaxResult add(@RequestBody EtWithdraw etWithdraw)
public AjaxResult withdraw(@RequestBody EtWithdraw etWithdraw)
{
logger.info("管理员提现请求:【{}】", JSON.toJSON(etWithdraw));
Long deptId = etWithdraw.getDeptId();

View File

@ -138,6 +138,71 @@ public class SysUser extends BaseEntity
/** 角色对象 */
private List<AsUser> users;
private String[] typeList;
/** 提现手续费类型: 1-按比例2-按每笔 */
public String handlingChargeType;
/** 提现手续费 */
public String withdrawHandlingCharge;
/** 收款码 */
public String collectionCode;
/** 待结算金额 */
public BigDecimal settlementAmount;
/** 可提现金额 */
public BigDecimal withdrawableAmount;
public String getCollectionCode() {
return collectionCode;
}
public String getHandlingChargeType() {
return handlingChargeType;
}
public void setHandlingChargeType(String handlingChargeType) {
this.handlingChargeType = handlingChargeType;
}
public String getWithdrawHandlingCharge() {
return withdrawHandlingCharge;
}
public void setWithdrawHandlingCharge(String withdrawHandlingCharge) {
this.withdrawHandlingCharge = withdrawHandlingCharge;
}
public void setCollectionCode(String collectionCode) {
this.collectionCode = collectionCode;
}
public BigDecimal getSettlementAmount() {
return settlementAmount;
}
public void setSettlementAmount(BigDecimal settlementAmount) {
this.settlementAmount = settlementAmount;
}
public BigDecimal getWithdrawableAmount() {
return withdrawableAmount;
}
public void setWithdrawableAmount(BigDecimal withdrawableAmount) {
this.withdrawableAmount = withdrawableAmount;
}
public String[] getTypeList() {
return typeList;
}
public void setTypeList(String[] typeList) {
this.typeList = typeList;
}
public List<AsUser> getUsers() {
return users;
}

View File

@ -44,9 +44,11 @@ public interface CallbackService {
* @param ownerType 所属人类型
* @param user 合伙人对象
* @param payType 支付方式
* @param totalPartnerDividend 合伙人退款金额
* @param refundPercentage 退款比例
* @return void
*/
public EtCapitalFlow capitalFlowRecords(EtOrder order, String type, String busType, String ownerType, SysUser user, String payType);
public EtCapitalFlow capitalFlowRecords(EtOrder order, String type, String busType, String ownerType, SysUser user, String payType,BigDecimal totalPartnerDividend,BigDecimal refundPercentage);
/**
* 新增资金流水记录
@ -88,6 +90,6 @@ public interface CallbackService {
* @param area 运营区域
* @return boolean
*/
public boolean dividendHandle(String transactionId, EtOrder order, EtOperatingArea area, BigDecimal dividendAmount);
public boolean dividendHandle(EtOrder order, EtOperatingArea area, BigDecimal dividendAmount);
}

View File

@ -1,6 +1,9 @@
package com.ruoyi.system.service;
import java.math.BigDecimal;
import java.util.List;
import com.ruoyi.common.core.domain.entity.SysDept;
import com.ruoyi.common.core.domain.entity.SysUser;
/**
@ -208,4 +211,9 @@ public interface ISysUserService
* 绑定app用户
*/
int bandAppUser(SysUser user);
/**
* 合伙人提现
*/
int adminWithdraw(BigDecimal amount, SysUser sysUser);
}

View File

@ -46,6 +46,7 @@ import org.springframework.transaction.support.TransactionTemplate;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.Comparator;
import java.util.Date;
import java.util.List;
@ -233,12 +234,17 @@ public class CallbackServiceImpl implements CallbackService {
asDevice.setStatus(ServiceConstants.VEHICLE_STATUS_NORMAL);//还车后车辆正常运营
asDevice.setLockStatus(ServiceConstants.LOCK_STATUS_CLOSE);
// 新增资金流水记录
EtCapitalFlow capitalFlow = capitalFlowRecords(order, ServiceConstants.FLOW_TYPE_INCOME, ServiceConstants.ORDER_TYPE_RIDING, ServiceConstants.OWNER_TYPE_OPERATOR, null, ServiceConstants.PAY_TYPE_WX);
EtCapitalFlow capitalFlow = capitalFlowRecords(order, ServiceConstants.FLOW_TYPE_INCOME, ServiceConstants.ORDER_TYPE_RIDING,
ServiceConstants.OWNER_TYPE_OPERATOR, null, ServiceConstants.PAY_TYPE_WX,null,null);
logger.info("=================【微信/太米支付回调-新增资金流水记录后】=================={}",JSON.toJSON(capitalFlow));
order1.setHandlingCharge(capitalFlow.getHandlingCharge());
order1.setPlatformServiceFee(capitalFlow.getPlatformServiceFee());
order1.setOperatorDividend(capitalFlow.getOperatorDividend());
order1.setCost(getCost(channelVO,order.getPayFee()));
BigDecimal dividendAmount= order.getPayFee().subtract(capitalFlow.getHandlingCharge()).subtract(capitalFlow.getPlatformServiceFee());//分账金额订单实际支付金额-平台服务费-支付手续费
logger.info("=================【微信支付回调】分账金额=================={}",dividendAmount);
dividendHandle(order, area,dividendAmount);
logger.info("=================【微信/太米支付回调】4444444==================");
}else if(attachVo.getType().equals(ServiceConstants.BUSINESS_TYPE_APPOINTMENT)){
logger.info("【微信/太米支付回调】取消预约支付");
@ -383,7 +389,7 @@ public class CallbackServiceImpl implements CallbackService {
logger.info("【微信支付回调】优惠券支付-------------5");
// 增加优惠券账变
callbackService.capitalFlowRecords(order,ServiceConstants.FLOW_TYPE_INCOME,
ServiceConstants.ORDER_TYPE_COUPON_INCOME,ServiceConstants.OWNER_TYPE_OPERATOR,null,ServiceConstants.PAY_TYPE_WX);
ServiceConstants.ORDER_TYPE_COUPON_INCOME,ServiceConstants.OWNER_TYPE_OPERATOR,null,ServiceConstants.PAY_TYPE_WX,null,null);
logger.info("【微信支付回调】优惠券支付-------------6");
}
@ -413,7 +419,7 @@ public class CallbackServiceImpl implements CallbackService {
//记录资金流水
order.setPayFee(new BigDecimal(0.1));
callbackService.capitalFlowRecords(order,ServiceConstants.FLOW_TYPE_DISBURSE,
ServiceConstants.ORDER_TYPE_MSG,ServiceConstants.OWNER_TYPE_OPERATOR,null,ServiceConstants.PAY_TYPE_YE);
ServiceConstants.ORDER_TYPE_MSG,ServiceConstants.OWNER_TYPE_OPERATOR,null,ServiceConstants.PAY_TYPE_YE,null,null);
// 短信日志
EtMsgLog etMsgLog = new EtMsgLog();
@ -466,7 +472,7 @@ public class CallbackServiceImpl implements CallbackService {
//记录资金流水
order.setPayFee(new BigDecimal(0.1));
callbackService.capitalFlowRecords(order,ServiceConstants.FLOW_TYPE_DISBURSE,
ServiceConstants.ORDER_TYPE_MSG,ServiceConstants.OWNER_TYPE_OPERATOR,null,ServiceConstants.PAY_TYPE_YE);
ServiceConstants.ORDER_TYPE_MSG,ServiceConstants.OWNER_TYPE_OPERATOR,null,ServiceConstants.PAY_TYPE_YE,null,null);
// 短信日志
EtMsgLog etMsgLog = new EtMsgLog();
@ -500,21 +506,19 @@ public class CallbackServiceImpl implements CallbackService {
/**
* 分账处理
* 1.根据订单号查询分账记录如果有记录直接返回
* 2.根据区域id查询合伙人列表根据合伙人分红比例分账保存分账明细表
* 3.请求分账
* 2.所有的分账人保存分账明细表
* 3.新增资金流水表
* 分账金额dividendAmount 分账金额订单实际支付金额-平台服务费-支付手续费
*/
@Override
public boolean dividendHandle(String transactionId, EtOrder order, EtOperatingArea area, BigDecimal dividendAmount) {
public boolean dividendHandle(EtOrder order, EtOperatingArea area, BigDecimal dividendAmount) {
List<EtDividendDetail> etDividendDetails = dividendDetailService.selectEtDividendDetailByOrderNo(order.getOrderNo());
if(ObjectUtil.isNotNull(etDividendDetails) && etDividendDetails.size()>0){
return true;
}
logger.info("=================【微信支付回调】24小时后开始请求分账==================");
logger.info("=================【微信支付回调】开始请求分账==================");
logger.info("区域对象====="+JSON.toJSONString(area));
logger.info("订单对象====="+JSON.toJSONString(order));
// 请求分账
// List<CreateOrderReceiver> receivers = new ArrayList<>();
// 获取到合伙人的openid
SysUser sysUser = new SysUser();
sysUser.setUserType("03");
@ -527,61 +531,33 @@ public class CallbackServiceImpl implements CallbackService {
boolean cooperationExpired = DateUtils.isCooperationExpired(sysUser1.getCooperationTime());
if(!cooperationExpired && sysUser1.getStatus().equals("0")){
EtDividendDetail etDividendDetail = new EtDividendDetail();
AsUser asUser1 = asUserMapper.selectUserById(sysUser1.getAppUserId());
if(asUser1!=null && asUser1.getWxopenid()!=null){
logger.info("=============系统用户sysUser1============"+JSON.toJSONString(sysUser1));
CreateOrderReceiver receiver = new CreateOrderReceiver();
receiver.setType(ReceiverType.PERSONAL_OPENID.name());
receiver.setAccount(asUser1.getWxopenid());
logger.info("=================分账金额(订单实际支付金额-平台服务费-支付手续费dividendAmount=================="+dividendAmount);
BigDecimal divide = new BigDecimal(sysUser1.getDividendProportion()).divide(new BigDecimal(100), 2, BigDecimal.ROUND_HALF_UP);
logger.info("=================分账比例%=================="+divide);
BigDecimal multiply = dividendAmount.multiply(divide);
logger.info(sysUser1.getUserName()+"分账比例:"+sysUser1.getDividendProportion()+"%,分账金额:"+multiply);
receiver.setAmount(multiply.multiply(new BigDecimal(100)).longValue());
receiver.setDescription(area.getAreaName()+"共享电动车自动分账");
etDividendDetail.setAreaId(area.getAreaId());
etDividendDetail.setType(ServiceConstants.PROFITSHARING_TYPE_PARTNER);
etDividendDetail.setPartnerId(sysUser1.getUserId());
etDividendDetail.setOrderNo(order.getOrderNo());
etDividendDetail.setTotalAmount(order.getPayFee());
etDividendDetail.setCreateTime(DateUtils.getNowDate());
etDividendDetail.setDividendProportion(sysUser1.getDividendProportion());
etDividendDetail.setDividendAmount(multiply);
logger.info("【微信支付回调】保存分账明细 === " + JSON.toJSONString(etDividendDetail));
int i = dividendDetailService.insertEtDividendDetail(etDividendDetail);
if(i==0){
throw new ServiceException("保存分账明细失败");
}
order.setPayFee(multiply);
callbackService.capitalFlowRecords(order,ServiceConstants.FLOW_TYPE_INCOME,ServiceConstants.ORDER_TYPE_RIDING,ServiceConstants.OWNER_TYPE_PARTNER,sysUser1,ServiceConstants.PAY_TYPE_WX);
logger.info("=============系统用户合伙人sysUser1============"+JSON.toJSONString(sysUser1));
logger.info("=================分账金额(订单实际支付金额-平台服务费-支付手续费dividendAmount=================="+dividendAmount);
BigDecimal divide = new BigDecimal(sysUser1.getDividendProportion()).divide(new BigDecimal(100), 2, BigDecimal.ROUND_HALF_UP);
logger.info("=================分账比例%=================="+divide);
BigDecimal multiply = dividendAmount.multiply(divide);
logger.info(sysUser1.getUserName()+"分账比例:"+sysUser1.getDividendProportion()+"%,分账金额:"+multiply);
etDividendDetail.setAreaId(area.getAreaId());
etDividendDetail.setType(ServiceConstants.PROFITSHARING_TYPE_PARTNER);
etDividendDetail.setPartnerId(sysUser1.getUserId());
etDividendDetail.setOrderNo(order.getOrderNo());
etDividendDetail.setTotalAmount(order.getPayFee());
etDividendDetail.setCreateTime(DateUtils.getNowDate());
etDividendDetail.setDividendProportion(sysUser1.getDividendProportion());
etDividendDetail.setDividendAmount(multiply);
logger.info("【微信支付回调】保存分账明细 === " + JSON.toJSONString(etDividendDetail));
int i = dividendDetailService.insertEtDividendDetail(etDividendDetail);
if(i==0){
throw new ServiceException("保存分账明细失败");
}
order.setPayFee(multiply);
callbackService.capitalFlowRecords(order,ServiceConstants.FLOW_TYPE_INCOME,ServiceConstants.ORDER_TYPE_RIDING,
ServiceConstants.OWNER_TYPE_PARTNER,sysUser1,ServiceConstants.PAY_TYPE_WX,null,null);
}else{
logger.info("=================【微信支付回调】合伙人【{}】已禁用或已过期合作期==================",sysUser1.getUserName());
}
}
}
// 计算平台服务费
// logger.info("=================【微信支付回调】计算平台服务费==================");
// platformServiceFee(order, area);
// List<EtAreaDept> areaId1 = etAreaDeptMapper.selectList(new QueryWrapper<EtAreaDept>().eq("area_id", order.getAreaId()));
// if (ObjectUtil.isNotEmpty(areaId1) && areaId1.size() > 0){
// EtAreaDept etAreaDept = areaId1.get(0);
// SysDept sysDept = deptService.selectDeptById(etAreaDept.getDeptId());
// logger.info("获取到运营商对象:【{}】",JSON.toJSON(sysDept));
// OrdersEntity ordersEntity = wxPayService.createOrder(sysDept,transactionId,receivers);
// if(ordersEntity!=null){
// logger.info("【微信支付回调】发起分账响应:【{}】",JSON.toJSON(ordersEntity));
// }else{
// logger.info("【微信支付回调】发起分账失败");
// throw new ServiceException("发起分账失败");
// }
// }else{
// logger.info("区域:【{}】没有绑定运营商",order.getAreaId());
// throw new ServiceException("区域:【"+order.getAreaId()+"】没有绑定运营商");
// }
return false;
}
@ -687,7 +663,7 @@ public class CallbackServiceImpl implements CallbackService {
* 资金流水记录
* */
@Override
public EtCapitalFlow capitalFlowRecords(EtOrder order,String type,String busType,String ownerType,SysUser user,String payType) {
public EtCapitalFlow capitalFlowRecords(EtOrder order,String type,String busType,String ownerType,SysUser user,String payType,BigDecimal totalPartnerDividend,BigDecimal refundPercentage) {
EtCapitalFlow capitalFlow = new EtCapitalFlow();
if(ownerType.equals(ServiceConstants.OWNER_TYPE_OPERATOR)){//运营商
SysDept sysDept = wxPayService.getDeptObjByAreaId(order.getAreaId());
@ -744,21 +720,16 @@ public class CallbackServiceImpl implements CallbackService {
BigDecimal partnerDividend = BigDecimal.ZERO;
BigDecimal separateAccountFee = order.getPayFee().subtract(handlingCharge).subtract(platformServiceFee);
logger.info("【微信支付回调--保存资金流水记录】 ==============扣掉手续费和服务费之后的金额,这个金额拿来分账====================="+separateAccountFee);
BigDecimal operatorDividend = separateAccountFee;
// if(sysDept.getIsProfitSharing().equals("true")){//需要分账
// logger.info("【微信支付回调--保存资金流水记录】 ==============需要分账====================="+sysDept.getIsProfitSharing());
//获取所有合伙人列表
SysUser sysUser = new SysUser();
sysUser.setUserType("03");
sysUser.setAreaId(order.getAreaId());
List<SysUser> sysUsers = userMapper.selectUserList(sysUser);
double totalDividendProportion = sysUsers.stream()
.mapToDouble(SysUser::getDividendProportion)
.sum();//算出总的分成比例
BigDecimal decimal = new BigDecimal(totalDividendProportion).divide(new BigDecimal(100), 2, BigDecimal.ROUND_HALF_UP);
partnerDividend = operatorDividend.multiply(decimal);
operatorDividend = operatorDividend.subtract(partnerDividend);
// }
BigDecimal operatorDividend = separateAccountFee;//1.92
//计算总的分成比例不包含合作过期的,如果总的退款金额totalPartnerDividend有传入则直接用否则根据合伙人的比例计算得出
if(totalPartnerDividend != null){
operatorDividend = operatorDividend.subtract(totalPartnerDividend);
logger.info("【微信支付回调--保存资金流水记录】 ===退款金额(扣除掉手续费和服务费的金额)【{}】减去合伙人总退款{}=========结果{},",separateAccountFee,totalPartnerDividend,operatorDividend);
}else{
BigDecimal decimal = getTotalDividendProportion(order);//0.3
partnerDividend = operatorDividend.multiply(decimal);
operatorDividend = operatorDividend.subtract(partnerDividend);
}
logger.info("【微信支付回调--保存资金流水记录】 ==============partnerDividend====================="+partnerDividend);
logger.info("【微信支付回调--保存资金流水记录】 ==============operatorDividend====================="+operatorDividend);
if(type.equals(ServiceConstants.FLOW_TYPE_INCOME)){
@ -813,6 +784,7 @@ public class CallbackServiceImpl implements CallbackService {
if(busType.equals(ServiceConstants.ORDER_TYPE_WITHDRAW)){//提现需要手续费不需要平台服务费
BigDecimal separateAccountFee = order.getPayFee();
capitalFlow.setPartnerDividend(BigDecimal.ZERO);
capitalFlow.setStatus(ServiceConstants.FLOW_STATUS_APPLY);
capitalFlow.setOperatorDividend(separateAccountFee.negate());
capitalFlow.setOperatorBalance(user.getBalance().subtract(separateAccountFee));
userMapper.changeUserBalance(separateAccountFee.negate(),user.getUserId());
@ -829,7 +801,7 @@ public class CallbackServiceImpl implements CallbackService {
logger.info("【微信支付回调(合伙人)--保存资金流水记录】 ==============收入=====================");
}else{
capitalFlow.setPartnerDividend(partnerDividend.negate());
capitalFlow.setOperatorDividend(order.getPayFee());
capitalFlow.setOperatorDividend(order.getPayFee().negate());
capitalFlow.setOperatorBalance(user.getBalance().subtract(partnerDividend));
userMapper.changeUserBalance(partnerDividend.negate(),user.getUserId());
logger.info("【微信支付回调(合伙人)--保存资金流水记录】 ==============支出=====================");
@ -852,6 +824,20 @@ public class CallbackServiceImpl implements CallbackService {
return capitalFlow;
}
private BigDecimal getTotalDividendProportion(EtOrder order) {
SysUser sysUser = new SysUser();
sysUser.setUserType("03");
sysUser.setAreaId(order.getAreaId());
List<SysUser> sysUsers = userMapper.selectUserList(sysUser);
// 计算总的分成比例过滤掉合作时间过期的用户
double totalDividendProportion = sysUsers.stream()
.filter(u -> u.getCooperationTime() != null && u.getCooperationTime().compareTo(new Date()) > 0) // 判断合作时间是否未过期
.mapToDouble(SysUser::getDividendProportion)
.sum(); // 算出总的分成比例
BigDecimal decimal = new BigDecimal(totalDividendProportion).divide(new BigDecimal(100), 2, BigDecimal.ROUND_HALF_UP);
return decimal;
}
/**
* 资金流水记录
* */

View File

@ -10,6 +10,7 @@ import com.ruoyi.common.constant.IotConstants;
import com.ruoyi.common.constant.ServiceConstants;
import com.ruoyi.common.core.domain.entity.AsUser;
import com.ruoyi.common.core.domain.entity.SysDept;
import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.enums.BusinessStatus;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.pay.PaymentResult;
@ -68,6 +69,9 @@ public class EtOrderServiceImpl implements IEtOrderService
@Resource
private AsUserMapper asUserMapper;
@Resource
private SysUserMapper userMapper;
@Autowired
private IEtOperatingAreaService etOperatingAreaService;
@ -604,7 +608,8 @@ public class EtOrderServiceImpl implements IEtOrderService
}
}
/** 押金抵扣后生成资金流水记录 */
callbackService.capitalFlowRecords(order,ServiceConstants.FLOW_TYPE_INCOME,ServiceConstants.ORDER_TYPE_RIDING,ServiceConstants.OWNER_TYPE_OPERATOR,null,ServiceConstants.PAY_TYPE_YJ);
callbackService.capitalFlowRecords(order,ServiceConstants.FLOW_TYPE_INCOME,ServiceConstants.ORDER_TYPE_RIDING,
ServiceConstants.OWNER_TYPE_OPERATOR,null,ServiceConstants.PAY_TYPE_YJ,null,null);
return 1;
}
@ -795,7 +800,8 @@ public class EtOrderServiceImpl implements IEtOrderService
if(deductionAmount.compareTo(BigDecimal.ZERO) >= 0){//抵扣金额大于0时增加车损收入
/** 押金抵扣后生成资金流水记录 */
etOrder.setPayFee(deductionAmount);
callbackService.capitalFlowRecords(etOrder,ServiceConstants.FLOW_TYPE_INCOME,ServiceConstants.ORDER_TYPE_VEHICLE_DAMAGE,ServiceConstants.OWNER_TYPE_OPERATOR,null,ServiceConstants.PAY_TYPE_YJ);
callbackService.capitalFlowRecords(etOrder,ServiceConstants.FLOW_TYPE_INCOME,ServiceConstants.ORDER_TYPE_VEHICLE_DAMAGE,
ServiceConstants.OWNER_TYPE_OPERATOR,null,ServiceConstants.PAY_TYPE_YJ,null,null);
}
}else{
log.info("【还车审核通过】当前用户押金已退款!!------不退押金");
@ -1829,13 +1835,6 @@ public class EtOrderServiceImpl implements IEtOrderService
if(ServiceConstants.ORDER_PAY_STATUS_NON_PAYMENT.equals(etOrder1.getPaid())){
throw new ServiceException("订单未支付,不能退款");
}
// 根据分账明细查询
// List<EtCapitalFlow> etCapitalFlows = etCapitalFlowService.selectEtCapitalFlowByOrderNo(etOrder.getOrderNo());
// for (EtCapitalFlow etCapitalFlow : etCapitalFlows) {
// if(etCapitalFlow.getOwnerType().equals("1")){
// etCapitalFlow.
// }
// }
SysDept sysDept = wxPayService.getDeptObjByAreaId(etOrder1.getAreaId());
BigDecimal subtract = sysDept.getBalance().subtract(etOrder1.getTotalFee());
if(subtract.compareTo(BigDecimal.ZERO) <= 0 && sysDept.getSeparateAccount().equals("N")){
@ -1860,16 +1859,20 @@ public class EtOrderServiceImpl implements IEtOrderService
if(ObjectUtil.isNotNull(ridingFee) && !ridingFee.equals(BigDecimal.ZERO)){
refundAmount = refundAmount.add(ridingFee);
}
BigDecimal refundPercentage = refundAmount.divide(etOrder1.getPayFee()).setScale(2, RoundingMode.HALF_UP);// 0.33
// 合伙人退款
BigDecimal totalPartnerDividend = partnerRefund(etOrder, etOrder1, refundPercentage);
log.info("【合伙人退款】:总金额【{}】", totalPartnerDividend);
// 如果已支付并且支付方式是押金则退款的流程是根据押金退款获取押金订单进行退款
if(etOrder1.getPayType().equals(ServiceConstants.PAY_TYPE_YJ) && etOrder1.getPaid().equals(ServiceConstants.ORDER_PAY_STATUS_PAID)){
etOrder1 = getDepositOrder(etOrder1.getUserId());
log.info("【押金抵扣的退款】:【{}】,退款金额:【{}】", etOrder1.getTotalFee(), refundAmount);
etOrder1.setReason(etOrder.getReason());
}
// 新增资金流水记录
// 运营商退款
etOrder1.setPayFee(refundAmount);
callbackService.capitalFlowRecords(etOrder1,ServiceConstants.FLOW_TYPE_DISBURSE,ServiceConstants.ORDER_TYPE_RIDING_REFUND,ServiceConstants.OWNER_TYPE_OPERATOR,null,ServiceConstants.PAY_TYPE_WX);
//todo 更新订单的payFee = totalFee - refundAmount
callbackService.capitalFlowRecords(etOrder1,ServiceConstants.FLOW_TYPE_DISBURSE,ServiceConstants.ORDER_TYPE_RIDING_REFUND,
ServiceConstants.OWNER_TYPE_OPERATOR,null,ServiceConstants.PAY_TYPE_WX,totalPartnerDividend.abs(),refundPercentage);
String outRefundNo = IdUtils.getOrderNo("ref");
/** 2.记录退款表 创建退款对象*/
EtRefund refund1= createRefund(etOrder1, refundAmount, appointmentFee, dispatchFee, manageFee, ridingFee, outRefundNo,ServiceConstants.REFUND_TYPE_SYSTEM);
@ -1882,6 +1885,37 @@ public class EtOrderServiceImpl implements IEtOrderService
return i;
}
/**
* 计算出退款比例 保留两位小数点 比如退款金额为5元 订单金额为32元 退款比例 = 5/32 = 0.16 四舍五入由运营商来平账
* 1. 查询出所有的合伙人的资金流水按退款比例退款
* 2. 新增合伙人的资金流水,余额减少
* */
private BigDecimal partnerRefund(EtOrder etOrder, EtOrder etOrder1, BigDecimal refundPercentage) {
// 统计
EtCapitalFlow etCapitalFlow1 = new EtCapitalFlow();
etCapitalFlow1.setOrderNo(etOrder.getOrderNo());
etCapitalFlow1.setBusType("1");//骑行订单
etCapitalFlow1.setType("1");//收入
etCapitalFlow1.setOwnerType("2");//类型是合伙人
List<EtCapitalFlow> etCapitalFlows = etCapitalFlowService.selectEtCapitalFlowList(etCapitalFlow1);
log.info("【合伙人退款】:查询出的该订单【{}】下的所有资金流水记录【{}】,退款比例是【{}】", etOrder.getOrderNo(),etCapitalFlows, refundPercentage);
BigDecimal totalPartnerDividend = BigDecimal.ZERO; // 用于累计合伙人分红
for (EtCapitalFlow etCapitalFlow : etCapitalFlows) {
BigDecimal userRefundAmount = etCapitalFlow.getAmount().multiply(refundPercentage).setScale(2, RoundingMode.HALF_UP);//用户退款金额 = 0.33 * 1元 = 0.8元
etOrder1.setPayFee(userRefundAmount);
SysUser sysUser = userMapper.selectUserById(etCapitalFlow.getOwnerId());
EtCapitalFlow etCapitalFlow2 = callbackService.capitalFlowRecords(etOrder1, ServiceConstants.FLOW_TYPE_DISBURSE, ServiceConstants.ORDER_TYPE_RIDING_REFUND,
ServiceConstants.OWNER_TYPE_PARTNER, sysUser, ServiceConstants.PAY_TYPE_WX,null,null);
// 累加etCapitalFlow2中的合伙人分红金额
if (etCapitalFlow2.getPartnerDividend() != null) {
totalPartnerDividend = totalPartnerDividend.add(etCapitalFlow2.getPartnerDividend());
}
}
return totalPartnerDividend;
}
/**
* 提现
*/

View File

@ -541,7 +541,7 @@ public class SysDeptServiceImpl implements ISysDeptService
if(ObjectUtil.isNull(sysDept)){
throw new RuntimeException("运营商未绑定app用户,请联系管理员添加【绑定微信用户】");
}
String batchName= sysDept.getDeptName()+"发起提现";
// String batchName= sysDept.getDeptName()+"发起提现";
List<TransferDetailInput> transferDetailInputs = new ArrayList<>();
TransferDetailInput transferDetailInput = new TransferDetailInput();
transferDetailInput.setOutDetailNo(IdUtils.getOrderNo("txd"));//明细订单号

View File

@ -3,6 +3,9 @@ package com.ruoyi.system.service.impl;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.aliyuncs.dysmsapi.model.v20170525.SendSmsResponse;
import com.aliyuncs.exceptions.ClientException;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.ruoyi.common.annotation.DataScope;
import com.ruoyi.common.constant.CacheConstants;
@ -15,18 +18,23 @@ import com.ruoyi.common.core.domain.model.LoginUser;
import com.ruoyi.common.core.redis.RedisCache;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.common.utils.SendAliSmsUtil;
import com.ruoyi.common.utils.SendSmsVo;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.bean.BeanValidators;
import com.ruoyi.common.utils.spring.SpringUtils;
import com.ruoyi.common.utils.uuid.IdUtils;
import com.ruoyi.system.domain.*;
import com.ruoyi.system.mapper.*;
import com.ruoyi.system.service.*;
import com.wechat.pay.java.service.profitsharing.model.AddReceiverResponse;
import com.wechat.pay.java.service.profitsharing.model.DeleteReceiverResponse;
import com.wechat.pay.java.service.transferbatch.model.TransferDetailInput;
import org.apache.commons.lang3.ObjectUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.core.token.TokenService;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@ -34,8 +42,11 @@ import org.springframework.util.CollectionUtils;
import javax.annotation.Resource;
import javax.validation.Validator;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
/**
@ -90,6 +101,30 @@ public class SysUserServiceImpl implements ISysUserService
@Resource
private AsUserMapper asUserMapper;
@Autowired
private CallbackService callbackService;
@Autowired
private ScheduledExecutorService scheduledExecutorService;
@Value("${aliyun.accessKeyId}")
private String accessKeyId;
@Value("${aliyun.accessKeySecret}")
private String accessKeySecret;
@Value("${aliyun.signName}")
private String signName;
@Value("${aliyun.templateCode3}")
private String templateCode3;
@Value("${aliyun.phone}")
private String phone;
@Resource
private EtMsgLogMapper etMsgLogMapper;
/**
* 根据条件分页查询用户列表
@ -725,4 +760,64 @@ public class SysUserServiceImpl implements ISysUserService
public int bandAppUser(SysUser user) {
return userMapper.updateUser(user);
}
/**
* 合伙人提现
* 1. 获取当前用户
* 2. 发短信
* 3. 记录资金流水
*/
@Override
public int adminWithdraw(BigDecimal amount, SysUser sysUser) {
String orderNo = IdUtils.getOrderNo("tx");
log.info("【合伙人提现】获取到合伙人信息:【{}】", JSON.toJSON(sysUser));
EtOrder order = new EtOrder();
order.setOrderNo(orderNo);
order.setPayFee(amount);
order.setTotalFee(amount);
order.setAreaId(sysUser.getAreaId());
// 发短信
asynchronousMsg(sysUser.getUserName());
//记录资金流水
EtCapitalFlow etCapitalFlow = callbackService.capitalFlowRecords(order, ServiceConstants.FLOW_TYPE_DISBURSE, ServiceConstants.ORDER_TYPE_WITHDRAW,
ServiceConstants.OWNER_TYPE_PARTNER, sysUser, ServiceConstants.PAY_TYPE_WX, null, null);
log.info("【合伙人提现】记录资金流水成功========{}", JSON.toJSONString(etCapitalFlow));
return 1;
}
private void asynchronousMsg(String userName) {
scheduledExecutorService.schedule(() -> {
/** 提现申请发送一个短信给丁建帮*/
JSONObject jsonObject = new JSONObject();
jsonObject.put("name", userName);
SendSmsVo sendSmsVo = new SendSmsVo();
sendSmsVo.setMobile(phone);
sendSmsVo.setTemplateCode(templateCode3);
sendSmsVo.setParam(jsonObject.toJSONString());
sendSmsVo.setSignName(signName);
SendSmsResponse response = null;
log.info("【提现申请】向阿里云发送短信,请求,----------【{}】", JSON.toJSONString(sendSmsVo));
try {
response = SendAliSmsUtil.sendVerifyCode(accessKeyId,accessKeySecret,sendSmsVo);
} catch (ClientException e) {
e.printStackTrace();
}
log.info("【提现申请】发送阿里云短信成功,返回----------【{}】",JSON.toJSONString(response));
// 短信日志
EtMsgLog etMsgLog = new EtMsgLog();
etMsgLog.setPhone(phone);
etMsgLog.setContent("用户"+userName+",发起押金提现申请,请尽快审核!");
etMsgLog.setType("2");
etMsgLog.setSignName(signName);
etMsgLog.setTemplateCode(templateCode3);
int i = etMsgLogMapper.insertEtMsgLog(etMsgLog);
if(i>0){
log.info("【提现申请】短信日志记录成功");
}else{
log.info("【提现申请】短信日志记录失败");
}
}, 0 , TimeUnit.HOURS);
}
}

View File

@ -30,6 +30,8 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<result property="cooperationTime" column="cooperation_time" />
<result property="dividendStatus" column="dividend_status" />
<result property="balance" column="balance" />
<result property="userType" column="user_type" />
<result property="collectionCode" column="collection_code" />
<association property="dept" javaType="SysDept" resultMap="deptResult" />
<collection property="roles" javaType="java.util.List" resultMap="RoleResult" />
</resultMap>
@ -55,7 +57,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<sql id="selectUserVo">
select u.user_id, u.dept_id, u.user_name, u.nick_name, u.email, u.avatar, u.phonenumber, u.password, u.sex, u.status, u.del_flag, u.login_ip, u.login_date, u.create_by, u.create_time, u.remark,u.area_id,u.dividend_proportion,u.dividend_item,u.app_user_id, u.cooperation_time,u.dividend_status,u.balance,
d.dept_id, d.parent_id, d.ancestors, d.dept_name, d.order_num, d.leader, d.status as dept_status,
d.dept_id, d.parent_id, d.ancestors, d.dept_name, d.order_num, d.leader, d.status as dept_status,u.user_type,u.collection_code,
r.role_id, r.role_name, r.role_key, r.role_sort, r.data_scope, r.status as role_status,a.area_name areaName
from sys_user u
left join sys_dept d on u.dept_id = d.dept_id
@ -98,6 +100,12 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<if test="deptId != null and deptId != 0">
AND (u.dept_id = #{deptId} OR u.dept_id IN ( SELECT t.dept_id FROM sys_dept t WHERE find_in_set(#{deptId}, ancestors) ))
</if>
<if test="typeList != null and typeList !=''">
AND u.user_type IN
<foreach item="item" index="index" collection="typeList" open="(" separator="," close=")">
#{item}
</foreach>
</if>
<!-- 数据范围过滤 -->
${params.dataScope}
</select>
@ -228,6 +236,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<if test="appUserId != null">app_user_id = #{appUserId},</if>
<if test="cooperationTime != null">cooperation_time = #{cooperationTime},</if>
<if test="dividendStatus != null">dividend_status = #{dividendStatus},</if>
<if test="collectionCode != null">collection_code = #{collectionCode},</if>
update_time = sysdate()
</set>
where user_id = #{userId}