123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292 |
- 'use strict';
- const { CrudService } = require('naf-framework-mongoose/lib/service');
- const { BusinessError, ErrorCode } = require('naf-core').Error;
- const { ObjectId } = require('mongoose').Types;
- const _ = require('lodash');
- const moment = require('moment');
- /**
- * 核心逻辑
- * . A
- * /_\ B
- * /_ _\ C crime
- * /_ _ _\ D crime
- * /_ _ _ _\ E crime
- */
- class CardService extends CrudService {
- constructor(ctx) {
- super(ctx, 'card');
- this.model = this.ctx.model.Card;
- this.record = this.ctx.model.Record;
- /**
- * @constant Number 车奖的积分 default:131400
- */
- this.car_point = 131400;
- /**
- * @constant Number 股东的积分 default:10
- */
- this.stockholder_point = 10;
- /**
- * @constant Number 股东的单数界限,前xxxx单不是股东 default: 9999
- */
- this.stockholder_limit = 20;
- /**
- * @constant Number 股东的等级界限,前x级不是股东 default:6
- */
- this.stockholder_limit_level = 6;
- /**
- * @constant Number 车奖的等级界限,前x级不是能获得车奖 default:4
- */
- this.car_show_limit_level = 4;
- /**
- * @constant Number 车奖的B梯队等级界限 default:4
- */
- this.car_show_b_limit_level = 4;
- /**
- * @constant Number 车奖的B梯队等级界限的人数 default:5
- */
- this.car_show_b_limit_person = 5;
- }
- /**
- * 修改密码
- * @param {Object} param 参数
- */
- async passwd({ id, password }) {
- password = { secret: password };
- const res = await this.model.update({ _id: ObjectId(id) }, { password });
- return res;
- }
- /**
- * 1创建卡用户;2检查推荐人
- * @param {Object} data 参数
- */
- async create(data) {
- // 先创建用户
- // 1,检查手机号是否存在
- const { password, mobile, set, r_mobile } = data;
- const is_exists = await this.model.count({ mobile });
- if (is_exists) { throw new BusinessError(ErrorCode.DATA_EXISTED, '手机号已存在'); }
- // 2,创建用户
- let user;
- try {
- data.password = { secret: password };
- user = await this.model.create(data);
- user = _.omit(user, [ 'password' ]);
- } catch (e) {
- this.ctx.logger.error(e);
- throw new BusinessError(
- ErrorCode.SERVICE_FAULT,
- '输入信息有误,用户创建失败!'
- );
- }
- // 3,检查有没有推荐人,如果没有推荐人,那就完事了,有推荐人,还需要检查给推荐人加多少分
- if (!r_mobile) return user;
- const recommender = await this.model.findOne({ mobile: r_mobile });
- if (!recommender) {
- await this.model.deleteOne({ _id: user._id });
- throw new BusinessError(
- ErrorCode.SERVICE_FAULT,
- '推荐人信息错误,用户创建失败!'
- );
- }
- // 4,判断是129套餐,还是169套餐,如果是129套餐,那就不需要继续了
- if (set === '129') return user;
- // 根据等级,找下推荐人应该加多少分
- const { stockholder } = recommender;
- // 重新计算推荐人用户等级
- const nlevel = await this.reComputedLevel(recommender);
- recommender.level = nlevel;
- const rank = this.getRank().find(f => f.rank === nlevel);
- if (!rank) {
- // TODO 告知推荐人,等级信息有错误,中断,返回用户添加成功
- return user;
- }
- let { score } = rank;
- // 需要检查股东奖,是否需要+10
- if (stockholder) score = score + this.stockholder_point;
- else {
- // 去写检查是不是股东的问题
- const result = await this.checkStockholder(recommender);
- if (result === undefined) {
- // TODO 告知推荐人,股东检测有错误,中断,返回用户添加成功
- return user;
- }
- // 这次加上这个用户就是股东了
- if (result) {
- // 此情况主要讨论的是 9999 单时,是否加=>9999单时,不加
- recommender.stockholder = true;
- score = score + 10;
- }
- }
- // 加积分
- recommender.points = `${recommender.points + score}`;
- await recommender.save();
- const record = _.pick(recommender, [ 'mobile', 'name' ]);
- record.points = score;
- record.opera = '推荐办卡';
- record.params = { name: user.name, mobile: user.mobile };
- try {
- await this.record.create(record);
- } catch (error) {
- this.logger.error(`积分记录添加失败${JSON.stringify(record)}`);
- }
- return user;
- }
- /**
- * 计算推荐人信息的等级;找到@property的2个变量
- * @param {Object} user 推荐人信息
- * @property r_number A推出去的人数 B级总数
- * @property b_r_number B级推出去的人数 C级总数
- * @property group_number 团队完成单数: r_number + b_r_number
- * @return {Number} level 等级
- */
- async reComputedLevel(user) {
- const result = await this.getEchelon(user);
- if (!result) return;
- const { b = [], c = 0 } = result;
- /**
- * @constant Number group_number 团队完成单数
- * @type Number
- */
- const group_number = b.length + c;
- // 先用1阶条件过滤,是否满足推荐人数要求 + 是否满足团队单数要求
- let ranks = this.getRank().filter(f => b.length >= f.person && group_number >= f.group);
- // 按rank 倒序
- ranks = _.orderBy(ranks, [ 'rank' ], [ 'desc' ]);
- // 使用find查找,因为倒序排列,所以按照条件挨个比,取的就是结果
- const rank = ranks.find(f => {
- const { n_rank, n_r_person } = f;
- // 查找B梯队里,满足当前阶级要求的 B梯队职位 的人数
- const list = b.filter(bl => bl.level === n_rank);
- // 如果人数也满足要求,推荐人就应该是这个阶级了,反之继续找
- return list >= n_r_person;
- });
- if (rank) return rank.rank;
- return user.level;
- }
- /**
- * 检查该用户是否满足股东身份
- * @param {Object} user 用户
- */
- async checkStockholder(user) {
- try {
- const level = _.get(user, 'level', 1) * 1;
- if (level < this.stockholder_limit_level) return false;
- const result = await this.getEchelon(user);
- if (!result) return;
- const { b = [], c = 0 } = result;
- const group_number = b.length + c;
- return group_number > this.stockholder_limit;
- } catch (error) {
- this.ctx.logger.error(`${moment().format('YYYY-MM-DD HH:mm:ss')}-${user.name}-${user.mobile}:股东检查出错`);
- return undefined;
- }
- }
- /**
- * 检查该用户是否满足车奖
- */
- async checkCarshow() {
- const list = await this.model.find({ level: { $gte: this.car_show_limit_level }, car_show: false });
- try {
- for (const user of list) {
- const b = await this.model.count({ r_mobile: user.mobile, level: { $gte: this.car_show_b_limit_level } });
- if (b >= this.car_show_b_limit_person) {
- user.car_show = true;
- user.points = user.points + this.car_point;
- await user.save();
- // TODO 添加积分记录
- const record = _.pick(user, [ 'mobile', 'name' ]);
- record.points = this.car_point;
- record.opera = '车奖';
- try {
- await this.record.create(record);
- } catch (error) {
- this.logger.error(`积分记录添加失败${JSON.stringify(record)}`);
- }
- }
- }
- } catch (error) {
- this.ctx.logger.error(`${moment().format('YYYY-MM-DD HH:mm:ss')}-车奖检查出错`);
- return undefined;
- }
- }
- /**
- * 查找用户的梯队
- * @param {Object} user 用户(其实指的就是推荐人)
- * @return {Object} {b:b梯队列表,c:c梯队数据}
- */
- async getEchelon(user) {
- // 推荐的人 B梯队
- const b_echelon = await this.model.find({ r_mobile: user.mobile });
- // c梯队的总人数
- const c_echelon_number = await this.model.count({ r_mobile: b_echelon.map(i => i.mobile) });
- return { b: b_echelon, c: c_echelon_number };
- }
- /**
- * 等级设置
- * @property rank 等级:1,业务员;2,经理;3一星经理;4,二星经理;5,三星经理;6,四星经理;
- * @property person 该等级人数底线要求
- * @property group 该等级团队单数底线要求
- * @property n_rank 该团队中,要求B梯队中的等级
- * @property n_r_person 该团队中,要求B梯队指定等级的人数
- */
- getRank() {
- return [
- {
- rank: 1,
- person: 1,
- group: 0,
- score: 600,
- n_rank: undefined,
- n_r_person: 0,
- },
- {
- rank: 2,
- person: 3,
- group: 11,
- score: 600 + 100,
- n_rank: undefined,
- n_r_person: 0,
- },
- {
- rank: 3,
- person: 10,
- group: 111,
- score: 600 + 150,
- n_rank: 2,
- n_r_person: 1,
- },
- {
- rank: 4,
- person: 20,
- group: 555,
- score: 600 + 200,
- n_rank: 3,
- n_r_person: 2,
- },
- {
- rank: 5,
- person: 25,
- group: 1111,
- score: 600 + 250,
- n_rank: 4,
- n_r_person: 2,
- },
- {
- rank: 6,
- person: 30,
- group: 5555,
- score: 600 + 300,
- n_rank: 5,
- n_r_person: 3,
- },
- ];
- }
- }
- module.exports = CardService;
|