Skip to content

エッジケース仕様

自動保存中のネットワークタイムアウト復帰

自動保存トリガー保存成功保存失敗バックオフ経過リトライ成功リトライ失敗(3回未満)3回リトライ後も失敗ネットワーク復帰(navigator.onLine)同期成功バージョン競合ユーザー選択IdleSavingRetryWaitRetryingOfflineModeSyncingConflictDialog
自動保存トリガー保存成功保存失敗バックオフ経過リトライ成功リトライ失敗(3回未満)3回リトライ後も失敗ネットワーク復帰(navigator.onLine)同期成功バージョン競合ユーザー選択IdleSavingRetryWaitRetryingOfflineModeSyncingConflictDialog

動作仕様:

  1. 保存失敗時、UI に「保存失敗」インジケーターを表示
  2. Exponential Backoff + Jitter で最大3回自動リトライ(1秒 → 2秒 → 4秒)
  3. リトライ中は「再保存中...」インジケーターを表示
  4. 3回リトライ後も失敗した場合、入力データを IndexedDB にローカル保存し「オフラインモード」に移行
  5. ネットワーク復帰時(navigator.onLine イベント)に自動同期を実行
  6. 同期時にサーバー側のバージョンと競合した場合、ユーザーに選択を促すダイアログを表示

マルウェアスキャンタイムアウト時の UX

→ 関連: SR-006 マルウェア対策PE-001 パフォーマンス

フェーズタイムアウト動作
アップロード中30秒プログレスバー表示。タイムアウト時は「アップロードに時間がかかっています。しばらくお待ちください」
スキャン中10秒/件「ウイルススキャン中...」ステータス表示
スキャンタイムアウト10秒超過ファイルを「スキャン保留中」状態で保持。ユーザーには「スキャン結果の確認に時間がかかっています。完了次第通知します」と表示
スキャン完了(安全)-「スキャン完了」に更新。申告フローを続行可能
スキャン完了(検出)-ファイルを拒否し「ウイルスが検出されたため、このファイルはアップロードできません」と表示。TSHK-BIZ-006 を返却

税計算サービス障害中の確認画面の振る舞い

税計算サービスが障害中の場合、確認画面は以下のように振る舞う:

  1. 計算結果セクション: 「税額計算が一時的に利用できません」と表示し、前回の計算結果がある場合は「前回の計算結果({日時}時点)」として参考表示
  2. 入力データ確認: 入力データの確認・編集は引き続き可能
  3. 最終確認ボタン: 無効化し、「税額計算が完了するまで最終確認はできません」と説明表示
  4. 自動リカバリ: バックグラウンドで定期的に(30秒間隔)計算サービスの復旧を確認し、復旧後は自動で再計算を実行

一括操作での部分失敗ハンドリング

一括操作(一括承認、一括帳票生成、データインポート等)において一部が失敗した場合の仕様:

レスポンスフォーマット:

json
{
  "type": "https://tashika.example/errors/business/partial-failure",
  "title": "Partial Operation Failure",
  "status": 422,
  "detail": "100件中3件の処理に失敗しました。",
  "instance": "/api/v1/2025/declarations/bulk-approve",
  "traceId": "d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9",
  "errorCode": "TSHK-BIZ-005",
  "summary": {
    "total": 100,
    "succeeded": 97,
    "failed": 3
  },
  "failures": [
    {
      "resourceId": "decl-001",
      "errorCode": "TSHK-BIZ-001",
      "detail": "申告が既に確定済みです"
    },
    {
      "resourceId": "decl-042",
      "errorCode": "TSHK-BIZ-002",
      "detail": "承認の前提条件未達です"
    },
    {
      "resourceId": "decl-099",
      "errorCode": "TSHK-SYS-002",
      "detail": "処理中にタイムアウトが発生しました"
    }
  ]
}

UI 動作:

  1. 一括操作の実行結果をサマリとして表示(「97件成功 / 3件失敗」)
  2. 失敗した項目の一覧をテーブルで表示し、個別に原因と対処方法を案内
  3. 「失敗した項目のみ再実行」ボタンを提供
  4. 成功した項目は確定済みとし、ロールバックしない(部分コミット方式)

セッション期限切れ中の自動保存

→ 関連: SR-005 セッション管理

自動保存のリクエストが 401(トークン期限切れ)で失敗した場合のフロー:

alt [Refresh Token 有効 (7日以内)][Refresh Token 失効]自動保存リクエスト401 UnauthorizedトークンリフレッシュRefresh Token で再認証新 Access Token新セッション自動保存リトライ200 OKデータを IndexedDB に退避再ログイン画面へ遷移再ログイン認証成功退避データを取得バージョン競合チェック付き同期同期結果「未保存データがあります」表示FrontendBFF ServerIdP / 認証基盤IndexedDB
alt [Refresh Token 有効 (7日以内)][Refresh Token 失効]自動保存リクエスト401 UnauthorizedトークンリフレッシュRefresh Token で再認証新 Access Token新セッション自動保存リトライ200 OKデータを IndexedDB に退避再ログイン画面へ遷移再ログイン認証成功退避データを取得バージョン競合チェック付き同期同期結果「未保存データがあります」表示FrontendBFF ServerIdP / 認証基盤IndexedDB

ポイント:

  • リフレッシュトークンが有効な間(7日以内)は自動的にアクセストークンを更新してリトライ
  • リフレッシュトークンも失効している場合は IndexedDB にデータを退避
  • 再ログイン後、IndexedDB のデータをサーバーと同期(バージョン競合チェック付き)

同時編集の競合(楽観的ロック)

→ 関連: AV-002 データ整合性

従業員と管理者が同一の申告データを同時に編集した場合の競合解決:

GET /declarations/123データ + ETag: v1GET /declarations/123データ + ETag: v1PATCH /declarations/123If-Match: v1UPDATE ... WHERE version = 1更新成功 (version → 2)200 OK + ETag: v2PATCH /declarations/123If-Match: v1UPDATE ... WHERE version = 10 rows affected (競合)409 Conflict + TSHK-BIZ-004差分ハイライト確認GET /declarations/123 (最新取得)最新データ + ETag: v2PATCH /declarations/123If-Match: v2 (変更再適用)200 OK競合解決 UI 表示従業員管理者Application APIPostgreSQL
GET /declarations/123データ + ETag: v1GET /declarations/123データ + ETag: v1PATCH /declarations/123If-Match: v1UPDATE ... WHERE version = 1更新成功 (version → 2)200 OK + ETag: v2PATCH /declarations/123If-Match: v1UPDATE ... WHERE version = 10 rows affected (競合)409 Conflict + TSHK-BIZ-004差分ハイライト確認GET /declarations/123 (最新取得)最新データ + ETag: v2PATCH /declarations/123If-Match: v2 (変更再適用)200 OK競合解決 UI 表示従業員管理者Application APIPostgreSQL

競合検出方式:

  • ETag / If-Match ヘッダーによるバージョンベースの楽観的排他制御
  • サーバー側は Declaration エンティティの Version カラム(行バージョン)で競合を検出
  • 競合時は 409 Conflict + TSHK-BIZ-004 を返却

競合解決 UI:

  • 競合発生時、最新のサーバー側データと自分の変更内容の差分をハイライト表示
  • ユーザーに「最新データを取得して自分の変更を再適用」するか「自分の変更を破棄」するかを選択させる