feat: backend the new monthly susbcription plans

This commit is contained in:
Ahmed Bouhuolia
2024-07-14 14:19:04 +02:00
parent 72128a72c4
commit 67d155759e
4 changed files with 160 additions and 34 deletions

View File

@@ -1,4 +1,3 @@
import { getPrice } from '@lemonsqueezy/lemonsqueezy.js';
import config from '@/config';
import { Inject, Service } from 'typedi';
import {
@@ -10,7 +9,6 @@ import {
} from './utils';
import { Plan } from '@/system/models';
import { Subscription } from './Subscription';
import { isEmpty } from 'lodash';
@Service()
export class LemonSqueezyWebhooks {
@@ -18,7 +16,7 @@ export class LemonSqueezyWebhooks {
private subscriptionService: Subscription;
/**
* handle the LemonSqueezy webhooks.
* Handles the Lemon Squeezy webhooks.
* @param {string} rawBody
* @param {string} signature
* @returns {Promise<void>}
@@ -74,7 +72,7 @@ export class LemonSqueezyWebhooks {
const variantId = attributes.variant_id as string;
// We assume that the Plan table is up to date.
const plan = await Plan.query().findOne('slug', 'early-adaptor');
const plan = await Plan.query().findOne('lemonVariantId', variantId);
if (!plan) {
throw new Error(`Plan with variantId ${variantId} not found.`);
@@ -82,26 +80,9 @@ export class LemonSqueezyWebhooks {
// Update the subscription in the database.
const priceId = attributes.first_subscription_item.price_id;
// Get the price data from Lemon Squeezy.
const priceData = await getPrice(priceId);
if (priceData.error) {
throw new Error(
`Failed to get the price data for the subscription ${eventBody.data.id}.`
);
}
const isUsageBased =
attributes.first_subscription_item.is_usage_based;
const price = isUsageBased
? priceData.data?.data.attributes.unit_price_decimal
: priceData.data?.data.attributes.unit_price;
// Create a new subscription of the tenant.
if (webhookEvent === 'subscription_created') {
await this.subscriptionService.newSubscribtion(
tenantId,
'early-adaptor'
);
await this.subscriptionService.newSubscribtion(tenantId, plan.slug);
}
}
} else if (webhookEvent.startsWith('order_')) {

View File

@@ -0,0 +1,11 @@
exports.up = function (knex) {
return knex.schema.table('subscription_plans', (table) => {
table.string('lemon_variant_id').nullable().index();
});
};
exports.down = (knex) => {
return knex.schema.table('subscription_plans', (table) => {
table.dropColumn('lemon_variant_id');
});
};

View File

@@ -0,0 +1,96 @@
exports.up = function (knex) {
return knex('subscription_plans').insert([
// Capital Basic
{
name: 'Capital Basic (Monthly)',
slug: 'capital-basic-monthly',
price: 10,
active: true,
currency: 'USD',
invoice_period: 1,
invoice_interval: 'month',
lemon_variant_id: '446152',
// lemon_variant_id: '450016',
},
{
name: 'Capital Basic (Annually)',
slug: 'capital-basic-annually',
price: 90,
active: true,
currency: 'USD',
invoice_period: 1,
invoice_interval: 'year',
lemon_variant_id: '446153',
// lemon_variant_id: '450018',
},
// # Capital Essential
{
name: 'Capital Essential (Monthly)',
slug: 'capital-essential-monthly',
price: 20,
active: true,
currency: 'USD',
invoice_period: 1,
invoice_interval: 'month',
lemon_variant_id: '446155',
// lemon_variant_id: '450028',
},
{
name: 'Capital Essential (Annually)',
slug: 'capital-essential-annually',
price: 180,
active: true,
invoice_period: 1,
invoice_interval: 'year',
lemon_variant_id: '446156',
// lemon_variant_id: '450029',
},
// # Capital Plus
{
name: 'Capital Plus (Monthly)',
slug: 'capital-plus-monthly',
price: 25,
active: true,
invoice_period: 1,
invoice_interval: 'month',
lemon_variant_id: '446165',
// lemon_variant_id: '450031',
},
{
name: 'Capital Plus (Annually)',
slug: 'capital-plus-annually',
price: 228,
active: true,
invoice_period: 1,
invoice_interval: 'year',
lemon_variant_id: '446164',
// lemon_variant_id: '450032',
},
// # Capital Big
{
name: 'Capital Big (Monthly)',
slug: 'capital-big-monthly',
price: 40,
active: true,
invoice_period: 1,
invoice_interval: 'month',
lemon_variant_id: '446167',
// lemon_variant_id: '450024',
},
{
name: 'Capital Big (Annually)',
slug: 'capital-big-annually',
price: 360,
active: true,
invoice_period: 1,
invoice_interval: 'year',
lemon_variant_id: '446168',
// lemon_variant_id: '450025',
},
]);
};
exports.down = function (knex) {};

View File

@@ -33,8 +33,15 @@ export const SubscriptionPlans = [
{ text: 'Track GST and VAT' },
{ text: 'Connect Banks for Automatic Importing' },
{ text: 'Chart of Accounts' },
{ text: 'Manual Journals' },
{ text: 'Basic Financial Reports & Insights' },
{
text: 'Manual Journals',
hintLabel: 'Manual Journals',
hint: 'Write manual journals entries for financial transactions not automatically captured by the system to adjust financial statements.',
},
{
text: 'Basic Financial Reports & Insights',
hint: 'Balance sheet, profit & loss statement, cashflow statement, general ledger, journal sheet, A/P aging summary, A/R aging summary',
},
{ text: 'Unlimited User Seats' },
],
monthlyPrice: '$10',
@@ -42,7 +49,9 @@ export const SubscriptionPlans = [
annuallyPrice: '$7.5',
annuallyPriceLabel: 'Per month',
monthlyVariantId: '446152',
// monthlyVariantId: '450016',
annuallyVariantId: '446153',
// annuallyVariantId: '450018',
},
{
name: 'Capital Essential',
@@ -51,9 +60,21 @@ export const SubscriptionPlans = [
features: [
{ text: 'All Capital Basic features' },
{ text: 'Purchase Invoices' },
{ text: 'Multi Currency Transactions' },
{ text: 'Transactions Locking' },
{ text: 'Inventory Tracking' },
{
text: 'Multi Currency Transactions',
hintLabel: 'Multi Currency',
hint: 'Pay and get paid and do manual journals in any currency with real time exchange rates conversions.',
},
{
text: 'Transactions Locking',
hintLabel: 'Transactions Locking',
hint: 'Transaction Locking freezes transactions to prevent any additions, modifications, or deletions of transactions recorded during the specified date.',
},
{
text: 'Inventory Tracking',
hintLabel: 'Inventory Tracking',
hint: 'Track goods in the stock, cost of goods, and get notifications when quantity is low.',
},
{ text: 'Smart Financial Reports' },
{ text: 'Advanced Inventory Reports' },
],
@@ -61,8 +82,10 @@ export const SubscriptionPlans = [
monthlyPriceLabel: 'Per month',
annuallyPrice: '$15',
annuallyPriceLabel: 'Per month',
monthlyVariantId: '446165',
annuallyVariantId: '446164',
// monthlyVariantId: '450028',
monthlyVariantId: '446155',
// annuallyVariantId: '450029',
annuallyVariantId: '446156',
},
{
name: 'Capital Plus',
@@ -72,15 +95,20 @@ export const SubscriptionPlans = [
{ text: 'All Capital Essential features' },
{ text: 'Custom User Roles Access' },
{ text: 'Vendor Credits' },
{ text: 'Budgeting' },
{ text: 'Analysis Tracking Tags' },
{
text: 'Budgeting',
hint: 'Create multiple budgets and compare targets with actuals to understand how your business is performing.',
},
{ text: 'Analysis Cost Center' },
],
monthlyPrice: '$25',
monthlyPriceLabel: 'Per month',
annuallyPrice: '$18',
annuallyPrice: '$19',
annuallyPriceLabel: 'Per month',
featured: true,
// monthlyVariantId: '450031',
monthlyVariantId: '446165',
// annuallyVariantId: '450032',
annuallyVariantId: '446164',
},
{
@@ -89,14 +117,24 @@ export const SubscriptionPlans = [
description: 'Good for businesses have multiple branches.',
features: [
{ text: 'All Capital Plus features' },
{ text: 'Multiple Branches' },
{ text: 'Multiple Warehouses' },
{
text: 'Multiple Branches',
hintLabel: '',
hint: 'Track the organization transactions and accounts in multiple branches.',
},
{
text: 'Multiple Warehouses',
hintLabel: 'Multiple Warehouses',
hint: 'Track the organization inventory in multiple warehouses and transfer goods between them.',
},
],
monthlyPrice: '$40',
monthlyPriceLabel: 'Per month',
annuallyPrice: '$30',
annuallyPriceLabel: 'Per month',
// monthlyVariantId: '450024',
monthlyVariantId: '446167',
// annuallyVariantId: '450025',
annuallyVariantId: '446168',
},
] as SubscriptionPlan[];