Skip to content

Commit

Permalink
3372 - adds database changes to support managing IAA subrecipients (#…
Browse files Browse the repository at this point in the history
…3522)

* feat: allow ability to find recipients using name

* feat: drop unique constraints on uei/tin and add name

* fix: typo

* fix: ensure validation to not call attribute on undefined

* feat: add tests for finding subrecipients

* fix: ensures recipients have a tenant_id

* fix: key-name in test to stop it from failing

* fix: linting and wrong name

* feat: add passing tests for all three cases for finding recipients

* feat: update createsubrecipient to enforce uniqueness constraints

* feat: ensure that all three fields uei/tin/name are checked for uniqueness

* feat: capture subrecipient field moving forward

* fix: update to use more idiomatic function calling

* fix: add docstrings and enum values for supported query-fields

* fix: ensure error is thrown when subrecipient is being queried using a wrong field-type

* fix: update migrations to have a more scoped index when values are not null. add unit-tests to ensure indexes work correctly

* fix: object structure of index

* chore: document multiple iterations of migration configuraiton to see what works

* fix: update migrations to create a unique-index rather than a unique-constraint or plain index

* fix: remove unnecessary comment

* fix: add descriptive comment
  • Loading branch information
as1729 authored Sep 20, 2024
1 parent d1fbf73 commit e974db6
Show file tree
Hide file tree
Showing 6 changed files with 500 additions and 67 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,242 @@
/*
--------------------------------------------------------------------------------
- tests/db/arpa-subrecipients.spec.js
--------------------------------------------------------------------------------
To see what the `arpa_subrecipients` table looks like in postgres, run the following command:
docker compose run --rm -it app /bin/bash
PGPASSWORD=password123 psql -U postgres -d usdr_grants -h postgres
\d arpa_subrecipients
*/
const { findRecipient, createRecipient } = requireSrc(__filename);
const assert = require('assert');
const knex = require('../../../../src/db/connection');
const { withTenantId } = require('../helpers/with-tenant-id');

const TENANT_A = 0;
const TENANT_B = 1;

