generator client { provider = "prisma-client-js" binaryTargets = ["native", "debian-openssl-3.0.x"] } datasource db { provider = "sqlite" url = env("DATABASE_URL") } model User { id String @id @default(cuid()) email String @unique passwordHash String firstName String lastName String isActive Boolean @default(true) createdAt DateTime @default(now()) updatedAt DateTime @updatedAt userRoles UserRole[] contactEntries CrmContactEntry[] inventoryTransactions InventoryTransaction[] purchaseReceipts PurchaseReceipt[] } model Role { id String @id @default(cuid()) name String @unique description String createdAt DateTime @default(now()) updatedAt DateTime @updatedAt userRoles UserRole[] rolePermissions RolePermission[] } model Permission { id String @id @default(cuid()) key String @unique description String createdAt DateTime @default(now()) updatedAt DateTime @updatedAt rolePermissions RolePermission[] } model UserRole { userId String roleId String assignedAt DateTime @default(now()) assignedBy String? role Role @relation(fields: [roleId], references: [id], onDelete: Cascade) user User @relation(fields: [userId], references: [id], onDelete: Cascade) @@id([userId, roleId]) } model RolePermission { roleId String permissionId String grantedAt DateTime @default(now()) permission Permission @relation(fields: [permissionId], references: [id], onDelete: Cascade) role Role @relation(fields: [roleId], references: [id], onDelete: Cascade) @@id([roleId, permissionId]) } model CompanyProfile { id String @id @default(cuid()) companyName String legalName String email String phone String website String taxId String addressLine1 String addressLine2 String city String state String postalCode String country String primaryColor String @default("#185ADB") accentColor String @default("#00A6A6") surfaceColor String @default("#F4F7FB") fontFamily String @default("Manrope") logoFileId String? @unique isActive Boolean @default(true) createdAt DateTime @default(now()) updatedAt DateTime @updatedAt logoFile FileAttachment? @relation("CompanyLogo", fields: [logoFileId], references: [id], onDelete: SetNull) } model FileAttachment { id String @id @default(cuid()) originalName String storedName String mimeType String sizeBytes Int relativePath String ownerType String ownerId String createdById String? createdAt DateTime @default(now()) updatedAt DateTime @updatedAt companyLogoFor CompanyProfile? @relation("CompanyLogo") } model InventoryItem { id String @id @default(cuid()) sku String @unique name String description String type String status String unitOfMeasure String isSellable Boolean @default(true) isPurchasable Boolean @default(true) defaultCost Float? defaultPrice Float? notes String createdAt DateTime @default(now()) updatedAt DateTime @updatedAt bomLines InventoryBomLine[] @relation("InventoryBomParent") usedInBomLines InventoryBomLine[] @relation("InventoryBomComponent") inventoryTransactions InventoryTransaction[] salesQuoteLines SalesQuoteLine[] salesOrderLines SalesOrderLine[] purchaseOrderLines PurchaseOrderLine[] } model Warehouse { id String @id @default(cuid()) code String @unique name String notes String createdAt DateTime @default(now()) updatedAt DateTime @updatedAt locations WarehouseLocation[] inventoryTransactions InventoryTransaction[] purchaseReceipts PurchaseReceipt[] } model Customer { id String @id @default(cuid()) name String email String phone String addressLine1 String addressLine2 String city String state String postalCode String country String status String @default("ACTIVE") lifecycleStage String @default("ACTIVE") isReseller Boolean @default(false) resellerDiscountPercent Float @default(0) parentCustomerId String? paymentTerms String? currencyCode String? @default("USD") taxExempt Boolean @default(false) creditHold Boolean @default(false) preferredAccount Boolean @default(false) strategicAccount Boolean @default(false) requiresApproval Boolean @default(false) blockedAccount Boolean @default(false) notes String createdAt DateTime @default(now()) updatedAt DateTime @updatedAt contactEntries CrmContactEntry[] contacts CrmContact[] parentCustomer Customer? @relation("CustomerHierarchy", fields: [parentCustomerId], references: [id], onDelete: SetNull) childCustomers Customer[] @relation("CustomerHierarchy") salesQuotes SalesQuote[] salesOrders SalesOrder[] } model InventoryBomLine { id String @id @default(cuid()) parentItemId String componentItemId String quantity Float unitOfMeasure String notes String position Int @default(0) createdAt DateTime @default(now()) updatedAt DateTime @updatedAt parentItem InventoryItem @relation("InventoryBomParent", fields: [parentItemId], references: [id], onDelete: Cascade) componentItem InventoryItem @relation("InventoryBomComponent", fields: [componentItemId], references: [id], onDelete: Restrict) @@index([parentItemId, position]) @@index([componentItemId]) } model WarehouseLocation { id String @id @default(cuid()) warehouseId String code String name String notes String createdAt DateTime @default(now()) updatedAt DateTime @updatedAt warehouse Warehouse @relation(fields: [warehouseId], references: [id], onDelete: Cascade) inventoryTransactions InventoryTransaction[] purchaseReceipts PurchaseReceipt[] @@unique([warehouseId, code]) @@index([warehouseId]) } model InventoryTransaction { id String @id @default(cuid()) itemId String warehouseId String locationId String transactionType String quantity Int reference String notes String createdById String? createdAt DateTime @default(now()) updatedAt DateTime @updatedAt item InventoryItem @relation(fields: [itemId], references: [id], onDelete: Cascade) warehouse Warehouse @relation(fields: [warehouseId], references: [id], onDelete: Restrict) location WarehouseLocation @relation(fields: [locationId], references: [id], onDelete: Restrict) createdBy User? @relation(fields: [createdById], references: [id], onDelete: SetNull) @@index([itemId, createdAt]) @@index([warehouseId, createdAt]) @@index([locationId, createdAt]) } model Vendor { id String @id @default(cuid()) name String email String phone String addressLine1 String addressLine2 String city String state String postalCode String country String status String @default("ACTIVE") lifecycleStage String @default("ACTIVE") paymentTerms String? currencyCode String? @default("USD") taxExempt Boolean @default(false) creditHold Boolean @default(false) preferredAccount Boolean @default(false) strategicAccount Boolean @default(false) requiresApproval Boolean @default(false) blockedAccount Boolean @default(false) notes String createdAt DateTime @default(now()) updatedAt DateTime @updatedAt contactEntries CrmContactEntry[] contacts CrmContact[] purchaseOrders PurchaseOrder[] } model CrmContactEntry { id String @id @default(cuid()) type String @default("NOTE") summary String body String contactAt DateTime customerId String? vendorId String? createdById String? createdAt DateTime @default(now()) updatedAt DateTime @updatedAt customer Customer? @relation(fields: [customerId], references: [id], onDelete: Cascade) vendor Vendor? @relation(fields: [vendorId], references: [id], onDelete: Cascade) createdBy User? @relation(fields: [createdById], references: [id], onDelete: SetNull) } model CrmContact { id String @id @default(cuid()) fullName String role String @default("OTHER") email String phone String isPrimary Boolean @default(false) customerId String? vendorId String? createdAt DateTime @default(now()) updatedAt DateTime @updatedAt customer Customer? @relation(fields: [customerId], references: [id], onDelete: Cascade) vendor Vendor? @relation(fields: [vendorId], references: [id], onDelete: Cascade) } model SalesQuote { id String @id @default(cuid()) documentNumber String @unique customerId String status String issueDate DateTime expiresAt DateTime? discountPercent Float @default(0) taxPercent Float @default(0) freightAmount Float @default(0) notes String createdAt DateTime @default(now()) updatedAt DateTime @updatedAt customer Customer @relation(fields: [customerId], references: [id], onDelete: Restrict) lines SalesQuoteLine[] } model SalesQuoteLine { id String @id @default(cuid()) quoteId String itemId String description String quantity Int unitOfMeasure String unitPrice Float position Int @default(0) createdAt DateTime @default(now()) updatedAt DateTime @updatedAt quote SalesQuote @relation(fields: [quoteId], references: [id], onDelete: Cascade) item InventoryItem @relation(fields: [itemId], references: [id], onDelete: Restrict) @@index([quoteId, position]) } model SalesOrder { id String @id @default(cuid()) documentNumber String @unique customerId String status String issueDate DateTime discountPercent Float @default(0) taxPercent Float @default(0) freightAmount Float @default(0) notes String createdAt DateTime @default(now()) updatedAt DateTime @updatedAt customer Customer @relation(fields: [customerId], references: [id], onDelete: Restrict) lines SalesOrderLine[] shipments Shipment[] } model SalesOrderLine { id String @id @default(cuid()) orderId String itemId String description String quantity Int unitOfMeasure String unitPrice Float position Int @default(0) createdAt DateTime @default(now()) updatedAt DateTime @updatedAt order SalesOrder @relation(fields: [orderId], references: [id], onDelete: Cascade) item InventoryItem @relation(fields: [itemId], references: [id], onDelete: Restrict) @@index([orderId, position]) } model Shipment { id String @id @default(cuid()) shipmentNumber String @unique salesOrderId String status String shipDate DateTime? carrier String serviceLevel String trackingNumber String packageCount Int @default(1) notes String createdAt DateTime @default(now()) updatedAt DateTime @updatedAt salesOrder SalesOrder @relation(fields: [salesOrderId], references: [id], onDelete: Restrict) @@index([salesOrderId, createdAt]) } model PurchaseOrder { id String @id @default(cuid()) documentNumber String @unique vendorId String status String issueDate DateTime taxPercent Float @default(0) freightAmount Float @default(0) notes String createdAt DateTime @default(now()) updatedAt DateTime @updatedAt vendor Vendor @relation(fields: [vendorId], references: [id], onDelete: Restrict) lines PurchaseOrderLine[] receipts PurchaseReceipt[] } model PurchaseOrderLine { id String @id @default(cuid()) purchaseOrderId String itemId String description String quantity Int unitOfMeasure String unitCost Float position Int @default(0) createdAt DateTime @default(now()) updatedAt DateTime @updatedAt purchaseOrder PurchaseOrder @relation(fields: [purchaseOrderId], references: [id], onDelete: Cascade) item InventoryItem @relation(fields: [itemId], references: [id], onDelete: Restrict) receiptLines PurchaseReceiptLine[] @@index([purchaseOrderId, position]) } model PurchaseReceipt { id String @id @default(cuid()) receiptNumber String @unique purchaseOrderId String warehouseId String locationId String receivedAt DateTime notes String createdById String? createdAt DateTime @default(now()) updatedAt DateTime @updatedAt purchaseOrder PurchaseOrder @relation(fields: [purchaseOrderId], references: [id], onDelete: Cascade) warehouse Warehouse @relation(fields: [warehouseId], references: [id], onDelete: Restrict) location WarehouseLocation @relation(fields: [locationId], references: [id], onDelete: Restrict) createdBy User? @relation(fields: [createdById], references: [id], onDelete: SetNull) lines PurchaseReceiptLine[] @@index([purchaseOrderId, createdAt]) @@index([warehouseId, createdAt]) @@index([locationId, createdAt]) } model PurchaseReceiptLine { id String @id @default(cuid()) purchaseReceiptId String purchaseOrderLineId String quantity Int createdAt DateTime @default(now()) updatedAt DateTime @updatedAt purchaseReceipt PurchaseReceipt @relation(fields: [purchaseReceiptId], references: [id], onDelete: Cascade) purchaseOrderLine PurchaseOrderLine @relation(fields: [purchaseOrderLineId], references: [id], onDelete: Restrict) @@index([purchaseReceiptId]) @@index([purchaseOrderLineId]) }