ylb-接口14购买理财产品

news/2025/3/19 20:15:29/

总览:
在这里插入图片描述
在api模块service包,Invest类下添加(投资理财产品, int 是投资的结果 , 1 投资成功):

package com.bjpowernode.api.service;import com.bjpowernode.api.pojo.BidInfoProduct;import java.math.BigDecimal;
import java.util.List;public interface InvestService {/** 查询某个产品的投资记录 */List<BidInfoProduct> queryBidListByProductId(Integer productId,Integer pageNo,Integer pageSize);/*投资理财产品, int 是投资的结果 , 1 投资成功*/int investProduct(Integer uid, Integer productId, BigDecimal money);
}

实现这个接口方法,在dataservice模块service包下,补充InvestServiceImpl,(投资理财产品, int 是投资的结果 , 1 投资成功):
1、参数检查(用户ID是否存在,产品ID是否存在,金钱是否存在且购买金额大于100和100整数倍)
2、查询账号金额(accountMapper.selectByUidForUpdate(uid)),比较资金(ge),是否满足购买要求
3、检查产品是否可以购买(产品不能为空且还有卖;比较ge:产品剩余可投资总金额大于要投的钱,要投的钱在最小和最大一个人可以投资金额之间)
4、可以购买了,扣除账号资金(更新资金accountMapper.updateAvailableMoneyByInvest(uid, money))
5、扣除产品剩余可投资金额(productInfoMapper.updateLeftProductMoney(productId, money))
6、创建投资记录(bidInfoMapper.insertSelective(bidInfo))
7、判断产品是否卖完(判断产品剩余可卖金额是否为0),更新产品是满标状态(productInfoMapper.updateSelled(productId))

package com.bjpowernode.dataservice.service;import com.bjpowernode.api.model.BidInfo;
import com.bjpowernode.api.model.FinanceAccount;
import com.bjpowernode.api.model.ProductInfo;
import com.bjpowernode.api.pojo.BidInfoProduct;
import com.bjpowernode.api.service.InvestService;
import com.bjpowernode.common.constants.YLBConstant;
import com.bjpowernode.common.util.CommonUtil;
import com.bjpowernode.dataservice.mapper.BidInfoMapper;
import com.bjpowernode.dataservice.mapper.FinanceAccountMapper;
import com.bjpowernode.dataservice.mapper.ProductInfoMapper;
import org.apache.dubbo.config.annotation.DubboService;
import org.springframework.transaction.annotation.Transactional;import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;@DubboService(interfaceClass = InvestService.class, version = "1.0")
public class InvestServiceImpl implements InvestService {@Resourceprivate BidInfoMapper bidInfoMapper;@Resourceprivate FinanceAccountMapper accountMapper;@Resourceprivate ProductInfoMapper productInfoMapper;/*** 查询某个产品的投资记录*/@Overridepublic List<BidInfoProduct> queryBidListByProductId(Integer productId,Integer pageNo,Integer pageSize) {List<BidInfoProduct> bidList = new ArrayList<>();if (productId != null && productId > 0) {pageNo = CommonUtil.defaultPageNo(pageNo);pageSize = CommonUtil.defaultPageSize(pageSize);int offset = (pageNo - 1) * pageSize;bidList = bidInfoMapper.selectByProductId(productId, offset, pageSize);}return bidList;}/*投资理财产品, int 是投资的结果 , 1 投资成功*/@Transactional(rollbackFor = Exception.class)@Overridepublic int investProduct(Integer uid, Integer productId, BigDecimal money) {int result = 0;//默认,参数不正确int rows = 0;//1参数检查if ((uid != null && uid > 0) && (productId != null && productId > 0)&& (money != null && money.intValue() % 100 == 0 && money.intValue() >= 100)) {//2.查询账号金额FinanceAccount account = accountMapper.selectByUidForUpdate(uid);if (account != null) {if (CommonUtil.ge(account.getAvailableMoney(), money)) {//资金满足购买要求//3.检查产品是否可以购买ProductInfo productInfo = productInfoMapper.selectByPrimaryKey(productId);if (productInfo != null&& productInfo.getProductStatus() == YLBConstant.PRODUCT_STATUS_SELLING) {if (CommonUtil.ge(productInfo.getLeftProductMoney(), money) &&CommonUtil.ge(money, productInfo.getBidMinLimit()) &&CommonUtil.ge(productInfo.getBidMaxLimit(), money)) {//可以购买了 4. 扣除账号资金rows = accountMapper.updateAvailableMoneyByInvest(uid, money);if (rows < 1) {throw new RuntimeException("投资更新账号资金失败");}//5.扣除产品剩余可投资金额rows = productInfoMapper.updateLeftProductMoney(productId, money);if (rows < 1) {throw new RuntimeException("投资更新产品剩余金额失败");}//6.创建投资记录BidInfo bidInfo = new BidInfo();bidInfo.setBidMoney(money);bidInfo.setBidStatus(YLBConstant.INVEST_STATUS_SUCC);bidInfo.setBidTime(new Date());bidInfo.setProdId(productId);bidInfo.setUid(uid);bidInfoMapper.insertSelective(bidInfo);//7.判断产品是否卖完,更新产品是满标状态ProductInfo dbProductInfo = productInfoMapper.selectByPrimaryKey(productId);if( dbProductInfo.getLeftProductMoney().compareTo(new BigDecimal("0")) == 0 ){rows  = productInfoMapper.updateSelled(productId);if( rows < 1 ){throw new RuntimeException("投资更新产品满标失败");}}//8.最后这是投资成功result = 1;}} else {result = 4;//理财产品不存在}} else {result = 3;//资金不足}} else {result = 2;//资金账号不存在}}return result;}
}

其中:
1、给uid的记录上锁(需要在dataservice模块mapper包下的FinanceAccountMapper接口添加方法,并在resources/mappers/FinanceAccountMapper.xml编写SQL语句):

