d0b3f21bde
Remove AI-dependent extensions (ai-chat, ai-categorization, receipt-ocr, invoice-inbox) and their infrastructure (lib/ai/*, ai-consent, LangChain/ Anthropic/OpenAI deps) to simplify core and reduce bundle size. Restructure monolithic settings page into dedicated sub-pages (company, bookkeeping, invoicing, tax, banking, api, account, team, templates) with shared layout and sidebar navigation. Add atomic commit_journal_entry RPC so voucher number increment and status update happen in a single transaction — prevents burned numbers on constraint failures. Add continuity check report and voucher gap explanation tracking. Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
55 lines
1.9 KiB
PL/PgSQL
55 lines
1.9 KiB
PL/PgSQL
-- Atomic journal entry commit: assigns voucher number and posts entry in one transaction.
|
|
-- Prevents burned voucher numbers from failed commits (the counter increment rolls back
|
|
-- if the status update or balance trigger fails).
|
|
--
|
|
-- Only used for the draft→posted transition (commitEntry). reverseEntry and storno
|
|
-- use a different flow (INSERT with voucher number) and still call next_voucher_number.
|
|
CREATE OR REPLACE FUNCTION public.commit_journal_entry(
|
|
p_company_id uuid,
|
|
p_entry_id uuid
|
|
)
|
|
RETURNS TABLE (voucher_number integer)
|
|
LANGUAGE plpgsql
|
|
SECURITY DEFINER
|
|
AS $$
|
|
DECLARE
|
|
v_next integer;
|
|
v_fiscal_period_id uuid;
|
|
v_series text;
|
|
BEGIN
|
|
-- Fetch and lock the draft entry
|
|
SELECT je.fiscal_period_id, COALESCE(je.voucher_series, 'A')
|
|
INTO v_fiscal_period_id, v_series
|
|
FROM public.journal_entries je
|
|
WHERE je.id = p_entry_id
|
|
AND je.company_id = p_company_id
|
|
AND je.status = 'draft'
|
|
FOR UPDATE;
|
|
|
|
IF NOT FOUND THEN
|
|
RAISE EXCEPTION 'Draft journal entry not found: %', p_entry_id;
|
|
END IF;
|
|
|
|
-- Increment voucher sequence (atomic via INSERT ON CONFLICT)
|
|
INSERT INTO public.voucher_sequences (company_id, user_id, fiscal_period_id, voucher_series, last_number)
|
|
VALUES (p_company_id, auth.uid(), v_fiscal_period_id, v_series, 1)
|
|
ON CONFLICT (company_id, fiscal_period_id, voucher_series)
|
|
DO UPDATE SET
|
|
last_number = public.voucher_sequences.last_number + 1,
|
|
updated_at = now()
|
|
RETURNING last_number INTO v_next;
|
|
|
|
-- Update entry to posted with the assigned voucher number.
|
|
-- If the balance trigger (check_balance_on_post) rejects the UPDATE,
|
|
-- the entire transaction rolls back — including the sequence increment.
|
|
-- No burned number, no gap.
|
|
UPDATE public.journal_entries
|
|
SET voucher_number = v_next,
|
|
status = 'posted'
|
|
WHERE id = p_entry_id
|
|
AND company_id = p_company_id;
|
|
|
|
RETURN QUERY SELECT v_next;
|
|
END;
|
|
$$;
|