bedroom.js 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268
  1. 'use strict';
  2. const assert = require('assert');
  3. const _ = require('lodash');
  4. const { ObjectId } = require('mongoose').Types;
  5. const { CrudService } = require('naf-framework-mongoose/lib/service');
  6. const { BusinessError, ErrorCode } = require('naf-core').Error;
  7. class BedroomService extends CrudService {
  8. constructor(ctx) {
  9. super(ctx, 'bedroom');
  10. this.model = this.ctx.model.Bedroom;
  11. this.smodel = this.ctx.model.Student;
  12. this.tmodel = this.ctx.model.Trainplan;
  13. this.cmodel = this.ctx.model.Class;
  14. this.umodel = this.ctx.model.User;
  15. this.ctmodel = this.ctx.model.Classtype;
  16. this.nmodel = this.ctx.model.Notice;
  17. }
  18. // 根据班级id查找班级下所有寝室列表并查询出寝室下学生信息
  19. async roomstu({ id }) {
  20. // 通过班级id查询学生表信息
  21. const students = await this.smodel.find({ classid: id });
  22. const _bedrooms = _.map(students, 'bedroom');
  23. // 取得无重复的寝室号
  24. const bedrooms = _.uniq(_bedrooms);
  25. const data = [];
  26. // 根据寝室号 取得相应的学生信息
  27. for (const elm of bedrooms) {
  28. const stus = students.filter(item => item.bedroom === elm);
  29. const newdata = { bedroom: elm, stus };
  30. data.push(newdata);
  31. }
  32. return data;
  33. }
  34. async ibeacon(data) {
  35. assert(data.openid, '用户信息不能为空');
  36. // 通过openid取得学生信息
  37. const user = await this.ctx.service.user.findByOpenid(data.openid);
  38. if (!user) {
  39. throw new BusinessError(ErrorCode.DATA_NOT_EXIST, '用户不存在');
  40. }
  41. const student = await this.smodel.findById(user.uid);
  42. if (!student) {
  43. throw new BusinessError(ErrorCode.DATA_NOT_EXIST, '学生信息不存在');
  44. }
  45. const beedroom = await this.model.findOne({ code: student.bedroom });
  46. if (!beedroom) {
  47. throw new BusinessError(ErrorCode.DATA_NOT_EXIST, '寝室信息不存在');
  48. }
  49. return { data: { ibeacon: beedroom.ibeacon } };
  50. }
  51. // 一键分寝
  52. async apart(data) {
  53. const { trainplanid, termid, batchid } = data;
  54. assert(trainplanid, 'trainplanid不能为空');
  55. assert(termid, 'termid不能为空');
  56. assert(batchid, 'batchid不能为空');
  57. // 根据计划id取得当前计划
  58. const trainplan = await this.tmodel.findById(trainplanid);
  59. // 根据期id取得当前期信息
  60. const term = trainplan.termnum.find(p => p.id === termid);
  61. // 根据批次id查询批次信息
  62. const _batch = term.batchnum.find(p => p.id === batchid);
  63. // 查询所有寝室列表
  64. const bedroomList = await this.model
  65. .find({ batch: _batch.batch, status: '0' })
  66. .sort({ floor: -1 });
  67. // 循环所有当前批次下的寝室列表进行分寝处理
  68. const studentList = await this.getstudents(termid, batchid);
  69. for (const bedroom of bedroomList) {
  70. // 判断当前寝室号是否已有
  71. // 根据期id查找所有当期学生列表
  72. const _stu = _.filter(studentList, { bedroom: bedroom.code });
  73. if (bedroom.number !== _stu.length) {
  74. let i = 0;
  75. let _gender = '';
  76. for (const stud of studentList) {
  77. if (stud.bedroom) {
  78. if (stud.bedroom === bedroom.code) {
  79. i = i + 1;
  80. }
  81. continue;
  82. }
  83. if (i === 0) {
  84. if (!bedroom.gender) {
  85. stud.bedroomid = bedroom.id;
  86. stud.bedroom = bedroom.code;
  87. await stud.save();
  88. i = i + 1;
  89. _gender = stud.gender;
  90. } else {
  91. if (bedroom.gender === stud.gender) {
  92. stud.bedroomid = bedroom.id;
  93. stud.bedroom = bedroom.code;
  94. await stud.save();
  95. i = i + 1;
  96. _gender = stud.gender;
  97. }
  98. }
  99. } else if (i < bedroom.number) {
  100. if (_gender === stud.gender) {
  101. stud.bedroomid = bedroom.id;
  102. stud.bedroom = bedroom.code;
  103. await stud.save();
  104. i = i + 1;
  105. }
  106. } else if (i === bedroom.number) {
  107. i = 0;
  108. break;
  109. }
  110. }
  111. }
  112. }
  113. // 取得当前批次的所有班级
  114. const classes = await this.cmodel.find({ batchid });
  115. const detail = '班级学生名单与寝室安排已确认,请及时查收';
  116. const nres = await this.nmodel.create({
  117. planyearid: trainplan.planyearid,
  118. planid: trainplanid,
  119. termid,
  120. noticeid: 'system',
  121. content: detail,
  122. type: '5',
  123. });
  124. for (const _class of classes) {
  125. // 取得每个班级的班主任id
  126. const headteacherid = _class.headteacherid;
  127. const headteacher = await this.umodel.findOne({
  128. uid: headteacherid,
  129. type: '1',
  130. });
  131. if (headteacher && headteacher.openid) {
  132. const openid = headteacher.openid;
  133. const remark = '感谢您的使用';
  134. const date = await this.ctx.service.util.updatedate();
  135. this.ctx.service.weixin.sendTemplateMsg(
  136. this.ctx.app.config.REVIEW_TEMPLATE_ID,
  137. openid,
  138. '您有一个新的通知',
  139. detail,
  140. date,
  141. remark,
  142. _class.id
  143. );
  144. nres.notified.push({
  145. notifiedid: headteacher.uid,
  146. username: headteacher.name,
  147. });
  148. }
  149. await nres.save();
  150. }
  151. }
  152. // 取得符合条件的学生列表
  153. async getstudents(termid, batchid) {
  154. // 根据期id查找所有当期学生列表
  155. const cltype = await this.ctmodel.find({ bedroom: '0' });
  156. const types = _.map(cltype, 'code');
  157. const studentList = await this.smodel
  158. .find({ termid, batchid, type: { $in: types } })
  159. .sort({ gender: -1 });
  160. return studentList;
  161. }
  162. // 取得符合条件的学生列表
  163. async getbedroomstudents(termid, batchid, bedroom) {
  164. // 根据期id查找所有当期学生列表
  165. const studentList = await this.smodel.find({ termid, batchid, bedroom });
  166. return studentList;
  167. }
  168. // 新 分配寝室查询可以的列表
  169. async getAssignRoom({ termid }) {
  170. const bedroomList = await this.model.find();
  171. const stuList = await this.smodel.find({ termid });
  172. const stuBedIdGroup = _.groupBy(stuList, 'bedroomid');
  173. const keys = Object.keys(stuBedIdGroup);
  174. // 过滤出没有人的寝室
  175. let noperson = bedroomList.filter(f => !(keys.find(k => {
  176. if (k === undefined || k === 'undefined' || k === null || k === 'null') return false;
  177. return ObjectId(k).equals(f._id);
  178. })));
  179. noperson = JSON.parse(JSON.stringify(noperson));
  180. const nopersonList = [];
  181. for (const i of noperson) {
  182. const n = `${i.code}(${i.number}人)`;
  183. const obj = { ...i, name: n };
  184. nopersonList.push(obj);
  185. }
  186. const havepersonList = [];
  187. for (const key of keys) {
  188. if (key === undefined || key === 'undefined' || key === null || key === 'null') continue;
  189. // 取出分组后,以寝室id为key的学生列表
  190. const list = stuBedIdGroup[key];
  191. // 找到寝室obj
  192. const bedroom = bedroomList.find(f => ObjectId(key).equals(f._id));
  193. // 找不到寝室就算了,下一个吧
  194. if (!bedroom) continue;
  195. // 找到这个寝室人数限制
  196. const { number } = bedroom;
  197. // 超出,等于限制人数,继续下个寝室
  198. if (list.length >= number * 1) continue;
  199. // 这个寝室人没满,需要组织数据了
  200. const { _id, code, floor } = bedroom;
  201. const elsenum = number * 1 - list.length;
  202. const stu = _.head(list);
  203. const { gender } = stu;
  204. let ncode = `${code}(`;
  205. if (elsenum) ncode = `${ncode} 剩余${elsenum}人`;
  206. if (gender) ncode = `${ncode} ${gender}性`;
  207. if (floor)ncode = `${ncode} ${floor}楼`;
  208. ncode = `${ncode})`;
  209. const obj = { _id, code, name: ncode };
  210. havepersonList.push(obj);
  211. }
  212. return [ ...nopersonList, ...havepersonList ];
  213. }
  214. // 批量修改学生寝室(新) TODO,需要添加期id,然后找这个寝室,这期同学是否占满/性别错误的问题
  215. async updateStudent(data, body) {
  216. const { code, ids, bedroomid, termid } = body;
  217. const bedroom = await this.model.findById(bedroomid);
  218. if (!bedroom) throw new BusinessError(ErrorCode.DATA_NOT_EXIST, '不存在该寝室');
  219. let { number, gender } = bedroom;
  220. // 找到多少人在这个寝室
  221. const inRoom = await this.ctx.model.Student.find({ termid, bedroomid });
  222. const ifTotal = inRoom.length * 1 + ids.length;
  223. if (ifTotal > number * 1) throw new BusinessError(ErrorCode.BUSINESS, `超出人数,该寝室人最多为${number}人`);
  224. if (!gender) {
  225. // 寝室没设置性别,从这个寝室的学生中取出性别
  226. const stu = _.head(inRoom);
  227. gender = _.trim(_.get(stu, 'gender'));
  228. }
  229. const selectStuList = await this.ctx.model.Student.find({ _id: ids.map(i => ObjectId(i)) });
  230. for (const id of ids) {
  231. const r = await this.ctx.model.Student.findById(id);
  232. // 性别查询,是否有误
  233. const { gender: sg, name } = r;
  234. // 寝室或有已入住学生,产生的性别结果,
  235. if (!gender) {
  236. r.bedroom = code;
  237. r.bedroomid = bedroomid;
  238. await r.save();
  239. } else {
  240. if (sg && sg.includes(gender)) {
  241. // 有性别判断
  242. r.bedroom = code;
  243. r.bedroomid = bedroomid;
  244. await r.save();
  245. } else {
  246. throw new BusinessError(
  247. ErrorCode.BusinessError,
  248. `${name} 与该寝室已分配的学生性别不符!`
  249. );
  250. }
  251. }
  252. }
  253. }
  254. }
  255. module.exports = BedroomService;