123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522 |
- 'use strict';
- /**
- * 质量管理 - 工程质量
- *
- * @author Mai
- * @date 2024/7/22
- * @version
- */
- class RuleCheck {
- sortCondition(condition) {
- const fieldKey = ['gongxu_name', 'yinbi_name', 'file_count', 'file_name'];
- condition.forEach(c => { c.fieldKeyIndex = fieldKey.indexOf(c.fieldKey); });
- condition.sort((a, b) => { return a.fieldKeyIndex - b.fieldKeyIndex; });
- }
- fileCountCheck(files, check) {
- if (check.operateKey === '>') return files.length > parseInt(check.value);
- if (check.operateKey === '=') return files.length === parseInt(check.value);
- }
- fileNameCheck(files, check) {
- const matchName = check.multi ? check.value.split(';') : [check.value];
- if (check.operateKey === '=') return files.findIndex(f => { return matchName.indexOf(f.filename) >= 0; }) >= 0;
- if (check.operateKey === 'has') return files.findIndex(f => {
- return matchName.findIndex(x => { return f.filename.indexOf(x) >= 0; }) >= 0;
- }) >= 0;
- }
- getAllFiles() {
- const files = [];
- if (this.quality.kaigong) files.push(...this.quality.kaigong.files);
- if (this.quality.gongxu) {
- for (const gx of this.quality.gongxu.list) {
- files.push(...gx.files);
- }
- }
- if (this.quality.pingding) {
- files.push(...this.quality.pingding.files);
- this.quality.pingding.source_files.forEach(sf => {
- if (sf.spec_type === 'add') files.push(sf);
- });
- }
- if (this.quality.jiaogong) files.push(...this.quality.jiaogong.files);
- // if (this.quality.yinbi) {
- // for (const yb of this.quality.yinbi.list) {
- // files.push(...yb.files);
- // }
- // }
- return files;
- }
- kaigongCheck(check) {
- if (!this.quality.kaigong) return false;
- switch (check.fieldKey) {
- case 'file_count':
- return this.fileCountCheck(this.quality.kaigong.files, check);
- case 'file_name':
- return this.fileNameCheck(this.quality.kaigong.files, check);
- default:
- return false;
- }
- }
- GongxuNameCheck(check) {
- const matchName = check.multi ? check.value.split(';') : [check.value];
- if (check.operateKey === '=') {
- this.matchGongxu = this.quality.gongxu.list.filter(f => { return matchName.indexOf(f.name) >= 0; });
- }
- if (check.operateKey === 'has') {
- this.matchGongxu = this.quality.gongxu.list.filter(f => {
- return matchName.findIndex(x => { return f.name.indexOf(x) >= 0; }) >= 0;
- });
- }
- return this.matchGongxu.length > 0;
- }
- getGongxuFiles() {
- const files = [];
- const gongxuList = this.matchGongxu || this.quality.gongxu.list;
- for (const gx of gongxuList) {
- files.push(...gx.files);
- }
- return files;
- }
- gongxuCheck(check) {
- switch (check.fieldKey) {
- case 'gongxu_name':
- return this.GongxuNameCheck(check);
- case 'file_count':
- return this.fileCountCheck(this.getGongxuFiles(), check);
- case 'file_name':
- return this.fileNameCheck(this.getGongxuFiles(), check);
- default:
- return false;
- }
- }
- pingdingCheck(check) {
- if (!this.quality.pingding) return false;
- const files = [...this.quality.pingding.files, ...this.quality.pingding.source_files];
- switch (check.fieldKey) {
- case 'file_count':
- return this.fileCountCheck(files, check);
- case 'file_name':
- return this.fileNameCheck(files, check);
- default:
- return false;
- }
- }
- jiaogongCheck(check) {
- if (!this.quality.jiaogong) return false;
- switch (check.fieldKey) {
- case 'file_count':
- return this.fileCountCheck(this.quality.jiaogong.files, check);
- case 'file_name':
- return this.fileNameCheck(this.quality.jiaogong.files, check);
- default:
- return false;
- }
- }
- YinbiNameCheck(check) {
- const matchName = check.multi ? check.value.split(';') : [check.value];
- if (check.operateKey === '=') {
- this.matchYinbi = this.quality.yinbi.list.filter(f => { return matchName.indexOf(f.name) >= 0; });
- }
- if (check.operateKey === '>') {
- this.matchYinbi = this.quality.yinbi.list.filter(f => {
- return matchName.findIndex(x => { return f.name.indexOf(x) >= 0; }) >= 0;
- });
- }
- return this.matchYinbi.length > 0;
- }
- getYinbiFiles() {
- const files = [];
- const yinbiList = this.matchYinbi || this.quality.yinbi.list;
- for (const yb of yinbiList) {
- files.push(...yb.files);
- }
- return files;
- }
- yinbiCheck(check) {
- switch (check.fieldKey) {
- case 'gongxu_name':
- return this.YinbiNameCheck(check);
- case 'file_count':
- return this.fileCountCheck(this.getYinbiFiles(), check);
- case 'file_name':
- return this.fileNameCheck(this.getYinbiFiles(), check);
- default:
- return false;
- }
- }
- allFilesCheck(check) {
- const allFiles = this.getAllFiles();
- switch (check.fieldKey) {
- case 'file_count':
- return this.fileCountCheck(allFiles, check);
- case 'file_name':
- return this.fileNameCheck(allFiles, check);
- default:
- return false;
- }
- }
- conditionCheck(check) {
- switch (check.blockKey) {
- case 'kaigong':
- return this.kaigongCheck(check);
- case 'gongxu':
- return this.gongxuCheck(check);
- case 'pingding':
- return this.pingdingCheck(check);
- case 'jiaogong':
- return this.jiaogongCheck(check);
- case 'yinbi':
- return this.yinbiCheck(check);
- case 'all':
- return this.allFilesCheck(check);
- default:
- return false;
- }
- }
- calcQualityStatus(quality, group) {
- this.quality = quality;
- this.group = group;
- for (const r of group.rules) {
- if (r.condition.length === 0) return false;
- if (r.condition.length > 1) this.sortCondition(r.condition);
- }
- const match = group.rules.filter(r => {
- this.matchGongxu = null;
- this.matchYinbi = null;
- for (const check of r.condition) {
- if (!this.conditionCheck(check)) {
- return false;
- }
- }
- return true;
- });
- if (match.length === 0) return null;
- const data = {};
- for (const m of match) {
- for (const s of m.push_status) {
- if (!data[s.field] || s.value > data[s.field]) {
- data[s.field] = s.value;
- }
- }
- }
- return data;
- }
- }
- module.exports = app => {
- class Quality extends app.BaseService {
- /**
- * 构造函数
- *
- * @param {Object} ctx - egg全局变量
- * @return {void}
- */
- constructor(ctx) {
- super(ctx);
- this.tableName = 'quality';
- this.editableColumns = ['gxby_status', 'gxby_date', 'gxby_limit', 'dagl_status', 'dagl_limit'];
- this.blockType = {
- kaigong: { key: 'kaigong', name: '开工' },
- gongxu: { key: 'gongxu', name: '工序' },
- jiaogong: { key: 'jiaogong', name: '中间交工' },
- pingding: { key: 'pingding', name: '评定' },
- yinbi: { key: 'yinbi', name: '隐蔽工程' },
- shiyan: { key: 'shiyan', name: '试验检测' },
- waiwei: { key: 'waiwei', name: '外委检测' },
- sanfang: { key: 'sanfang', name: '第三方检测' },
- };
- }
- async saveQualityManage(tid, data) {
- const quality = await this.getDataByCondition({ tid, rela_type: data.rela_type, rela_id: data.rela_id, rela_name: data.rela_name });
- if (quality) {
- const updateData = { id: quality.id, group_id: data.group_id, update_uid: this.ctx.session.sessionUser.accountId, };
- await this.db.update(this.tableName, updateData);
- updateData.rela_id = data.rela_id;
- updateData.rela_name = data.rela_name;
- return updateData;
- } else {
- const newQuality = {
- id: this.uuid.v4(), tid, rela_type: data.rela_type, rela_id: data.rela_id, rela_name: data.rela_name,
- create_uid: this.ctx.session.sessionUser.accountId, update_uid: this.ctx.session.sessionUser.accountId,
- group_id: data.group_id,
- };
- await this.db.insert(this.tableName, newQuality);
- return newQuality;
- }
- }
- async saveQuality(quality, filter, data, conn) {
- data.update_uid = this.ctx.session.sessionUser.accountId;
- data.is_used = 1;
- if (quality) {
- data.id = quality.id;
- if (conn) {
- await conn.update(this.tableName, data);
- } else {
- await this.db.update(this.tableName, data);
- }
- return data;
- } else {
- data.id = this.uuid.v4();
- data.tid = this.ctx.tender.id;
- data.rela_type = filter.rela_type;
- data.rela_id = filter.rela_id;
- data.rela_name = filter.rela_name;
- data.create_uid = this.ctx.session.sessionUser.accountId;
- if (conn) {
- await conn.insert(this.tableName, data);
- } else {
- await this.db.insert(this.tableName, data);
- }
- return data;
- }
- }
- async getQuality(filter) {
- if (filter.quality_id) return await this.getDataByCondition({ id: filter.quality_id });
- if (filter.rela_type && filter.rela_id) return await this.getDataByCondition({ tid: filter.tid || this.ctx.tender.id, rela_id: filter.rela_id, rela_name: filter.rela_name });
- throw '参数错误';
- }
- async _loadKgData(quality) {
- if (!quality.kaigong_time) return;
- quality.kaigong = {};
- for (const p in quality) {
- if (p.indexOf('kaigong_') !== 0) continue;
- quality.kaigong[p] = quality[p];
- delete quality[p];
- }
- const files = await this.ctx.service.qualityFile.getBlockFiles(quality, 'kaigong');
- quality.kaigong.files = files.filter(f => { return !f.spec_type; });
- quality.kaigong.qa_files = files.filter(f => { return f.spec_type === 'qa'; });
- // todo 加载开工审批数据
- }
- async _loadGxData(quality) {
- quality.gongxu = {};
- // todo 加载工序审批数据
- quality.gongxu.list = await this.ctx.service.qualityGongxu.getAllDataByCondition({ where: { quality_id: quality.id }, orders:[['create_time', 'asc']] });
- for (const gx of quality.gongxu.list) {
- gx.canEdit = gx.user_id === this.ctx.session.sessionUser.accountId;
- gx.files = await this.ctx.service.qualityFile.getBlockFiles(quality, 'gongxu', gx.id);
- // todo 加载工序步骤审批数据
- }
- }
- async _loadPdData(quality) {
- if (!quality.kaigong && quality.gongxu.list.length === 0) return;
- quality.pingding = {};
- for (const p in quality) {
- if (p.indexOf('pingding_') !== 0) continue;
- quality.kaigong[p] = quality[p];
- delete quality[p];
- }
- const files = await this.ctx.service.qualityFile.getBlockFiles(quality, 'pingding');
- quality.pingding.files = files.filter(f => { return !f.spec_type; });
- quality.pingding.source_files = files.filter(f => { return f.spec_type === 'add'; }); // addtional
- if (quality.gongxu) {
- for (const gx of quality.gongxu.list) {
- const qaFiles = gx.files.filter(f => { return f.spec_type === 'qa'; });
- for (const f of qaFiles) {
- const qaF = JSON.parse(JSON.stringify(f));
- qaF.canEdit = false;
- quality.pingding.source_files.push(qaF);
- }
- }
- }
- // todo 加载评定审批数据
- }
- async _loadJgData(quality) {
- if (!quality.kaigong && quality.gongxu.list.length === 0) return;
- quality.jiaogong = {};
- for (const p in quality) {
- if (p.indexOf('jiaogong_') !== 0) continue;
- quality.jiaogong[p] = quality[p];
- delete quality[p];
- }
- quality.jiaogong.files = await this.ctx.service.qualityFile.getBlockFiles(quality, 'jiaogong');
- }
- async _loadYbData(quality) {
- quality.yinbi = {};
- quality.yinbi.list = await this.ctx.service.qualityYinbi.getAllDataByCondition({ where: { quality_id: quality.id }, orders:[['create_time', 'asc']] });
- for (const yb of quality.yinbi.list) {
- yb.canEdit = yb.user_id === this.ctx.session.sessionUser.accountId;
- const files = await this.ctx.service.qualityFile.getBlockFiles(quality, 'yinbi', yb.id);
- yb.before_files = files.filter(f => { return f.spec_type === 'before'; });
- yb.after_files = files.filter(f => { return f.spec_type === 'after'; });
- }
- }
- async loadQualityDetail(quality) {
- if (!quality) return;
- await this._loadKgData(quality);
- await this._loadGxData(quality);
- await this._loadPdData(quality);
- await this._loadJgData(quality);
- await this._loadYbData(quality);
- }
- async getQualityGroup(quality) {
- if (quality.group_id) return quality.group_id;
- const ledger = await this.ctx.service.ledger.getDataById(quality.rela_id);
- const sql = 'SELECT l.id, l.ledger_id, l.level, q.group_id ' +
- ` FROM ${this.tableName} q LEFT JOIN ${this.ctx.service.ledger.tableName} l ON q.rela_id = l.id ` +
- ` WHERE q.tid = ${quality.tid} and l.ledger_id in (${ledger.full_path.split('-').join(', ')}) and group_id <> ''` +
- ' ORDER BY l.level DESC';
- const allQuality = await this.db.query(sql);
- return allQuality.length > 0 ? allQuality[0].group_id : '';
- }
- async checkQualityStatus(quality) {
- const groupId = await this.getQualityGroup(quality);
- if (!groupId) return null;
- const groupRule = await this.ctx.service.qualityRule.getGroupRule(groupId);
- if (!groupRule) return null;
- const ruleCheck = new RuleCheck();
- return ruleCheck.calcQualityStatus(quality, groupRule);
- }
- async checkQualityStatusAndSave(quality) {
- const data = await this.checkQualityStatus(quality);
- if (!data) return;
- for (const field in data) {
- quality[field] = data[field];
- }
- data.id = quality.id;
- await this.db.update(this.tableName, data);
- }
- async kaigong(filter, name, date) {
- const quality = await this.getQuality(filter);
- const conn = await this.db.beginTransaction();
- try {
- const kaigongData = {
- kaigong_name: name || '开工工序', kaigong_date: date || this.ctx.moment().format('YYYY-MM-DD'),
- kaigong_uid: this.ctx.session.sessionUser.accountId, kaigong_time: new Date(),
- };
- await this.saveQuality(quality, filter, kaigongData, conn);
- await conn.commit();
- } catch (err) {
- await conn.rollback();
- throw err;
- }
- }
- async delKaigong(filter) {
- const quality = await this.getQuality(filter);
- if (!quality || !quality.kaigong_uid) throw '该工程未开工';
- if (quality.kaigong_uid !== this.ctx.session.sessionUser.accountId) throw '开工数据不是您新增的,无权删除';
- const conn = await this.db.beginTransaction();
- try {
- await this.saveQuality(quality, filter, { kaigong_name: '', kaigong_date: '', kaigong_uid: 0, kaigong_time: null }, conn);
- await conn.update(this.ctx.service.qualityFile.tableName, { is_deleted: 1 }, { where: { quality_id: quality.id, block_type: 'kaigong' } });
- await conn.commit();
- } catch (err) {
- await conn.rollback();
- throw err;
- }
- }
- async pushIncStatus(select) {
- const quality = await this.ctx.service.quality.getAllDataByCondition({ where: { tid: this.ctx.tender.id, rela_id: select, is_used: 1 } });
- if (quality.length === 0) return 0;
- const xmjInsert = [], xmjUpdate = [], posInsert = [], posUpdate = [];
- const xmjQuality = [], posQuality = [];
- quality.forEach(q => {
- if (q.rela_type === 'xmj') {
- xmjQuality.push(q);
- } else {
- posQuality.push(q);
- }
- });
- const xmjExtra = xmjQuality.length > 0 ? await this.ctx.service.ledgerExtra.getAllDataByCondition({ where: { id: xmjQuality.map(x => { return x.rela_id; }) } }) : [];
- for (const xq of xmjQuality) {
- const xe = xmjExtra.find(x => { return x.id === xq.rela_id; });
- const wbs_url = `/3f/zh/info?pid=${this.ctx.session.sessionProject.id}&tid=${xq.tid}&${xq.rela_type}id=${xq.rela_id}`;
- if (xe) {
- xmjUpdate.push({ id: xe.id, gxby_status: xq.gxby_status, gxby_date: xq.gxby_date, dagl_status: xq.dagl_status, wbs_url });
- } else {
- xmjInsert.push({ id: xq.rela_id, gxby_status: xq.gxby_status, gxby_date: xq.gxby_date, dagl_status: xq.dagl_status, wbs_url });
- }
- }
- const posExtra = posQuality.length > 0 ? await this.ctx.service.posExtra.getAllDataByCondition({ where: { id: posQuality.map(x => { return x.rela_id; }) } }) : [];
- for (const pq of posQuality) {
- const pe = posExtra.find(x => { return x.id === pq.rela_id; });
- const wbs_url = `/3f/zh/info?pid=${this.ctx.session.sessionProject.id}&tid=${pq.tid}&${pq.rela_type}id=${pq.rela_id}`;
- if (pe) {
- posUpdate.push({ id: pe.id, gxby_status: pq.gxby_status, gxby_date: pq.gxby_date, dagl_status: pq.dagl_status, wbs_url });
- } else {
- posInsert.push({ id: pq.rela_id, gxby_status: pq.gxby_status, gxby_date: pq.gxby_date, dagl_status: pq.dagl_status, wbs_url });
- }
- }
- const conn = await this.db.beginTransaction();
- try {
- if (xmjInsert.length > 0) await conn.insert(this.ctx.service.ledgerExtra.tableName, xmjInsert);
- if (xmjUpdate.length > 0) await conn.updateRows(this.ctx.service.ledgerExtra.tableName, xmjUpdate);
- if (posInsert.length > 0) await conn.insert(this.ctx.service.posExtra.tableName, posInsert);
- if (posUpdate.length > 0) await conn.updateRows(this.ctx.service.posExtra.tableName, posUpdate);
- await conn.commit();
- } catch (err) {
- this.ctx.log(err);
- await conn.rollback();
- throw '推送状态错误';
- }
- return xmjInsert.length + xmjUpdate.length + posInsert.length + posUpdate.length;
- }
- async pushAllStatus() {
- const quality = await this.ctx.service.quality.getAllDataByCondition({ where: { tid: this.ctx.tender.id, is_used: 1 } });
- if (quality.length === 0) return 0;
- const xmjQuality = [], posQuality = [];
- quality.forEach(q => {
- if (q.rela_type === 'xmj') {
- xmjQuality.push(q);
- } else {
- posQuality.push(q);
- }
- });
- const xmjInsert = [], xmjUpdate = [], posInsert = [], posUpdate = [];
- const xmjExtra = await this.ctx.service.ledgerExtra.getAllDataByCondition({ where: { tid: this.ctx.tender.id } });
- for (const xq of xmjQuality) {
- const xe = xmjExtra.find(x => { return x.id === xq.rela_id; });
- const wbs_url = `/3f/zh/info?pid=${this.ctx.session.sessionProject.id}&tid=${xq.tid}&${xq.rela_type}id=${xq.rela_id}`;
- if (xe) {
- xmjUpdate.push({ id: xe.id, gxby_status: xq.gxby_status, gxby_date: xq.gxby_date, dagl_status: xq.dagl_status, wbs_url });
- } else {
- xmjInsert.push({ id: xq.rela_id, tid: this.ctx.tender.id, gxby_status: xq.gxby_status, gxby_date: xq.gxby_date, dagl_status: xq.dagl_status, wbs_url });
- }
- }
- const posExtra = await this.ctx.service.posExtra.getAllDataByCondition({ where: { tid: this.ctx.tender.id } });
- for (const pq of posQuality) {
- const pe = posExtra.find(x => { return x.id === pq.rela_id; });
- const wbs_url = `/3f/zh/info?pid=${this.ctx.session.sessionProject.id}&tid=${pq.tid}&${pq.rela_type}id=${pq.rela_id}`;
- if (pe) {
- posUpdate.push({ id: pe.id, gxby_status: pq.gxby_status, gxby_date: pq.gxby_date, dagl_status: pq.dagl_status, wbs_url });
- } else {
- posInsert.push({ id: pq.rela_id, tid: this.ctx.tender.id, gxby_status: pq.gxby_status, gxby_date: pq.gxby_date, dagl_status: pq.dagl_status, wbs_url });
- }
- }
- const conn = await this.db.beginTransaction();
- try {
- const defaultData = { gxby_status: -1, gxby_date: null, dagl_status: -1 };
- await conn.update(this.ctx.service.ledgerExtra.tableName, defaultData, { where: {tid: this.ctx.tender.id } });
- await conn.update(this.ctx.service.posExtra.tableName, defaultData, { where: {tid: this.ctx.tender.id } });
- if (xmjInsert.length > 0) await conn.insert(this.ctx.service.ledgerExtra.tableName, xmjInsert);
- if (xmjUpdate.length > 0) await conn.updateRows(this.ctx.service.ledgerExtra.tableName, xmjUpdate);
- if (posInsert.length > 0) await conn.insert(this.ctx.service.posExtra.tableName, posInsert);
- if (posUpdate.length > 0) await conn.updateRows(this.ctx.service.posExtra.tableName, posUpdate);
- await conn.commit();
- } catch (err) {
- this.ctx.log(err);
- await conn.rollback();
- throw '推送状态错误';
- }
- return xmjInsert.length + xmjUpdate.length + posInsert.length + posUpdate.length;
- }
- }
- return Quality;
- };
|