Newer
Older
client_dwatch / prisma / schema.prisma
generator client {
  provider = "prisma-client"
  output   = "../lib/generated/prisma"
}

datasource db {
  provider = "mysql"
  // Prisma 7 では接続URLを schema.prisma に書けない。
  // 接続先は prisma7.config.ts の datasource.url(DATABASE_URL 環境変数)が正。
}

// ============================================================================
// このファイルは prisma db pull による生成物です(D-056)。
//
// db pull 実施履歴:
//   1回目 2026-09-03 / 元DDL: clean_watch_20260902.sql
//     (TeamWorks提供 / 受領日: 2026-09-02。投入先は当時の dwatch_ddl)
//   2回目 2026-09-09 / 元DDL: clean_watch_20260909.sql
//     (TeamWorks提供 / 受領日: 2026-09-09。投入先は dwatch_local。
//      D-094(率・面積23列の型変更を照合)/ D-095(dwatch_local を最新DDLから作り直し)の対応。
//      dwatch_local は受領DDLと列レベルで完全一致させてから db pull した)
//   3回目 2026-09-11 / 元DDL: clean_watch_20260911.sql
//     (TeamWorks提供 / 受領日: 2026-09-11。投入先は dwatch_local。D-112(第7回回答受領)/
//      指示書X 段階3 の対応。0909版との実質差分は facility_contacts.email の
//      varchar(255)→varchar(100)(第7回 A-3b)と robot_task_versions.clean_schedule_id への
//      索引・外部キー追加(第7回 B-2)の2件のみ。テーブル数39は不変。
//      dwatch_local は受領DDLから作り直してから db pull した)
//
// ★db pull を実施済み。カラム・型・キー・インデックスなど DB由来の事実は
//   以後 db pull の生成結果を正とし、手で書き換えない(D-056)★
//   (このファイル自体へのコメント追記・整理は対象外。db pull はコメントを保持しないため、
//    再度 db pull した場合は本コミットの diff を見ながらコメントを移植し直すこと)
//   ★RobotErrorReport.updated_at には @updatedAt を付けない(指示書AT §3-1)★ — db pull 後に
//    @updatedAt を付け直す作業(D-059 運用)の唯一の例外。理由は該当フィールドのコメント
//   ★例外(手書き。2026-10-27。D-184): ErrorList モデルと RobotErrorReport.error_list_id★ —
//    ステージングに接続できず db pull できないため、定義書ベースで手書きした(指示書BD §5-1)。
//    接続回復後に db pull で置き換え、手書きとの差分を確認すること
// ★今後DDLを受領した場合も、実DDLを正として db pull で答え合わせする(D-059)★
//
// 命名: 1回目の db pull 前の手書き版(PascalCaseモデル名 + @@map)に対して実行したため、
//   既存28モデルは enrich され、モデル名・@@map が維持されている。
//   新規に取り込まれた11モデル(clean_link_schedules と、末尾にまとめた
//   Laravel基盤10テーブル)は db pull の既定命名(物理テーブル名そのまま)。
//   2回目の db pull も同じ enrich が効き、命名は変わっていない。
//
// 2026-09-09 の再 pull で判明した変更(D-094 / D-095。詳細は各該当フィールドのコメント参照):
//   - 率カラム13列・面積カラム10列(計23列)が tinyint/decimal から double 化された。
//     Prisma 上の型は Decimal/Int → ★Float(`@db.Double` は付かない。実測。
//     MySQL8では `double(M,D)` の精度指定が非推奨のため、Prisma が固有の @db.Double 属性を
//     出力せず素の Float になったと見られる)★
//   - customer_contacts.contact_type が bigint unsigned → tinyint unsigned に修正されていた
//     (TeamWorks回答 B-6 の一部。ただし 0902→0907 の間に反映済みで、0909 での新規変更ではない。
//      email 側(varchar(100) vs varchar(255)の不一致)は未反映のまま)
//   - ★clean_task_reports.updated_at に ON UPDATE CURRENT_TIMESTAMP が新たに付与された★
//     (0902/0907 には無かった。D-094 が報告した23列の型変更とは別の、今回新たに見つかった変更。
//      @updatedAt を付けるべきものが増えたので、モデル側で追随した)
//
// TeamWorks 回答済み(D-057: A-1 / A-2 / B-1〜B-6)の内容は各該当フィールドの
// コメントを参照。
//
// TeamWorks へ確認中の項目(回答後に該当箇所を修正すること。詳細は各モデルのコメント参照):
//   - robot_error_reports: PRIMARY KEY が無く、UNIQUE は error_id のみ
//   - clean_status_histories / clean_timetable_histories: id が AUTO_INCREMENT でない
//   - facility_contacts.email: TeamWorks回答(B-6)では customer_contacts.email(varchar(100))
//     と型・サイズを揃える予定だったが、現行DDL(0909)では facility_contacts.email が
//     varchar(255) のままで食い違っている(contact_type 側は既に揃った。上記参照)
// ============================================================================

model Group {
  id         BigInt     @id @default(autoincrement()) @db.UnsignedBigInt
  group_name String     @db.VarChar(100)
  inactive   Int        @default(0) @db.UnsignedTinyInt
  created_at DateTime   @default(now()) @db.Timestamp(0)
  updated_at DateTime   @default(now()) @updatedAt @db.Timestamp(0)
  deleted_at DateTime?  @db.Timestamp(0)
  customers  Customer[]

  @@map("groups")
}

model Device {
  id BigInt @id @default(autoincrement()) @db.UnsignedBigInt

  // TeamWorks回答(A-1): makers テーブルは提供されない
  // (メーカー情報は設定ファイルで代替する想定)。そのため外部キーは張らず、
  // maker_id は 0〜255 の範囲で運用する。
  maker_id     Int       @db.UnsignedTinyInt
  model_name   String    @db.VarChar(100)
  model_number String?   @db.VarChar(100)
  inactive     Int       @default(0) @db.UnsignedTinyInt
  created_at   DateTime  @default(now()) @db.Timestamp(0)
  updated_at   DateTime  @default(now()) @updatedAt @db.Timestamp(0)
  deleted_at   DateTime? @db.Timestamp(0)
  robots       Robot[]

  @@map("devices")
}

model Customer {
  id            BigInt @id @default(autoincrement()) @db.UnsignedBigInt
  group_id      BigInt @default(0) @db.UnsignedBigInt
  customer_name String @db.VarChar(400)
  zip_cd        String @db.VarChar(8)

  // 実DDLのまま: customers.prefecture_cd は unsigned なしの tinyint
  // (facilities.prefecture_cd は unsigned tinyint で型が異なる。実DDLでも別々の型のまま)
  prefecture_cd Int @db.TinyInt

  prefecture_name          String                 @db.VarChar(16)
  addr1                    String                 @db.VarChar(800)
  addr2                    String?                @db.VarChar(800)
  phone                    String?                @db.VarChar(16)
  inactive                 Int                    @default(0) @db.UnsignedTinyInt
  created_at               DateTime               @default(now()) @db.Timestamp(0)
  updated_at               DateTime               @default(now()) @updatedAt @db.Timestamp(0)
  deleted_at               DateTime?              @db.Timestamp(0)
  customer_contacts        CustomerContact[]
  customer_error_summaries CustomerErrorSummary[]
  customer_summaries       CustomerSummary[]
  group                    Group                  @relation(fields: [group_id], references: [id], onDelete: NoAction, onUpdate: NoAction, map: "customers_group_id_foreign")
  facilities               Facility[]

  @@index([group_id], map: "customers_group_id_foreign")
  @@map("customers")
}

