mirror of
https://github.com/bigcapitalhq/bigcapital.git
synced 2026-02-21 07:10:33 +00:00
feat: backend the new monthly susbcription plans
This commit is contained in:
@@ -1,4 +1,3 @@
|
|||||||
import { getPrice } from '@lemonsqueezy/lemonsqueezy.js';
|
|
||||||
import config from '@/config';
|
import config from '@/config';
|
||||||
import { Inject, Service } from 'typedi';
|
import { Inject, Service } from 'typedi';
|
||||||
import {
|
import {
|
||||||
@@ -10,7 +9,6 @@ import {
|
|||||||
} from './utils';
|
} from './utils';
|
||||||
import { Plan } from '@/system/models';
|
import { Plan } from '@/system/models';
|
||||||
import { Subscription } from './Subscription';
|
import { Subscription } from './Subscription';
|
||||||
import { isEmpty } from 'lodash';
|
|
||||||
|
|
||||||
@Service()
|
@Service()
|
||||||
export class LemonSqueezyWebhooks {
|
export class LemonSqueezyWebhooks {
|
||||||
@@ -18,7 +16,7 @@ export class LemonSqueezyWebhooks {
|
|||||||
private subscriptionService: Subscription;
|
private subscriptionService: Subscription;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* handle the LemonSqueezy webhooks.
|
* Handles the Lemon Squeezy webhooks.
|
||||||
* @param {string} rawBody
|
* @param {string} rawBody
|
||||||
* @param {string} signature
|
* @param {string} signature
|
||||||
* @returns {Promise<void>}
|
* @returns {Promise<void>}
|
||||||
@@ -74,7 +72,7 @@ export class LemonSqueezyWebhooks {
|
|||||||
const variantId = attributes.variant_id as string;
|
const variantId = attributes.variant_id as string;
|
||||||
|
|
||||||
// We assume that the Plan table is up to date.
|
// 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) {
|
if (!plan) {
|
||||||
throw new Error(`Plan with variantId ${variantId} not found.`);
|
throw new Error(`Plan with variantId ${variantId} not found.`);
|
||||||
@@ -82,26 +80,9 @@ export class LemonSqueezyWebhooks {
|
|||||||
// Update the subscription in the database.
|
// Update the subscription in the database.
|
||||||
const priceId = attributes.first_subscription_item.price_id;
|
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.
|
// Create a new subscription of the tenant.
|
||||||
if (webhookEvent === 'subscription_created') {
|
if (webhookEvent === 'subscription_created') {
|
||||||
await this.subscriptionService.newSubscribtion(
|
await this.subscriptionService.newSubscribtion(tenantId, plan.slug);
|
||||||
tenantId,
|
|
||||||
'early-adaptor'
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (webhookEvent.startsWith('order_')) {
|
} else if (webhookEvent.startsWith('order_')) {
|
||||||
|
|||||||
@@ -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');
|
||||||
|
});
|
||||||
|
};
|
||||||
@@ -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) {};
|
||||||
@@ -33,8 +33,15 @@ export const SubscriptionPlans = [
|
|||||||
{ text: 'Track GST and VAT' },
|
{ text: 'Track GST and VAT' },
|
||||||
{ text: 'Connect Banks for Automatic Importing' },
|
{ text: 'Connect Banks for Automatic Importing' },
|
||||||
{ text: 'Chart of Accounts' },
|
{ 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' },
|
{ text: 'Unlimited User Seats' },
|
||||||
],
|
],
|
||||||
monthlyPrice: '$10',
|
monthlyPrice: '$10',
|
||||||
@@ -42,7 +49,9 @@ export const SubscriptionPlans = [
|
|||||||
annuallyPrice: '$7.5',
|
annuallyPrice: '$7.5',
|
||||||
annuallyPriceLabel: 'Per month',
|
annuallyPriceLabel: 'Per month',
|
||||||
monthlyVariantId: '446152',
|
monthlyVariantId: '446152',
|
||||||
|
// monthlyVariantId: '450016',
|
||||||
annuallyVariantId: '446153',
|
annuallyVariantId: '446153',
|
||||||
|
// annuallyVariantId: '450018',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'Capital Essential',
|
name: 'Capital Essential',
|
||||||
@@ -51,9 +60,21 @@ export const SubscriptionPlans = [
|
|||||||
features: [
|
features: [
|
||||||
{ text: 'All Capital Basic features' },
|
{ text: 'All Capital Basic features' },
|
||||||
{ text: 'Purchase Invoices' },
|
{ text: 'Purchase Invoices' },
|
||||||
{ text: 'Multi Currency Transactions' },
|
{
|
||||||
{ text: 'Transactions Locking' },
|
text: 'Multi Currency Transactions',
|
||||||
{ text: 'Inventory Tracking' },
|
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: 'Smart Financial Reports' },
|
||||||
{ text: 'Advanced Inventory Reports' },
|
{ text: 'Advanced Inventory Reports' },
|
||||||
],
|
],
|
||||||
@@ -61,8 +82,10 @@ export const SubscriptionPlans = [
|
|||||||
monthlyPriceLabel: 'Per month',
|
monthlyPriceLabel: 'Per month',
|
||||||
annuallyPrice: '$15',
|
annuallyPrice: '$15',
|
||||||
annuallyPriceLabel: 'Per month',
|
annuallyPriceLabel: 'Per month',
|
||||||
monthlyVariantId: '446165',
|
// monthlyVariantId: '450028',
|
||||||
annuallyVariantId: '446164',
|
monthlyVariantId: '446155',
|
||||||
|
// annuallyVariantId: '450029',
|
||||||
|
annuallyVariantId: '446156',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'Capital Plus',
|
name: 'Capital Plus',
|
||||||
@@ -72,15 +95,20 @@ export const SubscriptionPlans = [
|
|||||||
{ text: 'All Capital Essential features' },
|
{ text: 'All Capital Essential features' },
|
||||||
{ text: 'Custom User Roles Access' },
|
{ text: 'Custom User Roles Access' },
|
||||||
{ text: 'Vendor Credits' },
|
{ 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',
|
monthlyPrice: '$25',
|
||||||
monthlyPriceLabel: 'Per month',
|
monthlyPriceLabel: 'Per month',
|
||||||
annuallyPrice: '$18',
|
annuallyPrice: '$19',
|
||||||
annuallyPriceLabel: 'Per month',
|
annuallyPriceLabel: 'Per month',
|
||||||
featured: true,
|
featured: true,
|
||||||
|
// monthlyVariantId: '450031',
|
||||||
monthlyVariantId: '446165',
|
monthlyVariantId: '446165',
|
||||||
|
// annuallyVariantId: '450032',
|
||||||
annuallyVariantId: '446164',
|
annuallyVariantId: '446164',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -89,14 +117,24 @@ export const SubscriptionPlans = [
|
|||||||
description: 'Good for businesses have multiple branches.',
|
description: 'Good for businesses have multiple branches.',
|
||||||
features: [
|
features: [
|
||||||
{ text: 'All Capital Plus 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',
|
monthlyPrice: '$40',
|
||||||
monthlyPriceLabel: 'Per month',
|
monthlyPriceLabel: 'Per month',
|
||||||
annuallyPrice: '$30',
|
annuallyPrice: '$30',
|
||||||
annuallyPriceLabel: 'Per month',
|
annuallyPriceLabel: 'Per month',
|
||||||
|
// monthlyVariantId: '450024',
|
||||||
monthlyVariantId: '446167',
|
monthlyVariantId: '446167',
|
||||||
|
// annuallyVariantId: '450025',
|
||||||
annuallyVariantId: '446168',
|
annuallyVariantId: '446168',
|
||||||
},
|
},
|
||||||
] as SubscriptionPlan[];
|
] as SubscriptionPlan[];
|
||||||
|
|||||||
Reference in New Issue
Block a user