From 86caf3b04e56d8cb430150a70a7344d464cb04db Mon Sep 17 00:00:00 2001 From: P J Borowiecki Date: Sun, 7 Jan 2024 22:22:43 +0100 Subject: [PATCH] Define initial data schemas; fix linting errors --- src/actions/inventory/brands.ts | 2 +- src/actions/inventory/units.ts | 2 +- .../forms/inventory/brands/add-brand-form.tsx | 4 +- .../categories/add-category-form.tsx | 10 +- .../forms/inventory/units/add-unit-form.tsx | 10 +- .../forms/warehouses/add-warehouse-form.tsx | 10 +- .../0001_friendly_silver_samurai.sql | 9 + src/db/migrations/0002_spooky_thor.sql | 46 +++ src/db/migrations/meta/0001_snapshot.json | 96 +++++ src/db/migrations/meta/0002_snapshot.json | 328 ++++++++++++++++++ src/db/migrations/meta/_journal.json | 14 + src/db/schema/index.ts | 80 ++++- src/types/index.d.ts | 6 + 13 files changed, 595 insertions(+), 22 deletions(-) create mode 100644 src/db/migrations/0001_friendly_silver_samurai.sql create mode 100644 src/db/migrations/0002_spooky_thor.sql create mode 100644 src/db/migrations/meta/0001_snapshot.json create mode 100644 src/db/migrations/meta/0002_snapshot.json diff --git a/src/actions/inventory/brands.ts b/src/actions/inventory/brands.ts index fa39a7f..bf1f33f 100644 --- a/src/actions/inventory/brands.ts +++ b/src/actions/inventory/brands.ts @@ -3,7 +3,7 @@ import { type brandSchema } from "@/validations/inventory" import type { z } from "zod" -export async function addNewBrand(input: z.infer) { +export async function addBrand(input: z.infer) { console.log(input.name) console.log("Adding brand to the database...") return new Promise((resolve) => { diff --git a/src/actions/inventory/units.ts b/src/actions/inventory/units.ts index aaa004d..e0a0bb6 100644 --- a/src/actions/inventory/units.ts +++ b/src/actions/inventory/units.ts @@ -3,7 +3,7 @@ import type { unitSchema } from "@/validations/inventory" import type { z } from "zod" -export async function addNewUnit(input: z.infer) { +export async function addUnit(input: z.infer) { console.log(input.name, input.abbreviation) console.log("Adding unit to the database...") return new Promise((resolve) => { diff --git a/src/components/forms/inventory/brands/add-brand-form.tsx b/src/components/forms/inventory/brands/add-brand-form.tsx index 701f36d..533eba9 100644 --- a/src/components/forms/inventory/brands/add-brand-form.tsx +++ b/src/components/forms/inventory/brands/add-brand-form.tsx @@ -3,7 +3,7 @@ import React from "react" import Link from "next/link" import { useRouter } from "next/navigation" -import { addNewBrand } from "@/actions/inventory/brands" +import { addBrand } from "@/actions/inventory/brands" import { brandSchema } from "@/validations/inventory" import { zodResolver } from "@hookform/resolvers/zod" import { useForm } from "react-hook-form" @@ -40,7 +40,7 @@ export function AddBrandForm(): JSX.Element { function onSubmit(formData: AddBrandFormInputs) { startTransition(async () => { try { - const response = await addNewBrand(formData) + const response = await addBrand(formData) if (response === "success") { toast({ title: "Success!", description: "New category added" }) diff --git a/src/components/forms/inventory/categories/add-category-form.tsx b/src/components/forms/inventory/categories/add-category-form.tsx index 475aa72..16e6280 100644 --- a/src/components/forms/inventory/categories/add-category-form.tsx +++ b/src/components/forms/inventory/categories/add-category-form.tsx @@ -3,8 +3,8 @@ import React from "react" import Link from "next/link" import { useRouter } from "next/navigation" -import { addNewCategory } from "@/actions/inventory/categories" -import { addCategorySchema } from "@/validations/inventory" +import { addCategory } from "@/actions/inventory/categories" +import { categorySchema } from "@/validations/inventory" import { zodResolver } from "@hookform/resolvers/zod" import { useForm } from "react-hook-form" import type { z } from "zod" @@ -24,7 +24,7 @@ import { Input } from "@/components/ui/input" import { Textarea } from "@/components/ui/textarea" import { Icons } from "@/components/icons" -type AddCategoryFormInputs = z.infer +type AddCategoryFormInputs = z.infer export function AddCategoryForm(): JSX.Element { const { toast } = useToast() @@ -32,7 +32,7 @@ export function AddCategoryForm(): JSX.Element { const [isPending, startTransition] = React.useTransition() const form = useForm({ - resolver: zodResolver(addCategorySchema), + resolver: zodResolver(categorySchema), defaultValues: { name: "", description: "", @@ -42,7 +42,7 @@ export function AddCategoryForm(): JSX.Element { function onSubmit(formData: AddCategoryFormInputs) { startTransition(async () => { try { - const response = await addNewCategory({ + const response = await addCategory({ name: formData.name, description: formData.description, }) diff --git a/src/components/forms/inventory/units/add-unit-form.tsx b/src/components/forms/inventory/units/add-unit-form.tsx index 9ac4eff..53c897e 100644 --- a/src/components/forms/inventory/units/add-unit-form.tsx +++ b/src/components/forms/inventory/units/add-unit-form.tsx @@ -3,8 +3,8 @@ import React from "react" import Link from "next/link" import { useRouter } from "next/navigation" -import { addNewUnit } from "@/actions/inventory/units" -import { addUnitSchema } from "@/validations/inventory" +import { addUnit } from "@/actions/inventory/units" +import { unitSchema } from "@/validations/inventory" import { zodResolver } from "@hookform/resolvers/zod" import { useForm } from "react-hook-form" import type { z } from "zod" @@ -23,7 +23,7 @@ import { import { Input } from "@/components/ui/input" import { Icons } from "@/components/icons" -type AddUnitFormInputs = z.infer +type AddUnitFormInputs = z.infer export function AddUnitForm(): JSX.Element { const { toast } = useToast() @@ -31,7 +31,7 @@ export function AddUnitForm(): JSX.Element { const [isPending, startTransition] = React.useTransition() const form = useForm({ - resolver: zodResolver(addUnitSchema), + resolver: zodResolver(unitSchema), defaultValues: { name: "", abbreviation: "", @@ -41,7 +41,7 @@ export function AddUnitForm(): JSX.Element { function onSubmit(formData: AddUnitFormInputs) { startTransition(async () => { try { - const response = await addNewUnit({ + const response = await addUnit({ name: formData.name, abbreviation: formData.abbreviation, }) diff --git a/src/components/forms/warehouses/add-warehouse-form.tsx b/src/components/forms/warehouses/add-warehouse-form.tsx index 6270cf5..c875dfb 100644 --- a/src/components/forms/warehouses/add-warehouse-form.tsx +++ b/src/components/forms/warehouses/add-warehouse-form.tsx @@ -3,8 +3,8 @@ import React from "react" import Link from "next/link" import { useRouter } from "next/navigation" -import { addNewWarehouse } from "@/actions/warehouses" -import { addWarehouseSchema } from "@/validations/warehouses" +import { addWarehouse } from "@/actions/warehouses" +import { warehouseSchema } from "@/validations/warehouses" import { zodResolver } from "@hookform/resolvers/zod" import { useForm } from "react-hook-form" import type { z } from "zod" @@ -32,7 +32,7 @@ import { import { Textarea } from "@/components/ui/textarea" import { Icons } from "@/components/icons" -type AddWarehouseFormInputs = z.infer +type AddWarehouseFormInputs = z.infer export function AddWarehouseForm(): JSX.Element { const { toast } = useToast() @@ -40,7 +40,7 @@ export function AddWarehouseForm(): JSX.Element { const [isPending, startTransition] = React.useTransition() const form = useForm({ - resolver: zodResolver(addWarehouseSchema), + resolver: zodResolver(warehouseSchema), defaultValues: { name: "", type: "branch", @@ -52,7 +52,7 @@ export function AddWarehouseForm(): JSX.Element { function onSubmit(formData: AddWarehouseFormInputs) { startTransition(async () => { try { - const response = await addNewWarehouse(formData) + const response = await addWarehouse(formData) if (response === "success") { toast({ title: "Success!", description: "New category added" }) diff --git a/src/db/migrations/0001_friendly_silver_samurai.sql b/src/db/migrations/0001_friendly_silver_samurai.sql new file mode 100644 index 0000000..7e0f5b9 --- /dev/null +++ b/src/db/migrations/0001_friendly_silver_samurai.sql @@ -0,0 +1,9 @@ +ALTER TABLE "items" ADD COLUMN "category" varchar(63) NOT NULL;--> statement-breakpoint +ALTER TABLE "items" ADD COLUMN "brand" varchar(63) NOT NULL;--> statement-breakpoint +ALTER TABLE "items" ADD COLUMN "barcode" varchar(63) NOT NULL;--> statement-breakpoint +ALTER TABLE "items" ADD COLUMN "description" text;--> statement-breakpoint +ALTER TABLE "items" ADD COLUMN "selling_price" numeric(10, 2) DEFAULT '0' NOT NULL;--> statement-breakpoint +ALTER TABLE "items" ADD COLUMN "purchase_price" numeric(10, 2) DEFAULT '0' NOT NULL;--> statement-breakpoint +ALTER TABLE "items" ADD COLUMN "images" json DEFAULT 'null'::json;--> statement-breakpoint +ALTER TABLE "items" ADD COLUMN "created_at" timestamp DEFAULT now() NOT NULL;--> statement-breakpoint +ALTER TABLE "items" ADD COLUMN "updated_at" timestamp DEFAULT now(); \ No newline at end of file diff --git a/src/db/migrations/0002_spooky_thor.sql b/src/db/migrations/0002_spooky_thor.sql new file mode 100644 index 0000000..cc478bb --- /dev/null +++ b/src/db/migrations/0002_spooky_thor.sql @@ -0,0 +1,46 @@ +CREATE TABLE IF NOT EXISTS "brands" ( + "id" serial PRIMARY KEY NOT NULL, + "name" varchar(32) NOT NULL, + CONSTRAINT "brands_name_unique" UNIQUE("name") +); +--> statement-breakpoint +CREATE TABLE IF NOT EXISTS "categories" ( + "id" serial PRIMARY KEY NOT NULL, + "name" varchar(32) NOT NULL, + "description" text, + CONSTRAINT "categories_name_unique" UNIQUE("name") +); +--> statement-breakpoint +CREATE TABLE IF NOT EXISTS "units" ( + "id" serial PRIMARY KEY NOT NULL, + "name" varchar(24) NOT NULL, + "abbreviation" varchar(8) NOT NULL, + CONSTRAINT "units_name_unique" UNIQUE("name"), + CONSTRAINT "units_abbreviation_unique" UNIQUE("abbreviation") +); +--> statement-breakpoint +CREATE TABLE IF NOT EXISTS "warehouses" ( + "id" serial PRIMARY KEY NOT NULL, + "name" varchar(32) NOT NULL, + "type" varchar(32) NOT NULL, + "description" text, + "location" varchar(32) NOT NULL +); +--> statement-breakpoint +ALTER TABLE "items" ALTER COLUMN "name" SET DATA TYPE varchar(128);--> statement-breakpoint +ALTER TABLE "items" ALTER COLUMN "category" SET DATA TYPE varchar(64);--> statement-breakpoint +ALTER TABLE "items" ALTER COLUMN "brand" SET DATA TYPE varchar(64);--> statement-breakpoint +ALTER TABLE "items" ALTER COLUMN "barcode" SET DATA TYPE varchar(64);--> statement-breakpoint +ALTER TABLE "items" ADD COLUMN "tax_rate" numeric(3, 1) DEFAULT '0' NOT NULL;--> statement-breakpoint +ALTER TABLE "items" ADD COLUMN "width" numeric(10, 2) DEFAULT '0' NOT NULL;--> statement-breakpoint +ALTER TABLE "items" ADD COLUMN "height" numeric(10, 2) DEFAULT '0' NOT NULL;--> statement-breakpoint +ALTER TABLE "items" ADD COLUMN "depth" numeric(10, 2) DEFAULT '0' NOT NULL;--> statement-breakpoint +ALTER TABLE "items" ADD COLUMN "dimensions_unit" varchar(8) NOT NULL;--> statement-breakpoint +ALTER TABLE "items" ADD COLUMN "weight" numeric(10, 2) DEFAULT '0' NOT NULL;--> statement-breakpoint +ALTER TABLE "items" ADD COLUMN "warehouse" varchar NOT NULL;--> statement-breakpoint +ALTER TABLE "items" ADD COLUMN "sku" varchar(128) NOT NULL;--> statement-breakpoint +ALTER TABLE "items" ADD COLUMN "quantity" integer NOT NULL;--> statement-breakpoint +ALTER TABLE "items" ADD COLUMN "unit" varchar(8) NOT NULL;--> statement-breakpoint +ALTER TABLE "items" ADD COLUMN "reorder_point" integer NOT NULL;--> statement-breakpoint +ALTER TABLE "items" ADD COLUMN "supplier" varchar(64) NOT NULL;--> statement-breakpoint +ALTER TABLE "items" ADD COLUMN "notes" text; \ No newline at end of file diff --git a/src/db/migrations/meta/0001_snapshot.json b/src/db/migrations/meta/0001_snapshot.json new file mode 100644 index 0000000..a78ebc2 --- /dev/null +++ b/src/db/migrations/meta/0001_snapshot.json @@ -0,0 +1,96 @@ +{ + "id": "c94e65e8-8faf-4c7e-90ea-9b7040f619f1", + "prevId": "354d536f-c455-42b5-be06-72c96dbab27f", + "version": "5", + "dialect": "pg", + "tables": { + "items": { + "name": "items", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "serial", + "primaryKey": true, + "notNull": true + }, + "name": { + "name": "name", + "type": "varchar(127)", + "primaryKey": false, + "notNull": true + }, + "category": { + "name": "category", + "type": "varchar(63)", + "primaryKey": false, + "notNull": true + }, + "brand": { + "name": "brand", + "type": "varchar(63)", + "primaryKey": false, + "notNull": true + }, + "barcode": { + "name": "barcode", + "type": "varchar(63)", + "primaryKey": false, + "notNull": true + }, + "description": { + "name": "description", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "selling_price": { + "name": "selling_price", + "type": "numeric(10, 2)", + "primaryKey": false, + "notNull": true, + "default": "'0'" + }, + "purchase_price": { + "name": "purchase_price", + "type": "numeric(10, 2)", + "primaryKey": false, + "notNull": true, + "default": "'0'" + }, + "images": { + "name": "images", + "type": "json", + "primaryKey": false, + "notNull": false, + "default": "'null'::json" + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + } + }, + "enums": {}, + "schemas": {}, + "_meta": { + "columns": {}, + "schemas": {}, + "tables": {} + } +} \ No newline at end of file diff --git a/src/db/migrations/meta/0002_snapshot.json b/src/db/migrations/meta/0002_snapshot.json new file mode 100644 index 0000000..c0ac830 --- /dev/null +++ b/src/db/migrations/meta/0002_snapshot.json @@ -0,0 +1,328 @@ +{ + "id": "d7315751-eb8a-4006-8f84-8384c0be4b38", + "prevId": "c94e65e8-8faf-4c7e-90ea-9b7040f619f1", + "version": "5", + "dialect": "pg", + "tables": { + "brands": { + "name": "brands", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "serial", + "primaryKey": true, + "notNull": true + }, + "name": { + "name": "name", + "type": "varchar(32)", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "brands_name_unique": { + "name": "brands_name_unique", + "nullsNotDistinct": false, + "columns": [ + "name" + ] + } + } + }, + "categories": { + "name": "categories", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "serial", + "primaryKey": true, + "notNull": true + }, + "name": { + "name": "name", + "type": "varchar(32)", + "primaryKey": false, + "notNull": true + }, + "description": { + "name": "description", + "type": "text", + "primaryKey": false, + "notNull": false + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "categories_name_unique": { + "name": "categories_name_unique", + "nullsNotDistinct": false, + "columns": [ + "name" + ] + } + } + }, + "items": { + "name": "items", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "serial", + "primaryKey": true, + "notNull": true + }, + "name": { + "name": "name", + "type": "varchar(128)", + "primaryKey": false, + "notNull": true + }, + "category": { + "name": "category", + "type": "varchar(64)", + "primaryKey": false, + "notNull": true + }, + "brand": { + "name": "brand", + "type": "varchar(64)", + "primaryKey": false, + "notNull": true + }, + "barcode": { + "name": "barcode", + "type": "varchar(64)", + "primaryKey": false, + "notNull": true + }, + "description": { + "name": "description", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "selling_price": { + "name": "selling_price", + "type": "numeric(10, 2)", + "primaryKey": false, + "notNull": true, + "default": "'0'" + }, + "purchase_price": { + "name": "purchase_price", + "type": "numeric(10, 2)", + "primaryKey": false, + "notNull": true, + "default": "'0'" + }, + "tax_rate": { + "name": "tax_rate", + "type": "numeric(3, 1)", + "primaryKey": false, + "notNull": true, + "default": "'0'" + }, + "width": { + "name": "width", + "type": "numeric(10, 2)", + "primaryKey": false, + "notNull": true, + "default": "'0'" + }, + "height": { + "name": "height", + "type": "numeric(10, 2)", + "primaryKey": false, + "notNull": true, + "default": "'0'" + }, + "depth": { + "name": "depth", + "type": "numeric(10, 2)", + "primaryKey": false, + "notNull": true, + "default": "'0'" + }, + "dimensions_unit": { + "name": "dimensions_unit", + "type": "varchar(8)", + "primaryKey": false, + "notNull": true + }, + "weight": { + "name": "weight", + "type": "numeric(10, 2)", + "primaryKey": false, + "notNull": true, + "default": "'0'" + }, + "warehouse": { + "name": "warehouse", + "type": "varchar", + "primaryKey": false, + "notNull": true + }, + "sku": { + "name": "sku", + "type": "varchar(128)", + "primaryKey": false, + "notNull": true + }, + "quantity": { + "name": "quantity", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "unit": { + "name": "unit", + "type": "varchar(8)", + "primaryKey": false, + "notNull": true + }, + "reorder_point": { + "name": "reorder_point", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "supplier": { + "name": "supplier", + "type": "varchar(64)", + "primaryKey": false, + "notNull": true + }, + "notes": { + "name": "notes", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "images": { + "name": "images", + "type": "json", + "primaryKey": false, + "notNull": false, + "default": "'null'::json" + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "units": { + "name": "units", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "serial", + "primaryKey": true, + "notNull": true + }, + "name": { + "name": "name", + "type": "varchar(24)", + "primaryKey": false, + "notNull": true + }, + "abbreviation": { + "name": "abbreviation", + "type": "varchar(8)", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "units_name_unique": { + "name": "units_name_unique", + "nullsNotDistinct": false, + "columns": [ + "name" + ] + }, + "units_abbreviation_unique": { + "name": "units_abbreviation_unique", + "nullsNotDistinct": false, + "columns": [ + "abbreviation" + ] + } + } + }, + "warehouses": { + "name": "warehouses", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "serial", + "primaryKey": true, + "notNull": true + }, + "name": { + "name": "name", + "type": "varchar(32)", + "primaryKey": false, + "notNull": true + }, + "type": { + "name": "type", + "type": "varchar(32)", + "primaryKey": false, + "notNull": true + }, + "description": { + "name": "description", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "location": { + "name": "location", + "type": "varchar(32)", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + } + }, + "enums": {}, + "schemas": {}, + "_meta": { + "columns": {}, + "schemas": {}, + "tables": {} + } +} \ No newline at end of file diff --git a/src/db/migrations/meta/_journal.json b/src/db/migrations/meta/_journal.json index 9568211..08bdfa0 100644 --- a/src/db/migrations/meta/_journal.json +++ b/src/db/migrations/meta/_journal.json @@ -8,6 +8,20 @@ "when": 1704658376355, "tag": "0000_last_kang", "breakpoints": true + }, + { + "idx": 1, + "version": "5", + "when": 1704659926968, + "tag": "0001_friendly_silver_samurai", + "breakpoints": true + }, + { + "idx": 2, + "version": "5", + "when": 1704662521906, + "tag": "0002_spooky_thor", + "breakpoints": true } ] } \ No newline at end of file diff --git a/src/db/schema/index.ts b/src/db/schema/index.ts index 4ad30d6..a3584ad 100644 --- a/src/db/schema/index.ts +++ b/src/db/schema/index.ts @@ -1,18 +1,92 @@ -import { relations } from "drizzle-orm" +import { type StoredFile } from "@/types" import { + decimal, integer, + json, pgTable, - primaryKey, serial, text, timestamp, varchar, } from "drizzle-orm/pg-core" +export const warehouses = pgTable("warehouses", { + id: serial("id").primaryKey(), + name: varchar("name", { length: 32 }).notNull(), + type: varchar("type", { length: 32 }).notNull(), + description: text("description"), + location: varchar("location", { length: 32 }).notNull(), +}) + +export const categories = pgTable("categories", { + id: serial("id").primaryKey(), + name: varchar("name", { length: 32 }).unique().notNull(), + description: text("description"), +}) + +export const brands = pgTable("brands", { + id: serial("id").primaryKey(), + name: varchar("name", { length: 32 }).unique().notNull(), +}) + export const items = pgTable("items", { id: serial("id").primaryKey(), - name: varchar("name", { length: 127 }).notNull(), + name: varchar("name", { length: 128 }).notNull(), + // TODO: Link to category id, define relations + category: varchar("category", { length: 64 }).notNull(), + // TODO: Link to brand id, define relations + brand: varchar("brand", { length: 64 }).notNull(), + barcode: varchar("barcode", { length: 64 }).notNull(), + description: text("description"), + sellingPrice: decimal("selling_price", { precision: 10, scale: 2 }) + .notNull() + .default("0"), + purchasePrice: decimal("purchase_price", { precision: 10, scale: 2 }) + .notNull() + .default("0"), + taxRate: decimal("tax_rate", { precision: 3, scale: 1 }) + .notNull() + .default("0"), + width: decimal("width", { precision: 10, scale: 2 }).notNull().default("0"), + height: decimal("height", { precision: 10, scale: 2 }).notNull().default("0"), + depth: decimal("depth", { precision: 10, scale: 2 }).notNull().default("0"), + // TODO: Link to unit id, define relations + dimensionsUnit: varchar("dimensions_unit", { length: 8 }).notNull(), + weight: decimal("weight", { precision: 10, scale: 2 }).notNull().default("0"), + // TODO: Link to unit id, define relations + weightUnit: varchar("dimensions_unit", { length: 8 }).notNull(), + // TODO: Link to warehouse id, define relations + warehouse: varchar("warehouse").notNull(), + sku: varchar("sku", { length: 128 }).notNull(), + quantity: integer("quantity").notNull(), + // TODO: Link to unit id, define relations + unit: varchar("unit", { length: 8 }).notNull(), + reorderPoint: integer("reorder_point").notNull(), + // TODO: Possibly add suppliers table, link id, define relations + supplier: varchar("supplier", { length: 64 }).notNull(), + notes: text("notes"), + images: json("images").$type().default(null), + createdAt: timestamp("created_at", { mode: "date" }).defaultNow().notNull(), + updatedAt: timestamp("updated_at", { mode: "date" }).defaultNow(), +}) + +export const units = pgTable("units", { + id: serial("id").primaryKey(), + name: varchar("name", { length: 24 }).unique().notNull(), + abbreviation: varchar("abbreviation", { length: 8 }).notNull().unique(), }) +export type Warehouse = typeof warehouses.$inferSelect +export type NewWarehouse = typeof warehouses.$inferInsert + +export type Category = typeof categories.$inferSelect +export type NewCategory = typeof categories.$inferInsert + +export type Brand = typeof brands.$inferSelect +export type NewBrand = typeof brands.$inferInsert + export type Item = typeof items.$inferSelect export type NewItem = typeof items.$inferInsert + +export type Unit = typeof units.$inferSelect +export type NewUnit = typeof units.$inferInsert diff --git a/src/types/index.d.ts b/src/types/index.d.ts index 24d9c87..307b5b5 100644 --- a/src/types/index.d.ts +++ b/src/types/index.d.ts @@ -55,3 +55,9 @@ export interface SettingsOption { export type FileWithPreview = FileWithPath & { preview: string } + +export interface StoredFile { + id: string + name: string + url: string +}