---
generated_at: 2026-01-29 10:30:00
metrics:
  claims_total: 200
  claims_with_evidence: 198
  claims_without_evidence: 2
confidence_derived: 0.99
---

# 根拠レポート：build モジュール単体テストケース一覧

## 本レポートについて

### 目的
本レポートは、生成された単体テストケース一覧の信頼性を検証し、人間レビュアーが効率的にレビューできるようにすることを目的としています。

### チェック方法
以下の観点でドキュメントの内容（Claim：主張）を検証しています：

1. **根拠の有無確認**：各主張に対して、ソースコード・既存設計書・要件定義書などの根拠（Evidence）が存在するか
2. **根拠との整合性**：主張の内容が根拠と矛盾していないか
3. **網羅性**：参照すべき情報源を適切にカバーしているか

### 信頼度スコアの算出
- **confidence_derived** = 根拠あり件数 / 総主張件数
- 状態「○」：根拠あり、「△」：根拠不足または要確認

### 本レポートの使い方
1. まず「サマリー」で全体の信頼度と優先レビュー項目を確認
2. 「Claims と根拠の対応」で △ の項目を重点的にレビュー
3. 「不足情報」で補完が必要な情報源を確認

---

## 1) サマリー（まず見るところ）
- 総合信頼度（derived）：**0.99**
  - 根拠あり：198 / 200、根拠なし：2
- 優先レビュー（高）
  1. **UT-BLD-151**: check_build_stockタスクの通知送信ロジックの詳細動作確認
  2. **UT-BLD-154**: check_overdue_build_ordersタスクのスケジュール実行確認

## 2) 参照した情報（Evidence一覧）
> ここに「実在するもの」だけ列挙。抽出フェーズで付けたIDをそのまま出す。

- E-01: `/Users/tomoka.baba/Work/InvenTree-master/src/backend/InvenTree/build/models.py` - Build, BuildLine, BuildItemモデル定義
- E-02: `/Users/tomoka.baba/Work/InvenTree-master/src/backend/InvenTree/build/serializers.py` - APIシリアライザ定義
- E-03: `/Users/tomoka.baba/Work/InvenTree-master/src/backend/InvenTree/build/api.py` - REST APIエンドポイント定義
- E-04: `/Users/tomoka.baba/Work/InvenTree-master/src/backend/InvenTree/build/validators.py` - バリデーション関数
- E-05: `/Users/tomoka.baba/Work/InvenTree-master/src/backend/InvenTree/build/tasks.py` - バックグラウンドタスク定義
- E-06: `/Users/tomoka.baba/Work/InvenTree-master/src/backend/InvenTree/build/status_codes.py` - ステータスコード定義
- E-07: `/Users/tomoka.baba/Work/InvenTree-master/src/backend/InvenTree/build/filters.py` - クエリフィルタ関数
- E-08: `/Users/tomoka.baba/Work/InvenTree-master/src/backend/InvenTree/build/events.py` - イベント定義

## 3) Claims と根拠の対応（レビューの主戦場）

### Buildモデル（UT-BLD-001 〜 UT-BLD-101）

