// Product Management Domain // Contains Product, ProductVariant, modifiers, and pricing models // Product-specific Enums enum ModifierSelectionType { DROPDOWN INPUT } enum NominalType { NOMINAL PERCENTAGE } enum RuleCondition { EQUALS LESS_THAN GREATER_THAN BETWEEN } // Product Models model Product { id String @id @default(cuid()) name String // e.g., "Pepper" code String @unique description String? category String unit String @default("kg") // kg, ton, etc isActive Boolean @default(true) createdAt DateTime @default(now()) updatedAt DateTime @updatedAt // Relations plots Plot[] variants ProductVariant[] modifiers ProductModifier[] contracts Contract[] priceHistory PriceHistory[] marketPrices MarketPrice[] marketDemand MarketDemand[] plotSeasons PlotSeason[] seasonHarvests SeasonHarvest[] @@index([code]) @@index([category]) @@index([isActive]) @@index([name]) @@map("products") } model ProductVariant { id String @id @default(cuid()) productId String name String // e.g., "Black Pepper", "White Pepper" code String @unique description String? basePrice Decimal? // default base price isActive Boolean @default(true) createdAt DateTime @default(now()) updatedAt DateTime @updatedAt // Relations product Product @relation(fields: [productId], references: [id], onDelete: Cascade) plots Plot[] harvests Harvest[] procurements Procurement[] contracts Contract[] priceHistory PriceHistory[] marketPrices MarketPrice[] marketDemand MarketDemand[] plotSeasons PlotSeason[] seasonHarvests SeasonHarvest[] @@index([code]) @@index([productId]) @@index([isActive]) @@index([basePrice]) @@map("product_variants") } model ProductModifier { id String @id @default(cuid()) productId String name String // e.g., "Water Content", "Density" code String description String? selectionType ModifierSelectionType @default(INPUT) nominalType NominalType @default(NOMINAL) options String[] // For dropdown selections minimum Decimal? maximum Decimal? unit String? // %, kg/m3, etc isRequired Boolean @default(false) isActive Boolean @default(true) createdAt DateTime @default(now()) updatedAt DateTime @updatedAt // Relations product Product @relation(fields: [productId], references: [id], onDelete: Cascade) rules ProductModifierRule[] harvestModifiers HarvestModifier[] @@unique([productId, code]) @@index([productId]) @@index([isActive]) @@index([selectionType]) @@map("product_modifiers") } model ProductModifierRule { id String @id @default(cuid()) modifierId String condition RuleCondition priceAdjustment Decimal // amount to adjust price value String? // For equals condition minValue Decimal? // For lessThan or between conditions maxValue Decimal? // For greaterThan or between conditions description String? isActive Boolean @default(true) createdAt DateTime @default(now()) updatedAt DateTime @updatedAt // Relations modifier ProductModifier @relation(fields: [modifierId], references: [id], onDelete: Cascade) @@map("product_modifier_rules") } model HarvestModifier { id String @id @default(cuid()) harvestId String modifierId String value String // actual value applied adjustment Decimal? // calculated price adjustment createdAt DateTime @default(now()) updatedAt DateTime @updatedAt // Relations harvest Harvest @relation(fields: [harvestId], references: [id], onDelete: Cascade) modifier ProductModifier @relation(fields: [modifierId], references: [id]) @@unique([harvestId, modifierId]) @@map("harvest_modifiers") } model PriceHistory { id String @id @default(cuid()) productId String? variantId String? qualityGrade QualityGrade basePrice Decimal marketPrice Decimal? premiumRate Decimal @default(0) effectiveDate DateTime region String? notes String? createdAt DateTime @default(now()) // Relations product Product? @relation(fields: [productId], references: [id]) variant ProductVariant? @relation(fields: [variantId], references: [id]) @@index([productId, variantId]) @@index([effectiveDate]) @@index([qualityGrade]) @@index([region]) @@map("price_history") }