@accounter/server
Version:
The test suite is split into three Vitest projects for efficiency and isolation:
111 lines (99 loc) • 3.63 kB
text/typescript
import DataLoader from 'dataloader';
import { Injectable, Scope } from 'graphql-modules';
import { sql } from '@pgtyped/runtime';
import { getCacheInstance } from '../../../shared/helpers/index.js';
import { DBProvider } from '../../app-providers/db.provider.js';
import type {
IGetEmployeeIDsByContractIdsQuery,
IGetEmployeeIdsByDocumentIdsQuery,
IInsertDeelContractParams,
IInsertDeelContractQuery,
} from '../types.js';
const getEmployeeIDsByContractIds = sql<IGetEmployeeIDsByContractIdsQuery>`
SELECT *
FROM accounter_schema.deel_workers
WHERE contract_id in $$contractIds;`;
const getEmployeeIdsByDocumentIds = sql<IGetEmployeeIdsByDocumentIdsQuery>`
SELECT di.document_id, dw.business_id
FROM accounter_schema.deel_invoices di
LEFT JOIN accounter_schema.deel_workers dw
ON di.contract_id = dw.contract_id
WHERE di.document_id in $$documentIds;`;
const insertDeelContract = sql<IInsertDeelContractQuery>`
INSERT INTO accounter_schema.deel_workers (
contract_id,
contractor_id,
contractor_name,
contract_start_date,
business_id
)
VALUES (
$contractId,
$contractorId,
$contractorName,
$contractStartDate,
$businessId
)
RETURNING *;`;
({
scope: Scope.Singleton,
global: true,
})
export class DeelContractsProvider {
cache = getCacheInstance({
stdTTL: 60 * 5,
});
constructor(private dbProvider: DBProvider) {}
private async batchEmployeeIDsByContractIds(contractIds: readonly string[]) {
const contracts = await getEmployeeIDsByContractIds.run({ contractIds }, this.dbProvider);
return contractIds.map(id => {
const businessId = contracts.find(contract => contract.contract_id === id)?.business_id;
if (!businessId) {
throw new Error(`Missing businessId for Deel contract ID [${id}]`);
}
return businessId;
});
}
public getEmployeeIDByContractIdLoader = new DataLoader(
(contractIds: readonly string[]) => this.batchEmployeeIDsByContractIds(contractIds),
{
cacheKeyFn: key => `worker-contract-${key}`,
cacheMap: this.cache,
},
);
private async batchEmployeesByContractIds(contractIds: readonly string[]) {
const contracts = await getEmployeeIDsByContractIds.run({ contractIds }, this.dbProvider);
return contractIds.map(id => contracts.find(contract => contract.contract_id === id));
}
public getEmployeeByContractIdLoader = new DataLoader(
(contractIds: readonly string[]) => this.batchEmployeesByContractIds(contractIds),
{
cacheKeyFn: key => `worker-contract-full-${key}`,
cacheMap: this.cache,
},
);
private async batchEmployeeIdsByDocumentIds(documentIds: readonly string[]) {
const employeeMatches = await getEmployeeIdsByDocumentIds.run({ documentIds }, this.dbProvider);
return documentIds.map(
documentId =>
employeeMatches.find(match => match.document_id === documentId)?.business_id ?? null,
);
}
public getEmployeeIdByDocumentIdLoader = new DataLoader(
(documentIds: readonly string[]) => this.batchEmployeeIdsByDocumentIds(documentIds),
{
cacheKeyFn: key => `employee-by-document-${key}`,
cacheMap: this.cache,
},
);
public async insertDeelContract(params: IInsertDeelContractParams) {
try {
// invalidate cache
return insertDeelContract.run(params, this.dbProvider);
} catch (e) {
const message = `Error inserting Deel contract [${params.contractId}]`;
console.error(`${message}: ${e}`);
throw new Error(message);
}
}
}