# 00_07 データベース仕様書 | 項目 | 内容 | |---|---| | 版 | v2.13(承認待ち) | | 作成 | 全体管理者 14代目 | | 対象 | SPS BACK OFFICE のデータ保存(MariaDB) | | 実装の状況 | `work_order_db_migration.md`(作業書)を見る | --- ## 1. 目的 - データの更新は、トランザクションで行い、データ破損・同時更新の競合・複数テーブルの不整合を起こさない。 - 画面(HTML)は、データを直接読まない。すべてAPI経由にする。 - 公開領域(public_html配下)にデータを置かない。 ## 2. 環境 | 項目 | 内容 | |---|---| | DB | MariaDB 10.11(MySQL互換) | | DB名 | (実名は `db_config.php` にだけ記す。例:`xs000000_exampledb`) | | ユーザー | (実名は `db_config.php` にだけ記す。例:`xs000000_exampleuser`。上記DBにアクセス権あり) | | ホスト | `localhost` | | 文字コード | utf8mb4 | | 容量上限 | 5000 MB(サーバーパネル表示) | ## 3. 接続設定の置き場 - 設定ファイル:`backoffice/db_config.php`(PHPファイル。設定値を return するだけで、画面には何も出力しない)。 - パスワードは真柴さんがサーバー上で直接記入する。チャット・仕様書・Gitには書かない。 - 共通の接続処理は1か所にまとめる(`backoffice/lib/db.php`)。各APIはそれを読み込む。 - 接続は PDO、`ERRMODE_EXCEPTION`、プリペアドステートメント必須。文字列連結でSQLを組み立てない。 - 接続エラーの詳細(ホスト名・ユーザー名・SQL文)は、画面・APIレスポンスに出さない。ログにのみ残す。 ## 4. 設計方針 1. **ID・コードは意味のある値をそのまま主キーにする**(SPS_ID、拠点コード K01、顧客ID C001 など)。自動連番に置き換えない。 2. **採番は DB で行う**。採番用テーブル `id_counters` を `SELECT ... FOR UPDATE`(トランザクション内)で更新する。 3. **複数テーブルを更新する処理は、必ずトランザクション**で囲む。途中で失敗したら全部ロールバックする。 4. **一部のみ更新**を原則とする(UPDATE で変更項目だけ)。全体上書きはしない。 5. **削除は原則しない**。退職・無効化は状態項目で表す(物理削除の扱いは未決。10節)。 6. 入れ子が深く、検索・集計に使わない項目は、`JSON` 型の列(MariaDB では LONGTEXT の別名)にそのまま入れる。検索や集計が必要になった時点で、列に分ける。 7. 画面(HTML)は DB に接続しない。DB に触るのは PHP の API だけ。 8. パスワードの平文保存は、`00_03_login_session.md` 10節の決定どおり(変更禁止)。`users` テーブルの `password` 列は、どの API でも返さない。真柴さん専用の確認機能以外では読み出さない。 9. 値の変更の履歴は、データの更新と同じトランザクションで記録する(`00_10_change_history.md`)。 ## 5. テーブル設計 全列の定義は、領域ごとの SQL(`schema_*.sql`)に置き、仕様書と同じ版で管理する。ここには主な列を記す。従事者系の項目は `02_01_employee_table.md` のとおり。 ### 5.1 マスタ系 | テーブル | 主キー | 主な列 | |---|---|---| | `companies` | `company_code` | 会社(SPS、SCSPS)の基本情報(`02_03`)。`company_detective_names`:探偵業で使える名称 | | `businesses`、`business_companies` | `business_code` | 事業と、事業を行う会社(`01_02`) | | `branches` | `branch_code`(K01) | id_part(01)、name、location、active、sort_order(`01_11`) | | `satellites` | `satellite_code`(S01) | name、area、active、promoted_to(`01_11`) | | `branch_jurisdictions` | `jurisdiction_id` | satellite_code、branch_code、valid_from、valid_to(サテライトを管轄する拠点。期間つき。`01_11`) | | `contracts`、`contract_companies` | `contract_code`(C01) | 契約と、使える会社(`01_04`) | | `departments`、`department_companies` | `department_code`(D00) | 部署と、使える会社(`01_06`) | | `positions`、`position_companies` | `position_code`(P001) | 職務ポジションと、使える会社(`01_07`) | | `position_default_permissions` | (`position_code`, `permission_key`) | 職務ポジションの初期権限(`01_07` 4節) | | `position_rates` | `rate_id` | 業務委託の報酬の率。調査員比率、指導者配分率、宿泊日当、作成レベル、valid_from、valid_to(`01_07` 5節、`04_03`) | | `salaries` | `salary_id` | sps_id、company_code、contract_code、base_salary、hourly_wage、valid_from、valid_to、active(`01_08`) | | `permissions` | `permission_key` | name、description(付与画面の説明文)、scope、level、category、active、sort_order(`06_01`) | | `permission_ui_targets` | `target_id` | permission_key、page、element_type(page / box / button / link)、element_id、label(権限がどのページのどの部品に効くか。`06_01`) | | `case_types` | `case_type_code` | 案件種別(`04_01_03`)。ヒアリング項目などの一覧は JSON 列で持つ | テーブル作成のSQLは `schema_master.sql`。実行の順序:`schema_master.sql` → `schema_employees.sql` → `schema_history.sql` → `schema_clients.sql` → `schema_pricing.sql` → `schema_cases.sql` → 会計の残りの表(5.4節)。 ### 5.2 従事者系 | テーブル | 主キー | 主な列 | |---|---|---| | `employees` | `sps_id` | 氏名、氏名カナ、生年月日、住所各項目、電話、携帯、メール、採用年月日、採用拠点CD、稼働状況、写真パス、その他 など(`02_01` のとおり)。入れ子(業務委託契約・社会保険情報)は JSON 列 | | `employee_companies` | (`sps_id`, `company_code`) | 所属(従事者×会社で1行。掛け持ちは会社ごとに1行)。会社ごとの contract_cd、position_cd、dept_cd、contract_branch(契約拠点)、jurisdiction_branch(管轄拠点)、satellite_cd(サテライト)を持つ(`02_01`、`01_11`)。主たる所属は `employees.primary_company`(二重に持たない) | | `employee_permissions` | (`sps_id`, `permission_key`) | granted(bool)。`permission_key` は `permissions.permission_key` | | `employee_events` | `id` | 賞罰、昇進・降格の出来事(日付、種類、題名、内容、確認状態)。1件ずつ(`00_10` 7.3) | | `employee_evaluations` | 設計未確定 | 人事考課(`05_07`) | | `users` | `user_id` | sps_id、password(平文・非公開)、emergency_override、force_change、password_kind、password_issued_at、password_issued_by | | `active_sessions` | `user_id` | session_id、ログイン日時(二重ログイン制御用。1人1行) | ### 5.3 顧客系 列の定義は `schema_clients.sql`。項目は `02_02_client_table.md` 3.6節。 | テーブル | 主キー | 主な列 | |---|---|---| | `client_types` | `code` | name、sort_order、active(顧客区分) | | `client_type_companies` | (`code`, `company_code`) | 区分ごとに使える会社 | | `clients` | `client_id` | type、name、maiden_name、parent_client_id、postal_code、address、business_phone、business_email、active、created_by。顧客区分+3桁連番(例:L101)。Pは「親法人ID-支部2桁-個人2桁」 | | `client_aliases` | `alias_id` | client_id、alias_name、note(顧客の別名。検索・名寄せ用) | | `client_branches` | `branch_id` | client_id、branch_name、department_name、section_name、active | | `persons` | `person_id`(P-…) | name、name_kana、birthday、personal_mobile、personal_email、created_at | | `client_contacts` | `contact_id`(CT-…) | person_id、client_id、branch_id、role、grade、company_phone、direct_phone、company_mobile、company_email、is_window(窓口担当)、valid_from、valid_to、active。API で権限制御する | | `meishi_history` | `meishi_id`(M-…) | person_id、contact_id、image_front、original_file、OCR結果、received_by、exchanged_at、exchanged_place、tags | ### 5.4 会計系 | テーブル | 内容 | |---|---| | `journals` | 仕訳。主キーは自動採番の `row_id`。仕訳の `id`(小数付き数値)は `journal_id`(文字列。一意制約なし、通常の索引)で持つ。company、journal_date、tax_included、project_id、description、status、receipt_path、extra_json(作成者など)、created_at、updated_at ほか。会社区分(SPS/SCSPS)は列 `company` で持つ。年ごとの分割はせず、日付(`journal_date`)で区別する。`source_file` の列は、年・期の区切りに使わない。申告済みかどうかは `tax_filings` で決まり、`locked` の列は使わない | | `journal_entries` | 仕訳の明細。account、sub_account、debit、credit、tax_type | | `accounts` | 勘定科目。account_code、name、account_type、tax_default、use_sub、sub_display、etax_group、is_system、active、sort_order(並び順)、created_at(`07_07`)。`account_companies`:科目を使える会社。`sub_accounts`:補助科目 | | `fixed_assets` | 固定資産。fixed_asset_id(FA+数字13桁、15文字)、name、asset_type(vehicle/equipment/building/deferred)、company_code、acquisition_date、acquisition_cost、useful_life、depreciation_method(straight/declining)、depreciation_rate、business_ratio、note、status(active/disposed)、disposal_date、sale_date、sale_price(`07_08` 6.1節) | | `user_data` | 画面が保存する手入力の値(BS期首残高・借入金内訳など)。data_key(英数字・`_`・`-`)を主キーに、内容を JSON 文字列で持つ。updated_by、updated_at | | `tax_filings` | 申告の記録(会社・期間ごと)。filing_id(自動採番)、company、period_start、period_end、filed_at、filed_by、unlocked_at、unlocked_by。`unlocked_at` が空の行がある期間は申告済みで、その期間に入る日付の仕訳の追加・変更・削除を、保存APIが断る。解除しても行は消さず、再申告は新しい行で登録する(`07_02` 6節、`07_05` 3.4節) | - 貸借の不一致、同一 `journal_id` の重複、年と日付の不一致があるデータを、DB は拒否しない。取込・保存の結果で、件数を警告として報告する。 - 法人会計は、個人会計と同じ構造で、会社区分で分ける。 - 会社間の仕訳の移動(`07_02` 4.3節)は、専用の表を持たず、`audit_logs`(5.6節)に記録する。 ### 5.5 案件系(会計と連動) 案件の内容はDBで持ち、写真・報告書・請求書PDFなどの実ファイルは、案件ごとのフォルダ(`data/cases/{private|corporate}/{案件番号}/`)の `files/`、`reports/`、`invoices/`、`reimbursement/` に置く(定義は `04_01_02`、SQL は `schema_cases.sql`)。 | テーブル | 主キー | 内容 | |---|---|---| | `case_approaches` | `approach_code` | 着手対応のマスタ(弁護士特約/弁護士依頼(通常)/弁護士依頼(高難易度)/依頼者直接。顧客区分が弁護士のときだけ使う。請求先・価格区分・契約保険会社の要否。`04_01_03`) | | `case_client_refs` | `ref_id` | 依頼先の番号(事故受付番号・貴社管理番号・事件番号など。種類つきで複数) | | `case_ref_types` | `ref_type` | 依頼先の番号の種類(増やせる) | | `client_type_ref_defaults` | `client_type`+`ref_type` | 顧客区分ごとの最初の番号の欄 | | `cases` | `case_id` | 案件レベルの項目と基本情報(案件番号、状態、種別、依頼元と控え、着手対応、請求先、依頼者、事故日、担当、日付など) | | `case_investigators` | `case_id`+`sps_id` | 担当調査員(主担当・副担当) | | `case_files` | `file_id` | 案件の資料の名前と場所 | | `case_branch_history` | `history_id` | 案件管理拠点の変更の履歴 | | `case_assignment_history` | `history_id` | 担当(営業・管理担当者・主担当・副担当)の変更の履歴。理由、前任者への報酬の有無 | | `case_change_reasons` | `reason_code` | 担当変更の理由のマスタ(`04_01_03`) | | `case_members` | `case_id`+`sps_id` | 案件ごとの追加の権限者(指導指名・特例アクセス) | | `case_reviews` | `review_id` | 金額まわりの確認と差し戻し | | `case_contact_logs` | `log_id` | 問い合わせ対応の連絡メモ | | `case_edit_history` | `edit_id` | 案件の内容を修正した履歴 | | `case_access_requests` | `request_id` | 特例アクセスの申請 | | `notifications` | `notice_id` | アプリ内のお知らせ(案件の中身は書かない) | | `position_case_access` | `position_code` | 職務ポジションごとの、案件を見られる範囲の既定(`04_01_08`) | | `employee_case_access` | `sps_id` | 個人ごとの例外 | | `case_sections` | `case_id`+`section` | 聴取内容・分析・近隣確認・証拠資料・経費・請求・経過・成果物チェックリスト(各タブの設計が決まるまで JSON) | 案件番号の採番は `id_counters`(キー `CASE-YYYYMM`)。案件番号の決め方は `04_01_02` 4.3節。 ### 5.5.1 料金・報酬系 定義は `schema_pricing.sql`(マスタ)と `schema_cases.sql`(案件ごとの固定値)。設計は `04_03_01_pricing_and_reward.md`。 | テーブル | 主キー | 内容 | |---|---|---| | `difficulty_ranks` | `rank_code` | 難易度ランク(S/D/H)。運用で増やせる | | `survey_items` | `item_code` | 調査種目 | | `price_classes` | `price_class` | 価格区分(価格の種類。一般調査料金、法人会員、弁護士A・B、弁護士特約、損保社用など。増やせる)と、基本料金・時間単価の係数 | | `price_table` | `price_id` | 価格区分×調査種目×ランクの基本料金。期間つき | | `client_type_price_defaults` | `client_type` | 顧客区分ごとの既定の価格区分。着手対応を聞くか(弁護士だけ) | | `client_discounts` | `discount_id` | 顧客ごとの基本料金の値引き。期間つき | | `client_price_settings` | `setting_id` | 顧客ごとの価格区分(契約・会員など)。期間つき | | `pricing_params` | `param_key`+`valid_from` | 単価、消費税、物価スライド係数、営業手当・事務手当の率。期間つき | | `work_breakdown_items` | `item_code` | 業務内訳の12項目と比率 | | `case_pricing` | `case_id` | 案件の価格(確定時点の値を固定) | | `case_reward_lines` | `line_id` | 案件の報酬の内訳(確定時点の率を固定) | | `case_work_breakdown` | `case_id`+`item_code` | 業務内訳の実施記録 | 業務委託の報酬の率は `position_rates`、直接雇用の給与は `salaries`(5.1節)。 ### 5.6 ログ・履歴系(追記型) | テーブル | 内容 | |---|---| | `login_logs` | ログイン成功・失敗の履歴 | | `audit_logs` | 重要操作の履歴(権限変更、アカウント停止・解除、2名承認の記録、会計の会社間移動 など)。log_id(自動採番)、logged_at、operator_id、action(操作の種類)、target(対象の種類とID)、detail_json(内容。会社間移動なら移動元と移動先の会社、仕訳のID) | | `change_history` | マスタ項目の値の変更の履歴と、Wチェック(確認)の状態(`00_10`) | | `edit_logs` | 訂正扱いの編集の短期ログ(保管90日。`00_10`) | | `id_counters` | 採番用(名前・年・現在値) | - `audit_logs`=権限変更・アカウント停止・書類発行など「操作」の記録。`change_history`=拠点・従事者・得意先などの「値の変更」の記録。詳細は `00_10_change_history.md`。 ## 6. バックアップ - サーバーの自動バックアップ(毎日・14日分)に加え、必要なときは、phpMyAdmin から `.sql` を書き出して保管する。 - 手順と、復元の注意は `manual/database_manual.md` に従う。復元は、全体管理者に相談してから行う。 - 画像などのファイルは、DB のバックアップに含まれない。ファイルは別に保管する(8節)。 ## 7. 画像ファイルの扱い(DB化しない) - 領収書・名刺・従事者写真は、**ファイルのまま**保存し、DBにはパスだけを持つ。 - 画像フォルダ(`data/receipts/`、`data/clients/meishi/`、`data/employees/photos/`)への直接アクセスは禁止する。画像は認証付きの配信PHPを通して返す。 - 領収書:`master/api/get_receipt.php`(権限:accounting_view/edit/export/approve、全権、permission_assign) - 名刺:`clients/api/get_meishi.php`(権限:client_view/edit、全権、permission_assign) - 従事者写真:`employees/api/upload_photo.php`(保存)。表示の配信は `03_02_master_management.md` 11.2節に従う - 配信PHPは、`data/` 配下の想定フォルダの外を指すパス、拡張子が jpg/jpeg/png 以外のものを拒否する。 ## 8. セキュリティ規則 1. `data/` 配下には `.htaccess` を置き、json・bak・log・csv・txt・lock・tmp を外から読めなくする。 2. 新しいデータフォルダを作ったら、公開URLで開いて 403 か 404 になるかを必ず確認する。 3. DBのパスワードを含むファイルは、実際にURLで開いて内容が出ないことを確認する。 4. 画面は、`master/` などのデータファイルを直接読まない。マスタも API 経由で取得する。 ### 8.1 APIの認証規則 1. **すべてのAPIは、ログイン確認から始める**。未ログインは 401。権限のない場合は 403。ログイン確認のないAPIは作らない。 2. 共通処理は `master/api/require_login.php` に置き、各APIは `sps_require_login()`/`sps_require_any([権限キー…])` を呼ぶ。全権(`supreme_access`)は、すべての権限キーを持つものとして扱う。 3. 操作者のIDは、**ログイン中のセッションから取る**。リクエストに入っている user/user_id の値は使わない。 4. 権限キーの割り当て: | 対象 | 読む | 書く | |---|---|---| | 仕訳・勘定科目・固定資産・BS期首残高等 | accounting_view/edit/export/approve のいずれか | accounting_edit(申告済みにする(`tax_filings` への登録)は accounting_approve でも可。申告済みの解除は accounting_approve だけ) | | 領収書画像(保存・移動・OCR・表示) | accounting_view 等 | accounting_edit | | 事業者情報 | company_info_view | company_info_edit | | 案件の読込 | company_access_{sps\|scsps} + case_detail_view_all/own 等(案件一覧と同じ基準) | 既存の save_case.php の基準 | | 案件番号の発行 | — | case_create_from_cases または case_create_from_sales | | PDF生成 | ログイン済みであれば可 | — | 5. 会計の権限は、個人の確定申告用に先に作ったため、他の領域と方式が異なる。会社単位の制限(`company_access_*` を会計に適用するか)は未決(10節)。 6. 画像の保存は、中身が JPEG/PNG であることを確認する。日付・ファイル名・移動元パスは形式を検査し、領収書フォルダの外を指すものは拒否する。 ### 8.2 会計データ保存の規則 - 仕訳の保存は、トランザクションで行う。失敗したら全部ロールバックする。 - 保存の前に、既存データの状態を `data/backups/` 以下に残す。残せない場合は保存しない。 - 保存は、追加・変更・削除した仕訳だけを受け取る(4節の4)。一度の保存で、期間内の仕訳をすべて削除する要求は拒否する(409)。全件削除は、画面からは行えない。 - 申告済みの期間(`tax_filings`)に入る日付の仕訳の追加・変更・削除は拒否する(変更の前と後の日付の両方を確かめる)。 - 配列でないデータ、形式の不正な仕訳(`id`・`entries` なし)は拒否する。 - `journal_id` が重複した場合は警告として返し、保存は止めない。 - 保存に失敗したとき、画面は必ず利用者に知らせる。 - バックアップは自動削除しない。容量が増えた場合の整理方法は未決(10節)。 ## 9. 公開領域の規則 - 公開領域(public_html配下)にある `master/` などのデータファイルは、`.htaccess` で外から読めなくする。 - 勘定科目などのマスタは、API経由で取得する。別ドメインのファイルを直接読まない。 ## 10. 未決事項(真柴さんの決定が必要) 1. 退職者・無効データの物理削除をするか(4節の5)。 2. 会計に会社単位の制限(`company_access_*`)を適用するか(8.1節の5)。 3. 会計のバックアップの整理方法(8.2節)。 ## 改訂履歴 | 日付 | 版 | 担当 | 内容 | |---|---|---|---| | 2026-11-07 | v2.13 | 全体管理者16代目 | (承認前の追記)5.4節:`accounts` に並び順の列 `sort_order` を追加(真柴さんの決定 2026-11-07。`07_07` 5.1・5.2節)。created_at を列の一覧に明記 | | 2026-11-06 | v2.13 | 全体管理者16代目 | v2.12 の承認取り消し(2026-11-05)を受けた修正と、2026-11-06 の決定(決定1〜3)。5.4節:`journals` の列を実物に合わせ、日付で区別(`source_file`・`locked` は使わない)、`fixed_assets` の列を `07_08` v2.2 に合わせた、`journal_transfers` を削除、申告の記録 `tax_filings` を追加。5.6節:`audit_logs` の列を追加し、会社間移動の記録先とした。8.1節:申告済みの解除は accounting_approve だけ。8.2節:保存は変更分だけ、申告済みの期間の保存は拒否。5.1節:実行の順序を7本に | | 2026-11-05 | v2.12 | 全体管理者14代目 | 5.4 の「設計未確定」を解消。`fixed_assets`、`user_data`、`journal_transfers` を追加 | | 2026-11-04 | v2.11 | 全体管理者14代目 | 5.5 に依頼先の番号(`case_client_refs`、`case_ref_types`、`client_type_ref_defaults`)を追加 | | 2026-11-02 | v2.10 | 全体管理者14代目 | 5.5.1 に `client_discounts` を追加。`client_type_price_defaults` に着手対応を聞くかの列を追加。価格区分に対外名を追加 | | 2026-10-31 | v2.9 | 全体管理者14代目 | 5.5.1 に料金・報酬系のテーブルを追加 | | 2026-10-31 | v2.8 | 全体管理者14代目 | 5.5 に `case_edit_history`、`case_access_requests`、`notifications` を追加 | | 2026-10-31 | v2.7 | 全体管理者14代目 | 5.5 の案件系に、案件の権限(`case_members`、`position_case_access`、`employee_case_access`)、確認と差し戻し(`case_reviews`)、連絡メモ(`case_contact_logs`)を追加。`branches` に `is_headquarters` を追加 | | 2026-10-31 | v2.6 | 全体管理者14代目 | 5.5 の案件系に `case_assignment_history`、`case_change_reasons` を追加 | | 2026-10-31 | v2.5 | 全体管理者14代目 | 5.5 の案件系に `case_branch_history`(案件管理拠点の変更の履歴)を追加 | | 2026-10-30 | v2.4 | 全体管理者14代目 | 5.5 の案件系を、テーブルの一覧(`case_approaches`、`cases`、`case_investigators`、`case_files`、`case_sections`)に確定。案件番号の採番キー `CASE-YYYYMM` を記載 | | 2026-10-30 | v2.3 | 全体管理者14代目 | 5.1 にマスタ系のテーブルを確定(会社、事業、拠点、サテライト、管轄、契約、部署、職務ポジション、報酬の率、給与、権限、案件種別)。5.2:契約・職務ポジション・部署・拠点を `employee_companies`(会社ごと)に移した。5.4:`accounts` などを追記 | | 2026-10-29 | v2.2 | 全体管理者14代目 | 5.3節に `client_aliases`(顧客の別名)、`client_contacts.is_window`(窓口担当)を追加 | | 2026-10-29 | v2.1 | 全体管理者14代目 | 5.3節(顧客系)を、実データの確認に基づき確定。`schema_clients.sql` を追加 | | 2026-10-29 | v2.0 | 全体管理者14代目 | 全面書き直し。DB前提の完成形のみを記述。JSONからの移行の手順・順序・元ファイル欄・移行前の点検の記述を除き、作業書(`work_order_db_migration.md`)へ移した。5節をテーブル設計として整理(未確定の表は「設計未確定」と明記)。バックアップ(6節)に自動バックアップと `.sql` の書き出しを記載。API認証規則・会計保存規則を、DB前提に直した | | 2026-10-29 | v1.1 | 全体管理者14代目 | 変更履歴(00_10)の追加に伴い、5.2 に `employee_events`、5.5 に `change_history`・`edit_logs` を追記。`employee_companies` の `is_primary` を削除(主たる所属は `employees.primary_company`)、`employee_permissions` の列名を `permission_key` に統一。2節のDB名・DBユーザー名の実名を、例に差し替え(実名は `db_config.php` にだけ記す) | | 2026-10-29 | v1.0 | 全体管理者14代目 | 真柴さん承認。5.4 に、会計データの既知の問題を修正せずに取り込む方針と、DB側の扱い(`row_id`、`journal_id`、警告)を追記。10節を更新 | | 2026-10-28 | v0.1 | 全体管理者14代目 | 新規作成(ドラフト) |