首页 > 其他分享 >立即投资

立即投资

时间:2023-08-26 14:02:41浏览次数:28  
标签:product uid money 立即 userinfo && 投资 productId

1. 页面原型   138

立即投资_sql

立即投资_User_02

2.购买理财产品实现   139

2.1 业务接口  139

micr-api

InvestService

//购买理财产品 139
    int investProduct(Integer uid, Integer productId, BigDecimal money);

2.2 业务接口实现类  139

2.2.1 查询用户账户金额 给uid的记录上锁

micr-dataservice

在mapper中定义方法FinanceAccountMapper
//购买理财产品之查询用户账户金额 给uid的记录上锁  139
    FinanceAccount selectByUidForUpdate(@Param("uid") Integer uid);
编写sql  FinanceAccountMapper.xml     139-140

micr-dataservice

给某一行上锁我们用for update

给u_finance_account表的uid唯一索引

立即投资_sql_03

立即投资_sql_04

<!--购买理财产品之查询用户账户金额 给uid的记录上锁*139-140-->
  <select id="selectByUidForUpdate" resultMap="BaseResultMap">
    select <include refid="Base_Column_List" />
    from u_finance_account
    where uid = #{uid}
    for update
  </select>

2.2.2 比较大小方法   140

micr-common

CommonUtil
/*比较BigDecimal  n1 >=2 :true ,false   140*/
    public static boolean ge(BigDecimal n1, BigDecimal n2){
        if( n1 == null || n2 == null){
            throw new RuntimeException("参数BigDecimal是null");
        }
        return  n1.compareTo(n2) >= 0;
    }

2.2.3 可以购买了 扣除账号资金  141

micr-dataservice

mapper定义方法

 FinanceAccountMapper

//可以购买了 更新扣除账号资金   141
    int updateAvailableMoneyByInvest(Integer uid, BigDecimal money);
编写sql  

 FinanceAccountMapper.xml

<!--可以购买了更新扣除账号资金   141-->
  <update id="updateAvailableMoneyByInvest">
    update  u_finance_account set available_money = available_money - #{money}
    where uid = #{uid} and ( available_money - #{money} >=0 )
  </update>

2.2.4 扣除产品剩余可投资金额   141

在mapper中定义方法

 ProductInfoMapper

//扣除产品剩余可投资金额  141
    int updateLeftProductMoney(@Param("id") Integer productId, @Param("money") BigDecimal money);
编写sql 

 ProductInfoMapper.xml

<!--扣除产品剩余可投资金额  141-->
  <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>

2.2.5 判断产品是否卖完,更新产品是满标状态  142

在mapper中定义方法

ProductInfoMapper

//更新产品是满标状态  142
    int updateSelled(@Param("id") Integer productId);
编写sql

ProductInfoMapper.xml

<!--更新产品是满标状态  142-->
  <update id="updateSelled">
    update  b_product_info set product_status = 1 ,  product_full_time = now()
    where id = #{id}
  </update>

2.2.6 实现类InvestServiceImpl    139

添加常量类  141

micr-common

立即投资_xml_05

InvestServiceImpl

micr-dataservice

//购买理财产品 139
    @Transactional(rollbackFor = Exception.class) //143
    @Override
    public 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) {
                //因为我们的资金的类型是 BigDecimal这个类型是不能使用><符号比较大小的,
                // 所以需要我们定义一个工具类来比较大小  140
                if (CommonUtil.ge(account.getAvailableMoney(), money)) {//当用户余额大于等于购买金额时为true
                    //资金满足购买要求

                    //3.检查产品是否可以购买    140
                    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. 扣除账号资金   141
                            rows = accountMapper.updateAvailableMoneyByInvest(uid, money);
                            if (rows < 1) {
                                throw new RuntimeException("投资更新账号资金失败");
                            }

                            //5.扣除产品剩余可投资金额  141
                            rows = productInfoMapper.updateLeftProductMoney(productId, money);
                            if (rows < 1) {
                                throw new RuntimeException("投资更新产品剩余金额失败");
                            }

                            //6.创建投资记录   142
                            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.判断产品是否卖完,更新产品是满标状态  142
                            ProductInfo dbProductInfo = productInfoMapper.selectByPrimaryKey(productId);
                            if( dbProductInfo.getLeftProductMoney().compareTo(new BigDecimal("0")) == 0 ){
                                rows  = productInfoMapper.updateSelled(productId);
                                if( rows < 1 ){
                                    throw new RuntimeException("投资更新产品满标失败");
                                }
                            }
                            //8.最后这是投资成功   143
                            result = 1;
                        }
                    } else {
                        result = 4;//理财产品不存在
                    }
                } else {
                    result = 3;//资金不足
                }
            } else {
                result = 2;//资金账号不存在
            }
        }
        return result;
    }