model Facility {
  id          BigInt @id @default(autoincrement()) @db.UnsignedBigInt
  customer_id BigInt @db.UnsignedBigInt

  // 実DDL確認済み: shop_id の既定値は文字列 "0"(varchar型の DEFAULT '0')
  shop_id String @default("0") @db.VarChar(20)

  facility_name             String                  @db.VarChar(400)
  zip_cd                    String                  @db.VarChar(8)
  prefecture_cd             Int                     @db.UnsignedTinyInt
  prefecture_name           String                  @db.VarChar(16)
  addr1                     String                  @db.VarChar(800)
  addr2                     String?                 @db.VarChar(800)
  phone                     String?                 @db.VarChar(16)
  email                     String?                 @db.VarChar(100)
  manager_name              String?                 @db.VarChar(100)
  charger_name              String?                 @db.VarChar(100)
  contract                  String                  @default("0000000000") @db.VarChar(10)
  inactive                  Int                     @default(0) @db.UnsignedTinyInt
  created_at                DateTime                @default(now()) @db.Timestamp(0)
  updated_at                DateTime                @default(now()) @updatedAt @db.Timestamp(0)
  deleted_at                DateTime?               @db.Timestamp(0)
  clean_schedules           CleanSchedule[]
  clean_status_histories    CleanStatusHistory[]
  clean_statuses            CleanStatus[]
  clean_task_reports        CleanTaskReport[]
  clean_timetable_histories CleanTimetableHistory[]
  clean_timetables          CleanTimetable[]
  control_error_histories   ControlErrorHistory[]
  control_reports           ControlReport[]
  controls                  Control[]
  customer                  Customer                @relation(fields: [customer_id], references: [id], onDelete: NoAction, onUpdate: NoAction, map: "facilities_customer_id_foreign")
  facility_contacts         FacilityContact[]
  facility_error_summaries  FacilityErrorSummary[]
  facility_summaries        FacilitySummary[]
  robot_error_reports       RobotErrorReport[]
  robots                    Robot[]
  section_robot_statuses    SectionRobotStatus[]
  sections                  Section[]
  security_status_histories SecurityStatusHistory[]
  security_statuses         SecurityStatus[]

  @@index([customer_id], map: "facilities_customer_id_foreign")
  @@map("facilities")
}

model Section {
  id                        BigInt                  @id @default(autoincrement()) @db.UnsignedBigInt
  facility_id               BigInt                  @db.UnsignedBigInt
  section_name              String                  @db.VarChar(100)
  floor_name                String?                 @db.VarChar(100)
  layout                    String?                 @db.VarChar(200)
  inactive                  Int                     @default(0) @db.UnsignedTinyInt
  created_at                DateTime                @default(now()) @db.Timestamp(0)
  updated_at                DateTime                @default(now()) @updatedAt @db.Timestamp(0)
  deleted_at                DateTime?               @db.Timestamp(0)
  clean_link_schedules      clean_link_schedules[]
  clean_schedules           CleanSchedule[]
  clean_status_histories    CleanStatusHistory[]
  clean_statuses            CleanStatus[]
  clean_task_reports        CleanTaskReport[]
  clean_timetable_histories CleanTimetableHistory[]
  clean_timetables          CleanTimetable[]
  control_error_histories   ControlErrorHistory[]
  control_reports           ControlReport[]
  controls                  Control[]
  link_schedules            LinkSchedule[]
  robot_error_reports       RobotErrorReport[]
  robots                    Robot[]
  section_robot_statuses    SectionRobotStatus[]
  facility                  Facility                @relation(fields: [facility_id], references: [id], onDelete: NoAction, onUpdate: NoAction, map: "sections_facility_id_foreign")
  security_status_histories SecurityStatusHistory[]
  security_statuses         SecurityStatus[]

  @@index([facility_id], map: "sections_facility_id_foreign")
  @@map("sections")
}

model Control {
  id            BigInt @id @default(autoincrement()) @db.UnsignedBigInt
  serial_number String @db.VarChar(100)
  password      String @db.VarChar(255)

  // TeamWorks回答(B-2): facility_id は外部キーとして定義する(開発環境は定義済み)。
  facility_id BigInt @db.UnsignedBigInt

  section_id              BigInt                @db.UnsignedBigInt
  status                  Int                   @default(0) @db.UnsignedTinyInt
  inactive                Int                   @default(0) @db.UnsignedTinyInt
  remember_token          String?               @db.VarChar(100)
  created_at              DateTime              @default(now()) @db.Timestamp(0)
  updated_at              DateTime              @default(now()) @updatedAt @db.Timestamp(0)
  deleted_at              DateTime?             @db.Timestamp(0)
  verified_at             DateTime?             @db.Timestamp(0)
  control_error_histories ControlErrorHistory[]
  control_reports         ControlReport[]
  facility                Facility              @relation(fields: [facility_id], references: [id], onDelete: NoAction, onUpdate: NoAction, map: "controls_facility_id_foreign")
  section                 Section               @relation(fields: [section_id], references: [id], onDelete: NoAction, onUpdate: NoAction, map: "controls_section_id_foreign")

  @@index([facility_id], map: "controls_facility_id_foreign")
  @@index([section_id], map: "controls_section_id_foreign")
  @@map("controls")
}

model Robot {
  id            BigInt  @id @default(autoincrement()) @db.UnsignedBigInt
  facility_id   BigInt  @db.UnsignedBigInt
  section_id    BigInt  @db.UnsignedBigInt
  device_id     BigInt  @db.UnsignedBigInt
  serial_number String  @db.VarChar(20)
  robot_name    String? @db.VarChar(100)
  status        Int     @default(0) @db.SmallInt
  clean_status  Int     @default(0) @db.UnsignedTinyInt

  // D-094(2026-09-09 db pull で判明): 実DDLは tinyint unsigned → double(4,1) に変更済み。
  // Prisma型は Int → Float(`@db.Double` は付かない。ファイル冒頭コメント参照)
  clean_ratio Float @default(0.0)

  battery                  Int                    @default(0) @db.UnsignedTinyInt
  inactive                 Int                    @default(0) @db.UnsignedTinyInt
  created_at               DateTime               @default(now()) @db.Timestamp(0)
  updated_at               DateTime               @default(now()) @updatedAt @db.Timestamp(0)
  deleted_at               DateTime?              @db.Timestamp(0)
  clean_task_reports       CleanTaskReport[]
  robot_error_reports      RobotErrorReport[]
  robot_instruct_histories RobotInstructHistory[]
  robot_task_versions      RobotTaskVersion[]
  device                   Device                 @relation(fields: [device_id], references: [id], onDelete: NoAction, onUpdate: NoAction, map: "robots_device_id_foreign")
  facility                 Facility               @relation(fields: [facility_id], references: [id], onDelete: NoAction, onUpdate: NoAction, map: "robots_facility_id_foreign")
  section                  Section                @relation(fields: [section_id], references: [id], onDelete: NoAction, onUpdate: NoAction, map: "robots_section_id_foreign")

  @@index([device_id], map: "robots_device_id_foreign")
  @@index([facility_id], map: "robots_facility_id_foreign")
  @@index([section_id], map: "robots_section_id_foreign")
  @@map("robots")
}

