Billing: fatture manuali, profilo obbligatorio e piani Stripe mensile/annuale.

Rimuove link al portale Stripe in area cliente, aggiunge flusso admin per PDF
fattura e email, blocca checkout senza dati di fatturazione, allinea prezzi
a €4,90/€39,90 e €9,90/€69,90, locale italiano e documentazione deploy.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-06-02 17:10:12 +02:00
parent 148402a97c
commit a5e781729c
78 changed files with 2457 additions and 424 deletions

View File

@@ -15,49 +15,38 @@ RSpec.describe Billing::Stripe::CheckoutSession do
before do
load Rails.root.join("db/seeds/plans.rb")
allow(MatchLiveTv).to receive(:stripe_enabled?).and_return(true)
allow(MatchLiveTv).to receive(:stripe_premium_light_price_id).and_return("price_light")
allow(MatchLiveTv).to receive(:stripe_premium_full_price_id).and_return("price_full")
allow(MatchLiveTv).to receive(:stripe_premium_light_yearly_price_id).and_return("price_light_y")
allow(MatchLiveTv).to receive(:stripe_premium_light_monthly_price_id).and_return("price_light_m")
allow(MatchLiveTv).to receive(:stripe_premium_full_yearly_price_id).and_return("price_full_y")
allow(MatchLiveTv).to receive(:stripe_premium_full_monthly_price_id).and_return("price_full_m")
allow(MatchLiveTv).to receive(:app_public_url).and_return("http://localhost:3000")
Plan.find_by!(slug: "premium_light").update!(stripe_price_id: "price_light")
Plan.find_by!(slug: "premium_full").update!(stripe_price_id: "price_full")
end
it "crea checkout senza subscription esistente" do
session = double(url: "https://checkout.stripe.com/test")
it "crea checkout annuale" do
session = double(url: "https://checkout.stripe.com/yearly")
expect(Stripe::Customer).to receive(:create).and_return(double(id: "cus_new"))
expect(Billing::Stripe::CustomerSync).to receive(:call).with(club: club, customer_id: "cus_new")
expect(Stripe::Checkout::Session).to receive(:create).with(
hash_including(
mode: "subscription",
customer: "cus_new",
line_items: [{ price: "price_light", quantity: 1 }],
subscription_data: { metadata: { club_id: club.id, plan_slug: "premium_light" } }
line_items: [{ price: "price_light_y", quantity: 1 }],
metadata: hash_including(plan_slug: "premium_light", billing_interval: "yearly"),
subscription_data: { metadata: hash_including(billing_interval: "yearly") }
)
).and_return(session)
url = described_class.new(club: club, user: user, plan_slug: "premium_light").url
expect(url).to eq("https://checkout.stripe.com/test")
url = described_class.new(club: club, user: user, plan_slug: "premium_light", interval: "yearly").url
expect(url).to eq("https://checkout.stripe.com/yearly")
end
it "crea checkout per cambio piano con subscription esistente" do
Billing::AssignPlan.call(
club: club,
plan_slug: "premium_light",
status: "active",
stripe_attrs: { stripe_customer_id: "cus_x", stripe_subscription_id: "sub_x" }
)
session = double(url: "https://checkout.stripe.com/change")
expect(Billing::Stripe::CustomerSync).to receive(:call).with(club: club, customer_id: "cus_x")
it "crea checkout mensile" do
session = double(url: "https://checkout.stripe.com/monthly")
allow(Stripe::Customer).to receive(:create).and_return(double(id: "cus_m"))
allow(Billing::Stripe::CustomerSync).to receive(:call)
expect(Stripe::Checkout::Session).to receive(:create).with(
hash_including(
customer: "cus_x",
subscription: "sub_x",
line_items: [{ price: "price_full", quantity: 1 }]
)
hash_including(line_items: [{ price: "price_light_m", quantity: 1 }])
).and_return(session)
url = described_class.new(club: club, user: user, plan_slug: "premium_full").url
expect(url).to eq("https://checkout.stripe.com/change")
url = described_class.new(club: club, user: user, plan_slug: "premium_light", interval: "monthly").url
expect(url).to eq("https://checkout.stripe.com/monthly")
end
end