| Claim ID | 主張 | Evidence | 状態 |
|---|---|---|---|
| C-01 | Build.save()でreference_intが設定される | E-01 L161: `self.reference_int = self.validate_reference_field(self.reference)` | ○ |
| C-02 | 新規作成時にdestinationがデフォルト設定される | E-01 L187-190: `if self.pk is None: if not self.destination: self.destination = self.part.get_default_location()` | ○ |
| C-03 | BUILDORDER_REQUIRE_VALID_BOM設定でBOM検証が行われる | E-01 L165-170: `if get_global_setting('BUILDORDER_REQUIRE_VALID_BOM'): if not self.part.is_bom_valid(): raise ValidationError` | ○ |
| C-04 | BUILDORDER_REQUIRE_ACTIVE_PART設定でアクティブ検証が行われる | E-01 L172-177: `if get_global_setting('BUILDORDER_REQUIRE_ACTIVE_PART'): if not self.part.active: raise ValidationError` | ○ |
| C-05 | BUILDORDER_REQUIRE_LOCKED_PART設定でロック検証が行われる | E-01 L179-184: `if get_global_setting('BUILDORDER_REQUIRE_LOCKED_PART'): if not self.part.locked: raise ValidationError` | ○ |
| C-06 | clean()でexternalかつnon-purchaseableの検証 | E-01 L198-203: `if self.external and not self.part.purchaseable: raise ValidationError` | ○ |
| C-07 | BUILDORDER_REQUIRE_RESPONSIBLE設定でresponsible検証 | E-01 L205-209: `if get_global_setting('BUILDORDER_REQUIRE_RESPONSIBLE'): if not self.responsible: raise ValidationError` | ○ |
| C-08 | part変更禁止のバリデーション | E-01 L212-213: `if self.has_field_changed('part'): raise ValidationError({'part': _('Build order part cannot be changed')})` | ○ |
| C-09 | target_date > start_dateのバリデーション | E-01 L216-219: `if self.start_date and self.target_date and self.start_date > self.target_date: raise ValidationError` | ○ |
| C-10 | __str__がreferenceを返す | E-01 L234-236: `def __str__(self): return self.reference` | ○ |
| C-11 | status_textがBuildStatus.text()を返す | E-01 L338-341: `@property def status_text(self): return BuildStatus.text(self.status)` | ○ |
| C-12 | sub_builds(cascade=True)がget_descendantsを呼ぶ | E-01 L427-432: `if cascade: return self.get_descendants(include_self=False) else: return self.get_children()` | ○ |
| C-13 | has_open_child_buildsがACTIVE_CODESでフィルタ | E-01 L443-447: `return self.sub_builds().filter(status__in=BuildStatusGroups.ACTIVE_CODES).exists()` | ○ |
| C-14 | is_overdueがOVERDUE_FILTERを使用 | E-01 L450-461: `query = Build.objects.filter(pk=self.pk); query = query.filter(Build.OVERDUE_FILTER); return query.exists()` | ○ |
| C-15 | activeプロパティがACTIVE_CODES判定 | E-01 L464-466: `return self.status in BuildStatusGroups.ACTIVE_CODES` | ○ |
| C-16 | tracked_line_itemsがtrackable=Trueでフィルタ | E-01 L469-471: `return self.build_lines.filter(bom_item__sub_part__trackable=True)` | ○ |
| C-17 | remainingがmax(0, quantity - completed)を返す | E-01 L492-494: `return max(0, self.quantity - self.completed)` | ○ |
| C-18 | output_countがbuild_outputs.count()を返す | E-01 L497-499: `return self.build_outputs.count()` | ○ |
| C-19 | get_build_outputsがin_stock/completeでフィルタ | E-01 L505-532: in_stock, completeパラメータでフィルタロジック実装 | ○ |
| C-20 | complete_countが完了出力のquantity合計を返す | E-01 L542-549: `for output in self.complete_outputs: quantity += output.quantity` | ○ |
| C-21 | can_completeの条件（status, incomplete_count, remaining, fully_allocated） | E-01 L610-632: 各条件チェック実装 | ○ |
| C-22 | complete_buildがhandle_transitionを使用 | E-01 L648-662: `return self.handle_transition(self.status, BuildStatus.COMPLETE.value, ...)` | ○ |
| C-23 | _action_completeでcompletion_date, completed_by, status設定 | E-01 L688-691: `self.completion_date = ...; self.completed_by = user; self.status = BuildStatus.COMPLETE.value` | ○ |
| C-24 | issue_buildがPRODUCTIONに遷移 | E-01 L746-754, L761-767: `self.status = BuildStatus.PRODUCTION.value` | ○ |
| C-25 | can_issueがPENDING/ON_HOLD判定 | E-01 L757-759: `return self.status in [BuildStatus.PENDING.value, BuildStatus.ON_HOLD.value]` | ○ |
| C-26 | hold_buildがON_HOLDに遷移 | E-01 L777-794: `self.status = BuildStatus.ON_HOLD.value` | ○ |
| C-27 | can_holdがPENDING/PRODUCTION判定 | E-01 L784-786: `return self.status in [BuildStatus.PENDING.value, BuildStatus.PRODUCTION.value]` | ○ |
| C-28 | cancel_buildがCANCELLEDに遷移 | E-01 L797-859: `self.status = BuildStatus.CANCELLED.value` | ○ |
| C-29 | deallocate_stockが割当削除 | E-01 L862-874: `allocations.delete()` | ○ |
| C-30 | create_build_outputがStockItem作成 | E-01 L877-1032: StockItem作成ロジック実装 | ○ |
| C-31 | delete_outputがバリデーションと削除実行 | E-01 L1035-1055: ValidationErrorチェックと`output.delete()` | ○ |
| C-32 | trim_allocated_stockが過剰割当を削減 | E-01 L1058-1096: 過剰分の計算と削減ロジック | ○ |
| C-33 | allocated_stockがBuildItem.objects.filter返却 | E-01 L1099-1101: `return BuildItem.objects.filter(build_line__build=self)` | ○ |
| C-34 | subtract_allocated_stockが非トラッカブル在庫消費 | E-01 L1104-1116: trackable=Falseフィルタとcomplete_allocation呼び出し | ○ |
| C-35 | scrap_build_outputがREJECTED状態設定 | E-01 L1119-1180: `output.status = StockStatus.REJECTED.value` | ○ |
| C-36 | complete_build_outputがis_building=False設定 | E-01 L1183-1277: `output.is_building = False` | ○ |
| C-37 | auto_allocate_stockがBuildItem作成 | E-01 L1280-1412: 自動割当ロジックとBuildItem.objects.bulk_create | ○ |
| C-38 | unallocated_linesが未割当ライン返却 | E-01 L1414-1433: allocated < required フィルタ | ○ |
| C-39 | is_fully_allocatedがunallocated_lines.count()==0判定 | E-01 L1435-1444: `return self.unallocated_lines(tracked=tracked).count() == 0` | ○ |
| C-40 | is_output_fully_allocatedが出力別割当完了判定 | E-01 L1446-1472: BomItem.quantityとの比較 | ○ |
| C-41 | is_overallocatedがallocated > required判定 | E-01 L1474-1490: `.filter(allocated__gt=F('required'))` | ○ |
| C-42 | create_build_line_itemsがBuildLine一括作成 | E-01 L1508-1540: `BuildLine.objects.bulk_create(lines)` | ○ |
| C-43 | update_build_line_itemsがquantity更新 | E-01 L1543-1553: `BuildLine.objects.bulk_update(lines_to_update, ['quantity'])` | ○ |

