From 9309334d52df40acaf9356e69393f299a1f60343 Mon Sep 17 00:00:00 2001 From: Ashwin Kumar Sivakumar Date: Tue, 21 Jul 2026 03:47:54 +0530 Subject: [PATCH] seed: add a starter Tracecoin package per role; fix paise unit bug in invoice line item MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Seeds one TRACECOIN_BUNDLE package per role (100 Tracecoins / ₹250, placeholder pricing per your instruction) so the purchase flow (CreditsPage.tsx -> GET /api/packages, filtered client-side by role_key) has something to show instead of "No packages available for your role," and so create_order/verify_payment/invoice generation can actually be exercised end-to-end. Idempotent (WHERE NOT EXISTS guard) so it's safe against the custom db-migrate runner re-executing every file on every deploy. Adjust real pricing later via the existing admin CRUD (POST/PATCH /api/packages) — no new endpoint needed, it already works. Also fixes a unit bug introduced in the invoice wiring last commit: payments.amount_inr is already paise (copied straight from pricing_packages.price_inr, which is paise despite the name — PayU order creation divides it by 100 via paise_to_rupee_string), but the invoice line item multiplied it by 100 again, making every generated invoice show a 100x inflated amount. --- apps/payments/src/main.rs | 5 +++- ...60721070000_seed_pricing_packages.down.sql | 2 ++ ...0260721070000_seed_pricing_packages.up.sql | 28 +++++++++++++++++++ 3 files changed, 34 insertions(+), 1 deletion(-) create mode 100644 crates/db/migrations/20260721070000_seed_pricing_packages.down.sql create mode 100644 crates/db/migrations/20260721070000_seed_pricing_packages.up.sql diff --git a/apps/payments/src/main.rs b/apps/payments/src/main.rs index a68e2af..a8549ac 100644 --- a/apps/payments/src/main.rs +++ b/apps/payments/src/main.rs @@ -191,7 +191,10 @@ async fn generate_purchase_invoice( description, hsn_sac_code: None, quantity: 1.0, - unit_price_paise: (payment.amount_inr as i64) * 100, + // payments.amount_inr is already paise (copied straight from + // pricing_packages.price_inr, itself paise despite the name — see + // payu::paise_to_rupee_string dividing by 100), not rupees. + unit_price_paise: payment.amount_inr as i64, tax_rate_percent: 18.0, metadata: payment.package_id.map(|id| serde_json::json!({ "package_id": id })), }; diff --git a/crates/db/migrations/20260721070000_seed_pricing_packages.down.sql b/crates/db/migrations/20260721070000_seed_pricing_packages.down.sql new file mode 100644 index 0000000..44225c7 --- /dev/null +++ b/crates/db/migrations/20260721070000_seed_pricing_packages.down.sql @@ -0,0 +1,2 @@ +DELETE FROM pricing_packages +WHERE name = 'Starter Pack' AND package_type = 'TRACECOIN_BUNDLE' AND price_inr = 25000; diff --git a/crates/db/migrations/20260721070000_seed_pricing_packages.up.sql b/crates/db/migrations/20260721070000_seed_pricing_packages.up.sql new file mode 100644 index 0000000..d1ef469 --- /dev/null +++ b/crates/db/migrations/20260721070000_seed_pricing_packages.up.sql @@ -0,0 +1,28 @@ +-- Seed one purchasable Tracecoin package per role so the purchase flow +-- (CreditsPage.tsx -> GET /api/packages, filtered client-side by +-- role_key) has something to show instead of "No packages available for +-- your role." Placeholder pricing per user instruction: ₹250 flat +-- (25000 paise — pricing_packages.price_inr is paise despite the name, +-- see apps/payments/src/payu.rs::paise_to_rupee_string) for 100 +-- Tracecoins, across every role. Adjust via the existing admin API +-- (POST/PATCH /api/packages) once real pricing is decided. +INSERT INTO pricing_packages (name, role_key, package_type, tracecoins_amount, price_inr, description, is_active) +SELECT 'Starter Pack', role_key, 'TRACECOIN_BUNDLE', 100, 25000, '100 Tracecoins', true +FROM (VALUES + ('COMPANY'), + ('CUSTOMER'), + ('JOB_SEEKER'), + ('PHOTOGRAPHER'), + ('MAKEUP_ARTIST'), + ('TUTOR'), + ('DEVELOPER'), + ('VIDEO_EDITOR'), + ('GRAPHIC_DESIGNER'), + ('SOCIAL_MEDIA_MANAGER'), + ('FITNESS_TRAINER'), + ('CATERING_SERVICES'), + ('UGC_CONTENT_CREATOR') +) AS roles(role_key) +WHERE NOT EXISTS ( + SELECT 1 FROM pricing_packages p WHERE p.role_key = roles.role_key +);