Terminal
This commit is contained in:
@@ -1,173 +0,0 @@
|
|||||||
-- The rest of the billing views had the same fault as v_billing_detail.
|
|
||||||
--
|
|
||||||
-- 20260807002000 fixed v_billing_detail, but three sibling views still inner
|
|
||||||
-- joined public.students purely to build a display name. A billing administrator
|
|
||||||
-- can read every invoice, payment and ledger entry in the organisation and no
|
|
||||||
-- student rows at all, so that join silently emptied each of them:
|
|
||||||
--
|
|
||||||
-- v_outstanding_invoices 0 rows, while public.invoices showed 5
|
|
||||||
-- v_student_ledger 0 rows, while public.payments showed 1
|
|
||||||
--
|
|
||||||
-- Both now resolve the name through student_display_name(), which re-checks
|
|
||||||
-- entitlement inside its SECURITY DEFINER body. Student row access is unchanged;
|
|
||||||
-- only the name lookup moved. v_payment_detail is added for the same reason —
|
|
||||||
-- the receivables screen was reaching for payments.students(...) directly and
|
|
||||||
-- rendering "—" for every payer.
|
|
||||||
|
|
||||||
-- ============================================================================
|
|
||||||
-- 1. Outstanding invoices
|
|
||||||
-- ============================================================================
|
|
||||||
CREATE OR REPLACE VIEW public.v_outstanding_invoices
|
|
||||||
WITH (security_invoker = true) AS
|
|
||||||
SELECT
|
|
||||||
i.id AS invoice_id,
|
|
||||||
i.invoice_number,
|
|
||||||
i.student_id,
|
|
||||||
public.student_display_name(i.student_id) AS student_name,
|
|
||||||
i.household_id,
|
|
||||||
i.campus_id,
|
|
||||||
c.name AS campus_name,
|
|
||||||
i.billing_period_start,
|
|
||||||
i.billing_period_end,
|
|
||||||
i.invoice_date,
|
|
||||||
i.due_date,
|
|
||||||
i.total_cents,
|
|
||||||
i.amount_paid_cents,
|
|
||||||
i.balance_due_cents,
|
|
||||||
i.status,
|
|
||||||
CURRENT_DATE - i.due_date AS days_overdue
|
|
||||||
FROM public.invoices i
|
|
||||||
LEFT JOIN public.campuses c ON c.id = i.campus_id
|
|
||||||
WHERE i.status = ANY (ARRAY['issued'::text, 'partially_paid'::text])
|
|
||||||
AND i.balance_due_cents > 0;
|
|
||||||
|
|
||||||
GRANT SELECT ON public.v_outstanding_invoices TO authenticated;
|
|
||||||
|
|
||||||
-- ============================================================================
|
|
||||||
-- 2. Payments, with the payer named
|
|
||||||
-- ============================================================================
|
|
||||||
CREATE OR REPLACE VIEW public.v_payment_detail
|
|
||||||
WITH (security_invoker = true) AS
|
|
||||||
SELECT
|
|
||||||
p.id AS payment_id,
|
|
||||||
p.student_id,
|
|
||||||
public.student_display_name(p.student_id) AS student_name,
|
|
||||||
p.household_id,
|
|
||||||
p.campus_id,
|
|
||||||
c.name AS campus_name,
|
|
||||||
p.kind,
|
|
||||||
p.method,
|
|
||||||
p.amount_cents,
|
|
||||||
p.received_at,
|
|
||||||
p.effective_date,
|
|
||||||
p.reference_number,
|
|
||||||
p.payer_name,
|
|
||||||
p.third_party_name,
|
|
||||||
p.scholarship_id,
|
|
||||||
p.status,
|
|
||||||
p.reverses_payment_id,
|
|
||||||
p.void_reason,
|
|
||||||
p.notes,
|
|
||||||
p.received_by
|
|
||||||
FROM public.payments p
|
|
||||||
LEFT JOIN public.campuses c ON c.id = p.campus_id;
|
|
||||||
|
|
||||||
GRANT SELECT ON public.v_payment_detail TO authenticated;
|
|
||||||
|
|
||||||
-- ============================================================================
|
|
||||||
-- 3. Student ledger
|
|
||||||
-- ============================================================================
|
|
||||||
-- Reproduced from the deployed definition with only the trailing students join
|
|
||||||
-- removed, so the running-balance window and the four-way UNION behind it are
|
|
||||||
-- untouched.
|
|
||||||
CREATE OR REPLACE VIEW public.v_student_ledger
|
|
||||||
WITH (security_invoker = true) AS
|
|
||||||
WITH events AS (
|
|
||||||
SELECT i.student_id,
|
|
||||||
i.campus_id,
|
|
||||||
i.invoice_date AS txn_date,
|
|
||||||
i.billing_period_start AS effective_date,
|
|
||||||
i.created_at AS sort_ts,
|
|
||||||
'invoice'::text AS source,
|
|
||||||
'charge'::text AS direction,
|
|
||||||
i.total_cents AS amount_cents,
|
|
||||||
i.invoice_number AS reference,
|
|
||||||
NULL::text AS method,
|
|
||||||
i.issued_by AS entered_by,
|
|
||||||
i.id AS ref_id
|
|
||||||
FROM invoices i
|
|
||||||
WHERE i.status <> 'void'::text
|
|
||||||
UNION ALL
|
|
||||||
SELECT p.student_id,
|
|
||||||
p.campus_id,
|
|
||||||
p.received_at::date AS received_at,
|
|
||||||
p.effective_date,
|
|
||||||
p.created_at,
|
|
||||||
'payment'::text,
|
|
||||||
CASE
|
|
||||||
WHEN p.kind = 'payment'::text THEN 'credit'::text
|
|
||||||
ELSE 'charge'::text
|
|
||||||
END AS "case",
|
|
||||||
CASE
|
|
||||||
WHEN p.kind = 'payment'::text THEN - p.amount_cents
|
|
||||||
ELSE p.amount_cents
|
|
||||||
END AS amount_cents,
|
|
||||||
p.reference_number,
|
|
||||||
p.method,
|
|
||||||
p.received_by,
|
|
||||||
p.id
|
|
||||||
FROM payments p
|
|
||||||
WHERE p.status <> 'voided'::text AND p.student_id IS NOT NULL
|
|
||||||
UNION ALL
|
|
||||||
SELECT c.student_id,
|
|
||||||
NULL::uuid AS uuid,
|
|
||||||
c.issued_at::date AS issued_at,
|
|
||||||
c.issued_at::date AS issued_at,
|
|
||||||
c.issued_at,
|
|
||||||
'credit'::text,
|
|
||||||
'credit'::text,
|
|
||||||
- c.amount_cents,
|
|
||||||
NULL::text,
|
|
||||||
NULL::text,
|
|
||||||
c.issued_by,
|
|
||||||
c.id
|
|
||||||
FROM student_credits c
|
|
||||||
WHERE NOT c.is_void
|
|
||||||
UNION ALL
|
|
||||||
SELECT l.student_id,
|
|
||||||
NULL::uuid AS uuid,
|
|
||||||
l.date,
|
|
||||||
l.date,
|
|
||||||
l.created_at,
|
|
||||||
'ledger_entry'::text,
|
|
||||||
CASE
|
|
||||||
WHEN l.kind = 'charge'::ledger_kind THEN 'charge'::text
|
|
||||||
ELSE 'credit'::text
|
|
||||||
END AS "case",
|
|
||||||
CASE
|
|
||||||
WHEN l.kind = 'charge'::ledger_kind THEN l.amount_cents
|
|
||||||
ELSE - l.amount_cents
|
|
||||||
END AS "case",
|
|
||||||
NULL::text,
|
|
||||||
l.category::text AS category,
|
|
||||||
l.created_by,
|
|
||||||
l.id
|
|
||||||
FROM ledger_entries l
|
|
||||||
)
|
|
||||||
SELECT e.student_id,
|
|
||||||
e.campus_id,
|
|
||||||
e.txn_date,
|
|
||||||
e.effective_date,
|
|
||||||
e.sort_ts,
|
|
||||||
e.source,
|
|
||||||
e.direction,
|
|
||||||
e.amount_cents,
|
|
||||||
e.reference,
|
|
||||||
e.method,
|
|
||||||
e.entered_by,
|
|
||||||
e.ref_id,
|
|
||||||
public.student_display_name(e.student_id) AS student_name,
|
|
||||||
sum(e.amount_cents) OVER (PARTITION BY e.student_id ORDER BY e.effective_date, e.sort_ts, e.ref_id ROWS UNBOUNDED PRECEDING) AS running_balance_cents
|
|
||||||
FROM events e;
|
|
||||||
|
|
||||||
GRANT SELECT ON public.v_student_ledger TO authenticated;
|
|
||||||
Reference in New Issue
Block a user