Authored by 李奇

用户端model redis引入

@@ -3,7 +3,7 @@ @@ -3,7 +3,7 @@
3 * @author: leo <qi.li@yoho.cn> 3 * @author: leo <qi.li@yoho.cn>
4 * @date: 26/09/2018 4 * @date: 26/09/2018
5 */ 5 */
6 -const wheelSurfModel = require('../models/wheel-surf'); 6 +const wheelSurfModelRedis = require('../models/wheel-surf-redis');
7 const valid = require('../../../utils/validator'); 7 const valid = require('../../../utils/validator');
8 8
9 const whSurfController = { 9 const whSurfController = {
@@ -13,7 +13,7 @@ const whSurfController = { @@ -13,7 +13,7 @@ const whSurfController = {
13 act_id: {type: 'number', empty: false}, 13 act_id: {type: 'number', empty: false},
14 uid: {type: 'number', empty: true}, 14 uid: {type: 'number', empty: true},
15 }); 15 });
16 - let result = await req.ctx(wheelSurfModel).getNowConf(data); 16 + let result = await req.ctx(wheelSurfModelRedis).getNowConf(data);
17 17
18 res.json({code: 200, data: result, result: true}); 18 res.json({code: 200, data: result, result: true});
19 } catch (e) { 19 } catch (e) {
@@ -31,7 +31,7 @@ const whSurfController = { @@ -31,7 +31,7 @@ const whSurfController = {
31 appVersion: {type: 'string', empty: false}, 31 appVersion: {type: 'string', empty: false},
32 appSessionType: {type: 'string', empty: true} 32 appSessionType: {type: 'string', empty: true}
33 }); 33 });
34 - let result = await req.ctx(wheelSurfModel).goPrize(data); 34 + let result = await req.ctx(wheelSurfModelRedis).goPrize(data);
35 35
36 res.json({code: 200, data: result, result: true}); 36 res.json({code: 200, data: result, result: true});
37 } catch (e) { 37 } catch (e) {
@@ -45,7 +45,7 @@ const whSurfController = { @@ -45,7 +45,7 @@ const whSurfController = {
45 act_id: {type: 'number', empty: false}, 45 act_id: {type: 'number', empty: false},
46 uid: {type: 'number', empty: false}, 46 uid: {type: 'number', empty: false},
47 }); 47 });
48 - let result = await req.ctx(wheelSurfModel).getUserPrize(data); 48 + let result = await req.ctx(wheelSurfModelRedis).getUserPrize(data);
49 49
50 res.json({code: 200, data: result, result: true}); 50 res.json({code: 200, data: result, result: true});
51 } catch (e) { 51 } catch (e) {
  1 +/* eslint-disable array-callback-return */
  2 +const {ActWheelSurfConf, ActWheelSurfPrize, ActWheelSurfUser, Activity, sequelize} = require('../../../db');
  3 +
  4 +// const md5 = require('yoho-md5');
  5 +const _ = require('lodash');
  6 +const logger = global.yoho.logger;
  7 +const mysqlCli = global.yoho.utils.mysqlCli;
  8 +
  9 +const _sender = global.yoho.sender;
  10 +
  11 +/**
  12 + * 上报
  13 + * @param type 0: packrain 1: turntable
  14 + * @param tags 一些基础参数
  15 + * @param fields 红包的金额
  16 + * @param isFail 接口是否失败
  17 + */
  18 +const sendMessage = (type, tags, fields, isFail) => {
  19 + if (!_sender) {
  20 + return;
  21 + }
  22 + const hostname = (require('os').hostname());
  23 + let typeName = ['turntable-red', 'turntable-coupon'][type];
  24 + let initTags = {
  25 + hostname,
  26 + pid: process.pid || 0,
  27 + app: global.yoho.config.appName,
  28 + type: typeName
  29 + };
  30 +
  31 + tags = Object.assign({}, initTags, tags);
  32 + isFail = isFail ? 1 : 0;
  33 + fields = Object.assign({}, fields);
  34 +
  35 + let mesurement = ['monitor_success_report', 'monitor_error_report'][isFail];
  36 +
  37 + try {
  38 + _sender.addMessage({
  39 + measurement: mesurement,
  40 + tags,
  41 + fields
  42 + });
  43 + } catch (e) {
  44 + logger.error(e);
  45 + }
  46 +};
  47 +
  48 +class ActWheelSurfModelRedis extends global.yoho.BaseModel {
  49 + constructor(ctx) {
  50 + super(ctx);
  51 + this.redis = global.yoho.redis;
  52 + this.client = this.redis.client;
  53 + }
  54 +
  55 + async getNowConf(obj) {
  56 + try {
  57 + let data = {};
  58 +
  59 + data.conf = await this.client.hgetallAsync(`turntable:${obj.act_id}`)
  60 + .then(conf => {
  61 + Object.keys(conf).forEach(key => {
  62 + if (conf[key] && !_.isNaN(Number(conf[key]))) {
  63 + conf[key] = Number(conf[key])
  64 + }
  65 + });
  66 + return conf;
  67 + });
  68 +
  69 + // 获取当前活动奖品
  70 + let prize = await this.client.lrangeAsync(`turntable:${obj.act_id}:prize`, 0, 7)
  71 + .then(prizes => {
  72 + return prizes.map(prize => {
  73 + return JSON.parse(prize);
  74 + })
  75 + });
  76 +
  77 + data.prize = prize.length;
  78 + data.emptyPrize = {};
  79 +
  80 + for (let value of prize) {
  81 + if (value.type === 1) {
  82 + data.emptyPrize = value;
  83 + break;
  84 + }
  85 + }
  86 +
  87 + let act = await Activity.findOne({where: {id: obj.act_id}});
  88 + let nowDate = new Date();
  89 +
  90 + nowDate = parseInt(nowDate.getTime() / 1000);
  91 + if (act.startTime > nowDate) {
  92 + data.startType = false;
  93 + data.errorType = 0;
  94 + data.errorMsg = '活动未开始';
  95 + }
  96 + if (act.endTime < nowDate) {
  97 + data.startType = false;
  98 + data.errorType = 1;
  99 + data.errorMsg = '活动已过期';
  100 + }
  101 +
  102 + // 获取当去用户剩余次数
  103 + let residueCount;
  104 +
  105 + // 判断用户是否登录 如果没登录就取当前活动最大次数
  106 + if (obj.uid) {
  107 + // 每日最大次数
  108 + if (data.conf.times_type === 1) {
  109 + // 获取当天0点和23:59:59
  110 + let endTime = new Date(new Date(new Date().toLocaleDateString()).getTime() + 24 * 60 * 60 * 1000 - 1);
  111 + let startTime = new Date(new Date(new Date().toLocaleDateString()).getTime());
  112 +
  113 + obj.create_time = {gt: startTime, lte: endTime};
  114 + residueCount = data.conf.day_limit_times - await ActWheelSurfUser.count({
  115 + where: obj
  116 + });
  117 + } else {
  118 + // 活动最大次数
  119 + residueCount = data.conf.act_total_times - await ActWheelSurfUser.count({where: obj});
  120 + }
  121 + } else {
  122 + residueCount = data.conf.times_type === 3 ? data.conf.act_total_times : data.conf.day_limit_times;
  123 + }
  124 + data.residueCount = residueCount;
  125 + return Promise.resolve(data);
  126 + } catch (e) {
  127 + logger.error(e);
  128 + return Promise.reject({code: 305, result: false, msg: '服务错误,请稍等'});
  129 + }
  130 + }
  131 +
  132 + // noinspection JSAnnotator
  133 + async goPrize(obj) {
  134 + try {
  135 + // 校验有效活动时间
  136 + let act = await Activity.findOne({where: {id: obj.act_id}});
  137 + let nowDate = new Date();
  138 +
  139 + nowDate = parseInt(nowDate.getTime() / 1000);
  140 + if (act.startTime > nowDate) {
  141 + return Promise.reject({code: 301, result: false, msg: '活动未开始'});
  142 + }
  143 + if (act.endTime < nowDate) {
  144 + return Promise.reject({code: 302, result: false, msg: '活动已过期'});
  145 + }
  146 +
  147 + // 获取活动信息
  148 + let conf = await ActWheelSurfConf.findOne({where: {act_id: obj.act_id}});
  149 + let residueCount;
  150 + let uid = {
  151 + toString: () => {
  152 + return _.parseInt(obj.uid);
  153 + },
  154 + sessionKey: obj.sessionKey,
  155 + appVersion: obj.appVersion,
  156 + appSessionType: obj.sessionType
  157 + };
  158 +
  159 + delete obj.sessionKey;
  160 + delete obj.appVersion;
  161 + delete obj.sessionType;
  162 +
  163 + // 计算用户剩余次数校验
  164 + if (conf.times_type === 1) {
  165 + // 获取当天0点和23:59:59
  166 + let endTime = new Date(new Date(new Date().toLocaleDateString()).getTime() + 24 * 60 * 60 * 1000 - 1);
  167 + let startTime = new Date(new Date(new Date().toLocaleDateString()).getTime());
  168 +
  169 + obj.create_time = {gt: startTime, lte: endTime};
  170 + residueCount = conf.day_limit_times - await ActWheelSurfUser.count({
  171 + where: obj
  172 + });
  173 + } else {
  174 + // 活动最大次数
  175 + residueCount = conf.act_total_times - await ActWheelSurfUser.count({where: obj});
  176 + }
  177 +
  178 + if (residueCount > 0) {
  179 + // 获取抽取到奖品
  180 + // 获取奖品信息
  181 + let prize = await ActWheelSurfPrize.findAll({where: {act_id: obj.act_id}});
  182 +
  183 + // 获取每个奖品获取它们的中奖范围
  184 + let arr = {}, oldValue;
  185 +
  186 + prize.map(function (value, index) {
  187 + if (value.chance) {
  188 + if (typeof(oldValue) === 'undefined') {
  189 + arr[index] = {maxValue: value.chance, leastValue: 0};
  190 + } else {
  191 + let maxValue = value.chance + oldValue;
  192 + let leastValue = oldValue;
  193 +
  194 + arr[index] = {maxValue, leastValue};
  195 + }
  196 + oldValue = arr[index].maxValue;
  197 + }
  198 + });
  199 +
  200 + // 比较概率获取中奖奖品
  201 + // 随机生成0-100的随机数
  202 + let random = Math.random() * 100;
  203 +
  204 + // 判定随机数在奖品池子取件 选定中奖奖品
  205 + let getPrize, sendResult = {}, result, reduce;
  206 +
  207 + for (let i in arr) {
  208 + if (arr[i].maxValue >= random && arr[i].leastValue < random) {
  209 + getPrize = prize[i];
  210 + break;
  211 + }
  212 + }
  213 +
  214 + if (getPrize.type !== 1) {
  215 + // 校验剩余库存 减库存
  216 + reduce = await ActWheelSurfPrize.update({total_left: sequelize.literal('`total_left`-1')}, {
  217 + where: {
  218 + total_left: {$gt: 0},
  219 + id: getPrize.id
  220 + }
  221 + });
  222 +
  223 + // 如果库存不够则返回当前type=1的商品
  224 + if (reduce[0] !== 1) {
  225 + for (let p of prize) {
  226 + if (p.type === 1) {
  227 + getPrize = p;
  228 + break;
  229 + }
  230 + }
  231 + }
  232 + }
  233 +
  234 + getPrize = getPrize.dataValues;
  235 + if (getPrize.type === 1) {
  236 + sendResult.code = 200;
  237 + getPrize.desc = '对不起,您没有中奖';
  238 + } else if (getPrize.type === 2) {
  239 +
  240 + try {
  241 + // 调用java接口
  242 + sendResult = await this.get({
  243 + data: {
  244 + method: 'app.redpac.addRedpac',
  245 + actSource: 1001,
  246 + uid: uid,
  247 + redpacToken: getPrize.value
  248 + }
  249 + });
  250 +
  251 + sendResult = sendResult || {};
  252 + sendResult.data = sendResult.data || {};
  253 + sendMessage(0, {}, {succeedTimes: sendResult.data.amount || 0}, 0);
  254 +
  255 + if (sendResult.code === 200) {
  256 + if (!sendResult.data.amount) {
  257 + sendResult.code = 201; // 重复领取
  258 + } else {
  259 + getPrize.desc = '恭喜您获得' + sendResult.data.amount + '元红包';
  260 + }
  261 + }
  262 + } catch (e) {
  263 + logger.error(e);
  264 + sendMessage(0, {}, {message: e.message || 'interface error', stack: e}, 1);
  265 + }
  266 + } else if (getPrize.type === 3) {
  267 + try {
  268 + sendResult = await this.get({
  269 + data: {
  270 + method: 'app.coupons.couponsSend',
  271 + uid: uid,
  272 + coupon_send_token: getPrize.value
  273 + }
  274 + });
  275 +
  276 + sendMessage(1, {}, {succeedTimes: 1}, 0);
  277 +
  278 + if (sendResult && sendResult.code === 200) {
  279 + getPrize.desc = '恭喜您获得' + getPrize.name + '优惠券';
  280 + }
  281 +
  282 + } catch (e) {
  283 + logger.error(e);
  284 + sendMessage(1, {}, {message: e.message || 'interface error', stack: e}, 1);
  285 + }
  286 + } else if (getPrize.type === 4) {
  287 + sendResult.code = 200;
  288 + getPrize.desc = '恭喜您获得' + getPrize.name;
  289 + }
  290 +
  291 + // 插入数据库
  292 + if (sendResult.code !== 200) {
  293 + getPrize = null;
  294 + for (let item of prize) {
  295 + if (item.type === 1) {
  296 + getPrize = item.dataValues;
  297 + break;
  298 + }
  299 + }
  300 + getPrize.desc = '对不起,您没有中奖';
  301 + }
  302 + result = await ActWheelSurfUser.create({act_id: obj.act_id, uid: obj.uid, prize_id: getPrize.id});
  303 + if (result) {
  304 + delete getPrize.chance;
  305 + delete getPrize.create_time;
  306 + delete getPrize.total;
  307 + delete getPrize.total_left;
  308 + delete getPrize.value;
  309 + return Promise.resolve(getPrize);
  310 + } else {
  311 + return Promise.reject({code: 305, result: false, msg: '服务错误,请稍等'});
  312 + }
  313 + } else {
  314 + return Promise.reject({code: 304, result: false, msg: '用户使用次数不足'});
  315 + }
  316 + } catch (e) {
  317 + logger.error(e);
  318 + return Promise.reject({code: 305, result: false, msg: '服务错误,请稍等'});
  319 + }
  320 + }
  321 +
  322 + async getUserPrize(obj) {
  323 + try {
  324 + return await mysqlCli.query(
  325 + `select u.id, u.act_id act_id, u.prize_id prize_id, u.create_time createTime, p.name name,p.type type ,p.value value,p.img img
  326 + from act_wheel_surf_user u , act_wheel_surf_prize p where u.prize_id = p.id and u.act_id =:act_id and u.uid = :uid and type != :type
  327 + order by u.create_time desc`, {act_id: obj.act_id, uid: obj.uid, type: 1});
  328 +
  329 + // return await ActWheelSurfUser.findAll({include: [{
  330 + // model: ActWheelSurfPrize,
  331 + // as: 'ActWheelSurfPrize',
  332 + // }],
  333 + // where: obj
  334 + // });
  335 + } catch (e) {
  336 + logger.error(e);
  337 + return Promise.reject({code: 305, result: false, msg: '服务错误,请稍等'});
  338 + }
  339 + }
  340 +}
  341 +
  342 +module.exports = ActWheelSurfModelRedis;