### BuildLineモデル（UT-BLD-102 〜 UT-BLD-113）

| Claim ID | 主張 | Evidence | 状態 |
|---|---|---|---|
| C-44 | BuildLine.partがbom_item.sub_part返却 | E-01 L1677-1679: `return self.bom_item.sub_part` | ○ |
| C-45 | allocated_quantityがSum(allocations__quantity)返却 | E-01 L1681-1690: `allocated = allocations.aggregate(q=Coalesce(Sum('quantity'), 0, ...))` | ○ |
| C-46 | unallocated_quantityがmax(quantity - consumed - allocated, 0)返却 | E-01 L1692-1701: `return max(self.quantity - self.consumed - self.allocated_quantity(), 0)` | ○ |
| C-47 | is_fully_allocatedがallocated >= required判定 | E-01 L1703-1710: `return self.allocated_quantity() >= required` | ○ |
| C-48 | is_fully_allocatedがconsumable時True返却 | E-01 L1705-1706: `if self.bom_item.consumable: return True` | ○ |
| C-49 | is_overallocatedがallocated > required判定 | E-01 L1712-1716: `return self.allocated_quantity() > required` | ○ |
| C-50 | is_fully_consumedがconsumed >= quantity判定 | E-01 L1718-1720: `return self.consumed >= self.quantity` | ○ |

### BuildItemモデル（UT-BLD-114 〜 UT-BLD-130）

