@accounter/server
Version:
Accounter GraphQL server
214 lines (210 loc) • 7.62 kB
text/typescript
import { Injectable, Scope } from 'graphql-modules';
import { sql } from '@pgtyped/runtime';
import { TenantAwareDBClient } from '../../app-providers/tenant-db-client.js';
import { IGetNormalizedRevenueRecordsParams, IGetNormalizedRevenueRecordsQuery } from '../types.js';
const getNormalizedRevenueRecords = sql<IGetNormalizedRevenueRecordsQuery>`
WITH
normalizedLedgerRevenue AS (
WITH
ChargeBusinessID AS (
-- 1. Gather potential Business IDs from transactions and documents
SELECT
t.charge_id,
CASE
WHEN array_length(ARRAY_AGG(DISTINCT potential_id), 1) = 1 THEN ARRAY_AGG(DISTINCT potential_id)
ELSE NULL
END AS entity_id
FROM
(
-- IDs from 'transactions' table (if not a fee and not null)
SELECT
charge_id,
business_id AS potential_id
FROM
accounter_schema.transactions
WHERE
NOT is_fee
AND business_id IS NOT NULL
UNION ALL
-- IDs from 'documents' table (creditor_id if not OWNER_ID and not null)
SELECT
charge_id,
creditor_id AS potential_id
FROM
accounter_schema.documents
WHERE
creditor_id IS NOT NULL
AND creditor_id <> $ownerId -- OWNER_ID constant
UNION ALL
-- IDs from 'documents' table (debtor_id if not OWNER_ID and not null)
SELECT
charge_id,
debtor_id AS potential_id
FROM
accounter_schema.documents
WHERE
debtor_id IS NOT NULL
AND debtor_id <> $ownerId -- OWNER_ID constant
) t
GROUP BY
t.charge_id
)
SELECT
ledger_records.id,
ledger_records.charge_id,
ledger_records.owner_id,
ledger_records.debit_local_amount1 as amount_local,
ledger_records.debit_foreign_amount1 as amount_foreign,
ledger_records.currency as currency,
ledger_records.value_date as date,
ledger_records.reference1 as reference,
ledger_records.description as description,
ledger_records.debit_entity1 as business_id,
b.country as country
FROM
accounter_schema.ledger_records
LEFT JOIN accounter_schema.businesses b ON b.id = ledger_records.debit_entity1
WHERE
(
ledger_records.credit_entity1 IN $$incomeTaxCategoriesIDs
OR ledger_records.credit_entity2 IN $$incomeTaxCategoriesIDs
)
AND ledger_records.owner_id = $ownerId
AND ledger_records.value_date BETWEEN $fromDate AND $toDate
UNION
SELECT
ledger_records.id,
ledger_records.charge_id,
ledger_records.owner_id,
ledger_records.credit_local_amount1 * -1 as amount_local,
ledger_records.credit_foreign_amount1 * -1 as amount_foreign,
ledger_records.currency as currency,
ledger_records.value_date as date,
ledger_records.reference1 as reference,
ledger_records.description as description,
ledger_records.credit_entity1 as business_id,
b.country as country
FROM
accounter_schema.ledger_records
LEFT JOIN accounter_schema.businesses b ON b.id = ledger_records.credit_entity1
WHERE
(
ledger_records.debit_entity1 IN $$incomeTaxCategoriesIDs
OR ledger_records.debit_entity2 IN $$incomeTaxCategoriesIDs
)
AND ledger_records.owner_id = $ownerId
AND ledger_records.value_date BETWEEN $fromDate AND $toDate
UNION
SELECT
ledger_records.id,
ledger_records.charge_id,
ledger_records.owner_id,
ledger_records.debit_local_amount1 * -1 as amount_local,
ledger_records.debit_foreign_amount1 * -1 as amount_foreign,
ledger_records.currency as currency,
ledger_records.invoice_date as date,
ledger_records.reference1 as reference,
ledger_records.description as description,
cbi.entity_id[1] as business_id,
b.country as country
FROM
accounter_schema.ledger_records
LEFT JOIN ChargeBusinessID cbi ON ledger_records.charge_id = cbi.charge_id
LEFT JOIN accounter_schema.businesses b ON b.id = cbi.entity_id[1]
WHERE
(
ledger_records.credit_entity1 = $incomeToCollectId
OR ledger_records.credit_entity2 = $incomeToCollectId
)
AND ledger_records.owner_id = $ownerId
AND ledger_records.invoice_date = $fromDate
UNION
SELECT
ledger_records.id,
ledger_records.charge_id,
ledger_records.owner_id,
ledger_records.credit_local_amount1 as amount_local,
ledger_records.credit_foreign_amount1 as amount_foreign,
ledger_records.currency as currency,
ledger_records.invoice_date as date,
ledger_records.reference1 as reference,
ledger_records.description as description,
cbi.entity_id[1] as business_id,
b.country as country
FROM
accounter_schema.ledger_records
LEFT JOIN ChargeBusinessID cbi ON ledger_records.charge_id = cbi.charge_id
LEFT JOIN accounter_schema.businesses b ON b.id = cbi.entity_id[1]
WHERE
(
ledger_records.debit_entity1 = $incomeToCollectId
OR ledger_records.debit_entity2 = $incomeToCollectId
)
AND ledger_records.owner_id = $ownerId
AND ledger_records.invoice_date = $toDate
)
SELECT
nlr.*,
CASE
WHEN nlr.currency = 'USD' THEN nlr.amount_foreign
WHEN nlr.currency = 'ILS' THEN nlr.amount_local / lr.usd -- Convert ILS => USD
WHEN nlr.currency = 'AUD' THEN nlr.amount_foreign * (lr.aud / lr.usd) -- Convert AUD => ILS => USD
WHEN nlr.currency = 'CAD' THEN nlr.amount_foreign * (lr.cad / lr.usd) -- Convert CAD => ILS => USD
WHEN nlr.currency = 'EUR' THEN nlr.amount_foreign * (lr.eur / lr.usd) -- Convert EUR => ILS => USD
WHEN nlr.currency = 'GBP' THEN nlr.amount_foreign * (lr.gbp / lr.usd) -- Convert GBP => ILS => USD
WHEN nlr.currency = 'JPY' THEN nlr.amount_foreign * (lr.jpy / lr.usd) -- Convert JPY => ILS => USD
WHEN nlr.currency = 'SEK' THEN nlr.amount_foreign * (lr.sek / lr.usd) -- Convert SEK => ILS => USD
WHEN nlr.currency = 'USDC'
OR nlr.currency = 'GRT'
OR nlr.currency = 'ETH' THEN nlr.amount_foreign * lr2.value -- Convert Crypto => USD
END AS amount_usd
FROM
normalizedLedgerRevenue nlr
LEFT JOIN LATERAL (
SELECT
er.usd,
er.eur,
er.gbp,
er.cad,
er.jpy,
er.aud,
er.sek
FROM
accounter_schema.exchange_rates er
WHERE
er.exchange_date <= nlr.date
ORDER BY
er.exchange_date DESC
LIMIT
1
) lr ON TRUE
LEFT JOIN LATERAL (
SELECT
cer.value
FROM
accounter_schema.crypto_exchange_rates cer
WHERE
cer.date <= nlr.date
AND cer.coin_symbol::accounter_schema.currency = nlr.currency
AND cer.against = 'USD'
ORDER BY
cer.date DESC
LIMIT
1
) lr2 ON nlr.date IS NOT NULL;`;
@Injectable({
scope: Scope.Operation,
global: true,
})
export class AnnualRevenueReportProvider {
constructor(private db: TenantAwareDBClient) {}
public async getNormalizedRevenueRecords(params: IGetNormalizedRevenueRecordsParams) {
try {
return getNormalizedRevenueRecords.run(params, this.db);
} catch (error) {
const message = 'Failed to get balance transactions';
console.error(`${message}: ${error}`);
throw new Error(message, { cause: error });
}
}
}