2.3 消费者 controller   139-143

micr-web

InvestController

//购买理财产品,更新投资排行榜   139
    @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);
            //  143
            switch (investResult){
                case 0:
                    result.setMsg("投资数据不正确");
                    break;
                case 1:
                    result = RespResult.ok();
                    break;
                case 2:
                    result.setMsg("资金账号不存在");
                    break;
                case 3:
                    result.setMsg("资金不足");
                    break;
                case 4:
                    result.setMsg("理财产品不存在");
                    break;
            }
        }
        return result;
    }

2.4 测试   143

我们使用swagger

浏览器输入http://localhost:8000/api/doc.html

立即投资_sql_06

成功

立即投资_xml_07

产品表,剩余可投资金额减100

立即投资_sql_08

用户资金表减100

立即投资_User_09

投资记录标增加一条投资记录

立即投资_sql_10

3. 更新投资排行榜  144

立即投资_User_11

3.1 定义业务接口  144

UserService

micr-api

//更新投资排行榜   144
    User queryById(Integer uid);

3.2 业务接口实现类   144

UserServiceImpl

micr-dataservice

//更新投资排行榜   144
    @Override
    public User queryById(Integer uid) {
        User user = null;
        if( uid != null && uid > 0 ){
            user = userMapper.selectByPrimaryKey(uid);
        }
        return user;
    }

3.3 消费者controller  144

micr-web

InvestController

/*更新投资排行榜   144*/
    private void modifyInvestRank(Integer uid,BigDecimal money){
        User user  = userService.queryById(uid);
        if(user != null){
            //更新 redis中的投资排行榜
            String key = RedisKey.KEY_INVEST_RANK;
            //incrementScore给user.getPhone()对应的值 累加 money.doubleValue()值
            stringRedisTemplate.boundZSetOps(key).incrementScore(
                    user.getPhone(),money.doubleValue());
        }
    }

3.4 测试   144

一样我们使用swagger测试

浏览器输入http://localhost:8000/api/doc.html

我们投资产品

立即投资_xml_12

成功

立即投资_User_13

看看redis中有没有添加数据,成功

立即投资_xml_14

4. 前端实现  145

4.1 修改一下代码逻辑   148

这里解释因为我们想要

前端httpRequest.js   148

立即投资_xml_15

后端UserController  148

给uid参数加上非必须的参数

解释原因,因为前端想要在非登录状态可以查看产品详情,但是我们在展示产品详情页面需要展示用户资金余额,这个资金余额目前只有用户中心的方法返回了如下图引用了/v1/user/usercenter此后端用户中心的接口,但是后端在接收uid参数时是从请求头中获取的,而我们此时处于非登录状态浏览器中缓存中没有token和用户信息,所以后端就拿不到参数,前端程序就会被错误拦截,为了避免这种情况,我们需要将后端的uid设置为非必须,这样前端就能成功访问了,uid为空后端只会返回空数据,而前端还做了非登录看不到数据的保护,至此没问题

立即投资_User_16


立即投资_xml_17

4.2 ProductDetail.vue