model RobotTaskVersion {
  id       BigInt @id @default(autoincrement()) @db.UnsignedBigInt
  robot_id BigInt @db.UnsignedBigInt

  // 第7回 B-2 が 0911版DDL で反映され、clean_schedule_id に FK と索引が付いた
  // (指示書X 段階3)。db pull がリレーションとして拾うようになった
  clean_schedule_id BigInt @db.UnsignedBigInt

  task_id         String?       @db.VarChar(20)
  version         String?       @db.VarChar(20)
  inactive        Int           @default(0) @db.UnsignedTinyInt
  created_at      DateTime      @default(now()) @db.Timestamp(0)
  updated_at      DateTime      @default(now()) @updatedAt @db.Timestamp(0)
  deleted_at      DateTime?     @db.Timestamp(0)
  clean_schedules CleanSchedule @relation(fields: [clean_schedule_id], references: [id], onDelete: NoAction, onUpdate: NoAction, map: "robot_task_versions_clean_schedule_id_foreign")
  robot           Robot         @relation(fields: [robot_id], references: [id], onDelete: NoAction, onUpdate: NoAction, map: "robot_task_versions_robot_id_foreign")

  @@index([clean_schedule_id], map: "robot_task_versions_clean_schedule_id_foreign")
  @@index([robot_id], map: "robot_task_versions_robot_id_foreign")
  @@map("robot_task_versions")
}

model SectionRobotStatus {
  id          BigInt @id @default(autoincrement()) @db.UnsignedBigInt
  facility_id BigInt @db.UnsignedBigInt
  section_id  BigInt @db.UnsignedBigInt

  // 定義書の備考: 「現時点では未確定」。配下の robots.status から算出するルールは未確定。
  robot_status Int @default(0) @db.SmallInt

  clean_status Int @default(0) @db.UnsignedTinyInt

  // D-094(2026-09-09 db pull で判明): 実DDLは tinyint unsigned → double(4,1) に変更済み。
  // Prisma型は Int → Float(`@db.Double` は付かない。ファイル冒頭コメント参照)
  clean_ratio Float @default(0.0)

  created_at DateTime @default(now()) @db.Timestamp(0)
  // 実DDL確認済み: updated_at に ON UPDATE CURRENT_TIMESTAMP が無いため @updatedAt は付けない
  // (DBが自動更新しない。従来の手書き版は誤って付けていた。2026-09-09の再pullでも変化なし)
  updated_at DateTime @default(now()) @db.Timestamp(0)
  facility   Facility @relation(fields: [facility_id], references: [id], onDelete: NoAction, onUpdate: NoAction, map: "section_robot_statuses_facility_id_foreign")
  section    Section  @relation(fields: [section_id], references: [id], onDelete: NoAction, onUpdate: NoAction, map: "section_robot_statuses_section_id_foreign")

  @@index([facility_id], map: "section_robot_statuses_facility_id_foreign")
  @@index([section_id], map: "section_robot_statuses_section_id_foreign")
  @@map("section_robot_statuses")
}

model RobotErrorReport {
  // 実DDL に PRIMARY KEY が無く、UNIQUE は error_id のみ。id は varchar(50) で制約なし。
  // ★API が返す ID は error_id★(`PrecheckItem.id` は `string`。`lib/types/index.ts` / d-watch-api.yaml)。
  //   旧: 「TeamWorks へ確認中。回答までは `PrecheckItem.id: number` を変更しない」— 解決済み(D-105)。
  id       String @db.VarChar(50)
  error_id String @unique(map: "robot_error_reports_report_id_unique") @db.VarChar(50)

  facility_id BigInt @db.UnsignedBigInt
  section_id  BigInt @db.UnsignedBigInt
  robot_id    BigInt @db.UnsignedBigInt

  // 定義書のキー欄に fk 指定なし(備考:「要確認. 清掃タイムテーブルに該当する情報がない場合,
  // 登録しないでよいのか.」)。実DDLでも FK・KEY ともに無く、リレーション対象としていない。
  clean_timetable_id BigInt? @db.UnsignedBigInt

  serial_number    String    @db.VarChar(20)
  product_code     String?   @db.VarChar(20)
  hardware_version String?   @db.VarChar(50)
  software_version String?   @db.VarChar(50)
  os_version       String?   @db.VarChar(50)
  error_level      String    @db.VarChar(20)
  error_type       String    @db.VarChar(100)
  error_detail     String    @db.Text
  status           Int       @default(0) @db.UnsignedTinyInt
  comment          String?   @db.Text
  errored_at       DateTime? @db.DateTime(0)
  responded_at     DateTime? @db.DateTime(0)
  resolved_at      DateTime? @db.DateTime(0)
  created_at       DateTime  @default(now()) @db.Timestamp(0)
  // ★@updatedAt を付けないこと(DDL に ON UPDATE current_timestamp() はある)★
  //   アプリがこの表の4カラム(status/comment/responded_at/resolved_at)を UPDATE するため。
  //   付けると Prisma が updated_at = <アプリの時刻(UTC)> を SET に足し、
  //   ①列単位 GRANT の更新用アカウントでは権限エラー ②JST の DB に UTC の値が入る。
  //   DB が ON UPDATE で自分で更新する。db pull 後に @updatedAt を付け直す作業の★唯一の例外★。
  //   lib/db/__tests__/robot-error-write-sql.test.ts が固定している(指示書AT §3-1)
  updated_at       DateTime  @default(now()) @db.Timestamp(0)
  // ★定義書ベースの手書き(2026-10-27)。ステージングに接続できず db pull できないため。
  //   接続回復後に db pull で置き換え、差分を確認する(D-056 の例外。D-184)★
  // エラー一覧の「エラー内容」(error_lists.id)。定義書は bigint unsigned・必須○・既定値なし・FK なし・索引なし。
  // ★ユーザー回答③(2026-10-27)「初期は空欄」で NULL 可にしてある★(実DDLの NULL 可否は未確認。指示書BD §8)。
  // ★アプリが書く5列目★ — PATCH /errors/{error_id}/status の経路だけ(事前チェック・D-Sec からは書かない。指示書BD §2)。
  // FK が無いのでリレーションは張らない(名前解決はアプリ側で error_lists を引く)
  error_list_id    BigInt?   @db.UnsignedBigInt
  facility         Facility  @relation(fields: [facility_id], references: [id], onDelete: NoAction, onUpdate: NoAction, map: "robot_error_reports_facility_id_foreign")
  robot            Robot     @relation(fields: [robot_id], references: [id], onDelete: NoAction, onUpdate: NoAction, map: "robot_error_reports_robot_id_foreign")
  section          Section   @relation(fields: [section_id], references: [id], onDelete: NoAction, onUpdate: NoAction, map: "robot_error_reports_section_id_foreign")

  @@index([facility_id], map: "robot_error_reports_facility_id_foreign")
  @@index([robot_id], map: "robot_error_reports_robot_id_foreign")
  @@index([section_id], map: "robot_error_reports_section_id_foreign")
  @@map("robot_error_reports")
}

