123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284 |
- 'use strict';
- const { CrudService } = require('naf-framework-mongoose-free/lib/service');
- const { BusinessError, ErrorCode } = require('naf-core').Error;
- const _ = require('lodash');
- const assert = require('assert');
- const { ObjectId } = require('mongoose').Types;
- //
- class MatchSmallGroupScheduleService extends CrudService {
- constructor(ctx) {
- super(ctx, 'matchsmallgroupschedule');
- this.model = this.ctx.model.Race.MatchSmallGroupSchedule;
- this.baseUserModel = this.ctx.model.Base.User;
- this.userModel = this.ctx.model.Race.User;
- this.teamApplyModel = this.ctx.model.Race.TeamApply;
- // 加入框架
- this.defaultModule = this.app.config.defaultModel || 'Race';
- }
- async saveAll(data) {
- for (const i of data) {
- const { _id } = i;
- if (!_id) {
- // TODO: 创建前:需要检查这些人员是否出现在这个项目中的别的组中
- await this.model.create(i);
- } else {
- await this.model.updateOne({ _id }, i);
- }
- }
- }
- async beforeCreate(body) {
- // 检查数据是否有重复,如果符合检查重复条件,就把之前的删了,用新来的
- const { match_id, group_id, project_id, team_id, player_one, player_two } = body;
- const query = {
- match_id,
- group_id,
- project_id,
- team_id,
- $or: [
- { player_one, player_two },
- { player_one: player_two, player_two: player_one },
- ],
- };
- const d = await this.model.findOne(query);
- if (d) await this.model.deleteOne(query);
- return body;
- }
- async beforeQuery(filter) {
- // 可查询自己的赛程-user_id / 某人的赛程
- // const { user_id, user_name } = filter;
- const user_name = _.get(filter, 'user_name');
- let user_id = _.get(filter, 'user_id');
- // 没有user_id就不需要处理查询条件
- if (!user_id && !user_name) return filter;
- const usualCondition = _.pick(filter, [ 'match_id', 'group_id', 'project_id' ]);
- if (user_name) {
- // 要先找比赛用户模块的数据id
- const baseUser = await this.baseUserModel.findOne({ name: new RegExp(user_name) }, { _id: 1 });
- if (!baseUser) delete filter.user_name;
- delete filter.user_name;
- const baseUserId = baseUser._id;
- const raceUser = await this.userModel.findOne({ user_id: baseUserId, type: '0' });
- if (raceUser) user_id = raceUser._id;
- }
- if (user_id) {
- // 需要查:该用户是 单打 和 双打 的情况
- // 单打,直接user_id 为player_one/two 就可以,双打需要查teamApply
- // 所以先把user_id添加进查询范围里
- let probablyList = [ user_id ];
- // 尽可能的缩小查询范围
- // 接着找组队申请中和该用户有关的人
- const teamApplyList = await this.teamApplyModel.find({ ...usualCondition, status: '1', $or: [{ one_member_id: user_id }, { two_member_id: user_id }] }, { _id: 1 });
- const teamApplyIds = teamApplyList.map(i => i._id);
- probablyList.push(...teamApplyIds);
- // 删除user_id.会造成错误
- delete filter.user_id;
- // 添加该用户正确的范围条件
- probablyList = probablyList.map(i => ObjectId(i).toString());
- filter.$or = [{ player_one: { $in: probablyList } }, { player_two: { $in: probablyList } }];
- }
- return filter;
- }
- turnFilter(filter) {
- const str = /^%\S*%$/;
- // $是mongodb固定条件,不用处理;大多为手写特殊处理过的条件
- let keys = Object.keys(filter).filter(f => !f.includes('$'));
- for (const key of keys) {
- const res = key.match(str);
- if (res) {
- const newKey = key.slice(1, key.length - 1);
- if (!ObjectId.isValid(filter[key])) filter[newKey] = new RegExp(filter[key]);
- delete filter[key];
- }
- }
- // 再次过滤数据,将数组的数据都变成{$in:value},因为查询变成了聚合查询
- // $是mongodb固定条件,不用处理;大多为手写特殊处理过的条件
- keys = Object.keys(filter).filter(f => !f.includes('$'));
- for (const key of keys) {
- if (_.isArray(filter[key])) {
- filter[key] = { $in: filter[key] };
- } else if (filter[key] === 'true' || filter[key] === 'false') {
- // 布尔类型的值检查,如果是布尔类型,则将字符串转为布尔
- filter[key] = filter[key] === 'true';
- }
- }
- return filter;
- }
- async afterQuery(filter, data) {
- data = JSON.parse(JSON.stringify(data));
- for (const d of data) {
- const { player_type, player_one, player_two, referee_id } = d;
- if (player_type === 'User') {
- const pouid = _.get(player_one, 'user_id');
- const user1 = await this.baseUserModel.findById(pouid);
- d.player_one_name = _.get(user1, 'name');
- d.player_one = _.get(d, 'player_one._id');
- const ptuid = _.get(player_two, 'user_id');
- const user2 = await this.baseUserModel.findById(ptuid);
- d.player_two_name = _.get(user2, 'name');
- d.player_two = _.get(d, 'player_two._id');
- } else if (player_type === 'TeamApply') {
- d.player_one_name = `${_.get(d, 'player_one.one_member_name')}-${_.get(d, 'player_one.two_member_name')}`;
- d.player_one = _.get(d, 'player_one._id');
- d.player_two_name = `${_.get(d, 'player_two.one_member_name')}-${_.get(d, 'player_two.two_member_name')}`;
- d.player_two = _.get(d, 'player_two._id');
- }
- const referee = await this.userModel.findById(referee_id).populate({
- path: 'user_id',
- model: this.baseUserModel,
- });
- d.referee_id_name = _.get(referee, 'user_id.name');
- }
- return data;
- }
- async fetch(filter, { sort, desc, projection } = {}) {
- assert(filter);
- filter = await this.beforeFetch(filter);
- const { _id, id } = filter;
- if (_id || id) filter = { _id: ObjectId(_id || id) };
- // 处理排序
- if (sort && _.isString(sort)) {
- sort = { [sort]: desc ? -1 : 1 };
- } else if (sort && _.isArray(sort)) {
- sort = sort.map(f => ({ [f]: desc ? -1 : 1 })).reduce((p, c) => ({ ...p, ...c }), {});
- }
- const { refMods, populate } = await this.getRefMods();
- let res = await this.model.findOne(filter, projection).populate(populate).exec();
- res = JSON.parse(JSON.stringify(res));
- for (const obj of refMods) {
- const { col, prop, type } = obj;
- if (!prop) continue;
- if (_.isArray(prop)) {
- for (const p of prop) {
- if (type === 'String') res[`${col}_${p}`] = _.get(res, `${col}.${p}`);
- if (type === 'Array') {
- const list = [];
- const oList = _.get(res, `${col}`);
- for (const d of oList) {
- const obj = { _id: d._id };
- obj[p] = _.get(d, p);
- list.push(obj);
- }
- res[`${col}_${p}`] = list;
- }
- }
- res[col] = _.get(res, `${col}._id`);
- }
- }
- res = await this.afterFetch(filter, res);
- return res;
- }
- async afterFetch(filter, d) {
- const { player_type, player_one, player_two, referee_id } = d;
- if (player_type === 'User') {
- const pouid = _.get(player_one, 'user_id');
- const user1 = await this.baseUserModel.findById(pouid);
- d.player_one_name = _.get(user1, 'name');
- d.player_one = _.get(d, 'player_one._id');
- const ptuid = _.get(player_two, 'user_id');
- const user2 = await this.baseUserModel.findById(ptuid);
- d.player_two_name = _.get(user2, 'name');
- d.player_two = _.get(d, 'player_two._id');
- } else if (player_type === 'TeamApply') {
- d.player_one_name = `${_.get(d, 'player_one.one_member_name')}-${_.get(d, 'player_one.two_member_name')}`;
- d.player_one = _.get(d, 'player_one._id');
- d.player_two_name = `${_.get(d, 'player_two.one_member_name')}-${_.get(d, 'player_two.two_member_name')}`;
- d.player_two = _.get(d, 'player_two._id');
- }
- const referee = await this.userModel.findById(referee_id).populate({
- path: 'user_id',
- model: this.baseUserModel,
- });
- d.referee_id_name = _.get(referee, 'user_id.name');
- return d;
- }
- // async getRefMods() {
- // const mod = await this.getModel();
- // const refMods = [];
- // const populate = [];
- // for (const key in mod) {
- // const { ref, refPath } = mod[key];
- // if (!ref && !refPath) continue;
- // const obj = { col: key, prop: mod[key].getProp, type: mod[key].type.name };
- // refMods.push(obj);
- // // 检查ref/refPath是否还有嵌套
- // if (ref) {
- // // 递归查找ref的关系,构造ref关系树图
- // const res = this.checkSchema(ref);
- // // console.log(res);
- // }
- // }
- // return { refMods, populate };
- // }
- // 组成子 populate => {path,model}
- checkSchema(thisRef, path) {
- const { schema } = this.findModel(thisRef, path);
- for (const key in schema) {
- const { ref, refPath } = schema[key];
- if (!ref && !refPath) continue;
- const obj = {};
- if (ref) {
- const arr = ref.split('.').map(i => _.upperFirst(i));
- obj.ref = _.upperFirst(_.last(arr));
- let mpath = path;
- // 如果有path,就应该不会有arr.length>0的情况
- if (arr.length > 0) {
- // 说明是有路径的,需要将路径也填充
- arr.pop();
- mpath = arr.join('.');
- }
- // 递归寻找ref
- const { schema: sch } = this.checkSchema(obj.ref, mpath);
- console.log(key, ref);
- console.log(sch);
- // for (const key in sch) {
- // const obj = sch[key];
- // const populate = this.dealSchema(obj);
- // }
- }
- }
- return schema;
- }
- // dealSchema(schema) {
- // }
- findModel(modelName, path = this.defaultModule) {
- // 有没有默认路径,将路径整合进去
- const modelPath = [];
- if (path) modelPath.push(...path.split('.'));
- modelPath.push(_.upperFirst(modelName));
- const modelPathStr = modelPath.join('.');
- const m = _.get(this.ctx.model, modelPathStr);
- if (m) return { schema: _.get(m, 'prototype.schema.obj'), path: modelPathStr };
- let returnData;
- // 去掉要找到的目标model
- modelPath.pop();
- const dir = modelPath.join('.');
- const rootModel = _.get(this.ctx.model, dir, this.ctx.model);
- for (const mn in rootModel) {
- const type = typeof rootModel[mn];
- if (type === 'object') {
- // rootModel[mn] 是目录,要进入目录里面找内容
- returnData = this.findModel(modelName, mn);
- }
- // 没有 else 的原因是,对于model来说;路径是object类型,model是function类型,而model在 上面 有关m变量 部分已经处理完,不会有其他形式
- }
- return returnData;
- }
- }
- module.exports = MatchSmallGroupScheduleService;
|