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;
        }
    }

     

  • 相关阅读:
    POJ 1811 Prime Test 素性测试 分解素因子
    sysbench的安装与使用
    电脑中已有VS2005和VS2010安装.NET3.5失败的解决方案
    I.MX6 show battery states in commandLine
    RPi 2B Raspbian system install
    I.MX6 bq27441 driver porting
    I.MX6 隐藏电池图标
    I.MX6 Power off register hacking
    I.MX6 Goodix GT9xx touchscreen driver porting
    busybox filesystem httpd php-5.5.31 sqlite3 webserver
  • 原文地址:https://www.cnblogs.com/sunjf/p/design_beans.html
Copyright © 2011-2022 走看看