// ★定義書ベースの手書き(2026-10-27)。ステージングに接続できず db pull できないため。
//   接続回復後に db pull で置き換え、差分を確認する(D-056 の例外。D-184)★
// エラー内容の選択肢(管理側UIなし。先方で作成済み — ユーザー回答① 2026-10-27)。指示書BD §5-1。
// ★Pudu の error_type の列は無い★(決定稿のシートにはあるが、表には無い)。
// varchar / text 列の NULL 可否は定義書の記載が無く、NOT NULL として書いた(db pull で確かめる)。
// ★@updatedAt を付けない★(RobotErrorReport.updated_at と同じく、アプリが時刻を書く列を増やさない。DB 側で更新する)。
// robot_error_reports.error_list_id から参照されるが FK が無いのでリレーションは張らない。
model ErrorList {
  id                     BigInt    @id @default(autoincrement()) @db.UnsignedBigInt
  error_category_main_en String    @db.VarChar(100)
  error_category_main_ja String    @db.VarChar(200)
  error_category_sub_en  String    @db.VarChar(100)
  error_category_sub_ja  String    @db.VarChar(200)
  error_detail_en        String    @db.Text
  error_detail_ja        String    @db.Text
  inactive               Int       @default(0) @db.UnsignedTinyInt
  created_at             DateTime  @db.Timestamp(0)
  updated_at             DateTime? @db.Timestamp(0)
  deleted_at             DateTime? @db.Timestamp(0)

  @@map("error_lists")
}

model RobotInstructHistory {
  id         BigInt   @id @default(autoincrement()) @db.UnsignedBigInt
  robot_id   BigInt   @db.UnsignedBigInt
  instruct   Int      @db.UnsignedTinyInt
  created_at DateTime @default(now()) @db.Timestamp(0)
  robot      Robot    @relation(fields: [robot_id], references: [id], onDelete: NoAction, onUpdate: NoAction, map: "robot_instruct_histories_robot_id_foreign")

  @@index([instruct], map: "robot_instruct_histories_instruct_index")
  @@index([robot_id], map: "robot_instruct_histories_robot_id_foreign")
  @@map("robot_instruct_histories")
}

model ControlReport {
  id            BigInt   @id @default(autoincrement()) @db.UnsignedBigInt
  facility_id   BigInt   @db.UnsignedBigInt
  section_id    BigInt   @db.UnsignedBigInt
  control_id    BigInt   @db.UnsignedBigInt
  serial_number String   @db.VarChar(100)
  reported_at   DateTime @default(now()) @db.Timestamp(0)
  created_at    DateTime @default(now()) @db.Timestamp(0)
  updated_at    DateTime @default(now()) @updatedAt @db.Timestamp(0)
  control       Control  @relation(fields: [control_id], references: [id], onDelete: NoAction, onUpdate: NoAction, map: "control_reports_control_id_foreign")
  facility      Facility @relation(fields: [facility_id], references: [id], onDelete: NoAction, onUpdate: NoAction, map: "control_reports_facility_id_foreign")
  section       Section  @relation(fields: [section_id], references: [id], onDelete: NoAction, onUpdate: NoAction, map: "control_reports_section_id_foreign")

  @@index([control_id], map: "control_reports_control_id_foreign")
  @@index([facility_id], map: "control_reports_facility_id_foreign")
  @@index([section_id], map: "control_reports_section_id_foreign")
  @@map("control_reports")
}

model ControlErrorHistory {
  id           BigInt    @id @default(autoincrement()) @db.UnsignedBigInt
  facility_id  BigInt    @db.UnsignedBigInt
  section_id   BigInt    @db.UnsignedBigInt
  control_id   BigInt    @db.UnsignedBigInt
  status       Int       @default(0) @db.UnsignedTinyInt
  comment      String?   @db.Text
  occurred_at  DateTime  @default(now()) @db.DateTime(0)
  responded_at DateTime? @db.DateTime(0)
  resolved_at  DateTime? @db.DateTime(0)
  control      Control   @relation(fields: [control_id], references: [id], onDelete: NoAction, onUpdate: NoAction, map: "control_error_histories_control_id_foreign")
  facility     Facility  @relation(fields: [facility_id], references: [id], onDelete: NoAction, onUpdate: NoAction, map: "control_error_histories_facility_id_foreign")
  section      Section   @relation(fields: [section_id], references: [id], onDelete: NoAction, onUpdate: NoAction, map: "control_error_histories_section_id_foreign")

  @@index([control_id], map: "control_error_histories_control_id_foreign")
  @@index([facility_id], map: "control_error_histories_facility_id_foreign")
  @@index([section_id], map: "control_error_histories_section_id_foreign")
  @@map("control_error_histories")
}

model SecurityStatus {
  id          BigInt   @id @default(autoincrement()) @db.UnsignedBigInt
  facility_id BigInt   @db.UnsignedBigInt
  section_id  BigInt   @db.UnsignedBigInt
  status      Int      @default(1) @db.UnsignedTinyInt
  // 実DDL確認済み: reported_at にも ON UPDATE CURRENT_TIMESTAMP が付いている(付け漏れを修正)
  reported_at DateTime @default(now()) @updatedAt @db.Timestamp(0)
  created_at  DateTime @default(now()) @db.Timestamp(0)
  updated_at  DateTime @default(now()) @updatedAt @db.Timestamp(0)
  facility    Facility @relation(fields: [facility_id], references: [id], onDelete: NoAction, onUpdate: NoAction, map: "security_statuses_facility_id_foreign")
  section     Section  @relation(fields: [section_id], references: [id], onDelete: NoAction, onUpdate: NoAction, map: "security_statuses_section_id_foreign")

  @@index([facility_id], map: "security_statuses_facility_id_foreign")
  @@index([section_id], map: "security_statuses_section_id_foreign")
  @@map("security_statuses")
}

model SecurityStatusHistory {
  id          BigInt   @id @default(autoincrement()) @db.UnsignedBigInt
  facility_id BigInt   @db.UnsignedBigInt
  section_id  BigInt   @db.UnsignedBigInt
  status      Int      @db.UnsignedTinyInt
  reported_at DateTime @db.Timestamp(0)
  created_at  DateTime @default(now()) @db.Timestamp(0)
  facility    Facility @relation(fields: [facility_id], references: [id], onDelete: NoAction, onUpdate: NoAction, map: "security_status_histories_facility_id_foreign")
  section     Section  @relation(fields: [section_id], references: [id], onDelete: NoAction, onUpdate: NoAction, map: "security_status_histories_section_id_foreign")

  @@index([facility_id], map: "security_status_histories_facility_id_foreign")
  @@index([section_id], map: "security_status_histories_section_id_foreign")
  @@map("security_status_histories")
}

model CleanStatus {
  id          BigInt @id @default(autoincrement()) @db.UnsignedBigInt
  facility_id BigInt @db.UnsignedBigInt
  section_id  BigInt @db.UnsignedBigInt

  // 定義書のキー欄は fk。手書き版は CleanTimetable へのリレーションを張っていたが、
  // 実DDLには FK も KEY も無く、DBでは参照整合性が担保されていない。リレーション対象から外した
  clean_timetable_id BigInt @db.UnsignedBigInt

  // TeamWorks回答(A-2): 0: 清掃前 / 1: 清掃中 / 2: 清掃終了(セキュリティ有効) /
  // -1: 清掃完了(セキュリティ無効)。-1 があるため符号あり tinyint
  clean_status Int @default(0) @db.TinyInt

  // 定義書のまま(負値の定義は無い)。A-2の再定義対象外
  clean_status_trans Int @default(0) @db.UnsignedTinyInt
  // 定義書のまま(負値の定義は無い)。A-2の再定義対象外
  clean_error        Int @default(0) @db.UnsignedTinyInt

  // D-094(2026-09-09 db pull で判明): 実DDLは decimal(12,6) unsigned → double(12,6) に変更済み
  // (unsigned も外れた)。Prisma型は Decimal → Float(`@db.Double` は付かない。ファイル冒頭コメント参照)
  task_area  Float @default(0.000000)
  // 同上
  clean_area Float @default(0.000000)

  // TeamWorks回答(B-3): 取得元で 100 に丸められるため上限は 100。画面側で頭打ち処理は不要
  // D-094(2026-09-09 db pull で判明): 実DDLは tinyint unsigned → double(4,1) に変更済み。
  // Prisma型は Int → Float(`@db.Double` は付かない)
  clean_ratio Float     @default(0.0)
  started_at  DateTime? @db.DateTime(0)
  ended_at    DateTime? @db.DateTime(0)
  created_at  DateTime  @default(now()) @db.Timestamp(0)
  updated_at  DateTime  @default(now()) @updatedAt @db.Timestamp(0)
  facility    Facility  @relation(fields: [facility_id], references: [id], onDelete: NoAction, onUpdate: NoAction, map: "clean_statuses_facility_id_foreign")
  section     Section   @relation(fields: [section_id], references: [id], onDelete: NoAction, onUpdate: NoAction, map: "clean_statuses_section_id_foreign")

  @@index([facility_id], map: "clean_statuses_facility_id_foreign")
  @@index([section_id], map: "clean_statuses_section_id_foreign")
  @@map("clean_statuses")
}

