'use strict'; const assert = require('assert'); const _ = require('lodash'); const { ObjectId } = require('mongoose').Types; const { CrudService } = require('naf-framework-mongoose/lib/service'); const { BusinessError, ErrorCode } = require('naf-core').Error; class ClassService extends CrudService { constructor(ctx) { super(ctx, 'class'); this.model = this.ctx.model.Class; this.stumodel = this.ctx.model.Student; this.lessmodel = this.ctx.model.Lesson; this.umodel = this.ctx.model.User; this.tmodel = this.ctx.model.Trainplan; this.gmodel = this.ctx.model.Group; this.heamodel = this.ctx.model.Headteacher; this.teamodel = this.ctx.model.Teacher; this.locamodel = this.ctx.model.Location; } async divide(data) { const { planid, termid } = data; assert(planid, '计划id为必填项'); assert(termid, '期id为必填项'); // 先自动生成班级 await this.autoclass(planid, termid); // 根据计划id与期id查询所有批次下的班级 const newclass = await this.model.find({ planid, termid }); if (!newclass) { throw new BusinessError(ErrorCode.DATA_NOT_EXIST, '班级信息不存在'); } // 根据计划和期查询所有上报的学生 并按照学校排序 const newstudent = await this.stumodel.find({ termid }).sort({ schid: 1 }); if (!newstudent) { throw new BusinessError(ErrorCode.DATA_NOT_EXIST, '学生信息不存在'); } let _students = _.map(newstudent, 'id'); for (const _class of newclass) { // 取得班级人数 const stunum = _class.number; // 取出相同类型的学生 const studentids = await this.getstutype(_students, _class.type); // 取出班级人数下的学生id const beforestu = _.take(studentids, stunum); // 将取出的数据调用更新学生的班级信息方法 await this.studentup(_class.id, _class.batchid, beforestu); // 将班级自动分为组 await this.groupcreate(termid, _class.batchid, _class.id); // 取出的学生数据从原数据中删除 _students = _.difference(_students, beforestu); } // 判断学生是否有剩余 const stulen_ = _students.length; if (stulen_ > 0) { // 判断共有多少班级 // 判断学生数与班级数,当小于或等于班级数 将班级直接分配给学生 const classlength = newclass.length; // 循环取得学生id并分配班级 let cindex_ = 0; for (const stuid of _students) { const student = await this.stumodel.findById(stuid); if (student) { const cla_ = newclass[cindex_]; student.classid = cla_.classid; student.batchid = cla_.batchid; await student.save(); cindex_ = cindex_ + 1; if (cindex_ === classlength - 1) { cindex_ = 0; } } } } } // 取得同样类型的学生 async getstutype(_students, type) { const data = []; for (const stuid of _students) { const student = await this.stumodel.findById(stuid); if (student && student.type === type) { data.push(stuid); } } return data; } // 自动生成班级私有方法 async autoclass(planid, termid) { // 删除所有计划下的班级 await this.model.deleteMany({ planid, termid }); // 根据批次id取得当前批次具体信息 const res = await this.tmodel.findById(planid); if (!res) { throw new BusinessError(ErrorCode.DATA_NOT_EXIST, '全年计划信息不存在'); } // 循环出所有班级进行添加操作 const term = await res.termnum.id(termid); let yclocationid = ''; // 用餐地点 let kzjhlocationid = ''; // 拓展计划地点 let kbyslocationid = ''; // 开班仪式地点 let jslocationid = ''; // 教室位置 const locations = await this.locamodel.find(); const jslocationids = _.filter(locations, { type: '0' }); const kbyslocationids = _.filter(locations, { type: '1' }); const kzjhlocationids = _.filter(locations, { type: '2' }); const yclocationids = _.filter(locations, { type: '3' }); for (const batch of term.batchnum) { const classs = await batch.class; for (const cla of classs) { // 取得班级各个地点 // 同一地点同期只能使用一次 if (jslocationids.length > 0) { jslocationid = jslocationids[0].id; _.remove(jslocationids, { id: jslocationid }); } if (kbyslocationids.length > 0) { kbyslocationid = kbyslocationids[0].id; _.remove(kbyslocationids, { id: kbyslocationid }); } if (kzjhlocationids.length > 0) { kzjhlocationid = kzjhlocationids[0].id; _.remove(kzjhlocationids, { id: kzjhlocationid }); } if (yclocationids.length > 0) { yclocationid = yclocationids[0].id; _.remove(yclocationids, { id: yclocationid }); } const newdata = { name: cla.name, number: cla.number, batchid: batch.id, termid: term.id, planid: res.id, type: cla.type, headteacherid: cla.headteacherid, jslocationid, kbyslocationid, kzjhlocationid, yclocationid }; await this.model.create(newdata); } } } // 根据传入的学生列表和班级id更新学生信息 async studentup(classid, batchid, beforestu) { // 循环学生id for (const stuid of beforestu) { const student = await this.stumodel.findById(stuid); if (student) { student.classid = classid; student.batchid = batchid; await student.save(); } } } // 自动分组 async groupcreate(termid, batchid, classid) { const group = await this.gmodel.find({ termid, batchid, classid }); if (group.length === 0) { for (let i = 1; i < 8; i++) { const name = i + '组'; const newdata = { name, termid, batchid, classid }; await this.gmodel.create(newdata); } } } // 根据传入的学生列表和班级id更新学生信息 async studentupclass({ id }, data) { assert(id, '班级id为必填项'); // 根据全年计划表id查出对应的全年计划详细信息 const trainplan = await this.tmodel.findOne({ 'termnum.batchnum.class._id': ObjectId(id) }); if (!trainplan) { throw new BusinessError(ErrorCode.DATA_NOT_EXIST, '全年计划信息不存在'); } // 取得计划期批次信息 let termid = ''; let batchid = ''; let classname = ''; let class_ = {}; for (const term of trainplan.termnum) { for (const batch of term.batchnum) { const _class = await batch.class.id(id); if (_class) { termid = term.id; batchid = batch.id; classname = _class.name; class_ = _class; break; } } } if (!class_) { throw new BusinessError(ErrorCode.DATA_NOT_EXIST, '班级信息不存在'); } let classid_ = ''; if (classname) { const cla_ = await this.model.findOne({ termid, batchid, name: classname }); if (cla_) { classid_ = cla_.id; } else { const newdata = { name: class_.name, number: class_.number, batchid, termid, planid: trainplan.id, type: class_.type, }; const rescla = await this.model.create(newdata); if (rescla) { classid_ = rescla.id; } } } if (classid_) { // 循环学生id for (const stuid of data) { const student = await this.stumodel.findById(stuid); if (student) { student.classid = classid_; await student.save(); } } } } async notice(data) { for (const classid of data.classids) { // 根据班级id找到需要通知的班级 const _class = await this.model.findById(classid); const { headteacherid } = _class; // 根据班级id找到对应的课程表 const lesson = await this.lessmodel.findOne({ classid }); if (lesson) { const lessons = lesson.lessons; const remark = '感谢您的使用'; const date = await this.ctx.service.util.updatedate(); const detail = '班级各项信息已确认,请注意查收'; // 遍历班级授课教师发送通知 for (const lessoninfo of lessons) { const teaid = lessoninfo.teaid; const _teacher = await this.umodel.findOne({ uid: teaid, type: '3' }); if (_teacher) { const teaopenid = _teacher.openid; this.ctx.service.weixin.sendTemplateMsg(this.ctx.app.config.REVIEW_TEMPLATE_ID, teaopenid, '您有一个新的通知', detail, date, remark, classid); } } // 给班主任发送通知 const _headteacher = await this.umodel.findOne({ uid: headteacherid, type: '1' }); if (_headteacher) { const headteaopenid = _headteacher.openid; this.ctx.service.weixin.sendTemplateMsg(this.ctx.app.config.REVIEW_TEMPLATE_ID, headteaopenid, '您有一个新的通知', detail, date, remark, classid); } // 根据班级的期id查询对应的培训计划 const trainplan = await this.tmodel.findOne({ 'termnum._id': _class.termid }); const term = await trainplan.termnum.id(_class.termid); const batch = await term.batchnum.id(_class.batchid); const startdate = batch.startdate; const classname = _class.name; // 给班级所有学生发送邮件通知 const students = await this.stumodel.find({ classid }); for (const student of students) { const { email, name } = student; const subject = '吉林省高等学校毕业生就业指导中心通知'; const text = name + '您好!\n欢迎参加由吉林省高等学校毕业生就业指导中心举办的“双困生培训会”。\n您所在的班级为:' + classname + '\n班级开课时间为:' + startdate; this.ctx.service.util.sendMail(email, subject, text); } } } } async uptea(data) { for (const _data of data) { const classInfo = await this.model.findById(_data.id); classInfo.headteacherid = _data.headteacherid; await classInfo.save(); } } async query({ skip, limit, ...info }) { const classes = await this.model.find(info).skip(Number(skip)).limit(Number(limit)); const data = []; for (const _class of classes) { const classInfo = await this.fetch({ id: _class.id }); data.push(classInfo); } return data; } async fetch({ id }) { const classInfo = _.cloneDeep(JSON.parse(JSON.stringify(await this.model.findById(id)))); const trainplan = await this.tmodel.findById(classInfo.planid); if (trainplan) { const term = _.filter(trainplan.termnum, item => item.id === classInfo.termid); if (term.length > 0) { classInfo.term = term[0].term; const batch = _.filter(term[0].batchnum, item => item.id === classInfo.batchid); if (batch.length > 0) { classInfo.batch = batch[0].batch; classInfo.startdate = batch[0].startdate; classInfo.enddate = batch[0].enddate; } } } if (classInfo.yclocationid) { classInfo.yclocation = (await this.locamodel.findById(classInfo.yclocationid)).name; } if (classInfo.kzjhlocationid) { classInfo.kzjhlocation = (await this.locamodel.findById(classInfo.kzjhlocationid)).name; } if (classInfo.kbyslocationid) { classInfo.kbyslocation = (await this.locamodel.findById(classInfo.kbyslocationid)).name; } if (classInfo.jslocationid) { classInfo.jslocation = (await this.locamodel.findById(classInfo.jslocationid)).name; } if (classInfo.headteacherid) { classInfo.headteacher = (await this.heamodel.findById(classInfo.headteacherid)).name; } if (classInfo.lyteacherid) { let res = await this.teamodel.findById(classInfo.lyteacherid); if (!res) res = await this.heamodel.findById(classInfo.lyteacherid); if (res)classInfo.lyteacher = res.name; } return classInfo; } async upclasses(data) { for (const _data of data) { await this.model.findByIdAndUpdate(_data.id, _data); } } async classinfo({ id: classid }) { const _classes = await this.model.findById(classid); // 班级信息 const classes = _.cloneDeep(JSON.parse(JSON.stringify(_classes))); // 学生信息 const students = await this.stumodel.find({ classid }); // 所有用户信息 const users = await this.umodel.find(); if (students) { for (const stu of students) { const user = users.find(item => item.uid === stu.id); if (user && user.openid) { const _stu = _.cloneDeep(JSON.parse(JSON.stringify(stu))); _stu.hasuserinfo = '1'; _.remove(students, stu); students.push(_stu); } } classes.students = students; } // 班主任信息 let headteacher; if (classes.headteacherid) { headteacher = await this.heamodel.findById(classes.headteacherid); } // 礼仪课老师信息 let lyteacher; if (classes.lyteacherid) { lyteacher = await this.heamodel.findById(classes.lyteacherid); if (!lyteacher) { lyteacher = await this.teamodel.findById(classes.lyteacherid); } } // 教课老师信息 let teachers = []; const lessones = await this.lessmodel.findOne({ classid }); if (lessones) { for (const lesson of lessones.lessons) { if (lesson.teaid) { const teacher = await this.teamodel.findById(lesson.teaid); teachers.push(teacher); } } } teachers.push(lyteacher); teachers.push(headteacher); teachers = _.uniq(_.compact(teachers)); for (const tea of teachers) { const user = users.find(item => item.uid === tea.id); console.log(user); if (user && user.openid) { const _tea = _.cloneDeep(JSON.parse(JSON.stringify(tea))); _tea.hasuserinfo = '1'; _.remove(teachers, tea); teachers.push(_tea); } } classes.teachers = teachers; return classes; } } module.exports = ClassService;