From 96088421baf1e3fcff37fde1b603de680890160c Mon Sep 17 00:00:00 2001 From: toanhoang Date: Sun, 2 Aug 2026 08:54:53 -0400 Subject: [PATCH] feat: add License Prisma model + migration --- .../20260802123955_add_license/migration.sql | 16 ++++++++++ prisma/schema.prisma | 30 +++++++++++++++++++ 2 files changed, 46 insertions(+) create mode 100644 prisma/migrations/20260802123955_add_license/migration.sql diff --git a/prisma/migrations/20260802123955_add_license/migration.sql b/prisma/migrations/20260802123955_add_license/migration.sql new file mode 100644 index 0000000..8c208f0 --- /dev/null +++ b/prisma/migrations/20260802123955_add_license/migration.sql @@ -0,0 +1,16 @@ +-- CreateEnum +CREATE TYPE "LicenseType" AS ENUM ('perpetual', 'subscription'); + +-- CreateTable +CREATE TABLE "licenses" ( + "id" UUID NOT NULL, + "name" TEXT NOT NULL, + "vendor" TEXT NOT NULL, + "seats_total" INTEGER NOT NULL, + "seats_used" INTEGER NOT NULL DEFAULT 0, + "expiry_date" DATE, + "license_type" "LicenseType" NOT NULL, + "created_at" TIMESTAMPTZ(6) NOT NULL DEFAULT CURRENT_TIMESTAMP, + + CONSTRAINT "licenses_pkey" PRIMARY KEY ("id") +); diff --git a/prisma/schema.prisma b/prisma/schema.prisma index c6a5087..63c54fa 100644 --- a/prisma/schema.prisma +++ b/prisma/schema.prisma @@ -92,6 +92,36 @@ model AssetItem { @@map("asset_items") } +// Fixed, closed set of 2 values tied to the domain (see docs/ +// asset-license-management.md's "Data model (sơ bộ)" table) — native +// Postgres enum, same rationale as RequestType/AssetItemStatus above. +enum LicenseType { + perpetual + subscription +} + +// Software license inventory — see docs/asset-license-management.md's "Data +// model (sơ bộ)" table (tên, vendor, tổng seat, seat đã dùng, ngày hết hạn, +// loại). `vendor` is deliberately a plain String for now, not a separate +// Vendor entity — no Vendor entity exists yet, same "plain string for now" +// precedent as Employee.department. `seatsUsed` is a stored counter +// (defaults to 0 at creation), not a computed value — it will only ever be +// set to 0 here since Assignment (the thing that would consume seats) +// doesn't exist yet. `expiryDate` is nullable: perpetual licenses never +// expire, only subscription licenses usually have one. +model License { + id String @id @default(uuid()) @db.Uuid + name String + vendor String + seatsTotal Int @map("seats_total") + seatsUsed Int @default(0) @map("seats_used") + expiryDate DateTime? @map("expiry_date") @db.Date + licenseType LicenseType @map("license_type") + createdAt DateTime @default(now()) @map("created_at") @db.Timestamptz(6) + + @@map("licenses") +} + // Minimal internal auth accounts — NOT company SSO (deliberately ruled out, // see CLAUDE.md / auth decision notes). A handful of trusted IT staff // accounts, created by hand via scripts/create-user.ts, no self-registration.