36. 尚融宝放款

编程入门 行业动态 更新时间:2024-10-24 05:22:41

36. <a href=https://www.elefans.com/category/jswz/34/1693685.html style=尚融宝放款"/>

36. 尚融宝放款

后台放款

需求

管理员在后台对标的进行放款


相关数据库表

还款人还款记录:lend_return

投资人回款记录:lend_item_return

参考文档

参考《汇付宝商户账户技术文档》3.11满标放款

后端

controller

AdminLendController.java

    @ApiOperation("放款")@GetMapping("/makeLoan/{id}")public R makeLoan(@ApiParam(value = "标的id",required = true)@PathVariable Long id){lendService.makeLoan(id);return R.ok().setMessage("放款成功");}

service

LendService.java

    void makeLoan(Long id);

LendServiceImpl.java

    @Resourceprivate UserAccountMapper userAccountMapper;@Resourceprivate UserBindService userBindService;@Resourceprivate TransFlowService transFlowService;@Resourceprivate LendItemService lendItemService;@Override@Transactional(rollbackFor = Exception.class)public void makeLoan(Long id) {Lend lend = baseMapper.selectById(id);String agentBillNo = LendNoUtils.getLoanNo();Map<String, Object> map = new HashMap<>();map.put("agentId", HfbConst.AGENT_ID);map.put("agentProjectCode", lend.getLendNo());map.put("agentBillNo", agentBillNo);BigDecimal monthRate = lend.getServiceRate().divide(new BigDecimal(12), 8, BigDecimal.ROUND_DOWN);// 平台实际收益:已投金额 * 平台月化率 * 投资时长BigDecimal realAmount = lend.getInvestAmount().multiply(monthRate).multiply(new BigDecimal(lend.getPeriod()));map.put("mchFee", realAmount);    map.put("timestamp", RequestHelper.getTimestamp());map.put("sign", RequestHelper.getSign(map));// 放款是一个同步接口,如果放款返回成功,那么我们要处理平台业务JSONObject result = RequestHelper.sendRequest(map, HfbConst.MAKE_LOAN_URL);BigDecimal voteAmt = result.getBigDecimal("voteAmt");   // 投资金额if (!"0000".equals(result.get("resultCode"))) {throw new BusinessException(result.getString("resultMsg"));}// 1、更新标的:平台实际收益、状态、支付时间lend.setRealAmount(realAmount);lend.setStatus(LendStatusEnum.PAY_RUN.getStatus());lend.setPaymentTime(LocalDateTime.now());baseMapper.updateById(lend);// 2、更新借款人账户String benefitBindCode = userBindService.getBindCodeByUserId(lend.getUserId());userAccountMapper.updateAccount(benefitBindCode, voteAmt, new BigDecimal(0));// 3、添加交易流水TransFlowBO transFlowBO = new TransFlowBO(agentBillNo,benefitBindCode,TransTypeEnum.BORROW_BACK,voteAmt,"放款到账,项目编号:" + lend.getLendNo());transFlowService.saveTransFlow(transFlowBO);// 4、解冻并扣除投资人资金List<LendItem> lendItemList = lendItemService.listByIdAndStatus(lend.getId(), LendItemEnum.PAY_OK.getStatus());lendItemList.forEach(lendItem -> {String voteBindCode = userBindService.getBindCodeByUserId(lendItem.getInvestUserId());userAccountMapper.updateAccount(voteBindCode, new BigDecimal(0), lendItem.getInvestAmount().negate());// 5、增加投资人交易流水TransFlowBO investTransFlow = new TransFlowBO(LendNoUtils.getLendNo(),voteBindCode,TransTypeEnum.INVEST_UNLOCK,lendItem.getInvestAmount(),"冻结资金转出放款,项目编号:" + lend.getLendNo() + "项目名称:" + lend.getTitle());transFlowService.saveTransFlow(investTransFlow);});// 6、生成借款人还款计划、投资人回款计划repaymentPlan(lend);}       
    @Resourceprivate LendReturnService lendReturnService;/*** 生成借款人还款计划	*      * @param lend 标的*/private void repaymentPlan(Lend lend) {// 一、创建还款计划列表List<LendReturn> lendReturnList = new ArrayList<>();// 根据标的还款期限(period)生成还款计划// 你借多少期,我就给你生成多少条还款计划int period = lend.getPeriod().intValue();// 遍历还款期限,从第1期开始for (int i = 1; i <= period; i++) {// 创建还款计划LendReturn lendReturn = new LendReturn();// 填充属性lendReturn.setLendId(lend.getId());lendReturn.setBorrowInfoId(lend.getBorrowInfoId());lendReturn.setReturnNo(LendNoUtils.getReturnNo());lendReturn.setUserId(lend.getUserId());lendReturn.setAmount(lend.getAmount());lendReturn.setBaseAmount(lend.getInvestAmount());// 计算利息所需要用到的本金:根据已投金额,得出利息lendReturn.setCurrentPeriod(i);lendReturn.setLendYearRate(lend.getLendYearRate());lendReturn.setReturnMethod(lend.getReturnMethod());lendReturn.setFee(BigDecimal.ZERO);lendReturn.setReturnDate(lend.getLendStartDate().plusMonths(i)); // 开始日期往后i个月开始还款lendReturn.setOverdue(false);   // 不逾期lendReturn.setLast(i == period);    // 是否为最后一期lendReturn.setStatus(0);    // 设置还款状态lendReturnList.add(lendReturn); // 将还款计划加入还款计划列表}// 批量保存还款计划lendReturnService.saveBatch(lendReturnList);// 将还款计划列表的还款期数、还款计划id提取出来,转换成一个还款计划mapMap<Integer, Long> lendReturnMap = lendReturnList.stream().collect(Collectors.toMap(LendReturn::getCurrentPeriod, LendReturn::getId));// ------------------------------------------------------------------// ---------------------------获取回款计划----------------------------// ------------------------------------------------------------------// 创建当前标的下所有投资人的回款计划列表List<LendItemReturn> lendItemReturnAllList = new ArrayList<>();// 获取当前标的下所有已支付的投资记录List<LendItem> lendItemList = lendItemService.listByIdAndStatus(lend.getId(), LendItemEnum.PAY_OK.getStatus());// 遍历投资记录for (LendItem lendItem : lendItemList) {// 三、根据投资记录、还款计划map、标的,当前投资记录的所有回款计划List<LendItemReturn> lendItemReturnList = this.returnInvest(lendItem, lendReturnMap, lend);// 将每个投资记录的回款计划添加至回款计划列表中lendItemReturnAllList.addAll(lendItemReturnList);}// 四、遍历还款计划列表for (LendReturn lendReturn : lendReturnList) {// 计算总利息、总本金、总本息// 把回款计划中同一期所有的利息/本金/本息加起来// 计算出总利息、总本金、总本息BigDecimal principal = lendItemReturnAllList.stream().filter(item -> item.getLendReturnId().longValue() == lendReturn.getId().longValue()).map(LendItemReturn::getPrincipal).reduce(BigDecimal.ZERO, BigDecimal::add);BigDecimal interest = lendItemReturnAllList.stream().filter(item -> item.getLendReturnId().longValue() == lendReturn.getId().longValue()).map(LendItemReturn::getInterest).reduce(BigDecimal.ZERO, BigDecimal::add);BigDecimal total = lendItemReturnAllList.stream().filter(item -> item.getLendReturnId().longValue() == lendReturn.getId().longValue()).map(LendItemReturn::getTotal).reduce(BigDecimal.ZERO, BigDecimal::add);lendReturn.setPrincipal(principal);lendReturn.setInterest(interest);lendReturn.setTotal(total);}// 批量更新lendReturnService.updateBatchById(lendReturnList);}
    @Resourceprivate LendItemReturnService lendItemReturnService;/*** 投资人还款计划** @param lend* @param lendReturnMap* @param lendItem* @return*/private List<LendItemReturn> returnInvest(LendItem lendItem, Map<Integer, Long> lendReturnMap, Lend lend) {// 投资金额BigDecimal investAmount = lendItem.getInvestAmount();// 年化利率BigDecimal lendYearRate = lendItem.getLendYearRate();// 投资期数Integer period = lend.getPeriod();// 创建还款期数、利息的mapMap<Integer, BigDecimal> mapInterest;// 创建还款期数、本金的mapMap<Integer, BigDecimal> mapPrincipal;// 二、根据还款方式计算本金和利息switch (ReturnMethodEnum.getByValue(lend.getReturnMethod().intValue())) {case ONE:mapInterest = Amount1Helper.getPerMonthInterest(investAmount, lendYearRate, period);mapPrincipal = Amount1Helper.getPerMonthPrincipal(investAmount, lendYearRate, period);break;case TWO:mapInterest = Amount2Helper.getPerMonthInterest(investAmount, lendYearRate, period);mapPrincipal = Amount2Helper.getPerMonthPrincipal(investAmount, lendYearRate, period);break;case THREE:mapInterest = Amount3Helper.getPerMonthInterest(investAmount, lendYearRate, period);mapPrincipal = Amount3Helper.getPerMonthPrincipal(investAmount, lendYearRate, period);break;default:mapInterest = Amount4Helper.getPerMonthInterest(investAmount, lendYearRate, period);mapPrincipal = Amount4Helper.getPerMonthPrincipal(investAmount, lendYearRate, period);break;}// 创建回款计划列表List<LendItemReturn> lendItemReturnList = new ArrayList<>();// 遍历还款期数、利息mapfor (Entry<Integer, BigDecimal> entry : mapInterest.entrySet()) {Integer currentPeriod = entry.getKey();    // 当前期数// 通过当前期数获取到还款计划的idLong lendReturnId = lendReturnMap.get(currentPeriod);// 创建回款计划LendItemReturn lendItemReturn = new LendItemReturn();// 填充数据lendItemReturn.setLendReturnId(lendReturnId);lendItemReturn.setLendItemId(lendItem.getId());lendItemReturn.setLendId(lendItem.getLendId());lendItemReturn.setInvestUserId(lendItem.getInvestUserId());lendItemReturn.setInvestAmount(lendItem.getInvestAmount());lendItemReturn.setCurrentPeriod(currentPeriod);lendItemReturn.setLendYearRate(lend.getLendYearRate());lendItemReturn.setReturnMethod(lend.getReturnMethod());// filter做过滤 map取属性 reduce做处理if (currentPeriod.intValue() == lend.getPeriod().intValue()) {// 最后一期// 前几期要还的本金之和BigDecimal sumPrincipal = lendItemReturnList.stream().map(LendItemReturn::getPrincipal).reduce(BigDecimal.ZERO, BigDecimal::add);// 最后一次还款本金 = 投资人的总投资 - 前几次还款金额之和// 因为数据库只保留两位,所以此处需要四舍五入进位// 否则会导致还款计划精度不一致的问题BigDecimal lastPrincipal = lendItem.getInvestAmount().subtract(sumPrincipal);lendItemReturn.setPrincipal(lastPrincipal.setScale(2, BigDecimal.ROUND_HALF_UP));// 前几期要还的利息之和BigDecimal sumInterest = lendItemReturnList.stream().map(LendItemReturn::getInterest).reduce(BigDecimal.ZERO, BigDecimal::add);// 最后一次还款利息 = 投资人的预期收益 - 前几次还款利息之和BigDecimal lastInterest = lendItem.getExpectAmount().subtract(sumInterest);lendItemReturn.setInterest(lastInterest.setScale(2, BigDecimal.ROUND_HALF_UP));} else {// 非最后一期,直接从map中获取对应当前期数的本金/利息lendItemReturn.setPrincipal(mapPrincipal.get(currentPeriod).setScale(2, BigDecimal.ROUND_HALF_UP));lendItemReturn.setInterest(mapInterest.get(currentPeriod).setScale(2, BigDecimal.ROUND_HALF_UP));}// 回款总金额lendItemReturn.setTotal(lendItemReturn.getPrincipal().add(lendItemReturn.getInterest()));// 设置其他属性lendItemReturn.setFee(BigDecimal.ZERO);lendItemReturn.setReturnDate(lend.getLendStartDate().plusMonths(currentPeriod));lendItemReturn.setOverdue(false);lendItemReturn.setStatus(0);// 添加到回款计划列表中lendItemReturnList.add(lendItemReturn);}// 批量保存lendItemReturnService.saveBatch(lendItemReturnList);// 返回回款计划列表return lendItemReturnList;}

LendItemService

LendItemService.java

    // 根据标的id和状态获取投资人列表List<LendItem> listByIdAndStatus(Long lendId, Integer status)

LendItemServiceImpl.java

    @Overridepublic List<LendItem> listByIdAndStatus(Long lendId, Integer status) {QueryWrapper<LendItem> queryWrapper = new QueryWrapper<>();queryWrapper.eq("lend_id",lendId).eq("status",status);return baseMapper.selectList(queryWrapper);}

前端

api

创建 src/api/core/lend.js

  makeLoan(id) {return request({url: `/admin/core/lend/makeLoan/${id}`,method: 'get'})}

script

src/views/core/lend/list.vue

methods:

    makeLoan(id) {this.$confirm('确定放款吗?', '提示', {confirmButtonText: '确定',cancelButtonText: '取消',type: 'warning'}).then(() => {return lendApi.makeLoan(id)}).then(response => {//放款成功则重新获取数据列表this.fetchData()this.$message({type: 'success',message: response.message})}).catch(error => {console.log('取消', error)if (error === 'cancel') {this.$message({type: 'info',message: '已取消放款'})}})}

测试各个表的变化

还款方式为等额本息,借3个月,标的金额为95000,实际募集2000,有两个人分别投资了1000元

测试时,注意多个表之间的数据关系,尤其是汇付宝的数据,一旦测试失败,需要重新投资的话,需要清空user_invest表。

尚融宝

lend

标的表

user_account

账户表

trans_flow

流水表

lend_return

还款计划表

lend_item_return

回款计划表

汇付宝

user_account

账户表

更多推荐

36. 尚融宝放款

本文发布于:2024-02-17 10:22:47,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1693684.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:尚融宝

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!