summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorFrank <[email protected]>2026-01-16 17:46:32 -0500
committerFrank <[email protected]>2026-01-16 17:46:36 -0500
commitcbe1c81470564a8f5042047d7422219426e78030 (patch)
tree73d3f2b3d8f806d7978dc6f2031f1fa2040ba397
parentc25155586cd57b8db68a479c714c44f2bfbf667b (diff)
downloadopencode-cbe1c81470564a8f5042047d7422219426e78030.tar.gz
opencode-cbe1c81470564a8f5042047d7422219426e78030.zip
wip: black
-rw-r--r--packages/console/app/src/routes/stripe/webhook.ts9
-rw-r--r--packages/console/core/migrations/0053_gigantic_hardball.sql1
-rw-r--r--packages/console/core/migrations/meta/0053_snapshot.json1316
-rw-r--r--packages/console/core/migrations/meta/_journal.json9
-rw-r--r--packages/console/core/script/black-gift.ts112
-rw-r--r--packages/console/core/script/black-onboard.ts (renamed from packages/console/core/script/onboard-zen-black.ts)11
-rw-r--r--packages/console/core/script/black-transfer.ts6
-rw-r--r--packages/console/core/script/lookup-user.ts18
-rw-r--r--packages/console/core/src/schema/billing.sql.ts13
9 files changed, 1474 insertions, 21 deletions
diff --git a/packages/console/app/src/routes/stripe/webhook.ts b/packages/console/app/src/routes/stripe/webhook.ts
index 3422d9dd6..4c3430193 100644
--- a/packages/console/app/src/routes/stripe/webhook.ts
+++ b/packages/console/app/src/routes/stripe/webhook.ts
@@ -183,7 +183,12 @@ export async function POST(input: APIEvent) {
.set({
customerID,
subscriptionID,
- subscriptionCouponID: couponID,
+ subscription: {
+ status: "subscribed",
+ coupon: couponID,
+ seats: 1,
+ plan: "200",
+ },
paymentMethodID: paymentMethod.id,
paymentMethodLast4: paymentMethod.card?.last4 ?? null,
paymentMethodType: paymentMethod.type,
@@ -408,7 +413,7 @@ export async function POST(input: APIEvent) {
await Database.transaction(async (tx) => {
await tx
.update(BillingTable)
- .set({ subscriptionID: null, subscriptionCouponID: null })
+ .set({ subscriptionID: null, subscription: null })
.where(eq(BillingTable.workspaceID, workspaceID))
await tx.delete(SubscriptionTable).where(eq(SubscriptionTable.workspaceID, workspaceID))
diff --git a/packages/console/core/migrations/0053_gigantic_hardball.sql b/packages/console/core/migrations/0053_gigantic_hardball.sql
new file mode 100644
index 000000000..72d43135f
--- /dev/null
+++ b/packages/console/core/migrations/0053_gigantic_hardball.sql
@@ -0,0 +1 @@
+ALTER TABLE `billing` ADD `subscription` json; \ No newline at end of file
diff --git a/packages/console/core/migrations/meta/0053_snapshot.json b/packages/console/core/migrations/meta/0053_snapshot.json
new file mode 100644
index 000000000..fba46b14b
--- /dev/null
+++ b/packages/console/core/migrations/meta/0053_snapshot.json
@@ -0,0 +1,1316 @@
+{
+ "version": "5",
+ "dialect": "mysql",
+ "id": "32a0c40b-a269-4ad1-a5a0-52b1f18932aa",
+ "prevId": "00774acd-a1e5-49c0-b296-cacc9506a566",
+ "tables": {
+ "account": {
+ "name": "account",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "varchar(30)",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "time_created": {
+ "name": "time_created",
+ "type": "timestamp(3)",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false,
+ "default": "(now())"
+ },
+ "time_updated": {
+ "name": "time_updated",
+ "type": "timestamp(3)",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false,
+ "default": "CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3)"
+ },
+ "time_deleted": {
+ "name": "time_deleted",
+ "type": "timestamp(3)",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {},
+ "compositePrimaryKeys": {
+ "account_id_pk": {
+ "name": "account_id_pk",
+ "columns": [
+ "id"
+ ]
+ }
+ },
+ "uniqueConstraints": {},
+ "checkConstraint": {}
+ },
+ "auth": {
+ "name": "auth",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "varchar(30)",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "time_created": {
+ "name": "time_created",
+ "type": "timestamp(3)",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false,
+ "default": "(now())"
+ },
+ "time_updated": {
+ "name": "time_updated",
+ "type": "timestamp(3)",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false,
+ "default": "CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3)"
+ },
+ "time_deleted": {
+ "name": "time_deleted",
+ "type": "timestamp(3)",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ },
+ "provider": {
+ "name": "provider",
+ "type": "enum('email','github','google')",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "subject": {
+ "name": "subject",
+ "type": "varchar(255)",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "account_id": {
+ "name": "account_id",
+ "type": "varchar(30)",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ }
+ },
+ "indexes": {
+ "provider": {
+ "name": "provider",
+ "columns": [
+ "provider",
+ "subject"
+ ],
+ "isUnique": true
+ },
+ "account_id": {
+ "name": "account_id",
+ "columns": [
+ "account_id"
+ ],
+ "isUnique": false
+ }
+ },
+ "foreignKeys": {},
+ "compositePrimaryKeys": {
+ "auth_id_pk": {
+ "name": "auth_id_pk",
+ "columns": [
+ "id"
+ ]
+ }
+ },
+ "uniqueConstraints": {},
+ "checkConstraint": {}
+ },
+ "benchmark": {
+ "name": "benchmark",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "varchar(30)",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "time_created": {
+ "name": "time_created",
+ "type": "timestamp(3)",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false,
+ "default": "(now())"
+ },
+ "time_updated": {
+ "name": "time_updated",
+ "type": "timestamp(3)",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false,
+ "default": "CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3)"
+ },
+ "time_deleted": {
+ "name": "time_deleted",
+ "type": "timestamp(3)",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ },
+ "model": {
+ "name": "model",
+ "type": "varchar(64)",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "agent": {
+ "name": "agent",
+ "type": "varchar(64)",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "result": {
+ "name": "result",
+ "type": "mediumtext",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ }
+ },
+ "indexes": {
+ "time_created": {
+ "name": "time_created",
+ "columns": [
+ "time_created"
+ ],
+ "isUnique": false
+ }
+ },
+ "foreignKeys": {},
+ "compositePrimaryKeys": {
+ "benchmark_id_pk": {
+ "name": "benchmark_id_pk",
+ "columns": [
+ "id"
+ ]
+ }
+ },
+ "uniqueConstraints": {},
+ "checkConstraint": {}
+ },
+ "billing": {
+ "name": "billing",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "varchar(30)",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "workspace_id": {
+ "name": "workspace_id",
+ "type": "varchar(30)",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "time_created": {
+ "name": "time_created",
+ "type": "timestamp(3)",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false,
+ "default": "(now())"
+ },
+ "time_updated": {
+ "name": "time_updated",
+ "type": "timestamp(3)",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false,
+ "default": "CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3)"
+ },
+ "time_deleted": {
+ "name": "time_deleted",
+ "type": "timestamp(3)",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ },
+ "customer_id": {
+ "name": "customer_id",
+ "type": "varchar(255)",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ },
+ "payment_method_id": {
+ "name": "payment_method_id",
+ "type": "varchar(255)",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ },
+ "payment_method_type": {
+ "name": "payment_method_type",
+ "type": "varchar(32)",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ },
+ "payment_method_last4": {
+ "name": "payment_method_last4",
+ "type": "varchar(4)",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ },
+ "balance": {
+ "name": "balance",
+ "type": "bigint",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "monthly_limit": {
+ "name": "monthly_limit",
+ "type": "int",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ },
+ "monthly_usage": {
+ "name": "monthly_usage",
+ "type": "bigint",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ },
+ "time_monthly_usage_updated": {
+ "name": "time_monthly_usage_updated",
+ "type": "timestamp(3)",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ },
+ "reload": {
+ "name": "reload",
+ "type": "boolean",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ },
+ "reload_trigger": {
+ "name": "reload_trigger",
+ "type": "int",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ },
+ "reload_amount": {
+ "name": "reload_amount",
+ "type": "int",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ },
+ "reload_error": {
+ "name": "reload_error",
+ "type": "varchar(255)",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ },
+ "time_reload_error": {
+ "name": "time_reload_error",
+ "type": "timestamp(3)",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ },
+ "time_reload_locked_till": {
+ "name": "time_reload_locked_till",
+ "type": "timestamp(3)",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ },
+ "subscription": {
+ "name": "subscription",
+ "type": "json",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ },
+ "subscription_id": {
+ "name": "subscription_id",
+ "type": "varchar(28)",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ },
+ "subscription_coupon_id": {
+ "name": "subscription_coupon_id",
+ "type": "varchar(28)",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ },
+ "subscription_plan": {
+ "name": "subscription_plan",
+ "type": "enum('20','100','200')",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ },
+ "time_subscription_booked": {
+ "name": "time_subscription_booked",
+ "type": "timestamp(3)",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ }
+ },
+ "indexes": {
+ "global_customer_id": {
+ "name": "global_customer_id",
+ "columns": [
+ "customer_id"
+ ],
+ "isUnique": true
+ },
+ "global_subscription_id": {
+ "name": "global_subscription_id",
+ "columns": [
+ "subscription_id"
+ ],
+ "isUnique": true
+ }
+ },
+ "foreignKeys": {},
+ "compositePrimaryKeys": {
+ "billing_workspace_id_id_pk": {
+ "name": "billing_workspace_id_id_pk",
+ "columns": [
+ "workspace_id",
+ "id"
+ ]
+ }
+ },
+ "uniqueConstraints": {},
+ "checkConstraint": {}
+ },
+ "payment": {
+ "name": "payment",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "varchar(30)",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "workspace_id": {
+ "name": "workspace_id",
+ "type": "varchar(30)",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "time_created": {
+ "name": "time_created",
+ "type": "timestamp(3)",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false,
+ "default": "(now())"
+ },
+ "time_updated": {
+ "name": "time_updated",
+ "type": "timestamp(3)",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false,
+ "default": "CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3)"
+ },
+ "time_deleted": {
+ "name": "time_deleted",
+ "type": "timestamp(3)",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ },
+ "customer_id": {
+ "name": "customer_id",
+ "type": "varchar(255)",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ },
+ "invoice_id": {
+ "name": "invoice_id",
+ "type": "varchar(255)",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ },
+ "payment_id": {
+ "name": "payment_id",
+ "type": "varchar(255)",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ },
+ "amount": {
+ "name": "amount",
+ "type": "bigint",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "time_refunded": {
+ "name": "time_refunded",
+ "type": "timestamp(3)",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ },
+ "enrichment": {
+ "name": "enrichment",
+ "type": "json",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {},
+ "compositePrimaryKeys": {
+ "payment_workspace_id_id_pk": {
+ "name": "payment_workspace_id_id_pk",
+ "columns": [
+ "workspace_id",
+ "id"
+ ]
+ }
+ },
+ "uniqueConstraints": {},
+ "checkConstraint": {}
+ },
+ "subscription": {
+ "name": "subscription",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "varchar(30)",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "workspace_id": {
+ "name": "workspace_id",
+ "type": "varchar(30)",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "time_created": {
+ "name": "time_created",
+ "type": "timestamp(3)",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false,
+ "default": "(now())"
+ },
+ "time_updated": {
+ "name": "time_updated",
+ "type": "timestamp(3)",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false,
+ "default": "CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3)"
+ },
+ "time_deleted": {
+ "name": "time_deleted",
+ "type": "timestamp(3)",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ },
+ "user_id": {
+ "name": "user_id",
+ "type": "varchar(30)",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "rolling_usage": {
+ "name": "rolling_usage",
+ "type": "bigint",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ },
+ "fixed_usage": {
+ "name": "fixed_usage",
+ "type": "bigint",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ },
+ "time_rolling_updated": {
+ "name": "time_rolling_updated",
+ "type": "timestamp(3)",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ },
+ "time_fixed_updated": {
+ "name": "time_fixed_updated",
+ "type": "timestamp(3)",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ }
+ },
+ "indexes": {
+ "workspace_user_id": {
+ "name": "workspace_user_id",
+ "columns": [
+ "workspace_id",
+ "user_id"
+ ],
+ "isUnique": true
+ }
+ },
+ "foreignKeys": {},
+ "compositePrimaryKeys": {
+ "subscription_workspace_id_id_pk": {
+ "name": "subscription_workspace_id_id_pk",
+ "columns": [
+ "workspace_id",
+ "id"
+ ]
+ }
+ },
+ "uniqueConstraints": {},
+ "checkConstraint": {}
+ },
+ "usage": {
+ "name": "usage",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "varchar(30)",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "workspace_id": {
+ "name": "workspace_id",
+ "type": "varchar(30)",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "time_created": {
+ "name": "time_created",
+ "type": "timestamp(3)",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false,
+ "default": "(now())"
+ },
+ "time_updated": {
+ "name": "time_updated",
+ "type": "timestamp(3)",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false,
+ "default": "CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3)"
+ },
+ "time_deleted": {
+ "name": "time_deleted",
+ "type": "timestamp(3)",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ },
+ "model": {
+ "name": "model",
+ "type": "varchar(255)",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "provider": {
+ "name": "provider",
+ "type": "varchar(255)",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "input_tokens": {
+ "name": "input_tokens",
+ "type": "int",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "output_tokens": {
+ "name": "output_tokens",
+ "type": "int",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "reasoning_tokens": {
+ "name": "reasoning_tokens",
+ "type": "int",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ },
+ "cache_read_tokens": {
+ "name": "cache_read_tokens",
+ "type": "int",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ },
+ "cache_write_5m_tokens": {
+ "name": "cache_write_5m_tokens",
+ "type": "int",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ },
+ "cache_write_1h_tokens": {
+ "name": "cache_write_1h_tokens",
+ "type": "int",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ },
+ "cost": {
+ "name": "cost",
+ "type": "bigint",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "key_id": {
+ "name": "key_id",
+ "type": "varchar(30)",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ },
+ "enrichment": {
+ "name": "enrichment",
+ "type": "json",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ }
+ },
+ "indexes": {
+ "usage_time_created": {
+ "name": "usage_time_created",
+ "columns": [
+ "workspace_id",
+ "time_created"
+ ],
+ "isUnique": false
+ }
+ },
+ "foreignKeys": {},
+ "compositePrimaryKeys": {
+ "usage_workspace_id_id_pk": {
+ "name": "usage_workspace_id_id_pk",
+ "columns": [
+ "workspace_id",
+ "id"
+ ]
+ }
+ },
+ "uniqueConstraints": {},
+ "checkConstraint": {}
+ },
+ "ip_rate_limit": {
+ "name": "ip_rate_limit",
+ "columns": {
+ "ip": {
+ "name": "ip",
+ "type": "varchar(45)",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "interval": {
+ "name": "interval",
+ "type": "varchar(10)",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "count": {
+ "name": "count",
+ "type": "int",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {},
+ "compositePrimaryKeys": {
+ "ip_rate_limit_ip_interval_pk": {
+ "name": "ip_rate_limit_ip_interval_pk",
+ "columns": [
+ "ip",
+ "interval"
+ ]
+ }
+ },
+ "uniqueConstraints": {},
+ "checkConstraint": {}
+ },
+ "ip": {
+ "name": "ip",
+ "columns": {
+ "ip": {
+ "name": "ip",
+ "type": "varchar(45)",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "time_created": {
+ "name": "time_created",
+ "type": "timestamp(3)",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false,
+ "default": "(now())"
+ },
+ "time_updated": {
+ "name": "time_updated",
+ "type": "timestamp(3)",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false,
+ "default": "CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3)"
+ },
+ "time_deleted": {
+ "name": "time_deleted",
+ "type": "timestamp(3)",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ },
+ "usage": {
+ "name": "usage",
+ "type": "int",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {},
+ "compositePrimaryKeys": {
+ "ip_ip_pk": {
+ "name": "ip_ip_pk",
+ "columns": [
+ "ip"
+ ]
+ }
+ },
+ "uniqueConstraints": {},
+ "checkConstraint": {}
+ },
+ "key": {
+ "name": "key",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "varchar(30)",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "workspace_id": {
+ "name": "workspace_id",
+ "type": "varchar(30)",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "time_created": {
+ "name": "time_created",
+ "type": "timestamp(3)",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false,
+ "default": "(now())"
+ },
+ "time_updated": {
+ "name": "time_updated",
+ "type": "timestamp(3)",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false,
+ "default": "CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3)"
+ },
+ "time_deleted": {
+ "name": "time_deleted",
+ "type": "timestamp(3)",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ },
+ "name": {
+ "name": "name",
+ "type": "varchar(255)",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "key": {
+ "name": "key",
+ "type": "varchar(255)",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "user_id": {
+ "name": "user_id",
+ "type": "varchar(30)",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "time_used": {
+ "name": "time_used",
+ "type": "timestamp(3)",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ }
+ },
+ "indexes": {
+ "global_key": {
+ "name": "global_key",
+ "columns": [
+ "key"
+ ],
+ "isUnique": true
+ }
+ },
+ "foreignKeys": {},
+ "compositePrimaryKeys": {
+ "key_workspace_id_id_pk": {
+ "name": "key_workspace_id_id_pk",
+ "columns": [
+ "workspace_id",
+ "id"
+ ]
+ }
+ },
+ "uniqueConstraints": {},
+ "checkConstraint": {}
+ },
+ "model": {
+ "name": "model",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "varchar(30)",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "workspace_id": {
+ "name": "workspace_id",
+ "type": "varchar(30)",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "time_created": {
+ "name": "time_created",
+ "type": "timestamp(3)",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false,
+ "default": "(now())"
+ },
+ "time_updated": {
+ "name": "time_updated",
+ "type": "timestamp(3)",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false,
+ "default": "CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3)"
+ },
+ "time_deleted": {
+ "name": "time_deleted",
+ "type": "timestamp(3)",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ },
+ "model": {
+ "name": "model",
+ "type": "varchar(64)",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ }
+ },
+ "indexes": {
+ "model_workspace_model": {
+ "name": "model_workspace_model",
+ "columns": [
+ "workspace_id",
+ "model"
+ ],
+ "isUnique": true
+ }
+ },
+ "foreignKeys": {},
+ "compositePrimaryKeys": {
+ "model_workspace_id_id_pk": {
+ "name": "model_workspace_id_id_pk",
+ "columns": [
+ "workspace_id",
+ "id"
+ ]
+ }
+ },
+ "uniqueConstraints": {},
+ "checkConstraint": {}
+ },
+ "provider": {
+ "name": "provider",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "varchar(30)",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "workspace_id": {
+ "name": "workspace_id",
+ "type": "varchar(30)",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "time_created": {
+ "name": "time_created",
+ "type": "timestamp(3)",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false,
+ "default": "(now())"
+ },
+ "time_updated": {
+ "name": "time_updated",
+ "type": "timestamp(3)",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false,
+ "default": "CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3)"
+ },
+ "time_deleted": {
+ "name": "time_deleted",
+ "type": "timestamp(3)",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ },
+ "provider": {
+ "name": "provider",
+ "type": "varchar(64)",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "credentials": {
+ "name": "credentials",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ }
+ },
+ "indexes": {
+ "workspace_provider": {
+ "name": "workspace_provider",
+ "columns": [
+ "workspace_id",
+ "provider"
+ ],
+ "isUnique": true
+ }
+ },
+ "foreignKeys": {},
+ "compositePrimaryKeys": {
+ "provider_workspace_id_id_pk": {
+ "name": "provider_workspace_id_id_pk",
+ "columns": [
+ "workspace_id",
+ "id"
+ ]
+ }
+ },
+ "uniqueConstraints": {},
+ "checkConstraint": {}
+ },
+ "user": {
+ "name": "user",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "varchar(30)",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "workspace_id": {
+ "name": "workspace_id",
+ "type": "varchar(30)",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "time_created": {
+ "name": "time_created",
+ "type": "timestamp(3)",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false,
+ "default": "(now())"
+ },
+ "time_updated": {
+ "name": "time_updated",
+ "type": "timestamp(3)",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false,
+ "default": "CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3)"
+ },
+ "time_deleted": {
+ "name": "time_deleted",
+ "type": "timestamp(3)",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ },
+ "account_id": {
+ "name": "account_id",
+ "type": "varchar(30)",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ },
+ "email": {
+ "name": "email",
+ "type": "varchar(255)",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ },
+ "name": {
+ "name": "name",
+ "type": "varchar(255)",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "time_seen": {
+ "name": "time_seen",
+ "type": "timestamp(3)",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ },
+ "color": {
+ "name": "color",
+ "type": "int",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ },
+ "role": {
+ "name": "role",
+ "type": "enum('admin','member')",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "monthly_limit": {
+ "name": "monthly_limit",
+ "type": "int",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ },
+ "monthly_usage": {
+ "name": "monthly_usage",
+ "type": "bigint",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ },
+ "time_monthly_usage_updated": {
+ "name": "time_monthly_usage_updated",
+ "type": "timestamp(3)",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ }
+ },
+ "indexes": {
+ "user_account_id": {
+ "name": "user_account_id",
+ "columns": [
+ "workspace_id",
+ "account_id"
+ ],
+ "isUnique": true
+ },
+ "user_email": {
+ "name": "user_email",
+ "columns": [
+ "workspace_id",
+ "email"
+ ],
+ "isUnique": true
+ },
+ "global_account_id": {
+ "name": "global_account_id",
+ "columns": [
+ "account_id"
+ ],
+ "isUnique": false
+ },
+ "global_email": {
+ "name": "global_email",
+ "columns": [
+ "email"
+ ],
+ "isUnique": false
+ }
+ },
+ "foreignKeys": {},
+ "compositePrimaryKeys": {
+ "user_workspace_id_id_pk": {
+ "name": "user_workspace_id_id_pk",
+ "columns": [
+ "workspace_id",
+ "id"
+ ]
+ }
+ },
+ "uniqueConstraints": {},
+ "checkConstraint": {}
+ },
+ "workspace": {
+ "name": "workspace",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "varchar(30)",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "slug": {
+ "name": "slug",
+ "type": "varchar(255)",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ },
+ "name": {
+ "name": "name",
+ "type": "varchar(255)",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "time_created": {
+ "name": "time_created",
+ "type": "timestamp(3)",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false,
+ "default": "(now())"
+ },
+ "time_updated": {
+ "name": "time_updated",
+ "type": "timestamp(3)",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false,
+ "default": "CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3)"
+ },
+ "time_deleted": {
+ "name": "time_deleted",
+ "type": "timestamp(3)",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ }
+ },
+ "indexes": {
+ "slug": {
+ "name": "slug",
+ "columns": [
+ "slug"
+ ],
+ "isUnique": true
+ }
+ },
+ "foreignKeys": {},
+ "compositePrimaryKeys": {
+ "workspace_id": {
+ "name": "workspace_id",
+ "columns": [
+ "id"
+ ]
+ }
+ },
+ "uniqueConstraints": {},
+ "checkConstraint": {}
+ }
+ },
+ "views": {},
+ "_meta": {
+ "schemas": {},
+ "tables": {},
+ "columns": {}
+ },
+ "internal": {
+ "tables": {},
+ "indexes": {}
+ }
+} \ No newline at end of file
diff --git a/packages/console/core/migrations/meta/_journal.json b/packages/console/core/migrations/meta/_journal.json
index cdf4f6390..89ffd2423 100644
--- a/packages/console/core/migrations/meta/_journal.json
+++ b/packages/console/core/migrations/meta/_journal.json
@@ -372,6 +372,13 @@
"when": 1768343920467,
"tag": "0052_aromatic_agent_zero",
"breakpoints": true
+ },
+ {
+ "idx": 53,
+ "version": "5",
+ "when": 1768599366758,
+ "tag": "0053_gigantic_hardball",
+ "breakpoints": true
}
]
-}
+} \ No newline at end of file
diff --git a/packages/console/core/script/black-gift.ts b/packages/console/core/script/black-gift.ts
new file mode 100644
index 000000000..3fbf210ab
--- /dev/null
+++ b/packages/console/core/script/black-gift.ts
@@ -0,0 +1,112 @@
+import { Billing } from "../src/billing.js"
+import { and, Database, eq, isNull, sql } from "../src/drizzle/index.js"
+import { UserTable } from "../src/schema/user.sql.js"
+import { BillingTable, PaymentTable, SubscriptionTable } from "../src/schema/billing.sql.js"
+import { Identifier } from "../src/identifier.js"
+import { centsToMicroCents } from "../src/util/price.js"
+import { AuthTable } from "../src/schema/auth.sql.js"
+
+const plan = "200"
+const workspaceID = process.argv[2]
+const seats = parseInt(process.argv[3])
+
+console.log(`Gifting ${seats} seats of Black to workspace ${workspaceID}`)
+
+if (!workspaceID || !seats) throw new Error("Usage: bun foo.ts <workspaceID> <seats>")
+
+// Get workspace user
+const users = await Database.use((tx) =>
+ tx
+ .select({
+ id: UserTable.id,
+ role: UserTable.role,
+ email: AuthTable.subject,
+ })
+ .from(UserTable)
+ .leftJoin(AuthTable, and(eq(AuthTable.accountID, UserTable.accountID), eq(AuthTable.provider, "email")))
+ .where(and(eq(UserTable.workspaceID, workspaceID), isNull(UserTable.timeDeleted))),
+)
+if (users.length === 0) throw new Error(`Error: No users found in workspace ${workspaceID}`)
+if (users.length !== seats)
+ throw new Error(`Error: Workspace ${workspaceID} has ${users.length} users, expected ${seats}`)
+const adminUser = users.find((user) => user.role === "admin")
+if (!adminUser) throw new Error(`Error: No admin user found in workspace ${workspaceID}`)
+if (!adminUser.email) throw new Error(`Error: Admin user ${adminUser.id} has no email`)
+
+// Get Billing
+const billing = await Database.use((tx) =>
+ tx
+ .select({
+ customerID: BillingTable.customerID,
+ subscriptionID: BillingTable.subscriptionID,
+ })
+ .from(BillingTable)
+ .where(eq(BillingTable.workspaceID, workspaceID))
+ .then((rows) => rows[0]),
+)
+if (!billing) throw new Error(`Error: Workspace ${workspaceID} has no billing record`)
+if (billing.subscriptionID) throw new Error(`Error: Workspace ${workspaceID} already has a subscription`)
+
+// Look up the Stripe customer by email
+const customerID =
+ billing.customerID ??
+ (await (() =>
+ Billing.stripe()
+ .customers.create({
+ email: adminUser.email,
+ metadata: {
+ workspaceID,
+ },
+ })
+ .then((customer) => customer.id))())
+console.log(`Customer ID: ${customerID}`)
+
+const couponID = "JAIr0Pe1"
+const subscription = await Billing.stripe().subscriptions.create({
+ customer: customerID!,
+ items: [
+ {
+ price: `price_1SmfyI2StuRr0lbXovxJNeZn`,
+ discounts: [{ coupon: couponID }],
+ quantity: 2,
+ },
+ ],
+})
+console.log(`Subscription ID: ${subscription.id}`)
+
+await Database.transaction(async (tx) => {
+ // Set customer id, subscription id, and payment method on workspace billing
+ await tx
+ .update(BillingTable)
+ .set({
+ customerID,
+ subscriptionID: subscription.id,
+ subscription: { status: "subscribed", coupon: couponID, seats, plan },
+ })
+ .where(eq(BillingTable.workspaceID, workspaceID))
+
+ // Create a row in subscription table
+ for (const user of users) {
+ await tx.insert(SubscriptionTable).values({
+ workspaceID,
+ id: Identifier.create("subscription"),
+ userID: user.id,
+ })
+ }
+ //
+ // // Create a row in payments table
+ // await tx.insert(PaymentTable).values({
+ // workspaceID,
+ // id: Identifier.create("payment"),
+ // amount: centsToMicroCents(amountInCents),
+ // customerID,
+ // invoiceID,
+ // paymentID,
+ // enrichment: {
+ // type: "subscription",
+ // couponID,
+ // },
+ // })
+})
+
+console.log(`done`)
diff --git a/packages/console/core/script/onboard-zen-black.ts b/packages/console/core/script/black-onboard.ts
index 3ee880973..77e5b779e 100644
--- a/packages/console/core/script/onboard-zen-black.ts
+++ b/packages/console/core/script/black-onboard.ts
@@ -12,7 +12,7 @@ const email = process.argv[3]
console.log(`Onboarding workspace ${workspaceID} for email ${email}`)
if (!workspaceID || !email) {
- console.error("Usage: bun onboard-zen-black.ts <workspaceID> <email>")
+ console.error("Usage: bun foo.ts <workspaceID> <email>")
process.exit(1)
}
@@ -50,7 +50,7 @@ const existingSubscription = await Database.use((tx) =>
tx
.select({ workspaceID: BillingTable.workspaceID })
.from(BillingTable)
- .where(eq(BillingTable.subscriptionID, subscriptionID))
+ .where(sql`JSON_EXTRACT(${BillingTable.subscription}, '$.id') = ${subscriptionID}`)
.then((rows) => rows[0]),
)
if (existingSubscription) {
@@ -128,10 +128,15 @@ await Database.transaction(async (tx) => {
.set({
customerID,
subscriptionID,
- subscriptionCouponID: couponID,
paymentMethodID,
paymentMethodLast4,
paymentMethodType,
+ subscription: {
+ status: "subscribed",
+ coupon: couponID,
+ seats: 1,
+ plan: "200",
+ },
})
.where(eq(BillingTable.workspaceID, workspaceID))
diff --git a/packages/console/core/script/black-transfer.ts b/packages/console/core/script/black-transfer.ts
index a7947fe72..e962ba5d3 100644
--- a/packages/console/core/script/black-transfer.ts
+++ b/packages/console/core/script/black-transfer.ts
@@ -18,7 +18,7 @@ const fromBilling = await Database.use((tx) =>
.select({
customerID: BillingTable.customerID,
subscriptionID: BillingTable.subscriptionID,
- subscriptionCouponID: BillingTable.subscriptionCouponID,
+ subscription: BillingTable.subscription,
paymentMethodID: BillingTable.paymentMethodID,
paymentMethodType: BillingTable.paymentMethodType,
paymentMethodLast4: BillingTable.paymentMethodLast4,
@@ -119,7 +119,7 @@ await Database.transaction(async (tx) => {
.set({
customerID: fromPrevPayment.customerID,
subscriptionID: null,
- subscriptionCouponID: null,
+ subscription: null,
paymentMethodID: fromPrevPaymentMethods.data[0].id,
paymentMethodLast4: fromPrevPaymentMethods.data[0].card?.last4 ?? null,
paymentMethodType: fromPrevPaymentMethods.data[0].type,
@@ -131,7 +131,7 @@ await Database.transaction(async (tx) => {
.set({
customerID: fromBilling.customerID,
subscriptionID: fromBilling.subscriptionID,
- subscriptionCouponID: fromBilling.subscriptionCouponID,
+ subscription: fromBilling.subscription,
paymentMethodID: fromBilling.paymentMethodID,
paymentMethodLast4: fromBilling.paymentMethodLast4,
paymentMethodType: fromBilling.paymentMethodType,
diff --git a/packages/console/core/script/lookup-user.ts b/packages/console/core/script/lookup-user.ts
index b3a104457..3dc5e7a96 100644
--- a/packages/console/core/script/lookup-user.ts
+++ b/packages/console/core/script/lookup-user.ts
@@ -55,8 +55,9 @@ if (identifier.startsWith("wrk_")) {
),
)
- // Get all payments for these workspaces
- await Promise.all(users.map((u: { workspaceID: string }) => printWorkspace(u.workspaceID)))
+ for (const user of users) {
+ await printWorkspace(user.workspaceID)
+ }
}
async function printWorkspace(workspaceID: string) {
@@ -114,11 +115,11 @@ async function printWorkspace(workspaceID: string) {
balance: BillingTable.balance,
customerID: BillingTable.customerID,
reload: BillingTable.reload,
+ subscriptionID: BillingTable.subscriptionID,
subscription: {
- id: BillingTable.subscriptionID,
- couponID: BillingTable.subscriptionCouponID,
plan: BillingTable.subscriptionPlan,
booked: BillingTable.timeSubscriptionBooked,
+ enrichment: BillingTable.subscription,
},
})
.from(BillingTable)
@@ -128,8 +129,13 @@ async function printWorkspace(workspaceID: string) {
rows.map((row) => ({
...row,
balance: `$${(row.balance / 100000000).toFixed(2)}`,
- subscription: row.subscription.id
- ? `Subscribed ${row.subscription.couponID ? `(coupon: ${row.subscription.couponID}) ` : ""}`
+ subscription: row.subscriptionID
+ ? [
+ `Black ${row.subscription.enrichment!.plan}`,
+ row.subscription.enrichment!.seats > 1 ? `X ${row.subscription.enrichment!.seats} seats` : "",
+ row.subscription.enrichment!.coupon ? `(coupon: ${row.subscription.enrichment!.coupon})` : "",
+ `(ref: ${row.subscriptionID})`,
+ ].join(" ")
: row.subscription.booked
? `Waitlist ${row.subscription.plan} plan`
: undefined,
diff --git a/packages/console/core/src/schema/billing.sql.ts b/packages/console/core/src/schema/billing.sql.ts
index f1300f849..56b2ef33b 100644
--- a/packages/console/core/src/schema/billing.sql.ts
+++ b/packages/console/core/src/schema/billing.sql.ts
@@ -21,16 +21,17 @@ export const BillingTable = mysqlTable(
reloadError: varchar("reload_error", { length: 255 }),
timeReloadError: utc("time_reload_error"),
timeReloadLockedTill: utc("time_reload_locked_till"),
+ subscription: json("subscription").$type<{
+ status: "subscribed"
+ coupon?: string
+ seats: number
+ plan: "20" | "100" | "200"
+ }>(),
subscriptionID: varchar("subscription_id", { length: 28 }),
- subscriptionCouponID: varchar("subscription_coupon_id", { length: 28 }),
subscriptionPlan: mysqlEnum("subscription_plan", ["20", "100", "200"] as const),
timeSubscriptionBooked: utc("time_subscription_booked"),
},
- (table) => [
- ...workspaceIndexes(table),
- uniqueIndex("global_customer_id").on(table.customerID),
- uniqueIndex("global_subscription_id").on(table.subscriptionID),
- ],
+ (table) => [...workspaceIndexes(table), uniqueIndex("global_customer_id").on(table.customerID)],
)
export const SubscriptionTable = mysqlTable(