zoukankan      html  css  js  c++  java
  • 会员体系-系统豆的获取与消费

      因为业务需求,系统需要设计会员体系,其中一环是有关系统豆的获取与消费。

    一、设计场景

      1)系统豆的获得:用户可通过购买产品、签到、发表动态、评论、分享等途径获得系统豆,用户可查看系统豆获得明细及总数

      2)系统豆的消费:系统豆可以用于消费(按一定比例折算成人民币),消费途径包括

        过期,要求每年6月30日(去年12月31日前获得但未使用的系统豆)和12月31日(本年6月30日前获得但未使用的系统豆)定时清除上半年未使用的系统豆,提高用户在平台的消费积极度

        购买产品,按先获得先消费的原则,保证用户对拥有系统豆的合理消费。

      3)退还系统豆:说到购买就会涉及退货,对此产品要求退还在购买中消费的未过期的系统豆(够人性吧)。

    二、设计思路及流程图

      设计分为三部分,一部分是系统豆的获得,二是消费,三是退还。有人想将获得、退还一块考虑,不幸的告诉你两者区别很大,退还较获得实现复杂的多,也是这三部分最为麻烦的一个,下面逐一介绍。

      1)对于系统豆获得的设计是非常简单的,我们只需两步,一是为用户建统计系统豆(beans_count)字段,二是建系统豆明细表(记录系统豆增减数量、增减途径、用户id、记录时间等信息),用户表与明细表一对多关联

      2)对于系统豆的消费一个费解的问题是如何保证先获得先消费

        方案一:刚开始想到的方案是在明细表中增加消费标记字段,按时间顺序消费已有系统豆,但这个方案的可操作性确是有限的,一是需要解决余数问题,二是消费数额大往往导致很大的计算量,这显然不是一个理想的方案。正是因为存在这些难以避免的缺陷,迫使自己思考再思考,终于有了较为理想的解决办法,所以好的方法都是不满意触发的。

        方案二:由于对上述方案不甚满意,于是开启了思考模式,终于在某个时刻触发灵感,一个好的方案就这样产生了。我们的思路是这样的,我们不再单一考虑每条系统豆的获得记录,而是在某次消费的时候检查用户有多少系统豆即将过期,这样我们只需保证优先消费即将过期的系统豆即可。由于有了这样的切入点,所以我们现在的问题是要如何轻松获得用户即将过期的系统豆数。

        到了这里我们有必要重新捋一下需求,怎么样的系统豆符合过期的条件?每年6月30日和12月31日定时清除上半年获得但未使用的系统豆,于是我们做这样的假设,假设系统在6月30日之前上线,那么到了7月1日,之前所有获得的系统都都将被视为即将过期的系统豆,接着我们就会想到,如果从7月1日起用另一个字段保存新获得的系统豆(new_beans),那么beans_count - new_beans就是我们需要的即将过期的系统豆数量。

        那么到此我们的问题得到解决了么?并没有,这里我们只是获取到了6月30日之前要过期的系统豆数量,那么随着时间的推移,我们如何能保证6月31日获得去年12月31日前获得但未使用的系统豆数量(轮换变化)?于是我们想到了系统豆过期定时处理,结合过期处理这个问题将迎刃而解。我们只需在每年的6月30日和12月31日做如下两步处理即可:一、beans_count = beans_count - (beans_count - new_beans),二、new_beans = 0,这样就可以永远保证beans_count - new_beans获得是准确的将过期的系统豆数量(这里需要说明,之前new_beans还需要在第一个过期系统豆清理时间点开始统计,现在完全不用了,new_beans和beans_count字段从一开始保持同增即可)。

        通过上面分析,现在的表结构为用户表新增统计系统豆(beans_count)、新获得的系统豆(new_beans)两个字段,明细表保持不变,设计流程图如下:

        系统豆过期流程图

        

      

      注:其中beans_count为云豆总数,new_beans为新得云豆数,num为要过期云豆数。

      系统豆支付流程图

      

      

      注:其中beans_count为云豆总数,new_beans为新得云豆数,num为要过期云豆数,pay_beans为支付云豆数。

      3)关于系统豆的返还我们需要考虑消费时间、当前时间和定时清理时间这三个时间点,这样可以将处理情况清晰的分为四种情况,并且需要建立一张中间表保存消费具体细节,具体设计如下

        

      

    注:其中beans_count为云豆总数,new_beans为新得云豆数,pay_beans为支付云豆数,expire_beans为要过期云豆数,dval=pay_beans-expire_beanscrTime为创建时间,cuTime为当前时间,6.3012.31crTime当年的时间。

      中间表结构

      

    序号

    字段名

    字段中文含义

    字段类型

    是否为主键

    是否可以为空

    是否唯一

    备注

    1

    id

    唯一标识

    Bigint(20)

    YES

    NO

    YES

     

    2

    user_id

    用户id

    Bigint(20)

    NO

    NO

    NO

     

    3

    create_time

    创建时间

    datetime

    NO

    NO

    NO

     

    4

    beans_num

    所需系统豆数

    Int(11)

    NO

    NO

    NO

     

    5

    empire_beans

    使用要过期系统豆数

    Int(11)

    NO

    NO

    NO

     

    6

    order_id

    订单id

    varchar(50)

    NO

    NO

    NO

     

      到此,一个比较完整的系统豆获取、消费系统设计完成。

       附上一段判断是否过期的代码

    public class Test {
    
        public static void main(String[] args) {
            System.out.println(new Test().isEmpire(new Date()));
        }
    
        private boolean isEmpire(Date date) {
            Date createTime = date;
            Calendar calendar = Calendar.getInstance();
            calendar.setTime(createTime);
            String index1 = calendar.get(Calendar.YEAR) + "-06-30 00:00:00";
            Date index_6 = getDateFromString(index1);
    
            Date currentDate = new Date();
            calendar.setTime(currentDate);
            String index2 = calendar.get(Calendar.YEAR) + "-12-31 00:00:00";
            Date index_12 = getDateFromString(index2);
            return ((createTime.compareTo(index_6) < 0 && currentDate.compareTo(index_6) < 0) || (createTime.compareTo(index_6) > 0 && currentDate.compareTo(index_12) < 0)) ? false : true;
        }
    
        public static Date getDateFromString(String datastr) {
            Date date = new Date();
            SimpleDateFormat dateFormat = new SimpleDateFormat(
                    "yyyy-MM-dd HH:mm:ss");
            SimpleDateFormat dateFormat2 = new SimpleDateFormat("yyyy-MM-dd");
    
            try {
                if (datastr.length() == 10) {
    
                    date = dateFormat2.parse(datastr);
                } else if (datastr.length() == 19) {
                    date = dateFormat.parse(datastr);
                }
            } catch (ParseException e) {
                e.printStackTrace();
            }
            return date;
        }
    }

     

  • 相关阅读:
    MySQL主从.md
    mysqldump.md
    MySQL管理.md
    SQL语句.md
    如何在同一台服务器上部署两个tomcat
    loadrunner函数解密之web_reg_save_param
    loadrunner函数解密之web_reg_find
    Jmeter如何保持cookie,让所有请求都能用同一个cookie,免去提取JSESSIONID
    Jmeter如何提取响应头部的JSESSIONID
    Loadrunner如何进行有效的IP欺骗
  • 原文地址:https://www.cnblogs.com/sunjf/p/design_beans.html
Copyright © 2011-2022 走看看