generator client {
  provider = "prisma-client-js"
}

datasource db {
  provider = "mysql"
  url      = env("DATABASE_URL")
}

model SysUser {
  id           BigInt   @id @default(autoincrement()) @db.UnsignedBigInt
  userId       String   @unique @map("user_id") @db.VarChar(32)
  customerId   String?  @unique @map("customer_id") @db.VarChar(32)
  username     String   @unique @db.VarChar(64)
  passwordHash String   @map("password_hash") @db.VarChar(255)
  role         String   @db.VarChar(16)
  isDeleted    Boolean  @default(false) @map("is_deleted")
  createdAt    DateTime @default(now()) @map("created_at")
  updatedAt    DateTime @updatedAt @map("updated_at")

  @@map("sys_user")
}

model QuoteRecord {
  id              BigInt    @id @default(autoincrement()) @db.UnsignedBigInt
  quoteId         String    @unique @map("quote_id") @db.VarChar(32)
  requestId       String    @map("request_id") @db.VarChar(36)
  customerId      String    @map("customer_id") @db.VarChar(32)
  cargoHash       String    @map("cargo_hash") @db.Char(32)
  status          String    @default("processing") @db.VarChar(16)
  sourceType      String?   @map("source_type") @db.VarChar(16)
  isRealtime      Boolean   @default(true) @map("is_realtime")
  confidenceScore Decimal?  @map("confidence_score") @db.Decimal(3, 2)
  currency        String    @default("USD") @db.VarChar(8)
  pickupJson      Json      @map("pickup_json")
  deliveryJson    Json      @map("delivery_json")
  weightLb        Decimal   @map("weight_lb") @db.Decimal(12, 2)
  dimLIn          Decimal   @map("dim_l_in") @db.Decimal(8, 2)
  dimWIn          Decimal   @map("dim_w_in") @db.Decimal(8, 2)
  dimHIn          Decimal   @map("dim_h_in") @db.Decimal(8, 2)
  palletCount     Int       @map("pallet_count")
  cargoType       String    @map("cargo_type") @db.VarChar(32)
  quotesJson      Json?     @map("quotes_json")
  markupPercent   Decimal   @default(0.0) @map("markup_percent") @db.Decimal(5, 2)
  validUntil      DateTime? @map("valid_until")
  errorCode       String?   @map("error_code") @db.VarChar(32)
  errorMessage    String?   @map("error_message") @db.VarChar(512)
  ccCustomerId    String?   @map("cc_customer_id") @db.VarChar(32)
  forecastId      String?   @map("forecast_id") @db.VarChar(32)
  isDeleted       Boolean   @default(false) @map("is_deleted")
  createdAt       DateTime  @default(now()) @map("created_at")
  updatedAt       DateTime  @updatedAt @map("updated_at")

  @@index([customerId, createdAt], map: "idx_customer_created")
  @@index([cargoHash], map: "idx_cargo_hash")
  @@index([requestId], map: "idx_request")
  @@map("quote_record")
}

model IdempotencyRecord {
  id         BigInt   @id @default(autoincrement()) @db.UnsignedBigInt
  requestId  String   @unique @map("request_id") @db.VarChar(36)
  customerId String   @map("customer_id") @db.VarChar(32)
  quoteId    String   @map("quote_id") @db.VarChar(32)
  expireAt   DateTime @map("expire_at")
  createdAt  DateTime @default(now()) @map("created_at")

  @@map("idempotency_record")
}

model QuoteCacheMeta {
  id                 BigInt   @id @default(autoincrement()) @db.UnsignedBigInt
  cargoHash          String   @unique @map("cargo_hash") @db.Char(32)
  rawTotalStandard   Decimal  @map("raw_total_standard") @db.Decimal(12, 2)
  rawTotalGuaranteed Decimal  @map("raw_total_guaranteed") @db.Decimal(12, 2)
  lastQuotesJson     Json     @map("last_quotes_json")
  refreshedAt        DateTime @default(now()) @map("refreshed_at")

  @@map("quote_cache_meta")
}

