@accounter/server
Version:
Accounter GraphQL server
130 lines (118 loc) • 4.14 kB
text/typescript
import DataLoader from 'dataloader';
import { Injectable, Scope } from 'graphql-modules';
// eslint-disable-next-line no-restricted-imports
import type { PoolClient } from 'pg';
import { sql } from '@pgtyped/runtime';
import { TenantAwareDBClient } from '../../app-providers/tenant-db-client.js';
import { adminBusinessUpdateSchema } from '../helpers/admin-businesses.helper.js';
import type {
IGetAdminBusinessesByIdsQuery,
IGetAllAdminBusinessesQuery,
IGetAllAdminBusinessesResult,
IInsertAdminBusinessQuery,
IUpdateAdminBusinessesParams,
IUpdateAdminBusinessesQuery,
IUpdateAdminBusinessesResult,
} from '../types.js';
const getAdminBusinessesByIds = sql<IGetAdminBusinessesByIdsQuery>`
SELECT ab.*, f.name, b.vat_number
FROM accounter_schema.businesses_admin ab
INNER JOIN accounter_schema.businesses b
USING (id)
INNER JOIN accounter_schema.financial_entities f
USING (id)
WHERE ab.id IN $$ids;`;
const getAllAdminBusinesses = sql<IGetAllAdminBusinessesQuery>`
SELECT ab.*, f.name, b.vat_number
FROM accounter_schema.businesses_admin ab
INNER JOIN accounter_schema.businesses b
USING (id)
INNER JOIN accounter_schema.financial_entities f
USING (id)
INNER JOIN accounter_schema.financial_entities fe
USING (id);`;
const updateAdminBusinesses = sql<IUpdateAdminBusinessesQuery>`
UPDATE accounter_schema.businesses_admin
SET
business_registration_start_date = COALESCE(
$businessRegistrationStartDate,
business_registration_start_date
),
company_tax_id = COALESCE(
$companyTaxId,
company_tax_id
),
advance_tax_rates = COALESCE(
$advanceTaxRates,
advance_tax_rates
),
tax_advances_ids = COALESCE(
$taxAdvancesIds,
tax_advances_ids
),
social_security_employer_ids = COALESCE(
$socialSecurityEmployerIds,
social_security_employer_ids
),
withholding_tax_annual_ids = COALESCE(
$withholdingTaxAnnualIds,
withholding_tax_annual_ids
)
WHERE
id = $id
RETURNING *;`;
const insertAdminBusiness = sql<IInsertAdminBusinessQuery>`
INSERT INTO accounter_schema.businesses_admin (id, owner_id) VALUES ($id, $id) ON CONFLICT (id) DO NOTHING;`;
({
scope: Scope.Operation,
global: true,
})
export class AdminBusinessesProvider {
constructor(private db: TenantAwareDBClient) {}
private async batchAdminBusinessesByIds(ids: readonly string[]) {
const uniqueIds = [...new Set(ids)];
const adminBusinesses = await getAdminBusinessesByIds.run(
{
ids: uniqueIds,
},
this.db,
);
adminBusinesses.map(adminBusiness => {
this.getAdminBusinessByIdLoader.prime(adminBusiness.id, adminBusiness);
});
return ids.map(id => adminBusinesses.find(admin => admin.id === id));
}
public getAdminBusinessByIdLoader = new DataLoader((ids: readonly string[]) =>
this.batchAdminBusinessesByIds(ids),
);
private allAdminBusinessesPromise: Promise<IGetAllAdminBusinessesResult[]> | null = null;
public getAllAdminBusinesses() {
if (this.allAdminBusinessesPromise) {
return this.allAdminBusinessesPromise;
}
this.allAdminBusinessesPromise = getAllAdminBusinesses
.run(undefined, this.db)
.then(adminBusinesses => {
adminBusinesses.map(adminBusiness => {
this.getAdminBusinessByIdLoader.prime(adminBusiness.id, adminBusiness);
});
return adminBusinesses;
});
return this.allAdminBusinessesPromise;
}
public async insertAdminBusiness(id: string, client?: PoolClient): Promise<void> {
await insertAdminBusiness.run({ id }, client ?? this.db);
}
public async updateAdminBusiness(
params: IUpdateAdminBusinessesParams,
): Promise<IUpdateAdminBusinessesResult> {
const inputParams = adminBusinessUpdateSchema.parse(params);
const [result] = await updateAdminBusinesses.run(inputParams, this.db);
this.clearCache();
return result;
}
public clearCache() {
this.allAdminBusinessesPromise = null;
this.getAdminBusinessByIdLoader.clearAll();
}
}