<template>
  <div>
    <Header></Header>
    <div class="content clearfix">
      <div class="detail-left">
        <div class="detail-left-title">{{ product.productName }}({{ product.productNo }}期)</div>
        <ul class="detail-left-number">
          <li>
            <span>历史年化收益率</span>
            <p><b>{{ product.rate }}</b>%</p>
            <span>历史年化收益率</span>
          </li>
          <li>
            <span>募集金额(元)</span>
            <p><b>{{ product.productMoney }}</b>元</p>
            <span v-if="product.leftProductMoney > 0 ">募集中  剩余募集金额{{ product.leftProductMoney }}元</span>
            <span v-else>已满标</span>
          </li>
          <li>
            <span>投资周期</span>
            <p v-if="product.productType == 0 "><b>{{product.cycle}}</b>天</p>
            <p v-else><b>{{product.cycle}}</b>个月</p>

          </li>

        </ul>
        <div class="detail-left-way">
          <span>收益获取方式</span>
          <span>收益返还:<i>到期还本付息</i></span>
        </div>
        <!--投资记录-->
        <div class="datail-record">
          <h2 class="datail-record-title">投资记录</h2>
          <div class="datail-record-list">
            <table align="center" width="880" border="0" cellspacing="0" cellpadding="0">
              <colgroup>
                <col style="width: 72px" />
                <col style="width: 203px" />
                <col style="width: 251px" />
                <col style="width: 354px" />
              </colgroup>
              <thead class="datail_thead">
              <tr>
                <th>序号</th>
                <th>投资人</th>
                <th>投资金额(元)</th>
                <th>投资时间</th>
              </tr>
              </thead>
              <tbody>
              <tr v-for="(bid,ind) in bidList" :key="bid.id">
                <td>{{ind+1}}</td>
                <td class="datail-record-phone">{{ bid.phone }}</td>
                <td>{{ bid.bidMoney }}</td>
                <td>{{ bid.bidTime }}</td>
              </tr>

              </tbody>
            </table>
          </div>
        </div>

      </div>
      <!--右侧-->
      <div class="detail-right">
        <div class="detail-right-title">立即投资</div>
        <div class="detail-right-mode">
          <h3 class="detail-right-mode-title">收益方式</h3>
          <p class="detail-right-mode-p"><span>到期还本付息</span></p>
          <h3 class="detail-right-mode-title">我的账户可用</h3>

          <div class="detail-right-mode-rmb" v-if="logined==false">
            <p>资金(元):******</p>
            <a href="javascript:void(0);" @click="goLink('/page/user/login',)">请登录</a>
          </div>
          <div class="detail-right-mode-rmb"  v-else>
            <p>资金(元):{{this.accountMoney}}</p>
          </div>

          <h3 class="detail-right-mode-title">利息收入(元){{income}}</h3>
          <form action="" id="number_submit">
            <p>请在下方输入投资金额</p>
            <input type="text" placeholder="请输入日投资金额,应为100元整倍数" v-model="investMoney" @blur="checkInvestMoney" class="number-money" >
            <div class="err">{{investMoneyErr}}</div>
            <input type="button" value="立即投资" @click="investProduct" class="submit-btn">
          </form>

        </div>
      </div>
    </div>
    <Footer></Footer>

  </div>
</template>

<script>
import Header from "@/components/common/Header";
import Footer from "@/components/common/Footer";
import {doGet, doPost} from "@/api/httpRequest";
import layx from "vue-layx";