model MarkupConfig {
  id                BigInt   @id @default(autoincrement()) @db.UnsignedBigInt
  customerId        String   @unique @map("customer_id") @db.VarChar(32)
  markupType        String   @default("percent") @map("markup_type") @db.VarChar(16)
  markupPercent     Decimal  @map("markup_percent") @db.Decimal(5, 2)
  markupFixedAmount Decimal? @map("markup_fixed_amount") @db.Decimal(12, 2)
  operatorId        String   @map("operator_id") @db.VarChar(32)
  remark            String?  @db.VarChar(255)
  isDeleted         Boolean  @default(false) @map("is_deleted")
  createdAt         DateTime @default(now()) @map("created_at")
  updatedAt         DateTime @updatedAt @map("updated_at")

  @@map("markup_config")
}

model AlertLog {
  id         BigInt    @id @default(autoincrement()) @db.UnsignedBigInt
  alertType  String    @map("alert_type") @db.VarChar(32)
  quoteId    String?   @map("quote_id") @db.VarChar(32)
  cargoHash  String?   @map("cargo_hash") @db.Char(32)
  detailJson Json?     @map("detail_json")
  status     String    @default("open") @db.VarChar(16)
  resolverId String?   @map("resolver_id") @db.VarChar(32)
  resolvedAt DateTime? @map("resolved_at")
  createdAt  DateTime  @default(now()) @map("created_at")

  @@index([alertType, status], map: "idx_type_status")
  @@index([createdAt], map: "idx_created")
  @@map("alert_log")
}

model AuditLog {
  id         BigInt   @id @default(autoincrement()) @db.UnsignedBigInt
  action     String   @db.VarChar(64)
  actorId    String   @map("actor_id") @db.VarChar(32)
  resource   String?  @db.VarChar(128)
  detailJson Json?    @map("detail_json")
  createdAt  DateTime @default(now()) @map("created_at")

  @@index([actorId, createdAt], map: "idx_actor_created")
  @@index([action, createdAt], map: "idx_action_created")
  @@map("audit_log")
}

model HostCustomer {
  id                BigInt          @id @default(autoincrement()) @db.UnsignedBigInt
  customerId        String          @unique @map("customer_id") @db.VarChar(32)
  name              String          @db.VarChar(128)
  status            String          @default("active") @db.VarChar(16)
  remark            String?         @db.VarChar(255)
  embedPasswordHash String?         @map("embed_password_hash") @db.VarChar(255)
  isDeleted         Boolean         @default(false) @map("is_deleted")
  createdAt         DateTime        @default(now()) @map("created_at")
  updatedAt         DateTime        @updatedAt @map("updated_at")
  apiKeys           ServiceApiKey[]

  @@index([status, isDeleted], map: "idx_host_customer_status")
  @@map("host_customer")
}

model ServiceApiKey {
  id          BigInt       @id @default(autoincrement()) @db.UnsignedBigInt
  keyId       String       @unique @map("key_id") @db.VarChar(32)
  customerId  String       @map("customer_id") @db.VarChar(32)
  tokenHash   String       @unique @map("token_hash") @db.Char(64)
  keyPrefix   String       @map("key_prefix") @db.VarChar(16)
  permissions Json
  isActive    Boolean      @default(true) @map("is_active")
  createdAt   DateTime     @default(now()) @map("created_at")
  updatedAt   DateTime     @updatedAt @map("updated_at")
  customer    HostCustomer @relation(fields: [customerId], references: [customerId])

  @@index([customerId, isActive], map: "idx_service_api_key_customer")
  @@map("service_api_key")
}

model QuoteQueryLog {
  id            BigInt    @id @default(autoincrement()) @db.UnsignedBigInt
  quoteId       String    @unique @map("quote_id") @db.VarChar(32)
  requestId     String    @map("request_id") @db.VarChar(36)
  customerId    String    @map("customer_id") @db.VarChar(32)
  pickupJson    Json      @map("pickup_json")
  deliveryJson  Json      @map("delivery_json")
  cargoJson     Json      @map("cargo_json")
  outcome       String    @default("processing") @db.VarChar(16)
  failureReason String?   @map("failure_reason") @db.VarChar(512)
  errorCode     String?   @map("error_code") @db.VarChar(32)
  sourceType    String?   @map("source_type") @db.VarChar(16)
  tierCount     Int?      @map("tier_count")
  createdAt     DateTime  @default(now()) @map("created_at")
  completedAt   DateTime? @map("completed_at")

  @@index([createdAt], map: "idx_query_log_created")
  @@index([customerId, createdAt], map: "idx_query_log_customer")
  @@map("quote_query_log")
}
