@accounter/server
Version:
Accounter GraphQL server
331 lines • 10.8 kB
JavaScript
import { __decorate, __metadata } from "tslib";
import DataLoader from 'dataloader';
import { Injectable, Scope } from 'graphql-modules';
import { sql } from '@pgtyped/runtime';
import { LedgerLockError } from '../../../shared/errors.js';
import { reassureOwnerIdExists } from '../../../shared/helpers/index.js';
import { AdminContextProvider } from '../../admin-context/providers/admin-context.provider.js';
import { TenantAwareDBClient } from '../../app-providers/tenant-db-client.js';
import { validateLedgerRecordParams } from '../helpers/ledger-validation.helper.js';
const getLedgerRecordsByIds = sql `
SELECT *
FROM accounter_schema.ledger_records
WHERE id IN $$ids
AND owner_id = $ownerId;`;
const getLedgerRecordsByChargesIds = sql `
SELECT *
FROM accounter_schema.ledger_records
WHERE charge_id IN $$chargeIds
AND owner_id = $ownerId;`;
const getLedgerRecordsByFinancialEntityIds = sql `
SELECT *
FROM accounter_schema.ledger_records
WHERE debit_entity1 IN $$financialEntityIds
OR debit_entity2 IN $$financialEntityIds
OR credit_entity1 IN $$financialEntityIds
OR credit_entity1 IN $$financialEntityIds
AND owner_id = $ownerId;`;
const getLedgerRecordsByDates = sql `
SELECT *
FROM accounter_schema.ledger_records
WHERE invoice_date BETWEEN $fromDate AND $toDate
AND owner_id = $ownerId;`;
const getLedgerBalanceToDate = sql `
WITH grouped_entities AS (SELECT credit_entity1 AS entity_id, credit_local_amount1 AS amount, invoice_date
FROM accounter_schema.ledger_records
UNION
SELECT credit_entity1, credit_local_amount1, invoice_date
FROM accounter_schema.ledger_records
UNION
SELECT debit_entity1, debit_local_amount1 * -1, invoice_date
FROM accounter_schema.ledger_records
UNION
SELECT debit_entity2, debit_local_amount2 * -1, invoice_date
FROM accounter_schema.ledger_records)
SELECT entity_id, sum(amount)
FROM grouped_entities
WHERE invoice_date < $date
AND entity_id IS NOT NULL
GROUP BY entity_id;`;
const updateLedgerRecord = sql `
UPDATE accounter_schema.ledger_records
SET
charge_id = COALESCE(
$chargeId,
charge_id
),
credit_entity1 = COALESCE(
$creditEntity1,
credit_entity1
),
credit_entity2 = COALESCE(
$creditEntity2,
credit_entity2
),
credit_foreign_amount1 = COALESCE(
$creditForeignAmount1,
credit_foreign_amount1
),
credit_foreign_amount2 = COALESCE(
$creditForeignAmount2,
credit_foreign_amount2
),
credit_local_amount1 = COALESCE(
$creditLocalAmount1,
credit_local_amount1
),
credit_local_amount2 = COALESCE(
$creditLocalAmount2,
credit_local_amount2
),
currency = COALESCE(
$currency,
currency
),
debit_entity1 = COALESCE(
$debitEntity1,
debit_entity1
),
debit_entity2 = COALESCE(
$debitEntity2,
debit_entity2
),
debit_foreign_amount1 = COALESCE(
$debitForeignAmount1,
debit_foreign_amount1
),
debit_foreign_amount2 = COALESCE(
$debitForeignAmount2,
debit_foreign_amount2
),
debit_local_amount1 = COALESCE(
$debitLocalAmount1,
debit_local_amount1
),
debit_local_amount2 = COALESCE(
$debitLocalAmount2,
debit_local_amount2
),
description = COALESCE(
$description,
description
),
invoice_date = COALESCE(
$invoiceDate,
invoice_date
),
reference1 = COALESCE(
$reference,
reference1
),
value_date = COALESCE(
$valueDate,
value_date
)
WHERE
id = $ledgerId
AND owner_id = $ownerId
RETURNING *;
`;
const insertLedgerRecords = sql `
INSERT INTO accounter_schema.ledger_records (
charge_id,
credit_entity1,
credit_entity2,
credit_foreign_amount1,
credit_foreign_amount2,
credit_local_amount1,
credit_local_amount2,
currency,
debit_entity1,
debit_entity2,
debit_foreign_amount1,
debit_foreign_amount2,
debit_local_amount1,
debit_local_amount2,
description,
invoice_date,
owner_id,
reference1,
value_date
)
VALUES $$ledgerRecords(
chargeId,
creditEntity1,
creditEntity2,
creditForeignAmount1,
creditForeignAmount2,
creditLocalAmount1,
creditLocalAmount2,
currency,
debitEntity1,
debitEntity2,
debitForeignAmount1,
debitForeignAmount2,
debitLocalAmount1,
debitLocalAmount2,
description,
invoiceDate,
ownerId,
reference,
valueDate
)
RETURNING *;
`;
const deleteLedgerRecords = sql `
DELETE FROM accounter_schema.ledger_records
WHERE id IN $$ledgerRecordIds
AND owner_id = $ownerId;
`;
const deleteLedgerRecordsByChargeIds = sql `
DELETE FROM accounter_schema.ledger_records
WHERE charge_id IN $$chargeIds
AND owner_id = $ownerId;
`;
const replaceLedgerRecordsChargeId = sql `
UPDATE accounter_schema.ledger_records
SET
charge_id = $assertChargeID
WHERE
charge_id = $replaceChargeID
RETURNING *
`;
const lockLedgerRecords = sql `
UPDATE accounter_schema.ledger_records
SET
locked = TRUE
WHERE
invoice_date <= $date
OR value_date <= $date
RETURNING *
`;
let LedgerProvider = class LedgerProvider {
db;
adminContextProvider;
constructor(db, adminContextProvider) {
this.db = db;
this.adminContextProvider = adminContextProvider;
}
async batchLedgerRecordsByIds(ids) {
const { ownerId } = await this.adminContextProvider.getVerifiedAdminContext();
const ledgerRecords = await getLedgerRecordsByIds.run({
ids,
ownerId,
}, this.db);
return ids.map(id => ledgerRecords.find(record => record.id === id));
}
getLedgerRecordsByIdLoader = new DataLoader((ledgerIds) => this.batchLedgerRecordsByIds(ledgerIds));
async batchLedgerRecordsByChargesIds(ids) {
const { ownerId } = await this.adminContextProvider.getVerifiedAdminContext();
const ledgerRecords = await getLedgerRecordsByChargesIds.run({
chargeIds: ids,
ownerId,
}, this.db);
return ids.map(id => ledgerRecords.filter(record => record.charge_id === id));
}
getLedgerRecordsByChargesIdLoader = new DataLoader((keys) => this.batchLedgerRecordsByChargesIds(keys));
async batchLedgerRecordsByFinancialEntityIds(ids) {
const { ownerId } = await this.adminContextProvider.getVerifiedAdminContext();
const ledgerRecords = await getLedgerRecordsByFinancialEntityIds.run({
financialEntityIds: ids,
ownerId,
}, this.db);
return ids.map(id => ledgerRecords.filter(record => [
record.debit_entity1,
record.debit_entity2,
record.credit_entity1,
record.credit_entity2,
].includes(id)));
}
getLedgerRecordsByFinancialEntityIdLoader = new DataLoader((keys) => this.batchLedgerRecordsByFinancialEntityIds(keys));
async getLedgerRecordsByDates(params) {
const { ownerId } = await this.adminContextProvider.getVerifiedAdminContext();
return getLedgerRecordsByDates.run(reassureOwnerIdExists(params, ownerId), this.db);
}
getLedgerBalanceToDate(date) {
return getLedgerBalanceToDate.run({ date }, this.db);
}
async updateLedgerRecord(params) {
// validate non are locked
if (params.ledgerId) {
const record = await this.getLedgerRecordsByIdLoader.load(params.ledgerId);
if (record?.locked) {
throw new LedgerLockError();
}
}
this.clearCache();
const { ownerId } = await this.adminContextProvider.getVerifiedAdminContext();
return updateLedgerRecord.run(reassureOwnerIdExists(params, ownerId), this.db);
}
async insertLedgerRecords(params) {
if (params.ledgerRecords.length === 0)
return [];
this.clearCache();
const { defaultLocalCurrency } = await this.adminContextProvider.getVerifiedAdminContext();
params.ledgerRecords.map(record => validateLedgerRecordParams(record, defaultLocalCurrency));
return insertLedgerRecords.run(params, this.db);
}
async deleteLedgerRecordsByIds(ids) {
// validate non are locked
const records = await this.getLedgerRecordsByIdLoader.loadMany(ids);
records.map(record => {
if (record instanceof Error) {
throw record;
}
if (record?.locked) {
throw new LedgerLockError();
}
});
this.clearCache();
const { ownerId } = await this.adminContextProvider.getVerifiedAdminContext();
await deleteLedgerRecords.run({
ledgerRecordIds: ids,
ownerId,
}, this.db);
return ids.map(_id => void 0);
}
deleteLedgerRecordsByIdLoader = new DataLoader((keys) => this.deleteLedgerRecordsByIds(keys), { cache: false });
async deleteLedgerRecordsByChargeIds(chargeIds) {
// validate non are locked
const records = await this.getLedgerRecordsByChargesIdLoader.loadMany(chargeIds);
records.map(record => {
if (record instanceof Error) {
throw record;
}
if (record.some(r => r.locked)) {
throw new LedgerLockError();
}
});
this.clearCache();
const { ownerId } = await this.adminContextProvider.getVerifiedAdminContext();
await deleteLedgerRecordsByChargeIds.run({
chargeIds,
ownerId,
}, this.db);
return chargeIds.map(_id => void 0);
}
deleteLedgerRecordsByChargeIdLoader = new DataLoader((chargeIds) => this.deleteLedgerRecordsByChargeIds(chargeIds), { cache: false });
replaceLedgerRecordsChargeId(params) {
this.clearCache();
return replaceLedgerRecordsChargeId.run(params, this.db);
}
lockLedgerRecords(date) {
this.clearCache();
return lockLedgerRecords.run({ date }, this.db);
}
clearCache() {
this.getLedgerRecordsByIdLoader.clearAll();
this.getLedgerRecordsByChargesIdLoader.clearAll();
this.getLedgerRecordsByFinancialEntityIdLoader.clearAll();
}
};
LedgerProvider = __decorate([
Injectable({
scope: Scope.Operation,
global: true,
}),
__metadata("design:paramtypes", [TenantAwareDBClient,
AdminContextProvider])
], LedgerProvider);
export { LedgerProvider };
//# sourceMappingURL=ledger.provider.js.map