|
@@ -8,6 +8,7 @@ const { CrudService } = require('naf-framework-mongoose/lib/service');
|
|
const { BusinessError, ErrorCode } = require('naf-core').Error;
|
|
const { BusinessError, ErrorCode } = require('naf-core').Error;
|
|
const moment = require('moment');
|
|
const moment = require('moment');
|
|
const XLSX = require('xlsx');
|
|
const XLSX = require('xlsx');
|
|
|
|
+const Excel = require('exceljs');
|
|
|
|
|
|
class SchoolService extends CrudService {
|
|
class SchoolService extends CrudService {
|
|
constructor(ctx) {
|
|
constructor(ctx) {
|
|
@@ -48,336 +49,319 @@ class SchoolService extends CrudService {
|
|
if (!plan) {
|
|
if (!plan) {
|
|
throw new BusinessError(ErrorCode.DATA_NOT_EXIST, '计划信息不存在');
|
|
throw new BusinessError(ErrorCode.DATA_NOT_EXIST, '计划信息不存在');
|
|
}
|
|
}
|
|
- // const isOutOfDate = this.outOfDate(plan, termid, batchid);
|
|
|
|
- // if (!isOutOfDate) {
|
|
|
|
- // throw new BusinessError(
|
|
|
|
- // ErrorCode.BUSINESS,
|
|
|
|
- // '已经超过上报时间,不允许上报名单'
|
|
|
|
- // );
|
|
|
|
- // }
|
|
|
|
- // 取得学校预计人数
|
|
|
|
- const num_ = await this.getschnum(plan, type, schid, termid, batchid);
|
|
|
|
- // console.log('*******************');
|
|
|
|
- // console.log(num_);
|
|
|
|
- // console.log('*******************');
|
|
|
|
- // 检查学校是否上传过学生
|
|
|
|
- const schstu = await this.smodel.count({ schid, batchid });
|
|
|
|
- if (schstu && schstu > 0) throw new BusinessError(ErrorCode.BUSINESS, '该批次已经上传过学生,无需重复上传,若人员有变化,请联系中心负责人');
|
|
|
|
|
|
+ const term = plan.termnum.id(termid);
|
|
const planid = plan.id;
|
|
const planid = plan.id;
|
|
const planyearid = plan.planyearid;
|
|
const planyearid = plan.planyearid;
|
|
- // 取得excle中数据
|
|
|
|
- const _filepath = 'http://127.0.0.1' + filepath; // this.ctx.app.config.baseUrl http://127.0.0.1 http://jytz.jilinjobs.cn
|
|
|
|
- const studatas = await this.getImportXLSXData(
|
|
|
|
- _filepath,
|
|
|
|
- termid,
|
|
|
|
- schid,
|
|
|
|
- planid,
|
|
|
|
- planyearid,
|
|
|
|
- type,
|
|
|
|
- batchid
|
|
|
|
- );
|
|
|
|
- // 将得到的数据校验
|
|
|
|
- const datacheck = await this.datacheck(studatas);
|
|
|
|
- if (datacheck.errorcode === '1') {
|
|
|
|
- return datacheck;
|
|
|
|
- }
|
|
|
|
- const school_ = await this.model.findOne({ code: schid });
|
|
|
|
- let schname = '';
|
|
|
|
- if (school_) {
|
|
|
|
- schname = school_.name;
|
|
|
|
|
|
+ // 检查这个范围的学生是否存在,存在的话是否更改过(classid,bedroomid这两项存不存在可以放过,但凡有一个人,就不行了)
|
|
|
|
+ let dbStuList = await this.ctx.model.Student.find({ termid, batchid, schid });
|
|
|
|
+ if (dbStuList.length > 0) {
|
|
|
|
+ // 查这个学校的这期学生是否修改过班级 或 寝室
|
|
|
|
+ const is_change = dbStuList.find(f => f.classid || f.bedroomid);
|
|
|
|
+ if (is_change) throw new BusinessError(ErrorCode.BUSINESS, '上报过的学生已经安排班级或寝室!若需要替换学生,让同性别的学生直接来和班主任说,修改信息即可.若还是有疑问,请和中心负责人联系(最好联系下)');
|
|
}
|
|
}
|
|
- const trem_ = await plan.termnum.id(termid);
|
|
|
|
- if (!trem_) {
|
|
|
|
- throw new BusinessError(ErrorCode.DATA_NOT_EXIST, '期信息不存在');
|
|
|
|
|
|
+ // 获取学校名称
|
|
|
|
+ let school_name;
|
|
|
|
+ const sch = await this.ctx.model.School.findOne({ code: schid });
|
|
|
|
+ if (sch) school_name = sch.name;
|
|
|
|
+ const fullUrl = 'http://127.0.0.1' + filepath; // this.ctx.app.config.baseUrl http://127.0.0.1 http://jytz.jilinjobs.cn
|
|
|
|
+ let studentList = await this.getDataFromExcel(fullUrl);
|
|
|
|
+ const checkRes = await this.checkData(studentList);
|
|
|
|
+ const { errorcode } = checkRes;
|
|
|
|
+ if (errorcode === '1') {
|
|
|
|
+ return checkRes;
|
|
}
|
|
}
|
|
- const nowtime = moment().locale('zh-cn').format('YYYY-MM-DD HH:mm:ss');
|
|
|
|
- if (studatas.length > num_) {
|
|
|
|
- const jobdata = {
|
|
|
|
- code: schid,
|
|
|
|
- name: schname,
|
|
|
|
- planid: plan.id,
|
|
|
|
- termid,
|
|
|
|
- term: trem_.term,
|
|
|
|
- batchid,
|
|
|
|
- filepath,
|
|
|
|
- studs: JSON.stringify(studatas),
|
|
|
|
- plannum: num_,
|
|
|
|
- schnum: studatas.length,
|
|
|
|
- isstore: '0',
|
|
|
|
- createtime: nowtime,
|
|
|
|
- type,
|
|
|
|
- reason: '学校上传人数超过预期人数,请联系中心管理员',
|
|
|
|
- };
|
|
|
|
- await this.jmodel.create(jobdata);
|
|
|
|
- throw new BusinessError(
|
|
|
|
- ErrorCode.SERVICE_FAULT,
|
|
|
|
- '学校上传人数超过预期人数,请联系中心管理员'
|
|
|
|
- );
|
|
|
|
- } else if (studatas.length < num_) {
|
|
|
|
- const jobdata = {
|
|
|
|
- code: schid,
|
|
|
|
- name: schname,
|
|
|
|
- planid: plan.id,
|
|
|
|
- termid,
|
|
|
|
- term: trem_.term,
|
|
|
|
- batchid,
|
|
|
|
- filepath,
|
|
|
|
- studs: JSON.stringify(studatas),
|
|
|
|
- plannum: num_,
|
|
|
|
- schnum: studatas.length,
|
|
|
|
- isstore: '0',
|
|
|
|
- createtime: nowtime,
|
|
|
|
- type,
|
|
|
|
- reason: '学校上传人数少于预期人数,请联系中心管理员',
|
|
|
|
- };
|
|
|
|
- await this.jmodel.create(jobdata);
|
|
|
|
- throw new BusinessError(
|
|
|
|
- ErrorCode.SERVICE_FAULT,
|
|
|
|
- '学校上传人数少于预期人数,请联系中心管理员'
|
|
|
|
- );
|
|
|
|
- }
|
|
|
|
- // 将数据存入数据库中
|
|
|
|
- for (const stu of studatas) {
|
|
|
|
- const res = await this.smodel.create(stu);
|
|
|
|
- // if (res) {
|
|
|
|
- // const newdata = { name: stu.name, mobile: stu.phone, type: '4', uid: res.id };
|
|
|
|
- // newdata.passwd = { secret: '12345678' };
|
|
|
|
- // await this.umodel.create(newdata);
|
|
|
|
- // }
|
|
|
|
|
|
+ // 整理数据
|
|
|
|
+ studentList = this.lastSetData(studentList, {
|
|
|
|
+ planyearid,
|
|
|
|
+ planid,
|
|
|
|
+ batchid,
|
|
|
|
+ termid,
|
|
|
|
+ type,
|
|
|
|
+ schid,
|
|
|
|
+ school_name,
|
|
|
|
+ });
|
|
|
|
+ const num = await this.getschnum(plan, schid, batchid);
|
|
|
|
+ // 查看要求人数和整理完最后的人数能不能对上
|
|
|
|
+ if (studentList.length !== num) {
|
|
|
|
+ const res = await this.jmodel.findOne({ code: schid, batchid });
|
|
|
|
+ const reason = `学校上传人数${studentList.length > num ? '多于' : '少于'}预期人数,请联系中心管理员`;
|
|
|
|
+ if (res) {
|
|
|
|
+ res.reason = reason;
|
|
|
|
+ res.filepath = filepath;
|
|
|
|
+ await res.save();
|
|
|
|
+ } else {
|
|
|
|
+ const job = {
|
|
|
|
+ code: schid,
|
|
|
|
+ name: school_name,
|
|
|
|
+ planid,
|
|
|
|
+ termid,
|
|
|
|
+ term: term.term,
|
|
|
|
+ batchid,
|
|
|
|
+ filepath,
|
|
|
|
+ studs: JSON.stringify(studentList),
|
|
|
|
+ plannum: num,
|
|
|
|
+ schnum: studentList.length,
|
|
|
|
+ isstore: '0',
|
|
|
|
+ createtime: moment().format('YYYY-MM-DD HH:SS:mm'),
|
|
|
|
+ type,
|
|
|
|
+ };
|
|
|
|
+ job.reason = reason;
|
|
|
|
+ await this.jmodel.save(job);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ throw new BusinessError(ErrorCode.SERVICE_FAULT, reason);
|
|
|
|
+ } else {
|
|
|
|
+ // 复制,删除,添加
|
|
|
|
+ dbStuList = JSON.parse(JSON.stringify(dbStuList));
|
|
|
|
+ dbStuList = dbStuList.map(i => {
|
|
|
|
+ delete i.meta;
|
|
|
|
+ i.studentid = _.clone(i._id);
|
|
|
|
+ delete i.id;
|
|
|
|
+ delete i._id;
|
|
|
|
+ return i;
|
|
|
|
+ });
|
|
|
|
+ await this.ctx.model.Dstudent.insertMany(dbStuList);
|
|
|
|
+ await this.smodel.deleteMany({ termid, batchid, schid });
|
|
|
|
+ await this.smodel.insertMany(studentList);
|
|
}
|
|
}
|
|
- return datacheck;
|
|
|
|
}
|
|
}
|
|
|
|
|
|
// 取得学校预计人数
|
|
// 取得学校预计人数
|
|
- async getschnum(plan, type, schid, termid, batchid) {
|
|
|
|
|
|
+ async getschnum(plan, schid, batchid) {
|
|
const schtime = await this.schmodel.findOne({ schid, planid: plan.id });
|
|
const schtime = await this.schmodel.findOne({ schid, planid: plan.id });
|
|
const { arrange } = schtime;
|
|
const { arrange } = schtime;
|
|
const r = arrange.find(f => f.batchid === batchid);
|
|
const r = arrange.find(f => f.batchid === batchid);
|
|
if (!r) { throw new BusinessError(ErrorCode.DATA_NOT_EXIST, '没有找到该学校的计划'); }
|
|
if (!r) { throw new BusinessError(ErrorCode.DATA_NOT_EXIST, '没有找到该学校的计划'); }
|
|
const { number } = r;
|
|
const { number } = r;
|
|
return parseInt(number);
|
|
return parseInt(number);
|
|
- // const { termnum } = plan;
|
|
|
|
- // arrange = _.groupBy(arrange, 'termid');
|
|
|
|
- // const keys = Object.keys(arrange);
|
|
|
|
- // let arr = keys.map(key => {
|
|
|
|
- // const rt = termnum.find(f => ObjectId(key).equals(f._id));
|
|
|
|
- // let ar = arrange[key];
|
|
|
|
- // ar = ar.map(a => {
|
|
|
|
- // const rb = rt.batchnum.find(f => ObjectId(a.batchid).equals(f._id));
|
|
|
|
- // if (rb) {
|
|
|
|
- // const bh = _.head(rb.class);
|
|
|
|
- // const { type } = bh;
|
|
|
|
- // a.type = type;
|
|
|
|
- // return a;
|
|
|
|
- // }
|
|
|
|
- // });
|
|
|
|
- // let garr = _.groupBy(ar, 'type');
|
|
|
|
- // const gks = Object.keys(garr);
|
|
|
|
- // garr = gks.map(gk => {
|
|
|
|
- // const { term, termid } = _.head(garr[gk]);
|
|
|
|
- // const number = garr[gk].reduce((p, n) => p + n.number * 1, 0);
|
|
|
|
- // return { term, termid, number, type: gk };
|
|
|
|
- // });
|
|
|
|
- // return garr;
|
|
|
|
- // });
|
|
|
|
- // arr = arr.flat();
|
|
|
|
- // const obj_ = _.find(arr, { termid, type });
|
|
|
|
- return obj_.number;
|
|
|
|
}
|
|
}
|
|
-
|
|
|
|
- // 获取导入的XLSX文件中的数据
|
|
|
|
- async getImportXLSXData(
|
|
|
|
- filepath,
|
|
|
|
- termid,
|
|
|
|
- schid,
|
|
|
|
- planid,
|
|
|
|
- planyearid,
|
|
|
|
- type,
|
|
|
|
- batchid
|
|
|
|
- ) {
|
|
|
|
- const file = await this.ctx.curl(filepath);
|
|
|
|
- const workbook = XLSX.read(file.data);
|
|
|
|
- // 读取内容
|
|
|
|
- let exceldata = [];
|
|
|
|
- const sheetNames = workbook.SheetNames; // 获取表名
|
|
|
|
- const sheet = workbook.Sheets[sheetNames[0]]; // 通过表名得到表对象
|
|
|
|
-
|
|
|
|
- // 遍历26个字母
|
|
|
|
- const theadRule = [];
|
|
|
|
- const range = XLSX.utils.decode_range(sheet['!ref']);
|
|
|
|
- const col_start = range.s.c;
|
|
|
|
- const col_end = range.e.c;
|
|
|
|
- for (let i = col_start; i <= col_end; i++) {
|
|
|
|
- const addr = XLSX.utils.encode_col(i) + XLSX.utils.encode_row(0);
|
|
|
|
- theadRule.push(sheet[addr].v);
|
|
|
|
|
|
+ // 整理excel数据
|
|
|
|
+ async getDataFromExcel(url) {
|
|
|
|
+ const file = await this.ctx.curl(`http://127.0.0.1${url}`);
|
|
|
|
+ if (!(file && file.data)) {
|
|
|
|
+ throw new BusinessError(ErrorCode.DATA_NOT_EXIST, '未找到上传的名单');
|
|
}
|
|
}
|
|
- // const theadRule = [ sheet.A1.v, sheet.B1.v, sheet.C1.v, sheet.D1.v, sheet.E1.v, sheet.F1.v, sheet.G1.v, sheet.H1.v, sheet.I1.v, sheet.J1.v, sheet.K1.v, sheet.L1.v, sheet.M1.v, sheet.N1.v, sheet.O1.v, sheet.P1.v, sheet.Q1.v, sheet.R1.v ];
|
|
|
|
- const params = XLSX.utils.sheet_to_json(sheet); // 通过工具将表对象的数据读出来并转成json
|
|
|
|
- // const theadRule = [ '序号', '姓名', '性别', '民族', '身份证号', '学校名称', '院系', '专业', '入学年份', '毕业年份', '在校曾担任何种职务', '手机号', 'QQ号', '家庭所在地', '家庭是否困难', '是否获得过助学金' ];
|
|
|
|
- if (!params) return [];
|
|
|
|
- let i = 0;
|
|
|
|
- const length = params.length;
|
|
|
|
- const _datas = [];
|
|
|
|
- let data = {};
|
|
|
|
- for (i; i < length; i++) {
|
|
|
|
- data = params[i];
|
|
|
|
- const diy_ = [];
|
|
|
|
- if (theadRule.length > 18) {
|
|
|
|
- for (let j = 18; j < theadRule.length; j++) {
|
|
|
|
- const newdata = {
|
|
|
|
- itemname: theadRule[j],
|
|
|
|
- itemvalue: data[theadRule[j]],
|
|
|
|
- };
|
|
|
|
- diy_.push(newdata);
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- _datas.push({
|
|
|
|
- name: _.trim(data[theadRule[1]]),
|
|
|
|
- gender: _.trim(data[theadRule[2]]),
|
|
|
|
- nation: _.trim(data[theadRule[3]]),
|
|
|
|
- id_number: _.trim(data[theadRule[4]]),
|
|
|
|
- school_name: _.trim(data[theadRule[5]]),
|
|
|
|
- faculty: _.trim(data[theadRule[6]]),
|
|
|
|
- major: _.trim(data[theadRule[7]]),
|
|
|
|
- entry_year: _.trim(data[theadRule[8]]),
|
|
|
|
- finish_year: _.trim(data[theadRule[9]]),
|
|
|
|
- school_job: _.trim(data[theadRule[10]]),
|
|
|
|
- phone: _.trim(data[theadRule[11]]),
|
|
|
|
- qq: _.trim(data[theadRule[12]]),
|
|
|
|
- family_place: _.trim(data[theadRule[13]]),
|
|
|
|
- family_is_hard: _.trim(data[theadRule[14]]),
|
|
|
|
- have_grant: _.trim(data[theadRule[15]]),
|
|
|
|
- edua_level: _.trim(data[theadRule[16]]),
|
|
|
|
- edua_system: _.trim(data[theadRule[17]]),
|
|
|
|
- diy: diy_,
|
|
|
|
- termid,
|
|
|
|
- batchid,
|
|
|
|
- schid,
|
|
|
|
- planid,
|
|
|
|
- planyearid,
|
|
|
|
- type,
|
|
|
|
- });
|
|
|
|
|
|
+ const workbook = new Excel.Workbook();
|
|
|
|
+ await workbook.xlsx.load(file);
|
|
|
|
+ const worksheet = workbook.getWorksheet(1);
|
|
|
|
+ if (!worksheet) {
|
|
|
|
+ throw new BusinessError(ErrorCode.DATA_NOT_EXIST, '未发现excel中有工作表');
|
|
}
|
|
}
|
|
- exceldata = [ ...exceldata, ..._datas ];
|
|
|
|
|
|
+ const cols = this.getStucolumn();
|
|
|
|
+ const headRow = worksheet.getRow(1);
|
|
|
|
+ headRow.eachCell((cell, coli) => {
|
|
|
|
+ const r = cols.find(f => f.key === cell.value);
|
|
|
|
+ if (r) {
|
|
|
|
+ const ri = cols.findIndex(f => f.key === cell.value);
|
|
|
|
+ r.colIndex = coli;
|
|
|
|
+ cols[ri] = r;
|
|
|
|
+ }
|
|
|
|
+ });
|
|
|
|
+ const excelIsRigth = cols.find(f => f.colIndex);
|
|
|
|
+ if (!excelIsRigth) throw new BusinessError(ErrorCode.DATA_INVALID, 'Excel表格格式不正确,请使用系统提供的模板!');
|
|
|
|
+ // 删除掉第一行
|
|
|
|
+ worksheet.spliceRows(0, 1);
|
|
|
|
+ const stuList = [];
|
|
|
|
+ // 整理数据
|
|
|
|
+ worksheet.eachRow(row => {
|
|
|
|
+ const stu = {};
|
|
|
|
+ for (let i = 0; i < cols.length; i++) {
|
|
|
|
+ const col = cols[i];
|
|
|
|
+ if (!col) break;
|
|
|
|
+ let val = _.trim(row.getCell(col.colIndex));
|
|
|
|
+ if (col.column === 'id_number') val = val.toUpperCase();
|
|
|
|
+ stu[col.column] = val;
|
|
|
|
+ }
|
|
|
|
+ stuList.push(stu);
|
|
|
|
+ });
|
|
|
|
+ return stuList;
|
|
|
|
|
|
- return exceldata;
|
|
|
|
}
|
|
}
|
|
-
|
|
|
|
- // 获取导入的XLSX文件中的数据
|
|
|
|
- async datacheck(studatas) {
|
|
|
|
|
|
+ // 数据校验
|
|
|
|
+ async checkData(stuList) {
|
|
|
|
+ const cols = this.getStucolumn();
|
|
let errorcode = '0';
|
|
let errorcode = '0';
|
|
const errormsg = [];
|
|
const errormsg = [];
|
|
- for (const data of studatas) {
|
|
|
|
- // 判断是否为空
|
|
|
|
- if (!data.name) {
|
|
|
|
- errorcode = '1';
|
|
|
|
- data.msg = (data.msg || '') + '姓名不允许为空;';
|
|
|
|
- }
|
|
|
|
- if (!data.gender) {
|
|
|
|
- errorcode = '1';
|
|
|
|
- data.msg = (data.msg || '') + '性别不允许为空;';
|
|
|
|
- }
|
|
|
|
- // 判断性别是否是1个字
|
|
|
|
- if (data.gender.length !== 1) {
|
|
|
|
- errorcode = '1';
|
|
|
|
- data.msg(data.msg || '') + '性别内容超出1个字.可能含有空格;';
|
|
|
|
- }
|
|
|
|
- if (!data.nation) {
|
|
|
|
- errorcode = '1';
|
|
|
|
- data.msg = (data.msg || '') + '民族不允许为空;';
|
|
|
|
- }
|
|
|
|
- if (!data.id_number) {
|
|
|
|
- errorcode = '1';
|
|
|
|
- data.msg = (data.msg || '') + '身份证号不允许为空;';
|
|
|
|
- } else {
|
|
|
|
- const res = await this.smodel.findOne({ id_number: data.id_number });
|
|
|
|
- if (res) {
|
|
|
|
- errorcode = '1';
|
|
|
|
- data.msg = (data.msg || '') + '学生已经存在请检查;';
|
|
|
|
- } else {
|
|
|
|
- const { pass, msg } = this.idCodeValid(data.id_number);
|
|
|
|
|
|
+ for (const stu of stuList) {
|
|
|
|
+ const { name } = stu;
|
|
|
|
+ let error = false;
|
|
|
|
+ let msg = '';
|
|
|
|
+ // 各个字段检查,最低为非空检查
|
|
|
|
+ for (const col of cols) {
|
|
|
|
+ const { key, column } = col;
|
|
|
|
+ if (!column) throw new BusinessError(ErrorCode.SERVICE_FAULT, '未找到导出的字段名');
|
|
|
|
+ const val = _.get(stu, column);
|
|
|
|
+ // 空校验
|
|
|
|
+ if (!val || val === '') {
|
|
|
|
+ error = true;
|
|
|
|
+ msg = `${msg}"${key}"不能为空;`;
|
|
|
|
+ continue;
|
|
|
|
+ }
|
|
|
|
+ // 性别校验
|
|
|
|
+ if (column === 'gender') {
|
|
|
|
+ if (!(val.includes('男') || val.includes('女'))) {
|
|
|
|
+ error = true;
|
|
|
|
+ msg = `${msg}性别错误;`;
|
|
|
|
+ }
|
|
|
|
+ continue;
|
|
|
|
+ }
|
|
|
|
+ // 身份证号校验
|
|
|
|
+ if (column === 'id_number') {
|
|
|
|
+ // 因为删除再添加的流程导致此处 不能 校验数据库中是否有这个身份证号
|
|
|
|
+ // const res = await this.ctx.model.Student.findOne({ id_number: val });
|
|
|
|
+ // if (!res) {
|
|
|
|
+ const { pass, msg: idmsg } = this.ctx.service.school.idCodeValid(val);
|
|
if (!pass) {
|
|
if (!pass) {
|
|
- errorcode = '1';
|
|
|
|
- data.msg = (data.msg || '') + `${msg},`;
|
|
|
|
|
|
+ error = true;
|
|
|
|
+ msg = `${msg}${idmsg};`;
|
|
}
|
|
}
|
|
|
|
+ // } else {
|
|
|
|
+ // error = true;
|
|
|
|
+ // msg = `${msg}学生已存在`;
|
|
|
|
+ // }
|
|
|
|
+ const have_same = stuList.filter(f => f.id_number === val && f.name !== name);
|
|
|
|
+ if (have_same.length > 0) {
|
|
|
|
+ error = true;
|
|
|
|
+ const h = _.head(have_same);
|
|
|
|
+ const num = have_same.length;
|
|
|
|
+ if (num === 1) {
|
|
|
|
+ msg = `${msg}身份证号与本次名单的"${h.name}"重复;`;
|
|
|
|
+ } else msg = `${msg}身份证号与本次名单中"${h.name}"等${num}人重复;`;
|
|
|
|
+ }
|
|
|
|
+ continue;
|
|
}
|
|
}
|
|
-
|
|
|
|
- }
|
|
|
|
- if (!data.school_name) {
|
|
|
|
- errorcode = '1';
|
|
|
|
- data.msg = (data.msg || '') + '学校名称不允许为空;';
|
|
|
|
- }
|
|
|
|
- if (!data.phone) {
|
|
|
|
- errorcode = '1';
|
|
|
|
- data.msg = (data.msg || '') + '手机号不允许为空;';
|
|
|
|
- }
|
|
|
|
- if (!data.faculty) {
|
|
|
|
- errorcode = '1';
|
|
|
|
- data.msg = (data.msg || '') + '院系不允许为空;';
|
|
|
|
- }
|
|
|
|
- if (!data.major) {
|
|
|
|
- errorcode = '1';
|
|
|
|
- data.msg = (data.msg || '') + '专业不允许为空;';
|
|
|
|
- } else {
|
|
|
|
- // 限制专业字段中不能含有 '专业' 字样
|
|
|
|
- if (data.major.includes('专业')) {
|
|
|
|
- errorcode = '1';
|
|
|
|
- data.msg = (data.msg || '') + '专业列不能含有"专业"二字;';
|
|
|
|
|
|
+ // 手机号校验
|
|
|
|
+ if (column === 'phone') {
|
|
|
|
+ // 因为删除再添加的流程导致此处 不能 校验数据库中是否有这个手机号
|
|
|
|
+ // const res = await this.ctx.model.Student.findOne({ phone: val });
|
|
|
|
+ // if (!res) {
|
|
|
|
+ if (!/^\d{11}$/i.test(val)) {
|
|
|
|
+ error = true;
|
|
|
|
+ msg = `${msg}手机号位数不正确;`;
|
|
|
|
+ }
|
|
|
|
+ // } else {
|
|
|
|
+ // error = true;
|
|
|
|
+ // msg = `${msg}学生库中已有该手机号,请检查手机号是否正确,若无误,请联系中心负责人`;
|
|
|
|
+ // }
|
|
|
|
+ const have_same = stuList.filter(f => f.phone === val && f.name !== name);
|
|
|
|
+ if (have_same.length > 0) {
|
|
|
|
+ error = true;
|
|
|
|
+ const h = _.head(have_same);
|
|
|
|
+ const num = have_same.length;
|
|
|
|
+ if (num === 1) {
|
|
|
|
+ msg = `${msg}手机号与本次名单的"${h.name}"重复;`;
|
|
|
|
+ } else msg = `${msg}手机号与本次名单中"${h.name}"等${num}人重复;`;
|
|
|
|
+ }
|
|
|
|
+ continue;
|
|
}
|
|
}
|
|
- }
|
|
|
|
-
|
|
|
|
- if (!data.entry_year) {
|
|
|
|
- errorcode = '1';
|
|
|
|
- data.msg = (data.msg || '') + '入学年份不允许为空;';
|
|
|
|
- } else {
|
|
|
|
- const m = /^\w{4}$/;
|
|
|
|
- if (!data.entry_year.match(m)) {
|
|
|
|
- errorcode = '1';
|
|
|
|
- data.msg = (data.msg || '') + '入学年份格式不正确,只填写4位数字即可;';
|
|
|
|
|
|
+ // 专业校验
|
|
|
|
+ if (column === 'major') {
|
|
|
|
+ if (val.includes('专业')) {
|
|
|
|
+ error = true;
|
|
|
|
+ msg = `${msg}专业列不能含有"专业"二字;`;
|
|
|
|
+ }
|
|
|
|
+ continue;
|
|
}
|
|
}
|
|
- }
|
|
|
|
- // 限制是4位数字
|
|
|
|
- if (!data.finish_year) {
|
|
|
|
- errorcode = '1';
|
|
|
|
- data.msg = (data.msg || '') + '毕业年份不允许为空;';
|
|
|
|
- } else {
|
|
|
|
- const m = /^\w{4}$/;
|
|
|
|
- if (!data.finish_year.match(m)) {
|
|
|
|
- errorcode = '1';
|
|
|
|
- data.msg = (data.msg || '') + '毕业年份格式不正确,只填写4位数字即可;';
|
|
|
|
|
|
+ // 入学年份
|
|
|
|
+ if (column === 'entry_year') {
|
|
|
|
+ const m = /^\w{4}$/;
|
|
|
|
+ if (!val.match(m)) {
|
|
|
|
+ error = true;
|
|
|
|
+ msg = `${msg}入学年份格式不正确,只填写4位数字;`;
|
|
|
|
+ }
|
|
|
|
+ continue;
|
|
|
|
+ }
|
|
|
|
+ // 毕业年份
|
|
|
|
+ if (column === 'finish_year') {
|
|
|
|
+ const m = /^\w{4}$/;
|
|
|
|
+ if (!val.match(m)) {
|
|
|
|
+ error = true;
|
|
|
|
+ msg = `${msg}毕业年份格式不正确,只填写4位数字;`;
|
|
|
|
+ }
|
|
|
|
+ continue;
|
|
|
|
+ }
|
|
|
|
+ // 双困检查
|
|
|
|
+ if (column === 'family_is_hard') {
|
|
|
|
+ if (!(val.includes('是') || val.includes('否'))) {
|
|
|
|
+ error = true;
|
|
|
|
+ msg = `${msg}家庭是否困难填写"是"或"否";`;
|
|
|
|
+ }
|
|
|
|
+ continue;
|
|
|
|
+ }
|
|
|
|
+ if (column === 'have_grant') {
|
|
|
|
+ if (!(val.includes('是') || val.includes('否'))) {
|
|
|
|
+ error = true;
|
|
|
|
+ msg = `${msg}是否获得过助学金填写"是"或"否";`;
|
|
|
|
+ }
|
|
|
|
+ continue;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
- if (!data.school_job) {
|
|
|
|
- errorcode = '1';
|
|
|
|
- data.msg = (data.msg || '') + '职务不允许为空;';
|
|
|
|
- }
|
|
|
|
- if (!data.qq) {
|
|
|
|
- errorcode = '1';
|
|
|
|
- data.msg = (data.msg || '') + 'QQ号不允许为空;';
|
|
|
|
- }
|
|
|
|
- if (!data.family_place) {
|
|
|
|
- errorcode = '1';
|
|
|
|
- data.msg = (data.msg || '') + '家庭所在地不允许为空;';
|
|
|
|
- }
|
|
|
|
- if (!data.family_is_hard) {
|
|
|
|
- errorcode = '1';
|
|
|
|
- data.msg = (data.msg || '') + '家庭是否困难不允许为空;';
|
|
|
|
- }
|
|
|
|
- if (!data.have_grant) {
|
|
|
|
- errorcode = '1';
|
|
|
|
- data.msg = (data.msg || '') + '是否获得过助学金不允许为空;';
|
|
|
|
- }
|
|
|
|
- if (!/^\d{11}$/i.test(data.phone)) {
|
|
|
|
|
|
+ if (error) {
|
|
errorcode = '1';
|
|
errorcode = '1';
|
|
- data.msg = (data.msg || '') + '手机号不正确;';
|
|
|
|
- }
|
|
|
|
- if (errorcode === '1') {
|
|
|
|
- errormsg.push(data);
|
|
|
|
|
|
+ stu.msg = msg;
|
|
|
|
+ errormsg.push(stu);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return { errorcode, errormsg };
|
|
return { errorcode, errormsg };
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ // 最后整合数据
|
|
|
|
+ lastSetData(stuList, data) {
|
|
|
|
+ const cols = this.getStucolumn();
|
|
|
|
+ const needChange = cols.filter(f => f.change);
|
|
|
|
+ stuList = stuList.map(i => {
|
|
|
|
+ const d = { ...i, ...data };
|
|
|
|
+ for (const col of needChange) {
|
|
|
|
+ const { column, change } = col;
|
|
|
|
+ if (!column && change && _.isArray(change)) continue;
|
|
|
|
+ const val = _.get(d, column);
|
|
|
|
+ if (!val) continue;
|
|
|
|
+ const r = change.find(f => f.key === val);
|
|
|
|
+ if (!r) continue;
|
|
|
|
+ const { value } = r;
|
|
|
|
+ d[column] = value;
|
|
|
|
+ }
|
|
|
|
+ return d;
|
|
|
|
+ });
|
|
|
|
+ return stuList;
|
|
|
|
+ }
|
|
|
|
+ // excel中学生字段
|
|
|
|
+ getStucolumn() {
|
|
|
|
+ const arr = [
|
|
|
|
+ { key: '姓名', column: 'name' },
|
|
|
|
+ { key: '性别', column: 'gender' },
|
|
|
|
+ { key: '民族', column: 'nation' },
|
|
|
|
+ { key: '身份证号', column: 'id_number' },
|
|
|
|
+ { key: '学校名称', column: 'school_name' },
|
|
|
|
+ { key: '院(系)', column: 'faculty' },
|
|
|
|
+ { key: '专业', column: 'major' },
|
|
|
|
+ { key: '入学年份', column: 'entry_year' },
|
|
|
|
+ { key: '毕业年份', column: 'finish_year' },
|
|
|
|
+ { key: '在校曾担任何种职务', column: 'school_job' },
|
|
|
|
+ { key: '手机号', column: 'phone' },
|
|
|
|
+ { key: 'QQ号', column: 'qq' },
|
|
|
|
+ { key: '家庭所在地', column: 'family_place' },
|
|
|
|
+ {
|
|
|
|
+ key: '家庭是否困难',
|
|
|
|
+ column: 'family_is_hard',
|
|
|
|
+ change: [
|
|
|
|
+ { key: '否', value: '0' },
|
|
|
|
+ { key: '是', value: '1' },
|
|
|
|
+ ],
|
|
|
|
+ },
|
|
|
|
+ {
|
|
|
|
+ key: '是否获得过助学金',
|
|
|
|
+ column: 'have_grant',
|
|
|
|
+ change: [
|
|
|
|
+ { key: '否', value: '0' },
|
|
|
|
+ { key: '是', value: '1' },
|
|
|
|
+ ],
|
|
|
|
+ },
|
|
|
|
+ ];
|
|
|
|
+ return arr;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+
|
|
// 导出学校名单
|
|
// 导出学校名单
|
|
async exportSchool({ trainplanId }) {
|
|
async exportSchool({ trainplanId }) {
|
|
// 批次期次都在这里面
|
|
// 批次期次都在这里面
|
|
@@ -555,23 +539,6 @@ class SchoolService extends CrudService {
|
|
}
|
|
}
|
|
return row;
|
|
return row;
|
|
}
|
|
}
|
|
- // 判断是否超出该期前3天
|
|
|
|
- outOfDate(plan, termid, batchid) {
|
|
|
|
- const term = plan.termnum.find(f => ObjectId(termid).equals(f._id));
|
|
|
|
- const { batchnum } = term;
|
|
|
|
- if (!batchnum) throw new BusinessError(ErrorCode.BUSINESS, '没有找到该期下的批次');
|
|
|
|
- const batch = batchnum.find(f => ObjectId(batchid).equals(f._id));
|
|
|
|
- if (!batch) throw new BusinessError(ErrorCode.BUSINESS, '没有找到该批次');
|
|
|
|
- // let startList = batchnum.map(i => ({ start: i.startdate }));
|
|
|
|
- // startList = _.orderBy(startList, [ 'start' ], [ 'asc' ]);
|
|
|
|
- // const start = _.get(_.head(startList), 'start');
|
|
|
|
- const start = _.get(batch, 'startdate');
|
|
|
|
- if (!start) throw new BusinessError(ErrorCode.BUSINESS, '没有找到开始日期');
|
|
|
|
- const limit = moment(start).subtract(3, 'days').format('YYYY-MM-DD');
|
|
|
|
- const now = moment().format('YYYY-MM-DD');
|
|
|
|
- const res = moment(now).isBefore(limit);
|
|
|
|
- return res;
|
|
|
|
- }
|
|
|
|
}
|
|
}
|
|
|
|
|
|
module.exports = SchoolService;
|
|
module.exports = SchoolService;
|