export default {
  name: "ProductDetail",
  components:{
    // eslint-disable-next-line vue/no-unused-components
    Header,
    // eslint-disable-next-line vue/no-unused-components
    Footer
  },
  data(){
    return {
      product:{
        id: 0,
        productName: "",
        rate: 0.0,
        cycle: 0,
        releaseTime: 0,
        productType: 0,
        productNo: "",
        productMoney: 0,
        leftProductMoney: 0,
        bidMinLimit: 0,
        bidMaxLimit: 0,
        productStatus: 0,
        productFullTime: "",
        productDesc: ""
      },
      bidList:[
        {
          id: 0,
          phone: "",
          bidTime: "",
          bidMoney: 0.00
        }],
      logined:false,
      accountMoney:0.0,
      investMoney: 100,
      investMoneyErr:'',
      income:""
    }
  },
  mounted() {
    //判断是否登录  145
    if( window.localStorage.getItem("userinfo")){
      this.logined = true;
    }
    this.initPage();
  },

  methods:{
    goLink(url,params){
      //使用router做页面跳转, vue中的对象
      this.$router.push({
        path: url,
        query: params
      })
    },

    initPage(){
      //查询产品信息
      let productId = this.$route.query.productId;
      doGet('/v1/product/info',{productId:productId})
          .then(resp=>{
            if( resp ) {
              this.product = resp.data.data;
              this.bidList = resp.data.list;
            }
          })

      //查询用户资金  145
      doGet('/v1/user/usercenter').then(resp=>{
        if( resp && resp.data.code == 1000){
          this.accountMoney = resp.data.data.money;
        }
      })
    },

    checkInvestMoney() {   //146
      if (isNaN(this.investMoney)) {
        this.investMoneyErr = '请输入正确的金额';
      } else if (parseInt(this.investMoney) < 100) {
        this.investMoneyErr = '投资最小是100元';
      } else if (parseFloat(this.investMoney) % 100 != 0) {
        this.investMoneyErr = '投资金额是100的整数倍';
      } else {
        this.investMoneyErr = '';
        //计算利息  利息 = 本金 * 周期 * 利率   147
        //当前产品数据 利率是 年利率是 ,百分数 。
        //不同类型的产品 ,周期不同, 新手宝是 天,  其他是月(30)
        //日利率
        let dayRate = this.product.rate / 365 / 100;
        //利息
        let incomeMoney = 0.0;
        if (this.product.productType == 0) { //新手宝
          incomeMoney = this.investMoney * this.product.cycle * dayRate;
        } else {//其他
          incomeMoney = this.investMoney * (this.product.cycle * 30) * dayRate;
        }
        this.income = incomeMoney.toFixed(2);
      }
    },

    investProduct() {//立即投资  148
      //登录, 实名认证过
      let userinfo = JSON.parse(window.localStorage.getItem("userinfo"));
      if (userinfo) {
        //检查是否有实名认证
        if (userinfo.name != '') {
          //投资
          this.checkInvestMoney();
          if (this.investMoneyErr == '') {
            doPost('/v1/invest/product', {productId: this.product.id, money: this.investMoney})
                .then(resp => {
                  if (resp && resp.data.code == 1000) {
                    //投资成功,刷新页面   149
                    this.initPage();
                  }
                })
          }
        } else {
          //进行实名认证
          layx.msg('投资前需要实名认证.', {dialogIcon: 'warn', position: 'ct'});
        }
      } else {
        //去登录
        layx.msg('请先登录.', {dialogIcon: 'warn', position: 'ct'});
      }
    }
  }


}
</script>

<style scoped>
.err {
  color: red;
  font-size: 18px;
}
</style>

4.3 测试,投资成功  149

立即投资_User_18

看看数据库

投资记录标增加了四条数据

立即投资_sql_19

资金表减少400

立即投资_xml_20

产品表 满月宝剩余资金减少400

立即投资_xml_21

投资排行榜,在redis中,13812345699机主投资增加400

立即投资_User_22

5. 修改实名认证的bug,自己实现

realNameView.vue

立即投资_xml_23

//这里我们修改一个bug,自己实现,因为投资需要根据缓存中的name判断是否实名认证
            // ,这里我们要在实名成功后在缓存中加上name
            // 从浏览器缓存中获取userinfo的值
            const userinfo = JSON.parse(window.localStorage.getItem('userinfo'));
            // 给userinfo的name属性赋值
            userinfo.name = this.name;
            // 将更新后的userinfo重新存回浏览器缓存
            window.localStorage.setItem('userinfo', JSON.stringify(userinfo));

标签:product,uid,money,立即,userinfo,&&,投资,productId
From: https://blog.51cto.com/u_15784725/7243697

