sync
This commit is contained in:
@@ -161,7 +161,9 @@ export async function POST(input: APIEvent) {
|
|||||||
})
|
})
|
||||||
|
|
||||||
if (userEmail) {
|
if (userEmail) {
|
||||||
if (coupon === LiteData.firstMonth100Coupon) {
|
if (coupon === LiteData.firstMonth50Coupon) {
|
||||||
|
await Billing.redeemCoupon(userEmail, "GO1MONTH50")
|
||||||
|
} else if (coupon === LiteData.firstMonth100Coupon) {
|
||||||
await Billing.redeemCoupon(userEmail, "GOFREEMONTH")
|
await Billing.redeemCoupon(userEmail, "GOFREEMONTH")
|
||||||
} else if (coupon === LiteData.threeMonths100Coupon) {
|
} else if (coupon === LiteData.threeMonths100Coupon) {
|
||||||
await Billing.redeemCoupon(userEmail, "GO3MONTHS100")
|
await Billing.redeemCoupon(userEmail, "GO3MONTHS100")
|
||||||
|
|||||||
@@ -0,0 +1 @@
|
|||||||
|
ALTER TABLE `coupon` MODIFY COLUMN `type` enum('BUILDATHON','GO1MONTH50','GOFREEMONTH','GO3MONTHS100','GO6MONTHS100','GO12MONTHS100') NOT NULL;
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -156,33 +156,32 @@ export namespace Billing {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export const redeemCoupon = async (email: string, type: (typeof CouponType)[number]) => {
|
export const redeemCoupon = async (email: string, type: (typeof CouponType)[number]) => {
|
||||||
const coupon = await Database.use((tx) =>
|
// validate coupon type
|
||||||
tx
|
await (async () => {
|
||||||
.select()
|
if (type === "GO1MONTH50") return
|
||||||
.from(CouponTable)
|
const coupon = await Database.use((tx) =>
|
||||||
.where(and(eq(CouponTable.email, email), eq(CouponTable.type, type)))
|
tx
|
||||||
.then((rows) => rows[0]),
|
.select()
|
||||||
)
|
.from(CouponTable)
|
||||||
if (!coupon) throw new Error("Invalid coupon code")
|
.where(and(eq(CouponTable.email, email), eq(CouponTable.type, type)))
|
||||||
if (coupon.timeRedeemed) throw new Error("Coupon already redeemed")
|
.then((rows) => rows[0]),
|
||||||
|
)
|
||||||
|
if (!coupon) throw new Error("Invalid coupon code")
|
||||||
|
if (coupon.timeRedeemed) throw new Error("Coupon already redeemed")
|
||||||
|
})()
|
||||||
|
|
||||||
|
// handle coupon type
|
||||||
if (type === "BUILDATHON") await grantCredit(Actor.workspace(), 500)
|
if (type === "BUILDATHON") await grantCredit(Actor.workspace(), 500)
|
||||||
|
|
||||||
await Database.use((tx) =>
|
await Database.use((tx) =>
|
||||||
tx
|
tx
|
||||||
.update(CouponTable)
|
.insert(CouponTable)
|
||||||
.set({ timeRedeemed: sql`now()` })
|
.values({ email, type, timeRedeemed: sql`now()` })
|
||||||
.where(and(eq(CouponTable.email, email), eq(CouponTable.type, type))),
|
.onDuplicateKeyUpdate({
|
||||||
)
|
set: {
|
||||||
}
|
timeRedeemed: sql`now()`,
|
||||||
|
},
|
||||||
export const getCoupons = async (email: string) => {
|
}),
|
||||||
return await Database.use((tx) =>
|
|
||||||
tx
|
|
||||||
.select({ type: CouponTable.type, timeRedeemed: CouponTable.timeRedeemed })
|
|
||||||
.from(CouponTable)
|
|
||||||
.where(and(eq(CouponTable.email, email), isNull(CouponTable.timeRedeemed)))
|
|
||||||
.then((rows) => rows.map((row) => row.type)),
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -290,20 +289,29 @@ export namespace Billing {
|
|||||||
if (billing.subscriptionID) throw new Error("Already subscribed to Black")
|
if (billing.subscriptionID) throw new Error("Already subscribed to Black")
|
||||||
if (billing.liteSubscriptionID) throw new Error("Already subscribed to Lite")
|
if (billing.liteSubscriptionID) throw new Error("Already subscribed to Lite")
|
||||||
|
|
||||||
const coupons = await Billing.getCoupons(email)
|
const coupons = await Database.use((tx) =>
|
||||||
const coupon = coupons.includes("GO12MONTHS100")
|
tx
|
||||||
? LiteData.twelveMonths100Coupon
|
.select({ type: CouponTable.type, timeRedeemed: CouponTable.timeRedeemed })
|
||||||
: coupons.includes("GO6MONTHS100")
|
.from(CouponTable)
|
||||||
? LiteData.sixMonths100Coupon
|
.where(eq(CouponTable.email, email)),
|
||||||
: coupons.includes("GO3MONTHS100")
|
)
|
||||||
? LiteData.threeMonths100Coupon
|
|
||||||
: coupons.includes("GOFREEMONTH")
|
const coupon = (() => {
|
||||||
? LiteData.firstMonth100Coupon
|
if (coupons.some((coupon) => coupon.type === "GO12MONTHS100" && !coupon.timeRedeemed))
|
||||||
: LiteData.firstMonth50Coupon
|
return LiteData.twelveMonths100Coupon
|
||||||
|
if (coupons.some((coupon) => coupon.type === "GO6MONTHS100" && !coupon.timeRedeemed))
|
||||||
|
return LiteData.sixMonths100Coupon
|
||||||
|
if (coupons.some((coupon) => coupon.type === "GO3MONTHS100" && !coupon.timeRedeemed))
|
||||||
|
return LiteData.threeMonths100Coupon
|
||||||
|
if (coupons.some((coupon) => coupon.type === "GOFREEMONTH" && !coupon.timeRedeemed))
|
||||||
|
return LiteData.firstMonth100Coupon
|
||||||
|
if (!coupons.some((coupon) => coupon.type === "GO1MONTH50")) return LiteData.firstMonth50Coupon
|
||||||
|
return undefined
|
||||||
|
})()
|
||||||
const createSession = () =>
|
const createSession = () =>
|
||||||
Billing.stripe().checkout.sessions.create({
|
Billing.stripe().checkout.sessions.create({
|
||||||
mode: "subscription",
|
mode: "subscription",
|
||||||
discounts: [{ coupon }],
|
discounts: coupon ? [{ coupon }] : undefined,
|
||||||
...(billing.customerID
|
...(billing.customerID
|
||||||
? {
|
? {
|
||||||
customer: billing.customerID,
|
customer: billing.customerID,
|
||||||
|
|||||||
@@ -133,7 +133,14 @@ export const UsageTable = mysqlTable(
|
|||||||
(table) => [...workspaceIndexes(table), index("usage_time_created").on(table.workspaceID, table.timeCreated)],
|
(table) => [...workspaceIndexes(table), index("usage_time_created").on(table.workspaceID, table.timeCreated)],
|
||||||
)
|
)
|
||||||
|
|
||||||
export const CouponType = ["BUILDATHON", "GOFREEMONTH", "GO3MONTHS100", "GO6MONTHS100", "GO12MONTHS100"] as const
|
export const CouponType = [
|
||||||
|
"BUILDATHON",
|
||||||
|
"GO1MONTH50",
|
||||||
|
"GOFREEMONTH",
|
||||||
|
"GO3MONTHS100",
|
||||||
|
"GO6MONTHS100",
|
||||||
|
"GO12MONTHS100",
|
||||||
|
] as const
|
||||||
export const CouponTable = mysqlTable(
|
export const CouponTable = mysqlTable(
|
||||||
"coupon",
|
"coupon",
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in New Issue
Block a user