# 機能設計書: 住所・連絡先管理

## 1. 機能概要

### 1.1 機能の目的
住所・連絡先管理機能は、会社（Company）に関連付けられる住所情報と連絡先情報を管理するための機能である。これにより、取引先との通信や配送業務を効率化する。

### 1.2 機能の範囲
- 住所情報の登録・更新・削除・参照
- 連絡先情報の登録・更新・削除・参照
- 会社単位での住所・連絡先の管理
- 一括削除機能

### 1.3 関連画面
| 画面ID | 画面名 | 関連操作 |
|--------|--------|----------|
| SCR-COMPANY-DETAIL | 会社詳細 | 住所・連絡先の管理 |
| SCR-ADDRESS-LIST | 住所一覧 | 住所の検索・編集 |
| SCR-CONTACT-LIST | 連絡先一覧 | 連絡先の検索・編集 |

## 2. 機能仕様

### 2.1 住所管理（Address）

#### 2.1.1 データ項目
| フィールド名 | 型 | 必須 | 説明 |
|-------------|------|------|------|
| company | ForeignKey | Yes | 会社への参照 |
| title | String | No | 住所のタイトル（例：本社、支店） |
| primary | Boolean | No | プライマリ住所フラグ |
| line1 | String | No | 住所1行目 |
| line2 | String | No | 住所2行目 |
| postal_code | String | No | 郵便番号 |
| postal_city | String | No | 市区町村 |
| province | String | No | 都道府県/州 |
| country | String | No | 国 |
| shipping_notes | Text | No | 配送に関する備考 |
| internal_shipping_notes | Text | No | 内部用配送備考 |
| link | URL | No | 地図等へのリンク |

#### 2.1.2 住所一覧API
- **URL**: `GET /api/company/address/`
- **メソッド**: GET（一覧取得）, POST（新規作成）, DELETE（一括削除）
- **シリアライザ**: `AddressSerializer`

#### 2.1.3 フィルタパラメータ
| パラメータ名 | 型 | 説明 |
|-------------|------|------|
| company | Integer | 会社ID |

#### 2.1.4 ソートフィールド
- title: タイトル

#### 2.1.5 住所詳細API
- **URL**: `GET/PUT/PATCH/DELETE /api/company/address/{pk}/`
- **シリアライザ**: `AddressSerializer`

### 2.2 連絡先管理（Contact）

#### 2.2.1 データ項目
| フィールド名 | 型 | 必須 | 説明 |
|-------------|------|------|------|
| company | ForeignKey | Yes | 会社への参照 |
| name | String | Yes | 担当者名 |
| phone | String | No | 電話番号 |
| email | Email | No | メールアドレス |
| role | String | No | 役職 |

#### 2.2.2 連絡先一覧API
- **URL**: `GET /api/company/contact/`
- **メソッド**: GET（一覧取得）, POST（新規作成）, DELETE（一括削除）
- **シリアライザ**: `ContactSerializer`

#### 2.2.3 フィルタパラメータ
| パラメータ名 | 型 | 説明 |
|-------------|------|------|
| company | Integer | 会社ID |

#### 2.2.4 検索フィールド
- company__name
- name

#### 2.2.5 ソートフィールド
- name: 担当者名

#### 2.2.6 連絡先詳細API
- **URL**: `GET/PUT/PATCH/DELETE /api/company/contact/{pk}/`
- **シリアライザ**: `ContactSerializer`

## 3. データモデル

### 3.1 Addressモデル
```python
class Address(InvenTree.models.InvenTreeModel):
    company = models.ForeignKey(
        Company,
        on_delete=models.CASCADE,
        related_name='addresses',
        ...
    )
    title = models.CharField(max_length=100, blank=True)
    primary = models.BooleanField(default=False)
    line1 = models.CharField(max_length=255, blank=True)
    line2 = models.CharField(max_length=255, blank=True)
    postal_code = models.CharField(max_length=50, blank=True)
    postal_city = models.CharField(max_length=255, blank=True)
    province = models.CharField(max_length=255, blank=True)
    country = models.CharField(max_length=255, blank=True)
    shipping_notes = models.TextField(blank=True)
    internal_shipping_notes = models.TextField(blank=True)
    link = models.URLField(blank=True)
```

