Update credit_billing.ts
This commit is contained in:
parent
5991000d2b
commit
ec10eb09f3
@ -36,7 +36,10 @@ export async function supaBillTeam(team_id: string, credits: number) {
|
|||||||
|
|
||||||
let couponCredits = 0;
|
let couponCredits = 0;
|
||||||
if (coupons && coupons.length > 0) {
|
if (coupons && coupons.length > 0) {
|
||||||
couponCredits = coupons.reduce((total, coupon) => total + coupon.credits, 0);
|
couponCredits = coupons.reduce(
|
||||||
|
(total, coupon) => total + coupon.credits,
|
||||||
|
0
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
let sortedCoupons = coupons.sort((a, b) => b.credits - a.credits);
|
let sortedCoupons = coupons.sort((a, b) => b.credits - a.credits);
|
||||||
@ -55,28 +58,27 @@ export async function supaBillTeam(team_id: string, credits: number) {
|
|||||||
usedCredits = usedCredits - sortedCoupons[0].credits;
|
usedCredits = usedCredits - sortedCoupons[0].credits;
|
||||||
// update coupon credits
|
// update coupon credits
|
||||||
await supabase_service
|
await supabase_service
|
||||||
.from("coupons")
|
.from("coupons")
|
||||||
.update({
|
.update({
|
||||||
credits: 0
|
credits: 0,
|
||||||
})
|
})
|
||||||
.eq("id", sortedCoupons[0].id);
|
.eq("id", sortedCoupons[0].id);
|
||||||
sortedCoupons.shift();
|
sortedCoupons.shift();
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
// update coupon credits
|
// update coupon credits
|
||||||
await supabase_service
|
await supabase_service
|
||||||
.from("coupons")
|
.from("coupons")
|
||||||
.update({
|
.update({
|
||||||
credits: sortedCoupons[0].credits - usedCredits
|
credits: sortedCoupons[0].credits - usedCredits,
|
||||||
})
|
})
|
||||||
.eq("id", sortedCoupons[0].id);
|
.eq("id", sortedCoupons[0].id);
|
||||||
usedCredits = 0;
|
usedCredits = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return await createCreditUsage({ team_id, credits: 0 });
|
return await createCreditUsage({ team_id, credits: 0 });
|
||||||
|
|
||||||
// not enough coupon credits and no subscription
|
// not enough coupon credits and no subscription
|
||||||
} else {
|
} else {
|
||||||
// update coupon credits
|
// update coupon credits
|
||||||
const usedCredits = credits - couponCredits;
|
const usedCredits = credits - couponCredits;
|
||||||
@ -84,7 +86,7 @@ export async function supaBillTeam(team_id: string, credits: number) {
|
|||||||
await supabase_service
|
await supabase_service
|
||||||
.from("coupons")
|
.from("coupons")
|
||||||
.update({
|
.update({
|
||||||
credits: 0
|
credits: 0,
|
||||||
})
|
})
|
||||||
.eq("id", sortedCoupons[i].id);
|
.eq("id", sortedCoupons[i].id);
|
||||||
}
|
}
|
||||||
@ -101,14 +103,18 @@ export async function supaBillTeam(team_id: string, credits: number) {
|
|||||||
await supabase_service
|
await supabase_service
|
||||||
.from("coupons")
|
.from("coupons")
|
||||||
.update({
|
.update({
|
||||||
credits: 0
|
credits: 0,
|
||||||
})
|
})
|
||||||
.eq("id", sortedCoupons[i].id);
|
.eq("id", sortedCoupons[i].id);
|
||||||
}
|
}
|
||||||
const usedCredits = credits - couponCredits;
|
const usedCredits = credits - couponCredits;
|
||||||
return await createCreditUsage({ team_id, subscription_id: subscription.id, credits: usedCredits });
|
return await createCreditUsage({
|
||||||
|
team_id,
|
||||||
} else { // using only coupon credits
|
subscription_id: subscription.id,
|
||||||
|
credits: usedCredits,
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
// using only coupon credits
|
||||||
let usedCredits = credits;
|
let usedCredits = credits;
|
||||||
while (usedCredits > 0) {
|
while (usedCredits > 0) {
|
||||||
// update coupons
|
// update coupons
|
||||||
@ -116,26 +122,29 @@ export async function supaBillTeam(team_id: string, credits: number) {
|
|||||||
usedCredits = usedCredits - sortedCoupons[0].credits;
|
usedCredits = usedCredits - sortedCoupons[0].credits;
|
||||||
// update coupon credits
|
// update coupon credits
|
||||||
await supabase_service
|
await supabase_service
|
||||||
.from("coupons")
|
.from("coupons")
|
||||||
.update({
|
.update({
|
||||||
credits: 0
|
credits: 0,
|
||||||
})
|
})
|
||||||
.eq("id", sortedCoupons[0].id);
|
.eq("id", sortedCoupons[0].id);
|
||||||
sortedCoupons.shift();
|
sortedCoupons.shift();
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
// update coupon credits
|
// update coupon credits
|
||||||
await supabase_service
|
await supabase_service
|
||||||
.from("coupons")
|
.from("coupons")
|
||||||
.update({
|
.update({
|
||||||
credits: sortedCoupons[0].credits - usedCredits
|
credits: sortedCoupons[0].credits - usedCredits,
|
||||||
})
|
})
|
||||||
.eq("id", sortedCoupons[0].id);
|
.eq("id", sortedCoupons[0].id);
|
||||||
usedCredits = 0;
|
usedCredits = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return await createCreditUsage({ team_id, subscription_id: subscription.id, credits: 0 });
|
return await createCreditUsage({
|
||||||
|
team_id,
|
||||||
|
subscription_id: subscription.id,
|
||||||
|
credits: 0,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -144,7 +153,11 @@ export async function supaBillTeam(team_id: string, credits: number) {
|
|||||||
return await createCreditUsage({ team_id, credits });
|
return await createCreditUsage({ team_id, credits });
|
||||||
}
|
}
|
||||||
|
|
||||||
return await createCreditUsage({ team_id, subscription_id: subscription.id, credits });
|
return await createCreditUsage({
|
||||||
|
team_id,
|
||||||
|
subscription_id: subscription.id,
|
||||||
|
credits,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function checkTeamCredits(team_id: string, credits: number) {
|
export async function checkTeamCredits(team_id: string, credits: number) {
|
||||||
@ -157,12 +170,13 @@ export async function supaCheckTeamCredits(team_id: string, credits: number) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Retrieve the team's active subscription
|
// Retrieve the team's active subscription
|
||||||
const { data: subscription, error: subscriptionError } = await supabase_service
|
const { data: subscription, error: subscriptionError } =
|
||||||
.from("subscriptions")
|
await supabase_service
|
||||||
.select("id, price_id, current_period_start, current_period_end")
|
.from("subscriptions")
|
||||||
.eq("team_id", team_id)
|
.select("id, price_id, current_period_start, current_period_end")
|
||||||
.eq("status", "active")
|
.eq("team_id", team_id)
|
||||||
.single();
|
.eq("status", "active")
|
||||||
|
.single();
|
||||||
|
|
||||||
// Check for available coupons
|
// Check for available coupons
|
||||||
const { data: coupons } = await supabase_service
|
const { data: coupons } = await supabase_service
|
||||||
@ -173,7 +187,10 @@ export async function supaCheckTeamCredits(team_id: string, credits: number) {
|
|||||||
|
|
||||||
let couponCredits = 0;
|
let couponCredits = 0;
|
||||||
if (coupons && coupons.length > 0) {
|
if (coupons && coupons.length > 0) {
|
||||||
couponCredits = coupons.reduce((total, coupon) => total + coupon.credits, 0);
|
couponCredits = coupons.reduce(
|
||||||
|
(total, coupon) => total + coupon.credits,
|
||||||
|
0
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Free credits, no coupons
|
// Free credits, no coupons
|
||||||
@ -204,23 +221,30 @@ export async function supaCheckTeamCredits(team_id: string, credits: number) {
|
|||||||
console.log("totalCreditsUsed", totalCreditsUsed);
|
console.log("totalCreditsUsed", totalCreditsUsed);
|
||||||
|
|
||||||
const end = new Date();
|
const end = new Date();
|
||||||
end.setDate(end.getDate() + 30);
|
end.setDate(end.getDate() + 30);
|
||||||
// check if usage is within 80% of the limit
|
// check if usage is within 80% of the limit
|
||||||
const creditLimit = FREE_CREDITS;
|
const creditLimit = FREE_CREDITS;
|
||||||
const creditUsagePercentage = (totalCreditsUsed + credits) / creditLimit;
|
const creditUsagePercentage = (totalCreditsUsed + credits) / creditLimit;
|
||||||
|
|
||||||
|
|
||||||
if (creditUsagePercentage >= 0.8) {
|
if (creditUsagePercentage >= 0.8) {
|
||||||
await sendNotification(team_id, NotificationType.APPROACHING_LIMIT, new Date().toISOString(), end.toISOString());
|
await sendNotification(
|
||||||
|
team_id,
|
||||||
|
NotificationType.APPROACHING_LIMIT,
|
||||||
|
new Date().toISOString(),
|
||||||
|
end.toISOString()
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// 5. Compare the total credits used with the credits allowed by the plan.
|
// 5. Compare the total credits used with the credits allowed by the plan.
|
||||||
if (totalCreditsUsed + credits > FREE_CREDITS) {
|
if (totalCreditsUsed + credits > FREE_CREDITS) {
|
||||||
// Send email notification for insufficient credits
|
// Send email notification for insufficient credits
|
||||||
|
|
||||||
await sendNotification(team_id, NotificationType.LIMIT_REACHED, new Date().toISOString(), end.toISOString());
|
await sendNotification(
|
||||||
|
team_id,
|
||||||
|
NotificationType.LIMIT_REACHED,
|
||||||
|
new Date().toISOString(),
|
||||||
|
end.toISOString()
|
||||||
|
);
|
||||||
return {
|
return {
|
||||||
success: false,
|
success: false,
|
||||||
message: "Insufficient credits, please upgrade!",
|
message: "Insufficient credits, please upgrade!",
|
||||||
@ -231,19 +255,19 @@ export async function supaCheckTeamCredits(team_id: string, credits: number) {
|
|||||||
|
|
||||||
let totalCreditsUsed = 0;
|
let totalCreditsUsed = 0;
|
||||||
try {
|
try {
|
||||||
const { data: creditUsages, error: creditUsageError } = await supabase_service
|
const { data: creditUsages, error: creditUsageError } =
|
||||||
.rpc("get_credit_usage_2", {
|
await supabase_service.rpc("get_credit_usage_2", {
|
||||||
sub_id: subscription.id,
|
sub_id: subscription.id,
|
||||||
start_time: subscription.current_period_start,
|
start_time: subscription.current_period_start,
|
||||||
end_time: subscription.current_period_end
|
end_time: subscription.current_period_end,
|
||||||
});
|
});
|
||||||
|
|
||||||
if (creditUsageError) {
|
if (creditUsageError) {
|
||||||
console.error("Error calculating credit usage:", creditUsageError);
|
console.error("Error calculating credit usage:", creditUsageError);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (creditUsages && creditUsages.length > 0) {
|
if (creditUsages && creditUsages.length > 0) {
|
||||||
totalCreditsUsed = creditUsages[0].total_credits_used;
|
totalCreditsUsed = creditUsages[0].total_credits_used;
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("Error calculating credit usage:", error);
|
console.error("Error calculating credit usage:", error);
|
||||||
@ -260,7 +284,9 @@ export async function supaCheckTeamCredits(team_id: string, credits: number) {
|
|||||||
.single();
|
.single();
|
||||||
|
|
||||||
if (priceError) {
|
if (priceError) {
|
||||||
throw new Error(`Failed to retrieve price for price_id: ${subscription.price_id}`);
|
throw new Error(
|
||||||
|
`Failed to retrieve price for price_id: ${subscription.price_id}`
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
const creditLimit = price.credits;
|
const creditLimit = price.credits;
|
||||||
@ -268,11 +294,21 @@ export async function supaCheckTeamCredits(team_id: string, credits: number) {
|
|||||||
|
|
||||||
// Compare the adjusted total credits used with the credits allowed by the plan
|
// Compare the adjusted total credits used with the credits allowed by the plan
|
||||||
if (adjustedCreditsUsed + credits > price.credits) {
|
if (adjustedCreditsUsed + credits > price.credits) {
|
||||||
await sendNotification(team_id, NotificationType.LIMIT_REACHED, subscription.current_period_start, subscription.current_period_end);
|
await sendNotification(
|
||||||
|
team_id,
|
||||||
|
NotificationType.LIMIT_REACHED,
|
||||||
|
subscription.current_period_start,
|
||||||
|
subscription.current_period_end
|
||||||
|
);
|
||||||
return { success: false, message: "Insufficient credits, please upgrade!" };
|
return { success: false, message: "Insufficient credits, please upgrade!" };
|
||||||
} else if (creditUsagePercentage >= 0.8) {
|
} else if (creditUsagePercentage >= 0.8) {
|
||||||
// Send email notification for approaching credit limit
|
// Send email notification for approaching credit limit
|
||||||
await sendNotification(team_id, NotificationType.APPROACHING_LIMIT, subscription.current_period_start, subscription.current_period_end);
|
await sendNotification(
|
||||||
|
team_id,
|
||||||
|
NotificationType.APPROACHING_LIMIT,
|
||||||
|
subscription.current_period_start,
|
||||||
|
subscription.current_period_end
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return { success: true, message: "Sufficient credits available" };
|
return { success: true, message: "Sufficient credits available" };
|
||||||
@ -298,7 +334,10 @@ export async function countCreditsAndRemainingForCurrentBillingPeriod(
|
|||||||
|
|
||||||
let couponCredits = 0;
|
let couponCredits = 0;
|
||||||
if (coupons && coupons.length > 0) {
|
if (coupons && coupons.length > 0) {
|
||||||
couponCredits = coupons.reduce((total, coupon) => total + coupon.credits, 0);
|
couponCredits = coupons.reduce(
|
||||||
|
(total, coupon) => total + coupon.credits,
|
||||||
|
0
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (subscriptionError || !subscription) {
|
if (subscriptionError || !subscription) {
|
||||||
@ -311,7 +350,9 @@ export async function countCreditsAndRemainingForCurrentBillingPeriod(
|
|||||||
.eq("team_id", team_id);
|
.eq("team_id", team_id);
|
||||||
|
|
||||||
if (creditUsageError || !creditUsages) {
|
if (creditUsageError || !creditUsages) {
|
||||||
throw new Error(`Failed to retrieve credit usage for team_id: ${team_id}`);
|
throw new Error(
|
||||||
|
`Failed to retrieve credit usage for team_id: ${team_id}`
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
const totalCreditsUsed = creditUsages.reduce(
|
const totalCreditsUsed = creditUsages.reduce(
|
||||||
@ -320,7 +361,11 @@ export async function countCreditsAndRemainingForCurrentBillingPeriod(
|
|||||||
);
|
);
|
||||||
|
|
||||||
const remainingCredits = FREE_CREDITS + couponCredits - totalCreditsUsed;
|
const remainingCredits = FREE_CREDITS + couponCredits - totalCreditsUsed;
|
||||||
return { totalCreditsUsed: totalCreditsUsed, remainingCredits, totalCredits: FREE_CREDITS + couponCredits };
|
return {
|
||||||
|
totalCreditsUsed: totalCreditsUsed,
|
||||||
|
remainingCredits,
|
||||||
|
totalCredits: FREE_CREDITS + couponCredits,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
const { data: creditUsages, error: creditUsageError } = await supabase_service
|
const { data: creditUsages, error: creditUsageError } = await supabase_service
|
||||||
@ -331,10 +376,15 @@ export async function countCreditsAndRemainingForCurrentBillingPeriod(
|
|||||||
.lte("created_at", subscription.current_period_end);
|
.lte("created_at", subscription.current_period_end);
|
||||||
|
|
||||||
if (creditUsageError || !creditUsages) {
|
if (creditUsageError || !creditUsages) {
|
||||||
throw new Error(`Failed to retrieve credit usage for subscription_id: ${subscription.id}`);
|
throw new Error(
|
||||||
|
`Failed to retrieve credit usage for subscription_id: ${subscription.id}`
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
const totalCreditsUsed = creditUsages.reduce((acc, usage) => acc + usage.credits_used, 0);
|
const totalCreditsUsed = creditUsages.reduce(
|
||||||
|
(acc, usage) => acc + usage.credits_used,
|
||||||
|
0
|
||||||
|
);
|
||||||
|
|
||||||
const { data: price, error: priceError } = await supabase_service
|
const { data: price, error: priceError } = await supabase_service
|
||||||
.from("prices")
|
.from("prices")
|
||||||
@ -343,7 +393,9 @@ export async function countCreditsAndRemainingForCurrentBillingPeriod(
|
|||||||
.single();
|
.single();
|
||||||
|
|
||||||
if (priceError || !price) {
|
if (priceError || !price) {
|
||||||
throw new Error(`Failed to retrieve price for price_id: ${subscription.price_id}`);
|
throw new Error(
|
||||||
|
`Failed to retrieve price for price_id: ${subscription.price_id}`
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
const remainingCredits = price.credits + couponCredits - totalCreditsUsed;
|
const remainingCredits = price.credits + couponCredits - totalCreditsUsed;
|
||||||
@ -351,11 +403,19 @@ export async function countCreditsAndRemainingForCurrentBillingPeriod(
|
|||||||
return {
|
return {
|
||||||
totalCreditsUsed,
|
totalCreditsUsed,
|
||||||
remainingCredits,
|
remainingCredits,
|
||||||
totalCredits: price.credits
|
totalCredits: price.credits,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
async function createCreditUsage({ team_id, subscription_id, credits }: { team_id: string, subscription_id?: string, credits: number }) {
|
async function createCreditUsage({
|
||||||
|
team_id,
|
||||||
|
subscription_id,
|
||||||
|
credits,
|
||||||
|
}: {
|
||||||
|
team_id: string;
|
||||||
|
subscription_id?: string;
|
||||||
|
credits: number;
|
||||||
|
}) {
|
||||||
const { data: credit_usage } = await supabase_service
|
const { data: credit_usage } = await supabase_service
|
||||||
.from("credit_usage")
|
.from("credit_usage")
|
||||||
.insert([
|
.insert([
|
||||||
|
Loading…
Reference in New Issue
Block a user