fix(db): correct ai_credit_packages pricing (paise not rupees), add missing ai_credit_orders table
Discovered while wiring up role-scoped AI credit packages: the active seed migration (20260615060600) stored price_inr as 99/349/999/2499 - values that read like whole rupees, but every consumer (PayU's paise_to_rupee_string, matching pricing_packages' existing paise convention) treats price_inr as paise, meaning a real purchase would have charged ~1% of the intended price. The actual fix already existed as 20260705110000_ai_credit_packages .up.sql.skip (correct paise values + the ai_credit_orders table create_order inserts into) but got disabled in the same bulk skip pass as everything else this session has been un-tangling - its CREATE TABLE ai_credit_packages (no IF NOT EXISTS) hit 'relation already exists' since 20260615060600 had already created it, aborting before ai_credit_orders was ever created. Net effect before this fix: buying AI credits was completely broken (create_order would 500 - no ai_credit_orders table to insert into). Confirmed zero rows anywhere in ai_credit_orders (the table simply didn't exist) - nothing to reconcile, this is a pre-launch fix. New migration (not resurrecting the old .skip file, to keep a clean linear history matching this session's other fixes): UPDATE the 4 known-wrong rows by name to their correct paise values, CREATE TABLE IF NOT EXISTS ai_credit_orders. Applied to both nxtgauge_test and prod; verified. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
parent
eefc0457be
commit
8e4d64d33b
3 changed files with 60 additions and 48 deletions
|
|
@ -1,48 +0,0 @@
|
|||
-- AI credit purchase packages + PayU order tracking, matching the
|
||||
-- already-shipped frontend contract in
|
||||
-- nxtgauge-frontend-solid/src/components/dashboard/CreditsPage.tsx
|
||||
-- (GET /api/ai-credits, POST /api/ai-credits/order, POST /api/ai-credits/verify).
|
||||
-- price_inr is stored in paise (matches pricing_packages.price_inr's
|
||||
-- existing convention in this codebase), not rupees.
|
||||
|
||||
BEGIN;
|
||||
|
||||
CREATE TABLE ai_credit_packages (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
name VARCHAR(150) NOT NULL,
|
||||
description TEXT,
|
||||
credits INT NOT NULL,
|
||||
price_inr INT NOT NULL, -- paise
|
||||
is_active BOOLEAN NOT NULL DEFAULT TRUE,
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
||||
);
|
||||
|
||||
CREATE INDEX idx_ai_credit_packages_active ON ai_credit_packages(is_active, price_inr);
|
||||
|
||||
INSERT INTO ai_credit_packages (name, description, credits, price_inr) VALUES
|
||||
('Starter AI Credits', '50 AI credits for casual usage', 50, 9900),
|
||||
('Pro AI Credits', '200 AI credits for power users', 200, 34900),
|
||||
('Business AI Credits', '750 AI credits for teams', 750, 99900),
|
||||
('Enterprise AI Credits', '2500 AI credits for heavy usage', 2500, 249900);
|
||||
|
||||
-- PayU order tracking for AI credit purchases, separate from the
|
||||
-- TraceCoins `payments` table (crates/db/migrations/20260317190300_portfolio_payments.up.sql)
|
||||
-- per the earlier decision to keep AI credits fully separate from TraceCoins.
|
||||
CREATE TABLE ai_credit_orders (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
user_id UUID NOT NULL REFERENCES users(id),
|
||||
package_id UUID NOT NULL REFERENCES ai_credit_packages(id),
|
||||
txnid VARCHAR(100) UNIQUE NOT NULL,
|
||||
payu_payment_id VARCHAR(100),
|
||||
amount_inr INT NOT NULL, -- paise
|
||||
credits INT NOT NULL,
|
||||
status VARCHAR(20) NOT NULL DEFAULT 'PENDING', -- PENDING, SUCCESS, FAILED
|
||||
verified_at TIMESTAMPTZ,
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
||||
);
|
||||
|
||||
CREATE INDEX idx_ai_credit_orders_user_id ON ai_credit_orders(user_id);
|
||||
CREATE INDEX idx_ai_credit_orders_txnid ON ai_credit_orders(txnid);
|
||||
|
||||
COMMIT;
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
BEGIN;
|
||||
|
||||
DROP INDEX IF EXISTS idx_ai_credit_orders_txnid;
|
||||
DROP INDEX IF EXISTS idx_ai_credit_orders_user_id;
|
||||
DROP TABLE IF EXISTS ai_credit_orders;
|
||||
|
||||
UPDATE ai_credit_packages SET price_inr = 99 WHERE name = 'Starter AI Credits' AND price_inr = 9900;
|
||||
UPDATE ai_credit_packages SET price_inr = 349 WHERE name = 'Pro AI Credits' AND price_inr = 34900;
|
||||
UPDATE ai_credit_packages SET price_inr = 999 WHERE name = 'Business AI Credits' AND price_inr = 99900;
|
||||
UPDATE ai_credit_packages SET price_inr = 2499 WHERE name = 'Enterprise AI Credits' AND price_inr = 249900;
|
||||
|
||||
COMMIT;
|
||||
|
|
@ -0,0 +1,48 @@
|
|||
-- Fixes a tangled pair of migrations discovered while wiring up role-scoped
|
||||
-- AI credit packages:
|
||||
--
|
||||
-- 20260615060600_ai_credit_packages.up.sql (active) created
|
||||
-- ai_credit_packages and seeded it with price_inr = 99/349/999/2499 -
|
||||
-- values that look like whole rupees, but every consumer of this column
|
||||
-- (apps/payments/src/payu.rs's paise_to_rupee_string, and this repo's own
|
||||
-- pricing_packages.price_inr convention) treats price_inr as PAISE. So a
|
||||
-- "Starter AI Credits" purchase would have charged ₹0.99, not ₹99.
|
||||
--
|
||||
-- 20260705110000_ai_credit_packages.up.sql.skip (disabled) was the
|
||||
-- correction - right paise values (9900/34900/99900/249900) AND the
|
||||
-- ai_credit_orders table apps/payments/src/ai_credits.rs's create_order
|
||||
-- actually inserts into - but it re-issued CREATE TABLE ai_credit_packages
|
||||
-- without IF NOT EXISTS, so it errored on "relation already exists" and
|
||||
-- got skipped in the same bulk cleanup as everything else this session
|
||||
-- has been un-tangling, taking ai_credit_orders down with it.
|
||||
--
|
||||
-- Net effect fixed here: the purchase flow was 100% broken (create_order
|
||||
-- would 500 immediately - no ai_credit_orders table to insert into) and,
|
||||
-- had it worked, would have wildly underscharged. Confirmed zero rows in
|
||||
-- ai_credit_orders anywhere (the table didn't exist), so there is no real
|
||||
-- purchase history to reconcile - this is a pre-launch fix, not a refund.
|
||||
|
||||
BEGIN;
|
||||
|
||||
UPDATE ai_credit_packages SET price_inr = 9900 WHERE name = 'Starter AI Credits' AND price_inr = 99;
|
||||
UPDATE ai_credit_packages SET price_inr = 34900 WHERE name = 'Pro AI Credits' AND price_inr = 349;
|
||||
UPDATE ai_credit_packages SET price_inr = 99900 WHERE name = 'Business AI Credits' AND price_inr = 999;
|
||||
UPDATE ai_credit_packages SET price_inr = 249900 WHERE name = 'Enterprise AI Credits' AND price_inr = 2499;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS ai_credit_orders (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
user_id UUID NOT NULL REFERENCES users(id),
|
||||
package_id UUID NOT NULL REFERENCES ai_credit_packages(id),
|
||||
txnid VARCHAR(100) UNIQUE NOT NULL,
|
||||
payu_payment_id VARCHAR(100),
|
||||
amount_inr INT NOT NULL, -- paise
|
||||
credits INT NOT NULL,
|
||||
status VARCHAR(20) NOT NULL DEFAULT 'PENDING', -- PENDING, SUCCESS, FAILED
|
||||
verified_at TIMESTAMPTZ,
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
||||
);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_ai_credit_orders_user_id ON ai_credit_orders(user_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_ai_credit_orders_txnid ON ai_credit_orders(txnid);
|
||||
|
||||
COMMIT;
|
||||
Loading…
Add table
Reference in a new issue