0
Fork 0
mirror of https://github.com/TryGhost/Ghost.git synced 2025-02-24 23:48:13 -05:00

Updated setup wizard pricing to use new product API

refs https://github.com/TryGhost/Team/issues/721

The setup wizard in Admin handles creating default prices as well as handling new price changes on default Product. This change updates the handling to use updated Products API with support for `monthly/yearly_price` values that offloads price handling to backend and makes the logic simpler. Also updates the stripe connect flow to use new API for creating default prices.
This commit is contained in:
Rishabh 2021-06-04 13:22:20 +05:30 committed by Rishabh Garg
parent 2b13bfea98
commit d4cb7f9d1d
3 changed files with 50 additions and 163 deletions

View file

@ -80,17 +80,6 @@ export default class GhLaunchWizardConnectStripeComponent extends Component {
});
}
updatePortalPlans(monthlyPriceId, yearlyPriceId) {
let portalPlans = ['free'];
if (monthlyPriceId) {
portalPlans.push(monthlyPriceId);
}
if (yearlyPriceId) {
portalPlans.push(yearlyPriceId);
}
this.settings.set('portalPlans', portalPlans);
}
@task({drop: true})
*saveProduct() {
let pollTimeout = 0;
@ -169,38 +158,30 @@ export default class GhLaunchWizardConnectStripeComponent extends Component {
try {
yield this.settings.save();
const products = yield this.store.query('product', {include: 'stripe_prices'});
const products = yield this.store.query('product', {include: 'monthly_price,yearly_price'});
this.product = products.firstObject;
if (this.product) {
const stripePrices = this.product.stripePrices || [];
const yearlyDiscount = this.calculateDiscount(5, 50);
stripePrices.push(
{
nickname: 'Monthly',
amount: 500,
active: 1,
description: 'Full access',
currency: 'usd',
interval: 'month',
type: 'recurring'
},
{
nickname: 'Yearly',
amount: 5000,
active: 1,
currency: 'usd',
description: yearlyDiscount > 0 ? `${yearlyDiscount}% discount` : 'Full access',
interval: 'year',
type: 'recurring'
}
);
this.product.set('stripePrices', stripePrices);
const updatedProduct = yield this.saveProduct.perform();
const monthlyPrice = this.getActivePrice(updatedProduct.stripePrices, 'month', 500, 'usd');
const yearlyPrice = this.getActivePrice(updatedProduct.stripePrices, 'year', 5000, 'usd');
this.updatePortalPlans(monthlyPrice.id, yearlyPrice.id);
this.settings.set('membersMonthlyPriceId', monthlyPrice.id);
this.settings.set('membersYearlyPriceId', yearlyPrice.id);
this.product.set('monthlyPrice', {
nickname: 'Monthly',
amount: 500,
active: 1,
description: 'Full access',
currency: 'usd',
interval: 'month',
type: 'recurring'
});
this.product.set('yearlyPrice', {
nickname: 'Yearly',
amount: 5000,
active: 1,
currency: 'usd',
description: yearlyDiscount > 0 ? `${yearlyDiscount}% discount` : 'Full access',
interval: 'year',
type: 'recurring'
});
yield this.saveProduct.perform();
this.settings.set('portalPlans', ['free', 'monthly', 'yearly']);
yield this.settings.save();
}

View file

@ -14,89 +14,33 @@ export default class GhLaunchWizardFinaliseComponent extends Component {
this.settings.rollbackAttributes();
}
updatePortalPlans(monthlyPriceId, yearlyPriceId, data) {
let portalPlans = this.settings.get('portalPlans') || [];
const currentMontlyPriceId = this.settings.get('membersMonthlyPriceId');
const currentYearlyPriceId = this.settings.get('membersYearlyPriceId');
if (portalPlans.includes(currentMontlyPriceId)) {
portalPlans = portalPlans.filter(priceId => priceId !== currentMontlyPriceId);
}
if (data.isMonthlyChecked) {
portalPlans.pushObject(monthlyPriceId);
}
if (portalPlans.includes(currentYearlyPriceId)) {
portalPlans = portalPlans.filter(priceId => priceId !== currentYearlyPriceId);
}
if (data.isYearlyChecked) {
portalPlans.pushObject(yearlyPriceId);
}
portalPlans = portalPlans.filter(priceId => priceId !== 'free');
if (data.isFreeChecked) {
portalPlans.pushObject('free');
}
this.settings.set('portalPlans', portalPlans);
}
async saveProduct() {
const data = this.args.getData();
this.product = data?.product;
if (this.product) {
const stripePrices = this.product.stripePrices || [];
const monthlyAmount = data.monthlyAmount * 100;
const yearlyAmount = data.yearlyAmount * 100;
const currency = data.currency;
const getActivePrice = (prices, type, amount) => {
return prices.find((price) => {
return (
price.active && price.amount === amount && price.type === 'recurring' &&
price.interval === type && price.currency.toLowerCase() === currency.toLowerCase()
);
});
const monthlyPrice = {
nickname: 'Monthly',
amount: monthlyAmount,
active: 1,
currency: currency,
interval: 'month',
type: 'recurring'
};
const monthlyPrice = getActivePrice(stripePrices, 'month', monthlyAmount);
const yearlyPrice = getActivePrice(stripePrices, 'year', yearlyAmount);
if (!monthlyPrice) {
stripePrices.push(
{
nickname: 'Monthly',
amount: monthlyAmount,
active: 1,
currency: currency,
interval: 'month',
type: 'recurring'
}
);
}
if (!yearlyPrice) {
stripePrices.push(
{
nickname: 'Yearly',
amount: yearlyAmount,
active: 1,
currency: currency,
interval: 'year',
type: 'recurring'
}
);
}
if (monthlyPrice && yearlyPrice) {
this.updatePortalPlans(monthlyPrice.id, yearlyPrice.id, data);
this.settings.set('membersMonthlyPriceId', monthlyPrice.id);
this.settings.set('membersYearlyPriceId', yearlyPrice.id);
return this.product;
} else {
this.product.set('stripePrices', stripePrices);
const savedProduct = await this.product.save();
const updatedStripePrices = savedProduct.stripePrices || [];
const updatedMonthlyPrice = getActivePrice(updatedStripePrices, 'month', monthlyAmount);
const updatedYearlyPrice = getActivePrice(updatedStripePrices, 'year', yearlyAmount);
this.updatePortalPlans(updatedMonthlyPrice.id, updatedYearlyPrice.id, data);
this.settings.set('membersMonthlyPriceId', updatedMonthlyPrice.id);
this.settings.set('membersYearlyPriceId', updatedYearlyPrice.id);
return savedProduct;
}
const yearlyPrice = {
nickname: 'Yearly',
amount: yearlyAmount,
active: 1,
currency: currency,
interval: 'year',
type: 'recurring'
};
this.product.set('monthlyPrice', monthlyPrice);
this.product.set('yearlyPrice', yearlyPrice);
const savedProduct = await this.product.save();
return savedProduct;
}
}

View file

@ -46,38 +46,12 @@ export default class GhLaunchWizardSetPricingComponent extends Component {
return envConfig.environment !== 'development' && !/^https:/.test(siteUrl);
}
get disabled() {
return false;
}
get isPaidPriceDisabled() {
return this.disabled || !this.membersUtils.isStripeEnabled;
return !this.membersUtils.isStripeEnabled;
}
get isFreeDisabled() {
return this.disabled || this.settings.get('membersSignupAccess') !== 'all';
}
getPrice(prices, type) {
const monthlyPriceId = this.settings.get('membersMonthlyPriceId');
const yearlyPriceId = this.settings.get('membersYearlyPriceId');
if (type === 'monthly') {
return (
prices.find(price => price.id === monthlyPriceId) ||
prices.find(price => price.nickname === 'Monthly') ||
prices.find(price => price.interval === 'month')
);
}
if (type === 'yearly') {
return (
prices.find(price => price.id === yearlyPriceId) ||
prices.find(price => price.nickname === 'Yearly') ||
prices.find(price => price.interval === 'year')
);
}
return null;
return this.settings.get('membersSignupAccess') !== 'all';
}
@action
@ -182,7 +156,6 @@ export default class GhLaunchWizardSetPricingComponent extends Component {
const storedData = this.args.getData();
if (storedData?.product) {
this.product = storedData.product;
this.stripePrices = this.product.get('stripePrices') || [];
if (storedData.isMonthlyChecked !== undefined) {
this.isMonthlyChecked = storedData.isMonthlyChecked;
@ -199,27 +172,16 @@ export default class GhLaunchWizardSetPricingComponent extends Component {
this.stripeMonthlyAmount = storedData.monthlyAmount;
this.stripeYearlyAmount = storedData.yearlyAmount;
} else {
const products = yield this.store.query('product', {include: 'stripe_prices'});
const products = yield this.store.query('product', {include: 'monthly_price,yearly_price'});
this.product = products.firstObject;
let portalPlans = this.settings.get('portalPlans') || [];
const currentMontlyPriceId = this.settings.get('membersMonthlyPriceId');
const currentYearlyPriceId = this.settings.get('membersYearlyPriceId');
this.isMonthlyChecked = false;
this.isYearlyChecked = false;
this.isFreeChecked = false;
if (portalPlans.includes(currentMontlyPriceId)) {
this.isMonthlyChecked = true;
}
if (portalPlans.includes(currentYearlyPriceId)) {
this.isYearlyChecked = true;
}
if (portalPlans.includes('free')) {
this.isFreeChecked = true;
}
this.stripePrices = this.product.get('stripePrices') || [];
const activePrices = this.stripePrices.filter(price => !!price.active);
const monthlyPrice = this.getPrice(activePrices, 'monthly');
const yearlyPrice = this.getPrice(activePrices, 'yearly');
this.isMonthlyChecked = portalPlans.includes('monthly');
this.isYearlyChecked = portalPlans.includes('yearly');
this.isFreeChecked = portalPlans.includes('free');
const monthlyPrice = this.product.get('monthlyPrice');
const yearlyPrice = this.product.get('yearlyPrice');
if (monthlyPrice && monthlyPrice.amount) {
this.stripeMonthlyAmount = (monthlyPrice.amount / 100);
this.currency = monthlyPrice.currency;