feat(ops): use 'reset' quota status for plan-usage reset and invalidate quota cache

When ops staff reset a tenant's current-plan usage, the existing
'refunded' terminal status conflated user-initiated refunds with
ops-driven resets, and tenants still saw the old balance in the top-nav
chip until the quota-summary cache TTL expired.

- Introduce a dedicated 'reset' status for quota_reservations, separate
  from 'refunded'. Both the initial and an incremental migration widen
  the CHECK constraint to allow it; the down migration folds 'reset'
  rows back into 'refunded' before tightening the constraint.
- resetQuotaReservations / resetAIPointReservations now write 'reset'
  without touching refunded_amount, and stop cascading into
  ai_point_usage_logs (carried no audit value for ops resets).
- AdminUserService gains an optional cache dependency and calls
  invalidateQuotaSummaryCache(tenant_id) immediately after a successful
  reset so the tenant's top-nav chip refreshes on the next request
  without waiting on TTL.
- Wire the existing appCache into AdminUserService at boot.
- Drop the now-unused ai_point_usage_logs field from the reset response
  and from the ops-web AdminUsersView type.
- Add a unit test covering the cache-key invalidation contract.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-05-12 01:55:29 +08:00
parent 51d32fa96d
commit 1aad002a3e
8 changed files with 69 additions and 35 deletions
@@ -10,6 +10,8 @@ CREATE TABLE quota_reservations (
status VARCHAR(20) NOT NULL DEFAULT 'pending',
expire_at TIMESTAMPTZ NOT NULL,
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
CONSTRAINT chk_quota_reservation_status
CHECK (status IN ('pending', 'confirmed', 'refunded', 'reset'))
);
CREATE INDEX idx_quota_reservation_tenant_status ON quota_reservations(tenant_id, status);
@@ -0,0 +1,12 @@
UPDATE quota_reservations
SET status = 'refunded',
refunded_amount = reserved_amount,
updated_at = NOW()
WHERE status = 'reset';
ALTER TABLE quota_reservations
DROP CONSTRAINT IF EXISTS chk_quota_reservation_status;
ALTER TABLE quota_reservations
ADD CONSTRAINT chk_quota_reservation_status
CHECK (status IN ('pending', 'confirmed', 'refunded'));
@@ -0,0 +1,6 @@
ALTER TABLE quota_reservations
DROP CONSTRAINT IF EXISTS chk_quota_reservation_status;
ALTER TABLE quota_reservations
ADD CONSTRAINT chk_quota_reservation_status
CHECK (status IN ('pending', 'confirmed', 'refunded', 'reset'));