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