| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380 |
- 'use strict';
- const assert = require('node:assert/strict');
- const test = require('node:test');
- const moment = require('moment');
- const makeController = require('../../../app/controller/weapp_contract_controller');
- test('合同目录使用 UUID 子项目 ID 查询,不转换为数字', async () => {
- const spid = '5472d997-c4ae-4421-8265-feb6ab0833db';
- const projectId = '06c6dd13-e52b-4c37-9d90-468cf32942aa';
- const calls = [];
- const ctx = {
- query: { spid, type: 'expenses' },
- session: {
- sessionProject: { id: projectId },
- sessionUser: { is_admin: true },
- },
- service: {
- subProject: {
- getDataById: async id => {
- calls.push([ 'subProject', id ]);
- return { id: spid, project_id: projectId, page_show: '{}' };
- },
- getPageShow: () => ({ openContract: true }),
- },
- subProjPermission: { adminPermission: {} },
- contractTree: {
- insertTree: async options => calls.push([ 'insertTree', options ]),
- getAllDataByCondition: async options => {
- calls.push([ 'folders', options ]);
- return [{ contract_id: 1, contract_pid: -1, name: '第一部分' }];
- },
- },
- contract: {
- getListByUsers: async options => {
- calls.push([ 'contracts', options ]);
- return [{ id: 'contract-row-id', contract_id: 2, contract_pid: 1, name: '测试合同' }];
- },
- },
- contractAtt: {
- getCounts: async ids => {
- calls.push([ 'files', ids ]);
- return new Map([[ 'contract-row-id', 2 ]]);
- },
- },
- },
- };
- const Controller = makeController({ BaseController: class {} });
- await Controller.prototype.catalog.call({ log: () => {} }, ctx);
- assert.equal(ctx.body.code, 0);
- assert.deepEqual(calls[0], [ 'subProject', spid ]);
- assert.deepEqual(calls[1], [ 'insertTree', { spid } ]);
- assert.deepEqual(calls[2][1].where, { spid, contract_type: 1 });
- assert.deepEqual(calls[4], [ 'files', [ 'contract-row-id' ] ]);
- assert.equal(ctx.body.data.nodes[1].fileCount, 2);
- });
- test('标段合同目录使用 tid 查询,并校验当前项目和合同成员', async () => {
- const spid = '5472d997-c4ae-4421-8265-feb6ab0833db';
- const projectId = '06c6dd13-e52b-4c37-9d90-468cf32942aa';
- const calls = [];
- const ctx = {
- query: { spid, tid: '4852', type: 'income' },
- session: {
- sessionProject: { id: projectId },
- sessionUser: { is_admin: false, accountId: 'user-id' },
- },
- service: {
- subProject: {
- getDataById: async () => ({ id: spid, project_id: projectId, page_show: '{}' }),
- getPageShow: () => ({ openTenderContract: true }),
- },
- subProjPermission: {
- getSubProjectUserPermission: async () => ({ contract_permission: [] }),
- },
- tender: {
- getDataById: async id => {
- calls.push([ 'tender', id ]);
- return { id, spid, project_id: projectId };
- },
- },
- contractAudit: {
- getDataByCondition: async options => {
- calls.push([ 'audit', options ]);
- return { id: 'audit-id' };
- },
- },
- contractTree: {
- insertTree: async options => calls.push([ 'insertTree', options ]),
- getAllDataByCondition: async options => {
- calls.push([ 'folders', options ]);
- return [];
- },
- },
- contract: { getListByUsers: async () => [] },
- contractAtt: { getCounts: async () => new Map() },
- },
- };
- const Controller = makeController({ BaseController: class {} });
- await Controller.prototype.catalog.call({ log: () => {} }, ctx);
- assert.equal(ctx.body.code, 0);
- assert.deepEqual(calls[0], [ 'tender', 4852 ]);
- assert.deepEqual(calls[1], [ 'audit', { tid: 4852, uid: 'user-id' } ]);
- assert.deepEqual(calls[2], [ 'insertTree', { tid: 4852 } ]);
- assert.deepEqual(calls[3][1].where, { tid: 4852, contract_type: 2 });
- });
- test('标段合同选择列表只返回当前子项目的合同标段', async () => {
- const spid = '5472d997-c4ae-4421-8265-feb6ab0833db';
- const projectId = '06c6dd13-e52b-4c37-9d90-468cf32942aa';
- const ctx = {
- query: { spid },
- session: {
- sessionProject: { id: projectId },
- sessionUser: { is_admin: true, accountId: 'user-id' },
- },
- service: {
- subProject: {
- getDataById: async () => ({ id: spid, project_id: projectId, page_show: '{}' }),
- getPageShow: () => ({ openTenderContract: true }),
- },
- projectAccount: { getDataById: async () => ({ self_category_level: '' }) },
- tender: {
- getContractList: async () => {
- assert.equal(ctx.subProject.id, spid);
- return [{ id: 4852, name: '测试标段' }];
- },
- },
- category: { getAllCategory: async () => [] },
- },
- };
- const Controller = makeController({ BaseController: class {} });
- await Controller.prototype.tenderList.call({ log: () => {} }, ctx);
- assert.equal(ctx.body.code, 0);
- assert.deepEqual(ctx.body.data.tenderList, [{ id: 4852, name: '测试标段' }]);
- });
- test('标段合同概况按 tid 汇总金额,并补齐近六个月趋势', async () => {
- const spid = '5472d997-c4ae-4421-8265-feb6ab0833db';
- const projectId = '06c6dd13-e52b-4c37-9d90-468cf32942aa';
- const scopes = [];
- const ctx = {
- query: { spid, tid: '4852' },
- session: {
- sessionProject: { id: projectId },
- sessionUser: { is_admin: true, accountId: 'user-id' },
- },
- helper: {
- add: (a, b) => Number(a) + Number(b),
- sub: (a, b) => Number(a) - Number(b),
- div: (a, b) => Number(a) / Number(b),
- round: (a, digits) => Number(a.toFixed(digits)),
- },
- service: {
- subProject: {
- getDataById: async () => ({ id: spid, project_id: projectId, page_show: '{}' }),
- getPageShow: () => ({ openTenderContract: true }),
- },
- subProjPermission: { adminPermission: {} },
- tender: { getDataById: async () => ({ id: 4852, spid, project_id: projectId }) },
- contract: {
- getListByUsers: async options => {
- scopes.push(options);
- return options.contract_type === 1
- ? [
- { id: 'expense-contract', total_price: 1000, yf_price: 250, sf_price: 180 },
- { id: 'expense-contract', total_price: 1000, yf_price: 250, sf_price: 180 },
- ]
- : [{ id: 'income-contract', total_price: 2000, yf_price: 500, sf_price: 400 }];
- },
- },
- contractPay: {
- getMonthlyYfPrice: async ids => [{
- month: moment().format('YYYY-MM'),
- amount: ids[0] === 'expense-contract' ? 100 : 200,
- }],
- },
- },
- };
- const Controller = makeController({ BaseController: class {} });
- await Controller.prototype.summary.call({ log: () => {} }, ctx);
- assert.equal(ctx.body.code, 0);
- assert.deepEqual(scopes, [
- { tid: 4852, contract_type: 1 },
- { tid: 4852, contract_type: 2 },
- ]);
- assert.deepEqual(ctx.body.data.expenses, {
- total: 1000, paid: 180, unpaid: 820, percent: 25,
- trend: [0, 0, 0, 0, 0, 100],
- });
- assert.deepEqual(ctx.body.data.income, {
- total: 2000, paid: 400, unpaid: 1600, percent: 25,
- trend: [0, 0, 0, 0, 0, 200],
- });
- assert.equal(ctx.body.data.months.length, 6);
- });
- test('项目合同概况按 spid 查询,空合同返回零值', async () => {
- const spid = '5472d997-c4ae-4421-8265-feb6ab0833db';
- const projectId = '06c6dd13-e52b-4c37-9d90-468cf32942aa';
- const scopes = [];
- const ctx = {
- query: { spid },
- session: {
- sessionProject: { id: projectId },
- sessionUser: { is_admin: true },
- },
- helper: { add: (a, b) => Number(a) + Number(b), sub: (a, b) => Number(a) - Number(b) },
- service: {
- subProject: {
- getDataById: async () => ({ id: spid, project_id: projectId, page_show: '{}' }),
- getPageShow: () => ({ openContract: true }),
- },
- subProjPermission: { adminPermission: {} },
- contract: {
- getListByUsers: async options => {
- scopes.push(options);
- return [];
- },
- },
- contractPay: { getMonthlyYfPrice: async () => [] },
- },
- };
- const Controller = makeController({ BaseController: class {} });
- await Controller.prototype.summary.call({ log: () => {} }, ctx);
- assert.equal(ctx.body.code, 0);
- assert.deepEqual(scopes, [
- { spid, contract_type: 1 },
- { spid, contract_type: 2 },
- ]);
- assert.deepEqual(ctx.body.data.expenses, {
- total: 0, paid: 0, unpaid: 0, percent: 0,
- trend: [0, 0, 0, 0, 0, 0],
- });
- });
- test('合同详情只返回当前可见合同的支付与文件', async () => {
- const spid = '5472d997-c4ae-4421-8265-feb6ab0833db';
- const projectId = '06c6dd13-e52b-4c37-9d90-468cf32942aa';
- const queries = [];
- const ctx = {
- query: { spid, type: 'expenses', cid: 'contract-row-id' },
- session: {
- sessionProject: { id: projectId },
- sessionUser: { is_admin: true },
- },
- service: {
- subProject: {
- getDataById: async () => ({ id: spid, project_id: projectId, page_show: '{}' }),
- getPageShow: () => ({ openContract: true }),
- },
- subProjPermission: { adminPermission: {} },
- contract: {
- getListByUsers: async () => [{
- id: 'contract-row-id', name: '测试合同', total_price: 1000,
- pay_price: 800, debit_price: 50, yf_price: 750, sf_price: 500,
- party_a_user: '甲方签约人', party_b_user: '乙方签约人',
- entity: '收款单位', settle_code: 'JS-001',
- }],
- },
- contractPay: {
- getAllDataByCondition: async options => {
- queries.push(options.where);
- return [{ id: 1, pay_type: '网上转账', sf_price: 500, pay_time: '2025-12-06' }];
- },
- },
- contractAtt: {
- getAllDataByCondition: async options => {
- queries.push(options.where);
- return [{ id: 2, filename: '合同.pdf', filesize: '1.34 MB', filepath: 'private/file.pdf' }];
- },
- },
- },
- };
- const Controller = makeController({ BaseController: class {} });
- await Controller.prototype.detail.call({ log: () => {} }, ctx);
- assert.equal(ctx.body.code, 0);
- assert.deepEqual(queries, [
- { spid, contract_type: 1, cid: 'contract-row-id' },
- { spid, contract_type: 1, cid: 'contract-row-id' },
- ]);
- assert.equal(ctx.body.data.pays[0].sf_price, 500);
- assert.equal(ctx.body.data.contract.pay_price, 800);
- assert.equal(ctx.body.data.contract.yf_price, 750);
- assert.equal(ctx.body.data.contract.party_a_user, '甲方签约人');
- assert.equal(ctx.body.data.contract.entity, '收款单位');
- assert.equal(ctx.body.data.contract.settle_code, 'JS-001');
- assert.equal(ctx.body.data.files[0].filename, '合同.pdf');
- assert.equal(ctx.body.data.files[0].filepath, undefined);
- });
- test('合同文件下载拒绝其他合同的文件', async () => {
- const spid = '5472d997-c4ae-4421-8265-feb6ab0833db';
- const projectId = '06c6dd13-e52b-4c37-9d90-468cf32942aa';
- let readOss = false;
- const ctx = {
- query: { spid, type: 'expenses', cid: 'contract-row-id' },
- params: { fid: '2' },
- session: {
- sessionProject: { id: projectId },
- sessionUser: { is_admin: true },
- },
- service: {
- subProject: {
- getDataById: async () => ({ id: spid, project_id: projectId, page_show: '{}' }),
- getPageShow: () => ({ openContract: true }),
- },
- subProjPermission: { adminPermission: {} },
- contract: {
- getListByUsers: async () => [{ id: 'contract-row-id', name: '测试合同' }],
- },
- contractAtt: {
- getDataById: async () => ({ id: 2, cid: 'another-contract', spid, contract_type: 1, filepath: 'private/file.pdf' }),
- },
- },
- helper: {
- ossFileGet: async () => {
- readOss = true;
- },
- },
- };
- const Controller = makeController({ BaseController: class {} });
- await Controller.prototype.downloadFile.call({ log: () => {} }, ctx);
- assert.equal(ctx.status, 404);
- assert.equal(ctx.body.code, -1);
- assert.equal(readOss, false);
- });
- test('标段合同文件通过所属标段校验后返回文件内容', async () => {
- const spid = '5472d997-c4ae-4421-8265-feb6ab0833db';
- const projectId = '06c6dd13-e52b-4c37-9d90-468cf32942aa';
- const headers = {};
- const ctx = {
- query: { spid, tid: '4852', type: 'income', cid: 'contract-row-id' },
- params: { fid: '2' },
- session: {
- sessionProject: { id: projectId },
- sessionUser: { is_admin: true },
- },
- service: {
- subProject: {
- getDataById: async () => ({ id: spid, project_id: projectId, page_show: '{}' }),
- getPageShow: () => ({ openTenderContract: true }),
- },
- subProjPermission: { adminPermission: {} },
- tender: { getDataById: async () => ({ id: 4852, spid, project_id: projectId }) },
- contract: {
- getListByUsers: async options => {
- assert.deepEqual(options, { tid: 4852, contract_type: 2 });
- return [{ id: 'contract-row-id' }];
- },
- },
- contractAtt: {
- getDataById: async () => ({
- id: 2, cid: 'contract-row-id', tid: 4852, contract_type: 2,
- filename: '合同.pdf', fileext: '.pdf', filepath: 'private/file.pdf',
- }),
- },
- },
- response: { set: values => Object.assign(headers, values) },
- helper: {
- ossFileGet: async path => {
- assert.equal(path, 'private/file.pdf');
- return Buffer.from('test file');
- },
- },
- };
- const Controller = makeController({ BaseController: class {} });
- await Controller.prototype.downloadFile.call({ log: () => {} }, ctx);
- assert.equal(headers['Content-Type'], 'application/pdf');
- assert.deepEqual(ctx.body, Buffer.from('test file'));
- });
|