-- Import-mode companies (gl_auto_post=false) get their GL from the Buildium pull,
-- so locally-entered bank transactions never reached the GL and were invisible on
-- GL-based reports (P&L, Income Statement, Balance Sheet) even though they
-- reconciled. This lets those manual transactions post to the GL.
--
-- A transaction posts UNLESS it is: voided; sourced from the Buildium GL pull
-- (journal_entry_line_id set — would double-count); explicitly excluded
-- (exclude_from_gl — used to freeze pre-existing manual/duplicate register rows on
-- already-tied books so they don't double-post if later edited); a transfer/deposit
-- leg (handled by post_transfer_gl / post_deposit_gl); or missing an account/counter.
--
-- One-time data ops applied alongside this migration (not repeatable, so kept out
-- of the migration body): (a) linked every Buildium-sourced register row to its GL
-- bank line via (account,date,direction,amount) matching; (b) set
-- exclude_from_gl=true on all remaining pre-existing unlinked manual rows for
-- import companies EXCEPT Bent Oak; (c) posted Bent Oak's 4 verified-missing
-- operating rows (interest/insurance/electric/water-fee).
alter table accounting.transactions
  add column if not exists exclude_from_gl boolean not null default false;

create or replace function accounting.post_transaction_gl(_txn_id uuid)
 returns void language plpgsql security definer set search_path to 'public', 'accounting'
as $function$
declare t accounting.transactions%rowtype; _counter uuid; _je uuid; _amt numeric;
begin
  select * into t from accounting.transactions where id=_txn_id;
  if not found then return; end if;
  perform accounting._gl_clear(t.company_id, 'acmacc_txn', t.id::text);
  if coalesce(t.voided,false) then return; end if;
  if t.journal_entry_line_id is not null then return; end if;  -- already in GL via Buildium pull
  if coalesce(t.exclude_from_gl,false) then return; end if;    -- frozen legacy/duplicate register row
  if t.transfer_id is not null or t.deposit_id is not null then return; end if;
  if t.account_id is null then return; end if;
  _amt := coalesce(t.amount,0);
  if _amt = 0 then return; end if;
  _counter := case
    when t.customer_id is not null then accounting.coa_ar(t.company_id)
    when t.coa_account_id is not null then t.coa_account_id
    when t.vendor_id is not null then accounting.coa_ap(t.company_id)
    else null end;
  if _counter is null then return; end if;

  insert into accounting.journal_entries (company_id, date, description, reference, external_source, external_id)
  values (t.company_id, t.date, coalesce(nullif(t.description,''), 'Bank transaction'), t.reference, 'acmacc_txn', t.id::text)
  returning id into _je;
  if t.type = 'credit' then
    insert into accounting.journal_entry_lines (journal_entry_id, account_id, debit, credit, description) values
      (_je, t.account_id, _amt, 0, t.description), (_je, _counter, 0, _amt, t.description);
  else
    insert into accounting.journal_entry_lines (journal_entry_id, account_id, debit, credit, description) values
      (_je, _counter, _amt, 0, t.description), (_je, t.account_id, 0, _amt, t.description);
  end if;
end$function$;