    /*给uid的记录上锁*/FinanceAccount selectByUidForUpdate(@Param("uid") Integer uid);
  <!--/*给uid的记录上锁*/--><select id="selectByUidForUpdate" resultMap="BaseResultMap">select <include refid="Base_Column_List" />from u_finance_accountwhere uid = #{uid}for update</select>

2、在common模块util包下,CommonUtil类添加一个方法比较金额(比较BigDecimal:ge),是否可以购买:

package com.bjpowernode.common.util;import java.math.BigDecimal;
import java.util.regex.Pattern;public class CommonUtil {/*处理pageNo*/public static int defaultPageNo(Integer pageNo) {int pNo = pageNo;if (pageNo == null || pageNo < 1) {pNo = 1;}return pNo;}/*处理pageSize*/public static int defaultPageSize(Integer pageSize) {int pSize = pageSize;if (pageSize == null || pageSize < 1) {pSize = 1;}return pSize;}/*手机号脱敏*/public static String tuoMinPhone(String phone) {String result = "***********";if (phone != null && phone.trim().length() == 11) {result = phone.substring(0,3) + "******" + phone.substring(9,11);}return result;}/*手机号格式 true:格式正确;false不正确*/public static boolean checkPhone(String phone){boolean flag = false;if( phone != null && phone.length() == 11 ){//^1[1-9]\\d{9}$flag = Pattern.matches("^1[1-9]\\d{9}$",phone);}return flag;}/*比较BigDecimal  n1 >=n2 :true ,false*/public static boolean ge(BigDecimal n1, BigDecimal n2){if( n1 == null || n2 == null){throw new RuntimeException("参数BigDecimal是null");}return  n1.compareTo(n2) >= 0;}
}

3、更新资金(需要在dataservice模块mapper包下的FinanceAccountMapper接口添加方法,并在resources/mappers/FinanceAccountMapper.xml编写SQL语句):

    /*更新资金*/int updateAvailableMoneyByInvest(@Param("uid") Integer uid, @Param("money") BigDecimal money);
  <!--更新资金--><update id="updateAvailableMoneyByInvest">update   u_finance_account set available_money = available_money - #{money}where uid = #{uid} and ( available_money - #{money} >=0 )</update>

4、扣除产品剩余可投资金额(需要在dataservice模块mapper包下的ProductInfoMapper接口添加方法,并在resources/mappers/ProductInfoMapper.xml编写SQL语句):

    /*扣除产品剩余可投资金额*/int updateLeftProductMoney(@Param("id") Integer productId, @Param("money") BigDecimal money);
  <!--扣除产品剩余可投资金额--><update id="updateLeftProductMoney">update b_product_info set left_product_money = left_product_money - #{money}where id = #{id} and ( left_product_money - #{money} >=0 )</update>

5、更新产品为满标(需要在dataservice模块mapper包下的ProductInfoMapper接口添加方法,并在resources/mappers/ProductInfoMapper.xml编写SQL语句):

    /*更新产品为满标*/int updateSelled(@Param("id") Integer productId);
  <!--*更新产品为满标--><update id="updateSelled">update  b_product_info set product_status = 1 ,  product_full_time = now()where id = #{id}</update>

在web模块controller包,InvestController类下添加(购买理财产品, 更新投资排行榜):
1、检查基本参数(用户ID是否存在,产品ID是否存在,金钱是否存在且购买金额大于100和100整数倍)
2、根据investResult结果判断
3、更新投资排行榜(modifyInvestRank(uid,money))

package com.bjpowernode.front.controller;import com.bjpowernode.api.model.User;
import com.bjpowernode.common.constants.RedisKey;
import com.bjpowernode.common.util.CommonUtil;
import com.bjpowernode.front.view.RespResult;
import com.bjpowernode.front.view.invest.RankView;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.ZSetOperations;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.web.bind.annotation.*;import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;/*** 有关投资功能*/@Api(tags = "投资理财产品")
@RestController
public class InvestController extends BaseController {/*投资排行榜*/@ApiOperation(value = "投资排行榜", notes = "显式投资金额最高的3位用户信息")@GetMapping("/v1/invest/rank")public RespResult showInvestRank() {//从redis查询数据Set<ZSetOperations.TypedTuple<String>> sets = stringRedisTemplate.boundZSetOps(RedisKey.KEY_INVEST_RANK).reverseRangeWithScores(0, 2);List<RankView> rankList = new ArrayList<>();//遍历set集合sets.forEach(tuple -> {//tuple.getValue();//手机号//tuple.getScore();//投资金额rankList.add(new RankView(CommonUtil.tuoMinPhone(tuple.getValue()), tuple.getScore()));});RespResult result = RespResult.ok();result.setList(rankList);return result;}/*购买理财产品, 更新投资排行榜*/@ApiOperation(value = "投资理财产品")@PostMapping("/v1/invest/product")public RespResult investProduct(@RequestHeader("uid") Integer uid,@RequestParam("productId") Integer productId,@RequestParam("money") BigDecimal money){RespResult result = RespResult.fail();//1.检查基本参数if( (uid != null && uid > 0) && (productId != null && productId > 0)&&( money != null && money.intValue() % 100 == 0 && money.intValue() >= 100)){int investResult = investService.investProduct(uid,productId,money);switch (investResult){case 0:result.setMsg("投资数据不正确");break;case 1:result = RespResult.ok();modifyInvestRank(uid,money);break;case 2:result.setMsg("资金账号不存在");break;case 3:result.setMsg("资金不足");break;case 4:result.setMsg("理财产品不存在");break;}}return result;}/*更新投资排行榜*/private void modifyInvestRank(Integer uid,BigDecimal money){User user  = userService.queryById(uid);if(user != null){//更新redis中的投资排行榜String key = RedisKey.KEY_INVEST_RANK;stringRedisTemplate.boundZSetOps(key).incrementScore(user.getPhone(),money.doubleValue());}}
}

其中:
1、在web模块controller包,InvestController内添加一个方法,更新redis中的投资排行榜(更新投资排行榜modifyInvestRank):
2、在api模块service包,UserService添加查询用户方法(userService.queryById(uid))

package com.bjpowernode.api.service;import com.bjpowernode.api.model.User;
import com.bjpowernode.api.pojo.UserAccountInfo;public interface UserService {/*** 根据手机号查询数据*/User queryByPhone(String phone);/*用户注册*/int userRegister(String phone, String password);/*登录*/User userLogin(String phone, String pword);/*更新实名认证信息*/boolean modifyRealname(String phone, String name, String idCard);/*获取用户和资金信息*/UserAccountInfo queryUserAllInfo(Integer uid);/*查询用户*/User queryById(Integer uid);
}

3、在dataservice模块service包,UserService实现这个接口方法

package com.bjpowernode.dataservice.service;import com.bjpowernode.api.model.FinanceAccount;
import com.bjpowernode.api.model.User;
import com.bjpowernode.api.pojo.UserAccountInfo;
import com.bjpowernode.api.service.UserService;
import com.bjpowernode.common.util.CommonUtil;
import com.bjpowernode.dataservice.mapper.FinanceAccountMapper;
import com.bjpowernode.dataservice.mapper.UserMapper;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.dubbo.config.annotation.DubboService;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.transaction.annotation.Transactional;import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.Date;@DubboService(interfaceClass = UserService.class,version = "1.0")
public class UserServiceImpl implements UserService {@Resourceprivate UserMapper userMapper;@Resourceprivate FinanceAccountMapper financeAccountMapper;@Value("${ylb.config.password-salt}")private String passwordSalt;@Overridepublic User queryByPhone(String phone) {User user = null;if(CommonUtil.checkPhone(phone)){user = userMapper.selectByPhone(phone);}return user;}/*用户注册*/@Transactional(rollbackFor = Exception.class)@Overridepublic synchronized int userRegister(String phone, String password) {int result = 0;//默认参数不正确if( CommonUtil.checkPhone(phone)&& (password != null && password.length()==32)){//判断手机号在库中是否存在User queryUser = userMapper.selectByPhone(phone);if(queryUser == null){//注册密码的md5二次加密。 给原始的密码加盐(salt)String newPassword = DigestUtils.md5Hex( password + passwordSalt);//注册u_userUser user = new User();user.setPhone(phone);user.setLoginPassword(newPassword);user.setAddTime(new Date());userMapper.insertReturnPrimaryKey(user);//获取主键user.getId()FinanceAccount account = new FinanceAccount();account.setUid(user.getId());account.setAvailableMoney(new BigDecimal("0"));financeAccountMapper.insertSelective(account);//成功result = 1result = 1;} else {//手机号存在result = 2;}}return result;}/*登录*/@Transactional(rollbackFor = Exception.class)@Overridepublic User userLogin(String phone, String password) {User user = null;if( CommonUtil.checkPhone(phone) && (password != null && password.length() == 32)) {String newPassword = DigestUtils.md5Hex( password + passwordSalt);user = userMapper.selectLogin(phone,newPassword);//更新最后登录时间if( user != null){user.setLastLoginTime(new Date());userMapper.updateByPrimaryKeySelective(user);}}return user;}/*更新实名认证信息*/@Overridepublic boolean modifyRealname(String phone, String name, String idCard) {int rows = 0;if(!StringUtils.isAnyBlank(phone,name,idCard)){rows  = userMapper.updateRealname(phone,name,idCard);}return rows > 0 ;}/*获取用户和资金信息*/@Overridepublic UserAccountInfo queryUserAllInfo(Integer uid) {UserAccountInfo info = null;if( uid != null && uid > 0 ) {info  = userMapper.selectUserAccountById(uid);}return info ;}/*查询用户*/@Overridepublic User queryById(Integer uid) {User user = null;if( uid != null && uid > 0 ){user = userMapper.selectByPrimaryKey(uid);}return user;}
}

http://www.ppmy.cn/news/903989.html

相关文章

外包软件定制开发中时间和进度管理

引言 时间和进度管理是外包软件定制开发项目中至关重要的方面。有效地管理时间和进度可以确保项目按计划顺利进行&#xff0c;减少延误和风险&#xff0c;从而提高交付的可靠性和质量。然而&#xff0c;由于外包团队和客户位于不同的地理位置和时区&#xff0c;时间和进度管理…

【Pytorch神经网络实战案例】28 GitSet模型进行步态与身份识别(CASIA-B数据集)

1 CASIA-B数据集 本例使用的是预处理后的CASIA-B数据集&#xff0c; 数据集下载网址如下。 http&#xff1a;//www.cbsr.ia.ac.cn/china/Gait%20Databases%20cH.asp 该数据集是一个大规模的、多视角的步态库。其中包括124个人&#xff0c;每个人有11个视角(0&#xff0c;18&am…

MPP介绍

MPP即大规模并行处理&#xff08;Massively Parallel Processor &#xff09;。如greenplum&#xff0c;它是一种基于PostgreSQL的分布式数据库&#xff0c;采用Shared-Nothing架构&#xff0c;主机、操作系统、内存、存储都是自我控制的&#xff0c;不存在共享。数据节点通过专…

rpmsg

struct rproc 通讯的硬件基础是rproc virtio_device&#xff0c;rproc_add时会register_virtio_device&#xff0c;然后virtio_ipc_driver的rpmsg_probe执行&#xff0c;后面的rpmsg_device endpoint都是借助rproc virtio_device完成通讯 static struct rproc_ops rproc_ops …

GPGGA \ GPRMC 格式解析

一、GPGGA格式解析 示例&#xff1a; $GPGGA,044744.00,3122.4658,N,12025.2791,E,1,10,3.00,12.575,M,7.100,M,00,0000*5F 解析说明&#xff1a; 字段0&#xff1a;$GPGGA&#xff0c;语句ID&#xff0c;表明该语句为Global Positioning System Fix Data&#xff08;GGA&…

GMRP

gmrp&#xff08;garp multicast registration protocol&#xff0c;garp组播注册协议&#xff09;是基于garp的一个组播注册协议&#xff0c;用于维护交换机中的组播注册信息。所有支持gmrp的交换机都能够接收来自其他交换机的组播注册信息&#xff0c;并动态更新本地的组播注…

【论文阅读】GaitSet: Regarding Gait as a Set for Cross-View Gait Recognition

GaitSet: Regarding Gait as a Set for Cross-View Gait Recognition 摘要IntroGaitSet问题公式描述Set PoolingHorizontal Pyramid MappingMultilayer Global Pipeline 训练和测试实验 论文信息&#xff1a; 作者&#xff1a;Hanqing Chao, Yiwei He, Junping Zhang, Jianfen…

R语言基础绘图包--控制axis label位置--par(mgp)与mtext

代码 png("mtext.pdf") plot(1:10, type"n", xaxt"n", yaxt"n", ylab"original ylab site", xlab"original xlab site")for(j in 1:4) for(i in 0:10) mtext(as.character(i),sidej,linei) dev.of…