'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; const moment = require('moment'); class TeaplanService extends CrudService { constructor(ctx) { super(ctx, 'teaplan'); this.model = this.ctx.model.Teaplan; this.hmodel = this.ctx.model.Headteacher; this.tmodel = this.ctx.model.Trainplan; this.cmodel = this.ctx.model.Class; this.dmodel = this.ctx.model.Department; this.submodel = this.ctx.model.Subject; this.teamodel = this.ctx.model.Teacher; } // 查询所有班主任带是否能带班标记 async findteacher({ planid, termid, batchid }) { // 查询所有班主任信息 const headteachers = await this.hmodel.find(); // 根据批次id取得当前批次具体信息 const trainplan = await this.tmodel.findById(planid); if (!trainplan) { throw new BusinessError(ErrorCode.DATA_NOT_EXIST, '全年计划信息不存在'); } const term = await trainplan.termnum.id(termid); if (!term) { throw new BusinessError( ErrorCode.DATA_NOT_EXIST, '全年计划内期信息不存在' ); } const batch = await term.batchnum.id(batchid); if (!batch) { throw new BusinessError( ErrorCode.DATA_NOT_EXIST, '全年计划内批次信息不存在' ); } const newheadteachers = []; // 遍历班主任信息 for (const headteacher of headteachers) { // 查询某班主任对应的班主任全年计划表 const teaplan = await this.model.findOne({ headteacherid: headteacher.id, }); if (teaplan) { // 取得所有不能排班的日期列表 const nodates = teaplan.nodate; const iswork = await this.teacheriswork( nodates, batch.startdate, batch.enddate ); if (iswork) { newheadteachers.push(headteacher); } else { newheadteachers.push({ ...JSON.parse(JSON.stringify(headteacher)), disabled: true, }); } } else { newheadteachers.push(headteacher); } } return newheadteachers; } // 判断当前日期是否在两个日期之间 async betweendate(curdate, startdate, enddate) { // 比较开始日期,如果小于0 为不在此区间 // 比较结束日期 如果大于0 为不在此区间 const sres = moment(curdate).diff(moment(startdate), 'days'); const eres = moment(curdate).diff(moment(enddate), 'days'); let result = true; if (sres < 0 || eres > 0) { result = false; } return result; } // 判断班主任不能带班日期是否在批次日期里 async teacheriswork(nodates, startdate, enddate) { let result = true; for (const nodate of nodates) { const res = await this.betweendate(nodate, startdate, enddate); if (res) { result = false; break; } } return result; } async divide({ trainplanid }) { const data = []; // 根据全年计划表id查出对应的全年计划详细信息 const trainplan = await this.tmodel.findById(trainplanid); // 查询本培训计划中班主任全年计划表的全部信息 const teaplanList = await this.model.find({ trainplanid }); // 查询所有班主任信息 const headteacherList = await this.hmodel.find(); // for (const teaplan of teaplanList) { // // 过滤出班主任信息表中id为此班主任全年计划信息班主任id的数据 // const headteacherInfo = _.filter(headteacherList, item => item.id === teaplan.headteacherid); // // 如果班主任信息列表中班主任上报了班主任全年计划,将其移除 // if (headteacherInfo.length === 0) { // _.remove(headteacherList, item => item.id === teaplan.headteacherid); // } // } // 遍历所有批次信息 // 将全年计划中的批次信息取出放在一个数组中 for (const term of trainplan.termnum) { for (const batch of term.batchnum) { const teaListAll = _.cloneDeep( JSON.parse(JSON.stringify(headteacherList)) ); for (const teaplan of teaplanList) { if (teaplan.nodate && teaplan.nodate.length > 0) { // 遍历班主任全年计划表中的不能上课的日期 for (const nodate of teaplan.nodate) { // 如果不能上课的日期在该批次的开始时间和结束时间中,将该班主任从班主任列表中删除 if ( moment(nodate).isBetween( batch.startdate, batch.enddate, null, '[]' ) ) { // const headteacher_ = await this.hmodel.findById(teaplan.headteacherid); // if (headteacher_) { // teaListAll.push(headteacher_); // } _.remove( teaListAll, item => item.id === teaplan.headteacherid ); } } } } // 将班主任排班次数填入数组中 let teaListAll_ = []; for (const teac of teaListAll) { // 计算出每个班主任担任过班主任的次数 const teacount = await this.cmodel.count({ headteacherid: teac.id }); const newdata = { ...JSON.parse(JSON.stringify(teac)), teacount }; teaListAll_.push(newdata); } // 将班主任按排次数排序 teaListAll_ = _.orderBy(teaListAll_, [ 'teacount' ], [ 'asc' ]); // 查出该批次下所有的班级 const classList = await batch.class; console.log(classList); for (const _class of classList) { // 取出所有部门和部门可用人数 const departmentList = await this.departmentcount(teaListAll_); let index = 0; for (const _tea of teaListAll_) { // 过滤出当前教师的部门和部门可用人数 const deptinfo = _.find(departmentList, function(o) { return o.deparmentid === _tea.department; }); if (deptinfo.dcount - index > 1) { _class.headteacherid = _tea.id; _.remove(teaListAll_, item => item.id === _tea.id); _.remove(teaListAll, item => item.id === _tea.id); index = index + 1; break; } } } } } return await trainplan.save(); } // 判断两个时间段是否有重合部分 async isrepeat(startdate1, enddate1, startdate2, enddate2) { let result = true; if (moment(enddate1).isSameOrBefore(startdate2)) { result = false; } if (moment(startdate1).isSameOrAfter(enddate2)) { result = false; } return result; } // 查询传递的班主任列表中每个部门的人数以及每个部门的总人数 // teaList 传递的教师列表 dnum 传递的教师列表中各部门的人数 dcount 各部门的总人数 async departmentcount(teaList) { let departmentList = []; for (const teaplan of teaList) { departmentList.push({ deparmentid: teaplan.department }); } // 将数组去重 departmentList = _.uniqWith(departmentList, _.isEqual); for (const department of departmentList) { // 计算出能该批次能上课的班主任中各部门有多少人 const dnum = _.filter( teaList, item => item.department === department.deparmentid ).length; department.dnum = dnum; // 计算出各部门有多少人 const dcount = await this.hmodel.count({ department: department.deparmentid, }); department.dcount = dcount; } return departmentList; } async arrangeteacher({ planid }) { const trainplan = await this.tmodel.findOne({ id: planid }); if (!trainplan) { throw new BusinessError(ErrorCode.DATA_EXISTED, '年度计划不存在'); } // 查找所有教师列表 const teacherList = await this.teamodel.find(); // 查找所有教师上报列表 const teaplanList = await this.model.find(); // 课程 const subjectList = await this.submodel.find(); const termList = _.cloneDeep(trainplan.termnum); const { termnum } = termList; if (!termnum) return; // 整理出课表 const arr = []; for (const t of termnum) { const { batchnum, term, _id: termid } = t; // 班级和课程一一匹配显示在列表上 for (const b of batchnum) { const { class: classes, lessons, startdate, enddate, _id: batchid } = b; const claslesList = this.setList(term, termid, batchid, classes, lessons); arr.push(...claslesList); } } // 安排后的课表 const afterList = []; // 排课 for (const l of arr) { const { termid, subid, day: date, teaid } = l; if (teaid) { afterList.push(l); continue; } const subject = subjectList.find(f => ObjectId(subid).equals(f._id)); if (subject.need_teacher !== '0') continue; // 申请该天,该科目的教师,并查出教师的名字,分数;并按分数排序 let applyList = teaplanList.filter(f => f.termid === termid && f.subid === subid && f.date === date); applyList = applyList.map(i => { const r = this.teacherList.find(f => ObjectId(i.teacherid).equals(f._id)); if (r) { const { name: teaname, xsscore: score } = r; i.teaname = teaname; i.score = score * 1; } return i; }); applyList = _.orderBy(applyList, [ 'score' ], [ 'desc' ]); // 依次循环申请的教师列表,往这个课程安排中放教师 for (const atea of applyList) { // 先查询,该教师,是否在今天有安排 const tr = afterList.find(f => f.teaid === atea.teacherid && f.day === atea.date); if (tr) continue; else { l.teaid = tr.teacherid; l.teaname = tr.teaname; break; } } afterList.push(l); } // 将afterList还原回正常的termnum let newTermnum = []; for (const l of afterList) { const { termid, batchid, classid, ...info } = l; const updata = _.pick(info, [ 'day', 'subid', 'subname', 'teaid', 'teaname', 'time' ]); newTermnum = trainplan.termnum.map(t => { // 找到期 if (ObjectId(termid).equals(t._id)) { t.batchnum = t.batchnum.map(b => { if (ObjectId(batchid).equals(b._id)) { // 找到批次 b.class = b.class.map(c => { if (ObjectId(classid).equals(c._id)) { if (c.lessons) { // 说明有课程安排,找有没有重复的,没有就推进去,有就更改,subid查 const r = c.lessons.find(f => f.subid === updata.subid); if (r) { const rindex = c.lessons.findIndex( f => f.subid === updata.subid ); c.lessons[rindex] = updata; } else { c.lessons.push(updata); } } else { // 说明没有课程安排,放进去一条保存 c.lessons = [ updata ]; } } return c; }); } return b; }); } return t; }); } // 保存至计划 trainplan.termnum = newTermnum; return await trainplan.save(); } setList(term, termid, batchid, classes, lessonTemplate) { const arr = []; // 班级和课程匹配 for (const cla of classes) { cla.term = term; cla.termid = termid; cla.batchid = batchid; const { lessons } = cla; if (!lessons) cla.lessons = lessonTemplate; cla.lessons.map(i => { let obj = _.omit(cla, [ 'lessons' ]); obj = { ...obj, ...i, classid: _.clone(cla._id) }; arr.push(obj); }); } return arr; } } module.exports = TeaplanService;