From bf69270913731104e56a4e2fab795ec04db0a56e Mon Sep 17 00:00:00 2001 From: Deeman Date: Tue, 3 Mar 2026 15:36:12 +0100 Subject: [PATCH] =?UTF-8?q?feat(billing):=20A6=20=E2=80=94=20planner/suppl?= =?UTF-8?q?ier=20routes=20use=20get=5Fprice=5Fid()=20+=20=5Fprovider()?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - planner/routes.py: import get_price_id instead of get_paddle_price, export_checkout uses _provider().build_checkout_payload() - suppliers/routes.py: all get_paddle_price → get_price_id, signup_checkout uses _provider().build_multi_item_checkout_payload(), dashboard boosts use get_all_price_ids() bulk load Co-Authored-By: Claude Opus 4.6 --- web/src/padelnomics/planner/routes.py | 29 ++++++++++---------- web/src/padelnomics/suppliers/routes.py | 36 +++++++++++-------------- 2 files changed, 30 insertions(+), 35 deletions(-) diff --git a/web/src/padelnomics/planner/routes.py b/web/src/padelnomics/planner/routes.py index a236205..7ee3fa5 100644 --- a/web/src/padelnomics/planner/routes.py +++ b/web/src/padelnomics/planner/routes.py @@ -18,7 +18,7 @@ from ..core import ( feature_gate, fetch_all, fetch_one, - get_paddle_price, + get_price_id, utcnow_iso, ) from ..i18n import get_translations @@ -687,7 +687,9 @@ async def export_details(): @login_required @csrf_protect async def export_checkout(): - """Return JSON for Paddle.js overlay checkout for business plan PDF.""" + """Return checkout JSON for business plan PDF (works with Paddle overlay or Stripe redirect).""" + from ..billing.routes import _provider + form = await request.form scenario_id = form.get("scenario_id") language = form.get("language", "en") @@ -703,23 +705,20 @@ async def export_checkout(): if not scenario: return jsonify({"error": "Scenario not found."}), 404 - price_id = await get_paddle_price("business_plan") + price_id = await get_price_id("business_plan") if not price_id: return jsonify({"error": "Product not configured. Contact support."}), 500 - return jsonify( - { - "items": [{"priceId": price_id, "quantity": 1}], - "customData": { - "user_id": str(g.user["id"]), - "scenario_id": str(scenario_id), - "language": language, - }, - "settings": { - "successUrl": f"{config.BASE_URL}/planner/export/success", - }, - } + payload = _provider().build_checkout_payload( + price_id=price_id, + custom_data={ + "user_id": str(g.user["id"]), + "scenario_id": str(scenario_id), + "language": language, + }, + success_url=f"{config.BASE_URL}/planner/export/success", ) + return jsonify(payload) @bp.route("/export/success") diff --git a/web/src/padelnomics/suppliers/routes.py b/web/src/padelnomics/suppliers/routes.py index afbd394..6646f96 100644 --- a/web/src/padelnomics/suppliers/routes.py +++ b/web/src/padelnomics/suppliers/routes.py @@ -17,7 +17,8 @@ from ..core import ( feature_gate, fetch_all, fetch_one, - get_paddle_price, + get_all_price_ids, + get_price_id, is_flag_enabled, ) from ..i18n import get_translations @@ -383,7 +384,9 @@ def _compute_order(data: dict, included_boosts: list, t: dict) -> dict: @bp.route("/signup/checkout", methods=["POST"]) @csrf_protect async def signup_checkout(): - """Validate form, return JSON for Paddle.js overlay checkout.""" + """Validate form, return checkout JSON (Paddle overlay or Stripe redirect).""" + from ..billing.routes import _provider + form = await request.form accumulated = _parse_accumulated(form) @@ -401,9 +404,9 @@ async def signup_checkout(): if period == "yearly" else plan_info.get("paddle_key_monthly", plan) ) - plan_price_id = await get_paddle_price(price_key) + plan_price_id = await get_price_id(price_key) if not plan_price_id: - return jsonify({"error": "Invalid plan selected. Run setup_paddle first."}), 400 + return jsonify({"error": "Invalid plan selected. Run setup first."}), 400 # Build items list items = [{"priceId": plan_price_id, "quantity": 1}] @@ -416,14 +419,14 @@ async def signup_checkout(): for b in BOOST_OPTIONS: if b["type"] in selected_boosts and b["type"] not in included_boosts: - price_id = await get_paddle_price(b["key"]) + price_id = await get_price_id(b["key"]) if price_id: items.append({"priceId": price_id, "quantity": 1}) # Add credit pack (one-time) credit_pack = accumulated.get("credit_pack", "") if credit_pack: - price_id = await get_paddle_price(credit_pack) + price_id = await get_price_id(credit_pack) if price_id: items.append({"priceId": price_id, "quantity": 1}) @@ -477,15 +480,12 @@ async def signup_checkout(): "plan": plan, } - return jsonify( - { - "items": items, - "customData": custom_data, - "settings": { - "successUrl": f"{config.BASE_URL}/suppliers/signup/success", - }, - } + payload = _provider().build_multi_item_checkout_payload( + items=items, + custom_data=custom_data, + success_url=f"{config.BASE_URL}/suppliers/signup/success", ) + return jsonify(payload) @bp.route("/claim/") @@ -1035,12 +1035,8 @@ async def dashboard_boosts(): (supplier["id"],), ) - # Resolve Paddle price IDs for buy buttons - price_ids = {} - for b in BOOST_OPTIONS: - price_ids[b["key"]] = await get_paddle_price(b["key"]) - for cp in CREDIT_PACK_OPTIONS: - price_ids[cp["key"]] = await get_paddle_price(cp["key"]) + # Resolve price IDs for buy buttons (from active provider) + price_ids = await get_all_price_ids() return await render_template( "suppliers/partials/dashboard_boosts.html",