UNPKG

@accounter/server

Version:
904 lines (846 loc) • 50.1 kB
export default { name: '2024-03-21T15-33-43.transactions-extension-tables.sql', run: ({ sql }) => sql ` -- create transaction fees table and migrate data from transactions create table accounter_schema.transactions_fees ( id uuid not null constraint transactions_fees_pk primary key constraint transactions_fees_transactions_id_fk references accounter_schema.transactions, is_recurring boolean default false not null ); INSERT INTO accounter_schema.transactions_fees (id) SELECT id FROM accounter_schema.transactions t WHERE t.is_fee = true; -- create transactions bank deposits table create table accounter_schema.transactions_bank_deposits ( id uuid not null constraint transactions_bank_deposits_pk primary key constraint transactions_bank_deposits_transactions_id_fk references accounter_schema.transactions, deposit_id text ); -- update extended_transactions view create or replace view accounter_schema.extended_transactions (id, charge_id, business_id, currency, debit_date, debit_timestamp, event_date, account_id, account_type, amount, current_balance, source_description, source_details, created_at, updated_at, source_id, source_reference, source_origin, currency_rate, is_conversion, is_fee) as SELECT DISTINCT ON (t.id) t.id, t.charge_id, t.business_id, t.currency, CASE WHEN ot.origin = 'ISRACARD'::text AND t.currency = 'ILS'::accounter_schema.currency AND t.debit_date IS NULL THEN dd.event_date ELSE t.debit_date END AS debit_date, ot.debit_timestamp, t.event_date, t.account_id, a.type AS account_type, t.amount, t.current_balance, t.source_description, ot.source_details, t.created_at, t.updated_at, ot.raw_id AS source_id, ot.reference_number AS source_reference, ot.origin AS source_origin, ot.currency_rate, c.is_conversion, CASE WHEN f.id IS NULL THEN FALSE ELSE TRUE END FROM accounter_schema.transactions t LEFT JOIN accounter_schema.transactions_raw_list rt ON t.source_id = rt.id LEFT JOIN accounter_schema.charges c ON c.id = t.charge_id LEFT JOIN accounter_schema.financial_accounts a ON a.id = t.account_id LEFT JOIN accounter_schema.transactions_fees f ON f.id = t.id LEFT JOIN (SELECT isracard_creditcard_transactions.id::text AS raw_id, COALESCE(isracard_creditcard_transactions.voucher_number::text, isracard_creditcard_transactions.voucher_number_ratz::text) AS reference_number, 0 AS currency_rate, NULL::timestamp without time zone AS debit_timestamp, 'ISRACARD'::text AS origin, isracard_creditcard_transactions.card AS card_number, COALESCE(isracard_creditcard_transactions.full_supplier_name_heb, isracard_creditcard_transactions.full_supplier_name_outbound) AS source_details FROM accounter_schema.isracard_creditcard_transactions UNION SELECT poalim_ils_account_transactions.id::text AS id, poalim_ils_account_transactions.reference_number::text AS reference_number, 0 AS currency_rate, NULL::timestamp without time zone AS debit_timestamp, 'POALIM'::text AS origin, NULL::integer AS card_number, poalim_ils_account_transactions.beneficiary_details_data_message_detail AS source_details FROM accounter_schema.poalim_ils_account_transactions UNION SELECT poalim_eur_account_transactions.id::text AS id, poalim_eur_account_transactions.reference_number::text AS reference_number, poalim_eur_account_transactions.currency_rate, NULL::timestamp without time zone AS debit_timestamp, 'POALIM'::text AS origin, NULL::integer AS card_number, poalim_eur_account_transactions.event_details AS source_details FROM accounter_schema.poalim_eur_account_transactions UNION SELECT poalim_gbp_account_transactions.id::text AS id, poalim_gbp_account_transactions.reference_number::text AS reference_number, poalim_gbp_account_transactions.currency_rate, NULL::timestamp without time zone AS debit_timestamp, 'POALIM'::text AS origin, NULL::integer AS card_number, poalim_gbp_account_transactions.event_details AS source_details FROM accounter_schema.poalim_gbp_account_transactions UNION SELECT poalim_usd_account_transactions.id::text AS id, poalim_usd_account_transactions.reference_number::text AS reference_number, poalim_usd_account_transactions.currency_rate, NULL::timestamp without time zone AS debit_timestamp, 'POALIM'::text AS origin, NULL::integer AS card_number, poalim_usd_account_transactions.event_details AS source_details FROM accounter_schema.poalim_usd_account_transactions UNION SELECT poalim_swift_account_transactions.id::text AS id, poalim_swift_account_transactions.reference_number, 0, NULL::timestamp without time zone AS debit_timestamp, 'POALIM'::text AS origin, NULL::integer AS card_number, poalim_swift_account_transactions.charge_party_name AS source_details FROM accounter_schema.poalim_swift_account_transactions UNION SELECT kraken_ledger_records.ledger_id, kraken_ledger_records.ledger_id, CASE WHEN kraken_trades.price IS NOT NULL THEN 1::numeric / kraken_trades.price ELSE 0::numeric END AS currency_rate, kraken_ledger_records.value_date AS debit_timestamp, 'KRAKEN'::text AS origin, NULL::integer AS card_number, NULL::character varying AS source_details FROM accounter_schema.kraken_ledger_records LEFT JOIN accounter_schema.kraken_trades ON kraken_ledger_records.trade_ref_id = kraken_trades.trade_id UNION SELECT etana_account_transactions.transaction_id, etana_account_transactions.transaction_id, 0, NULL::timestamp without time zone AS debit_timestamp, 'ETANA'::text AS origin, NULL::integer AS card_number, NULL::character varying AS source_details FROM accounter_schema.etana_account_transactions UNION SELECT etherscan_transactions.id::text AS id, etherscan_transactions.transaction_hash, 0, etherscan_transactions.event_date AS debit_timestamp, 'ETHERSCAN'::text AS origin, NULL::integer AS card_number, NULL::character varying AS source_details FROM accounter_schema.etherscan_transactions) ot ON ot.raw_id = COALESCE(rt.creditcard_id::text, rt.poalim_ils_id::text, rt.poalim_eur_id::text, rt.poalim_gbp_id::text, rt.poalim_swift_id::text, rt.poalim_usd_id::text, rt.kraken_id, rt.etana_id, rt.etherscan_id::text) LEFT JOIN (SELECT p.event_date, p.reference_number FROM accounter_schema.poalim_ils_account_transactions p WHERE p.activity_type_code = 491) dd ON dd.reference_number = ot.card_number AND dd.event_date > t.event_date AND dd.event_date < (t.event_date + '40 days'::interval) ORDER BY t.id, dd.event_date; -- update extended_charges view create or replace view accounter_schema.extended_charges (id, owner_id, is_conversion, is_property, is_salary, accountant_reviewed, user_description, created_at, updated_at, tax_category_id, event_amount, transactions_min_event_date, transactions_max_event_date, transactions_min_debit_date, transactions_max_debit_date, transactions_event_amount, transactions_currency, transactions_count, invalid_transactions, documents_min_date, documents_max_date, documents_event_amount, documents_vat_amount, documents_currency, invoices_count, receipts_count, documents_count, invalid_documents, business_array, business_id, can_settle_with_receipt, tags, business_trip_id, ledger_count, ledger_financial_entities, years_of_relevance) as SELECT c.id, c.owner_id, c.is_conversion, c.is_property, 'salary'::accounter_schema.tags_enum = ANY (tags_table.tags_array) AS is_salary, c.accountant_reviewed, c.user_description, c.created_at, c.updated_at, COALESCE(c.tax_category_id, tcm.tax_category_id) AS tax_category_id, COALESCE(d.invoice_event_amount::numeric, d.receipt_event_amount::numeric, t.event_amount) AS event_amount, t.min_event_date AS transactions_min_event_date, t.max_event_date AS transactions_max_event_date, t.min_debit_date AS transactions_min_debit_date, t.max_debit_date AS transactions_max_debit_date, t.event_amount AS transactions_event_amount, CASE WHEN array_length(t.currency_array, 1) = 1 THEN t.currency_array[1] ELSE NULL::accounter_schema.currency END AS transactions_currency, t.transactions_count, t.invalid_transactions, d.min_event_date AS documents_min_date, d.max_event_date AS documents_max_date, COALESCE(d.invoice_event_amount, d.receipt_event_amount) AS documents_event_amount, COALESCE(d.invoice_vat_amount, d.receipt_vat_amount) AS documents_vat_amount, CASE WHEN array_length(d.currency_array, 1) = 1 THEN d.currency_array[1] ELSE NULL::accounter_schema.currency END AS documents_currency, d.invoices_count, d.receipts_count, d.documents_count, d.invalid_documents, b2.business_array, b.id AS business_id, COALESCE(b.can_settle_with_receipt, false) AS can_settle_with_receipt, tags_table.tags_array AS tags, btc.business_trip_id, l.ledger_count, l.ledger_financial_entities, c.years_of_relevance FROM accounter_schema.charges c LEFT JOIN (SELECT extended_transactions.charge_id, min(extended_transactions.event_date) AS min_event_date, max(extended_transactions.event_date) AS max_event_date, min(extended_transactions.debit_date) AS min_debit_date, max(extended_transactions.debit_date) AS max_debit_date, sum(extended_transactions.amount) AS event_amount, count(*) AS transactions_count, count(*) FILTER (WHERE extended_transactions.business_id IS NULL OR extended_transactions.debit_date IS NULL) > 0 AS invalid_transactions, array_agg(DISTINCT extended_transactions.currency) AS currency_array, array_agg(extended_transactions.account_id) AS account FROM accounter_schema.extended_transactions GROUP BY extended_transactions.charge_id) t ON t.charge_id = c.id LEFT JOIN (SELECT documents.charge_id_new, min(documents.date) FILTER (WHERE documents.type = ANY (ARRAY ['INVOICE'::accounter_schema.document_type, 'INVOICE_RECEIPT'::accounter_schema.document_type, 'RECEIPT'::accounter_schema.document_type])) AS min_event_date, max(documents.date) FILTER (WHERE documents.type = ANY (ARRAY ['INVOICE'::accounter_schema.document_type, 'INVOICE_RECEIPT'::accounter_schema.document_type, 'RECEIPT'::accounter_schema.document_type])) AS max_event_date, sum(documents.total_amount * CASE WHEN documents.creditor_id = charges.owner_id THEN 1 ELSE '-1'::integer END::double precision) FILTER (WHERE businesses.can_settle_with_receipt = true AND (documents.type = ANY (ARRAY ['RECEIPT'::accounter_schema.document_type, 'INVOICE_RECEIPT'::accounter_schema.document_type]))) AS receipt_event_amount, sum(documents.total_amount * CASE WHEN documents.creditor_id = charges.owner_id THEN 1 ELSE '-1'::integer END::double precision) FILTER (WHERE documents.type = ANY (ARRAY ['INVOICE'::accounter_schema.document_type, 'INVOICE_RECEIPT'::accounter_schema.document_type])) AS invoice_event_amount, sum(documents.vat_amount * CASE WHEN documents.creditor_id = charges.owner_id THEN 1 ELSE '-1'::integer END::double precision) FILTER (WHERE businesses.can_settle_with_receipt = true AND (documents.type = ANY (ARRAY ['RECEIPT'::accounter_schema.document_type, 'INVOICE_RECEIPT'::accounter_schema.document_type]))) AS receipt_vat_amount, sum(documents.vat_amount * CASE WHEN documents.creditor_id = charges.owner_id THEN 1 ELSE '-1'::integer END::double precision) FILTER (WHERE documents.type = ANY (ARRAY ['INVOICE'::accounter_schema.document_type, 'INVOICE_RECEIPT'::accounter_schema.document_type])) AS invoice_vat_amount, count(*) FILTER (WHERE documents.type = ANY (ARRAY ['INVOICE'::accounter_schema.document_type, 'INVOICE_RECEIPT'::accounter_schema.document_type])) AS invoices_count, count(*) FILTER (WHERE documents.type = ANY (ARRAY ['RECEIPT'::accounter_schema.document_type, 'INVOICE_RECEIPT'::accounter_schema.document_type])) AS receipts_count, count(*) AS documents_count, count(*) FILTER (WHERE (documents.type = ANY (ARRAY ['INVOICE'::accounter_schema.document_type, 'INVOICE_RECEIPT'::accounter_schema.document_type, 'RECEIPT'::accounter_schema.document_type])) AND (documents.debtor_id IS NULL OR documents.creditor_id IS NULL OR documents.date IS NULL OR documents.serial_number IS NULL OR documents.vat_amount IS NULL OR documents.total_amount IS NULL OR documents.charge_id_new IS NULL OR documents.currency_code IS NULL) OR documents.type = 'UNPROCESSED'::accounter_schema.document_type) > 0 AS invalid_documents, array_agg(documents.currency_code) FILTER (WHERE businesses.can_settle_with_receipt = true AND (documents.type = ANY (ARRAY ['RECEIPT'::accounter_schema.document_type, 'INVOICE_RECEIPT'::accounter_schema.document_type])) OR (documents.type = ANY (ARRAY ['INVOICE'::accounter_schema.document_type, 'INVOICE_RECEIPT'::accounter_schema.document_type]))) AS currency_array FROM accounter_schema.documents LEFT JOIN accounter_schema.charges ON documents.charge_id_new = charges.id LEFT JOIN accounter_schema.businesses ON documents.creditor_id = charges.owner_id AND documents.debtor_id = businesses.id OR documents.creditor_id = businesses.id AND documents.debtor_id = charges.owner_id GROUP BY documents.charge_id_new) d ON d.charge_id_new = c.id LEFT JOIN (SELECT base.charge_id, array_remove(base.business_array, charges.owner_id) AS business_array, array_remove(base.filtered_business_array, charges.owner_id) AS filtered_business_array FROM (SELECT b_1.charge_id, array_agg(DISTINCT b_1.business_id) AS business_array, array_remove(array_agg(DISTINCT CASE WHEN b_1.is_fee THEN NULL::uuid ELSE b_1.business_id END), NULL::uuid) AS filtered_business_array FROM (SELECT transactions.charge_id, transactions.business_id, CASE WHEN transactions_fees.id IS NULL THEN FALSE ELSE TRUE END AS is_fee FROM accounter_schema.transactions LEFT JOIN accounter_schema.transactions_fees ON transactions.id = transactions_fees.id WHERE transactions.business_id IS NOT NULL UNION SELECT documents.charge_id_new, documents.creditor_id, false AS bool FROM accounter_schema.documents WHERE documents.creditor_id IS NOT NULL UNION SELECT documents.charge_id_new, documents.debtor_id, false AS bool FROM accounter_schema.documents WHERE documents.debtor_id IS NOT NULL) b_1 GROUP BY b_1.charge_id) base LEFT JOIN accounter_schema.charges ON base.charge_id = charges.id) b2 ON b2.charge_id = c.id LEFT JOIN accounter_schema.businesses b ON b.id = b2.filtered_business_array[1] AND array_length(b2.filtered_business_array, 1) = 1 LEFT JOIN accounter_schema.business_tax_category_match tcm ON tcm.business_id = b.id AND tcm.owner_id = c.owner_id LEFT JOIN (SELECT tags_1.charge_id, array_agg(tags_1.tag_name) AS tags_array FROM accounter_schema.tags tags_1 GROUP BY tags_1.charge_id) tags_table ON c.id = tags_table.charge_id LEFT JOIN accounter_schema.business_trip_charges btc ON btc.charge_id = c.id LEFT JOIN (SELECT count(DISTINCT l2.id) AS ledger_count, array_remove(array_agg(DISTINCT l2.financial_entity), NULL::uuid) AS ledger_financial_entities, l2.charge_id FROM (SELECT ledger_records.charge_id, ledger_records.id, unnest(ARRAY [ledger_records.credit_entity1, ledger_records.credit_entity2, ledger_records.debit_entity1, ledger_records.debit_entity2]) AS financial_entity FROM accounter_schema.ledger_records) l2 GROUP BY l2.charge_id) l ON l.charge_id = c.id; -- update transaction trigger functions create or replace function accounter_schema.insert_poalim_eur_transaction_handler() returns trigger language plpgsql as $$ DECLARE merged_id UUID; account_id_var UUID; owner_id_var UUID; charge_id_var UUID = NULL; is_conversion BOOLEAN = false; is_fee BOOLEAN = false; transaction_id_var UUID = NULL; BEGIN -- Create merged raw transactions record: INSERT INTO accounter_schema.transactions_raw_list (poalim_eur_id) VALUES (NEW.id) RETURNING id INTO merged_id; -- get account and owner IDs SELECT INTO account_id_var, owner_id_var id, owner FROM accounter_schema.financial_accounts WHERE account_number = NEW.account_number::TEXT; -- handle conversions IF (new.activity_type_code in (884, 957,1058)) THEN is_conversion = true; -- check if matching charge exists: SELECT t.charge_id INTO charge_id_var FROM ( SELECT 'usd' AS currency, id, reference_number, reference_catenated_number, value_date, event_amount FROM accounter_schema.poalim_usd_account_transactions WHERE activity_type_code IN (884, 957,1058) UNION SELECT 'gbp', id, reference_number, reference_catenated_number, value_date, event_amount FROM accounter_schema.poalim_gbp_account_transactions WHERE activity_type_code IN (884, 957,1058) UNION SELECT 'ils', id, reference_number, reference_catenated_number, value_date, event_amount FROM accounter_schema.poalim_ils_account_transactions WHERE text_code IN (22, 23)) AS s LEFT JOIN accounter_schema.transactions_raw_list tr ON COALESCE(tr.poalim_ils_id, tr.poalim_eur_id, tr.poalim_gbp_id, tr.poalim_usd_id) = s.id LEFT JOIN accounter_schema.transactions t ON tr.id = t.source_id WHERE t.charge_id IS NOT NULL AND s.reference_number = NEW.reference_number AND s.reference_catenated_number = NEW.reference_catenated_number AND s.value_date = NEW.value_date; -- update charge's tag to 'conversion' IF (charge_id_var IS NOT NULL) THEN INSERT INTO accounter_schema.tags (charge_id, tag_name) VALUES (charge_id_var, 'conversion') ON CONFLICT DO NOTHING; END IF; END IF; -- if no match, create new charge IF (charge_id_var IS NULL) THEN INSERT INTO accounter_schema.charges (owner_id, is_conversion) VALUES ( owner_id_var, is_conversion ) RETURNING id INTO charge_id_var; END IF; -- check if new record is fee IF (new.activity_type_code = 1279 AND new.event_amount BETWEEN 0 AND 30) THEN is_fee = true; END IF; -- check if new record contains fees -- TBD -- create new transaction INSERT INTO accounter_schema.transactions (account_id, charge_id, source_id, source_description, currency, event_date, debit_date, amount, current_balance) VALUES ( account_id_var, charge_id_var, merged_id, concat( new.activity_description, ' ', coalesce(new.event_details, ''), ' ', coalesce(new.account_name, '') ), 'EUR', new.executing_date::text::date, new.value_date::text::date, (CASE WHEN new.event_activity_type_code = 2 THEN (new.event_amount * -1) ELSE new.event_amount END ), new.current_balance ) RETURNING id INTO transaction_id_var; -- extend transaction with fee IF (is_fee = TRUE) THEN INSERT INTO accounter_schema.transactions_fees (id) VALUES ( transaction_id_var ); END IF; RETURN NEW; END; $$; create or replace function accounter_schema.insert_poalim_gbp_transaction_handler() returns trigger language plpgsql as $$ DECLARE merged_id UUID; account_id_var UUID; owner_id_var UUID; charge_id_var UUID = NULL; is_conversion BOOLEAN = false; is_fee BOOLEAN = false; transaction_id_var UUID = NULL; BEGIN -- Create merged raw transactions record: INSERT INTO accounter_schema.transactions_raw_list (poalim_gbp_id) VALUES (NEW.id) RETURNING id INTO merged_id; -- get account and owner IDs SELECT INTO account_id_var, owner_id_var id, owner FROM accounter_schema.financial_accounts WHERE account_number = NEW.account_number::TEXT; -- handle conversions IF (new.activity_type_code IN (884, 957, 1058)) THEN is_conversion = true; -- check if matching charge exists: SELECT t.charge_id INTO charge_id_var FROM (SELECT 'usd' AS currency, id, reference_number, reference_catenated_number, value_date, event_amount FROM accounter_schema.poalim_usd_account_transactions WHERE activity_type_code IN (884, 957, 1058) UNION SELECT 'eur', id, reference_number, reference_catenated_number, value_date, event_amount FROM accounter_schema.poalim_eur_account_transactions WHERE activity_type_code IN (884, 957, 1058) UNION SELECT 'ils', id, reference_number, reference_catenated_number, value_date, event_amount FROM accounter_schema.poalim_ils_account_transactions WHERE text_code IN (22, 23)) AS s LEFT JOIN accounter_schema.transactions_raw_list tr ON COALESCE(tr.poalim_ils_id, tr.poalim_eur_id, tr.poalim_gbp_id, tr.poalim_usd_id) = s.id LEFT JOIN accounter_schema.transactions t ON tr.id = t.source_id WHERE t.charge_id IS NOT NULL AND s.reference_number = NEW.reference_number AND s.reference_catenated_number = NEW.reference_catenated_number AND s.value_date = NEW.value_date; -- update charge's tag to 'conversion' IF (charge_id_var IS NOT NULL) THEN INSERT INTO accounter_schema.tags (charge_id, tag_name) VALUES (charge_id_var, 'conversion') ON CONFLICT DO NOTHING; END IF; END IF; -- if no match, create new charge IF (charge_id_var IS NULL) THEN INSERT INTO accounter_schema.charges (owner_id, is_conversion) VALUES (owner_id_var, is_conversion) RETURNING id INTO charge_id_var; END IF; -- check if new record is fee IF (new.activity_type_code = 1279 AND new.event_amount BETWEEN 0 AND 30) THEN is_fee = true; END IF; -- check if new record contains fees -- TBD -- create new transaction INSERT INTO accounter_schema.transactions (account_id, charge_id, source_id, source_description, currency, event_date, debit_date, amount, current_balance) VALUES (account_id_var, charge_id_var, merged_id, concat( new.activity_description, ' ', coalesce(new.event_details, ''), ' ', coalesce(new.account_name, '') ), 'GBP', new.executing_date::text::date, new.value_date::text::date, (CASE WHEN new.event_activity_type_code = 2 THEN (new.event_amount * -1) ELSE new.event_amount END ), new.current_balance) RETURNING id INTO transaction_id_var; -- extend transaction with fee IF (is_fee = TRUE) THEN INSERT INTO accounter_schema.transactions_fees (id) VALUES (transaction_id_var); END IF; RETURN NEW; END; $$; create or replace function accounter_schema.insert_poalim_ils_transaction_handler() returns trigger language plpgsql as $$ DECLARE merged_id UUID; account_id_var UUID; owner_id_var UUID; charge_id_var UUID = NULL; is_conversion BOOLEAN = false; is_fee BOOLEAN = false; transaction_id_var UUID = NULL; BEGIN -- Create merged raw transactions record: INSERT INTO accounter_schema.transactions_raw_list (poalim_ils_id) VALUES (NEW.id) RETURNING id INTO merged_id; -- get account and owner IDs SELECT INTO account_id_var, owner_id_var id, owner FROM accounter_schema.financial_accounts WHERE account_number = NEW.account_number::TEXT; -- handle conversions IF (new.activity_type_code IN (22, 23)) THEN is_conversion = true; -- check if matching charge exists: SELECT t.charge_id INTO charge_id_var FROM (SELECT 'usd' AS currency, id, reference_number, reference_catenated_number, value_date, event_amount FROM accounter_schema.poalim_usd_account_transactions WHERE activity_type_code IN (884, 957, 1058) UNION SELECT 'eur', id, reference_number, reference_catenated_number, value_date, event_amount FROM accounter_schema.poalim_eur_account_transactions WHERE activity_type_code IN (884, 957, 1058) UNION SELECT 'gbp', id, reference_number, reference_catenated_number, value_date, event_amount FROM accounter_schema.poalim_gbp_account_transactions WHERE activity_type_code IN (884, 957, 1058)) AS s LEFT JOIN accounter_schema.transactions_raw_list tr ON COALESCE(tr.poalim_ils_id, tr.poalim_eur_id, tr.poalim_gbp_id, tr.poalim_usd_id) = s.id LEFT JOIN accounter_schema.transactions t ON tr.id = t.source_id WHERE t.charge_id IS NOT NULL AND s.reference_number = NEW.reference_number AND s.reference_catenated_number = NEW.reference_catenated_number AND s.value_date = NEW.value_date; -- update charge's tag to 'conversion' IF (charge_id_var IS NOT NULL) THEN INSERT INTO accounter_schema.tags (charge_id, tag_name) VALUES (charge_id_var, 'conversion') ON CONFLICT DO NOTHING; END IF; END IF; -- if no match, create new charge IF (charge_id_var IS NULL) THEN INSERT INTO accounter_schema.charges (owner_id, is_conversion) VALUES (owner_id_var, is_conversion) RETURNING id INTO charge_id_var; END IF; -- check if new record is fee IF ( (new.activity_type_code = 452 AND new.text_code IN (105, 547)) OR (new.activity_type_code = 473 AND new.text_code IN (378, 395, 437, 502, 602, 603, 716, 771, 774)) ) THEN is_fee = true; END IF; -- check if new record contains fees -- TBD -- create new transaction INSERT INTO accounter_schema.transactions (account_id, charge_id, source_id, source_description, currency, event_date, debit_date, amount, current_balance) VALUES (account_id_var, charge_id_var, merged_id, concat( new.activity_description, ' ', coalesce(new.beneficiary_details_data_party_name, ''), ' ', coalesce(new.beneficiary_details_data_message_detail, ''), ' ', coalesce(new.english_action_desc, '') ), 'ILS', new.event_date::text::date, new.event_date::text::date, (CASE WHEN new.event_activity_type_code = 2 THEN (new.event_amount * -1) ELSE new.event_amount END ), new.current_balance) RETURNING id INTO transaction_id_var; -- extend transaction with fee IF (is_fee = TRUE) THEN INSERT INTO accounter_schema.transactions_fees (id) VALUES (transaction_id_var); END IF; RETURN NEW; END; $$; create or replace function accounter_schema.insert_poalim_swift_transaction_handler() returns trigger language plpgsql as $$ DECLARE merged_id UUID; account_id_var UUID; owner_id_var UUID; charge_id_var UUID = NULL; transaction_amount NUMERIC; fee_amount NUMERIC; currency_code accounter_schema.currency; transaction_id_var UUID = NULL; BEGIN transaction_amount := REPLACE( RIGHT(NEW.swift_currency_instructed_amount_33b, LENGTH(NEW.swift_currency_instructed_amount_33b) - 3), ',', '.')::NUMERIC; fee_amount := transaction_amount - REPLACE( RIGHT(NEW.swift_value_date_currency_amount_32a, LENGTH(NEW.swift_value_date_currency_amount_32a) - 9), ',', '.')::NUMERIC; currency_code := LEFT(NEW.swift_currency_instructed_amount_33b, 3)::accounter_schema.currency; IF (fee_amount > 0) THEN -- Create merged raw transactions record: INSERT INTO accounter_schema.transactions_raw_list (poalim_swift_id) VALUES (NEW.id) RETURNING id INTO merged_id; -- get account and owner IDs SELECT INTO account_id_var, owner_id_var id, owner FROM accounter_schema.financial_accounts WHERE account_number = NEW.account_number::TEXT; -- check if matching charge exists for source: SELECT t.charge_id INTO charge_id_var FROM (SELECT formatted_value_date, event_details, id, 'GBP' as currency, event_amount FROM accounter_schema.poalim_gbp_account_transactions UNION SELECT formatted_value_date, event_details, id, 'EUR', event_amount FROM accounter_schema.poalim_eur_account_transactions UNION SELECT formatted_value_date, event_details, id, 'USD', event_amount FROM accounter_schema.poalim_usd_account_transactions) AS s LEFT JOIN accounter_schema.transactions_raw_list tr ON COALESCE(tr.poalim_ils_id, tr.poalim_eur_id, tr.poalim_gbp_id, tr.poalim_usd_id) = s.id LEFT JOIN accounter_schema.transactions t ON tr.id = t.source_id WHERE t.charge_id IS NOT NULL AND (s.formatted_value_date = NEW.formatted_start_date OR s.formatted_value_date = NEW.formatted_start_date) AND currency_code::text = s.currency AND (s.event_details LIKE '%' || TRIM(LEFT(NEW.charge_party_name, 13)) || '%' AND NEW.amount::NUMERIC = s.event_amount) OR (transaction_amount * -1 = s.event_amount); -- if no match, create new charge IF (charge_id_var IS NULL) THEN INSERT INTO accounter_schema.charges (owner_id) VALUES (owner_id_var) RETURNING id INTO charge_id_var; END IF; -- create new transaction for fee INSERT INTO accounter_schema.transactions (account_id, charge_id, source_id, source_description, currency, event_date, debit_date, amount, current_balance, business_id) VALUES (account_id_var, charge_id_var, merged_id, CONCAT_WS(' ', 'Swift Fee:', NEW.charge_party_name, NEW.reference_number ), currency_code, NEW.formatted_start_date::DATE, new.formatted_start_date::DATE, fee_amount * -1, 0, NULL) RETURNING id INTO transaction_id_var; -- extend transaction with fee INSERT INTO accounter_schema.transactions_fees (id) VALUES (transaction_id_var); END IF; RETURN NEW; END; $$; create or replace function accounter_schema.insert_poalim_usd_transaction_handler() returns trigger language plpgsql as $$ DECLARE merged_id UUID; account_id_var UUID; owner_id_var UUID; charge_id_var UUID = NULL; is_conversion BOOLEAN = false; is_fee BOOLEAN = false; transaction_id_var UUID = NULL; BEGIN -- Create merged raw transactions record: INSERT INTO accounter_schema.transactions_raw_list (poalim_usd_id) VALUES (NEW.id) RETURNING id INTO merged_id; -- get account and owner IDs SELECT INTO account_id_var, owner_id_var id, owner FROM accounter_schema.financial_accounts WHERE account_number = NEW.account_number::TEXT; -- handle conversions IF (new.activity_type_code IN (884, 957, 1058)) THEN is_conversion = true; -- check if matching charge exists: SELECT t.charge_id INTO charge_id_var FROM (SELECT 'eur', id, reference_number, reference_catenated_number, value_date, event_amount FROM accounter_schema.poalim_eur_account_transactions WHERE activity_type_code IN (884, 957, 1058) UNION SELECT 'gbp', id, reference_number, reference_catenated_number, value_date, event_amount FROM accounter_schema.poalim_gbp_account_transactions WHERE activity_type_code IN (884, 957, 1058) UNION SELECT 'ils', id, reference_number, reference_catenated_number, value_date, event_amount FROM accounter_schema.poalim_ils_account_transactions WHERE text_code IN (22, 23)) AS s LEFT JOIN accounter_schema.transactions_raw_list tr ON COALESCE(tr.poalim_ils_id, tr.poalim_eur_id, tr.poalim_gbp_id, tr.poalim_usd_id) = s.id LEFT JOIN accounter_schema.transactions t ON tr.id = t.source_id WHERE t.charge_id IS NOT NULL AND s.reference_number = NEW.reference_number AND s.reference_catenated_number = NEW.reference_catenated_number AND s.value_date = NEW.value_date; -- update charge's tag to 'conversion' IF (charge_id_var IS NOT NULL) THEN INSERT INTO accounter_schema.tags (charge_id, tag_name) VALUES (charge_id_var, 'conversion') ON CONFLICT DO NOTHING; END IF; END IF; -- handle bank deposits IF (new.activity_type_code IN (1376, 1384, 169, 171, 172)) THEN -- check if matching charge exists: SELECT t.charge_id INTO charge_id_var FROM (SELECT 'eur', id, reference_number, reference_catenated_number, value_date, event_amount FROM accounter_schema.poalim_eur_account_transactions WHERE activity_type_code IN (1376, 1384) UNION SELECT 'gbp', id, reference_number, reference_catenated_number, value_date, event_amount FROM accounter_schema.poalim_gbp_account_transactions WHERE activity_type_code IN (1376, 1384) UNION SELECT 'ils', id, reference_number, reference_catenated_number, value_date, event_amount FROM accounter_schema.poalim_ils_account_transactions WHERE text_code IN (113, 117, 457)) AS s LEFT JOIN accounter_schema.transactions_raw_list tr ON COALESCE(tr.poalim_ils_id, tr.poalim_eur_id, tr.poalim_gbp_id, tr.poalim_usd_id) = s.id LEFT JOIN accounter_schema.transactions t ON tr.id = t.source_id WHERE t.charge_id IS NOT NULL AND s.reference_number = NEW.reference_number AND s.reference_catenated_number = NEW.reference_catenated_number AND s.value_date = NEW.value_date; END IF; -- if no match, create new charge IF (charge_id_var IS NULL) THEN INSERT INTO accounter_schema.charges (owner_id, is_conversion) VALUES (owner_id_var, is_conversion) RETURNING id INTO charge_id_var; END IF; -- check if new record is fee IF (new.activity_type_code = 1279 AND new.event_amount BETWEEN 0 AND 30) THEN is_fee = true; END IF; -- check if new record contains fees -- TBD -- create new transaction INSERT INTO accounter_schema.transactions (account_id, charge_id, source_id, source_description, currency, event_date, debit_date, amount, current_balance) VALUES (account_id_var, charge_id_var, merged_id, concat( new.activity_description, ' ', coalesce(new.event_details, ''), ' ', coalesce(new.account_name, '') ), 'USD', new.executing_date::text::date, new.value_date::text::date, (CASE WHEN new.event_activity_type_code = 2 THEN (new.event_amount * -1) ELSE new.event_amount END ), new.current_balance) RETURNING id INTO transaction_id_var; -- extend transaction with fee IF (is_fee = TRUE) THEN INSERT INTO accounter_schema.transactions_fees (id) VALUES (transaction_id_var); END IF; RETURN NEW; END; $$; -- drop fee column on transactions table alter table accounter_schema