Enhance ledger operations and referral lifecycle
CI / verify (push) Has been cancelled
CI / publish (push) Has been cancelled

Add traceable ledger filtering and permanent referral codes so operators can investigate credit activity without weakening immutable accounting guarantees.
This commit is contained in:
Rocky
2026-08-20 22:14:22 +08:00
parent 74c3fcd45f
commit b5212dcdc2
38 changed files with 3080 additions and 620 deletions
@@ -0,0 +1,17 @@
ALTER TABLE credit_ledger
MODIFY reference_id CHAR(36) CHARACTER SET ascii COLLATE ascii_bin NULL;
ALTER TABLE provider_requests
MODIFY reservation_id CHAR(36) CHARACTER SET ascii COLLATE ascii_bin NULL;
CREATE INDEX idx_credit_ledger_amount_id
ON credit_ledger (amount_delta, id);
CREATE INDEX idx_credit_ledger_user_amount_id
ON credit_ledger (user_id, amount_delta, id);
CREATE INDEX idx_provider_requests_capability_source_reservation
ON provider_requests (capability, request_source, reservation_id);
CREATE INDEX idx_provider_requests_source_capability_reservation
ON provider_requests (request_source, capability, reservation_id);
@@ -0,0 +1,29 @@
-- Keep historical campaign-scoped codes as valid aliases while selecting exactly
-- one permanent code for every account. New writes claim this mapping atomically.
CREATE TABLE referral_owner_codes (
owner_user_id VARCHAR(36) CHARACTER SET ascii COLLATE ascii_bin NOT NULL,
code_id CHAR(36) NOT NULL,
created_at DATETIME(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6),
PRIMARY KEY (owner_user_id),
UNIQUE KEY uk_referral_owner_codes_code (code_id),
CONSTRAINT fk_referral_owner_codes_code
FOREIGN KEY (code_id) REFERENCES referral_codes (id) ON DELETE CASCADE
) ENGINE = InnoDB;
-- Preserve the code most recently distributed by the previous implementation.
-- Older codes remain in referral_codes so already-shared links never break.
INSERT INTO referral_owner_codes (owner_user_id, code_id, created_at)
SELECT candidate.owner_user_id, candidate.id, candidate.created_at
FROM referral_codes candidate
WHERE NOT EXISTS (
SELECT 1
FROM referral_codes newer
WHERE newer.owner_user_id = candidate.owner_user_id
AND (
newer.created_at > candidate.created_at
OR (
newer.created_at = candidate.created_at
AND newer.id > candidate.id
)
)
);