feat: manage owner usage history records
This commit is contained in:
167
backend/migrations/003_delete_usage_record.up.sql
Normal file
167
backend/migrations/003_delete_usage_record.up.sql
Normal file
@@ -0,0 +1,167 @@
|
||||
-- Add an atomic usage-record deletion path. The operation restores the
|
||||
-- entitlement period and reflows stored balance snapshots for later rows.
|
||||
|
||||
CREATE FUNCTION condon.delete_usage_record(
|
||||
p_usage_record_id uuid
|
||||
)
|
||||
RETURNS void
|
||||
LANGUAGE plpgsql
|
||||
VOLATILE
|
||||
SECURITY INVOKER
|
||||
SET search_path = pg_catalog
|
||||
AS $function$
|
||||
DECLARE
|
||||
v_usage condon.usage_records%ROWTYPE;
|
||||
v_period condon.entitlement_periods%ROWTYPE;
|
||||
v_initial_balance integer;
|
||||
v_now timestamptz := pg_catalog.clock_timestamp();
|
||||
BEGIN
|
||||
IF p_usage_record_id IS NULL THEN
|
||||
RAISE EXCEPTION USING
|
||||
ERRCODE = '22023',
|
||||
MESSAGE = 'CONDON_USAGE_RECORD_ID_REQUIRED';
|
||||
END IF;
|
||||
|
||||
SELECT *
|
||||
INTO v_usage
|
||||
FROM condon.usage_records
|
||||
WHERE id = p_usage_record_id
|
||||
FOR UPDATE;
|
||||
|
||||
IF NOT FOUND THEN
|
||||
RAISE EXCEPTION USING
|
||||
ERRCODE = 'P0002',
|
||||
MESSAGE = 'CONDON_USAGE_RECORD_NOT_FOUND';
|
||||
END IF;
|
||||
|
||||
SELECT *
|
||||
INTO v_period
|
||||
FROM condon.entitlement_periods
|
||||
WHERE id = v_usage.entitlement_period_id
|
||||
FOR UPDATE;
|
||||
|
||||
IF NOT FOUND THEN
|
||||
RAISE EXCEPTION USING
|
||||
ERRCODE = 'P0002',
|
||||
MESSAGE = 'CONDON_ENTITLEMENT_PERIOD_NOT_FOUND';
|
||||
END IF;
|
||||
|
||||
DELETE FROM condon.entitlement_ledger
|
||||
WHERE usage_record_id = v_usage.id;
|
||||
|
||||
DELETE FROM condon.usage_records
|
||||
WHERE id = v_usage.id;
|
||||
|
||||
v_initial_balance := v_period.annual_grant + v_period.carry_forward;
|
||||
|
||||
WITH ordered AS (
|
||||
SELECT
|
||||
ur.id,
|
||||
(
|
||||
v_initial_balance
|
||||
- COALESCE(
|
||||
SUM(ur.use_nights) OVER (
|
||||
ORDER BY
|
||||
CASE WHEN ur.source_sheet IS NULL THEN 1 ELSE 0 END,
|
||||
ur.source_sheet NULLS LAST,
|
||||
ur.source_sequence NULLS LAST,
|
||||
ur.source_row NULLS LAST,
|
||||
ur.created_at ASC,
|
||||
ur.id ASC
|
||||
ROWS BETWEEN UNBOUNDED PRECEDING AND 1 PRECEDING
|
||||
),
|
||||
0
|
||||
)
|
||||
)::integer AS balance_before,
|
||||
(
|
||||
v_initial_balance
|
||||
- SUM(ur.use_nights) OVER (
|
||||
ORDER BY
|
||||
CASE WHEN ur.source_sheet IS NULL THEN 1 ELSE 0 END,
|
||||
ur.source_sheet NULLS LAST,
|
||||
ur.source_sequence NULLS LAST,
|
||||
ur.source_row NULLS LAST,
|
||||
ur.created_at ASC,
|
||||
ur.id ASC
|
||||
)
|
||||
)::integer AS balance_after
|
||||
FROM condon.usage_records AS ur
|
||||
WHERE ur.entitlement_period_id = v_period.id
|
||||
)
|
||||
UPDATE condon.usage_records AS ur
|
||||
SET
|
||||
balance_before = ordered.balance_before,
|
||||
balance_after = ordered.balance_after
|
||||
FROM ordered
|
||||
WHERE ur.id = ordered.id;
|
||||
|
||||
WITH ordered AS (
|
||||
SELECT
|
||||
ur.id,
|
||||
(
|
||||
v_initial_balance
|
||||
- COALESCE(
|
||||
SUM(ur.use_nights) OVER (
|
||||
ORDER BY
|
||||
CASE WHEN ur.source_sheet IS NULL THEN 1 ELSE 0 END,
|
||||
ur.source_sheet NULLS LAST,
|
||||
ur.source_sequence NULLS LAST,
|
||||
ur.source_row NULLS LAST,
|
||||
ur.created_at ASC,
|
||||
ur.id ASC
|
||||
ROWS BETWEEN UNBOUNDED PRECEDING AND 1 PRECEDING
|
||||
),
|
||||
0
|
||||
)
|
||||
)::integer AS balance_before,
|
||||
(
|
||||
v_initial_balance
|
||||
- SUM(ur.use_nights) OVER (
|
||||
ORDER BY
|
||||
CASE WHEN ur.source_sheet IS NULL THEN 1 ELSE 0 END,
|
||||
ur.source_sheet NULLS LAST,
|
||||
ur.source_sequence NULLS LAST,
|
||||
ur.source_row NULLS LAST,
|
||||
ur.created_at ASC,
|
||||
ur.id ASC
|
||||
)
|
||||
)::integer AS balance_after
|
||||
FROM condon.usage_records AS ur
|
||||
WHERE ur.entitlement_period_id = v_period.id
|
||||
)
|
||||
UPDATE condon.entitlement_ledger AS ledger
|
||||
SET
|
||||
balance_before = ordered.balance_before,
|
||||
balance_after = ordered.balance_after
|
||||
FROM ordered
|
||||
WHERE ledger.usage_record_id = ordered.id
|
||||
AND ledger.entry_type = 'usage';
|
||||
|
||||
UPDATE condon.entitlement_periods
|
||||
SET
|
||||
current_balance = (
|
||||
v_initial_balance
|
||||
- COALESCE(
|
||||
(
|
||||
SELECT SUM(ur.use_nights)
|
||||
FROM condon.usage_records AS ur
|
||||
WHERE ur.entitlement_period_id = v_period.id
|
||||
),
|
||||
0
|
||||
)
|
||||
)::integer,
|
||||
row_version = row_version + 1,
|
||||
updated_at = v_now
|
||||
WHERE id = v_period.id;
|
||||
|
||||
DELETE FROM condon.bookings AS booking
|
||||
WHERE booking.confirmation_no = v_usage.confirmation_no
|
||||
AND NOT EXISTS (
|
||||
SELECT 1
|
||||
FROM condon.usage_records AS ur
|
||||
WHERE ur.confirmation_no = booking.confirmation_no
|
||||
);
|
||||
END;
|
||||
$function$;
|
||||
|
||||
REVOKE ALL ON FUNCTION condon.delete_usage_record(uuid) FROM PUBLIC;
|
||||
Reference in New Issue
Block a user