add: add unit (per second) to lemonsqueezy after run, and sync to db table
This commit is contained in:
@@ -1,6 +1,13 @@
|
||||
import { parseDataSafe } from "../../../../lib/parseDataSafe";
|
||||
import { db } from "@/db/db";
|
||||
import { workflowRunOutputs, workflowRunsTable } from "@/db/schema";
|
||||
import {
|
||||
userUsageTable,
|
||||
workflowRunOutputs,
|
||||
workflowRunsTable,
|
||||
workflowTable,
|
||||
} from "@/db/schema";
|
||||
import { getDuration } from "@/lib/getRelativeTime";
|
||||
import { getSubscription, setUsage } from "@/server/linkToPricing";
|
||||
import { eq } from "drizzle-orm";
|
||||
import { NextResponse } from "next/server";
|
||||
import { z } from "zod";
|
||||
@@ -27,7 +34,6 @@ export async function POST(request: Request) {
|
||||
data: output_data,
|
||||
});
|
||||
} else if (status) {
|
||||
// console.log("status", status);
|
||||
const workflow_run = await db
|
||||
.update(workflowRunsTable)
|
||||
.set({
|
||||
@@ -35,8 +41,15 @@ export async function POST(request: Request) {
|
||||
ended_at:
|
||||
status === "success" || status === "failed" ? new Date() : null,
|
||||
})
|
||||
.where(eq(workflowRunsTable.id, run_id))
|
||||
.returning();
|
||||
.where(eq(workflowRunsTable.id, run_id));
|
||||
|
||||
// get data from workflowRunsTable
|
||||
const userUsageTime = await importUserUsageData(run_id);
|
||||
|
||||
if (userUsageTime) {
|
||||
// get the usage_time from userUsage
|
||||
await addSubscriptionUnit(userUsageTime);
|
||||
}
|
||||
}
|
||||
|
||||
// const workflow_version = await db.query.workflowVersionTable.findFirst({
|
||||
@@ -54,3 +67,47 @@ export async function POST(request: Request) {
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
async function addSubscriptionUnit(userUsageTime: number) {
|
||||
const subscription = await getSubscription();
|
||||
|
||||
// round up userUsageTime to the nearest integer
|
||||
const roundedUsageTime = Math.ceil(userUsageTime);
|
||||
|
||||
if (subscription) {
|
||||
const usage = await setUsage(
|
||||
subscription.data[0].attributes.first_subscription_item.id,
|
||||
roundedUsageTime
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
async function importUserUsageData(run_id: string) {
|
||||
const workflowRuns = await db.query.workflowRunsTable.findFirst({
|
||||
where: eq(workflowRunsTable.id, run_id),
|
||||
});
|
||||
|
||||
if (!workflowRuns?.workflow_id) return;
|
||||
|
||||
// find if workflowTable id column contains workflowRunsTable workflow_id
|
||||
const workflow = await db.query.workflowTable.findFirst({
|
||||
where: eq(workflowTable.id, workflowRuns.workflow_id),
|
||||
});
|
||||
|
||||
if (workflowRuns?.ended_at === null || workflow == null) return;
|
||||
|
||||
const usageTime = parseFloat(
|
||||
getDuration((workflowRuns?.ended_at - workflowRuns?.started_at) / 1000)
|
||||
);
|
||||
|
||||
// add data to userUsageTable
|
||||
const user_usage = await db.insert(userUsageTable).values({
|
||||
user_id: workflow.user_id,
|
||||
created_at: workflowRuns.ended_at,
|
||||
org_id: workflow.org_id,
|
||||
ended_at: workflowRuns.ended_at,
|
||||
usage_time: usageTime,
|
||||
});
|
||||
|
||||
return usageTime;
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ import { checkMarkIcon, crossMarkIcon } from "../const/Icon";
|
||||
import { cn } from "@/lib/utils";
|
||||
import {
|
||||
getPricing,
|
||||
getSubscription,
|
||||
getSubscriptionItem,
|
||||
getUsage,
|
||||
setUsage,
|
||||
@@ -89,12 +90,14 @@ export default function PricingList() {
|
||||
// const currentUser = await getUserData();
|
||||
|
||||
const userUsage = await getUsage();
|
||||
const userSubscription = await getSubscriptionItem();
|
||||
const userSubscription = await getSubscription();
|
||||
|
||||
// const setUserUsage = await setUsage(236561, 10);
|
||||
|
||||
// console.log(currentUser);
|
||||
console.log(userSubscription);
|
||||
console.log(
|
||||
userSubscription.data[0].attributes.first_subscription_item.id
|
||||
);
|
||||
})();
|
||||
}, []);
|
||||
|
||||
|
||||
+60
-60
@@ -1,14 +1,14 @@
|
||||
import { type InferSelectModel, relations } from "drizzle-orm";
|
||||
import {
|
||||
boolean,
|
||||
integer,
|
||||
jsonb,
|
||||
pgEnum,
|
||||
pgSchema,
|
||||
text,
|
||||
timestamp,
|
||||
uuid,
|
||||
real,
|
||||
boolean,
|
||||
integer,
|
||||
jsonb,
|
||||
pgEnum,
|
||||
pgSchema,
|
||||
text,
|
||||
timestamp,
|
||||
uuid,
|
||||
real,
|
||||
} from "drizzle-orm/pg-core";
|
||||
import { createInsertSchema } from "drizzle-zod";
|
||||
import { z } from "zod";
|
||||
@@ -131,30 +131,30 @@ export const machinesStatus = pgEnum("machine_status", [
|
||||
|
||||
// We still want to keep the workflow run record.
|
||||
export const workflowRunsTable = dbSchema.table("workflow_runs", {
|
||||
id: uuid("id").primaryKey().defaultRandom().notNull(),
|
||||
// when workflow version deleted, still want to keep this record
|
||||
workflow_version_id: uuid("workflow_version_id").references(
|
||||
() => workflowVersionTable.id,
|
||||
{
|
||||
onDelete: "set null",
|
||||
},
|
||||
),
|
||||
workflow_inputs:
|
||||
jsonb("workflow_inputs").$type<Record<string, string | number>>(),
|
||||
workflow_id: uuid("workflow_id")
|
||||
.notNull()
|
||||
.references(() => workflowTable.id, {
|
||||
onDelete: "cascade",
|
||||
}),
|
||||
// when machine deleted, still want to keep this record
|
||||
machine_id: uuid("machine_id").references(() => machinesTable.id, {
|
||||
onDelete: "set null",
|
||||
}),
|
||||
origin: workflowRunOrigin("origin").notNull().default("api"),
|
||||
status: workflowRunStatus("status").notNull().default("not-started"),
|
||||
ended_at: timestamp("ended_at"),
|
||||
created_at: timestamp("created_at").defaultNow().notNull(),
|
||||
started_at: timestamp("started_at"),
|
||||
id: uuid("id").primaryKey().defaultRandom().notNull(),
|
||||
// when workflow version deleted, still want to keep this record
|
||||
workflow_version_id: uuid("workflow_version_id").references(
|
||||
() => workflowVersionTable.id,
|
||||
{
|
||||
onDelete: "set null",
|
||||
}
|
||||
),
|
||||
workflow_inputs:
|
||||
jsonb("workflow_inputs").$type<Record<string, string | number>>(),
|
||||
workflow_id: uuid("workflow_id")
|
||||
.notNull()
|
||||
.references(() => workflowTable.id, {
|
||||
onDelete: "cascade",
|
||||
}),
|
||||
// when machine deleted, still want to keep this record
|
||||
machine_id: uuid("machine_id").references(() => machinesTable.id, {
|
||||
onDelete: "set null",
|
||||
}),
|
||||
origin: workflowRunOrigin("origin").notNull().default("api"),
|
||||
status: workflowRunStatus("status").notNull().default("not-started"),
|
||||
ended_at: timestamp("ended_at"),
|
||||
created_at: timestamp("created_at").defaultNow().notNull(),
|
||||
started_at: timestamp("started_at"),
|
||||
});
|
||||
|
||||
export const workflowRunRelations = relations(
|
||||
@@ -258,31 +258,31 @@ export const showcaseMediaNullable = z
|
||||
.nullable();
|
||||
|
||||
export const deploymentsTable = dbSchema.table("deployments", {
|
||||
id: uuid("id").primaryKey().defaultRandom().notNull(),
|
||||
user_id: text("user_id")
|
||||
.references(() => usersTable.id, {
|
||||
onDelete: "cascade",
|
||||
})
|
||||
.notNull(),
|
||||
org_id: text("org_id"),
|
||||
workflow_version_id: uuid("workflow_version_id")
|
||||
.notNull()
|
||||
.references(() => workflowVersionTable.id),
|
||||
workflow_id: uuid("workflow_id")
|
||||
.notNull()
|
||||
.references(() => workflowTable.id, {
|
||||
onDelete: "cascade",
|
||||
}),
|
||||
machine_id: uuid("machine_id")
|
||||
.notNull()
|
||||
.references(() => machinesTable.id),
|
||||
share_slug: text("share_slug").unique(),
|
||||
description: text("description"),
|
||||
showcase_media:
|
||||
jsonb("showcase_media").$type<z.infer<typeof showcaseMedia>>(),
|
||||
environment: deploymentEnvironment("environment").notNull(),
|
||||
created_at: timestamp("created_at").defaultNow().notNull(),
|
||||
updated_at: timestamp("updated_at").defaultNow().notNull(),
|
||||
id: uuid("id").primaryKey().defaultRandom().notNull(),
|
||||
user_id: text("user_id")
|
||||
.references(() => usersTable.id, {
|
||||
onDelete: "cascade",
|
||||
})
|
||||
.notNull(),
|
||||
org_id: text("org_id"),
|
||||
workflow_version_id: uuid("workflow_version_id")
|
||||
.notNull()
|
||||
.references(() => workflowVersionTable.id),
|
||||
workflow_id: uuid("workflow_id")
|
||||
.notNull()
|
||||
.references(() => workflowTable.id, {
|
||||
onDelete: "cascade",
|
||||
}),
|
||||
machine_id: uuid("machine_id")
|
||||
.notNull()
|
||||
.references(() => machinesTable.id),
|
||||
share_slug: text("share_slug").unique(),
|
||||
description: text("description"),
|
||||
showcase_media:
|
||||
jsonb("showcase_media").$type<z.infer<typeof showcaseMedia>>(),
|
||||
environment: deploymentEnvironment("environment").notNull(),
|
||||
created_at: timestamp("created_at").defaultNow().notNull(),
|
||||
updated_at: timestamp("updated_at").defaultNow().notNull(),
|
||||
});
|
||||
|
||||
export const publicShareDeployment = z.object({
|
||||
@@ -334,15 +334,15 @@ export const apiKeyTable = dbSchema.table("api_keys", {
|
||||
|
||||
export const userUsageTable = dbSchema.table("user_usage", {
|
||||
id: uuid("id").primaryKey().defaultRandom().notNull(),
|
||||
org_id: text("org_id"),
|
||||
user_id: text("user_id")
|
||||
.references(() => usersTable.id, {
|
||||
onDelete: "cascade",
|
||||
})
|
||||
.notNull(),
|
||||
usage_time: real("usage_time").default(0).notNull(),
|
||||
|
||||
created_at: timestamp("created_at").defaultNow().notNull(),
|
||||
updated_at: timestamp("updated_at").defaultNow().notNull(),
|
||||
ended_at: timestamp("ended_at").defaultNow().notNull(),
|
||||
});
|
||||
|
||||
export type UserType = InferSelectModel<typeof usersTable>;
|
||||
|
||||
Reference in New Issue
Block a user