123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211 |
- 'use strict';
- const assert = require('assert');
- const _ = require('lodash');
- const { ObjectId } = require('mongoose').Types;
- const moment = require('moment');
- const { CrudService } = require('naf-framework-mongoose/lib/service');
- const { BusinessError, ErrorCode } = require('naf-core').Error;
- class CountService extends CrudService {
- constructor(ctx) {
- super(ctx, 'count');
- this.smodel = this.ctx.model.Student;
- this.tmodel = this.ctx.model.Trainplan;
- this.lmodel = this.ctx.model.Leave;
- this.schmodel = this.ctx.model.School;
- this.setmodel = this.ctx.model.Setting;
- }
- // 查询
- async countstudent() {
- // levelexit:退出人数 √
- // levelqj:请假人数 √
- // notrainstu:上传名单,但是未培训人数 student表中的数据不稳,后加的可能没有了.被人绑定更换也可能没有了.所以 这个数字用 student.total - user(type=4&&openid) 的结果 √
- // schstu:上传名单人数 该年度计划下,的student.total √
- // trainstu:已参加培训人数 user(type==4&&openid).total √
- // planstu:年度计划人数(重算) 根据年度计划学校的分配计算 √
- // schs:[{schname 学校名称,schnum 学校人数}] 学校上传人数 试用聚合做 √
- // 取得当前年份计划信息
- const setting = await this.setmodel.findOne();
- if (!setting) {
- throw new BusinessError(ErrorCode.DATA_NOT_EXIST, '没有找到默认设置');
- }
- const { planid } = setting;
- if (!planid) {
- throw new BusinessError(ErrorCode.DATA_NOT_EXIST, '没有找到默认年度计划');
- }
- const trainPlan = await this.tmodel.findById(planid);
- if (!trainPlan) {
- throw new BusinessError(ErrorCode.DATA_NOT_EXIST, '没有找到默认年度计划');
- }
- let { termnum } = trainPlan;
- if (!_.isArray(termnum)) {
- throw new BusinessError(ErrorCode.DATA_INVALID, '默认年度计划的期数据格式不正确');
- }
- // 转换下,因为之后用的期id不是ObjectId
- termnum = JSON.parse(JSON.stringify(termnum));
- const termids = termnum.map(i => i._id);
- const data = {};
- // 请假,退出
- const levelqj = await this.ctx.model.Leave.count({
- termid: { $in: termids },
- type: '0',
- status: '1',
- });
- const levelexit = await this.ctx.model.Leave.count({
- termid: { $in: termids },
- type: '1',
- status: '1',
- });
- data.levelqj = levelqj || 0;
- data.levelexit = levelexit || 0;
- // 参加培训的学生
- const trainstuRes = await this.ctx.model.Student.aggregate([{ $match: { planid } }, { $match: { openid: { $exists: true } } }, { $count: 'total' }]);
- const h = _.head(trainstuRes);
- if (h) {
- let { total: trainstu } = h;
- // 减去退出的学生
- trainstu = trainstu - data.levelexit || 0;
- data.trainstu = trainstu;
- } else {
- data.trainstu = 0;
- }
- // 已上传的学生总数
- const schstu = await this.ctx.model.Student.count({ planid });
- data.schstu = schstu;
- // 未参加培训的学生
- const notrainstu = schstu - data.trainstu;
- data.notrainstu = notrainstu;
- // 年度计划实际人数 这个还没用聚合,不是很优雅
- const mid = await this.ctx.model.Schtime.find({ planid });
- const planstu = mid.reduce((p, n) => p + n.arrange.reduce((np, nn) => np + (nn.number * 1 || 0), 0), 0);
- data.planstu = planstu;
- // 各个学校上传的人数
- const schs = await this.ctx.model.Student.aggregate([
- { $match: { planid } },
- { $group: { _id: '$schid', sum: { $sum: 1 } } },
- {
- $lookup: {
- from: 'school',
- localField: '_id',
- foreignField: 'code',
- as: 'school',
- },
- },
- { $unwind: '$school' },
- { $project: { _id: 0, schname: '$school.name', schnum: '$sum' } },
- ]);
- data.schs = schs;
- return data;
- }
- // 按学校id统计查询
- async countschstu({ id }) {
- // levelexit:退出人数 √
- // levelqj:请假人数 √
- // notrainstu:上传名单,但是未培训人数 student表中的数据不稳,后加的可能没有了.被人绑定更换也可能没有了.所以 这个数字用 student.total - user(type=4&&openid) 的结果 √
- // schstu:上传名单人数 该年度计划下,的student.total √
- // trainstu:已参加培训人数 user(type==4&&openid).total √
- // planstu:年度计划人数(重算) 根据年度计划学校的分配计算 √
- // leaveNum:请假人数未处理 √
- // uploadNum:计划上报未处理 √
- // 取得当前年份计划信息
- const setting = await this.setmodel.findOne();
- if (!setting) {
- throw new BusinessError(ErrorCode.DATA_NOT_EXIST, '没有找到默认设置');
- }
- const { planid, termid } = setting;
- if (!planid) {
- throw new BusinessError(ErrorCode.DATA_NOT_EXIST, '没有找到默认年度计划');
- }
- const trainPlan = await this.tmodel.findById(planid);
- if (!trainPlan) {
- throw new BusinessError(ErrorCode.DATA_NOT_EXIST, '没有找到默认年度计划');
- }
- let { termnum } = trainPlan;
- if (!_.isArray(termnum)) {
- throw new BusinessError(ErrorCode.DATA_INVALID, '默认年度计划的期数据格式不正确');
- }
- // 转换下,因为之后用的期id不是ObjectId
- termnum = JSON.parse(JSON.stringify(termnum));
- const termids = termnum.map(i => i._id);
- const data = {};
- // 请假,退出
- const levelqj = await this.ctx.model.Leave.count({
- termid: { $in: termids },
- type: '0',
- status: '1',
- schid: id,
- });
- const levelexit = await this.ctx.model.Leave.count({
- termid: { $in: termids },
- type: '1',
- status: '1',
- schid: id,
- });
- data.levelqj = levelqj || 0;
- data.levelexit = levelexit || 0;
- // 参加培训的学生
- const trainstuRes = await this.ctx.model.Student.aggregate([
- { $addFields: { u_id: { $toString: '$_id' } } },
- { $match: { planid, schid: id } },
- {
- $lookup: {
- from: 'user',
- localField: 'u_id',
- foreignField: 'uid',
- as: 'user',
- },
- },
- { $match: { 'user.type': '4', 'user.openid': { $exists: true } } },
- { $count: 'total' },
- ]);
- const h = _.head(trainstuRes);
- if (h) {
- let { total: trainstu } = h;
- // 减去退出的学生
- trainstu = trainstu - data.levelexit || 0;
- data.trainstu = trainstu;
- } else {
- data.trainstu = 0;
- }
- // 已上传的学生总数
- const schstu = await this.ctx.model.Student.count({ planid, schid: id });
- data.schstu = schstu;
- // 未参加培训的学生
- const notrainstu = schstu - data.trainstu;
- data.notrainstu = notrainstu;
- // 年度计划实际人数 这个还没用聚合,不是很优雅
- const mid = await this.ctx.model.Schtime.find({ planid, schid: id });
- const planstu = mid.reduce((p, n) => p + n.arrange.reduce((np, nn) => np + (nn.number * 1 || 0), 0), 0);
- data.planstu = planstu;
- // 请假或退出人数未处理
- const leaveNum = await this.ctx.model.Leave.count({
- termid,
- schid: id,
- status: '0',
- });
- data.leaveNum = leaveNum || 0;
- // 计划上报学校上传学生名单
- const schtime = await this.ctx.model.Schtime.findOne({ planid, schid: id }).lean();
- const uploadNum = 0;
- if (schtime && schtime.arrange) {
- for (const val of schtime.arrange) {
- const { termid, batchid } = val;
- const studentTotal = await this.ctx.model.Student.count({ termid, batchid, schid: id });
- if (studentTotal === 0) uploadNum + 1;
- }
- }
- data.uploadNum = uploadNum;
- return data;
- }
- }
- module.exports = CountService;
|