@accounter/server
Version:
Accounter GraphQL server
531 lines • 15.9 kB
JavaScript
import { __decorate, __metadata } from "tslib";
import { Injectable, Scope } from 'graphql-modules';
import { sql } from '@pgtyped/runtime';
import { dateToTimelessDateString } from '../../../shared/helpers/index.js';
import { TenantAwareDBClient } from '../../app-providers/tenant-db-client.js';
import { FiatExchangeProvider } from '../../exchange-rates/providers/fiat-exchange.provider.js';
import { formatValue } from '../helpers/utils.helper.js';
import { validateCalTransactions, validateDiscountTransactions, validateMaxTransactions, validateRates, } from '../helpers/validators.helper.js';
const uploadCalTransactions = sql `
INSERT INTO accounter_schema.cal_creditcard_transactions (
card,
trn_int_id,
trn_numaretor,
merchant_name,
trn_purchase_date,
trn_amt,
trn_currency_symbol,
trn_type,
trn_type_code,
deb_crd_date,
amt_before_conv_and_index,
deb_crd_currency_symbol,
merchant_address,
merchant_phone_no,
branch_code_desc,
trans_card_present_ind,
cur_payment_num,
num_of_payments,
token_ind,
wallet_provider_code,
wallet_provider_desc,
token_number_part4,
cash_account_trn_amt,
charge_external_to_card_comment,
refund_ind,
is_immediate_comment_ind,
is_immediate_hhk_ind,
is_margarita,
is_spread_paymenst_abroad,
trn_exac_way,
debit_spread_ind,
on_going_transactions_comment,
early_payment_ind,
merchant_id,
crd_ext_id_num_type_code,
trans_source,
is_abroad_transaction
)
VALUES $$transactions(
card,
trnIntId,
trnNumaretor,
merchantName,
trnPurchaseDate,
trnAmt,
trnCurrencySymbol,
trnType,
trnTypeCode,
debCrdDate,
amtBeforeConvAndIndex,
debCrdCurrencySymbol,
merchantAddress,
merchantPhoneNo,
branchCodeDesc,
transCardPresentInd,
curPaymentNum,
numOfPayments,
tokenInd,
walletProviderCode,
walletProviderDesc,
tokenNumberPart4,
cashAccountTrnAmt,
chargeExternalToCardComment,
refundInd,
isImmediateCommentInd,
isImmediateHhkInd,
isMargarita,
isSpreadPaymenstAbroad,
trnExacWay,
debitSpreadInd,
onGoingTransactionsComment,
earlyPaymentInd,
merchantId,
crdExtIdNumTypeCode,
transSource,
isAbroadTransaction
)
ON CONFLICT (trn_int_id) DO NOTHING
RETURNING id, trn_purchase_date, merchant_name, trn_amt, card;
`;
const uploadDiscountTransactions = sql `
INSERT INTO accounter_schema.bank_discount_transactions (
operation_date,
value_date,
operation_code,
operation_description,
operation_description2,
operation_description3,
operation_branch,
operation_bank,
account_number,
channel,
channel_name,
check_number,
institute_code,
operation_amount,
balance_after_operation,
operation_number,
branch_treasury_number,
urn,
operation_details_service_name,
commission_channel_code,
commission_channel_name,
commission_type_name,
business_day_date,
event_name,
category_code,
category_desc_code,
category_description,
operation_description_to_display,
operation_order,
is_last_seen
)
VALUES $$transactions(
operationDate,
valueDate,
operationCode,
operationDescription,
operationDescription2,
operationDescription3,
operationBranch,
operationBank,
accountNumber,
channel,
channelName,
checkNumber,
instituteCode,
operationAmount,
balanceAfterOperation,
operationNumber,
branchTreasuryNumber,
urn,
operationDetailsServiceName,
commissionChannelCode,
commissionChannelName,
commissionTypeName,
businessDayDate,
eventName,
categoryCode,
categoryDescCode,
categoryDescription,
operationDescriptionToDisplay,
operationOrder,
isLastSeen
)
ON CONFLICT (urn, account_number) WHERE urn IS NOT NULL AND account_number IS NOT NULL DO NOTHING
RETURNING id, operation_date, operation_description, operation_amount, account_number;
`;
const uploadMaxTransactions = sql `
INSERT INTO accounter_schema.max_creditcard_transactions (
actual_payment_amount,
arn,
card_index,
category_id,
comments,
deal_data_acq,
deal_data_adjustment_amount,
deal_data_adjustment_type,
deal_data_amount,
deal_data_amount_ils,
deal_data_amount_left,
deal_data_arn,
deal_data_authorization_number,
deal_data_card_name,
deal_data_card_token,
deal_data_commission_vat,
deal_data_direct_exchange,
deal_data_exchange_commission_amount,
deal_data_exchange_commission_maam,
deal_data_exchange_commission_type,
deal_data_exchange_direct,
deal_data_exchange_rate,
deal_data_index_rate_base,
deal_data_index_rate_pmt,
deal_data_interest_amount,
deal_data_is_allowed_spread_with_benefit,
deal_data_issuer_currency,
deal_data_issuer_exchange_rate,
deal_data_original_term,
deal_data_percent_maam,
deal_data_plan,
deal_data_pos_entry_emv,
deal_data_processing_date,
deal_data_purchase_amount,
deal_data_purchase_time,
deal_data_ref_nbr,
deal_data_show_cancel_debit,
deal_data_show_spread,
deal_data_show_spread_benefit_button,
deal_data_show_spread_button,
deal_data_show_spread_for_leumi,
deal_data_tdm_card_token,
deal_data_tdm_transaction_type,
deal_data_transaction_type,
deal_data_txn_code,
deal_data_user_name,
deal_data_withdrawal_commission_amount,
discount_key_amount,
discount_key_rec_type,
ethoca_ind,
funds_transfer_comment,
funds_transfer_receiver_or_transfer,
is_register_ch,
is_spreading_autorization_allowed,
issuer_id,
merchant_address,
merchant_coordinates,
merchant_max_phone,
merchant,
merchant_commercial_name,
merchant_number,
merchant_phone,
merchant_tax_id,
merchant_name,
original_amount,
original_currency,
payment_currency,
payment_date,
plan_name,
plan_type_id,
promotion_amount,
promotion_club,
promotion_type,
purchase_date,
receipt_p_d_f,
ref_index,
runtime_reference_internal_id,
runtime_reference_type,
runtime_reference_id,
short_card_number,
spread_transaction_by_campain_ind,
spread_transaction_by_campain_number,
table_type,
tag,
uid,
up_sale_for_transaction_result,
user_index
)
VALUES $$transactions(
actualPaymentAmount,
arn,
cardIndex,
categoryId,
comments,
dealDataAcq,
dealDataAdjustmentAmount,
dealDataAdjustmentType,
dealDataAmount,
dealDataAmountIls,
dealDataAmountLeft,
dealDataArn,
dealDataAuthorizationNumber,
dealDataCardName,
dealDataCardToken,
dealDataCommissionVat,
dealDataDirectExchange,
dealDataExchangeCommissionAmount,
dealDataExchangeCommissionMaam,
dealDataExchangeCommissionType,
dealDataExchangeDirect,
dealDataExchangeRate,
dealDataIndexRateBase,
dealDataIndexRatePmt,
dealDataInterestAmount,
dealDataIsAllowedSpreadWithBenefit,
dealDataIssuerCurrency,
dealDataIssuerExchangeRate,
dealDataOriginalTerm,
dealDataPercentMaam,
dealDataPlan,
dealDataPosEntryEmv,
dealDataProcessingDate,
dealDataPurchaseAmount,
dealDataPurchaseTime,
dealDataRefNbr,
dealDataShowCancelDebit,
dealDataShowSpread,
dealDataShowSpreadBenefitButton,
dealDataShowSpreadButton,
dealDataShowSpreadForLeumi,
dealDataTdmCardToken,
dealDataTdmTransactionType,
dealDataTransactionType,
dealDataTxnCode,
dealDataUserName,
dealDataWithdrawalCommissionAmount,
discountKeyAmount,
discountKeyRecType,
ethocaInd,
fundsTransferComment,
fundsTransferReceiverOrTransfer,
isRegisterCh,
isSpreadingAutorizationAllowed,
issuerId,
merchantAddress,
merchantCoordinates,
merchantMaxPhone,
merchant,
merchantCommercialName,
merchantNumber,
merchantPhone,
merchantTaxId,
merchantName,
originalAmount,
originalCurrency,
paymentCurrency,
paymentDate,
planName,
planTypeId,
promotionAmount,
promotionClub,
promotionType,
purchaseDate,
receiptPDF,
refIndex,
runtimeReferenceInternalId,
runtimeReferenceType,
runtimeReferenceId,
shortCardNumber,
spreadTransactionByCampainInd,
spreadTransactionByCampainNumber,
tableType,
tag,
uid,
upSaleForTransactionResult,
userIndex
)
ON CONFLICT (uid, arn, purchase_date, payment_date, original_amount) DO NOTHING
RETURNING id, purchase_date, merchant_name, actual_payment_amount, card_index;
`;
const uploadCurrencyRates = sql `
INSERT INTO accounter_schema.exchange_rates (
exchange_date,
usd,
eur,
gbp,
cad,
jpy,
aud,
sek
)
VALUES $$rates(
exchangeDate,
usd,
eur,
gbp,
cad,
jpy,
aud,
sek
)
ON CONFLICT (exchange_date) DO NOTHING
RETURNING exchange_date, usd, eur, gbp, cad, jpy, aud, sek;
`;
function diffExchangeRatesRow(existing, incoming) {
const changed = [];
for (const currency of ['aud', 'cad', 'eur', 'gbp', 'jpy', 'sek', 'usd']) {
const oldValue = formatValue(existing[currency], true);
const newValue = formatValue(incoming[currency], true);
const oldStr = oldValue;
const newStr = newValue;
if (oldStr !== newStr) {
changed.push({ field: currency, oldValue: String(oldStr), newValue: String(newStr) });
}
}
return changed;
}
let ScraperIngestionProvider = class ScraperIngestionProvider {
db;
exchangeRates;
constructor(db, exchangeRates) {
this.db = db;
this.exchangeRates = exchangeRates;
}
async uploadCalTransactions(transactions) {
if (transactions.length === 0)
return {
inserted: 0,
skipped: 0,
insertedIds: [],
insertedTransactions: [],
changedTransactions: [],
};
const result = await uploadCalTransactions.run({ transactions: validateCalTransactions(transactions) }, this.db);
const insertedIds = result.map(r => r.id).filter((id) => typeof id === 'string');
const insertedTransactions = result.map(r => ({
id: r.id,
date: r.trn_purchase_date ?? null,
description: r.merchant_name ?? null,
amount: r.trn_amt == null ? null : String(r.trn_amt),
account: String(r.card),
}));
return {
inserted: insertedIds.length,
skipped: transactions.length - insertedIds.length,
insertedIds,
insertedTransactions,
changedTransactions: [],
};
}
async uploadDiscountTransactions(transactions) {
if (transactions.length === 0)
return {
inserted: 0,
skipped: 0,
insertedIds: [],
insertedTransactions: [],
changedTransactions: [],
};
const result = await uploadDiscountTransactions.run({ transactions: validateDiscountTransactions(transactions) }, this.db);
const insertedIds = result.map(r => r.id).filter((id) => typeof id === 'string');
const insertedTransactions = result.map(r => ({
id: r.id,
date: r.operation_date ?? null,
description: r.operation_description ?? null,
amount: r.operation_amount ?? null,
account: r.account_number ?? null,
}));
return {
inserted: insertedIds.length,
skipped: transactions.length - insertedIds.length,
insertedIds,
insertedTransactions,
changedTransactions: [],
};
}
async uploadMaxTransactions(transactions) {
if (transactions.length === 0)
return {
inserted: 0,
skipped: 0,
insertedIds: [],
insertedTransactions: [],
changedTransactions: [],
};
const result = await uploadMaxTransactions.run({ transactions: validateMaxTransactions(transactions) }, this.db);
const insertedIds = result.map(r => r.id).filter((id) => typeof id === 'string');
const insertedTransactions = result.map(r => ({
id: r.id,
date: r.purchase_date ? dateToTimelessDateString(r.purchase_date) : null,
description: r.merchant_name ?? null,
amount: r.actual_payment_amount == null ? null : String(r.actual_payment_amount),
account: String(r.card_index),
}));
return {
inserted: insertedIds.length,
skipped: transactions.length - insertedIds.length,
insertedIds,
insertedTransactions,
changedTransactions: [],
};
}
async uploadCurrencyRates(rates) {
if (rates.length === 0)
return {
inserted: 0,
skipped: 0,
insertedIds: [],
insertedTransactions: [],
changedTransactions: [],
};
const validated = validateRates(rates);
const existing = await this.exchangeRates.getExchangeRatesByDatesLoader
.loadMany(rates.map(r => new Date(r.exchangeDate)))
.then(res => res.filter((r) => r !== null && !(r instanceof Error)));
const existingByDate = new Map(existing.map(row => [
row.exchange_date ? dateToTimelessDateString(row.exchange_date) : null,
row,
]));
const result = await uploadCurrencyRates.run({ rates: validated }, this.db);
const insertedDates = result
.map(r => (r.exchange_date ? dateToTimelessDateString(r.exchange_date) : undefined))
.filter((date) => !!date);
const insertedDatesSet = new Set(insertedDates);
const insertedRates = result.map(r => {
const date = dateToTimelessDateString(r.exchange_date);
const description = ['usd', 'eur', 'gbp', 'cad', 'jpy', 'aud', 'sek']
.filter(c => r[c] != null)
.map(c => `${c.toUpperCase()}=${r[c]}`)
.join(', ');
return {
id: date ?? undefined,
date,
description,
amount: undefined,
account: undefined,
};
});
const changedRates = [];
for (const r of validated) {
if (!r.exchangeDate)
continue;
const date = dateToTimelessDateString(new Date(r.exchangeDate));
const existingRow = existingByDate.get(date);
if (existingRow?.exchange_date &&
!insertedDatesSet.has(dateToTimelessDateString(existingRow.exchange_date))) {
const changedFields = diffExchangeRatesRow(existingRow, r);
if (changedFields.length > 0) {
changedRates.push({ id: date, changedFields });
}
}
}
return {
inserted: insertedDates.length,
skipped: rates.length - insertedDates.length,
insertedIds: insertedDates,
insertedTransactions: insertedRates,
changedTransactions: changedRates,
};
}
};
ScraperIngestionProvider = __decorate([
Injectable({
scope: Scope.Operation,
global: true,
}),
__metadata("design:paramtypes", [TenantAwareDBClient,
FiatExchangeProvider])
], ScraperIngestionProvider);
export { ScraperIngestionProvider };
//# sourceMappingURL=scraper-ingestion.provider.js.map