diff --git a/electripper-admin/src/main/java/com/ruoyi/web/controller/app/AppVerifyController.java b/electripper-admin/src/main/java/com/ruoyi/web/controller/app/AppVerifyController.java index 4f7cae4..e0ba016 100644 --- a/electripper-admin/src/main/java/com/ruoyi/web/controller/app/AppVerifyController.java +++ b/electripper-admin/src/main/java/com/ruoyi/web/controller/app/AppVerifyController.java @@ -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); diff --git a/electripper-admin/src/main/java/com/ruoyi/web/controller/system/EtCapitalFlowController.java b/electripper-admin/src/main/java/com/ruoyi/web/controller/system/EtCapitalFlowController.java index 4483bdc..d600ed2 100644 --- a/electripper-admin/src/main/java/com/ruoyi/web/controller/system/EtCapitalFlowController.java +++ b/electripper-admin/src/main/java/com/ruoyi/web/controller/system/EtCapitalFlowController.java @@ -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(); diff --git a/electripper-common/src/main/java/com/ruoyi/common/core/domain/entity/SysUser.java b/electripper-common/src/main/java/com/ruoyi/common/core/domain/entity/SysUser.java index 1ca3357..b339f40 100644 --- a/electripper-common/src/main/java/com/ruoyi/common/core/domain/entity/SysUser.java +++ b/electripper-common/src/main/java/com/ruoyi/common/core/domain/entity/SysUser.java @@ -138,6 +138,71 @@ public class SysUser extends BaseEntity /** 角色对象 */ private List 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 getUsers() { return users; } diff --git a/electripper-system/src/main/java/com/ruoyi/system/service/CallbackService.java b/electripper-system/src/main/java/com/ruoyi/system/service/CallbackService.java index ea8da35..92239a9 100644 --- a/electripper-system/src/main/java/com/ruoyi/system/service/CallbackService.java +++ b/electripper-system/src/main/java/com/ruoyi/system/service/CallbackService.java @@ -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); } diff --git a/electripper-system/src/main/java/com/ruoyi/system/service/ISysUserService.java b/electripper-system/src/main/java/com/ruoyi/system/service/ISysUserService.java index da2fcc0..e864c55 100644 --- a/electripper-system/src/main/java/com/ruoyi/system/service/ISysUserService.java +++ b/electripper-system/src/main/java/com/ruoyi/system/service/ISysUserService.java @@ -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); } diff --git a/electripper-system/src/main/java/com/ruoyi/system/service/impl/CallbackServiceImpl.java b/electripper-system/src/main/java/com/ruoyi/system/service/impl/CallbackServiceImpl.java index 1201b0c..cbc4560 100644 --- a/electripper-system/src/main/java/com/ruoyi/system/service/impl/CallbackServiceImpl.java +++ b/electripper-system/src/main/java/com/ruoyi/system/service/impl/CallbackServiceImpl.java @@ -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 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 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 areaId1 = etAreaDeptMapper.selectList(new QueryWrapper().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 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 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; + } + /** * 资金流水记录 * */ diff --git a/electripper-system/src/main/java/com/ruoyi/system/service/impl/EtOrderServiceImpl.java b/electripper-system/src/main/java/com/ruoyi/system/service/impl/EtOrderServiceImpl.java index fa50a2e..526f36b 100644 --- a/electripper-system/src/main/java/com/ruoyi/system/service/impl/EtOrderServiceImpl.java +++ b/electripper-system/src/main/java/com/ruoyi/system/service/impl/EtOrderServiceImpl.java @@ -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 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 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; + } + /** * 提现 */ diff --git a/electripper-system/src/main/java/com/ruoyi/system/service/impl/SysDeptServiceImpl.java b/electripper-system/src/main/java/com/ruoyi/system/service/impl/SysDeptServiceImpl.java index 88cec42..922740c 100644 --- a/electripper-system/src/main/java/com/ruoyi/system/service/impl/SysDeptServiceImpl.java +++ b/electripper-system/src/main/java/com/ruoyi/system/service/impl/SysDeptServiceImpl.java @@ -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 transferDetailInputs = new ArrayList<>(); TransferDetailInput transferDetailInput = new TransferDetailInput(); transferDetailInput.setOutDetailNo(IdUtils.getOrderNo("txd"));//明细订单号 diff --git a/electripper-system/src/main/java/com/ruoyi/system/service/impl/SysUserServiceImpl.java b/electripper-system/src/main/java/com/ruoyi/system/service/impl/SysUserServiceImpl.java index 45125ec..e9eec54 100644 --- a/electripper-system/src/main/java/com/ruoyi/system/service/impl/SysUserServiceImpl.java +++ b/electripper-system/src/main/java/com/ruoyi/system/service/impl/SysUserServiceImpl.java @@ -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); + } } diff --git a/electripper-system/src/main/resources/mapper/system/SysUserMapper.xml b/electripper-system/src/main/resources/mapper/system/SysUserMapper.xml index 61f9f51..203168d 100644 --- a/electripper-system/src/main/resources/mapper/system/SysUserMapper.xml +++ b/electripper-system/src/main/resources/mapper/system/SysUserMapper.xml @@ -30,6 +30,8 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" + + @@ -55,7 +57,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" 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" AND (u.dept_id = #{deptId} OR u.dept_id IN ( SELECT t.dept_id FROM sys_dept t WHERE find_in_set(#{deptId}, ancestors) )) + + AND u.user_type IN + + #{item} + + ${params.dataScope} @@ -228,6 +236,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" app_user_id = #{appUserId}, cooperation_time = #{cooperationTime}, dividend_status = #{dividendStatus}, + collection_code = #{collectionCode}, update_time = sysdate() where user_id = #{userId}