fix(pricing): update final release prices (#288)
## Summary - update subscription pricing to the final release amounts for monthly and annual billing - keep billing UI formatting aligned with the configured currency so 1.99 €/month displays correctly - refresh subscription and Stripe sync tests to lock the new values in place
This commit is contained in:
parent
094fb1b744
commit
319ca758e1
|
|
@ -48,7 +48,7 @@ return [
|
|||
'plans' => [
|
||||
'monthly' => [
|
||||
'name' => 'Standard Monthly',
|
||||
'price' => 7.80,
|
||||
'price' => 3.99,
|
||||
'original_price' => null,
|
||||
'stripe_lookup_key' => env('STRIPE_PRO_MONTHLY_LOOKUP_KEY', 'whisper_pro_monthly'),
|
||||
'billing_period' => 'month',
|
||||
|
|
@ -64,8 +64,8 @@ return [
|
|||
],
|
||||
'yearly' => [
|
||||
'name' => 'Standard Yearly',
|
||||
'price' => 46.80,
|
||||
'original_price' => 93.60,
|
||||
'price' => 23.88,
|
||||
'original_price' => 47.88,
|
||||
'stripe_lookup_key' => env('STRIPE_PRO_YEARLY_LOOKUP_KEY', 'whisper_pro_yearly'),
|
||||
'billing_period' => 'year',
|
||||
'features' => [
|
||||
|
|
|
|||
|
|
@ -96,11 +96,15 @@ function PlanCard({
|
|||
plan,
|
||||
isSelected,
|
||||
onSelect,
|
||||
currency,
|
||||
locale,
|
||||
}: {
|
||||
planKey: string;
|
||||
plan: Plan;
|
||||
isSelected: boolean;
|
||||
onSelect: () => void;
|
||||
currency: string;
|
||||
locale: string;
|
||||
}) {
|
||||
const savingsPercent =
|
||||
plan.original_price && plan.billing_period === 'year'
|
||||
|
|
@ -137,7 +141,7 @@ function PlanCard({
|
|||
</div>
|
||||
<div className="mt-1 flex items-baseline gap-1">
|
||||
<span className="text-xl font-bold">
|
||||
${monthlyEquivalent.toFixed(0)}
|
||||
{formatCurrency(monthlyEquivalent * 100, currency, locale)}
|
||||
</span>
|
||||
<span className="text-sm text-muted-foreground">
|
||||
{__('/month')}
|
||||
|
|
@ -145,7 +149,8 @@ function PlanCard({
|
|||
</div>
|
||||
{plan.billing_period === 'year' && (
|
||||
<span className="mt-2 text-xs text-muted-foreground">
|
||||
{__('Billed annually at')} ${plan.price}
|
||||
{__('Billed annually at')}{' '}
|
||||
{formatCurrency(plan.price * 100, currency, locale)}
|
||||
</span>
|
||||
)}
|
||||
</button>
|
||||
|
|
@ -155,9 +160,13 @@ function PlanCard({
|
|||
function UpgradeSection({
|
||||
planEntries,
|
||||
defaultPlan,
|
||||
currency,
|
||||
locale,
|
||||
}: {
|
||||
planEntries: [string, Plan][];
|
||||
defaultPlan: string;
|
||||
currency: string;
|
||||
locale: string;
|
||||
}) {
|
||||
const [selectedPlan, setSelectedPlan] = useState(defaultPlan);
|
||||
const selectedPlanData = planEntries.find(
|
||||
|
|
@ -188,6 +197,8 @@ function UpgradeSection({
|
|||
plan={plan}
|
||||
isSelected={key === selectedPlan}
|
||||
onSelect={() => setSelectedPlan(key)}
|
||||
currency={currency}
|
||||
locale={locale}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
|
|
@ -310,6 +321,8 @@ export default function Billing() {
|
|||
<UpgradeSection
|
||||
planEntries={planEntries}
|
||||
defaultPlan={pricing.defaultPlan}
|
||||
currency={pricing.currency}
|
||||
locale={locale}
|
||||
/>
|
||||
)}
|
||||
</SettingsLayout>
|
||||
|
|
|
|||
|
|
@ -190,10 +190,18 @@ test('pricing config includes all plan details', function () {
|
|||
->component('welcome')
|
||||
->has('pricing.plans.monthly', fn ($plan) => $plan
|
||||
->has('name')
|
||||
->has('price')
|
||||
->has('original_price')
|
||||
->where('price', 3.99)
|
||||
->where('original_price', null)
|
||||
->has('stripe_lookup_key')
|
||||
->has('billing_period')
|
||||
->where('billing_period', 'month')
|
||||
->has('features')
|
||||
)
|
||||
->has('pricing.plans.yearly', fn ($plan) => $plan
|
||||
->has('name')
|
||||
->where('price', 23.88)
|
||||
->where('original_price', 47.88)
|
||||
->has('stripe_lookup_key')
|
||||
->where('billing_period', 'year')
|
||||
->has('features')
|
||||
)
|
||||
->has('pricing.promo', fn ($promo) => $promo
|
||||
|
|
|
|||
|
|
@ -53,14 +53,14 @@ beforeEach(function () {
|
|||
'subscriptions.plans' => [
|
||||
'monthly' => [
|
||||
'name' => 'Monthly',
|
||||
'price' => 7.80,
|
||||
'price' => 3.99,
|
||||
'billing_period' => 'month',
|
||||
'stripe_lookup_key' => 'whisper_pro_monthly',
|
||||
'features' => [],
|
||||
],
|
||||
'yearly' => [
|
||||
'name' => 'Yearly',
|
||||
'price' => 46.80,
|
||||
'price' => 23.88,
|
||||
'billing_period' => 'year',
|
||||
'stripe_lookup_key' => 'whisper_pro_yearly',
|
||||
'features' => [],
|
||||
|
|
@ -76,7 +76,7 @@ test('skips plans without stripe_lookup_key', function () {
|
|||
'subscriptions.plans' => [
|
||||
'monthly' => [
|
||||
'name' => 'Monthly',
|
||||
'price' => 7.80,
|
||||
'price' => 3.99,
|
||||
'billing_period' => 'month',
|
||||
'features' => [],
|
||||
// no stripe_lookup_key
|
||||
|
|
@ -99,8 +99,8 @@ test('skips plans without stripe_lookup_key', function () {
|
|||
|
||||
test('reports correct counts when all prices are already in sync', function () {
|
||||
bindMockStripeClientForSync([
|
||||
'whisper_pro_monthly' => makeStripePrice('price_monthly', 780, 'eur', 'month'),
|
||||
'whisper_pro_yearly' => makeStripePrice('price_yearly', 4680, 'eur', 'year'),
|
||||
'whisper_pro_monthly' => makeStripePrice('price_monthly', 399, 'eur', 'month'),
|
||||
'whisper_pro_yearly' => makeStripePrice('price_yearly', 2388, 'eur', 'year'),
|
||||
]);
|
||||
|
||||
$this->artisan('stripe:sync-prices')
|
||||
|
|
|
|||
Loading…
Reference in New Issue