-- Finaccount-like Excel API POC for GL ACCOUNTS FUNCTIONS. -- -- Scope: -- - GetAccountBaseAmount -- - GetAccountRealBaseAmount -- - GetAccountAmount -- - GetAccountAbbr -- - GetAccountName -- - GetAccountContact -- -- Design notes: -- - PostgreSQL lowercases function names; VBA calls these SQL functions. -- - Balances are computed as of p_value_date. -- - This POC uses posted account moves only. -- - p_currency_iso is treated as the transaction currency. -- - p_company_key accepts either the company party code or company name. -- - p_currency_iso accepts the currency code/name/symbol/numeric code/id. -- - If account.move.line.second_currency is empty, the company currency is -- used as transaction currency and the company amount is reused. create schema if not exists excel_api; create or replace view excel_api.gl_account_lines as select aml.id as move_line_id, am.id as move_id, cc.id as company_id, cp.code as company_key, cp.name as company_name, aa.id as account_id, aa.code as account_code, aa.name as account_name, coalesce(tx_cur.code, base_cur.code) as transaction_currency_code, coalesce(aml.second_currency, cc.currency) as transaction_currency_id, base_cur.code as base_currency_code, cc.currency as base_currency_id, am.date as posting_date, am.state as posting_status, aml.party as party_id, party.code as party_code, party.name as party_name, coalesce(aml.debit, 0) as debit_base_currency, coalesce(aml.credit, 0) as credit_base_currency, coalesce(aml.debit, 0) - coalesce(aml.credit, 0) as balance_base_currency, case when aml.second_currency is not null then coalesce(aml.amount_second_currency, 0) else coalesce(aml.debit, 0) - coalesce(aml.credit, 0) end as balance_transaction_currency from account_move_line aml join account_move am on am.id = aml.move join account_account aa on aa.id = aml.account join company_company cc on cc.id = am.company left join party_party cp on cp.id = cc.party left join currency_currency base_cur on base_cur.id = cc.currency left join currency_currency tx_cur on tx_cur.id = aml.second_currency left join party_party party on party.id = aml.party where aa.type is not null and coalesce(aa.closed, false) is false; create or replace function excel_api.currency_rate_at( p_currency_id integer, p_value_date date) returns numeric language sql stable as $$ select cr.rate from currency_currency_rate cr where cr.currency = p_currency_id and cr.date <= p_value_date order by cr.date desc limit 1 $$; create or replace function excel_api.company_matches( p_company_key text, p_company_input text) returns boolean language sql stable as $$ select upper(btrim(coalesce(p_company_key, ''))) = upper(btrim(coalesce(p_company_input, ''))) or upper(btrim(coalesce(p_company_input, ''))) = ( select upper(btrim(coalesce(pp.name, ''))) from company_company cc left join party_party pp on pp.id = cc.party where pp.code = p_company_key limit 1) $$; create or replace function excel_api.currency_matches( p_currency_id integer, p_currency_input text) returns boolean language sql stable as $$ select exists ( select 1 from currency_currency cur where cur.id = p_currency_id and upper(btrim(coalesce(p_currency_input, ''))) in ( upper(btrim(cur.id::text)), upper(btrim(coalesce(cur.code, ''))), upper(btrim(coalesce(cur.name, ''))), upper(btrim(coalesce(cur.symbol, ''))), upper(btrim(coalesce(cur.numeric_code, ''))))) $$; create or replace function excel_api.get_account_amount( p_company_key text, p_account_code text, p_currency_iso text, p_value_date date) returns numeric language sql stable as $$ select coalesce(sum(gl.balance_transaction_currency), 0) from excel_api.gl_account_lines gl where excel_api.company_matches(gl.company_key, p_company_key) and gl.account_code = p_account_code and excel_api.currency_matches(gl.transaction_currency_id, p_currency_iso) and gl.posting_date <= p_value_date and gl.posting_status = 'posted' $$; create or replace function excel_api.get_account_real_base_amount( p_company_key text, p_account_code text, p_currency_iso text, p_value_date date) returns numeric language sql stable as $$ select coalesce(sum(gl.balance_base_currency), 0) from excel_api.gl_account_lines gl where excel_api.company_matches(gl.company_key, p_company_key) and gl.account_code = p_account_code and excel_api.currency_matches(gl.transaction_currency_id, p_currency_iso) and gl.posting_date <= p_value_date and gl.posting_status = 'posted' $$; create or replace function excel_api.get_account_base_amount( p_company_key text, p_account_code text, p_currency_iso text, p_value_date date) returns numeric language sql stable as $$ select coalesce(sum( case when gl.transaction_currency_id = gl.base_currency_id then gl.balance_transaction_currency else gl.balance_transaction_currency * excel_api.currency_rate_at(gl.base_currency_id, p_value_date) / nullif( excel_api.currency_rate_at( gl.transaction_currency_id, p_value_date), 0) end), 0) from excel_api.gl_account_lines gl where excel_api.company_matches(gl.company_key, p_company_key) and gl.account_code = p_account_code and excel_api.currency_matches(gl.transaction_currency_id, p_currency_iso) and gl.posting_date <= p_value_date and gl.posting_status = 'posted' $$; create or replace function excel_api.get_account_abbr( p_company_key text, p_account_code text, p_currency_iso text, p_value_date date) returns text language sql stable as $$ select gl.account_code from excel_api.gl_account_lines gl where excel_api.company_matches(gl.company_key, p_company_key) and gl.account_code = p_account_code and excel_api.currency_matches(gl.transaction_currency_id, p_currency_iso) and gl.posting_date <= p_value_date order by gl.posting_date desc, gl.move_line_id desc limit 1 $$; create or replace function excel_api.get_account_name( p_company_key text, p_account_code text, p_currency_iso text, p_value_date date) returns text language sql stable as $$ select gl.account_name from excel_api.gl_account_lines gl where excel_api.company_matches(gl.company_key, p_company_key) and gl.account_code = p_account_code and excel_api.currency_matches(gl.transaction_currency_id, p_currency_iso) and gl.posting_date <= p_value_date order by gl.posting_date desc, gl.move_line_id desc limit 1 $$; create or replace function excel_api.get_account_contact( p_company_key text, p_account_code text, p_currency_iso text, p_value_date date) returns text language sql stable as $$ select nullif(string_agg(distinct coalesce(gl.party_code, gl.party_name), ', ' order by coalesce(gl.party_code, gl.party_name)), '') from excel_api.gl_account_lines gl where excel_api.company_matches(gl.company_key, p_company_key) and gl.account_code = p_account_code and excel_api.currency_matches(gl.transaction_currency_id, p_currency_iso) and gl.posting_date <= p_value_date and gl.posting_status = 'posted' and coalesce(gl.party_code, gl.party_name) is not null $$;