File size: 2,848 Bytes
116a473
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
import { z } from "zod"
import { and, Database, eq, isNull } from "./drizzle"
import { LiteTable, SubscriptionTable } from "./schema/billing.sql"
import { Identifier } from "./identifier"
import { fn } from "./util/fn"

export namespace Quota {
  // Zero all usage counters of one plan for a workspace, using the same
  // workspace-scoped addressing as unsubscribeLite/unsubscribeBlack and
  // Billing.subtractLiteUsage. Timestamps are left untouched on purpose: a
  // zeroed counter with a current-window stamp reads as empty and the next
  // write accumulates on top of zero, so the active windows stay undisturbed.
  export const reset = fn(
    z.object({
      workspaceID: Identifier.schema("workspace"),
      plan: z.enum(["lite", "subscription"]),
    }),
    async (input) => {
      if (input.plan === "lite") {
        return Database.transaction(async (db) => {
          const where = and(eq(LiteTable.workspaceID, input.workspaceID), isNull(LiteTable.timeDeleted))
          const rows = await db
            .select({
              rollingUsage: LiteTable.rollingUsage,
              weeklyUsage: LiteTable.weeklyUsage,
              monthlyUsage: LiteTable.monthlyUsage,
            })
            .from(LiteTable)
            .where(where)
          if (rows.length === 0) throw new Error("No lite usage counters found for workspace")

          await db.update(LiteTable).set({ rollingUsage: 0, weeklyUsage: 0, monthlyUsage: 0 }).where(where)
          return {
            plan: "lite" as const,
            before: {
              rollingUsage: rows.reduce((sum, row) => sum + (row.rollingUsage ?? 0), 0),
              weeklyUsage: rows.reduce((sum, row) => sum + (row.weeklyUsage ?? 0), 0),
              monthlyUsage: rows.reduce((sum, row) => sum + (row.monthlyUsage ?? 0), 0),
            },
          }
        })
      }
      if (input.plan === "subscription") {
        return Database.transaction(async (db) => {
          const where = and(eq(SubscriptionTable.workspaceID, input.workspaceID), isNull(SubscriptionTable.timeDeleted))
          const rows = await db
            .select({ rollingUsage: SubscriptionTable.rollingUsage, fixedUsage: SubscriptionTable.fixedUsage })
            .from(SubscriptionTable)
            .where(where)
          if (rows.length === 0) throw new Error("No subscription usage counters found for workspace")

          await db.update(SubscriptionTable).set({ rollingUsage: 0, fixedUsage: 0 }).where(where)
          return {
            plan: "subscription" as const,
            before: {
              rollingUsage: rows.reduce((sum, row) => sum + (row.rollingUsage ?? 0), 0),
              fixedUsage: rows.reduce((sum, row) => sum + (row.fixedUsage ?? 0), 0),
            },
          }
        })
      }
      throw new Error(`Unknown plan: ${input.plan}`)
    },
  )
}