describe('db/arpa-subrecipients.js', () => {
const recipients = {
beneficiaryWithTIN: {
tenant_id: TENANT_A,
name: 'Beneficiary with TIN',
tin: 'TIN-1',
uei: null,
},
iaa: {
tenant_id: TENANT_A,
name: 'IAA',
tin: null,
uei: null,
},
contractorWithUEI: {
tenant_id: TENANT_A,
name: 'Contractor with UEI',
tin: null,
uei: 'UEI-1',
},
};
before(async () => {
await knex.raw('TRUNCATE TABLE arpa_subrecipients CASCADE');
await knex('arpa_subrecipients').insert(Object.values(recipients));
});
describe('findRecipient', () => {
it('Returns a recipient with UEI', async () => {
const result = await withTenantId(TENANT_A, () => findRecipient('uei', 'UEI-1'));
assert.equal(result.name, 'Contractor with UEI');
});
it('Returns a recipient with TIN', async () => {
const result = await withTenantId(TENANT_A, () => findRecipient('tin', 'TIN-1'));
assert.equal(result.name, 'Beneficiary with TIN');
});
it('Returns a recipient with Name', async () => {
const result = await withTenantId(TENANT_A, () => findRecipient('name', 'IAA'));
assert.equal(result.name, 'IAA');
});
it('Throws error when querying for a recipient with an invalid field type', async () => {
await assert.rejects(
async () => {
await withTenantId(TENANT_A, () => findRecipient('invalid', 'IAA'));
},
(err) => {
assert.strictEqual(err.name, 'Error');
assert.strictEqual(err.message, 'Cannot query for recipient without a valid field type');
return true;
},
);
});
});

describe('createRecipient', () => {
it('Throws error when creating two contractors with the same UEI', async () => {
const recipient = {
tenant_id: TENANT_A,
name: 'Another Contractor with UEI',
tin: null,
uei: 'UEI-1',
};

await assert.rejects(
async () => {
await withTenantId(TENANT_A, () => createRecipient(recipient));
},
(err) => {
assert.strictEqual(err.name, 'Error');
assert.strictEqual(err.message, 'A recipient with this UEI already exists');
return true;
},
);
});
it('Throws error creating two beneficiaries with the same TIN', async () => {
const recipient = {
tenant_id: TENANT_A,
name: 'Another Beneficiary with TIN',
tin: 'TIN-1',
uei: null,
};

await assert.rejects(
async () => {
await withTenantId(TENANT_A, () => createRecipient(recipient));
},
(err) => {
assert.strictEqual(err.name, 'Error');
assert.strictEqual(err.message, 'A recipient with this TIN already exists');
return true;
},
);
});
it('Throws error creating two IAA with the same name and no UEI/TIN value', async () => {
const recipient = {
tenant_id: TENANT_A,
name: 'IAA',
tin: null,
uei: null,
};

await assert.rejects(
async () => {
await withTenantId(TENANT_A, () => createRecipient(recipient));
},
(err) => {
assert.strictEqual(err.name, 'Error');
assert.strictEqual(err.message, 'A recipient with this name already exists');
return true;
},
);
});
it('Throws error creating a subrecipient with no name, uei, or tin', async () => {
const recipient = {
tenant_id: TENANT_A,
name: null,
tin: null,
uei: null,
};

await assert.rejects(
async () => {
await withTenantId(TENANT_A, () => createRecipient(recipient));
},
(err) => {
assert.strictEqual(err.name, 'Error');
assert.strictEqual(err.message, 'recipient row must include a `uei`, `tin`, or `name` field');
return true;
},
);
});
});
describe('testing database indexes and constraints', () => {
const insertStatement = 'INSERT INTO arpa_subrecipients (tenant_id, name, tin, uei) VALUES ';
it('throws an error when inserting a duplicate UEI within the same tenant', async () => {
const recipient = {
tenant_id: TENANT_A,
name: 'Another Contractor with UEI',
tin: null,
uei: 'UEI-1',
};
const values = `(${recipient.tenant_id}, '${recipient.name}', ${recipient.tin}, '${recipient.uei}')`;
await assert.rejects(
async () => {
await withTenantId(TENANT_A, () => knex.raw(insertStatement + values));
},
(err) => {
assert.strictEqual(err.name, 'error');
assert.strictEqual(err.message, `INSERT INTO arpa_subrecipients (tenant_id, name, tin, uei) VALUES (0, 'Another Contractor with UEI', null, 'UEI-1') - duplicate key value violates unique constraint "idx_arpa_subrecipients_tenant_id_uei_unique"`);
return true;
},
);
});
it('successfully creates a new subrecipient with same UEI in a different tenant', async () => {
const recipient = {
tenant_id: TENANT_B,
name: 'Another Contractor with UEI',
tin: null,
uei: 'UEI-1',
};
const values = `(${recipient.tenant_id}, '${recipient.name}', ${recipient.tin}, '${recipient.uei}')`;
await withTenantId(TENANT_B, () => knex.raw(insertStatement + values));
const result = await withTenantId(TENANT_B, () => findRecipient('uei', 'UEI-1'));
assert.strictEqual(result.name, 'Another Contractor with UEI');
});
it('throws an error when inserting a duplicate TIN within the same tenant', async () => {
const recipient = {
tenant_id: TENANT_A,
name: 'Another Beneficiary with TIN',
tin: 'TIN-1',
uei: null,
};
const values = `(${recipient.tenant_id}, '${recipient.name}', '${recipient.tin}', ${recipient.uei})`;
await assert.rejects(
async () => {
await withTenantId(TENANT_A, () => knex.raw(insertStatement + values));
},
(err) => {
assert.strictEqual(err.name, 'error');
assert.strictEqual(err.message, `INSERT INTO arpa_subrecipients (tenant_id, name, tin, uei) VALUES (0, 'Another Beneficiary with TIN', 'TIN-1', null) - duplicate key value violates unique constraint "idx_arpa_subrecipients_tenant_id_tin_unique"`);
return true;
},
);
});
it('successfully creates a new subrecipient with same TIN in a different tenant', async () => {
const recipient = {
tenant_id: TENANT_B,
name: 'Another Beneficiary with TIN',
tin: 'TIN-1',
uei: null,
};
const values = `(${recipient.tenant_id}, '${recipient.name}', '${recipient.tin}', ${recipient.uei})`;
await withTenantId(TENANT_B, () => knex.raw(insertStatement + values));
const result = await withTenantId(TENANT_B, () => findRecipient('tin', 'TIN-1'));
assert.strictEqual(result.name, 'Another Beneficiary with TIN');
});
it('throws an error when inserting a duplicate name within the same tenant when UEI/TIN are null', async () => {
const recipient = {
tenant_id: TENANT_A,
name: 'IAA',
tin: null,
uei: null,
};
const values = `(${recipient.tenant_id}, '${recipient.name}', ${recipient.tin}, ${recipient.uei})`;
await assert.rejects(
() => knex.raw(insertStatement + values),
(err) => {
assert.strictEqual(err.name, 'error');
assert.strictEqual(err.message, `INSERT INTO arpa_subrecipients (tenant_id, name, tin, uei) VALUES (0, 'IAA', null, null) - duplicate key value violates unique constraint "idx_arpa_subrecipients_tenant_id_name_unique"`);
return true;
},
);
});
it('successfuly creates a new subrecipient with duplicate name in same tenant when UEI/TIN are not null', async () => {
const recipient = {
tenant_id: TENANT_A,
name: 'IAA',
tin: 'TIN-2',
uei: null,
};
const values = `(${recipient.tenant_id}, '${recipient.name}', '${recipient.tin}', ${recipient.uei})`;
await withTenantId(TENANT_A, () => knex.raw(insertStatement + values));
const result = await knex('arpa_subrecipients').where('tenant_id', TENANT_A).where('name', 'IAA');
assert.strictEqual(result.length, 2);
});
});
});
Loading

0 comments on commit e974db6

Please sign in to comment.