model CleanStatusHistory {
  // 実DDL確認済み: PRIMARY KEY が無く、UNIQUE(id) のみ(定義書の「pkではなくuk」という記載どおり)。
  // id は AUTO_INCREMENT ではない。採番はアプリ側。
  // ★TeamWorks へ確認中: 元テーブルの id を引き継ぐ設計か★
  id          BigInt @unique(map: "clean_status_histories_id_unique") @db.UnsignedBigInt
  facility_id BigInt @db.UnsignedBigInt
  section_id  BigInt @db.UnsignedBigInt

  // 定義書のキー欄は fk。手書き版は CleanTimetable へのリレーションを張っていたが、
  // 実DDLには FK も KEY も無く、DBでは参照整合性が担保されていない。リレーション対象から外した
  clean_timetable_id BigInt @db.UnsignedBigInt

  // TeamWorks回答(A-2): 0: 清掃前 / 1: 清掃中 / 2: 清掃終了(セキュリティ有効) /
  // -1: 清掃完了(セキュリティ無効)。-1 があるため符号あり tinyint
  clean_status Int @default(0) @db.TinyInt

  // 定義書のまま(負値の定義は無い)。A-2の再定義対象外
  clean_error Int @default(0) @db.UnsignedTinyInt

  // D-094(2026-09-09 db pull で判明): 実DDLは decimal(12,6) unsigned → double(12,6) に変更済み
  // (unsigned も外れた)。Prisma型は Decimal → Float(`@db.Double` は付かない)
  task_area  Float @default(0.000000)
  clean_area Float @default(0.000000)

  // TeamWorks回答(B-3): 取得元で 100 に丸められるため上限は 100。画面側で頭打ち処理は不要
  // D-094(2026-09-09 db pull で判明): 実DDLは tinyint unsigned → double(4,1) に変更済み。
  // Prisma型は Int → Float(`@db.Double` は付かない)
  clean_ratio Float    @default(0.0)
  started_at  DateTime @db.DateTime(0)
  ended_at    DateTime @db.DateTime(0)
  created_at  DateTime @default(now()) @db.Timestamp(0)
  facility    Facility @relation(fields: [facility_id], references: [id], onDelete: NoAction, onUpdate: NoAction, map: "clean_status_histories_facility_id_foreign")
  section     Section  @relation(fields: [section_id], references: [id], onDelete: NoAction, onUpdate: NoAction, map: "clean_status_histories_section_id_foreign")

  @@index([facility_id], map: "clean_status_histories_facility_id_foreign")
  @@index([section_id], map: "clean_status_histories_section_id_foreign")
  @@map("clean_status_histories")
}

model CleanTaskReport {
  report_id   String @id @db.VarChar(20)
  facility_id BigInt @db.UnsignedBigInt
  section_id  BigInt @db.UnsignedBigInt
  robot_id    BigInt @db.UnsignedBigInt

  // 定義書のキー欄に fk 指定なし。実DDLでも FK・KEY ともに無く、リレーション対象としていない。
  clean_timetable_id BigInt? @db.UnsignedBigInt

  serial_number String @db.VarChar(20)

  // 定義書原文のまま: 他の status/state 系カラムと異なり、備考欄に値の説明が記載されていない
  status Int @default(0) @db.UnsignedTinyInt

  // D-094(2026-09-09 db pull で判明): 実DDLは decimal(12,6) unsigned → double(12,6) に変更済み
  // (unsigned も外れた)。Prisma型は Decimal → Float(`@db.Double` は付かない)
  task_area  Float @default(0.000000)
  clean_area Float @default(0.000000)

  // TeamWorks回答(B-3): 取得元で 100 に丸められるため上限は 100。画面側で頭打ち処理は不要
  // D-094(2026-09-09 db pull で判明): 実DDLは tinyint unsigned → double(4,1) に変更済み。
  // Prisma型は Int → Float(`@db.Double` は付かない)
  clean_ratio Float     @default(0.0)
  started_at  DateTime  @db.DateTime(0)
  ended_at    DateTime? @db.DateTime(0)
  clean_time  Int       @default(0) @db.UnsignedInt
  // ★2026-09-09 の再pullで判明した変更(D-094のリストには無い、新たな発見)★:
  //   0902/0907 のDDLでは created_at / updated_at ともに DEFAULT句が無い timestamp NOT NULL
  //   (ON UPDATEも無く、INSERT時に値を渡す必要があった)だったが、0909 のDDLでは
  //   両方に DEFAULT current_timestamp() が付き、updated_at には ON UPDATE current_timestamp()
  //   も付与された。実DDL確認済みのため、@default(now()) と updated_at への @updatedAt を付ける
  created_at  DateTime  @default(now()) @db.Timestamp(0)
  updated_at  DateTime  @default(now()) @updatedAt @db.Timestamp(0)
  facility    Facility  @relation(fields: [facility_id], references: [id], onDelete: NoAction, onUpdate: NoAction, map: "clean_task_reports_facility_id_foreign")
  robot       Robot     @relation(fields: [robot_id], references: [id], onDelete: NoAction, onUpdate: NoAction, map: "clean_task_reports_robot_id_foreign")
  section     Section   @relation(fields: [section_id], references: [id], onDelete: NoAction, onUpdate: NoAction, map: "clean_task_reports_section_id_foreign")

  @@index([facility_id], map: "clean_task_reports_facility_id_foreign")
  @@index([robot_id], map: "clean_task_reports_robot_id_foreign")
  @@index([section_id], map: "clean_task_reports_section_id_foreign")
  @@map("clean_task_reports")
}