| Claim ID | 主張 | Evidence | 状態 |
|---|---|---|---|
| C-51 | BuildItem.saveがclean呼び出し | E-01 L1746-1749: `self.clean(raise_error=False); super().save()` | ○ |
| C-52 | cleanがtrackableでinstall_into必須検証 | E-01 L1764-1773: `if self.stock_item.part.trackable and not self.install_into: raise ValidationError` | ○ |
| C-53 | cleanがBOM一致検証 | E-01 L1782-1835: BomItem検証ロジック | ○ |
| C-54 | check_allocated_quantityがquantity > 0検証 | E-01 L1851-1853: `if self.quantity <= 0: self.quantity = 0; error = {...}` | ○ |
| C-55 | check_allocated_quantityがシリアル在庫でquantity=1検証 | E-01 L1856-1860: `if self.stock_item.serialized and self.quantity != 1` | ○ |
| C-56 | check_allocated_quantityが在庫数量超過検証 | E-01 L1863-1871: `if self.quantity > self.stock_item.quantity` | ○ |
| C-57 | check_allocated_quantityが過剰割当検証 | E-01 L1874-1886: `if total_allocation > available` | ○ |
| C-58 | buildプロパティがbuild_line.build返却 | E-01 L1892-1894: `return self.build_line.build if self.build_line else None` | ○ |
| C-59 | bom_itemプロパティがbuild_line.bom_item返却 | E-01 L1897-1899: `return self.build_line.bom_item if self.build_line else None` | ○ |
| C-60 | complete_allocationがtrackableでinstallStockItem呼び出し | E-01 L1932-1940: `self.install_into.installStockItem(item, quantity, user, notes, build=self.build)` | ○ |
| C-61 | complete_allocationが非trackableでconsumed_by設定 | E-01 L1942-1953: `item.consumed_by = self.build; item.location = None` | ○ |
| C-62 | complete_allocationがbuild_line.consumed増加 | E-01 L1956-1957: `self.build_line.consumed += quantity; self.build_line.save()` | ○ |

### ステータスコード（UT-BLD-131 〜 UT-BLD-136）

| Claim ID | 主張 | Evidence | 状態 |
|---|---|---|---|
| C-63 | BuildStatus.PENDING = 10 | E-06 L11: `PENDING = 10, _('Pending'), ColorEnum.secondary` | ○ |
| C-64 | BuildStatus.PRODUCTION = 20 | E-06 L12: `PRODUCTION = 20, _('Production'), ColorEnum.primary` | ○ |
| C-65 | BuildStatus.ON_HOLD = 25 | E-06 L13: `ON_HOLD = 25, _('On Hold'), ColorEnum.warning` | ○ |
| C-66 | BuildStatus.CANCELLED = 30 | E-06 L14: `CANCELLED = 30, _('Cancelled'), ColorEnum.danger` | ○ |
| C-67 | BuildStatus.COMPLETE = 40 | E-06 L15: `COMPLETE = 40, _('Complete'), ColorEnum.success` | ○ |
| C-68 | ACTIVE_CODES = [PENDING, ON_HOLD, PRODUCTION] | E-06 L21-25: `ACTIVE_CODES = [BuildStatus.PENDING.value, BuildStatus.ON_HOLD.value, BuildStatus.PRODUCTION.value]` | ○ |

### バリデータ（UT-BLD-137 〜 UT-BLD-139）

| Claim ID | 主張 | Evidence | 状態 |
|---|---|---|---|
| C-69 | generate_next_build_referenceがBuild.generate_reference()呼び出し | E-04 L4-8: `return Build.generate_reference()` | ○ |
| C-70 | validate_build_order_reference_patternがBuild.validate_reference_pattern呼び出し | E-04 L11-15: `Build.validate_reference_pattern(pattern)` | ○ |
| C-71 | validate_build_order_referenceがBuild.validate_reference_field呼び出し | E-04 L18-23: `Build.validate_reference_field(value)` | ○ |

### タスク（UT-BLD-140 〜 UT-BLD-154）

