| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103 |
- 'use strict';
- // 独立回归测试:node --test test/app/service/advance_audit_order.test.js(无需连接数据库)
- const { test } = require('node:test');
- const assert = require('node:assert/strict');
- const _ = require('lodash');
- const status = require('../../../app/const/audit').advance.status;
- const Service = require('../../../app/service/advance_audit')({ BaseService: class {} });
- const { buildUpdates } = require('../../../db_script/bak/advance_audit_order');
- function fixture(rows) {
- const service = new Service();
- service._ = _;
- service.initSqlBuilder = () => { service.sqlBuilder = new (require('../../../app/lib/sql_builder'))(); };
- const advance = { id: 1, tid: 2, times: 1, type: 1, uid: 99, order: 1, cur_amount: 0 };
- let records = rows.map(x => ({ vid: 1, tid: 2, times: 1, type: 1, audit_type: 1, ...x }));
- const tx = {
- select: async (table, options) => _.orderBy(records.filter(x => _.isMatch(x, options.where)), options.orders.map(x => x[0]), options.orders.map(x => x[1])).map(x => ({ ...x })),
- insert: async (table, data) => {
- if (table === 'advance_audit') for (const row of [].concat(data)) records.push({ id: Math.max(0, ...records.map(x => x.id)) + 1, ...row });
- return { affectedRows: 1 };
- },
- update: async (table, row) => { if (table === 'advance_audit') Object.assign(records.find(x => x.id === row.id), row); },
- delete: async (table, where) => { records = records.filter(x => !_.isMatch(x, where)); },
- query: async (sql, params) => { assert(params.includes('times'), '退回顺移必须限定本轮'); },
- commit: async () => {}, rollback: async () => {},
- };
- service.db = { beginTransaction: async () => tx, query: async sql => {
- assert(sql.includes('`audit_order`') && sql.includes('`audit_type`'));
- return _.uniqBy(_.sortBy(records, 'audit_order'), 'audit_order').map(x => _.pick(x, ['tid', 'vid', 'type', 'audit_id', 'audit_order', 'audit_type']));
- } };
- service.getAllDataByCondition = async options => records.filter(x => _.isMatch(x, options.where));
- service.getDataByCondition = async where => records.find(x => _.isMatch(x, where));
- service.getAuditors = async () => _.sortBy(records, 'order').map(x => ({ ...x }));
- service._syncOrderByDelete = async (transaction, vid, order, times, operation, auditOrder) => {
- for (const x of records.filter(x => x.vid === vid && x.times === times)) {
- if (x.order >= order) x.order += operation === '+' ? 1 : -1;
- if (x.audit_order >= auditOrder) x.audit_order += operation === '+' ? 1 : -1;
- }
- };
- service.getNoticeContent = async () => '';
- service.ctx = { advance, tender: { id: 2, info: { shenpi: { advance: 1 } } }, session: { sessionProject: { id: 1 }, sessionUser: { accountId: 30 } },
- helper: { urlToShort: async () => '', sendWechat: async () => {} },
- service: { projectAccount: { getDataById: async () => ({ enable: 1, project_id: 1 }) },
- advance: { tableName: 'advance', getDataById: async () => advance }, noticePush: { tableName: 'notice' },
- noticeAgain: { stopNoticeAgain: async () => {}, addNoticeAgain: async () => {} }, specMsg: { addAdvanceMsg: async () => {} } } };
- return { service, advance, records: () => records };
- }
- test('中途插人后退回原报,保留插入位置和原终审', async () => {
- const f = fixture([{ id: 1, audit_id: 10, order: 1, audit_order: 1, status: status.checking }, { id: 2, audit_id: 30, order: 2, audit_order: 2, status: status.uncheck }]);
- await f.service.saveAudit(f.advance, { operate: 'add', old_aid: 10, new_aid: 20 });
- assert.deepEqual(_.sortBy(f.records(), 'order').map(x => [x.audit_id, x.audit_order]), [[10, 1], [20, 2], [30, 3]]);
- await f.service._checkNo(1, 1, { checkType: status.checkNo, opinion: '' }, 1);
- assert.deepEqual(f.records().filter(x => x.times === 2).map(x => [x.audit_id, x.order, x.audit_order, x.audit_type]), [[10, 1, 1, 1], [20, 2, 2, 1], [30, 3, 3, 1]]);
- });
- test('过程顺序与节点不同,插人分别移动两种序号,管理员取最新节点', async () => {
- const f = fixture([{ id: 1, audit_id: 10, order: 1, audit_order: 1, status: status.checked }, { id: 2, audit_id: 10, order: 4, audit_order: 1, status: status.checking }, { id: 3, audit_id: 30, order: 5, audit_order: 2, status: status.uncheck }]);
- await f.service.saveAudit(f.advance, { operate: 'add', old_aid: 10, new_aid: 20 });
- assert.deepEqual(_.sortBy(f.records(), 'order').map(x => [x.order, x.audit_order]), [[1, 1], [4, 1], [5, 2], [6, 3]]);
- assert.deepEqual((await f.service.getAuditGroupByList(1, 1)).map(x => x.audit_id), [10, 20, 30]);
- });
- test('顺移SQL使用独立边界并限定轮次', async () => {
- const s = new Service(), calls = [];
- s.db = { escape: x => x };
- s.initSqlBuilder = () => { s.sqlBuilder = new (require('../../../app/lib/sql_builder'))(); };
- await s._syncOrderByDelete({ query: async (...args) => calls.push(args) }, 1, 7, 2, '+', 3);
- assert(calls[0][0].includes('>= 7') && calls[0][0].includes('= 2'));
- assert.deepEqual(calls[1][1], ['advance_audit', 1, 2, 3]);
- });
- test('退回上一审只追加过程记录,节点序号保持不变', async () => {
- const f = fixture([{ id: 1, audit_id: 10, order: 1, audit_order: 1, status: status.checked }, { id: 2, audit_id: 30, order: 2, audit_order: 2, status: status.checking }]);
- await f.service._checkNoPre(1, 1, { checkType: status.checkNoPre, opinion: '' }, 1, 1);
- assert.deepEqual(f.records().slice(2).map(x => [x.audit_id, x.order, x.audit_order, x.audit_type]), [[10, 3, 1, 1], [30, 4, 2, 1]]);
- });
- test('终审重新审批,新增两条过程记录沿用终审节点', async () => {
- const f = fixture([{ id: 1, audit_id: 10, order: 1, audit_order: 1, status: status.checked }, { id: 2, audit_id: 30, order: 6, audit_order: 2, status: status.checked }]);
- f.advance.auditors = f.records();
- assert.equal(await f.service.checkAgain(f.advance), true);
- assert.deepEqual(f.records().slice(2).map(x => [x.order, x.audit_order, x.audit_type]), [[7, 2, 1], [8, 2, 1]]);
- });
- test('历史回填去重且可重复运行,冲突轮次跳过', () => {
- const rows = [{ id: 1, audit_id: 10, order: 1 }, { id: 2, audit_id: 30, order: 3 }, { id: 3, audit_id: 20, order: 2 }, { id: 4, audit_id: 10, order: 4 }];
- const updates = buildUpdates(rows).updates;
- assert.deepEqual(updates.map(x => x.audit_order), [1, 2, 3, 1]);
- assert.equal(buildUpdates(rows.map(x => ({ ...x, ...updates.find(y => y.id === x.id) }))).updates.length, 0);
- assert(buildUpdates([{ ...rows[0], audit_order: 5 }]).skip);
- });
- test('普通增加固定终审前人员、删除及替换同步节点', async () => {
- const f = fixture([{ id: 1, audit_id: 10, order: 1, audit_order: 1, status: status.uncheck }, { id: 2, audit_id: 30, order: 2, audit_order: 2, status: status.uncheck }]);
- await f.service.addAuditor(2, 1, 20, 1, 1, 1);
- assert.deepEqual(_.sortBy(f.records(), 'audit_order').map(x => x.audit_id), [10, 20, 30]);
- await f.service.saveAudit(f.advance, { operate: 'change', old_aid: 20, new_aid: 40 });
- assert.equal(f.records().find(x => x.audit_id === 40).audit_order, 2);
- await f.service.deleteAuditor(1, 40, 1);
- assert.deepEqual(_.sortBy(f.records(), 'audit_order').map(x => [x.audit_id, x.order, x.audit_order]), [[10, 1, 1], [30, 2, 2]]);
- });
|