gendesign/tradein-mvp/backend/data/sql/185_account_quota_overrides.sql
bot-backend 0875d5b9e6 fix(tradein/quota): renumber migration 184 -> 185 (prefix collision)
184_user_events.sql merged into main (#2515) after this branch's base,
claiming the 184 prefix first. Renumber account_quota_overrides to 185
(next free slot) and update the "migration 184" references in the SQL
header comment and account_quota.py docstrings so
test_migrations_manifest.py::test_new_files_do_not_reuse_prefix stays green.
2026-07-13 23:07:11 +03:00

59 lines
3.3 KiB
PL/PgSQL
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

-- Migration 184: account_quota_overrides — персональные месячные лимиты оценок
--
-- WHY:
-- Бонусные попытки для платящих пилотов раздавались хаком через SQL-runbook:
-- `UPDATE account_estimate_usage SET used = used - N` (negative used). Для user2
-- (Брусника) это дало used=-35 при глобальном limit=15 → GET /quota отдавал
-- {limit:15, used:-35, remaining:50} → фронт (EstimateForm.tsx) рендерил абсурд
-- «Осталось 50 из 15». Правильное решение — персональный лимит, а не отрицательный
-- счётчик использования.
--
-- WHAT:
-- 1. Таблица account_quota_overrides(username PK, monthly_limit, note, updated_at) —
-- per-user override глобального settings.estimate_quota_limit. Читается через
-- app.services.account_quota.user_limit().
-- 2. Seed: user2 (Брусника) → monthly_limit=50, пилотный грант 2026-07-13.
-- 3. Сброс хака: account_estimate_usage.used < 0 → 0 (для user2, единственного
-- затронутого аккаунта). После этой миграции user2: limit=50, used=0,
-- remaining=50 — корректно вместо «50 из 15».
--
-- IDEMPOTENCY:
-- CREATE TABLE IF NOT EXISTS + INSERT ... ON CONFLICT DO UPDATE (upsert, безопасен
-- при повторном применении) + UPDATE ... WHERE used < 0 (после первого прогона
-- used=0, условие больше не матчит — безопасный no-op при ре-apply).
--
-- Dependencies: 076_account_estimate_quota.sql (account_estimate_usage).
BEGIN;
CREATE TABLE IF NOT EXISTS account_quota_overrides (
username text PRIMARY KEY,
monthly_limit integer NOT NULL,
note text,
updated_at timestamptz NOT NULL DEFAULT now()
);
COMMENT ON TABLE account_quota_overrides IS
'Персональный override месячного лимита оценок trade-in (вместо глобального '
'settings.estimate_quota_limit). Читается app.services.account_quota.user_limit().';
COMMENT ON COLUMN account_quota_overrides.monthly_limit IS
'Персональный лимит успешных оценок в календарный месяц для username.';
COMMENT ON COLUMN account_quota_overrides.note IS
'Причина override (grant / pilot / manual bump) — для аудита ручных изменений.';
INSERT INTO account_quota_overrides (username, monthly_limit, note)
VALUES ('user2', 50, 'Брусника — пилот, грант 2026-07-13')
ON CONFLICT (username) DO UPDATE SET
monthly_limit = EXCLUDED.monthly_limit,
note = EXCLUDED.note,
updated_at = now();
-- Сбрасываем прежний хак бонусных попыток (negative used), который ломал /quota:
-- limit=15, used=-35 → remaining=50 → фронт рендерил «Осталось 50 из 15».
UPDATE account_estimate_usage
SET used = 0, updated_at = now()
WHERE username = 'user2' AND used < 0;
COMMIT;