model CleanSchedule {
  id          BigInt @id @default(autoincrement()) @db.UnsignedBigInt
  facility_id BigInt @db.UnsignedBigInt
  section_id  BigInt @db.UnsignedBigInt
  weeks       String @db.VarChar(7)
  // TeamWorks回答(B-5): HHMM 形式の文字列。start_time は 0000〜2359
  start_time  String @db.VarChar(4)
  // TeamWorks回答(B-5): HHMM 形式の文字列。★時が 24〜29 を取りうる★(例: 2830 は翌日4:30)。
  // 日跨ぎで翌 6:00 まで設定可能にするための表現。HH:MM として素朴にパースすると壊れる。
  end_time    String @db.VarChar(4)

  contract                  String                  @default("0000000000") @db.VarChar(10)
  inactive                  Int                     @default(0) @db.UnsignedTinyInt
  created_at                DateTime                @default(now()) @db.Timestamp(0)
  updated_at                DateTime                @default(now()) @updatedAt @db.Timestamp(0)
  deleted_at                DateTime?               @db.Timestamp(0)
  facility                  Facility                @relation(fields: [facility_id], references: [id], onDelete: NoAction, onUpdate: NoAction, map: "clean_schedules_facility_id_foreign")
  section                   Section                 @relation(fields: [section_id], references: [id], onDelete: NoAction, onUpdate: NoAction, map: "clean_schedules_section_id_foreign")
  clean_timetable_histories CleanTimetableHistory[]
  clean_timetables          CleanTimetable[]
  robot_task_versions       RobotTaskVersion[]

  @@index([facility_id], map: "clean_schedules_facility_id_foreign")
  @@index([section_id], map: "clean_schedules_section_id_foreign")
  @@map("clean_schedules")
}

model CleanTimetable {
  id                BigInt @id @default(autoincrement()) @db.UnsignedBigInt
  facility_id       BigInt @db.UnsignedBigInt
  section_id        BigInt @db.UnsignedBigInt
  clean_schedule_id BigInt @db.UnsignedBigInt

  // 定義書のキー欄に fk 指定なし(親(本清掃)は0、親以外は親のidを格納する自己参照的な列だが、
  // 実DDLでも FK・KEY ともに無く、リレーション対象としていない)
  parent_id BigInt @db.UnsignedBigInt

  start_at       DateTime      @db.DateTime(0)
  end_at         DateTime      @db.DateTime(0)
  // TeamWorks第7回回答(A5-2 / A5-5。2026-09-11受領。D-112): 0 = 本清掃 / それ以外は
  // その数値がそのまま「本清掃開始の何分前か」(分数そのもの)。1 は「1回目」ではなく
  // 「1分前」(A5-3)。新旧の混在は無い(A5-4)。定義書の当初の既定値表記(9)は誤りで、
  // 実DDLは @default(0)(clean_timetable_histories 側と一致)。読み方は
  // lib/db/precheck-mapping.ts の precheckMinutesFromCode() 1箇所(指示書X)。
  precheck       Int           @default(0) @db.UnsignedTinyInt
  inactive       Int           @default(0) @db.UnsignedTinyInt
  created_at     DateTime      @default(now()) @db.Timestamp(0)
  updated_at     DateTime      @default(now()) @updatedAt @db.Timestamp(0)
  clean_schedule CleanSchedule @relation(fields: [clean_schedule_id], references: [id], onDelete: NoAction, onUpdate: NoAction, map: "clean_timetables_clean_schedule_id_foreign")
  facility       Facility      @relation(fields: [facility_id], references: [id], onDelete: NoAction, onUpdate: NoAction, map: "clean_timetables_facility_id_foreign")
  section        Section       @relation(fields: [section_id], references: [id], onDelete: NoAction, onUpdate: NoAction, map: "clean_timetables_section_id_foreign")

  @@index([clean_schedule_id], map: "clean_timetables_clean_schedule_id_foreign")
  @@index([end_at], map: "clean_timetables_end_at_index")
  @@index([facility_id], map: "clean_timetables_facility_id_foreign")
  @@index([parent_id], map: "clean_timetables_parent_id_index")
  @@index([section_id], map: "clean_timetables_section_id_foreign")
  @@index([start_at], map: "clean_timetables_start_at_index")
  @@map("clean_timetables")
}

model CleanTimetableHistory {
  // 実DDL確認済み: PRIMARY KEY (id) のみ(定義書の「primary key」表記どおり)。
  // ただし AUTO_INCREMENT ではない。採番はアプリ側。
  // ★TeamWorks へ確認中: 元テーブルの id を引き継ぐ設計か★
  id                BigInt        @id @db.UnsignedBigInt
  facility_id       BigInt        @db.UnsignedBigInt
  section_id        BigInt        @db.UnsignedBigInt
  clean_schedule_id BigInt        @db.UnsignedBigInt
  parent_id         BigInt        @db.UnsignedBigInt
  start_at          DateTime      @db.DateTime(0)
  end_at            DateTime      @db.DateTime(0)
  // TeamWorks第7回回答(A5-2 / A5-5。2026-09-11受領。D-112): 0 = 本清掃 / それ以外は
  // その数値がそのまま「本清掃開始の何分前か」(分数そのもの)。1 は「1回目」ではなく
  // 「1分前」(A5-3)。新旧の混在は無い(A5-4)。定義書のこのテーブル側の記述(9: 本清掃)は誤り。
  precheck          Int           @default(0) @db.UnsignedTinyInt
  created_at        DateTime      @default(now()) @db.Timestamp(0)
  clean_schedule    CleanSchedule @relation(fields: [clean_schedule_id], references: [id], onDelete: NoAction, onUpdate: NoAction, map: "clean_timetable_histories_clean_schedule_id_foreign")
  facility          Facility      @relation(fields: [facility_id], references: [id], onDelete: NoAction, onUpdate: NoAction, map: "clean_timetable_histories_facility_id_foreign")
  section           Section       @relation(fields: [section_id], references: [id], onDelete: NoAction, onUpdate: NoAction, map: "clean_timetable_histories_section_id_foreign")

  @@index([clean_schedule_id], map: "clean_timetable_histories_clean_schedule_id_foreign")
  // 実DDL確認済み: インデックス名は started_at / ended_at 表記のままだが、対象カラムは
  // start_at / end_at(DDL側の索引命名が実カラム名とずれている。map: で正しく解決済み)
  @@index([end_at], map: "clean_timetable_histories_ended_at_index")
  @@index([facility_id], map: "clean_timetable_histories_facility_id_foreign")
  @@index([parent_id], map: "clean_timetable_histories_parent_id_index")
  @@index([section_id], map: "clean_timetable_histories_section_id_foreign")
  @@index([start_at], map: "clean_timetable_histories_started_at_index")
  @@map("clean_timetable_histories")
}

model LinkSchedule {
  id         BigInt    @id @default(autoincrement()) @db.UnsignedBigInt
  section_id BigInt    @db.UnsignedBigInt
  type       Int       @default(1) @db.UnsignedTinyInt
  weeks      String    @db.VarChar(7)
  intervals  String    @db.VarChar(120)
  inactive   Int       @default(0) @db.UnsignedTinyInt
  created_at DateTime  @default(now()) @db.Timestamp(0)
  updated_at DateTime  @default(now()) @updatedAt @db.Timestamp(0)
  deleted_at DateTime? @db.Timestamp(0)
  section    Section   @relation(fields: [section_id], references: [id], onDelete: NoAction, onUpdate: NoAction, map: "link_schedules_section_id_foreign")

  // TeamWorks回答(B-4): controls とのリレーションは張らない。外部キーは section_id のみ
  // (定義書の fk_link_schedules_control_id は誤り)。
  @@index([section_id], map: "link_schedules_section_id_foreign")
  @@map("link_schedules")
}

