0

[Feat] Coupon system

WIP. Idea for solving #57
This commit is contained in:
rafaelsideguide 2024-04-25 10:05:53 -03:00
parent abf6918642
commit 9c481e5e83

View File

@ -41,14 +41,30 @@ export async function supaBillTeam(team_id: string, credits: number) {
return { success: true, credit_usage }; return { success: true, credit_usage };
} }
// 2. add the credits to the credits_usage // 2. Check for available coupons
const { data: coupons } = await supabase_service
.from("coupons")
.select("credits")
.eq("team_id", team_id)
.eq("status", "active");
let couponValue = 0;
if (coupons && coupons.length > 0) {
couponValue = coupons[0].credits; // Assuming only one active coupon can be used at a time
console.log(`Applying coupon of ${couponValue} credits`);
}
// Calculate final credits used after applying coupon
const finalCreditsUsed = Math.max(0, credits - couponValue);
// 3. Log the credit usage
const { data: credit_usage } = await supabase_service const { data: credit_usage } = await supabase_service
.from("credit_usage") .from("credit_usage")
.insert([ .insert([
{ {
team_id, team_id,
subscription_id: subscription.id, subscription_id: subscription ? subscription.id : null,
credits_used: credits, credits_used: finalCreditsUsed,
created_at: new Date(), created_at: new Date(),
}, },
]) ])
@ -65,61 +81,32 @@ export async function supaCheckTeamCredits(team_id: string, credits: number) {
if (team_id === "preview") { if (team_id === "preview") {
return { success: true, message: "Preview team, no credits used" }; return { success: true, message: "Preview team, no credits used" };
} }
// 1. Retrieve the team's active subscription based on the team_id.
const { data: subscription, error: subscriptionError } =
await supabase_service
.from("subscriptions")
.select("id, price_id, current_period_start, current_period_end")
.eq("team_id", team_id)
.eq("status", "active")
.single();
if (subscriptionError || !subscription) { // Retrieve the team's active subscription
const { data: creditUsages, error: creditUsageError } = const { data: subscription, error: subscriptionError } = await supabase_service
await supabase_service .from("subscriptions")
.from("credit_usage") .select("id, price_id, current_period_start, current_period_end")
.select("credits_used") .eq("team_id", team_id)
.is("subscription_id", null) .eq("status", "active")
.eq("team_id", team_id);
// .gte("created_at", subscription.current_period_start)
// .lte("created_at", subscription.current_period_end);
if (creditUsageError) {
throw new Error(
`Failed to retrieve credit usage for subscription_id: ${subscription.id}`
);
}
const totalCreditsUsed = creditUsages.reduce(
(acc, usage) => acc + usage.credits_used,
0
);
console.log("totalCreditsUsed", totalCreditsUsed);
// 5. Compare the total credits used with the credits allowed by the plan.
if (totalCreditsUsed + credits > FREE_CREDITS) {
return {
success: false,
message: "Insufficient credits, please upgrade!",
};
}
return { success: true, message: "Sufficient credits available" };
}
// 2. Get the price_id from the subscription.
const { data: price, error: priceError } = await supabase_service
.from("prices")
.select("credits")
.eq("id", subscription.price_id)
.single(); .single();
if (priceError) { if (subscriptionError || !subscription) {
throw new Error( return { success: false, message: "No active subscription found" };
`Failed to retrieve price for price_id: ${subscription.price_id}`
);
} }
// 4. Calculate the total credits used by the team within the current billing period. // Check for available coupons
const { data: coupons } = await supabase_service
.from("coupons")
.select("credits")
.eq("team_id", team_id)
.eq("status", "active");
let couponValue = 0;
if (coupons && coupons.length > 0) {
couponValue = coupons[0].credits;
}
// Calculate the total credits used by the team within the current billing period
const { data: creditUsages, error: creditUsageError } = await supabase_service const { data: creditUsages, error: creditUsageError } = await supabase_service
.from("credit_usage") .from("credit_usage")
.select("credits_used") .select("credits_used")
@ -128,18 +115,27 @@ export async function supaCheckTeamCredits(team_id: string, credits: number) {
.lte("created_at", subscription.current_period_end); .lte("created_at", subscription.current_period_end);
if (creditUsageError) { if (creditUsageError) {
throw new Error( throw new Error(`Failed to retrieve credit usage for subscription_id: ${subscription.id}`);
`Failed to retrieve credit usage for subscription_id: ${subscription.id}`
);
} }
const totalCreditsUsed = creditUsages.reduce( const totalCreditsUsed = creditUsages.reduce((acc, usage) => acc + usage.credits_used, 0);
(acc, usage) => acc + usage.credits_used,
0
);
// 5. Compare the total credits used with the credits allowed by the plan. // Adjust total credits used by subtracting coupon value
if (totalCreditsUsed + credits > price.credits) { const adjustedCreditsUsed = Math.max(0, totalCreditsUsed - couponValue);
// Get the price details
const { data: price, error: priceError } = await supabase_service
.from("prices")
.select("credits")
.eq("id", subscription.price_id)
.single();
if (priceError) {
throw new Error(`Failed to retrieve price for price_id: ${subscription.price_id}`);
}
// Compare the adjusted total credits used with the credits allowed by the plan
if (adjustedCreditsUsed + credits > price.credits) {
return { success: false, message: "Insufficient credits, please upgrade!" }; return { success: false, message: "Insufficient credits, please upgrade!" };
} }
@ -159,7 +155,17 @@ export async function countCreditsAndRemainingForCurrentBillingPeriod(
.single(); .single();
if (subscriptionError || !subscription) { if (subscriptionError || !subscription) {
// throw new Error(`Failed to retrieve subscription for team_id: ${team_id}`); // Check for available coupons even if there's no subscription
const { data: coupons } = await supabase_service
.from("coupons")
.select("value")
.eq("team_id", team_id)
.eq("status", "active");
let couponValue = 0;
if (coupons && coupons.length > 0) {
couponValue = coupons[0].value;
}
// Free // Free
const { data: creditUsages, error: creditUsageError } = const { data: creditUsages, error: creditUsageError } =
@ -168,13 +174,9 @@ export async function countCreditsAndRemainingForCurrentBillingPeriod(
.select("credits_used") .select("credits_used")
.is("subscription_id", null) .is("subscription_id", null)
.eq("team_id", team_id); .eq("team_id", team_id);
// .gte("created_at", subscription.current_period_start)
// .lte("created_at", subscription.current_period_end);
if (creditUsageError || !creditUsages) { if (creditUsageError || !creditUsages) {
throw new Error( throw new Error(`Failed to retrieve credit usage for team_id: ${team_id}`);
`Failed to retrieve credit usage for subscription_id: ${subscription.id}`
);
} }
const totalCreditsUsed = creditUsages.reduce( const totalCreditsUsed = creditUsages.reduce(
@ -182,46 +184,62 @@ export async function countCreditsAndRemainingForCurrentBillingPeriod(
0 0
); );
// Adjust total credits used by subtracting coupon value
const adjustedCreditsUsed = Math.max(0, totalCreditsUsed - couponValue);
// 4. Calculate remaining credits. // 4. Calculate remaining credits.
const remainingCredits = FREE_CREDITS - totalCreditsUsed; const remainingCredits = FREE_CREDITS - adjustedCreditsUsed;
return { totalCreditsUsed, remainingCredits, totalCredits: FREE_CREDITS }; return { totalCreditsUsed: adjustedCreditsUsed, remainingCredits, totalCredits: FREE_CREDITS };
} }
// 2. Get the price_id from the subscription to retrieve the total credits available. // If there is an active subscription
const { data: price, error: priceError } = await supabase_service const { data: coupons } = await supabase_service
.from("prices") .from("coupons")
.select("credits") .select("credits")
.eq("id", subscription.price_id) .eq("team_id", team_id)
.single(); .eq("status", "active");
if (priceError || !price) { let couponValue = 0;
throw new Error( if (coupons && coupons.length > 0) {
`Failed to retrieve price for price_id: ${subscription.price_id}` couponValue = coupons[0].credits;
);
} }
// 3. Calculate the total credits used by the team within the current billing period.
const { data: creditUsages, error: creditUsageError } = await supabase_service const { data: creditUsages, error: creditUsageError } = await supabase_service
.from("credit_usage") .from("credit_usage")
.select("credits_used") .select("credits_used")
.eq("subscription_id", subscription.id) .eq("subscription_id", subscription.id)
.gte("created_at", subscription.current_period_start) .gte("created_at", subscription.current_period_start)
.lte("created_at", subscription.current_period_end); .lte("created_at", subscription.current_period_end);
if (creditUsageError || !creditUsages) { if (creditUsageError || !creditUsages) {
throw new Error( throw new Error(`Failed to retrieve credit usage for subscription_id: ${subscription.id}`);
`Failed to retrieve credit usage for subscription_id: ${subscription.id}`
);
} }
const totalCreditsUsed = creditUsages.reduce( const totalCreditsUsed = creditUsages.reduce(
(acc, usage) => acc + usage.credits_used, (acc, usage) => acc + usage.credits_used,
0 0
); );
// 4. Calculate remaining credits. // Adjust total credits used by subtracting coupon value
const remainingCredits = price.credits - totalCreditsUsed; const adjustedCreditsUsed = Math.max(0, totalCreditsUsed - couponValue);
return { totalCreditsUsed, remainingCredits, totalCredits: price.credits }; const { data: price, error: priceError } = await supabase_service
} .from("prices")
.select("credits")
.eq("id", subscription.price_id)
.single();
if (priceError || !price) {
throw new Error(`Failed to retrieve price for price_id: ${subscription.price_id}`);
}
// Calculate remaining credits.
const remainingCredits = price.credits - adjustedCreditsUsed;
return {
totalCreditsUsed: adjustedCreditsUsed,
remainingCredits,
totalCredits: price.credits
};
}