Showing
2 changed files
with
346 additions
and
4 deletions
@@ -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) { |
apps/api/models/wheel-surf-redis.js
0 → 100644
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; |
-
Please register or login to post a comment