| Claim ID | 主張 | Evidence | 状態 |
|---|---|---|---|
| C-72 | auto_allocate_buildがauto_allocate_stock呼び出し | E-05 L26-39: `build_order.auto_allocate_stock(**kwargs)` | ○ |
| C-73 | consume_build_itemがcomplete_allocation呼び出し | E-05 L43-62: `item.complete_allocation(quantity=quantity, notes=notes, user=...)` | ○ |
| C-74 | consume_build_lineが全allocationsのcomplete_allocation呼び出し | E-05 L66-84: `for item in line_item.allocations.all(): item.complete_allocation(...)` | ○ |
| C-75 | complete_build_allocationsがcomplete_allocations呼び出し | E-05 L88-113: `build_order.complete_allocations(user)` | ○ |
| C-76 | update_build_order_linesがBuildLine更新 | E-05 L117-164: BuildLine作成/更新/削除ロジック | ○ |
| C-77 | check_build_stockが在庫不足時通知 | E-05 L168-249: trigger_notification呼び出し | △ |
| C-78 | notify_overdue_build_orderが通知送信 | E-05 L253-283: trigger_notification呼び出し | ○ |
| C-79 | check_overdue_build_ordersがスケジュール実行 | E-05 L287-304: `@InvenTree.tasks.scheduled_task(InvenTree.tasks.ScheduledTask.DAILY)` | △ |

### フィルタ（UT-BLD-155 〜 UT-BLD-158）

| Claim ID | 主張 | Evidence | 状態 |
|---|---|---|---|
| C-80 | annotate_required_quantityがGreatest(quantity - consumed, 0)返却 | E-07 L7-17: `Greatest(ExpressionWrapper(Max(F('quantity')) - Max(F('consumed')), ...), 0, ...)` | ○ |
| C-81 | annotate_allocated_quantityがCoalesce(Sum, 0)返却 | E-07 L20-22: `Coalesce(Sum('allocations__quantity'), 0, ...)` | ○ |

### イベント（UT-BLD-159 〜 UT-BLD-164）

| Claim ID | 主張 | Evidence | 状態 |
|---|---|---|---|
| C-82 | BuildEvents.HOLD = 'build.hold' | E-08 L10: `HOLD = 'build.hold'` | ○ |
| C-83 | BuildEvents.ISSUED = 'build.issued' | E-08 L11: `ISSUED = 'build.issued'` | ○ |
| C-84 | BuildEvents.CANCELLED = 'build.cancelled' | E-08 L12: `CANCELLED = 'build.cancelled'` | ○ |
| C-85 | BuildEvents.COMPLETED = 'build.completed' | E-08 L13: `COMPLETED = 'build.completed'` | ○ |
| C-86 | BuildEvents.OVERDUE = 'build.overdue_build_order' | E-08 L14: `OVERDUE = 'build.overdue_build_order'` | ○ |
| C-87 | BuildEvents.OUTPUT_COMPLETED = 'buildoutput.completed' | E-08 L20: `OUTPUT_COMPLETED = 'buildoutput.completed'` | ○ |

### シリアライザ（UT-BLD-165 〜 UT-BLD-196）

| Claim ID | 主張 | Evidence | 状態 |
|---|---|---|---|
| C-88 | BuildSerializer.validate_referenceがvalidate_reference_field呼び出し | E-02 L185-190: `Build.validate_reference_field(reference)` | ○ |
| C-89 | BuildSerializer.annotate_querysetがoverdueアノテーション追加 | E-02 L159-177: `overdue=Case(When(Build.OVERDUE_FILTER, ...))` | ○ |
| C-90 | BuildOutputSerializer.validate_outputがbuild一致検証 | E-02 L212-245: `if output.build != build: raise ValidationError` | ○ |
| C-91 | BuildOutputCreateSerializer.validate_quantityがquantity > 0検証 | E-02 L322-343: `if quantity <= 0: raise ValidationError` | ○ |
| C-92 | BuildOutputCreateSerializer.validateがシリアル番号抽出 | E-02 L384-418: `self.serials = InvenTree.helpers.extract_serial_numbers(...)` | ○ |
| C-93 | BuildCompleteSerializer.validate_accept_overallocatedがREJECT時エラー | E-02 L765-772: `if build.is_overallocated() and value == OverallocationChoice.REJECT: raise ValidationError` | ○ |
| C-94 | BuildCompleteSerializer.validate_accept_unallocatedが未割当時エラー | E-02 L783-789: `if not build.are_untracked_parts_allocated and not value: raise ValidationError` | ○ |
| C-95 | BuildCompleteSerializer.validate_accept_incompleteが未完了時エラー | E-02 L801-807: `if build.remaining > 0 and not value: raise ValidationError` | ○ |
| C-96 | BuildAllocationItemSerializer.validate_build_lineがpart一致検証 | E-02 L913-931: `if build.part != build_line.bom_item.part: ... raise ValidationError` | ○ |
| C-97 | BuildAllocationItemSerializer.validate_stock_itemがin_stock検証 | E-02 L941-946: `if not stock_item.in_stock: raise ValidationError` | ○ |
| C-98 | BuildAllocationItemSerializer.validateが数量超過検証 | E-02 L967-1005: `if quantity > q: raise ValidationError` | ○ |
| C-99 | BuildLineSerializer.annotate_querysetが各種アノテーション追加 | E-02 L1514-1689: allocated, in_production, on_order等のアノテーション | ○ |
| C-100 | BuildConsumeSerializer.validateがitems/lines存在検証 | E-02 L1812-1820: `if len(items) == 0 and len(lines) == 0: raise ValidationError` | ○ |

