UNPKG

@accounter/server

Version:

The test suite is split into three Vitest projects for efficiency and isolation:

225 lines (208 loc) • 6.23 kB
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 { IGetChargeIdsByPaymentIdsQuery, IGetInvoicesByIdsQuery, IGetInvoicesByIssueDatesQuery, IGetReceiptToChargeQuery, IInsertDeelInvoiceRecordsParams, IInsertDeelInvoiceRecordsQuery, } from '../types.js'; const getInvoicesByIssueDates = sql<IGetInvoicesByIssueDatesQuery>` SELECT * FROM accounter_schema.deel_invoices WHERE issued_at >= $from AND issued_at <= $to;`; const getInvoicesByIds = sql<IGetInvoicesByIdsQuery>` SELECT * FROM accounter_schema.deel_invoices WHERE id in $$ids;`; const getChargeIdsByPaymentIds = sql<IGetChargeIdsByPaymentIdsQuery>` SELECT d.charge_id, i.payment_id FROM accounter_schema.deel_invoices i LEFT JOIN accounter_schema.documents d ON i.document_id = d.id AND d.charge_id IS NOT NULL WHERE i.payment_id in $$paymentIds;`; const getReceiptToCharge = sql<IGetReceiptToChargeQuery>` SELECT DISTINCT ON (di.payment_id) di.payment_id, d.charge_id FROM accounter_schema.deel_invoices di LEFT JOIN accounter_schema.documents d ON d.id = di.document_id ORDER BY di.payment_id, di.created_at ASC;`; const insertDeelInvoiceRecords = sql<IInsertDeelInvoiceRecordsQuery>` INSERT INTO accounter_schema.deel_invoices ( id, document_id, amount, contract_id, created_at, currency, deel_fee, due_date, is_overdue, issued_at, label, paid_at, status, total, vat_id, vat_percentage, vat_total, adjustment, approve_date, approvers, bonus, commissions, contract_country, contract_start_date, contract_type, contractor_email, contractor_employee_name, contractor_unique_identifier, deductions, expenses, frequency, general_ledger_account, group_id, others, overtime, payment_currency, pro_rata, processing_fee, "work", total_payment_currency, payment_id) VALUES ($id, $documentId, $amount, $contractId, $createdAt, $currency, $deelFee, $dueDate, $isOverdue, $issuedAt, $label, $paidAt, $status, $total, $vatId, $vatPercentage, $vatTotal, $adjustment, $approveDate, $approvers, $bonus, $commissions, $contractCountry, $contractStartDate, $contractType, $contractorEmail, $contractorEmployeeName, $contractorUniqueIdentifier, $deductions, $expenses, $frequency, $generalLedgerAccount, $groupId, $others, $overtime, $paymentCurrency, $proRata, $processingFee, $work, $totalPaymentCurrency, $paymentId) RETURNING *;`; @Injectable({ scope: Scope.Singleton, global: true, }) export class DeelInvoicesProvider { cache = getCacheInstance({ stdTTL: 60 * 5, }); constructor(private dbProvider: DBProvider) {} private async batchInvoicesByIssueDates(issueDates: readonly Date[]) { const times = issueDates.map(date => date.getTime()); const from = new Date(Math.min(...times)); const to = new Date(Math.max(...times)); const records = await getInvoicesByIssueDates.run({ from, to }, this.dbProvider); return issueDates.map(date => { return records.filter(record => record.issued_at.getTime() === date.getTime()); }); } public async getInvoicesByIssueDates(from: Date, to: Date) { try { return getInvoicesByIssueDates.run({ from, to }, this.dbProvider); } catch (e) { const message = `Error getting Deel invoices by issue dates`; console.error(message, e); throw new Error(message); } } public getInvoicesByIssueDateLoader = new DataLoader( (dates: readonly Date[]) => this.batchInvoicesByIssueDates(dates), { cacheKeyFn: key => `invoices-issue-date-${key}`, cacheMap: this.cache, }, ); private async batchInvoicesByIds(ids: readonly string[]) { const invoices = await getInvoicesByIds.run({ ids }, this.dbProvider); return ids.map(id => invoices.find(invoice => invoice.id === id)); } public getInvoicesByIdLoader = new DataLoader( (ids: readonly string[]) => this.batchInvoicesByIds(ids), { cacheKeyFn: key => `invoices-id-${key}`, cacheMap: this.cache, }, ); private async batchChargeIdsByPaymentIds(paymentIds: readonly string[]) { const matches = await getChargeIdsByPaymentIds.run({ paymentIds }, this.dbProvider); return paymentIds.map( paymentId => matches.find(match => match.payment_id === paymentId)?.charge_id, ); } public getChargeIdByPaymentIdLoader = new DataLoader( (paymentIds: readonly string[]) => this.batchChargeIdsByPaymentIds(paymentIds), { cacheKeyFn: key => `charge-by-payment-${key}`, cacheMap: this.cache, }, ); public async getReceiptToCharge() { try { const records = await getReceiptToCharge.run(undefined, this.dbProvider); const receiptChargeMap = new Map<string, string>(); for (const record of records) { if (record.charge_id) { receiptChargeMap.set(record.payment_id, record.charge_id); } } return receiptChargeMap; } catch (e) { const message = `Error getting receipt to charge mapping`; console.error(message, e); throw new Error(message); } } public async insertDeelInvoiceRecords(params: IInsertDeelInvoiceRecordsParams) { try { // invalidate cache return insertDeelInvoiceRecords.run(params, this.dbProvider); } catch (e) { const message = `Error inserting Deel invoice`; console.error(message, e); throw new Error(message); } } }