// TeamWorks確認済み・D-058: 不要テーブル。API/クエリは link_schedules を参照する
// (構造は link_schedules と完全同一。table_optionsにAUTO_INCREMENT記載が無く、データは0件 = 未使用)
model clean_link_schedules {
  id         BigInt    @id @default(autoincrement()) @db.UnsignedBigInt
  section_id BigInt    @db.UnsignedBigInt
  type       Int       @default(1) @db.UnsignedTinyInt
  weeks      String    @db.VarChar(7)
  intervals  String    @db.VarChar(120)
  inactive   Int       @default(0) @db.UnsignedTinyInt
  created_at DateTime  @default(now()) @db.Timestamp(0)
  // 実DDL確認済み: updated_at に ON UPDATE CURRENT_TIMESTAMP があるため @updatedAt を付ける
  updated_at DateTime  @default(now()) @updatedAt @db.Timestamp(0)
  deleted_at DateTime? @db.Timestamp(0)
  sections   Section   @relation(fields: [section_id], references: [id], onDelete: NoAction, onUpdate: NoAction, map: "clean_link_schedules_section_id_foreign")

  @@index([section_id], map: "clean_link_schedules_section_id_foreign")
}

model CustomerSummary {
  id           BigInt @id @default(autoincrement()) @db.UnsignedBigInt
  customer_id  BigInt @db.UnsignedBigInt
  year         Int    @db.UnsignedSmallInt
  month        Int    @db.UnsignedTinyInt
  week         Int    @db.UnsignedTinyInt
  task_count   Int    @db.UnsignedSmallInt
  launch_count Int    @db.UnsignedSmallInt
  error_count  Int    @db.UnsignedSmallInt

  // D-094(2026-09-09 db pull で判明): 実DDLは decimal(14,6) → double(14,6) に変更済み。
  // Prisma型は Decimal → Float(`@db.Double` は付かない)。あわせて NOT NULL DEFAULT 0.000000 が付いた
  // (0902/0907にはDEFAULTが無かった。D-094項1-D)
  task_area  Float @default(0.000000)
  clean_area Float @default(0.000000)

  // D-094(2026-09-09 db pull で判明): 実DDLは tinyint unsigned → double(4,1) に変更済み
  // (D-022「率カラムは小数のまま格納」がついに反映された)。Prisma型は Int → Float
  // (`@db.Double` は付かない)。あわせて NOT NULL DEFAULT 0.0 が付いた(D-094項1-D)
  operation_ratio Float    @default(0.0)
  launch_ratio    Float    @default(0.0)
  clean_ratio     Float    @default(0.0)
  error_ratio     Float    @default(0.0)
  created_at      DateTime @default(now()) @db.Timestamp(0)
  updated_at      DateTime @default(now()) @updatedAt @db.Timestamp(0)
  customer        Customer @relation(fields: [customer_id], references: [id], onDelete: NoAction, onUpdate: NoAction, map: "customer_summaries_customer_id_foreign")

  @@index([customer_id], map: "customer_summaries_customer_id_foreign")
  @@index([month], map: "customer_summaries_month_index")
  @@index([week], map: "customer_summaries_week_index")
  @@index([year], map: "customer_summaries_year_index")
  @@map("customer_summaries")
}

model FacilitySummary {
  id           BigInt @id @default(autoincrement()) @db.UnsignedBigInt
  facility_id  BigInt @db.UnsignedBigInt
  year         Int    @db.UnsignedSmallInt
  month        Int    @db.UnsignedTinyInt
  week         Int    @db.UnsignedTinyInt
  task_count   Int    @db.UnsignedSmallInt
  launch_count Int    @db.UnsignedSmallInt
  error_count  Int    @db.UnsignedSmallInt

  // D-094(2026-09-09 db pull で判明): 実DDLは decimal(14,6) → double(14,6) に変更済み。
  // Prisma型は Decimal → Float(`@db.Double` は付かない)。あわせて NOT NULL DEFAULT 0.000000 が付いた
  // (0902/0907にはDEFAULTが無かった。D-094項1-D)
  task_area  Float @default(0.000000)
  clean_area Float @default(0.000000)

  // D-094(2026-09-09 db pull で判明): 実DDLは tinyint unsigned → double(4,1) に変更済み
  // (D-022「率カラムは小数のまま格納」がついに反映された)。Prisma型は Int → Float
  // (`@db.Double` は付かない)。あわせて NOT NULL DEFAULT 0.0 が付いた(D-094項1-D)
  operation_ratio Float    @default(0.0)
  launch_ratio    Float    @default(0.0)
  clean_ratio     Float    @default(0.0)
  error_ratio     Float    @default(0.0)
  created_at      DateTime @default(now()) @db.Timestamp(0)
  updated_at      DateTime @default(now()) @updatedAt @db.Timestamp(0)
  facility        Facility @relation(fields: [facility_id], references: [id], onDelete: NoAction, onUpdate: NoAction, map: "facility_summaries_facility_id_foreign")

  @@index([facility_id], map: "facility_summaries_facility_id_foreign")
  @@index([month], map: "facility_summaries_month_index")
  @@index([week], map: "facility_summaries_week_index")
  @@index([year], map: "facility_summaries_year_index")
  @@map("facility_summaries")
}

// ★実DDLからの手書き(2026-10-29)。db pull は禁止のため(CLAUDE.md §7。D-056 の例外)★
//   出所: ステージングの information_schema(構造。2026-10-29 監督の実測)。
//   TeamWorks が DDL を変え、`error_detail`(text)が無くなり `error_list_id`(bigint unsigned NOT NULL)が入った。
//   ★DB には error_lists への FK(`fk_customer_error_summaries_error_list_id`)があるが、Prisma のリレーションは張らない★
//   (アプリは error_list_id を読まない。内訳は従来どおり error_type で束ねる)
model CustomerErrorSummary {
  id            BigInt   @id @default(autoincrement()) @db.UnsignedBigInt
  customer_id   BigInt   @db.UnsignedBigInt
  year          Int      @db.UnsignedSmallInt
  month         Int      @db.UnsignedTinyInt
  week          Int      @db.UnsignedTinyInt
  error_level   String   @db.VarChar(20)
  error_type    String   @db.VarChar(100)
  error_list_id BigInt   @db.UnsignedBigInt
  error_count   Int      @db.UnsignedSmallInt
  created_at    DateTime @default(now()) @db.Timestamp(0)
  customer      Customer @relation(fields: [customer_id], references: [id], onDelete: NoAction, onUpdate: NoAction, map: "customer_error_summaries_customer_id_foreign")

  @@index([customer_id], map: "customer_error_summaries_customer_id_foreign")
  @@index([error_list_id], map: "fk_customer_error_summaries_error_list_id")
  @@index([month], map: "customer_error_summaries_month_index")
  @@index([week], map: "customer_error_summaries_week_index")
  @@index([year], map: "customer_error_summaries_year_index")
  @@map("customer_error_summaries")
}

// ★実DDLからの手書き(2026-10-29)。db pull は禁止のため(CLAUDE.md §7。D-056 の例外)★
//   出所: ステージングの information_schema(構造。2026-10-29 監督の実測)。
//   TeamWorks が DDL を変え、`error_detail`(text)が無くなり `error_list_id`(bigint unsigned NOT NULL)が入った。
//   ★DB には error_lists への FK(`fk_facility_error_summaries_error_list_id`)があるが、Prisma のリレーションは張らない★
//   (アプリは error_list_id を読まない。内訳は従来どおり error_type で束ねる)
model FacilityErrorSummary {
  id            BigInt   @id @default(autoincrement()) @db.UnsignedBigInt
  facility_id   BigInt   @db.UnsignedBigInt
  year          Int      @db.UnsignedSmallInt
  month         Int      @db.UnsignedTinyInt
  week          Int      @db.UnsignedTinyInt
  error_level   String   @db.VarChar(20)
  error_type    String   @db.VarChar(100)
  error_list_id BigInt   @db.UnsignedBigInt
  error_count   Int      @db.UnsignedSmallInt
  created_at    DateTime @default(now()) @db.Timestamp(0)
  facility      Facility @relation(fields: [facility_id], references: [id], onDelete: NoAction, onUpdate: NoAction, map: "facility_error_summaries_facility_id_foreign")

  @@index([facility_id], map: "facility_error_summaries_facility_id_foreign")
  @@index([error_list_id], map: "fk_facility_error_summaries_error_list_id")
  @@index([month], map: "facility_error_summaries_month_index")
  @@index([week], map: "facility_error_summaries_week_index")
  @@index([year], map: "facility_error_summaries_year_index")
  @@map("facility_error_summaries")
}