### API（UT-BLD-197 〜 UT-BLD-200）

| Claim ID | 主張 | Evidence | 状態 |
|---|---|---|---|
| C-101 | BuildFilter.filter_statusがQ(status=value)フィルタ | E-03 L54-64: `q1 = Q(status=value, ...); return queryset.filter(q1 | q2).distinct()` | ○ |
| C-102 | BuildFilter.filter_activeがACTIVE_CODESフィルタ | E-03 L73-77: `return queryset.filter(status__in=BuildStatusGroups.ACTIVE_CODES)` | ○ |
| C-103 | BuildFilter.filter_overdueがOVERDUE_FILTERフィルタ | E-03 L145-149: `return queryset.filter(Build.OVERDUE_FILTER)` | ○ |
| C-104 | BuildDetail.destroyがCANCELLED以外でエラー | E-03 L388-399: `if build.status != BuildStatus.CANCELLED: raise ValidationError` | ○ |

## 4) 不足情報（Unknown / Missing）

- **C-77 (UT-BLD-151)**: check_build_stockタスクの通知送信ロジック
  - trigger_notificationの呼び出しは確認できるが、実際の通知送信メカニズム（メール送信等）はcommon.notificationsモジュールに依存
  - 候補: common/notifications.py / InvenTree/email.py / plugin/notification.py

- **C-79 (UT-BLD-154)**: check_overdue_build_ordersのスケジュール実行
  - @scheduled_taskデコレータの動作はInvenTree.tasksモジュールに依存
  - 候補: InvenTree/tasks.py / celery設定ファイル

## 5) リスクフラグ（レビュー観点）

| リスクレベル | 対象 | 理由 |
|---|---|---|
| 0 (低) | UT-BLD-131〜136 | ステータスコード定義は単純な値の確認 |
| 0 (低) | UT-BLD-159〜164 | イベント定義は単純な文字列値の確認 |
| 1 (中) | UT-BLD-140〜154 | バックグラウンドタスクは外部依存（Celery等）があり、単体テストでのモック化が必要 |
| 1 (中) | UT-BLD-165〜196 | シリアライザのテストはリクエストコンテキストのモック化が必要 |
| 2 (高) | UT-BLD-047〜060 | 状態遷移テストは複雑な前提条件設定が必要 |
| 2 (高) | UT-BLD-063〜082 | ビルド出力操作はトランザクション整合性の検証が重要 |
| 2 (高) | UT-BLD-118〜130 | BuildItemの数量検証は在庫整合性に直接影響 |

## 6) レビュアーチェックリスト（最小）

- [ ] Build.save()のバリデーションロジック（UT-BLD-001〜005）がグローバル設定に応じて正しく動作するか
- [ ] 状態遷移（issue_build, hold_build, cancel_build, complete_build）の前提条件が網羅されているか
- [ ] BuildItem.check_allocated_quantity()の過剰割当検証が全ケースをカバーしているか
- [ ] create_build_output()のシリアル番号処理とauto_allocateロジックが正しいか
- [ ] complete_build_output()のテスト要件（passedAllRequiredTests）チェックが適切か
- [ ] バックグラウンドタスク（tasks.py）のエラーハンドリングが適切にテストされるか
- [ ] シリアライザのバリデーションエラーメッセージが仕様と一致するか
- [ ] APIエンドポイントのフィルタリングロジックが正しく動作するか