### 3.2 Contactモデル
```python
class Contact(InvenTree.models.InvenTreeModel):
    company = models.ForeignKey(
        Company,
        on_delete=models.CASCADE,
        related_name='contacts',
        ...
    )
    name = models.CharField(max_length=100)
    phone = models.CharField(max_length=50, blank=True)
    email = models.EmailField(blank=True)
    role = models.CharField(max_length=100, blank=True)
```

### 3.3 関連エンティティ
```
Company
├── Address (住所: 1:N)
│   ├── title: 住所タイトル
│   ├── primary: プライマリフラグ
│   └── [住所詳細フィールド]
│
└── Contact (連絡先: 1:N)
    ├── name: 担当者名
    ├── phone: 電話番号
    ├── email: メールアドレス
    └── role: 役職
```

## 4. API仕様

### 4.1 住所一覧取得
```
GET /api/company/address/
```

### 4.2 会社でフィルタリング
```
GET /api/company/address/?company=1
```

### 4.3 連絡先一覧取得
```
GET /api/company/contact/
```

### 4.4 連絡先の検索
```
GET /api/company/contact/?search=山田
```

## 5. コードリーディングガイド

### 5.1 推奨読解順序

1. **モデル定義**
   - `src/backend/InvenTree/company/models.py`
     - **Address**: 住所モデル
     - **Contact**: 連絡先モデル

2. **APIエンドポイント（住所）**
   - `src/backend/InvenTree/company/api.py`
     - **108-120行目**: `AddressList` - 住所一覧API
     - **123-127行目**: `AddressDetail` - 住所詳細API

3. **APIエンドポイント（連絡先）**
   - `src/backend/InvenTree/company/api.py`
     - **84-98行目**: `ContactList` - 連絡先一覧API
     - **101-105行目**: `ContactDetail` - 連絡先詳細API

4. **URLルーティング**
   - `src/backend/InvenTree/company/api.py`
     - **535-554行目**: `company_api_urls` - 住所・連絡先のURLルーティング

### 5.2 プログラム呼び出し階層図

```
[API Request: GET /api/company/address/]
    │
    ▼
AddressList.get()
    │
    ├── queryset = Address.objects.all() [111行目]
    │
    ├── filter_backends = SEARCH_ORDER_FILTER [114行目]
    │   └── フィルタ適用（company）
    │
    └── AddressSerializer.to_representation()
        └── レスポンス生成
```

```
[API Request: GET /api/company/contact/]
    │
    ▼
ContactList.get()
    │
    ├── queryset = Contact.objects.all() [87行目]
    │
    ├── filter_backends = SEARCH_ORDER_FILTER [90行目]
    │   └── フィルタ適用（company）
    │   └── 検索適用（company__name, name）
    │
    └── ContactSerializer.to_representation()
        └── レスポンス生成
```

### 5.3 データフロー図

```
[住所登録]
    │
    ▼
┌─────────────────────────────────────┐
│ AddressSerializer                   │
│ ・company: 会社ID                  │
│ ・title: 住所タイトル              │
│ ・line1, line2: 住所               │
│ ・postal_code, postal_city等       │
└─────────────────────────────────────┘
    │
    ├── バリデーション
    │   └── companyの存在確認
    │
    ▼
┌─────────────────────────────────────┐
│ Address Model                       │
│ ・データベースへの永続化           │
└─────────────────────────────────────┘
    │
    ▼
┌─────────────────────────────────────┐
│ Company.addresses（逆参照）         │
│ ・会社から住所一覧を取得可能       │
└─────────────────────────────────────┘
```

### 5.4 関連ファイル一覧

| ファイルパス | 種別 | 役割 |
|-------------|------|------|
| `src/backend/InvenTree/company/models.py` | Model | Address, Contactモデル定義 |
| `src/backend/InvenTree/company/serializers.py` | Serializer | AddressSerializer, ContactSerializer定義 |
| `src/backend/InvenTree/company/api.py` | API | RESTful APIエンドポイント定義 |

## 6. 例外処理

### 6.1 バリデーションエラー
| エラー条件 | エラーメッセージ |
|-----------|-----------------|
| companyが未指定 | "This field is required" |
| companyが存在しない | "Invalid pk - object does not exist" |
| nameが未指定（Contact） | "This field is required" |
| 無効なメールアドレス | "Enter a valid email address" |

## 7. セキュリティ考慮事項

- APIアクセスには認証が必要
- 住所・連絡先の変更は適切な権限を持つユーザーのみ可能
- データエクスポート機能は権限制御される