model CustomerContact {
  id          BigInt @id @default(autoincrement()) @db.UnsignedBigInt
  customer_id BigInt @db.UnsignedBigInt

  // ★2026-09-09 db pull で判明(D-095の副次的な発見。D-094のリストには無い)★:
  // 旧コメントは「実DDL: bigint unsigned。TeamWorks回答(B-6)で tinyint unsigned に揃える予定だが
  // 現行DDLには未反映」としていたが、これは 2026-09-02 版DDLの話。2026-09-07 版の時点で
  // 既に tinyint unsigned に修正済みだったことが今回判明した(0909でも同じ)。
  // facility_contacts.contact_type と型が揃っている(B-6のcontact_type側は解消済み)
  contact_type Int @db.UnsignedTinyInt

  url        String?   @db.VarChar(200)
  email      String?   @db.VarChar(100)
  inactive   Int       @default(0) @db.UnsignedTinyInt
  created_at DateTime  @default(now()) @db.Timestamp(0)
  updated_at DateTime  @default(now()) @updatedAt @db.Timestamp(0)
  deleted_at DateTime? @db.Timestamp(0)
  customer   Customer  @relation(fields: [customer_id], references: [id], onDelete: NoAction, onUpdate: NoAction, map: "customer_contacts_customer_id_foreign")

  @@index([customer_id], map: "customer_contacts_customer_id_foreign")
  @@map("customer_contacts")
}

model FacilityContact {
  id          BigInt @id @default(autoincrement()) @db.UnsignedBigInt
  facility_id BigInt @db.UnsignedBigInt

  // TeamWorks回答(B-6): customer_contacts.contact_type と型を揃える予定だったが、
  // 2026-09-09時点でこちらは既に一致している(tinyint unsigned。上記モデル参照)
  contact_type Int @db.UnsignedTinyInt

  url String? @db.VarChar(200)

  // 第7回 A-3b が 0911版DDL で反映され、customer_contacts.email(varchar(100))と型が揃った
  // (指示書X 段階3。2026-09-11受領)
  email String? @db.VarChar(100)

  inactive   Int       @default(0) @db.UnsignedTinyInt
  created_at DateTime  @default(now()) @db.Timestamp(0)
  // 実DDL確認済み: updated_at に ON UPDATE CURRENT_TIMESTAMP が無いため @updatedAt は付けない
  // (DBが自動更新しない。従来の手書き版は誤って付けていた。2026-09-09の再pullでも変化なし)
  updated_at DateTime  @default(now()) @db.Timestamp(0)
  deleted_at DateTime? @db.Timestamp(0)
  facility   Facility  @relation(fields: [facility_id], references: [id], onDelete: NoAction, onUpdate: NoAction, map: "facility_contacts_facility_id_foreign")

  @@index([facility_id], map: "facility_contacts_facility_id_foreign")
  @@map("facility_contacts")
}

// ============================================================================
// 以下は Laravel 基盤のテーブル。ビューアーからは参照しない。
// db pull の差分をきれいに保つために残している(削除すると毎回再追加される)
// ============================================================================

model cache {
  key        String @id @db.VarChar(255)
  value      String @db.MediumText
  expiration BigInt

  @@index([expiration], map: "cache_expiration_index")
}

model cache_locks {
  key        String @id @db.VarChar(255)
  owner      String @db.VarChar(255)
  expiration BigInt

  @@index([expiration], map: "cache_locks_expiration_index")
}

model failed_jobs {
  id         BigInt   @id @default(autoincrement()) @db.UnsignedBigInt
  uuid       String   @unique(map: "failed_jobs_uuid_unique") @db.VarChar(255)
  connection String   @db.VarChar(255)
  queue      String   @db.VarChar(255)
  payload    String   @db.LongText
  exception  String   @db.LongText
  failed_at  DateTime @default(now()) @db.Timestamp(0)

  @@index([connection, queue, failed_at], map: "failed_jobs_connection_queue_failed_at_index")
}

model job_batches {
  id             String  @id @db.VarChar(255)
  name           String  @db.VarChar(255)
  total_jobs     Int
  pending_jobs   Int
  failed_jobs    Int
  failed_job_ids String  @db.LongText
  options        String? @db.MediumText
  cancelled_at   Int?
  created_at     Int
  finished_at    Int?
}

model jobs {
  id           BigInt @id @default(autoincrement()) @db.UnsignedBigInt
  queue        String @db.VarChar(255)
  payload      String @db.LongText
  attempts     Int    @db.UnsignedSmallInt
  reserved_at  Int?   @db.UnsignedInt
  available_at Int    @db.UnsignedInt
  created_at   Int    @db.UnsignedInt

  @@index([queue], map: "jobs_queue_index")
}

model migrations {
  id        Int    @id @default(autoincrement()) @db.UnsignedInt
  migration String @db.VarChar(255)
  batch     Int
}

model password_reset_tokens {
  email      String    @id @db.VarChar(255)
  token      String    @db.VarChar(255)
  created_at DateTime? @db.Timestamp(0)
}

model personal_access_tokens {
  id             BigInt    @id @default(autoincrement()) @db.UnsignedBigInt
  tokenable_type String    @db.VarChar(255)
  tokenable_id   BigInt    @db.UnsignedBigInt
  name           String    @db.Text
  token          String    @unique(map: "personal_access_tokens_token_unique") @db.VarChar(64)
  abilities      String?   @db.Text
  last_used_at   DateTime? @db.Timestamp(0)
  expires_at     DateTime? @db.Timestamp(0)
  created_at     DateTime? @db.Timestamp(0)
  updated_at     DateTime? @db.Timestamp(0)

  @@index([expires_at], map: "personal_access_tokens_expires_at_index")
  @@index([tokenable_type, tokenable_id], map: "personal_access_tokens_tokenable_type_tokenable_id_index")
}

model sessions {
  id            String  @id @db.VarChar(255)
  user_id       BigInt? @db.UnsignedBigInt
  ip_address    String? @db.VarChar(45)
  user_agent    String? @db.Text
  payload       String  @db.LongText
  last_activity Int

  @@index([last_activity], map: "sessions_last_activity_index")
  @@index([user_id], map: "sessions_user_id_index")
}

model users {
  id                BigInt    @id @default(autoincrement()) @db.UnsignedBigInt
  name              String    @db.VarChar(255)
  email             String    @unique(map: "users_email_unique") @db.VarChar(255)
  email_verified_at DateTime? @db.Timestamp(0)
  password          String    @db.VarChar(255)
  remember_token    String?   @db.VarChar(100)
  created_at        DateTime? @db.Timestamp(0)
  updated_at        DateTime? @db.Timestamp(0)
}