feat: add image support to the products
CI / build-and-test (push) Canceled after 0s

This commit is contained in:
2026-10-21 12:45:19 +02:00
parent ec77dd0e27
commit 5c604e0851
38 changed files with 1241 additions and 77 deletions
@@ -0,0 +1,28 @@
-- AlterTable
ALTER TABLE "ClientUser" ALTER COLUMN "role" SET DEFAULT 'manager';
-- AlterTable
ALTER TABLE "TabEvent" ADD COLUMN "productData" JSONB;
-- AlterTable
ALTER TABLE "Product" ADD COLUMN "fieldUpdatedAt" JSONB,
ADD COLUMN "imageId" TEXT;
-- CreateTable
CREATE TABLE "ProductImage" (
"id" TEXT NOT NULL,
"contentType" TEXT NOT NULL,
"width" INTEGER NOT NULL,
"height" INTEGER NOT NULL,
"bytes" BYTEA NOT NULL,
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
CONSTRAINT "ProductImage_pkey" PRIMARY KEY ("id")
);
-- AddForeignKey
ALTER TABLE "Product" ADD CONSTRAINT "Product_imageId_fkey" FOREIGN KEY ("imageId") REFERENCES "ProductImage"("id") ON DELETE SET NULL ON UPDATE CASCADE;
-- "viewer" was the name for the people running the venue: they are managers now
UPDATE "ClientUser" SET "role" = 'manager' WHERE "role" = 'viewer';
+23 -1
View File
@@ -59,7 +59,8 @@ model ClientUser {
email String @unique
passwordHash String
name String
role String @default("viewer")
// admin (the owner: users and terminals) | manager (runs the venue: products, stock, tabs, reminders)
role String @default("manager")
createdAt DateTime @default(now())
venue Venue @relation(fields: [venueId], references: [id])
@@ -222,6 +223,8 @@ model TabEvent {
items Json?
// stock_set: the counted stock, null to stop tracking
stockSetTo Int?
// product_created / product_updated: the product's fields as sent by the terminal
productData Json?
occurredAt DateTime
receivedAt DateTime @default(now())
@@ -252,6 +255,12 @@ model Product {
reportedAt DateTime
// Deleted on the dashboard: hidden on the terminals, kept because tabs and history refer to it
archivedAt DateTime?
imageId String?
// When each field was last changed ({ name: ISO date, ... }): a change from the dashboard or an (offline)
// terminal only wins over a later one per field, so edits of different fields never overwrite each other
fieldUpdatedAt Json?
image ProductImage? @relation(fields: [imageId], references: [id])
venue Venue @relation(fields: [venueId], references: [id])
@@ -330,3 +339,16 @@ model Settlement {
@@index([venueId, sequence])
@@index([venueId, settledAt])
}
// A product picture, resized and cropped on upload. The id is the SHA-256 of the stored bytes, so the picture at
// an address never changes and can be cached forever, and the same picture is stored once.
model ProductImage {
id String @id
contentType String
width Int
height Int
bytes Bytes
createdAt DateTime @default(now())
products Product[]
}
+1 -1
View File
@@ -50,7 +50,7 @@ async function main() {
email: 'viewer@example.com',
passwordHash: viewerHash,
name: 'Bartender',
role: 'viewer',
role: 'manager',
},
});
console.log('Created viewer user: viewer@example.com / Viewer123!');