@machynx/data-db 1.0.5 → 1.0.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,19 +1,58 @@
1
- // ----------------------------------------------------------------------
2
- // HOURLY (HOT DATA)
3
- // ----------------------------------------------------------------------
1
+ enum ProductionMeasurementUnit {
2
+ PIECE
3
+ PART
4
+ UNIT
5
+ ASSEMBLY
6
+ BATCH
7
+ LOT
8
+ KG
9
+ LITERS
10
+ METERS
11
+ GRAMS
12
+ TONS
13
+ HOURS
14
+ CYCLES
15
+ }
16
+
4
17
  model MachineHourlyAnalytics {
5
18
  id BigInt @id @default(autoincrement()) @db.BigInt
6
19
  machineId Int
7
20
  organizationId Int
8
21
 
9
- totalProductionCount Int?
10
- efficiency Float?
11
- utilization Float?
12
- totalPowerConsumed Float?
13
- idleTime Float?
14
- nonWorkingTime Float?
15
- upTime Float?
16
- productiveTime Float?
22
+ totalProduction Float?
23
+ productionUnit ProductionMeasurementUnit?
24
+ passedProduction Float?
25
+ rejectedProduction Float?
26
+ reworkProduction Float?
27
+ wasteProduction Float?
28
+
29
+ efficiency Float?
30
+ utilization Float?
31
+ availability Float?
32
+ performance Float?
33
+ quality Float?
34
+ oee Float?
35
+
36
+ totalPowerConsumed Float?
37
+
38
+ runningTime Float?
39
+ idleTime Float?
40
+ stoppedTime Float?
41
+ alarmTime Float?
42
+ setupTime Float?
43
+ maintenanceTime Float?
44
+ nonWorkingTime Float?
45
+ upTime Float?
46
+ productiveTime Float?
47
+
48
+ cycleCount Int?
49
+ avgCycleTime Float?
50
+ minCycleTime Float?
51
+ maxCycleTime Float?
52
+
53
+ expectedYield Float?
54
+ actualYield Float?
55
+ lossPercentage Float?
17
56
 
18
57
  startDateTime DateTime?
19
58
  endDateTime DateTime?
@@ -26,26 +65,28 @@ model MachineHourlyAnalytics {
26
65
 
27
66
  @@unique([organizationId, machineId, startDateTime], map: "unique_machineHourlyCompound")
28
67
  @@index([machineId, startDateTime])
29
- @@index([organizationId, startDateTime]) // For org-wide queries
30
- @@index([machineId, startDateTime, endDateTime]) // For range scans
31
- @@schema("analytics")
68
+ @@index([organizationId, startDateTime])
69
+ @@index([machineId, startDateTime, endDateTime])
32
70
  }
33
71
 
34
- // ----------------------------------------------------------------------
35
- // DAILY (WARM DATA - 2 to 5 Years)
36
- // ----------------------------------------------------------------------
37
72
  model MachineDailyAnalytics {
38
73
  id BigInt @id @default(autoincrement()) @db.BigInt
39
74
  machineId Int
40
75
  organizationId Int
41
76
 
42
- totalProductionCount Int?
43
- avgEfficiency Float?
44
- avgUtilization Float?
45
- totalPowerConsumed Float?
46
- totalUpTime Float?
77
+ totalProduction Float?
78
+ productionUnit ProductionMeasurementUnit?
79
+ passedProduction Float?
80
+ rejectedProduction Float?
81
+ reworkProduction Float?
82
+ wasteProduction Float?
83
+
84
+ avgEfficiency Float?
85
+ avgUtilization Float?
86
+ totalPowerConsumed Float?
87
+ totalUpTime Float?
47
88
 
48
- date DateTime @db.Date // YYYY-MM-DD
89
+ date DateTime @db.Date
49
90
 
50
91
  machine Machine @relation("MachineToDailyAnalytics", fields: [machineId], references: [id])
51
92
 
@@ -54,20 +95,22 @@ model MachineDailyAnalytics {
54
95
 
55
96
  @@unique([organizationId, machineId, date], map: "unique_machineDailyCompound")
56
97
  @@index([machineId, date])
57
- @@schema("analytics")
58
98
  }
59
99
 
60
- // ----------------------------------------------------------------------
61
- // MONTHLY (COLD DATA - Forever)
62
- // ----------------------------------------------------------------------
63
100
  model MachineMonthlyAnalytics {
64
101
  id BigInt @id @default(autoincrement()) @db.BigInt
65
102
  machineId Int
66
103
  organizationId Int
67
104
 
68
- totalProductionCount BigInt?
69
- avgEfficiency Float?
70
- totalPowerConsumed Float?
105
+ totalProduction Float?
106
+ productionUnit ProductionMeasurementUnit?
107
+ passedProduction Float?
108
+ rejectedProduction Float?
109
+ reworkProduction Float?
110
+ wasteProduction Float?
111
+
112
+ avgEfficiency Float?
113
+ totalPowerConsumed Float?
71
114
 
72
115
  month Int
73
116
  year Int
@@ -78,21 +121,18 @@ model MachineMonthlyAnalytics {
78
121
  updatedAt DateTime @updatedAt
79
122
 
80
123
  @@unique([organizationId, machineId, month, year], map: "unique_machineMonthlyCompound")
81
- @@schema("analytics")
82
124
  }
83
125
 
84
- // ----------------------------------------------------------------------
85
- // OTHER ENTITIES (Hourly is usually sufficient for these)
86
- // ----------------------------------------------------------------------
87
-
88
126
  model LineHourlyAnalytics {
89
127
  id BigInt @id @default(autoincrement()) @db.BigInt
90
128
  assemblyLineId Int
91
129
  organizationId Int
92
130
 
93
- averageEfficiency Float?
94
- averageUtilization Float?
95
- totalProductionCount Int?
131
+ averageEfficiency Float?
132
+ averageUtilization Float?
133
+
134
+ totalProduction Float?
135
+ productionUnit ProductionMeasurementUnit?
96
136
 
97
137
  startDateTime DateTime?
98
138
  endDateTime DateTime?
@@ -102,7 +142,6 @@ model LineHourlyAnalytics {
102
142
  updatedAt DateTime @updatedAt
103
143
 
104
144
  @@unique([organizationId, assemblyLineId, startDateTime], map: "unique_lineHourlyCompound")
105
- @@schema("analytics")
106
145
  }
107
146
 
108
147
  model FloorHourlyAnalytics {
@@ -110,8 +149,10 @@ model FloorHourlyAnalytics {
110
149
  floorId Int
111
150
  organizationId Int
112
151
 
113
- averageEfficiency Float?
114
- totalProductionCount Int?
152
+ averageEfficiency Float?
153
+
154
+ totalProduction Float?
155
+ productionUnit ProductionMeasurementUnit?
115
156
 
116
157
  startDateTime DateTime?
117
158
  endDateTime DateTime?
@@ -121,7 +162,6 @@ model FloorHourlyAnalytics {
121
162
  updatedAt DateTime @updatedAt
122
163
 
123
164
  @@unique([organizationId, floorId, startDateTime], map: "unique_floorHourlyCompound")
124
- @@schema("analytics")
125
165
  }
126
166
 
127
167
  model FactoryHourlyAnalytics {
@@ -129,8 +169,10 @@ model FactoryHourlyAnalytics {
129
169
  factoryId Int
130
170
  organizationId Int
131
171
 
132
- averageEfficiency Float?
133
- totalProductionCount Int?
172
+ averageEfficiency Float?
173
+
174
+ totalProduction Float?
175
+ productionUnit ProductionMeasurementUnit?
134
176
 
135
177
  startDateTime DateTime?
136
178
  endDateTime DateTime?
@@ -140,13 +182,12 @@ model FactoryHourlyAnalytics {
140
182
  updatedAt DateTime @updatedAt
141
183
 
142
184
  @@unique([organizationId, factoryId, startDateTime], map: "unique_factoryHourlyCompound")
143
- @@schema("analytics")
144
185
  }
145
186
 
146
187
  model DeviceHourlyAnalytics {
147
188
  id BigInt @id @default(autoincrement()) @db.BigInt
148
189
  deviceId Int
149
- machineHourlyAnalyticsId BigInt? // Optional if device is not attached to machine
190
+ machineHourlyAnalyticsId BigInt?
150
191
  organizationId Int
151
192
 
152
193
  totalOnTime Float?
@@ -165,7 +206,6 @@ model DeviceHourlyAnalytics {
165
206
  updatedAt DateTime @updatedAt
166
207
 
167
208
  @@unique([organizationId, deviceId, startDateTime], map: "unique_deviceHourlyCompound")
168
- @@schema("analytics")
169
209
  }
170
210
 
171
211
  model SensorHourlyAnalytics {
@@ -181,14 +221,19 @@ model SensorHourlyAnalytics {
181
221
  sensor Sensor @relation("SensorHourlyAnalytics_Sensor", fields: [sensorId], references: [id])
182
222
  deviceHourlyAnalytics DeviceHourlyAnalytics @relation("DeviceHourlyAnalytics_SensorHourlyAnalytics", fields: [deviceHourlyAnalyticsId], references: [id])
183
223
 
184
- proximitySensorHourlyAnalytics ProximitySensorHourlyAnalytics?
185
- infraredSensorHourlyAnalytics InfraredSensorHourlyAnalytics?
224
+ proximitySensorHourlyAnalytics ProximitySensorHourlyAnalytics?
225
+ infraredSensorHourlyAnalytics InfraredSensorHourlyAnalytics?
226
+ currentSensorHourlyAnalytics CurrentSensorHourlyAnalytics?
227
+ vibrationSensorHourlyAnalytics VibrationSensorHourlyAnalytics?
228
+ temperatureSensorHourlyAnalytics TemperatureSensorHourlyAnalytics?
229
+ flowSensorHourlyAnalytics FlowSensorHourlyAnalytics?
230
+ weightSensorHourlyAnalytics WeightSensorHourlyAnalytics?
231
+ pressureSensorHourlyAnalytics PressureSensorHourlyAnalytics?
186
232
 
187
233
  createdAt DateTime @default(now())
188
234
  updatedAt DateTime @updatedAt
189
235
 
190
236
  @@unique([sensorId, startDateTime], map: "unique_sensorHourlyCompound")
191
- @@schema("analytics")
192
237
  }
193
238
 
194
239
  model ProximitySensorHourlyAnalytics {
@@ -202,8 +247,6 @@ model ProximitySensorHourlyAnalytics {
202
247
  endDateTime DateTime?
203
248
  createdAt DateTime @default(now())
204
249
  updatedAt DateTime @updatedAt
205
-
206
- @@schema("analytics")
207
250
  }
208
251
 
209
252
  model InfraredSensorHourlyAnalytics {
@@ -217,8 +260,6 @@ model InfraredSensorHourlyAnalytics {
217
260
  endDateTime DateTime?
218
261
  createdAt DateTime @default(now())
219
262
  updatedAt DateTime @updatedAt
220
-
221
- @@schema("analytics")
222
263
  }
223
264
 
224
265
  model DevicePowerSensorHourlyAnalytics {
@@ -233,77 +274,1859 @@ model DevicePowerSensorHourlyAnalytics {
233
274
  deviceHourlyAnalytics DeviceHourlyAnalytics @relation("DevicePowerRelation", fields: [deviceHourlyAnalyticsId], references: [id])
234
275
  createdAt DateTime @default(now())
235
276
  updatedAt DateTime @updatedAt
236
-
237
- @@schema("analytics")
238
277
  }
239
278
 
240
- // ----------------------------------------------------------------------
241
- // SCHEMA: audit
242
- // ----------------------------------------------------------------------
279
+ model ProtocolDataSourceHourlyAnalytics {
280
+ id BigInt @id @default(autoincrement()) @db.BigInt
281
+ dataSourceId Int
282
+
283
+ dataSource ProtocolDataSource @relation("ProtocolDataSourceAnalytics", fields: [dataSourceId], references: [id])
284
+
285
+ totalSamples Int?
286
+ successfulReads Int?
287
+ failedReads Int?
288
+ avgValue Float?
289
+ minValue Float?
290
+ maxValue Float?
291
+ stdDev Float?
292
+
293
+ avgResponseTimeMs Float?
294
+ timeouts Int?
295
+ crcErrors Int?
296
+
297
+ startDateTime DateTime?
298
+ endDateTime DateTime?
299
+
300
+ createdAt DateTime @default(now())
301
+ updatedAt DateTime @updatedAt
302
+
303
+ @@unique([dataSourceId, startDateTime])
304
+ @@index([dataSourceId, startDateTime, endDateTime])
305
+ }
306
+
307
+ model CurrentSensorHourlyAnalytics {
308
+ id BigInt @id @default(autoincrement()) @db.BigInt
309
+ sensorHourlyAnalyticsId BigInt @unique
310
+ avgCurrent Float?
311
+ maxCurrent Float?
312
+ minCurrent Float?
313
+ runTime Float?
314
+ idleTime Float?
315
+ sensorHourlyAnalytics SensorHourlyAnalytics @relation(fields: [sensorHourlyAnalyticsId], references: [id])
316
+ startDateTime DateTime?
317
+ endDateTime DateTime?
318
+ createdAt DateTime @default(now())
319
+ updatedAt DateTime @updatedAt
320
+ }
321
+
322
+ model VibrationSensorHourlyAnalytics {
323
+ id BigInt @id @default(autoincrement()) @db.BigInt
324
+ sensorHourlyAnalyticsId BigInt @unique
325
+ avgRMS Float?
326
+ maxRMS Float?
327
+ dominantFrequency Float?
328
+ healthScore Float?
329
+ alertCount Int?
330
+ sensorHourlyAnalytics SensorHourlyAnalytics @relation(fields: [sensorHourlyAnalyticsId], references: [id])
331
+ startDateTime DateTime?
332
+ endDateTime DateTime?
333
+ createdAt DateTime @default(now())
334
+ updatedAt DateTime @updatedAt
335
+ }
336
+
337
+ model TemperatureSensorHourlyAnalytics {
338
+ id BigInt @id @default(autoincrement()) @db.BigInt
339
+ sensorHourlyAnalyticsId BigInt @unique
340
+ avgTemp Float?
341
+ maxTemp Float?
342
+ minTemp Float?
343
+ timeAboveThreshold Float?
344
+ sensorHourlyAnalytics SensorHourlyAnalytics @relation(fields: [sensorHourlyAnalyticsId], references: [id])
345
+ startDateTime DateTime?
346
+ endDateTime DateTime?
347
+ createdAt DateTime @default(now())
348
+ updatedAt DateTime @updatedAt
349
+ }
350
+
351
+ model FlowSensorHourlyAnalytics {
352
+ id BigInt @id @default(autoincrement()) @db.BigInt
353
+ sensorHourlyAnalyticsId BigInt @unique
354
+ avgFlowRate Float?
355
+ totalVolume Float?
356
+ maxFlowRate Float?
357
+ minFlowRate Float?
358
+ sensorHourlyAnalytics SensorHourlyAnalytics @relation(fields: [sensorHourlyAnalyticsId], references: [id])
359
+ startDateTime DateTime?
360
+ endDateTime DateTime?
361
+ createdAt DateTime @default(now())
362
+ updatedAt DateTime @updatedAt
363
+ }
364
+
365
+ model WeightSensorHourlyAnalytics {
366
+ id BigInt @id @default(autoincrement()) @db.BigInt
367
+ sensorHourlyAnalyticsId BigInt @unique
368
+ avgWeight Float?
369
+ maxWeight Float?
370
+ minWeight Float?
371
+ totalMeasurements Int?
372
+ sensorHourlyAnalytics SensorHourlyAnalytics @relation(fields: [sensorHourlyAnalyticsId], references: [id])
373
+ startDateTime DateTime?
374
+ endDateTime DateTime?
375
+ createdAt DateTime @default(now())
376
+ updatedAt DateTime @updatedAt
377
+ }
378
+
379
+ model PressureSensorHourlyAnalytics {
380
+ id BigInt @id @default(autoincrement()) @db.BigInt
381
+ sensorHourlyAnalyticsId BigInt @unique
382
+ avgPressure Float?
383
+ maxPressure Float?
384
+ minPressure Float?
385
+ timeOutOfRange Float?
386
+ sensorHourlyAnalytics SensorHourlyAnalytics @relation(fields: [sensorHourlyAnalyticsId], references: [id])
387
+ startDateTime DateTime?
388
+ endDateTime DateTime?
389
+ createdAt DateTime @default(now())
390
+ updatedAt DateTime @updatedAt
391
+ }
392
+
393
+ // ============================================================
394
+ // AUDIT SCHEMA - OPTIMIZED FOR SCALE
395
+ // ============================================================
396
+
397
+ enum LogCriticality {
398
+ LOW
399
+ MEDIUM
400
+ HIGH
401
+ CRITICAL
402
+ }
243
403
 
244
404
  model AuditLog {
245
- id BigInt @id @default(autoincrement()) @db.BigInt
246
- entityName String
247
- entityId Int?
248
- action String
249
- userId Int? // ID for CoreUser
250
- organizationId Int? // ID for CoreOrganization
251
- timestamp DateTime @default(now())
252
- httpMethod String
253
- route String
254
- statusCode Int
255
- ipAddress String?
256
- userAgent String?
257
- oldValues Json?
258
- newValues Json?
259
-
260
- @@index([entityName, entityId])
261
- @@index([userId])
262
- @@index([organizationId])
263
- @@schema("audit")
405
+ id BigInt @id @default(autoincrement()) @db.BigInt
406
+ organizationId Int
407
+
408
+ entityName String
409
+ entityId String?
410
+
411
+ action String
412
+ userId String? // Changed from Int to String
413
+ userName String?
414
+ roleNames String[]
415
+
416
+ timestamp DateTime @default(now()) @db.Timestamptz
417
+
418
+ httpMethod String?
419
+ route String?
420
+ statusCode Int?
421
+ ipAddress String?
422
+ userAgent String?
423
+ sessionId String?
424
+ duration Int?
425
+ errorMessage String?
426
+
427
+ // OPTIMIZED: Changed fields only, not full JSON
428
+ changedFields String[]
429
+ reasonForChange String?
430
+
431
+ // SPLIT PAYLOAD: Reference to separate payload table
432
+ payloadId String?
433
+ payload AuditLogPayload? @relation("AuditPayloads", fields: [payloadId], references: [id])
434
+
435
+ beforeValueHash String?
436
+ afterValueHash String?
437
+
438
+ criticality LogCriticality @default(MEDIUM)
439
+ isGxPRecord Boolean @default(false)
440
+ isComplianceEvent Boolean @default(false)
441
+
442
+ relatedSignatureId String?
443
+
444
+ @@index([organizationId, timestamp(sort: Desc)])
445
+ @@index([organizationId, entityName, entityId])
446
+ @@index([organizationId, userId, timestamp(sort: Desc)])
447
+ @@index([organizationId, isGxPRecord, timestamp(sort: Desc)])
448
+ @@index([criticality])
264
449
  }
265
450
 
266
- // ----------------------------------------------------------------------
267
- // SCHEMA: chatbot
268
- // ----------------------------------------------------------------------
451
+ // NEW: Separate table for heavy payload data
452
+ model AuditLogPayload {
453
+ id String @id @default(cuid())
454
+
455
+ // Only changed fields (not full records)
456
+ oldValues Json? // {"temperature": 75.0, "pressure": 120}
457
+ newValues Json? // {"temperature": 76.5, "pressure": 125}
458
+
459
+ // Optional: Full snapshot (only for critical GxP events)
460
+ fullSnapshot Json?
461
+
462
+ // Compression hint for application layer
463
+ isCompressed Boolean @default(false)
464
+
465
+ auditLogs AuditLog[] @relation("AuditPayloads")
466
+
467
+ createdAt DateTime @default(now())
468
+ }
269
469
 
270
470
  enum ChatbotMessageSender {
271
471
  USER
272
472
  BOT
473
+ SYSTEM
474
+ DEVICE
475
+ }
273
476
 
274
- @@schema("chatbot")
477
+ enum EmbeddingStatus {
478
+ PENDING
479
+ PROCESSING
480
+ COMPLETED
481
+ FAILED
275
482
  }
276
483
 
277
484
  model ChatbotHistory {
278
485
  id Int @id @default(autoincrement())
279
486
  title String
280
- userId Int // ID for CoreUser
281
- organizationId Int // ID for CoreOrganization
487
+ userId Int
488
+ organizationId Int
489
+ factoryId Int?
490
+ machineId Int?
491
+ deviceId Int?
492
+ sensorId Int?
493
+ contextType String?
494
+ contextData Json?
282
495
  messages ChatbotMessage[]
496
+ isArchived Boolean @default(false)
283
497
  createdAt DateTime @default(now())
284
498
  updatedAt DateTime @updatedAt
285
499
 
286
- @@index([userId])
287
- @@index([organizationId])
288
- @@index([createdAt])
289
- @@index([title])
290
- @@schema("chatbot")
500
+ @@index([userId])
501
+ @@index([organizationId])
502
+ @@index([factoryId])
503
+ @@index([machineId])
504
+ @@index([deviceId])
505
+ @@index([sensorId])
506
+ @@index([createdAt])
507
+ @@index([userId, createdAt])
508
+ @@index([organizationId, isArchived])
509
+ }
510
+
511
+ model ChatbotMessage {
512
+ id Int @id @default(autoincrement())
513
+ chatHistoryId Int
514
+ sender ChatbotMessageSender
515
+ message String
516
+ tokensUsed Int @default(0)
517
+ model String?
518
+ cost Float?
519
+ jsonContent Json?
520
+ embedding Unsupported("vector(1536)")?
521
+ retrievedChunkIds Int[] @default([])
522
+ chatHistory ChatbotHistory @relation(fields: [chatHistoryId], references: [id], onDelete: Cascade)
523
+ createdAt DateTime @default(now())
524
+ updatedAt DateTime @updatedAt
525
+
526
+ @@index([chatHistoryId])
527
+ @@index([createdAt])
528
+ @@index([sender])
529
+ }
530
+
531
+ model ChatbotKnowledgeBase {
532
+ id Int @id @default(autoincrement())
533
+ organizationId Int
534
+ factoryId Int?
535
+ machineId Int?
536
+ deviceId Int?
537
+ sensorId Int?
538
+ documentType DocumentType
539
+ title String
540
+ content String
541
+ summary String?
542
+ metadata Json?
543
+ fileUrl String?
544
+ embedding Unsupported("vector(1536)")?
545
+ embeddingModel String @default("text-embedding-3-small")
546
+ embeddingStatus EmbeddingStatus @default(PENDING)
547
+ embeddingError String?
548
+ chunks ChatbotKnowledgeChunk[]
549
+ isActive Boolean @default(true)
550
+ lastAccessedAt DateTime?
551
+ accessCount Int @default(0)
552
+ createdAt DateTime @default(now())
553
+ updatedAt DateTime @updatedAt
554
+
555
+ @@index([organizationId])
556
+ @@index([factoryId])
557
+ @@index([machineId])
558
+ @@index([deviceId])
559
+ @@index([sensorId])
560
+ @@index([documentType])
561
+ @@index([embeddingStatus])
562
+ @@index([isActive])
563
+ @@index([organizationId, documentType, isActive])
564
+ }
565
+
566
+ model ChatbotKnowledgeChunk {
567
+ id Int @id @default(autoincrement())
568
+ knowledgeBaseId Int
569
+ chunkIndex Int
570
+ content String
571
+ embedding Unsupported("vector(1536)")?
572
+ metadata Json?
573
+ tokenCount Int?
574
+ knowledgeBase ChatbotKnowledgeBase @relation(fields: [knowledgeBaseId], references: [id], onDelete: Cascade)
575
+ createdAt DateTime @default(now())
576
+ updatedAt DateTime @updatedAt
577
+
578
+ @@index([knowledgeBaseId])
579
+ @@index([knowledgeBaseId, chunkIndex])
580
+ }
581
+
582
+ model ChatbotSearchHistory {
583
+ id Int @id @default(autoincrement())
584
+ userId Int
585
+ organizationId Int
586
+ query String
587
+ queryEmbedding Unsupported("vector(1536)")?
588
+ results Json
589
+ clickedResults Int[] @default([])
590
+ resultCount Int @default(0)
591
+ wasHelpful Boolean?
592
+ createdAt DateTime @default(now())
593
+
594
+ @@index([userId])
595
+ @@index([organizationId])
596
+ @@index([createdAt])
597
+ @@index([userId, createdAt])
598
+ }
599
+
600
+ model DeviceConversationContext {
601
+ id Int @id @default(autoincrement())
602
+ organizationId Int
603
+ machineId Int?
604
+ deviceId Int?
605
+ sensorId Int?
606
+ entityType String
607
+ entityId Int
608
+ personality String?
609
+ capabilities Json
610
+ currentState Json?
611
+ lastSync DateTime @default(now())
612
+ isActive Boolean @default(true)
613
+ createdAt DateTime @default(now())
614
+ updatedAt DateTime @updatedAt
615
+
616
+ @@unique([organizationId, entityType, entityId])
617
+ @@index([machineId])
618
+ @@index([deviceId])
619
+ @@index([sensorId])
620
+ @@index([isActive])
621
+ }
622
+
623
+ model ChatbotFeedback {
624
+ id Int @id @default(autoincrement())
625
+ chatHistoryId Int
626
+ messageId Int
627
+ userId Int
628
+ organizationId Int
629
+ rating Int?
630
+ wasHelpful Boolean?
631
+ feedback String?
632
+ createdAt DateTime @default(now())
633
+
634
+ @@index([chatHistoryId])
635
+ @@index([messageId])
636
+ @@index([userId])
637
+ @@index([organizationId])
638
+ @@index([rating])
639
+ }
640
+
641
+ // ============================================================
642
+ // AUTOMOTIVE QUALITY MANAGEMENT (automotive schema)
643
+ // Standard: IATF 16949, AIAG-VDA FMEA, APQP, PPAP
644
+ // Purpose: FMEA, Control Plans, APQP, 8D Problem Solving
645
+ // ============================================================
646
+
647
+ enum FMEAType {
648
+ DFMEA
649
+ PFMEA
650
+ }
651
+
652
+ enum ControlPlanType {
653
+ PROTOTYPE
654
+ PRE_LAUNCH
655
+ PRODUCTION
656
+ }
657
+
658
+ enum PPAPStatus {
659
+ NOT_STARTED
660
+ IN_PROGRESS
661
+ SUBMITTED
662
+ APPROVED
663
+ REJECTED
664
+ }
665
+
666
+ enum ProblemStatus {
667
+ OPEN
668
+ CONTAINMENT_ACTIVE
669
+ ROOT_CAUSE_IDENTIFIED
670
+ CORRECTIVE_ACTION_IMPLEMENTED
671
+ EFFECTIVENESS_VERIFIED
672
+ CLOSED
673
+ }
674
+
675
+ model FMEA {
676
+ id Int @id @default(autoincrement())
677
+ organizationId Int
678
+
679
+ fmeaNumber String @unique
680
+ title String
681
+ type FMEAType
682
+
683
+ productId Int?
684
+ productName String?
685
+ processId Int?
686
+ partNumber String?
687
+
688
+ teamLead Int
689
+ teamMembers Int[]
690
+
691
+ revision String @default("A")
692
+ revisionDate DateTime @default(now())
693
+ status DocStatus @default(DRAFT)
694
+
695
+ items FMEAItem[] @relation("FMEAItems")
696
+
697
+ approvedBy Int?
698
+ approverName String?
699
+ approvedAt DateTime?
700
+
701
+ nextReviewDate DateTime?
702
+
703
+ signatures ElectronicSignature[] @relation("FMEASignatures")
704
+
705
+ createdAt DateTime @default(now())
706
+ updatedAt DateTime @updatedAt
707
+
708
+ @@index([organizationId, status])
709
+ @@index([fmeaNumber])
710
+ @@index([productId])
711
+ }
712
+
713
+ model FMEAItem {
714
+ id String @id @default(cuid())
715
+ fmeaId Int
716
+ fmea FMEA @relation("FMEAItems", fields: [fmeaId], references: [id], onDelete: Cascade)
717
+
718
+ processStep String
719
+ processFunction String?
720
+
721
+ failureMode String
722
+ failureEffect String
723
+ failureCause String
724
+
725
+ severity Int
726
+ severityJustification String?
727
+
728
+ occurrence Int
729
+ occurrenceJustification String?
730
+
731
+ preventionControl String?
732
+ detectionControl String?
733
+
734
+ detection Int
735
+ detectionJustification String?
736
+
737
+ rpn Int
738
+ riskLevel String?
739
+
740
+ recommendedAction String?
741
+ responsibility Int?
742
+ targetDate DateTime?
743
+
744
+ actionTaken String?
745
+ actionTakenBy Int?
746
+ actionTakenDate DateTime?
747
+
748
+ severityAfter Int?
749
+ occurrenceAfter Int?
750
+ detectionAfter Int?
751
+ rpnAfter Int?
752
+
753
+ linkedMachineId Int?
754
+ linkedCAPAId String?
755
+
756
+ isActionRequired Boolean @default(false)
757
+ isActionComplete Boolean @default(false)
758
+
759
+ tasks Task[] @relation("TaskFMEAFailures")
760
+
761
+ createdAt DateTime @default(now())
762
+ updatedAt DateTime @updatedAt
763
+
764
+ @@index([fmeaId])
765
+ @@index([rpn])
766
+ @@index([linkedMachineId])
767
+ }
768
+
769
+ model ControlPlan {
770
+ id Int @id @default(autoincrement())
771
+ organizationId Int
772
+
773
+ controlPlanNumber String @unique
774
+ title String
775
+ type ControlPlanType
776
+
777
+ productId Int?
778
+ productName String?
779
+ partNumber String?
780
+ processId Int?
781
+
782
+ revision String @default("A")
783
+ revisionDate DateTime @default(now())
784
+ status DocStatus @default(DRAFT)
785
+
786
+ items ControlPlanItem[] @relation("ControlPlanItems")
787
+
788
+ preparedBy Int
789
+ preparedName String
790
+ approvedBy Int?
791
+ approverName String?
792
+ approvedAt DateTime?
793
+
794
+ effectiveDate DateTime?
795
+ obsoleteDate DateTime?
796
+
797
+ signatures ElectronicSignature[] @relation("ControlPlanSignatures")
798
+
799
+ createdAt DateTime @default(now())
800
+ updatedAt DateTime @updatedAt
801
+
802
+ @@index([organizationId, status])
803
+ @@index([controlPlanNumber])
804
+ @@index([productId])
805
+ }
806
+
807
+ model ControlPlanItem {
808
+ id String @id @default(cuid())
809
+ controlPlanId Int
810
+ controlPlan ControlPlan @relation("ControlPlanItems", fields: [controlPlanId], references: [id], onDelete: Cascade)
811
+
812
+ processStep String
813
+ processNumber String?
814
+ machineId Int?
815
+ machineName String?
816
+
817
+ characteristic String
818
+ characteristicType String
819
+ classificationChar String?
820
+
821
+ specification String
822
+ lowerSpec Float?
823
+ upperSpec Float?
824
+ targetValue Float?
825
+ unit String?
826
+
827
+ controlMethod String
828
+ measurementDevice String?
829
+
830
+ sampleSize Int
831
+ sampleFrequency String
832
+
833
+ reactionPlan String?
834
+
835
+ linkedMachineId Int?
836
+ autoGenerateTask Boolean @default(false)
837
+
838
+ responsiblePerson String?
839
+
840
+ createdAt DateTime @default(now())
841
+ updatedAt DateTime @updatedAt
842
+
843
+ @@index([controlPlanId])
844
+ @@index([machineId])
845
+ }
846
+
847
+ model PPAPSubmission {
848
+ id Int @id @default(autoincrement())
849
+ organizationId Int
850
+
851
+ ppapNumber String @unique
852
+ productId Int
853
+ productName String
854
+ partNumber String
855
+
856
+ customerName String
857
+ customerPartNumber String?
858
+
859
+ submissionLevel Int
860
+
861
+ status PPAPStatus @default(NOT_STARTED)
862
+
863
+ designRecordProvided Boolean @default(false)
864
+ engineeringChangeDocuments Boolean @default(false)
865
+ customerApprovalProvided Boolean @default(false)
866
+ dfmeaProvided Boolean @default(false)
867
+ pfmeaProvided Boolean @default(false)
868
+ processFlowDiagram Boolean @default(false)
869
+ controlPlanProvided Boolean @default(false)
870
+ msaStudiesProvided Boolean @default(false)
871
+ dimensionalResults Boolean @default(false)
872
+ materialTestResults Boolean @default(false)
873
+ initialProcessStudies Boolean @default(false)
874
+ qualifiedLabDocumentation Boolean @default(false)
875
+ appearanceApprovalReport Boolean @default(false)
876
+ sampleProductProvided Boolean @default(false)
877
+ masterSampleProvided Boolean @default(false)
878
+ checkingAidsProvided Boolean @default(false)
879
+ customerSpecificRequirements Boolean @default(false)
880
+ partSubmissionWarrant Boolean @default(false)
881
+
882
+ documentUrls Json?
883
+
884
+ submittedBy Int?
885
+ submittedName String?
886
+ submittedDate DateTime?
887
+
888
+ approvedBy String?
889
+ approvalDate DateTime?
890
+ rejectionReason String?
891
+
892
+ validUntil DateTime?
893
+
894
+ notes String?
895
+
896
+ signatures ElectronicSignature[] @relation("PPAPSignatures")
897
+
898
+ createdAt DateTime @default(now())
899
+ updatedAt DateTime @updatedAt
900
+
901
+ @@index([organizationId, status])
902
+ @@index([ppapNumber])
903
+ @@index([productId])
904
+ }
905
+
906
+ model Problem8D {
907
+ id String @id @default(cuid())
908
+ organizationId Int
909
+
910
+ problemNumber String @unique
911
+ title String
912
+ description String
913
+
914
+ sourceType String
915
+ sourceRef String?
916
+ customerId Int?
917
+ customerName String?
918
+
919
+ productId Int?
920
+ partNumber String?
921
+ batchNumbers String[]
922
+ quantityAffected Int?
923
+
924
+ d0_plan String?
925
+ d0_completedAt DateTime?
926
+
927
+ d1_teamMembers Int[]
928
+ d1_teamLead Int?
929
+ d1_completedAt DateTime?
930
+
931
+ d2_problemDescription String?
932
+ d2_is_isNot Json?
933
+ d2_completedAt DateTime?
934
+
935
+ d3_containmentAction String?
936
+ d3_verificationOfContainment String?
937
+ d3_completedAt DateTime?
938
+
939
+ d4_rootCause String?
940
+ d4_rootCauseVerification String?
941
+ d4_whyWhyAnalysis Json?
942
+ d4_completedAt DateTime?
943
+
944
+ d5_correctiveActions String?
945
+ d5_verificationPlan String?
946
+ d5_completedAt DateTime?
947
+
948
+ d6_implementationPlan String?
949
+ d6_implementedBy Int?
950
+ d6_implementedAt DateTime?
951
+
952
+ d7_preventiveActions String?
953
+ d7_systemChanges String?
954
+ d7_completedAt DateTime?
955
+
956
+ d8_lessons String?
957
+ d8_recognition String?
958
+ d8_completedAt DateTime?
959
+
960
+ status ProblemStatus @default(OPEN)
961
+
962
+ detectedDate DateTime @default(now())
963
+ targetCloseDate DateTime
964
+ closedDate DateTime?
965
+
966
+ estimatedCost Float?
967
+ actualCost Float?
968
+
969
+ createdAt DateTime @default(now())
970
+ updatedAt DateTime @updatedAt
971
+
972
+ @@index([organizationId, status])
973
+ @@index([problemNumber])
974
+ @@index([customerId])
975
+ }
976
+
977
+ // ============================================================
978
+ // PHARMACEUTICAL COMPLIANCE (pharma schema)
979
+ // Regulatory: Schedule M (India), 21 CFR Part 11 (US), WHO-GMP
980
+ // Purpose: eBMR, batch records, deviations, CAPA
981
+ // ============================================================
982
+
983
+ enum BatchStatus {
984
+ PENDING
985
+ IN_PROGRESS
986
+ QUARANTINE
987
+ RELEASED
988
+ REJECTED
989
+ ON_HOLD
990
+ RECALLED
991
+ }
992
+
993
+ enum DeviationSeverity {
994
+ CRITICAL
995
+ MAJOR
996
+ MINOR
997
+ }
998
+
999
+ enum DeviationStatus {
1000
+ OPEN
1001
+ UNDER_INVESTIGATION
1002
+ CAPA_ASSIGNED
1003
+ CAPA_IN_PROGRESS
1004
+ EFFECTIVENESS_CHECK
1005
+ CLOSED
1006
+ REOPENED
1007
+ }
1008
+
1009
+ enum CAPAType {
1010
+ CORRECTIVE
1011
+ PREVENTIVE
1012
+ }
1013
+
1014
+ enum CAPAStatus {
1015
+ INITIATED
1016
+ UNDER_REVIEW
1017
+ APPROVED
1018
+ IN_PROGRESS
1019
+ IMPLEMENTED
1020
+ EFFECTIVENESS_CHECK
1021
+ COMPLETED
1022
+ CANCELED
1023
+ }
1024
+
1025
+ model MasterFormulaRecord {
1026
+ id Int @id @default(autoincrement())
1027
+ organizationId Int
1028
+
1029
+ productId Int
1030
+ productName String
1031
+ productCode String?
1032
+
1033
+ mfrNumber String @unique
1034
+ version String
1035
+ revision Int @default(1)
1036
+
1037
+ standardBatchSize Float
1038
+ batchSizeUnit String
1039
+ minBatchSize Float?
1040
+ maxBatchSize Float?
1041
+
1042
+ materials MFRMaterial[] @relation("MFRMaterials")
1043
+ processSteps MFRProcessStep[] @relation("MFRProcessSteps")
1044
+ qualitySpecs MFRQualitySpec[] @relation("MFRQualitySpecs")
1045
+
1046
+ requiredEquipment String[]
1047
+
1048
+ status DocStatus @default(DRAFT)
1049
+ effectiveDate DateTime?
1050
+ obsoleteDate DateTime?
1051
+ supersededBy Int?
1052
+
1053
+ authoredBy Int
1054
+ authorName String
1055
+ reviewedBy Int?
1056
+ reviewerName String?
1057
+ approvedBy Int?
1058
+ approverName String?
1059
+ approvedAt DateTime?
1060
+
1061
+ batches BatchManufacturingRecord[] @relation("MFRToBatches")
1062
+ signatures ElectronicSignature[] @relation("MFRSignatures")
1063
+
1064
+ createdAt DateTime @default(now())
1065
+ updatedAt DateTime @updatedAt
1066
+
1067
+ @@index([organizationId, status])
1068
+ @@index([productId])
1069
+ @@index([mfrNumber])
1070
+ }
1071
+
1072
+ model MFRMaterial {
1073
+ id Int @id @default(autoincrement())
1074
+ mfrId Int
1075
+ mfr MasterFormulaRecord @relation("MFRMaterials", fields: [mfrId], references: [id], onDelete: Cascade)
1076
+
1077
+ materialId Int?
1078
+ materialCode String
1079
+ materialName String
1080
+ materialType String
1081
+
1082
+ quantity Float
1083
+ unit String
1084
+
1085
+ tolerancePlus Float?
1086
+ toleranceMinus Float?
1087
+
1088
+ additionStage String?
1089
+ instructions String?
1090
+
1091
+ sequence Int
1092
+
1093
+ createdAt DateTime @default(now())
1094
+ updatedAt DateTime @updatedAt
1095
+
1096
+ @@index([mfrId, sequence])
1097
+ }
1098
+
1099
+ model MFRProcessStep {
1100
+ id Int @id @default(autoincrement())
1101
+ mfrId Int
1102
+ mfr MasterFormulaRecord @relation("MFRProcessSteps", fields: [mfrId], references: [id], onDelete: Cascade)
1103
+
1104
+ stepNumber Int
1105
+ operation String
1106
+ description String?
1107
+
1108
+ durationMinutes Int?
1109
+ temperatureMin Float?
1110
+ temperatureMax Float?
1111
+ temperatureUnit String?
1112
+
1113
+ speed Float?
1114
+ pressure Float?
1115
+ humidity Float?
1116
+
1117
+ requiredEquipment String?
1118
+ machineId Int?
1119
+
1120
+ qualitySpecs MFRQualitySpec[] @relation("StepQualitySpecs")
1121
+
1122
+ createdAt DateTime @default(now())
1123
+ updatedAt DateTime @updatedAt
1124
+
1125
+ @@index([mfrId, stepNumber])
1126
+ }
1127
+
1128
+ model MFRQualitySpec {
1129
+ id Int @id @default(autoincrement())
1130
+ mfrId Int
1131
+ mfr MasterFormulaRecord @relation("MFRQualitySpecs", fields: [mfrId], references: [id], onDelete: Cascade)
1132
+
1133
+ processStepId Int?
1134
+ processStep MFRProcessStep? @relation("StepQualitySpecs", fields: [processStepId], references: [id], onDelete: Cascade)
1135
+
1136
+ parameter String
1137
+ testStage String
1138
+ testMethod String?
1139
+
1140
+ minValue Float?
1141
+ maxValue Float?
1142
+ targetValue Float?
1143
+ unit String?
1144
+
1145
+ acceptanceCriteria String?
1146
+
1147
+ createdAt DateTime @default(now())
1148
+ updatedAt DateTime @updatedAt
1149
+
1150
+ @@index([mfrId])
1151
+ @@index([processStepId])
1152
+ }
1153
+
1154
+ model BatchManufacturingRecord {
1155
+ id String @id @default(cuid())
1156
+ organizationId Int
1157
+
1158
+ batchNumber String @unique
1159
+ mfrId Int
1160
+ mfr MasterFormulaRecord @relation("MFRToBatches", fields: [mfrId], references: [id])
1161
+ productId Int
1162
+ productName String
1163
+
1164
+ plannedBatchSize Float
1165
+ actualBatchSize Float?
1166
+ batchSizeUnit String
1167
+ yieldPercentage Float?
1168
+
1169
+ scheduledStartDate DateTime
1170
+ actualStartDate DateTime?
1171
+ actualEndDate DateTime?
1172
+ manufacturingDate DateTime
1173
+ expiryDate DateTime
1174
+ retestDate DateTime?
1175
+
1176
+ status BatchStatus @default(PENDING)
1177
+ currentStage String?
1178
+
1179
+ weighingLogs WeighingLog[] @relation("BatchWeighingLogs")
1180
+
1181
+ processExecutionData Json?
1182
+ equipmentUsed String[]
1183
+
1184
+ inProcessControls InProcessControl[] @relation("BatchIPCs")
1185
+
1186
+ deviations Deviation[] @relation("BatchDeviations")
1187
+
1188
+ qaStatus String?
1189
+ qaReleaseBy Int?
1190
+ qaReleaseName String?
1191
+ qaReleaseDate DateTime?
1192
+ qaComments String?
1193
+
1194
+ rejectionReason String?
1195
+ rejectionDate DateTime?
1196
+ rejectedBy Int?
1197
+
1198
+ storageLocation String?
1199
+ storageCondition String?
1200
+
1201
+ theoreticalYield Float?
1202
+ practicalYield Float?
1203
+ yieldReconciliation Json?
1204
+
1205
+ orderProductId Int?
1206
+
1207
+ notes String?
1208
+
1209
+ signatures ElectronicSignature[] @relation("BatchSignatures")
1210
+
1211
+ createdAt DateTime @default(now())
1212
+ updatedAt DateTime @updatedAt
1213
+
1214
+ @@index([organizationId, status])
1215
+ @@index([batchNumber])
1216
+ @@index([mfrId])
1217
+ @@index([manufacturingDate])
1218
+ @@index([expiryDate])
1219
+ @@index([status, qaReleaseDate])
1220
+ }
1221
+
1222
+ model WeighingLog {
1223
+ id String @id @default(cuid())
1224
+ batchId String
1225
+ batch BatchManufacturingRecord @relation("BatchWeighingLogs", fields: [batchId], references: [id], onDelete: Cascade)
1226
+
1227
+ materialId Int?
1228
+ materialCode String
1229
+ materialName String
1230
+ materialBatch String
1231
+ materialExpiry DateTime?
1232
+
1233
+ requiredQty Float
1234
+ actualQty Float
1235
+ tolerance Float?
1236
+ unit String
1237
+ variance Float?
1238
+ variancePct Float?
1239
+
1240
+ balanceId Int?
1241
+ balanceName String?
1242
+ isAutomated Boolean @default(false)
1243
+
1244
+ weighedBy Int
1245
+ weigherName String
1246
+ verifiedBy Int?
1247
+ verifierName String?
1248
+ verifiedAt DateTime?
1249
+
1250
+ weighedAt DateTime @default(now())
1251
+
1252
+ containerTare Float?
1253
+ grossWeight Float?
1254
+ notes String?
1255
+
1256
+ createdAt DateTime @default(now())
1257
+
1258
+ @@index([batchId])
1259
+ @@index([materialCode])
1260
+ @@index([weighedAt])
1261
+ }
1262
+
1263
+ model InProcessControl {
1264
+ id String @id @default(cuid())
1265
+ batchId String
1266
+ batch BatchManufacturingRecord @relation("BatchIPCs", fields: [batchId], references: [id], onDelete: Cascade)
1267
+
1268
+ testName String
1269
+ testStage String
1270
+ testMethod String?
1271
+
1272
+ parameter String
1273
+ specMin Float?
1274
+ specMax Float?
1275
+ targetValue Float?
1276
+ unit String?
1277
+
1278
+ measuredValue Float?
1279
+ textResult String?
1280
+ isPass Boolean
1281
+
1282
+ sampleSize Int?
1283
+ sampleLocation String?
1284
+
1285
+ testedBy Int
1286
+ testerName String
1287
+ testedAt DateTime @default(now())
1288
+
1289
+ reviewedBy Int?
1290
+ reviewerName String?
1291
+ reviewedAt DateTime?
1292
+
1293
+ notes String?
1294
+
1295
+ @@index([batchId])
1296
+ @@index([testStage])
1297
+ }
1298
+
1299
+ model Deviation {
1300
+ id String @id @default(cuid())
1301
+ organizationId Int
1302
+
1303
+ deviationNumber String @unique
1304
+ title String
1305
+ description String
1306
+
1307
+ batchId String?
1308
+ batch BatchManufacturingRecord? @relation("BatchDeviations", fields: [batchId], references: [id])
1309
+ productId Int?
1310
+ processStage String?
1311
+ equipmentId Int?
1312
+
1313
+ severity DeviationSeverity
1314
+ deviationType String
1315
+
1316
+ detectedBy Int
1317
+ detectorName String
1318
+ detectedAt DateTime @default(now())
1319
+
1320
+ status DeviationStatus @default(OPEN)
1321
+ rootCause String?
1322
+ investigation String?
1323
+ investigatedBy Int?
1324
+ investigatedAt DateTime?
1325
+
1326
+ productImpact Boolean @default(false)
1327
+ customerImpact Boolean @default(false)
1328
+ regulatoryImpact Boolean @default(false)
1329
+ impactDescription String?
1330
+
1331
+ immediateAction String?
1332
+ actionTakenBy Int?
1333
+ actionTakenAt DateTime?
1334
+
1335
+ capas CAPA[] @relation("DeviationCAPAs")
1336
+
1337
+ reviewedBy Int?
1338
+ reviewerName String?
1339
+ reviewedAt DateTime?
1340
+ approvedBy Int?
1341
+ approverName String?
1342
+ approvedAt DateTime?
1343
+ closedAt DateTime?
1344
+ closureComments String?
1345
+
1346
+ isRecurrence Boolean @default(false)
1347
+ previousDeviationId String?
1348
+
1349
+ signatures ElectronicSignature[] @relation("DeviationSignatures")
1350
+
1351
+ createdAt DateTime @default(now())
1352
+ updatedAt DateTime @updatedAt
1353
+
1354
+ @@index([organizationId, status])
1355
+ @@index([deviationNumber])
1356
+ @@index([batchId])
1357
+ @@index([severity, status])
1358
+ }
1359
+
1360
+ model CAPA {
1361
+ id String @id @default(cuid())
1362
+ organizationId Int
1363
+
1364
+ capaNumber String @unique
1365
+ title String
1366
+ description String
1367
+ type CAPAType
1368
+
1369
+ deviationId String?
1370
+ deviation Deviation? @relation("DeviationCAPAs", fields: [deviationId], references: [id])
1371
+ sourceType String?
1372
+ sourceRef String?
1373
+
1374
+ assignedTo Int
1375
+ assigneeName String
1376
+ assignedBy Int
1377
+ assignedAt DateTime @default(now())
1378
+
1379
+ dueDate DateTime
1380
+ status CAPAStatus @default(INITIATED)
1381
+
1382
+ actionPlan String?
1383
+ implementedBy Int?
1384
+ implementedAt DateTime?
1385
+ implementationEvidence String?
1386
+
1387
+ effectivenessCheck String?
1388
+ effectivenessDueDate DateTime?
1389
+ isEffective Boolean?
1390
+ effectivenessCheckedBy Int?
1391
+ effectivenessCheckedAt DateTime?
1392
+
1393
+ approvedBy Int?
1394
+ approverName String?
1395
+ approvedAt DateTime?
1396
+ completedAt DateTime?
1397
+
1398
+ relatedCAPAIds String[]
1399
+
1400
+ notes String?
1401
+
1402
+ signatures ElectronicSignature[] @relation("CAPASignatures")
1403
+
1404
+ createdAt DateTime @default(now())
1405
+ updatedAt DateTime @updatedAt
1406
+
1407
+ @@index([organizationId, status])
1408
+ @@index([capaNumber])
1409
+ @@index([deviationId])
1410
+ @@index([assignedTo, status])
1411
+ @@index([dueDate])
1412
+ }
1413
+
1414
+ // ============================================================
1415
+ // UNIVERSAL COMPLIANCE LAYER (quality schema) - PRODUCTION GRADE
1416
+ // ============================================================
1417
+
1418
+ enum SignatureMeaning {
1419
+ CREATED
1420
+ REVIEWED
1421
+ APPROVED
1422
+ RELEASED
1423
+ VERIFIED
1424
+ REJECTED
1425
+ CANCELED
1426
+ AMENDED
1427
+ }
1428
+
1429
+ enum DocStatus {
1430
+ DRAFT
1431
+ UNDER_REVIEW
1432
+ APPROVED
1433
+ OBSOLETE
1434
+ SUPERSEDED
1435
+ WITHDRAWN
1436
+ }
1437
+
1438
+ enum DocumentType {
1439
+ SOP
1440
+ WORK_INSTRUCTION
1441
+ FORM
1442
+ POLICY
1443
+ MANUAL
1444
+ SPECIFICATION
1445
+ PROTOCOL
1446
+ REPORT
1447
+
1448
+ TROUBLESHOOTING_GUIDE
1449
+ MACHINE_SPEC
1450
+ SAFETY_PROTOCOL
1451
+ TRAINING_MATERIAL
1452
+ ERROR_CODE_REFERENCE
1453
+ MAINTENANCE_LOG
1454
+ PAST_CHAT
1455
+ OTHER
1456
+ }
1457
+
1458
+ enum ChangeControlStatus {
1459
+ INITIATED
1460
+ UNDER_REVIEW
1461
+ APPROVED
1462
+ IMPLEMENTED
1463
+ COMPLETED
1464
+ REJECTED
1465
+ CANCELED
1466
+ }
1467
+
1468
+ enum TrainingStatus {
1469
+ NOT_STARTED
1470
+ IN_PROGRESS
1471
+ COMPLETED
1472
+ EXPIRED
1473
+ FAILED
1474
+ }
1475
+
1476
+ enum TestStatus {
1477
+ PENDING
1478
+ IN_PROGRESS
1479
+ PASSED
1480
+ FAILED
1481
+ RETEST_REQUIRED
1482
+ CANCELED
1483
+ }
1484
+
1485
+ model ElectronicSignature {
1486
+ id String @id @default(cuid())
1487
+ organizationId Int
1488
+
1489
+ userId String // Changed from Int to String for federation
1490
+ userFullName String
1491
+ userTitle String?
1492
+ userEmail String
1493
+ roleId String? // Changed from Int to String
1494
+ roleName String?
1495
+
1496
+ batchRecordId String?
1497
+ batchRecord BatchManufacturingRecord? @relation("BatchSignatures", fields: [batchRecordId], references: [id], onDelete: Restrict)
1498
+
1499
+ deviationId String?
1500
+ deviation Deviation? @relation("DeviationSignatures", fields: [deviationId], references: [id], onDelete: Restrict)
1501
+
1502
+ capaId String?
1503
+ capa CAPA? @relation("CAPASignatures", fields: [capaId], references: [id], onDelete: Restrict)
1504
+
1505
+ mfrId Int?
1506
+ masterFormulaRecord MasterFormulaRecord? @relation("MFRSignatures", fields: [mfrId], references: [id], onDelete: Restrict)
1507
+
1508
+ documentId Int?
1509
+ document ControlledDocument? @relation("DocumentSignatures", fields: [documentId], references: [id], onDelete: Restrict)
1510
+
1511
+ equipmentQualId Int?
1512
+ equipmentQualification EquipmentQualification? @relation("QualificationSignatures", fields: [equipmentQualId], references: [id], onDelete: Restrict)
1513
+
1514
+ changeControlId Int?
1515
+ changeControl ChangeControl? @relation("ChangeControlSignatures", fields: [changeControlId], references: [id], onDelete: Restrict)
1516
+
1517
+ labTestRequestId String?
1518
+ labTestRequest LabTestRequest? @relation("LabTestSignatures", fields: [labTestRequestId], references: [id], onDelete: Restrict)
1519
+
1520
+ dppId String?
1521
+ digitalProductPassport DigitalProductPassport? @relation("DPPSignatures", fields: [dppId], references: [id], onDelete: Restrict)
1522
+
1523
+ fmeaId Int?
1524
+ fmea FMEA? @relation("FMEASignatures", fields: [fmeaId], references: [id], onDelete: Restrict)
1525
+
1526
+ controlPlanId Int?
1527
+ controlPlan ControlPlan? @relation("ControlPlanSignatures", fields: [controlPlanId], references: [id], onDelete: Restrict)
1528
+
1529
+ ppapSubmissionId Int?
1530
+ ppapSubmission PPAPSubmission? @relation("PPAPSignatures", fields: [ppapSubmissionId], references: [id], onDelete: Restrict)
1531
+
1532
+ meaning SignatureMeaning
1533
+ reason String?
1534
+ comments String?
1535
+ timestamp DateTime @default(now())
1536
+
1537
+ checksum String
1538
+ checksumAlgo String @default("SHA256")
1539
+ dataSnapshot Json?
1540
+
1541
+ ipAddress String?
1542
+ deviceInfo String?
1543
+ authMethod String?
1544
+ sessionId String?
1545
+
1546
+ isValid Boolean @default(true)
1547
+ invalidatedAt DateTime?
1548
+ invalidatedBy String? // Changed from Int to String
1549
+ invalidationReason String?
1550
+
1551
+ deletedAt DateTime? // Soft delete for GDPR compliance
1552
+
1553
+ createdAt DateTime @default(now())
1554
+
1555
+ @@index([organizationId, timestamp(sort: Desc)])
1556
+ @@index([organizationId, batchRecordId])
1557
+ @@index([organizationId, documentId])
1558
+ @@index([organizationId, userId, timestamp(sort: Desc)])
1559
+ @@index([isValid])
1560
+ }
1561
+
1562
+ model EquipmentQualification {
1563
+ id Int @id @default(autoincrement())
1564
+ organizationId Int
1565
+ machineId Int
1566
+
1567
+ qualificationType String
1568
+ protocolNumber String
1569
+
1570
+ performedBy String // Changed from Int to String
1571
+ performedDate DateTime
1572
+ expiryDate DateTime
1573
+
1574
+ status String
1575
+ findings String?
1576
+ certificateUrl String?
1577
+
1578
+ reviewedBy String? // Changed from Int to String
1579
+ approvedBy String? // Changed from Int to String
1580
+ approvedAt DateTime?
1581
+
1582
+ notes String?
1583
+
1584
+ deletedAt DateTime? // Soft delete
1585
+
1586
+ machine Machine @relation("MachineQualifications", fields: [machineId], references: [id])
1587
+ signatures ElectronicSignature[] @relation("QualificationSignatures")
1588
+
1589
+ createdAt DateTime @default(now())
1590
+ updatedAt DateTime @updatedAt
1591
+
1592
+ @@index([organizationId, machineId])
1593
+ @@index([organizationId, expiryDate])
1594
+ @@index([organizationId, qualificationType, status])
1595
+ }
1596
+
1597
+ model ControlledDocument {
1598
+ id Int @id @default(autoincrement())
1599
+ organizationId Int
1600
+
1601
+ documentNumber String
1602
+ title String
1603
+ version String
1604
+ revision Int @default(1)
1605
+
1606
+ documentType DocumentType // Changed from String to enum
1607
+ category String?
1608
+ department String?
1609
+
1610
+ status DocStatus @default(DRAFT)
1611
+
1612
+ effectiveDate DateTime?
1613
+ reviewDate DateTime?
1614
+ reviewFrequencyMonths Int? @default(12)
1615
+ obsoleteDate DateTime?
1616
+
1617
+ supersededBy Int?
1618
+ supersedes Int?
1619
+
1620
+ contentUrl String
1621
+ contentType String?
1622
+ fileSize Int?
1623
+ contentHash String
1624
+
1625
+ authorId String // Changed from Int to String
1626
+ authorName String
1627
+ reviewedBy String? // Changed from Int to String
1628
+ approvedBy String? // Changed from Int to String
1629
+ approvalDate DateTime?
1630
+
1631
+ isPublic Boolean @default(false)
1632
+ targetRoles String[]
1633
+ targetUsers String[] // Changed from Int[] to String[]
1634
+
1635
+ linkedMachineTypes String[]
1636
+ linkedProductIds Int[]
1637
+ linkedTaskTypes String[]
1638
+
1639
+ deletedAt DateTime? // Soft delete
1640
+
1641
+ trainingRecords TrainingRecord[] @relation("DocumentTrainings")
1642
+ signatures ElectronicSignature[] @relation("DocumentSignatures")
1643
+
1644
+ keywords String[]
1645
+ tags String[]
1646
+ notes String?
1647
+
1648
+ createdAt DateTime @default(now())
1649
+ updatedAt DateTime @updatedAt
1650
+
1651
+ @@unique([organizationId, documentNumber, version])
1652
+ @@index([organizationId, status])
1653
+ @@index([organizationId, documentType, status])
1654
+ @@index([organizationId, reviewDate])
1655
+ @@index([effectiveDate, obsoleteDate])
1656
+ }
1657
+
1658
+ model TrainingRecord {
1659
+ id Int @id @default(autoincrement())
1660
+ organizationId Int
1661
+
1662
+ userId String // Changed from Int to String
1663
+ userName String
1664
+
1665
+ documentId Int?
1666
+ trainingType String
1667
+ trainingTitle String
1668
+ trainingVersion String?
1669
+
1670
+ status TrainingStatus @default(NOT_STARTED)
1671
+ startedAt DateTime?
1672
+ completedAt DateTime?
1673
+ expiresAt DateTime?
1674
+
1675
+ score Float?
1676
+ passingScore Float?
1677
+ attempts Int @default(0)
1678
+
1679
+ trainerId String? // Changed from Int to String
1680
+ trainerName String?
1681
+ verifiedById String? // Changed from Int to String
1682
+ verifiedAt DateTime?
1683
+
1684
+ certificateUrl String?
1685
+ assessmentUrl String?
1686
+ notes String?
1687
+
1688
+ document ControlledDocument? @relation("DocumentTrainings", fields: [documentId], references: [id])
1689
+
1690
+ createdAt DateTime @default(now())
1691
+ updatedAt DateTime @updatedAt
1692
+
1693
+ @@index([organizationId, userId, status])
1694
+ @@index([organizationId, expiresAt])
1695
+ @@index([documentId])
1696
+ }
1697
+
1698
+ model ChangeControl {
1699
+ id Int @id @default(autoincrement())
1700
+ organizationId Int
1701
+
1702
+ changeNumber String @unique
1703
+ title String
1704
+ description String
1705
+ changeType String
1706
+ priority String
1707
+
1708
+ initiatedBy String // Changed from Int to String
1709
+ initiatorName String
1710
+ initiatedAt DateTime @default(now())
1711
+
1712
+ impactedSystems String[]
1713
+ impactedDocuments Int[]
1714
+ impactedProducts Int[]
1715
+
1716
+ riskLevel String?
1717
+ riskDescription String?
1718
+
1719
+ status ChangeControlStatus @default(INITIATED)
1720
+ reviewers String[] // Changed from Int[] to String[]
1721
+ approvers String[] // Changed from Int[] to String[]
1722
+ approvedBy String? // Changed from Int to String
1723
+ approvedAt DateTime?
1724
+
1725
+ implementationPlan String?
1726
+ implementedBy String? // Changed from Int to String
1727
+ implementedAt DateTime?
1728
+
1729
+ verifiedBy String? // Changed from Int to String
1730
+ verifiedAt DateTime?
1731
+ effectivenessCheck String?
1732
+ closedAt DateTime?
1733
+
1734
+ relatedDeviationIds String[]
1735
+ relatedCAPAIds String[]
1736
+
1737
+ deletedAt DateTime? // Soft delete
1738
+
1739
+ signatures ElectronicSignature[] @relation("ChangeControlSignatures")
1740
+
1741
+ createdAt DateTime @default(now())
1742
+ updatedAt DateTime @updatedAt
1743
+
1744
+ @@index([organizationId, status])
1745
+ @@index([organizationId, changeNumber])
1746
+ @@index([organizationId, initiatedAt(sort: Desc)])
1747
+ }
1748
+
1749
+ model LabTestRequest {
1750
+ id String @id @default(cuid())
1751
+ organizationId Int
1752
+
1753
+ sampleId String @unique
1754
+ sampleType String
1755
+
1756
+ batchId String?
1757
+ lotId Int?
1758
+ productId Int?
1759
+
1760
+ testCategory String
1761
+ standardRef String
1762
+ testParameters String[]
1763
+
1764
+ labName String
1765
+ labAddress String?
1766
+ isBISRecognized Boolean @default(false)
1767
+ labAccreditation String?
1768
+
1769
+ status TestStatus @default(PENDING)
1770
+ requestedBy String // Changed from Int to String
1771
+ requestedAt DateTime @default(now())
1772
+ sampleSentAt DateTime?
1773
+ resultsReceivedAt DateTime?
1774
+
1775
+ sampleQuantity Float?
1776
+ sampleUnit String?
1777
+ storageCondition String?
1778
+ retentionPeriod Int?
1779
+ retentionExpiry DateTime?
1780
+
1781
+ results TestResult[] @relation("TestRequestResults")
1782
+ certificateUrl String?
1783
+ certificateNumber String?
1784
+
1785
+ reviewedBy String? // Changed from Int to String
1786
+ reviewedAt DateTime?
1787
+ approvedBy String? // Changed from Int to String
1788
+ approvedAt DateTime?
1789
+
1790
+ notes String?
1791
+
1792
+ deletedAt DateTime? // Soft delete
1793
+
1794
+ signatures ElectronicSignature[] @relation("LabTestSignatures")
1795
+
1796
+ createdAt DateTime @default(now())
1797
+ updatedAt DateTime @updatedAt
1798
+
1799
+ @@index([organizationId, status])
1800
+ @@index([organizationId, sampleId])
1801
+ @@index([organizationId, batchId])
1802
+ @@index([organizationId, requestedAt(sort: Desc)])
1803
+ }
1804
+
1805
+ model TestResult {
1806
+ id String @id @default(cuid())
1807
+ organizationId Int
1808
+ requestId String
1809
+
1810
+ parameter String
1811
+ method String?
1812
+ unit String?
1813
+
1814
+ specMin Float?
1815
+ specMax Float?
1816
+ targetValue Float?
1817
+
1818
+ measuredValue Float?
1819
+ textResult String?
1820
+
1821
+ isPass Boolean
1822
+ deviationPct Float?
1823
+
1824
+ uncertainty Float?
1825
+ confidenceLevel Float?
1826
+
1827
+ request LabTestRequest @relation("TestRequestResults", fields: [requestId], references: [id], onDelete: Cascade)
1828
+
1829
+ createdAt DateTime @default(now())
1830
+
1831
+ @@index([organizationId, requestId])
1832
+ @@index([organizationId, isPass])
1833
+ }
1834
+
1835
+ model CalibrationRecord {
1836
+ id Int @id @default(autoincrement())
1837
+ organizationId Int
1838
+
1839
+ equipmentType String
1840
+ equipmentId String
1841
+ deviceId Int?
1842
+
1843
+ calibrationDate DateTime
1844
+ nextDueDate DateTime
1845
+ frequency Int
1846
+
1847
+ standardRef String
1848
+ traceability String?
1849
+
1850
+ asFound String?
1851
+ asLeft String?
1852
+ withinTolerance Boolean
1853
+ adjustmentMade Boolean @default(false)
1854
+
1855
+ calibratedBy String
1856
+ certificateUrl String?
1857
+ certificateNo String?
1858
+
1859
+ reviewedBy String? // Changed from Int to String
1860
+ reviewedAt DateTime?
1861
+
1862
+ notes String?
1863
+
1864
+ createdAt DateTime @default(now())
1865
+ updatedAt DateTime @updatedAt
1866
+
1867
+ @@index([organizationId, nextDueDate])
1868
+ @@index([organizationId, equipmentId])
1869
+ @@index([deviceId])
1870
+ }
1871
+
1872
+ // ============================================================
1873
+ // TEXTILE & GARMENT COMPLIANCE (textile schema)
1874
+ // Regulatory: EU ESPR (DPP 2027), India Feb 2026 Labeling
1875
+ // Purpose: Digital Product Passports, supply chain traceability
1876
+ // ============================================================
1877
+
1878
+ enum PassportStatus {
1879
+ DRAFT
1880
+ PUBLISHED
1881
+ ACTIVE
1882
+ SUSPENDED
1883
+ REVOKED
1884
+ }
1885
+
1886
+ enum SupplyChainNodeType {
1887
+ RAW_MATERIAL_SUPPLIER
1888
+ SPINNING
1889
+ WEAVING
1890
+ KNITTING
1891
+ DYEING
1892
+ PRINTING
1893
+ FINISHING
1894
+ CUTTING
1895
+ SEWING
1896
+ EMBROIDERY
1897
+ WASHING
1898
+ QUALITY_CHECK
1899
+ PACKAGING
1900
+ DISTRIBUTION
1901
+ }
1902
+
1903
+ enum CertificationType {
1904
+ GOTS
1905
+ OEKO_TEX
1906
+ FAIR_TRADE
1907
+ ORGANIC_COTTON
1908
+ BCI
1909
+ BLUESIGN
1910
+ CRADLE_TO_CRADLE
1911
+ GRS
1912
+ ISO_14001
1913
+ WRAP
1914
+ SA8000
1915
+ }
1916
+
1917
+ model DigitalProductPassport {
1918
+ id String @id @default(cuid())
1919
+ organizationId Int
1920
+
1921
+ productionUnitId String? @unique
1922
+ productId Int?
1923
+ styleNumber String
1924
+ productName String
1925
+ productCategory String
1926
+
1927
+ publicUid String @unique @default(cuid())
1928
+ gtin String?
1929
+ taricCode String?
1930
+ hsnCode String?
1931
+
1932
+ qrCodeImageUrl String?
1933
+ qrCodeFormat String?
1934
+ qrCodeGeneratedAt DateTime?
1935
+
1936
+ fiberComposition Json
1937
+ primaryMaterial String
1938
+ recycledContent Float?
1939
+ organicContent Float?
1940
+
1941
+ careInstructions String
1942
+ washingSymbols String[]
1943
+
1944
+ manufacturerName String
1945
+ manufacturerAddress String
1946
+ brandName String?
1947
+ countryOfOrigin String
1948
+
1949
+ carbonFootprint Float?
1950
+ carbonCalculationMethod String?
1951
+ waterUsage Float?
1952
+ energyUsage Float?
1953
+ chemicalsUsed Json?
1954
+
1955
+ recyclability Int?
1956
+ durabilityRating String?
1957
+ repairability String?
1958
+ repairInstructions String?
1959
+ recyclingInstructions String?
1960
+ endOfLifeOptions String[]
1961
+
1962
+ microplasticRelease Float?
1963
+
1964
+ supplyChainNodes SupplyChainNode[] @relation("DPPSupplyChain")
1965
+ supplyChainEdges SupplyChainEdge[] @relation("DPPEdges")
1966
+ certificates ProductCertificate[] @relation("DPPCertificates")
1967
+
1968
+ laborCompliance Json?
1969
+ factoryCertifications String[]
1970
+
1971
+ scanCount Int @default(0)
1972
+ scans TextileQRScan[] @relation("DPPScans")
1973
+
1974
+ status PassportStatus @default(DRAFT)
1975
+ publishedAt DateTime?
1976
+ validUntil DateTime?
1977
+
1978
+ version String @default("v1.0")
1979
+ supersededBy String?
1980
+
1981
+ invoiceNumber String?
1982
+ shipmentDate DateTime?
1983
+ destinationCountry String?
1984
+ customsDocUrl String?
1985
+
1986
+ keywords String[]
1987
+ tags String[]
1988
+ internalNotes String?
1989
+
1990
+ signatures ElectronicSignature[] @relation("DPPSignatures")
1991
+
1992
+ createdAt DateTime @default(now())
1993
+ updatedAt DateTime @updatedAt
1994
+
1995
+ @@index([organizationId, status])
1996
+ @@index([publicUid])
1997
+ @@index([styleNumber])
1998
+ @@index([productId])
1999
+ @@index([gtin])
2000
+ }
2001
+
2002
+ model SupplyChainNode {
2003
+ id Int @id @default(autoincrement())
2004
+ dppId String
2005
+ dpp DigitalProductPassport @relation("DPPSupplyChain", fields: [dppId], references: [id], onDelete: Cascade)
2006
+
2007
+ nodeId String @unique
2008
+ nodeType SupplyChainNodeType
2009
+
2010
+ companyName String
2011
+ companyAddress String?
2012
+ contactPerson String?
2013
+ contactEmail String?
2014
+ location String
2015
+ coordinates String?
2016
+
2017
+ processDate DateTime
2018
+ processDuration Int?
2019
+ processDescription String?
2020
+
2021
+ outputMaterials Json?
2022
+
2023
+ certificates String[]
2024
+ certificateUrls Json?
2025
+
2026
+ energyUsed Float?
2027
+ waterUsed Float?
2028
+ wasteGenerated Float?
2029
+ emissionsGenerated Float?
2030
+
2031
+ qualityReports String?
2032
+
2033
+ isVerified Boolean @default(false)
2034
+ verifiedBy String?
2035
+ verifiedAt DateTime?
2036
+
2037
+ notes String?
2038
+
2039
+ incomingEdges SupplyChainEdge[] @relation("NodeInputs")
2040
+ outgoingEdges SupplyChainEdge[] @relation("NodeOutputs")
2041
+
2042
+ createdAt DateTime @default(now())
2043
+ updatedAt DateTime @updatedAt
2044
+
2045
+ @@index([dppId])
2046
+ @@index([nodeType])
2047
+ @@index([nodeId])
2048
+ }
2049
+
2050
+ model SupplyChainEdge {
2051
+ id Int @id @default(autoincrement())
2052
+ dppId String
2053
+ dpp DigitalProductPassport @relation("DPPEdges", fields: [dppId], references: [id], onDelete: Cascade)
2054
+
2055
+ fromNodeId String
2056
+ fromNode SupplyChainNode @relation("NodeOutputs", fields: [fromNodeId], references: [nodeId], onDelete: Cascade)
2057
+
2058
+ toNodeId String
2059
+ toNode SupplyChainNode @relation("NodeInputs", fields: [toNodeId], references: [nodeId], onDelete: Cascade)
2060
+
2061
+ materialType String
2062
+ materialBatchId String?
2063
+ quantity Float
2064
+ unit String
2065
+
2066
+ transferDate DateTime
2067
+ transportMethod String?
2068
+ invoiceNumber String?
2069
+
2070
+ documentUrl String?
2071
+
2072
+ createdAt DateTime @default(now())
2073
+
2074
+ @@unique([fromNodeId, toNodeId, materialBatchId])
2075
+ @@index([dppId])
2076
+ @@index([fromNodeId])
2077
+ @@index([toNodeId])
2078
+ }
2079
+
2080
+ model ProductCertificate {
2081
+ id Int @id @default(autoincrement())
2082
+ dppId String
2083
+ dpp DigitalProductPassport @relation("DPPCertificates", fields: [dppId], references: [id], onDelete: Cascade)
2084
+
2085
+ certificateType CertificationType
2086
+ certificateNumber String
2087
+ certificateName String?
2088
+
2089
+ issuedBy String
2090
+ issuerLogo String?
2091
+
2092
+ issuedDate DateTime
2093
+ expiryDate DateTime?
2094
+ isValid Boolean @default(true)
2095
+
2096
+ scope String?
2097
+
2098
+ certificateUrl String
2099
+ verificationUrl String?
2100
+
2101
+ createdAt DateTime @default(now())
2102
+ updatedAt DateTime @updatedAt
2103
+
2104
+ @@index([dppId])
2105
+ @@index([certificateType])
2106
+ @@index([expiryDate])
291
2107
  }
292
2108
 
293
- model ChatbotMessage {
294
- id Int @id @default(autoincrement())
295
- chatHistoryId Int
296
- sender ChatbotMessageSender
297
- message String
298
- tokensUsed Int
299
- jsonContent Json?
300
- chatHistory ChatbotHistory @relation(fields: [chatHistoryId], references: [id])
301
- createdAt DateTime @default(now())
302
- updatedAt DateTime @updatedAt
2109
+ model TextileQRScan {
2110
+ id String @id @default(cuid())
2111
+ dppId String
2112
+ dpp DigitalProductPassport @relation("DPPScans", fields: [dppId], references: [id], onDelete: Cascade)
303
2113
 
304
- @@index([chatHistoryId])
305
- @@index([tokensUsed])
306
- @@schema("chatbot")
2114
+ scannedAt DateTime @default(now())
2115
+
2116
+ ipAddress String?
2117
+ country String?
2118
+ city String?
2119
+ userAgent String?
2120
+
2121
+ timeOnPage Int?
2122
+ sectionsViewed String[]
2123
+
2124
+ referrer String?
2125
+ utmSource String?
2126
+ utmCampaign String?
2127
+
2128
+ @@index([dppId, scannedAt])
2129
+ @@index([country])
307
2130
  }
308
2131
 
309
2132
  enum SensorType {
@@ -311,31 +2134,89 @@ enum SensorType {
311
2134
  INFRARED
312
2135
  RFID
313
2136
  CURRENT
314
-
315
- @@schema("device")
2137
+ VIBRATION
2138
+ TEMPERATURE
2139
+ PRESSURE
2140
+ FLOW
2141
+ WEIGHT
2142
+ LEVEL
2143
+ PH
2144
+ HUMIDITY
316
2145
  }
317
2146
 
318
2147
  enum RFIDTapType {
319
2148
  CHECKIN
320
2149
  CHECKOUT
321
-
322
- @@schema("device")
323
2150
  }
324
2151
 
325
2152
  enum DevicePowerState {
326
2153
  POWER_ON
327
2154
  POWER_OFF
2155
+ }
328
2156
 
329
- @@schema("device")
2157
+ enum DeviceType {
2158
+ SENSOR_MODULE // Your current ESP32-based sensor boxes
2159
+ GATEWAY // Edge gateway (can do protocols)
2160
+ PLC // Direct PLC connection
2161
+ SCADA_RTU // SCADA remote terminal unit
2162
+ MODBUS_GATEWAY // Modbus-specific gateway
2163
+ MQTT_BRIDGE // MQTT bridge device
2164
+ PROTOCOL_CONVERTER // Multi-protocol converter
2165
+ HYBRID // Does both sensors + protocols
2166
+ }
2167
+
2168
+ enum CommunicationProtocol {
2169
+ // Industrial Ethernet
2170
+ MODBUS_TCP
2171
+ ETHERNET_IP
2172
+ PROFINET
2173
+ OPC_UA
2174
+ OPC_DA
2175
+ MQTT
2176
+ MQTT_SPARKPLUG_B
2177
+ HTTP_REST
2178
+ WEBSOCKET
2179
+
2180
+ // Serial/Fieldbus
2181
+ MODBUS_RTU
2182
+ MODBUS_ASCII
2183
+ RS232
2184
+ RS485
2185
+ PROFIBUS
2186
+ CANBUS
2187
+
2188
+ // PLC Proprietary
2189
+ SIEMENS_S7
2190
+ ALLEN_BRADLEY_DF1
2191
+ MITSUBISHI_MELSEC
2192
+ OMRON_FINS
2193
+ FANUC_FOCAS
2194
+ HEIDENHAIN_DNC
2195
+
2196
+ // Wireless
2197
+ BLUETOOTH_LE
2198
+ ZIGBEE
2199
+ LORA
2200
+ WIFI
2201
+
2202
+ // Legacy
2203
+ SERIAL_ASCII
2204
+ SERIAL_BINARY
330
2205
  }
331
2206
 
332
2207
  model Gateway {
333
- id Int @id @default(autoincrement())
334
- gatewayUid String @unique @default(cuid()) // Matches Core DB
335
- gatewayName String?
336
- isActive Boolean @default(true)
337
- floorId Int
338
- secret String
2208
+ id Int @id @default(autoincrement())
2209
+ gatewayUid String @unique @default(cuid())
2210
+ gatewayName String?
2211
+ globalInventoryDeviceId Int? @unique
2212
+ isActive Boolean @default(true)
2213
+ floorId Int
2214
+ secret String
2215
+
2216
+ // Hardware specs
2217
+ cpuModel String?
2218
+ ramMB Int?
2219
+ storageMB Int?
339
2220
 
340
2221
  // Network Config
341
2222
  currentWifiSSID String?
@@ -344,6 +2225,11 @@ model Gateway {
344
2225
  fallBackWifiSSID String?
345
2226
  fallBackWifiPassword String?
346
2227
 
2228
+ // Edge compute config
2229
+ edgeAnalytics Boolean @default(false)
2230
+ bufferSizeMB Int? @default(100)
2231
+ offlineMode Boolean @default(true)
2232
+
347
2233
  devices Device[] @relation("GatewayToDevices")
348
2234
  floor Floor @relation("FloorToGateways", fields: [floorId], references: [id])
349
2235
  apiToken GatewayApiToken?
@@ -352,7 +2238,6 @@ model Gateway {
352
2238
  updatedAt DateTime @updatedAt
353
2239
 
354
2240
  @@index([floorId])
355
- @@schema("device")
356
2241
  }
357
2242
 
358
2243
  model GatewayApiToken {
@@ -363,25 +2248,39 @@ model GatewayApiToken {
363
2248
  gateway Gateway @relation(fields: [gatewayId], references: [id])
364
2249
  createdAt DateTime @default(now())
365
2250
  updatedAt DateTime @updatedAt
366
-
367
- @@schema("device")
368
2251
  }
369
2252
 
370
2253
  model Device {
371
2254
  id Int @id @default(autoincrement())
372
2255
 
373
- // PRODUCTION CRITICAL: The Link to your Global Inventory
374
- globalDeviceUid String @unique // Immutable ID printed on the sticker (Core DB)
2256
+ globalDeviceUid String @unique
2257
+ deviceUid String @unique @default(cuid())
2258
+ globalInventoryDeviceId Int? @unique
2259
+ deviceName String?
2260
+ isActive Boolean @default(true)
2261
+ organizationId Int
2262
+ gatewayId Int?
375
2263
 
376
- deviceUid String @unique @default(cuid()) // Local Internal ID
377
- deviceName String?
378
- isActive Boolean @default(true)
379
- organizationId Int
380
- gatewayId Int?
2264
+ deviceType DeviceType @default(SENSOR_MODULE)
2265
+ deviceModel String? // "ESP32-WROOM", "Siemens S7-1200", "Advantech ADAM-4571"
2266
+ firmwareVersion String?
2267
+
2268
+ // Communication capabilities (can support multiple)
2269
+
2270
+ // Network addressing
2271
+ ipAddress String?
2272
+ macAddress String?
2273
+ subnet String?
2274
+ port Int?
2275
+
2276
+ // Serial config (if RS485/RS232)
2277
+ serialConfig Json? // {baudRate: 9600, parity: "N", stopBits: 1, dataBits: 8}
381
2278
 
382
2279
  // Hardware
383
- sensors Sensor[] @relation("DeviceSensors")
384
- gateway Gateway? @relation("GatewayToDevices", fields: [gatewayId], references: [id])
2280
+ sensors Sensor[] @relation("DeviceSensors")
2281
+ gateway Gateway? @relation("GatewayToDevices", fields: [gatewayId], references: [id])
2282
+ protocolDataSources ProtocolDataSource[] @relation("DeviceProtocolDataSources")
2283
+ deviceConnections DeviceConnection[] @relation("DeviceConnections")
385
2284
 
386
2285
  // Usage
387
2286
  tasks Task[] @relation("Device_UsedInTasks")
@@ -407,7 +2306,7 @@ model Device {
407
2306
  @@index([gatewayId])
408
2307
  @@index([machineId])
409
2308
  @@index([factoryId])
410
- @@schema("device")
2309
+ @@index([ipAddress])
411
2310
  }
412
2311
 
413
2312
  model Sensor {
@@ -418,13 +2317,21 @@ model Sensor {
418
2317
  deviceId Int
419
2318
  isActive Boolean @default(true)
420
2319
 
2320
+ isVirtual Boolean @default(false) // true if sourced from PLC/Modbus/MQTT
2321
+ protocolDataSource ProtocolDataSource? @relation("ProtocolDataSourceToSensor")
2322
+
421
2323
  device Device @relation("DeviceSensors", fields: [deviceId], references: [id])
422
2324
  sensorLogs SensorLog[] @relation("Sensor_SensorLogs")
423
2325
 
424
- // Configs
425
- proximityConfig ProximitySensorConfig?
426
- infraredConfig InfraredSensorConfig?
427
- currentConfig CurrentSensorConfig?
2326
+ // Configs (one-to-one per sensor type)
2327
+ proximityConfig ProximitySensorConfig?
2328
+ infraredConfig InfraredSensorConfig?
2329
+ currentConfig CurrentSensorConfig?
2330
+ vibrationConfig VibrationSensorConfig?
2331
+ temperatureConfig TemperatureSensorConfig?
2332
+ flowConfig FlowSensorConfig?
2333
+ weightConfig WeightSensorConfig?
2334
+ pressureConfig PressureSensorConfig?
428
2335
 
429
2336
  // Locations
430
2337
  machineId Int?
@@ -442,7 +2349,7 @@ model Sensor {
442
2349
  updatedAt DateTime @updatedAt
443
2350
 
444
2351
  @@index([deviceId])
445
- @@schema("device")
2352
+ @@index([isVirtual])
446
2353
  }
447
2354
 
448
2355
  model ProximitySensorConfig {
@@ -454,19 +2361,23 @@ model ProximitySensorConfig {
454
2361
  sensor Sensor @relation(fields: [sensorId], references: [id], onDelete: Cascade)
455
2362
  createdAt DateTime @default(now())
456
2363
  updatedAt DateTime @updatedAt
457
-
458
- @@schema("device")
459
2364
  }
460
2365
 
461
2366
  model CurrentSensorConfig {
462
- id Int @id @default(autoincrement())
463
- sensorId Int @unique
464
- currentThreshold Float?
465
- sensor Sensor @relation(fields: [sensorId], references: [id], onDelete: Cascade)
466
- createdAt DateTime @default(now())
467
- updatedAt DateTime @updatedAt
468
-
469
- @@schema("device")
2367
+ id Int @id @default(autoincrement())
2368
+ sensorId Int @unique
2369
+ currentThreshold Float? // Existing
2370
+
2371
+ ctRatio String? @default("100:5")
2372
+ burdenResistor Float? // Ohms
2373
+ calibrationGain Float? @default(1.0)
2374
+ idleThreshold Float? // Below = IDLE
2375
+ runThreshold Float? // Above = RUN
2376
+ samplingRateHz Int? @default(10)
2377
+
2378
+ sensor Sensor @relation(fields: [sensorId], references: [id], onDelete: Cascade)
2379
+ createdAt DateTime @default(now())
2380
+ updatedAt DateTime @updatedAt
470
2381
  }
471
2382
 
472
2383
  model InfraredSensorConfig {
@@ -478,8 +2389,6 @@ model InfraredSensorConfig {
478
2389
  sensor Sensor @relation(fields: [sensorId], references: [id], onDelete: Cascade)
479
2390
  createdAt DateTime @default(now())
480
2391
  updatedAt DateTime @updatedAt
481
-
482
- @@schema("device")
483
2392
  }
484
2393
 
485
2394
  model MachineDeviceAssignment {
@@ -495,7 +2404,65 @@ model MachineDeviceAssignment {
495
2404
  @@index([machineId])
496
2405
  @@index([assignedAt])
497
2406
  @@index([unassignedAt])
498
- @@schema("device")
2407
+ }
2408
+
2409
+ model VibrationSensorConfig {
2410
+ id Int @id @default(autoincrement())
2411
+ sensorId Int @unique
2412
+ samplingRateHz Int? @default(1000)
2413
+ rangeG Float? @default(16.0)
2414
+ fftEnabled Boolean @default(false)
2415
+ sensor Sensor @relation(fields: [sensorId], references: [id], onDelete: Cascade)
2416
+ createdAt DateTime @default(now())
2417
+ updatedAt DateTime @updatedAt
2418
+ }
2419
+
2420
+ model TemperatureSensorConfig {
2421
+ id Int @id @default(autoincrement())
2422
+ sensorId Int @unique
2423
+ sensorModel String? // "PT100", "PT1000", "NTC", "Thermocouple_K"
2424
+ minTemp Float?
2425
+ maxTemp Float?
2426
+ alertThreshold Float?
2427
+ sensor Sensor @relation(fields: [sensorId], references: [id], onDelete: Cascade)
2428
+ createdAt DateTime @default(now())
2429
+ updatedAt DateTime @updatedAt
2430
+ }
2431
+
2432
+ model FlowSensorConfig {
2433
+ id Int @id @default(autoincrement())
2434
+ sensorId Int @unique
2435
+ unit String @default("LITERS_PER_MINUTE") // or "KG_PER_HOUR"
2436
+ calibrationFactor Float? @default(1.0)
2437
+ minFlow Float?
2438
+ maxFlow Float?
2439
+ sensor Sensor @relation(fields: [sensorId], references: [id], onDelete: Cascade)
2440
+ createdAt DateTime @default(now())
2441
+ updatedAt DateTime @updatedAt
2442
+ }
2443
+
2444
+ model WeightSensorConfig {
2445
+ id Int @id @default(autoincrement())
2446
+ sensorId Int @unique
2447
+ unit String @default("KG")
2448
+ maxCapacity Float?
2449
+ resolution Float? // Smallest measurable change
2450
+ tareWeight Float?
2451
+ sensor Sensor @relation(fields: [sensorId], references: [id], onDelete: Cascade)
2452
+ createdAt DateTime @default(now())
2453
+ updatedAt DateTime @updatedAt
2454
+ }
2455
+
2456
+ model PressureSensorConfig {
2457
+ id Int @id @default(autoincrement())
2458
+ sensorId Int @unique
2459
+ unit String @default("BAR") // or "PSI", "KPA"
2460
+ minPressure Float?
2461
+ maxPressure Float?
2462
+ alertThreshold Float?
2463
+ sensor Sensor @relation(fields: [sensorId], references: [id], onDelete: Cascade)
2464
+ createdAt DateTime @default(now())
2465
+ updatedAt DateTime @updatedAt
499
2466
  }
500
2467
 
501
2468
  model SensorLog {
@@ -505,11 +2472,17 @@ model SensorLog {
505
2472
  isProcessed Boolean @default(false)
506
2473
  sensor Sensor @relation("Sensor_SensorLogs", fields: [sensorId], references: [id])
507
2474
 
2475
+ // Polymorphic logs (one active per SensorLog)
508
2476
  proximityLog ProximitySensorLog? @relation("SensorLogProximityLog")
509
2477
  infraredLog InfraredSensorLog? @relation("SensorLogInfraredLog")
510
2478
  rfidLog RFIDSensorLog? @relation("SensorLogRFIDSensorLog")
511
2479
  devicePowerLog DevicePowerSensorLog? @relation("SensorLogDevicePowerSensorLog")
512
2480
  currentLog CurrentSensorLog? @relation("SensorLogCurrentLog")
2481
+ vibrationLog VibrationSensorLog? @relation("SensorLogVibrationLog")
2482
+ temperatureLog TemperatureSensorLog? @relation("SensorLogTemperatureLog")
2483
+ flowLog FlowSensorLog? @relation("SensorLogFlowLog")
2484
+ weightLog WeightSensorLog? @relation("SensorLogWeightLog")
2485
+ pressureLog PressureSensorLog? @relation("SensorLogPressureLog")
513
2486
 
514
2487
  createdAt DateTime @default(now())
515
2488
  updatedAt DateTime @default(now())
@@ -518,7 +2491,6 @@ model SensorLog {
518
2491
  @@index([isProcessed])
519
2492
  @@index([sensorId, isProcessed])
520
2493
  @@index([senseTime])
521
- @@schema("device")
522
2494
  }
523
2495
 
524
2496
  model RFIDSensorLog {
@@ -526,7 +2498,7 @@ model RFIDSensorLog {
526
2498
  sensorLogId BigInt @unique
527
2499
  rfid String?
528
2500
  tapType RFIDTapType
529
- operatorId Int?
2501
+ operatorId String?
530
2502
 
531
2503
  sensorLog SensorLog @relation("SensorLogRFIDSensorLog", fields: [sensorLogId], references: [id], onDelete: Cascade)
532
2504
  operator Operator? @relation("OperatorToSensorLogs", fields: [operatorId], references: [id])
@@ -537,7 +2509,6 @@ model RFIDSensorLog {
537
2509
  @@index([operatorId])
538
2510
  @@index([rfid])
539
2511
  @@index([sensorLogId])
540
- @@schema("device")
541
2512
  }
542
2513
 
543
2514
  model ProximitySensorLog {
@@ -546,8 +2517,6 @@ model ProximitySensorLog {
546
2517
  sensorLog SensorLog @relation("SensorLogProximityLog", fields: [sensorLogId], references: [id], onDelete: Cascade)
547
2518
  createdAt DateTime @default(now())
548
2519
  updatedAt DateTime @updatedAt
549
-
550
- @@schema("device")
551
2520
  }
552
2521
 
553
2522
  model InfraredSensorLog {
@@ -556,8 +2525,6 @@ model InfraredSensorLog {
556
2525
  sensorLog SensorLog @relation("SensorLogInfraredLog", fields: [sensorLogId], references: [id], onDelete: Cascade)
557
2526
  createdAt DateTime @default(now())
558
2527
  updatedAt DateTime @updatedAt
559
-
560
- @@schema("device")
561
2528
  }
562
2529
 
563
2530
  model CurrentSensorLog {
@@ -567,8 +2534,6 @@ model CurrentSensorLog {
567
2534
  sensorLog SensorLog @relation("SensorLogCurrentLog", fields: [sensorLogId], references: [id], onDelete: Cascade)
568
2535
  createdAt DateTime @default(now())
569
2536
  updatedAt DateTime @updatedAt
570
-
571
- @@schema("device")
572
2537
  }
573
2538
 
574
2539
  model DevicePowerSensorLog {
@@ -578,8 +2543,196 @@ model DevicePowerSensorLog {
578
2543
  sensorLog SensorLog @relation("SensorLogDevicePowerSensorLog", fields: [sensorLogId], references: [id], onDelete: Cascade)
579
2544
  createdAt DateTime @default(now())
580
2545
  updatedAt DateTime @updatedAt
2546
+ }
2547
+
2548
+ model VibrationSensorLog {
2549
+ id BigInt @id @default(autoincrement()) @db.BigInt
2550
+ sensorLogId BigInt @unique
2551
+ rmsValue Float? // RMS acceleration
2552
+ peakValue Float?
2553
+ frequency Float? // Dominant frequency if FFT done
2554
+ fftData Json? // Optional: store FFT bins
2555
+ sensorLog SensorLog @relation("SensorLogVibrationLog", fields: [sensorLogId], references: [id], onDelete: Cascade)
2556
+ createdAt DateTime @default(now())
2557
+ updatedAt DateTime @updatedAt
2558
+ }
2559
+
2560
+ model TemperatureSensorLog {
2561
+ id BigInt @id @default(autoincrement()) @db.BigInt
2562
+ sensorLogId BigInt @unique
2563
+ temperature Float
2564
+ sensorLog SensorLog @relation("SensorLogTemperatureLog", fields: [sensorLogId], references: [id], onDelete: Cascade)
2565
+ createdAt DateTime @default(now())
2566
+ updatedAt DateTime @updatedAt
2567
+ }
2568
+
2569
+ model FlowSensorLog {
2570
+ id BigInt @id @default(autoincrement()) @db.BigInt
2571
+ sensorLogId BigInt @unique
2572
+ flowRate Float
2573
+ totalVolume Float? // Cumulative since reset
2574
+ sensorLog SensorLog @relation("SensorLogFlowLog", fields: [sensorLogId], references: [id], onDelete: Cascade)
2575
+ createdAt DateTime @default(now())
2576
+ updatedAt DateTime @updatedAt
2577
+ }
2578
+
2579
+ model WeightSensorLog {
2580
+ id BigInt @id @default(autoincrement()) @db.BigInt
2581
+ sensorLogId BigInt @unique
2582
+ weight Float
2583
+ sensorLog SensorLog @relation("SensorLogWeightLog", fields: [sensorLogId], references: [id], onDelete: Cascade)
2584
+ createdAt DateTime @default(now())
2585
+ updatedAt DateTime @updatedAt
2586
+ }
2587
+
2588
+ model PressureSensorLog {
2589
+ id BigInt @id @default(autoincrement()) @db.BigInt
2590
+ sensorLogId BigInt @unique
2591
+ pressure Float
2592
+ sensorLog SensorLog @relation("SensorLogPressureLog", fields: [sensorLogId], references: [id], onDelete: Cascade)
2593
+ createdAt DateTime @default(now())
2594
+ updatedAt DateTime @updatedAt
2595
+ }
2596
+
2597
+ enum DataSourceType {
2598
+ PHYSICAL_SENSOR // Your existing sensor hardware
2599
+ MODBUS_REGISTER // Modbus holding/input supportedProtocols
2600
+ MODBUS_COIL // Modbus coil/discrete input
2601
+ MQTT_TOPIC // MQTT subscription
2602
+ OPC_UA_NODE // OPC-UA node ID
2603
+ PLC_TAG // PLC memory address/tag
2604
+ SCADA_POINT // SCADA point/tag
2605
+ REST_ENDPOINT // HTTP REST API
2606
+ }
2607
+
2608
+ model ProtocolDataSource {
2609
+ id Int @id @default(autoincrement())
2610
+ deviceId Int
2611
+ sourceType DataSourceType
2612
+ sourceName String // Human-readable name
2613
+ description String?
2614
+ isActive Boolean @default(true)
2615
+
2616
+ // Generic addressing
2617
+ address String? // Modbus: "40001", MQTT: "factory/machine1/temp", OPC-UA: "ns=2;s=Temperature"
2618
+
2619
+ // Protocol-specific config (JSON for flexibility)
2620
+ protocolConfig Json?
2621
+ /**
2622
+ * Modbus example:
2623
+ * {
2624
+ * "slaveId": 1,
2625
+ * "function": "READ_HOLDING_REGISTERS",
2626
+ * "register": 40001,
2627
+ * "quantity": 1,
2628
+ * "dataType": "FLOAT32_ABCD",
2629
+ * "scaleFactor": 0.1
2630
+ * }
2631
+ * MQTT example:
2632
+ * {
2633
+ * "topic": "factory/line1/machine5/spindle/current",
2634
+ * "qos": 1,
2635
+ * "jsonPath": "$.value",
2636
+ * "dataType": "FLOAT"
2637
+ * }
2638
+ * OPC-UA example:
2639
+ * {
2640
+ * "nodeId": "ns=2;s=Machine.Spindle.Current",
2641
+ * "samplingInterval": 1000,
2642
+ * "dataType": "Double"
2643
+ * }
2644
+ * PLC Tag example:
2645
+ * {
2646
+ * "plcType": "SIEMENS_S7",
2647
+ * "dbNumber": 100,
2648
+ * "offset": 0,
2649
+ * "dataType": "REAL",
2650
+ * "tagName": "SpindleCurrent"
2651
+ * }
2652
+ */
2653
+
2654
+ // Data transformation
2655
+ dataType String? // "FLOAT", "INT16", "BOOL", "STRING"
2656
+ unit String? // "AMPERE", "CELSIUS", "BAR"
2657
+ scaleFactor Float? @default(1.0)
2658
+ offset Float? @default(0.0)
2659
+
2660
+ // Polling/sampling
2661
+ pollingInterval Int? // Milliseconds
2662
+ onChangeOnly Boolean @default(false)
2663
+
2664
+ // Link to existing sensor model (if physical)
2665
+ sensorId Int? @unique
2666
+ sensor Sensor? @relation("ProtocolDataSourceToSensor", fields: [sensorId], references: [id])
2667
+
2668
+ // Or link to machine directly
2669
+ machineId Int?
2670
+ machine Machine? @relation("MachineProtocolDataSources", fields: [machineId], references: [id])
2671
+
2672
+ device Device @relation("DeviceProtocolDataSources", fields: [deviceId], references: [id])
2673
+ dataLogs ProtocolDataLog[] @relation("DataSourceLogs")
2674
+
2675
+ hourlyAnalytics ProtocolDataSourceHourlyAnalytics[] @relation("ProtocolDataSourceAnalytics")
2676
+ createdAt DateTime @default(now())
2677
+ updatedAt DateTime @updatedAt
581
2678
 
582
- @@schema("device")
2679
+ @@index([deviceId])
2680
+ @@index([sourceType])
2681
+ @@index([machineId])
2682
+ }
2683
+
2684
+ // Generic log for protocol-sourced data (before it becomes SensorLog)
2685
+ model ProtocolDataLog {
2686
+ id BigInt @id @default(autoincrement()) @db.BigInt
2687
+ dataSourceId Int
2688
+ timestamp DateTime
2689
+ rawValue String? // Store as string initially
2690
+ parsedValue Float? // Numeric after parsing
2691
+ stringValue String? // If text/enum
2692
+ boolValue Boolean? // If boolean
2693
+ isProcessed Boolean @default(false)
2694
+
2695
+ dataSource ProtocolDataSource @relation("DataSourceLogs", fields: [dataSourceId], references: [id])
2696
+
2697
+ createdAt DateTime @default(now())
2698
+
2699
+ @@unique([dataSourceId, timestamp])
2700
+ @@index([dataSourceId, isProcessed])
2701
+ @@index([timestamp])
2702
+ }
2703
+
2704
+ model DeviceConnection {
2705
+ id Int @id @default(autoincrement())
2706
+ parentDeviceId Int // Gateway/Master
2707
+ childDeviceId Int // Slave/Subordinate
2708
+ protocol CommunicationProtocol
2709
+ connectionConfig Json?
2710
+ /**
2711
+ * Modbus RTU over RS485 example:
2712
+ * {
2713
+ * "slaveId": 1,
2714
+ * "baudRate": 9600,
2715
+ * "parity": "N",
2716
+ * "stopBits": 1
2717
+ * }
2718
+ * Ethernet example:
2719
+ * {
2720
+ * "ipAddress": "192.168.1.100",
2721
+ * "port": 502,
2722
+ * "timeout": 5000
2723
+ * }
2724
+ */
2725
+
2726
+ isActive Boolean @default(true)
2727
+ lastSeen DateTime?
2728
+
2729
+ parentDevice Device @relation("DeviceConnections", fields: [parentDeviceId], references: [id])
2730
+
2731
+ createdAt DateTime @default(now())
2732
+ updatedAt DateTime @updatedAt
2733
+
2734
+ @@unique([parentDeviceId, childDeviceId, protocol])
2735
+ @@index([parentDeviceId])
583
2736
  }
584
2737
 
585
2738
  enum WeekDay {
@@ -590,15 +2743,11 @@ enum WeekDay {
590
2743
  THURSDAY
591
2744
  FRIDAY
592
2745
  SATURDAY
593
-
594
- @@schema("factory")
595
2746
  }
596
2747
 
597
2748
  enum AccessLevel {
598
2749
  PUBLIC
599
2750
  PRIVATE
600
-
601
- @@schema("factory")
602
2751
  }
603
2752
 
604
2753
  model Factory {
@@ -609,39 +2758,30 @@ model Factory {
609
2758
  timeZone String @default("UTC+5:30")
610
2759
  timeZoneString String @default("Asia/Kolkata")
611
2760
 
612
- // Hierarchy
613
2761
  floors Floor[] @relation("FactoryToFloors")
614
2762
  shifts FactoryShift[] @relation("FactoryToShifts")
615
2763
 
616
- // Assets & IoT
617
2764
  sensors Sensor[] @relation("FactoryToSensors")
618
2765
  devicesDirect Device[] @relation("FactoryToDevicesDirect")
619
2766
 
620
- // People
621
2767
  operators Operator[] @relation("FactoryToOperators")
622
2768
  technicians MaintenanceTechnician[] @relation("FactoryToTechnicians")
623
2769
 
624
- // Mini-ERP & Production
625
2770
  finalProducts FinalProduct[] @relation("FactoryToFinalProducts")
626
2771
  orders Order[] @relation("FactoryToOrders")
627
2772
  lots FactoryLot[] @relation("Factory_Lots")
628
2773
 
629
- // Task Management
630
2774
  tasksHistory Task[] @relation("Factory_Tasks")
631
2775
  taskGroups TaskGroup[] @relation("Factory_TaskGroups")
632
2776
  opCategories OperatorOperationCategory[] @relation("Factory_OperatorOperationCategories")
633
2777
 
634
- // Maintenance & Analytics
635
2778
  requestCategories MaintenanceRequestCategory[] @relation("FactoryMaintenanceRequestCategories")
636
2779
  hourlyAnalytics FactoryHourlyAnalytics[] @relation("FactoryToHourlyAnalytics")
637
2780
 
638
- userAccess OrganizationUserFactoryEntityAccess[] @relation("UserToFactory")
639
-
640
2781
  createdAt DateTime @default(now())
641
2782
  updatedAt DateTime @updatedAt
642
2783
 
643
2784
  @@index([organizationId])
644
- @@schema("factory")
645
2785
  }
646
2786
 
647
2787
  model Floor {
@@ -654,15 +2794,12 @@ model Floor {
654
2794
  searchTags String[] @default([])
655
2795
  accessLevel AccessLevel @default(PUBLIC)
656
2796
 
657
- // Relations
658
2797
  lines AssemblyLine[] @relation("FloorToLines")
659
2798
  gateways Gateway[] @relation("FloorToGateways")
660
2799
  sensors Sensor[] @relation("FloorToSensors")
661
2800
  devicesDirect Device[] @relation("FloorToDevicesDirect")
662
2801
  hourlyAnalytics FloorHourlyAnalytics[] @relation("FloorToHourlyAnalytics")
663
2802
 
664
- userAccess OrganizationUserFactoryEntityAccess[] @relation("UserToFloors")
665
-
666
2803
  floorTypeId Int?
667
2804
  floorType FloorType? @relation("FloorToFloorType", fields: [floorTypeId], references: [id])
668
2805
  settings FloorSetting? @relation("FloorsToFloorSettings")
@@ -672,7 +2809,6 @@ model Floor {
672
2809
  updatedAt DateTime @updatedAt
673
2810
 
674
2811
  @@index([factoryId])
675
- @@schema("factory")
676
2812
  }
677
2813
 
678
2814
  model FloorType {
@@ -684,7 +2820,7 @@ model FloorType {
684
2820
  updatedAt DateTime @updatedAt
685
2821
 
686
2822
  @@unique([organizationId, name])
687
- @@schema("factory")
2823
+ @@index([organizationId])
688
2824
  }
689
2825
 
690
2826
  model FloorSetting {
@@ -702,8 +2838,6 @@ model FloorSetting {
702
2838
  floor Floor @relation("FloorsToFloorSettings", fields: [floorId], references: [id])
703
2839
  createdAt DateTime @default(now())
704
2840
  updatedAt DateTime @updatedAt
705
-
706
- @@schema("factory")
707
2841
  }
708
2842
 
709
2843
  model AssemblyLine {
@@ -719,9 +2853,6 @@ model AssemblyLine {
719
2853
  devicesDirect Device[] @relation("AssemblyLineToDevicesDirect")
720
2854
  hourlyAnalytics LineHourlyAnalytics[] @relation("LineToHourlyAnalytics")
721
2855
 
722
- // Access Control (FIXED: Added this relation)
723
- userAccess OrganizationUserFactoryEntityAccess[] @relation("UserToAssemblyLines")
724
-
725
2856
  floor Floor @relation("FloorToLines", fields: [floorId], references: [id])
726
2857
  machineOrder Int[] @default([])
727
2858
  assemblyLineTypeId Int?
@@ -730,7 +2861,7 @@ model AssemblyLine {
730
2861
  updatedAt DateTime @updatedAt
731
2862
 
732
2863
  @@index([floorId])
733
- @@schema("factory")
2864
+ @@index([organizationId])
734
2865
  }
735
2866
 
736
2867
  model FactoryShift {
@@ -748,7 +2879,6 @@ model FactoryShift {
748
2879
  updatedAt DateTime @updatedAt
749
2880
 
750
2881
  @@index([factoryId])
751
- @@schema("factory")
752
2882
  }
753
2883
 
754
2884
  model FactoryShiftMachine {
@@ -758,15 +2888,18 @@ model FactoryShiftMachine {
758
2888
  shift FactoryShift @relation("ShiftToMachineAssignments", fields: [shiftId], references: [id])
759
2889
  machine Machine? @relation("MachineToShiftAssignments", fields: [machineId], references: [id])
760
2890
 
761
- @@schema("factory")
2891
+ @@index([shiftId])
2892
+ @@index([machineId])
762
2893
  }
763
2894
 
764
2895
  model FactoryLot {
765
- id Int @id @default(autoincrement())
766
- lotNumber String
767
- receivedAt DateTime
768
- expiryAt DateTime?
769
- factoryId Int
2896
+ id Int @id @default(autoincrement())
2897
+ lotNumber String
2898
+ factoryId Int
2899
+ manufacturingDate DateTime?
2900
+ expiryDate DateTime?
2901
+ quantity Float?
2902
+ measurementUnit ProductionMeasurementUnit?
770
2903
 
771
2904
  tasks TaskLot[] @relation("TaskToLots")
772
2905
  taskGroups TaskGroupLot[] @relation("TaskGroupToLots")
@@ -775,15 +2908,15 @@ model FactoryLot {
775
2908
  createdAt DateTime @default(now())
776
2909
  updatedAt DateTime @updatedAt
777
2910
 
2911
+ @@unique([factoryId, lotNumber])
778
2912
  @@index([factoryId])
779
- @@schema("factory")
2913
+ @@index([lotNumber])
780
2914
  }
781
2915
 
782
2916
  model FinalProduct {
783
2917
  id Int @id @default(autoincrement())
784
2918
 
785
- // ERP OVERLAY FIELDS
786
- externalId String? // REMOVED @index here
2919
+ externalId String?
787
2920
 
788
2921
  name String
789
2922
  code String?
@@ -797,8 +2930,9 @@ model FinalProduct {
797
2930
  createdAt DateTime @default(now())
798
2931
  updatedAt DateTime @updatedAt
799
2932
 
800
- @@index([externalId]) // ADDED here
801
- @@schema("inventory")
2933
+ @@unique([factoryId, code])
2934
+ @@index([externalId])
2935
+ @@index([factoryId])
802
2936
  }
803
2937
 
804
2938
  model FinalProductRoute {
@@ -817,7 +2951,8 @@ model FinalProductRoute {
817
2951
  createdAt DateTime @default(now())
818
2952
  updatedAt DateTime @updatedAt
819
2953
 
820
- @@schema("inventory")
2954
+ @@index([finalProductId])
2955
+ @@index([finalProductId, sequence])
821
2956
  }
822
2957
 
823
2958
  model FinalProductMachineOperationRoute {
@@ -834,7 +2969,9 @@ model FinalProductMachineOperationRoute {
834
2969
  createdAt DateTime @default(now())
835
2970
  updatedAt DateTime @updatedAt
836
2971
 
837
- @@schema("inventory")
2972
+ @@index([routeId])
2973
+ @@index([operationId])
2974
+ @@index([routeId, sequence])
838
2975
  }
839
2976
 
840
2977
  model FinalProductRouteDependency {
@@ -844,15 +2981,17 @@ model FinalProductRouteDependency {
844
2981
  dependsOnRoute FinalProductRoute @relation("FinalProductRoute_Prerequisite", fields: [dependsOnRouteId], references: [id], onDelete: Cascade)
845
2982
 
846
2983
  @@id([routeId, dependsOnRouteId])
847
- @@schema("inventory")
2984
+ @@index([routeId])
2985
+ @@index([dependsOnRouteId])
848
2986
  }
849
2987
 
850
2988
  enum ProductionSIUnit {
851
- COUNT
852
- WEIGHT
853
- LITERS
854
-
855
- @@schema("machine")
2989
+ COUNT // Garments, parts
2990
+ WEIGHT // KG - bulk materials
2991
+ LITERS // Liquids
2992
+ METERS // Cable, fabric rolls
2993
+ BATCHES // Process industries
2994
+ HOURS // Service time
856
2995
  }
857
2996
 
858
2997
  enum MachineAlertSeverity {
@@ -860,8 +2999,6 @@ enum MachineAlertSeverity {
860
2999
  MEDIUM
861
3000
  HIGH
862
3001
  CRITICAL
863
-
864
- @@schema("machine")
865
3002
  }
866
3003
 
867
3004
  enum EventCategory {
@@ -869,15 +3006,76 @@ enum EventCategory {
869
3006
  MEDIUM
870
3007
  OPERATION
871
3008
  ALERT
872
-
873
- @@schema("machine")
874
3009
  }
875
3010
 
876
3011
  enum MachineTrackingType {
877
3012
  MANUAL
878
3013
  AUTOMATED
3014
+ }
3015
+
3016
+ enum MachineState {
3017
+ UNKNOWN
3018
+ RUNNING
3019
+ IDLE
3020
+ STOPPED
3021
+ ALARM
3022
+ SETUP
3023
+ MAINTENANCE
3024
+ }
3025
+
3026
+ enum MachineIndustryType {
3027
+ GARMENT
3028
+ CNC_MACHINING
3029
+ FOOD_BEVERAGE
3030
+ PHARMACEUTICAL
3031
+ AUTOMOTIVE
3032
+ PAPER
3033
+ PLASTICS
3034
+ GENERAL
3035
+ }
3036
+
3037
+ model MachineStateLog {
3038
+ id BigInt @id @default(autoincrement()) @db.BigInt
3039
+ machineId Int
3040
+ state MachineState
3041
+ startTime DateTime
3042
+ endTime DateTime?
3043
+ durationSec Int? // Computed on end
3044
+ metadata Json? // Store context: cycle#, alarm code, operator, etc.
3045
+ programId Int?
3046
+
3047
+ machine Machine @relation("MachineStateLogs", fields: [machineId], references: [id])
3048
+
3049
+ createdAt DateTime @default(now())
3050
+ updatedAt DateTime @updatedAt
3051
+
3052
+ @@index([machineId, startTime])
3053
+ @@index([state, startTime])
3054
+ }
3055
+
3056
+ model MachineProgram {
3057
+ id Int @id @default(autoincrement())
3058
+ machineId Int
3059
+ programNumber String // "O1234" for Fanuc, etc.
3060
+ programName String?
3061
+ description String?
3062
+
3063
+ // Expected metrics (for comparison/baseline)
3064
+ expectedCycleTime Int? // Seconds
3065
+ expectedPowerProfile Json? // Store power signature
3066
+
3067
+ isActive Boolean @default(true)
3068
+ lastRunAt DateTime?
3069
+ totalRuns Int @default(0)
879
3070
 
880
- @@schema("machine")
3071
+ machine Machine @relation("MachinePrograms", fields: [machineId], references: [id])
3072
+ machinesUsingThis Machine[] @relation("MachineCurrentProgram")
3073
+
3074
+ createdAt DateTime @default(now())
3075
+ updatedAt DateTime @updatedAt
3076
+
3077
+ @@unique([machineId, programNumber])
3078
+ @@index([machineId])
881
3079
  }
882
3080
 
883
3081
  model Machine {
@@ -889,6 +3087,21 @@ model Machine {
889
3087
  machineOperationId Int?
890
3088
  trackingType MachineTrackingType @default(MANUAL)
891
3089
 
3090
+ currentProgramId Int?
3091
+ currentProgram MachineProgram? @relation("MachineCurrentProgram", fields: [currentProgramId], references: [id])
3092
+ programs MachineProgram[] @relation("MachinePrograms")
3093
+
3094
+ // Industry & capabilities
3095
+ industryType MachineIndustryType? @default(GENERAL)
3096
+ machineModel String?
3097
+ capabilities Json?
3098
+
3099
+ primaryProtocol CommunicationProtocol?
3100
+
3101
+ // Connection health
3102
+ isConnected Boolean @default(false)
3103
+ lastDataReceived DateTime?
3104
+
892
3105
  // Production & Tasks
893
3106
  tasks Task[] @relation("Machine_UsedInTasks")
894
3107
 
@@ -897,6 +3110,9 @@ model Machine {
897
3110
  operation MachineOperation? @relation("OperationToMachine", fields: [machineOperationId], references: [id])
898
3111
  shifts FactoryShiftMachine[] @relation("MachineToShiftAssignments")
899
3112
 
3113
+ stateLogs MachineStateLog[] @relation("MachineStateLogs")
3114
+ protocolDataSources ProtocolDataSource[] @relation("MachineProtocolDataSources")
3115
+
900
3116
  // Hardware
901
3117
  sensors Sensor[] @relation("MachineToSensors")
902
3118
  devicesDirect Device[] @relation("MachineToDevicesDirect")
@@ -916,14 +3132,21 @@ model Machine {
916
3132
  alerts MachineAlert[] @relation("MachineToAlerts")
917
3133
  alertSubscriptions MachineAlertSubscription[]
918
3134
 
919
- // Access Control
920
- userAccess OrganizationUserFactoryEntityAccess[] @relation("UserToMachines")
3135
+ // Automotive: Active FMEA tracking
3136
+ activeFMEAIds String[] // Track which FMEAs apply
3137
+
3138
+ // Pharma: Equipment qualification
3139
+ qualificationStatus String? // "IQ", "OQ", "PQ", "QUALIFIED"
3140
+ lastQualificationDate DateTime?
3141
+ nextQualificationDate DateTime?
3142
+ qualificationRecords EquipmentQualification[] @relation("MachineQualifications")
921
3143
 
922
3144
  createdAt DateTime @default(now())
923
3145
  updatedAt DateTime @default(now())
924
3146
 
925
3147
  @@index([assemblyLineId])
926
- @@schema("machine")
3148
+ @@index([primaryProtocol])
3149
+ @@index([isConnected])
927
3150
  }
928
3151
 
929
3152
  model MachineOperation {
@@ -941,7 +3164,6 @@ model MachineOperation {
941
3164
  updatedAt DateTime @updatedAt
942
3165
 
943
3166
  @@unique([organizationId, operationName])
944
- @@schema("machine")
945
3167
  }
946
3168
 
947
3169
  model MachineEvent {
@@ -957,7 +3179,6 @@ model MachineEvent {
957
3179
  updatedAt DateTime @updatedAt
958
3180
 
959
3181
  @@index([machineId])
960
- @@schema("machine")
961
3182
  }
962
3183
 
963
3184
  model MachineAlert {
@@ -970,8 +3191,6 @@ model MachineAlert {
970
3191
  resolvedAt DateTime?
971
3192
  machine Machine @relation("MachineToAlerts", fields: [machineId], references: [id])
972
3193
  // Note: Subscriptions are not linked here. They are settings, not history.
973
-
974
- @@schema("machine")
975
3194
  }
976
3195
 
977
3196
  model MachineAlertSubscription {
@@ -982,7 +3201,6 @@ model MachineAlertSubscription {
982
3201
  createdAt DateTime @default(now())
983
3202
 
984
3203
  @@unique([userId, machineId])
985
- @@schema("machine")
986
3204
  }
987
3205
 
988
3206
  enum MaintenanceLogStatus {
@@ -990,8 +3208,6 @@ enum MaintenanceLogStatus {
990
3208
  IN_PROGRESS
991
3209
  COMPLETED
992
3210
  CANCELLED
993
-
994
- @@schema("maintenance")
995
3211
  }
996
3212
 
997
3213
  model MaintenanceLog {
@@ -1009,7 +3225,9 @@ model MaintenanceLog {
1009
3225
  createdAt DateTime @default(now())
1010
3226
  updatedAt DateTime @updatedAt
1011
3227
 
1012
- @@schema("maintenance")
3228
+ @@index([machineId])
3229
+ @@index([status])
3230
+ @@index([organizationId])
1013
3231
  }
1014
3232
 
1015
3233
  model MaintenanceManagerConfig {
@@ -1020,7 +3238,6 @@ model MaintenanceManagerConfig {
1020
3238
  updatedAt DateTime @updatedAt
1021
3239
 
1022
3240
  @@unique([managerId, key])
1023
- @@schema("maintenance")
1024
3241
  }
1025
3242
 
1026
3243
  enum MaintenanceRequestStatus {
@@ -1030,8 +3247,6 @@ enum MaintenanceRequestStatus {
1030
3247
  IN_PROGRESS
1031
3248
  COMPLETED
1032
3249
  CANCELLED
1033
-
1034
- @@schema("maintenance")
1035
3250
  }
1036
3251
 
1037
3252
  enum MaintenanceRequestPriority {
@@ -1039,8 +3254,6 @@ enum MaintenanceRequestPriority {
1039
3254
  MEDIUM
1040
3255
  HIGH
1041
3256
  CRITICAL
1042
-
1043
- @@schema("maintenance")
1044
3257
  }
1045
3258
 
1046
3259
  model MaintenanceRequest {
@@ -1061,7 +3274,9 @@ model MaintenanceRequest {
1061
3274
  createdAt DateTime @default(now())
1062
3275
  updatedAt DateTime @updatedAt
1063
3276
 
1064
- @@schema("maintenance")
3277
+ @@index([machineId])
3278
+ @@index([status])
3279
+ @@index([priority])
1065
3280
  }
1066
3281
 
1067
3282
  model MaintenanceRequestCategory {
@@ -1074,7 +3289,7 @@ model MaintenanceRequestCategory {
1074
3289
  updatedAt DateTime @updatedAt
1075
3290
 
1076
3291
  @@unique([factoryId, name])
1077
- @@schema("maintenance")
3292
+ @@index([factoryId])
1078
3293
  }
1079
3294
 
1080
3295
  model MaintenanceRequestAssignment {
@@ -1087,7 +3302,8 @@ model MaintenanceRequestAssignment {
1087
3302
  request MaintenanceRequest @relation(fields: [requestId], references: [id])
1088
3303
  technician MaintenanceTechnician @relation(fields: [technicianId], references: [id])
1089
3304
 
1090
- @@schema("maintenance")
3305
+ @@index([requestId])
3306
+ @@index([technicianId])
1091
3307
  }
1092
3308
 
1093
3309
  model MaintenanceRequestUpdate {
@@ -1099,7 +3315,7 @@ model MaintenanceRequestUpdate {
1099
3315
  request MaintenanceRequest @relation("MaintenanceReqUpdates", fields: [requestId], references: [id])
1100
3316
  attachments MaintenanceRequestAttachment[]
1101
3317
 
1102
- @@schema("maintenance")
3318
+ @@index([requestId])
1103
3319
  }
1104
3320
 
1105
3321
  model MaintenanceRequestAttachment {
@@ -1110,7 +3326,7 @@ model MaintenanceRequestAttachment {
1110
3326
  uploadedAt DateTime @default(now())
1111
3327
  update MaintenanceRequestUpdate @relation(fields: [updateId], references: [id])
1112
3328
 
1113
- @@schema("maintenance")
3329
+ @@index([updateId])
1114
3330
  }
1115
3331
 
1116
3332
  model MaintenanceTechnician {
@@ -1128,25 +3344,34 @@ model MaintenanceTechnician {
1128
3344
  createdAt DateTime @default(now())
1129
3345
  updatedAt DateTime @updatedAt
1130
3346
 
1131
- @@schema("maintenance")
3347
+ @@index([factoryId])
1132
3348
  }
1133
3349
 
1134
3350
  model TechnicianSpecialization {
1135
3351
  id Int @id @default(autoincrement())
1136
3352
  technicianId Int
1137
- specializationId Int // Links to Core DB Specialization
3353
+ specializationId Int
1138
3354
  technician MaintenanceTechnician @relation(fields: [technicianId], references: [id])
1139
3355
 
1140
3356
  @@unique([technicianId, specializationId])
1141
- @@schema("maintenance")
3357
+ @@index([technicianId])
3358
+ }
3359
+
3360
+ enum OperatorLevel {
3361
+ FLOOR_WORKER
3362
+ TEAM_LEAD
3363
+ SUPERVISOR
3364
+ QC_INSPECTOR
3365
+ MAINTENANCE_TECH
1142
3366
  }
1143
3367
 
1144
3368
  model Operator {
1145
- id Int @id @default(autoincrement())
3369
+ id String @id @default(nanoid())
1146
3370
  rfid String?
1147
3371
 
1148
- // ERP/HR Link
1149
- externalId String? // REMOVED @index here
3372
+ coreUserId Int? @unique
3373
+
3374
+ externalId String?
1150
3375
 
1151
3376
  firstName String?
1152
3377
  lastName String?
@@ -1154,6 +3379,11 @@ model Operator {
1154
3379
  organizationId Int?
1155
3380
  factoryId Int?
1156
3381
 
3382
+ operatorLevel OperatorLevel? @default(FLOOR_WORKER)
3383
+
3384
+ teamId Int?
3385
+ teamName String?
3386
+
1157
3387
  tasks Task[] @relation("Task_Operator")
1158
3388
  timeLogs OperatorTimeLog[]
1159
3389
  factory Factory? @relation("FactoryToOperators", fields: [factoryId], references: [id])
@@ -1163,19 +3393,19 @@ model Operator {
1163
3393
  updatedAt DateTime @updatedAt
1164
3394
 
1165
3395
  @@unique([organizationId, rfid])
1166
- @@index([externalId]) // This creates the index
1167
- @@schema("operator")
3396
+ @@index([externalId])
3397
+ @@index([coreUserId])
3398
+ @@index([organizationId, operatorLevel])
1168
3399
  }
1169
3400
 
1170
3401
  model OperatorTimeLog {
1171
3402
  id BigInt @id @default(autoincrement()) @db.BigInt
1172
- operatorId Int
3403
+ operatorId String
1173
3404
  checkInAt DateTime
1174
3405
  checkOutAt DateTime?
1175
3406
  deviceId Int?
1176
3407
  machineId Int?
1177
3408
 
1178
- // Efficiency metrics
1179
3409
  totalWorkingTime Int?
1180
3410
  totalIdleTime Int?
1181
3411
  totalNonWorkingTime Int?
@@ -1192,7 +3422,6 @@ model OperatorTimeLog {
1192
3422
  @@index([deviceId, checkInAt])
1193
3423
  @@index([machineId, checkInAt])
1194
3424
  @@index([checkInAt, checkOutAt])
1195
- @@schema("operator")
1196
3425
  }
1197
3426
 
1198
3427
  enum OrderStatus {
@@ -1204,8 +3433,6 @@ enum OrderStatus {
1204
3433
  AT_RISK
1205
3434
  COMPLETED
1206
3435
  CANCELED
1207
-
1208
- @@schema("order")
1209
3436
  }
1210
3437
 
1211
3438
  enum OrderPriority {
@@ -1213,8 +3440,6 @@ enum OrderPriority {
1213
3440
  MEDIUM
1214
3441
  HIGH
1215
3442
  CRITICAL
1216
-
1217
- @@schema("order")
1218
3443
  }
1219
3444
 
1220
3445
  enum OrderProductStatus {
@@ -1225,17 +3450,14 @@ enum OrderProductStatus {
1225
3450
  AT_RISK
1226
3451
  COMPLETED
1227
3452
  CANCELED
1228
-
1229
- @@schema("order")
1230
3453
  }
1231
3454
 
1232
3455
  model Order {
1233
3456
  id Int @id @default(autoincrement())
1234
3457
  organizationId Int
1235
3458
 
1236
- // ERP OVERLAY FIELDS
1237
- externalId String? @unique // e.g., "SAP-ORDER-1002"
1238
- erpSource String? // e.g., "SAP_S4HANA", "MS_DYNAMICS"
3459
+ externalId String? @unique
3460
+ erpSource String?
1239
3461
 
1240
3462
  customerId Int?
1241
3463
  orderNumber String?
@@ -1264,8 +3486,8 @@ model Order {
1264
3486
  @@index([organizationId])
1265
3487
  @@index([customerId])
1266
3488
  @@index([factoryId])
3489
+ @@index([status])
1267
3490
  @@index([erpSource, externalId])
1268
- @@schema("order")
1269
3491
  }
1270
3492
 
1271
3493
  model OrderProduct {
@@ -1288,7 +3510,7 @@ model OrderProduct {
1288
3510
 
1289
3511
  @@index([orderId])
1290
3512
  @@index([productId])
1291
- @@schema("order")
3513
+ @@index([status])
1292
3514
  }
1293
3515
 
1294
3516
  model OrderComment {
@@ -1304,7 +3526,6 @@ model OrderComment {
1304
3526
  @@index([orderId])
1305
3527
  @@index([organizationId])
1306
3528
  @@index([authorId])
1307
- @@schema("order")
1308
3529
  }
1309
3530
 
1310
3531
  enum ProductionUnitStatus {
@@ -1314,29 +3535,54 @@ enum ProductionUnitStatus {
1314
3535
  COMPLETE
1315
3536
  REJECTED
1316
3537
  SHIPPED
3538
+ }
1317
3539
 
1318
- @@schema("production_tracking")
3540
+ enum IdentifierType {
3541
+ RFID
3542
+ BARCODE
3543
+ QR_CODE
3544
+ MANUAL
3545
+ NFC
1319
3546
  }
1320
3547
 
1321
3548
  model ProductionUnit {
1322
3549
  id String @id @default(cuid())
1323
- tagId String @unique
1324
- serialNumber String? @unique
3550
+ serialNumber String @unique
1325
3551
  organizationId Int
1326
3552
  orderProductId Int
1327
3553
  currentStepId Int?
1328
3554
  status ProductionUnitStatus @default(IN_PRODUCTION)
1329
3555
 
1330
- logs ProductionUnitLog[] @relation("UnitLogs")
1331
- qcRecords ProductionUnitQC[] @relation("UnitQCRecords")
1332
- currentStep ProductionRouteStep? @relation("UnitToRouteStep")
1333
- orderProduct OrderProduct @relation("OrderProductToProductionUnits", fields: [orderProductId], references: [id])
3556
+ logs ProductionUnitLog[] @relation("UnitLogs")
3557
+ qcRecords ProductionUnitQC[] @relation("UnitQCRecords")
3558
+ identifiers ProductionUnitIdentifier[] @relation("UnitIdentifiers")
3559
+ currentStep ProductionRouteStep? @relation("UnitToRouteStep")
3560
+ orderProduct OrderProduct @relation("OrderProductToProductionUnits", fields: [orderProductId], references: [id])
1334
3561
 
1335
3562
  createdAt DateTime @default(now())
1336
3563
  updatedAt DateTime @updatedAt
1337
3564
 
1338
3565
  @@index([orderProductId])
1339
- @@schema("production_tracking")
3566
+ @@index([serialNumber])
3567
+ @@index([status])
3568
+ @@index([organizationId, status])
3569
+ }
3570
+
3571
+ model ProductionUnitIdentifier {
3572
+ id Int @id @default(autoincrement())
3573
+ productionUnitId String
3574
+ identifierType IdentifierType
3575
+ identifierValue String
3576
+ isPrimary Boolean @default(false)
3577
+
3578
+ productionUnit ProductionUnit @relation("UnitIdentifiers", fields: [productionUnitId], references: [id], onDelete: Cascade)
3579
+
3580
+ createdAt DateTime @default(now())
3581
+ updatedAt DateTime @updatedAt
3582
+
3583
+ @@unique([identifierValue])
3584
+ @@index([productionUnitId])
3585
+ @@index([identifierType, identifierValue])
1340
3586
  }
1341
3587
 
1342
3588
  model ProductionUnitLog {
@@ -1346,6 +3592,7 @@ model ProductionUnitLog {
1346
3592
  details String?
1347
3593
  stepId Int?
1348
3594
  operatorId Int?
3595
+ scannedBy String?
1349
3596
 
1350
3597
  productionUnit ProductionUnit @relation("UnitLogs", fields: [productionUnitId], references: [id])
1351
3598
  step ProductionRouteStep? @relation("StepToLogs", fields: [stepId], references: [id])
@@ -1353,7 +3600,8 @@ model ProductionUnitLog {
1353
3600
  createdAt DateTime @default(now())
1354
3601
 
1355
3602
  @@index([productionUnitId])
1356
- @@schema("production_tracking")
3603
+ @@index([eventId])
3604
+ @@index([createdAt])
1357
3605
  }
1358
3606
 
1359
3607
  model ProductionRouteStep {
@@ -1369,10 +3617,10 @@ model ProductionRouteStep {
1369
3617
  createdAt DateTime @default(now())
1370
3618
  updatedAt DateTime @updatedAt
1371
3619
 
1372
- @@schema("production_tracking")
3620
+ @@index([stepId])
3621
+ @@index([machineId])
1373
3622
  }
1374
3623
 
1375
- // Add ProductionUnitQC as needed, linking to ProductionUnit
1376
3624
  model ProductionUnitQC {
1377
3625
  id String @id @default(cuid())
1378
3626
  productionUnitId String
@@ -1383,10 +3631,11 @@ model ProductionUnitQC {
1383
3631
  createdAt DateTime @default(now())
1384
3632
  updatedAt DateTime @updatedAt
1385
3633
 
1386
- @@schema("production_tracking")
3634
+ @@index([productionUnitId])
3635
+ @@index([inspectorId])
1387
3636
  }
1388
3637
 
1389
- model OrganizationUserFactoryEntityAccess {
3638
+ model OrganizationUserEntityAccess {
1390
3639
  id Int @id @default(autoincrement())
1391
3640
  userId Int
1392
3641
  organizationId Int
@@ -1396,21 +3645,21 @@ model OrganizationUserFactoryEntityAccess {
1396
3645
  assemblyLineId Int?
1397
3646
  machineId Int?
1398
3647
 
1399
- factory Factory? @relation("UserToFactory", fields: [factoryId], references: [id], onDelete: Cascade)
1400
- floor Floor? @relation("UserToFloors", fields: [floorId], references: [id], onDelete: Cascade)
1401
- assemblyLine AssemblyLine? @relation("UserToAssemblyLines", fields: [assemblyLineId], references: [id], onDelete: Cascade)
1402
- machine Machine? @relation("UserToMachines", fields: [machineId], references: [id], onDelete: Cascade)
3648
+ scopeOverride String?
3649
+ expiresAt DateTime?
3650
+ reason String?
3651
+ grantedBy Int?
1403
3652
 
1404
3653
  createdAt DateTime @default(now())
1405
3654
  updatedAt DateTime @updatedAt
1406
3655
 
1407
- @@unique([userId, factoryId, floorId, assemblyLineId, machineId], name: "unique_user_entity")
1408
3656
  @@index([userId, organizationId])
3657
+ @@index([userId, organizationId, factoryId, floorId, assemblyLineId, machineId], name: "access_lookup_idx")
1409
3658
  @@index([factoryId])
1410
3659
  @@index([floorId])
1411
3660
  @@index([assemblyLineId])
1412
3661
  @@index([machineId])
1413
- @@schema("organization")
3662
+ @@index([expiresAt])
1414
3663
  }
1415
3664
 
1416
3665
  model MaintenanceSpecialization {
@@ -1419,19 +3668,20 @@ model MaintenanceSpecialization {
1419
3668
  name String
1420
3669
 
1421
3670
  @@unique([organizationId, name])
1422
- @@schema("organization")
3671
+ @@index([organizationId])
1423
3672
  }
1424
3673
 
1425
3674
  model OrganizationCustomer {
1426
3675
  id Int @id @default(autoincrement())
1427
3676
  organizationId Int
3677
+ externalId String?
1428
3678
  name String
1429
3679
  description String?
1430
3680
  createdAt DateTime @default(now())
1431
3681
  updatedAt DateTime @updatedAt
1432
3682
 
3683
+ @@unique([organizationId, externalId])
1433
3684
  @@index([organizationId])
1434
- @@schema("organization")
1435
3685
  }
1436
3686
 
1437
3687
  model AssemblyLineType {
@@ -1443,7 +3693,24 @@ model AssemblyLineType {
1443
3693
 
1444
3694
  @@unique([organizationId, name])
1445
3695
  @@index([organizationId])
1446
- @@schema("organization")
3696
+ }
3697
+
3698
+ model Team {
3699
+ id Int @id @default(autoincrement())
3700
+ organizationId Int
3701
+ name String
3702
+ description String?
3703
+ factoryId Int?
3704
+
3705
+ memberUserIds Int[]
3706
+ leadUserId Int?
3707
+
3708
+ createdAt DateTime @default(now())
3709
+ updatedAt DateTime @updatedAt
3710
+
3711
+ @@unique([organizationId, name])
3712
+ @@index([organizationId])
3713
+ @@index([factoryId])
1447
3714
  }
1448
3715
 
1449
3716
  // ----------------------------------------------------------------------
@@ -1455,14 +3722,15 @@ model AssemblyLineType {
1455
3722
  // ----------------------------------------------------------------------
1456
3723
 
1457
3724
  generator client {
1458
- provider = "prisma-client-js"
1459
- output = "../../client"
1460
- binaryTargets = ["native", "debian-openssl-3.0.x", "rhel-openssl-3.0.x", "darwin-arm64"]
3725
+ provider = "prisma-client-js"
3726
+ output = "../../client"
3727
+ binaryTargets = ["native", "debian-openssl-3.0.x", "rhel-openssl-3.0.x", "darwin-arm64"]
3728
+ previewFeatures = ["postgresqlExtensions"]
1461
3729
  }
1462
3730
 
1463
3731
  datasource db {
1464
- provider = "postgresql"
1465
- schemas = ["factory", "machine", "device", "tasks", "maintenance", "analytics", "audit", "operator", "chatbot", "inventory", "order", "production_tracking", "organization"]
3732
+ provider = "postgresql"
3733
+ extensions = [vector]
1466
3734
  }
1467
3735
 
1468
3736
  enum TaskStatus {
@@ -1472,8 +3740,6 @@ enum TaskStatus {
1472
3740
  CANCELED
1473
3741
  OVERDUE
1474
3742
  INCOMPLETE
1475
-
1476
- @@schema("tasks")
1477
3743
  }
1478
3744
 
1479
3745
  enum TaskGroupStatus {
@@ -1483,45 +3749,51 @@ enum TaskGroupStatus {
1483
3749
  CANCELED
1484
3750
  OVERDUE
1485
3751
  INCOMPLETE
1486
-
1487
- @@schema("tasks")
1488
- }
1489
-
1490
- model OperatorOperationCategory {
1491
- id Int @id @default(autoincrement())
1492
- factoryId Int
1493
- name String
1494
- description String?
1495
- tasks Task[] @relation("OperatorOperationCategory_Tasks")
1496
- factory Factory @relation("Factory_OperatorOperationCategories", fields: [factoryId], references: [id])
1497
- createdAt DateTime @default(now())
1498
- updatedAt DateTime @updatedAt
1499
-
1500
- @@index([factoryId])
1501
- @@schema("tasks")
1502
3752
  }
1503
3753
 
1504
3754
  model Task {
1505
- id Int @id @default(autoincrement())
1506
- operatorId Int?
1507
- assignedById Int
1508
- assignedToId Int?
3755
+ id Int @id @default(autoincrement())
3756
+ organizationId Int
3757
+
3758
+ operatorId String? // Changed from Int to String
3759
+ assignedById String // Changed from Int to String
3760
+ assignedToId String? // Changed from Int to String
1509
3761
  deviceId Int?
1510
3762
  machineId Int?
1511
3763
  taskGroupId Int?
1512
3764
  factoryId Int?
1513
- organizationId Int
1514
3765
  operatorOpCategoryId Int?
1515
3766
  shiftId Int?
1516
3767
 
3768
+ batchRecordId String?
3769
+ controlPlanItemId String?
3770
+ requiredDocumentId Int?
3771
+ documentAcknowledged Boolean @default(false)
3772
+ labTestRequestId String?
3773
+ labTestCleared Boolean @default(false)
3774
+
3775
+ fmeaItemId String?
3776
+ failureMode String?
3777
+
1517
3778
  title String?
1518
3779
  description String?
1519
3780
  status TaskStatus @default(NEW)
1520
3781
 
1521
- startTime DateTime
1522
- endTime DateTime
1523
- targetCount Int?
1524
- taskCount Int? @default(0)
3782
+ startTime DateTime
3783
+ endTime DateTime
3784
+
3785
+ targetQuantity Float?
3786
+ actualQuantity Float? @default(0)
3787
+ passedQuantity Float? @default(0)
3788
+ rejectedQuantity Float? @default(0)
3789
+ reworkQuantity Float? @default(0)
3790
+ wasteQuantity Float? @default(0)
3791
+ measurementUnit ProductionMeasurementUnit? @default(PIECE)
3792
+
3793
+ efficiency Float?
3794
+ yieldPercentage Float?
3795
+ qualityRate Float?
3796
+
1525
3797
  sequence Int @default(0)
1526
3798
  reworkOfTaskId Int?
1527
3799
  reworkCount Int @default(0)
@@ -1529,7 +3801,8 @@ model Task {
1529
3801
  startedAt DateTime?
1530
3802
  completedAt DateTime?
1531
3803
 
1532
- // Relations
3804
+ deletedAt DateTime? // Soft delete
3805
+
1533
3806
  operator Operator? @relation("Task_Operator", fields: [operatorId], references: [id])
1534
3807
  device Device? @relation("Device_UsedInTasks", fields: [deviceId], references: [id])
1535
3808
  machine Machine? @relation("Machine_UsedInTasks", fields: [machineId], references: [id])
@@ -1537,38 +3810,56 @@ model Task {
1537
3810
  shift FactoryShift? @relation("Task_Shift", fields: [shiftId], references: [id])
1538
3811
  factory Factory? @relation("Factory_Tasks", fields: [factoryId], references: [id])
1539
3812
  operatorOpCategory OperatorOperationCategory? @relation("OperatorOperationCategory_Tasks", fields: [operatorOpCategoryId], references: [id])
3813
+ machineOperation MachineOperation? @relation("MachineOperationTasks", fields: [machineOperationId], references: [id])
3814
+
3815
+ fmeaItem FMEAItem? @relation("TaskFMEAFailures", fields: [fmeaItemId], references: [id])
1540
3816
 
1541
3817
  reworkOf Task? @relation("Task_Rework", fields: [reworkOfTaskId], references: [id])
1542
3818
  reworks Task[] @relation("Task_Rework")
1543
3819
 
1544
- lots TaskLot[] @relation("TaskToLots")
1545
- inspections TaskInspection[]
1546
- taskComments TaskComment[] @relation("OrderToTaskComments")
1547
- machineOperation MachineOperation? @relation("MachineOperationTasks", fields: [machineOperationId], references: [id])
3820
+ lots TaskLot[] @relation("TaskToLots")
3821
+ inspections TaskInspection[] @relation("TaskInspections")
3822
+ taskComments TaskComment[] @relation("TaskToComments")
1548
3823
 
1549
3824
  createdAt DateTime @default(now())
1550
3825
  updatedAt DateTime @updatedAt
1551
3826
 
1552
- @@index([shiftId])
1553
- @@index([taskGroupId])
1554
- @@schema("tasks")
3827
+ // FIXED: Composite indexes with organizationId first
3828
+ @@index([organizationId, status, createdAt(sort: Desc)])
3829
+ @@index([organizationId, machineId, status])
3830
+ @@index([organizationId, operatorId, status])
3831
+ @@index([organizationId, batchRecordId])
3832
+ @@index([organizationId, taskGroupId])
3833
+ @@index([fmeaItemId])
1555
3834
  }
1556
3835
 
1557
3836
  model TaskGroup {
1558
- id Int @id @default(autoincrement())
1559
- description String?
1560
- status TaskGroupStatus @default(NEW)
1561
- targetCount Int
3837
+ id Int @id @default(autoincrement())
3838
+ description String?
3839
+ status TaskGroupStatus @default(NEW)
3840
+
3841
+ targetQuantity Float
3842
+ actualQuantity Float @default(0)
3843
+ measurementUnit ProductionMeasurementUnit @default(PIECE)
3844
+
3845
+ totalPassedQuantity Float? @default(0)
3846
+ totalRejectedQuantity Float? @default(0)
3847
+ totalReworkQuantity Float? @default(0)
3848
+
3849
+ overallEfficiency Float?
3850
+
1562
3851
  factoryId Int?
1563
3852
  organizationId Int?
1564
3853
  productRouteId Int?
1565
3854
  orderProductId Int?
1566
3855
  deadline DateTime
1567
3856
  reworkOfTaskGroupId Int?
1568
- reworkCount Int @default(0)
3857
+ reworkCount Int @default(0)
1569
3858
  startedAt DateTime?
1570
3859
  completedAt DateTime?
1571
3860
 
3861
+ deletedAt DateTime? // Soft delete
3862
+
1572
3863
  reworkOf TaskGroup? @relation("TaskGroupRework", fields: [reworkOfTaskGroupId], references: [id])
1573
3864
  reworks TaskGroup[] @relation("TaskGroupRework")
1574
3865
  productMachineRoute FinalProductRoute? @relation("FinalProductRouteToTaskGroups", fields: [productRouteId], references: [id])
@@ -1580,7 +3871,9 @@ model TaskGroup {
1580
3871
  createdAt DateTime @default(now())
1581
3872
  updatedAt DateTime @updatedAt
1582
3873
 
1583
- @@schema("tasks")
3874
+ @@index([organizationId, status])
3875
+ @@index([organizationId, orderProductId])
3876
+ @@index([organizationId, deadline])
1584
3877
  }
1585
3878
 
1586
3879
  model TaskLot {
@@ -1591,7 +3884,6 @@ model TaskLot {
1591
3884
  lot FactoryLot @relation("TaskToLots", fields: [lotId], references: [id])
1592
3885
 
1593
3886
  @@unique([taskId, lotId])
1594
- @@schema("tasks")
1595
3887
  }
1596
3888
 
1597
3889
  model TaskGroupLot {
@@ -1602,33 +3894,48 @@ model TaskGroupLot {
1602
3894
  lot FactoryLot @relation("TaskGroupToLots", fields: [lotId], references: [id])
1603
3895
 
1604
3896
  @@unique([taskGroupId, lotId])
1605
- @@schema("tasks")
1606
3897
  }
1607
3898
 
1608
3899
  model TaskInspection {
1609
- id Int @id @default(autoincrement())
3900
+ id Int @id @default(autoincrement())
1610
3901
  taskId Int
1611
- inspectorId Int
1612
- passed Boolean @default(false)
1613
- defectCount Int @default(0)
1614
- wasteCount Int @default(0)
1615
- notes String?
1616
- task Task @relation(fields: [taskId], references: [id])
1617
- createdAt DateTime @default(now())
1618
- updatedAt DateTime @updatedAt
3902
+ inspectorId String // Changed from Int to String
3903
+
3904
+ passed Boolean @default(false)
3905
+ passedQuantity Float? @default(0)
3906
+ defectQuantity Float? @default(0)
3907
+ wasteQuantity Float? @default(0)
3908
+ reworkQuantity Float? @default(0)
3909
+ measurementUnit ProductionMeasurementUnit? @default(PIECE)
1619
3910
 
1620
- @@schema("tasks")
3911
+ notes String?
3912
+ task Task @relation("TaskInspections", fields: [taskId], references: [id])
3913
+ createdAt DateTime @default(now())
3914
+ updatedAt DateTime @updatedAt
3915
+
3916
+ @@index([taskId])
1621
3917
  }
1622
3918
 
1623
3919
  model TaskComment {
1624
3920
  id Int @id @default(autoincrement())
1625
3921
  taskId Int
1626
- task Task @relation("OrderToTaskComments", fields: [taskId], references: [id])
3922
+ task Task @relation("TaskToComments", fields: [taskId], references: [id])
1627
3923
  organizationId Int
1628
- authorId Int?
3924
+ authorId String? // Changed from Int to String
1629
3925
  text String
1630
3926
  createdAt DateTime @default(now())
1631
3927
  updatedAt DateTime @updatedAt
3928
+ }
3929
+
3930
+ model OperatorOperationCategory {
3931
+ id Int @id @default(autoincrement())
3932
+ factoryId Int
3933
+ name String
3934
+ description String?
3935
+ tasks Task[] @relation("OperatorOperationCategory_Tasks")
3936
+ factory Factory @relation("Factory_OperatorOperationCategories", fields: [factoryId], references: [id])
3937
+ createdAt DateTime @default(now())
3938
+ updatedAt DateTime @updatedAt
1632
3939
 
1633
- @@schema("tasks")
3940
+ @@index([factoryId])
1634
3941
  }