データモデル設計 - 国際貨物輸送管理システム¶
概要¶
本ドキュメントは、国際貨物輸送管理システムの永続化層データモデルを定義する。
ドメインモデル分析で識別した 6 つの境界付けられたコンテキスト(Booking / Routing / Tracking / Handling / Billing / Shared Domain)に対応する 16 テーブルを設計する。
shipper(荷主)テーブルと、Spring Security 用の users / user_roles テーブルを含む。
設計方針¶
- DB: PostgreSQL 16.x(本番)、H2(テスト)
- ORM: MyBatis(XML マッパー)
- マイグレーション: Flyway(
V1__init.sql形式) - ID 戦略: サロゲートキー(
BIGSERIAL)+ 業務キー(VARCHAR)の併用 - 命名規則: スネークケース(PostgreSQL 慣習)
- 監査カラム: 全テーブルに
created_at/updated_atを付与
概念データモデル¶
全コンテキストのエンティティとその主要リレーションシップを俯瞰する。
論理データモデル¶
Shared Domain¶
共有ドメインとして全コンテキストが参照する場所マスタ。UN/LOCODE(国連貿易港コード)を業務キーとする。
Booking Context¶
貨物の予約・旅程情報を管理する。cargo が集約ルートで、leg が旅程の各区間を表す。荷主情報は shipper テーブルに正規化し、FK 参照とする。
Routing Context¶
航海スケジュールと運送区間を管理する。voyage が集約ルートで、carrier_movement が個々の移動区間を表す。
Tracking Context¶
貨物追跡の状態・イベント・例外を管理する。tracking_activity が集約ルート。
Handling Context¶
荷役作業の実績と税関申告を管理する。handling_activity が集約ルート。
Billing Context¶
精算書・明細・支払記録を管理する。参考実装には存在しない新規コンテキスト。
Security Context¶
Spring Security の UserDetailsService が利用するユーザー認証・認可テーブル。
テーブル定義¶
location(場所マスタ)¶
| カラム名 | データ型 | 制約 | 説明 |
|---|---|---|---|
id |
BIGINT |
PK, NOT NULL |
サロゲートキー(BIGSERIAL) |
unlocode |
VARCHAR(5) |
UK, NOT NULL |
UN/LOCODE(業務キー。例: JPTYO) |
name |
VARCHAR(100) |
NOT NULL |
場所名称(例: Tokyo) |
country_code |
VARCHAR(2) |
ISO 3166-1 alpha-2 国コード | |
time_zone |
VARCHAR(50) |
タイムゾーン(例: Asia/Tokyo) |
|
created_at |
TIMESTAMP WITH TIME ZONE |
NOT NULL, DEFAULT NOW() |
レコード作成日時 |
updated_at |
TIMESTAMP WITH TIME ZONE |
NOT NULL, DEFAULT NOW() |
レコード更新日時 |
shipper(荷主)¶
注記: 旧設計で
cargoテーブルに存在したshipper_name・shipper_emailカラムは本テーブルへの正規化に伴い削除した。
| カラム名 | データ型 | 制約 | 説明 |
|---|---|---|---|
id |
BIGINT |
PK, NOT NULL |
サロゲートキー(BIGSERIAL) |
shipper_code |
VARCHAR(20) |
UK, NOT NULL |
荷主コード(業務キー。SHP-XXXXXX 形式) |
shipper_type |
VARCHAR(20) |
NOT NULL |
荷主種別(INDIVIDUAL / CORPORATE) |
name |
VARCHAR(200) |
NOT NULL |
荷主名称 |
email |
VARCHAR(200) |
NOT NULL |
メールアドレス |
phone |
VARCHAR(50) |
電話番号 | |
contract_number |
VARCHAR(50) |
契約番号(法人のみ。NULLable) | |
discount_rate |
NUMERIC(5,4) |
DEFAULT 0.0000 |
割引率(0.0000〜0.1500、最大 15%) |
created_at |
TIMESTAMP WITH TIME ZONE |
NOT NULL, DEFAULT NOW() |
レコード作成日時 |
updated_at |
TIMESTAMP WITH TIME ZONE |
NOT NULL, DEFAULT NOW() |
レコード更新日時 |
DDL¶
CREATE TABLE shipper (
id BIGSERIAL PRIMARY KEY,
shipper_code VARCHAR(20) NOT NULL UNIQUE, -- SHP-XXXXXX 形式
shipper_type VARCHAR(20) NOT NULL, -- INDIVIDUAL / CORPORATE
name VARCHAR(200) NOT NULL,
email VARCHAR(200) NOT NULL,
phone VARCHAR(50),
contract_number VARCHAR(50), -- 法人のみ(NULLable)
discount_rate NUMERIC(5,4) DEFAULT 0.0000, -- 0.0000〜0.1500 (最大 15%)
created_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT NOW(),
updated_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT NOW()
);
cargo(貨物)¶
注記:
shipper_name・shipper_emailカラムは削除し、shipper_id(FK →shipper.id)による参照に変更した。
| カラム名 | データ型 | 制約 | 説明 |
|---|---|---|---|
id |
BIGINT |
PK, NOT NULL |
サロゲートキー(BIGSERIAL) |
booking_id |
VARCHAR(20) |
UK, NOT NULL |
予約 ID(業務キー) |
shipper_id |
BIGINT |
FK → shipper.id, NOT NULL |
荷主 ID |
booking_status |
VARCHAR(30) |
NOT NULL |
予約状態(BookingStatus 列挙値) |
transport_status |
VARCHAR(30) |
NOT NULL |
輸送状態(TransportStatus 列挙値) |
routing_status |
VARCHAR(30) |
NOT NULL |
経路決定状態(例: ROUTED, MISROUTED, NOT_ROUTED) |
cargo_type |
VARCHAR(20) |
NOT NULL, DEFAULT 'GENERAL' |
貨物種別(GENERAL / PERISHABLE / HAZARDOUS / REFRIGERATED) |
weight_kg |
NUMERIC(10,3) |
NOT NULL |
重量(kg) |
declared_value |
NUMERIC(15,2) |
申告価格(保険料算出用) | |
spec_origin_unlocode |
VARCHAR(5) |
FK → location.unlocode |
出荷元(RouteSpecification) |
spec_destination_unlocode |
VARCHAR(5) |
FK → location.unlocode |
仕向地(RouteSpecification) |
spec_arrival_deadline |
DATE |
到着期限(RouteSpecification) | |
origin_unlocode |
VARCHAR(5) |
FK → location.unlocode |
実際の出発地 |
booking_amount_value |
INTEGER |
NOT NULL |
予約金額(最小通貨単位、例: 円) |
booking_amount_currency |
VARCHAR(3) |
NOT NULL |
通貨コード(ISO 4217、例: JPY) |
consignee_name |
VARCHAR(200) |
荷受人名 | |
consignee_email |
VARCHAR(200) |
荷受人メールアドレス | |
tracking_number |
VARCHAR(20) |
追跡番号(発行後に設定) | |
next_expected_location_unlocode |
VARCHAR(5) |
次の予定場所(UN/LOCODE) | |
next_expected_handling_event_type |
VARCHAR(30) |
次の予定荷役タイプ | |
next_expected_voyage_number |
VARCHAR(20) |
次の予定航海番号 | |
last_known_location_unlocode |
VARCHAR(5) |
最終確認場所(UN/LOCODE) | |
current_voyage_number |
VARCHAR(20) |
現在の航海番号 | |
last_handling_event_type |
VARCHAR(30) |
最後の荷役タイプ | |
last_handling_event_location |
VARCHAR(5) |
最後の荷役場所(UN/LOCODE) | |
last_handling_event_voyage |
VARCHAR(20) |
最後の荷役航海番号 | |
created_at |
TIMESTAMP WITH TIME ZONE |
NOT NULL, DEFAULT NOW() |
レコード作成日時 |
updated_at |
TIMESTAMP WITH TIME ZONE |
NOT NULL, DEFAULT NOW() |
レコード更新日時 |
leg(輸送区間)¶
| カラム名 | データ型 | 制約 | 説明 |
|---|---|---|---|
id |
BIGINT |
PK, NOT NULL |
サロゲートキー(BIGSERIAL) |
cargo_id |
BIGINT |
FK → cargo.id, NOT NULL |
親貨物 ID |
voyage_number |
VARCHAR(20) |
FK → voyage.voyage_number, NOT NULL |
航海番号 |
load_location_unlocode |
VARCHAR(5) |
FK → location.unlocode, NOT NULL |
積込場所(UN/LOCODE) |
unload_location_unlocode |
VARCHAR(5) |
FK → location.unlocode, NOT NULL |
荷降場所(UN/LOCODE) |
load_time |
TIMESTAMP |
積込予定日時 | |
unload_time |
TIMESTAMP |
荷降予定日時 | |
seq_number |
INTEGER |
NOT NULL |
区間順序(1 始まり) |
created_at |
TIMESTAMP |
NOT NULL, DEFAULT NOW() |
レコード作成日時 |
updated_at |
TIMESTAMP |
NOT NULL, DEFAULT NOW() |
レコード更新日時 |
voyage(航海)¶
| カラム名 | データ型 | 制約 | 説明 |
|---|---|---|---|
id |
BIGINT |
PK, NOT NULL |
サロゲートキー(BIGSERIAL) |
voyage_number |
VARCHAR(20) |
UK, NOT NULL |
航海番号(業務キー) |
created_at |
TIMESTAMP |
NOT NULL, DEFAULT NOW() |
レコード作成日時 |
updated_at |
TIMESTAMP |
NOT NULL, DEFAULT NOW() |
レコード更新日時 |
carrier_movement(運送区間)¶
| カラム名 | データ型 | 制約 | 説明 |
|---|---|---|---|
id |
BIGINT |
PK, NOT NULL |
サロゲートキー(BIGSERIAL) |
voyage_id |
BIGINT |
FK → voyage.id, NOT NULL |
親航海 ID |
departure_location_unlocode |
VARCHAR(5) |
FK → location.unlocode, NOT NULL |
出発地(UN/LOCODE) |
arrival_location_unlocode |
VARCHAR(5) |
FK → location.unlocode, NOT NULL |
到着地(UN/LOCODE) |
departure_date |
TIMESTAMP |
NOT NULL |
出発日時 |
arrival_date |
TIMESTAMP |
NOT NULL |
到着日時 |
seq_number |
INTEGER |
NOT NULL |
区間順序(1 始まり) |
created_at |
TIMESTAMP |
NOT NULL, DEFAULT NOW() |
レコード作成日時 |
updated_at |
TIMESTAMP |
NOT NULL, DEFAULT NOW() |
レコード更新日時 |
tracking_activity(追跡レコード)¶
| カラム名 | データ型 | 制約 | 説明 |
|---|---|---|---|
id |
BIGINT |
PK, NOT NULL |
サロゲートキー(BIGSERIAL) |
tracking_number |
VARCHAR(20) |
UK, NOT NULL |
追跡番号(業務キー) |
booking_id |
VARCHAR(20) |
NOT NULL |
予約 ID(参照整合性は書き込み側で保証) |
transport_status |
VARCHAR(30) |
NOT NULL |
輸送状態(TransportStatus 列挙値) |
created_at |
TIMESTAMP |
NOT NULL, DEFAULT NOW() |
レコード作成日時 |
updated_at |
TIMESTAMP |
NOT NULL, DEFAULT NOW() |
レコード更新日時 |
tracking_handling_event(追跡イベント)¶
| カラム名 | データ型 | 制約 | 説明 |
|---|---|---|---|
id |
BIGINT |
PK, NOT NULL |
サロゲートキー(BIGSERIAL) |
tracking_id |
BIGINT |
FK → tracking_activity.id, NOT NULL |
親追跡レコード ID |
event_type |
VARCHAR(30) |
NOT NULL |
荷役タイプ(HandlingType 列挙値) |
event_time |
TIMESTAMP |
NOT NULL |
イベント発生日時 |
location_unlocode |
VARCHAR(5) |
FK → location.unlocode |
イベント発生場所(UN/LOCODE) |
voyage_number |
VARCHAR(20) |
関連する航海番号 | |
created_at |
TIMESTAMP |
NOT NULL, DEFAULT NOW() |
レコード作成日時 |
updated_at |
TIMESTAMP |
NOT NULL, DEFAULT NOW() |
レコード更新日時 |
tracking_exception_event(追跡例外イベント)¶
| カラム名 | データ型 | 制約 | 説明 |
|---|---|---|---|
id |
BIGINT |
PK, NOT NULL |
サロゲートキー(BIGSERIAL) |
tracking_id |
BIGINT |
FK → tracking_activity.id, NOT NULL |
親追跡レコード ID |
exception_type |
VARCHAR(50) |
NOT NULL |
例外種別(例: CUSTOMS_HOLD, DAMAGE, DELAY) |
occurred_at |
TIMESTAMP WITH TIME ZONE |
NOT NULL |
例外発生日時 |
escalation_flag |
BOOLEAN |
NOT NULL, DEFAULT FALSE |
エスカレーション判定フラグ(US15 紛失時) |
description |
VARCHAR(500) |
例外内容の詳細 | |
resolved_at |
TIMESTAMP WITH TIME ZONE |
解決日時(NULL = 未解決) | |
resolution_notes |
TEXT |
対応内容メモ | |
created_at |
TIMESTAMP WITH TIME ZONE |
NOT NULL, DEFAULT NOW() |
レコード作成日時 |
updated_at |
TIMESTAMP WITH TIME ZONE |
NOT NULL, DEFAULT NOW() |
レコード更新日時 |
handling_activity(荷役作業記録)¶
| カラム名 | データ型 | 制約 | 説明 |
|---|---|---|---|
id |
BIGINT |
PK, NOT NULL |
サロゲートキー(BIGSERIAL) |
booking_id |
VARCHAR(20) |
NOT NULL |
予約 ID(参照整合性は書き込み側で保証) |
event_type |
VARCHAR(30) |
NOT NULL |
荷役タイプ(RECEIVE / LOAD / UNLOAD / CUSTOMS / CLAIM) |
event_completion_time |
TIMESTAMP |
NOT NULL |
荷役完了日時 |
location_unlocode |
VARCHAR(5) |
FK → location.unlocode, NOT NULL |
作業場所(UN/LOCODE) |
voyage_number |
VARCHAR(20) |
関連する航海番号(LOAD / UNLOAD 時に設定) | |
operator_name |
VARCHAR(200) |
作業員名 | |
created_at |
TIMESTAMP |
NOT NULL, DEFAULT NOW() |
レコード作成日時 |
updated_at |
TIMESTAMP |
NOT NULL, DEFAULT NOW() |
レコード更新日時 |
customs_declaration(税関申告)¶
| カラム名 | データ型 | 制約 | 説明 |
|---|---|---|---|
id |
BIGINT |
PK, NOT NULL |
サロゲートキー(BIGSERIAL) |
handling_activity_id |
BIGINT |
FK → handling_activity.id, NOT NULL |
関連荷役作業 ID |
declaration_number |
VARCHAR(50) |
UK, NOT NULL |
申告番号(業務キー) |
declared_at |
TIMESTAMP |
NOT NULL |
申告日時 |
status |
VARCHAR(30) |
NOT NULL |
申告状態(例: PENDING, CLEARED, HELD) |
cleared_at |
TIMESTAMP |
通関完了日時(NULL = 未完了) | |
remarks |
VARCHAR(500) |
備考・メモ | |
created_at |
TIMESTAMP |
NOT NULL, DEFAULT NOW() |
レコード作成日時 |
updated_at |
TIMESTAMP |
NOT NULL, DEFAULT NOW() |
レコード更新日時 |
invoice(精算書)¶
| カラム名 | データ型 | 制約 | 説明 |
|---|---|---|---|
id |
BIGINT |
PK, NOT NULL |
サロゲートキー(BIGSERIAL) |
invoice_number |
VARCHAR(30) |
UK, NOT NULL |
精算書番号(業務キー) |
booking_id |
VARCHAR(20) |
UK, NOT NULL |
予約 ID(UNIQUE 制約で二重請求を防止) |
total_amount_value |
INTEGER |
NOT NULL |
合計金額(最小通貨単位) |
total_amount_currency |
VARCHAR(3) |
NOT NULL |
通貨コード(ISO 4217) |
tax_rate |
NUMERIC(5,4) |
NOT NULL, DEFAULT 0.1000 |
消費税率(デフォルト 10%) |
tax_amount |
NUMERIC(15,2) |
NOT NULL, DEFAULT 0 |
消費税額 |
payment_status |
VARCHAR(30) |
NOT NULL |
支払状態(PENDING / CONFIRMED / OVERDUE / REFUNDED) |
issued_at |
TIMESTAMP WITH TIME ZONE |
発行日時 | |
due_date |
DATE |
支払期日 | |
discount_amount_value |
INTEGER |
割引金額(最小通貨単位) | |
discount_amount_currency |
VARCHAR(3) |
割引通貨コード | |
created_at |
TIMESTAMP WITH TIME ZONE |
NOT NULL, DEFAULT NOW() |
レコード作成日時 |
updated_at |
TIMESTAMP WITH TIME ZONE |
NOT NULL, DEFAULT NOW() |
レコード更新日時 |
invoice_line_item(精算明細)¶
| カラム名 | データ型 | 制約 | 説明 |
|---|---|---|---|
id |
BIGINT |
PK, NOT NULL |
サロゲートキー(BIGSERIAL) |
invoice_id |
BIGINT |
FK → invoice.id, NOT NULL |
親精算書 ID |
description |
VARCHAR(200) |
NOT NULL |
明細項目説明 |
amount_value |
INTEGER |
NOT NULL |
明細金額(最小通貨単位) |
amount_currency |
VARCHAR(3) |
NOT NULL |
通貨コード(ISO 4217) |
seq_number |
INTEGER |
NOT NULL |
明細順序(1 始まり) |
created_at |
TIMESTAMP |
NOT NULL, DEFAULT NOW() |
レコード作成日時 |
updated_at |
TIMESTAMP |
NOT NULL, DEFAULT NOW() |
レコード更新日時 |
payment(支払記録)¶
| カラム名 | データ型 | 制約 | 説明 |
|---|---|---|---|
id |
BIGINT |
PK, NOT NULL |
サロゲートキー(BIGSERIAL) |
invoice_id |
BIGINT |
FK → invoice.id, NOT NULL |
親精算書 ID |
paid_amount_value |
INTEGER |
NOT NULL |
支払金額(最小通貨単位) |
paid_amount_currency |
VARCHAR(3) |
NOT NULL |
通貨コード(ISO 4217) |
paid_at |
TIMESTAMP |
NOT NULL |
支払日時 |
payment_method |
VARCHAR(30) |
NOT NULL |
支払方法(例: BANK_TRANSFER, CREDIT_CARD) |
transaction_reference |
VARCHAR(100) |
取引参照番号(外部決済システムの ID) | |
created_at |
TIMESTAMP WITH TIME ZONE |
NOT NULL, DEFAULT NOW() |
レコード作成日時 |
updated_at |
TIMESTAMP WITH TIME ZONE |
NOT NULL, DEFAULT NOW() |
レコード更新日時 |
users(ユーザー)¶
Spring Security の UserDetailsService が参照するユーザー認証テーブル。
| カラム名 | データ型 | 制約 | 説明 |
|---|---|---|---|
id |
BIGINT |
PK, NOT NULL |
サロゲートキー(BIGSERIAL) |
username |
VARCHAR(50) |
UK, NOT NULL |
ログイン名 |
email |
VARCHAR(200) |
UK, NOT NULL |
メールアドレス |
password |
VARCHAR(255) |
NOT NULL |
パスワード(BCrypt ハッシュ) |
enabled |
BOOLEAN |
NOT NULL, DEFAULT TRUE |
アカウント有効フラグ |
created_at |
TIMESTAMP WITH TIME ZONE |
NOT NULL, DEFAULT NOW() |
レコード作成日時 |
DDL¶
CREATE TABLE users (
id BIGSERIAL PRIMARY KEY,
username VARCHAR(50) NOT NULL UNIQUE,
email VARCHAR(200) NOT NULL UNIQUE,
password VARCHAR(255) NOT NULL, -- BCrypt ハッシュ
enabled BOOLEAN NOT NULL DEFAULT TRUE,
created_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT NOW()
);
user_roles(ユーザーロール)¶
| カラム名 | データ型 | 制約 | 説明 |
|---|---|---|---|
user_id |
BIGINT |
PK, FK → users.id, NOT NULL |
親ユーザー ID |
role |
VARCHAR(50) |
PK, NOT NULL |
ロール名(ROLE_ADMIN / ROLE_OPERATOR / ROLE_SHIPPER 等) |
DDL¶
CREATE TABLE user_roles (
user_id BIGINT NOT NULL REFERENCES users(id),
role VARCHAR(50) NOT NULL, -- ROLE_ADMIN / ROLE_OPERATOR / ROLE_SHIPPER 等
PRIMARY KEY (user_id, role)
);
設計上の判断¶
1. サロゲートキーと業務キーの併用¶
判断: 全テーブルに BIGSERIAL のサロゲートキー(id)を設け、業務上の識別子(booking_id、voyage_number、unlocode 等)には UNIQUE 制約を付与する。
根拠: 外部キー参照を BIGINT に統一することでインデックス効率が向上する。業務キーはドメインモデルの一部であり、別途管理することで業務ルールの変更に対応しやすい。
2. location テーブルへの参照方式¶
判断: 参考実装では VARCHAR で場所 ID を文字列管理していたが、本設計では location.unlocode を外部キーとして参照する。
根拠: UN/LOCODE は国際標準の 5 文字コードであり、それ自体が意味を持つ自然キーである。文字列参照でも JOIN 効率は許容範囲内であり、可読性が高まる。
3. 金額の表現(INTEGER + VARCHAR(3))¶
判断: 金額を INTEGER(最小通貨単位)と VARCHAR(3)(ISO 4217 通貨コード)の 2 カラムで表現する。NUMERIC / DECIMAL は使用しない。
根拠: 浮動小数点演算による精度誤差を排除するため、円・セントなど最小通貨単位で整数管理する。複数通貨対応のため通貨コードを常に付随させる。これはドメインモデルの MoneyAmount 値オブジェクトに対応する。
4. 列挙値のカラム型(VARCHAR(30))¶
判断: BookingStatus、TransportStatus、HandlingType 等の列挙型カラムは VARCHAR(30) で表現し、PostgreSQL の ENUM 型は使用しない。
根拠: PostgreSQL ENUM 型は値の追加・変更にスキーマ ALTER が必要でマイグレーション時のリスクが高い。VARCHAR ならば Flyway マイグレーションで CHECK 制約を追加・変更するだけで済み、テスト(H2)との互換性も維持できる。
5. コンテキスト間の参照整合性¶
判断: 異なるコンテキスト間(例: handling_activity.booking_id → cargo.booking_id)には DB 外部キー制約を設けない。コンテキスト内の参照(例: leg.cargo_id → cargo.id)には外部キー制約を設ける。
根拠: DDD の境界付けられたコンテキスト間はイベント連携を前提とする疎結合設計であり、DB 外部キーによる強結合は将来のサービス分割を妨げる。整合性はアプリケーション層で保証する。
6. Billing Context の新規設計¶
判断: 参考実装(Jakarta EE)には Billing Context が存在しなかったが、本設計では invoice・invoice_line_item・payment の 3 テーブルを新規追加する。
根拠: ドメインモデル分析で識別した SETTLED(BookingStatus)と Invoice エンティティを実現するために必要。経理担当者のユースケース(精算書生成・支払確認)を支える永続化構造として設計した。
7. 監査カラムの全テーブル付与¶
判断: created_at・updated_at を全テーブルに NOT NULL DEFAULT NOW() で付与する。updated_at の更新は MyBatis マッパー側で CURRENT_TIMESTAMP をセットする。
根拠: 国際貨物輸送は規制上の監査要件が高く、全レコードの作成・更新タイムスタンプが必要。PostgreSQL のトリガーで自動更新する方法もあるが、H2 との互換性を優先してアプリケーション側で制御する。
Flyway マイグレーション方針¶
ファイル命名規則¶
src/main/resources/db/migration/
V1__init.sql # 初期スキーマ全テーブル作成
V2__seed_locations.sql # 初期 UN/LOCODE マスタデータ
V3__add_xxx.sql # 機能追加に伴うスキーマ変更
マイグレーションルール¶
- バージョン番号は連番とし、番号の欠番を作らない
- 既存マイグレーションファイルの編集は禁止(Flyway チェックサム検証)
- ロールバックは
Uプレフィックスのファイル(Undo マイグレーション)で対応する - 本番とテスト(H2)で同一マイグレーションスクリプトを使用するため、PostgreSQL 固有の構文(
BIGSERIALなど)は H2 互換形式で記述する
V1__init.sql の構成イメージ¶
-- Shared Domain
CREATE TABLE location ( ... );
-- Security Context
CREATE TABLE users ( ... );
CREATE TABLE user_roles ( ... );
-- Booking Context
CREATE TABLE shipper ( ... );
CREATE TABLE cargo ( ... ); -- shipper_id FK あり
CREATE TABLE leg ( ... );
-- Routing Context
CREATE TABLE voyage ( ... );
CREATE TABLE carrier_movement ( ... );
-- Tracking Context
CREATE TABLE tracking_activity ( ... );
CREATE TABLE tracking_handling_event ( ... );
CREATE TABLE tracking_exception_event ( ... ); -- escalation_flag / resolution_notes あり
-- Handling Context
CREATE TABLE handling_activity ( ... );
CREATE TABLE customs_declaration ( ... );
-- Billing Context
CREATE TABLE invoice ( ... ); -- tax_rate / tax_amount / booking_id UNIQUE あり
CREATE TABLE invoice_line_item ( ... );
CREATE TABLE payment ( ... );