相关文章

  • MTFE骗局给全球投资者造成损失约15亿美元,约7000万人被骗
    据海外媒体统计,MTFE骗局在全球范围内诈骗了15亿美元,约7000万人上当。被骗的不仅有我们已知的孟加拉国、斯里兰卡、尼日利亚、巴基斯坦和印度等国,还有加拿大、英国、德国、瑞士、马来西亚、泰国、新加坡、阿拉伯联合酋长国、科威特、卡塔尔、意大利、澳大利亚、马尔代夫、沙特阿拉伯......
  • 贵金属投资新手必读:入门指南大揭秘!
    在当今多元化的投资市场中,贵金属投资成为了越来越多投资者关注和参与的领域。作为一种避险和保值增值的方式,贵金属投资具有很多独特的优势。然而,对于初入投资圈的新手来说,面对琳琅满目的贵金属品种和复杂的投资策略,可能会感到无所适从。因此,本文将为贵金属投资新手们揭秘一些入门......
  • 黄金投资初学者必读:入门指南及投资技巧
    黄金一直以来都被视为一种安全的投资选择。在经济不稳定和市场波动的时候,黄金往往是投资者避险的首选。对于黄金投资初学者来说,了解一些基本知识和投资技巧是非常重要的。本文将为您提供一个黄金投资的入门指南,帮助您在投资黄金时做出明智的决策。首先,让我们了解一下黄金的基本特......
  • 投资期货的好处,你知道多少?
    1、期货交易的双向性:期货买卖和股票最大的一个区别就在于,期货可以双向买卖,期货即可以买空也可以卖空。价格如果上涨可以低买高卖,价格下跌时可以高卖低补。做多可以赚钱,做空也可以赚钱,所以期货市场是没有熊市的。在熊市中,股市会惨淡而期货市场却风景依旧,机会仍然。当你认为未来......
  • 投资创新:四家公司在人工智能、数据探索和客户领域处于领先地位……
    在在不断发展的技术世界中,投资往往是创新、增长潜力和行业信心的试金石。最近,四家公司因其在人工智能(AI)、数据探索、大语言模型(LLM)和客户数据激活方面的开创性工作而引起了投资者的注意。让我们深入了解他们的故事:1.虚拟化:将数据转化为富有洞察力的体验Virtualitics已经完成......
  • 韩国上市公司FSN拟投资合约黑马WEEX 交易所赛道加速洗牌
    新加坡,2023年8月1日加密衍生品交易所WEEX将以1亿美金估值完成新一轮融资,韩国KOSDAQ上市公司、数位营销巨头FSN计划领投。WEEX表示,本次募集资金将主要用于扩大全球cryptocurrency市场版图,同时给用户提供更安全的交易保障。当前,cryptocurrency交易赛道仍以中心化平台为......
  • FX110曝光:山海ZFX平台出金难!投资者苦不堪言
    入金容易出金难,近数月,ZFX的投资用户深被平台苛刻的出金条件所困扰,想出金却被平台一些莫名其妙的要求折磨得苦不堪言。投资者们怨气四起,我站收到关于ZFX平台的投诉帖也是接连不断。层层关卡,盈利了无法出金据一汇友爆料,他在ZFX平台累计入金了15000美元,经过一段时间的交易,账户盈利了11......
  • AMEYA360:大唐恩智浦荣获〖2023中国具有投资价值车规级芯片企业〗
       2023年8月10日,由无锡市滨湖区政府、市工业和信息化局主办的2023中国汽车半导体新生态论坛暨第五届太湖创芯峰会在无锡隆重举行。峰会介绍当天,滨湖区“集成电路产教融合与人才培养基地”成功揭牌,《2023全球智能汽车产业图谱及研究报告》同期发布。期间,在无锡市......
  • 助力数字化转型︱北咨公司工程投资大数据平台顺利验收
    8月3日,由成都鹏业软件股份有限公司(以下简称“鹏业软件”)承建的北京市工程咨询有限公司(以下简称“北咨公司”)工程投资大数据平台(以下简称“平台”)顺利通过最终验收,平台的实施应用将进一步助力北咨数字化转型。本平台的建设,是在国家数字化转型和造价市场化改革的政策指引下,是北咨公司......
  • 一键式文本纠错工具,整合了BERT、ERNIE等多种模型,让您立即享受纠错的便利和效果
    pycorrector一键式文本纠错工具,整合了BERT、MacBERT、ELECTRA、ERNIE等多种模型,让您立即享受纠错的便利和效果pycorrector:中文文本纠错工具。支持中文音似、形似、语法错误纠正,python3开发。实现了Kenlm、ConvSeq2Seq、BERT、MacBERT、ELECTRA、ERNIE、Transformer等多种模型的......