ken_nogi/Pleasanter/健康診断管理/docs/n8n/design-fixed-menu.md

107 KiB
Raw Blame History

健康診断Bot 対話メニュー機能 設計メモ2026-09-06

508971社員別健康診断管理× LINEWORKS Bot連携で、3機能健診日程受診・再検査報告 診断書提出)を追加する設計。既存のhealthcheck-lineworks-survey-n8n-design.md HC-SUB/HC-WA/HC-WPの基本構成を前提に、その上に対話メニュー方式を追加する。

ストレスチェックは対象範囲外2026-09-07確定: 508971のCheckBSC受診済Class056SC判定は項目として残すが、運用誰がいつどう更新するかが未確定のため、 今回のBot対話メニュー機能の対象から除外する。以下の本文中に4択・4機能としてストレス チェックが含まれる記述が残っている場合は履歴であり、実装は3択・3機能で進める。

自分手配(社員が病院を自分で予約するケース)は仕様未確定・今回の対象範囲外 2026-09-07追加: 検査機関の選択肢(Class003、SiteId 511924「受診病院一覧」へ 「自分手配」を追加済みResultId 513480。ただし詳細仕様日程の入力方法・Bot対話フロー等は 未確定のため、Class003=「自分手配」のレコードは①日程通知Status 250→300、候補日Date001を 前提とした案内の対象から外す。自分手配のケースは今回の3カテゴリ健診日程受診・再検査報告 診断書提出)とは別に、専用のトークフローを別途用意する想定(設計は今後確定)。

最終確定方式(本ファイル末尾「最終設計確定」節参照): 固定メニューpersistentmenu、 「健康診断について」1ボタンのみで常時アクセス可能な入口を作り、タップ後はbutton_template メッセージ内埋め込みボタンで4択を提示するハイブリッド方式。当初は固定メニュー4ボタン 単独で設計していたが、PC版での表示方式三本線展開が必要が期待と異なっていたため転換した 経緯が「背景・設計転換」以下に残っている(読み進める場合は時系列の検討過程として参照)。

情報源の役割分担確定・2026-09-06: 健康診断管理/プリザンターテーブル設計書_健康診断.xlsx 「メッセージ設定」シートは管理者が見る・編集するメッセージ本文の一覧(一次情報源)、 本ファイルdesign-fixed-menu.mdは技術的な実装設計トリガー条件・データ構造・ n8n実装方針等を扱う。メッセージ本文を変更する場合はExcelを直接編集し、本ファイルは それを参照する形にする。

ExcelとPleasanter Process定義DescriptionBot案内文の実体の同期運用 → 確定 2026-09-07: 開発時はClaudeがExcel「メッセージ設定」シートの内容をPleasanterの 各Process定義のDescription欄へ転記する。運用開始後、メッセージ文言を変更する場合は 管理者がExcelとPleasanter両方を直接編集する自動同期の仕組みは作らない

健康診断管理システム全体のフェーズ構成確定・2026-09-06:

  • フェーズ1: LINEWORKSアンケートフォームの回答結果を508971社員別健康診断管理へ反映 (未着手。本ファイルの設計完了後に設計・開発着手予定)
  • フェーズ2本ファイルが対象: LINEWORKS Botを使った対話形式のワークフロー 固定メニュー・button_template・Process連携。現在設計中
  • フェーズ3: 産業医が診断データを確認し就業判定可否を入力するための、Pleasanter外部UI。 データはPleasanterに置いたまま連携するまだ設計に入らない

フェーズ2はレコードが既に508971に存在する前提Status=100以降で設計している。 フェーズ1未着手の間の検証は、既存レコードを壊さない捨てレコードを手動作成して行う 7章「導入・検証方針」参照

フェーズ3との整合性 → 確定2026-09-06: フェーズ2の「就業判定_可/不可」 「再検査通知」は管理者/産業医がClass052(健診結果)・Class053(就業判定)を見て 手動でProcessボタンを押す設計だが、将来フェーズ3産業医UIが稼働してもこの手動判断 フロー自体は不要にならない。フェーズ3はClass052/Class053への入力元が Pleasanter外部UIに変わるだけで、その後の「値を見てProcessボタンを押す」という フェーズ2側の設計は影響を受けない。

背景・設計転換

当初のHC-WA/HC-SUB設計は「現在Statusに紐づくProcess一覧をbutton_templateで動的提示し、 ユーザーがラベルで選ぶ」方式だった。固定メニューBot Persistent Menu API、 POST /v1.0/bots/{botId}/persistentmenuはトーク画面下に常時表示される最大4ボタンの 固定入口であるため、この方式に切り替える。

  • ボタンは最大4つLINEWORKS仕様上の制約 → 4機能の要件とちょうど一致
  • 固定メニューは1対1個人トークのみ有効。Botが入ったグループトークでは表示されない 複数Bot参加トークルームでは全Bot共通でメニュー機能が使えない、という制限もあるが、 健康診断Botは個人対話前提のためグループ運用は考慮不要
  • ボタン(type:"message"タップ時は通常のテキストメッセージと同じ形でBot Webhookに届く postbackの値がテキストとして送られる想定)
  • 表示方式は実機確認済み2026-09-06、PC版・スマホ版LINEWORKS両方:
    • PC版: 常時表示のボタン列ではなく、入力欄右下の三本線(≡)アイコンをタップすると 4項目がポップアップメニューとして展開される方式
    • スマホ版Android実機確認済み: 当初の想定通り、入力欄のすぐ下に4ボタンが常時表示の ボタン列として並ぶ。「トーク内にクリックするだけのボタンが出る」という期待に完全一致
    • ラベル(健診日程/受診・再検査報告/診断書提出/ストレスチェック)は両方の表示形式で 正しく反映されることを確認済み。診断書提出フローの対話中Botからの確認メッセージ後でも アクセスできることを確認済みのため、「対話フロー中にメニューへアクセスできるか」という懸念は解消
    • リッチメニューRich Menuとの比較 → 固定メニューのまま進める2026-09-07確定: LINEWORKS公式ドキュメントbot-menuによると、リッチメニューもPC/ブラウザ版では 固定メニューと同様にドロップダウン展開になる仕様であり、PC版の表示方式はどちらを 使っても変わらない。モバイル版は固定メニューで既に「常時表示ボタン列」というUXを 達成できているため、画像作成・アップロードの手間が発生するリッチメニューへの切替は 不採用

この転換により、HC-SUBの役割は「4カテゴリいずれかの対話完了時にProcess実行固定文言の 結果案内」に単純化される。HC-WAの動的選択肢マッチングpendingProcessesは不要になり、 固定メニューのpostbackカテゴリ名を受けて現在Statusから対応アクションを解決する 分岐ロジックが中心になる。

Status遷移全体像Excel雛形14項目 × 今回の役割分担)

Status遷移 実行者 Bot関与
100→200アンケート発行 管理者操作 なし
210→250申込中 管理者操作 なし
250→260検査機関確定、2026-09-07追加 管理者が病院・日程等の必要情報を入力して保存すると自動遷移 なし
260→300日程通知済み 管理者がProcess実行現状は手動。将来n8n側で自動化する可能性あり、未確定 HC-WP経由でBot通知候補日案内
300→310日程確定 本人がBot対話 HC-WA固定メニュー「健診日程」
310→400受診済 本人がBot対話 HC-WA固定メニュー「受診/再検査報告」
400→410診断書保存 本人がBot対話 HC-WA固定メニュー「診断書提出」
410→500就業判定済み 管理者/産業医操作 なし
500→800再検査通知 管理者操作 HC-WP経由でBot通知再検査案内
800→810再検査受診済み 本人がBot対話 HC-WA固定メニュー「受診/再検査報告」
500→900・810→900完了 管理者操作 なし
任意→910/920/930対象外/保留/その他) 管理者操作 なし

「日程通知」「再検査通知」の2箇所はHC-WP担当者操作起点のStatusプッシュ通知の用途として 確定。既存設計のHC-WPはそのまま活きる。

Status列の直接編集は不可にする2026-09-07確定: 508971画面上でStatus列を管理者が 手動で書き換えられてしまうと、Bot対話中の待機状態bot_conversation_state)とレコードの 実際のStatusがずれる懸念があったため、Status列はProcess経由でのみ変更できるよう編集不可に するEditorColumnsから除外する等。これにより「Bot対話中に管理者がStatusを直接変更する」 という競合ケース自体が発生しなくなる。なおDate001(候補日)は管理者が入力する項目のまま 変更可能で、Bot対話中に変わっても実害はない対話中の承諾/変更はDate002確定日に書き込む 別項目のため)。

Status=250/260等での長期停滞レコードの検知・催促 → 保留2026-09-07: 自分手配を含め、 今回は未確定のまま保留とするHC-REMINDERへの追加は今後の検討課題

Bot対話用Process定義508971へ新規追加、固定メニュー経由

Name CurrentStatus→ChangedStatus ValidateInputs
日程_確定 300→310 Date002確定日、必須
報告_受診済み 310→400 なし
報告_再検査受診済み 800→810 なし
診断書_保存 400→410 AttachmentsA必須

命名規則: Process.Name内部名、DisplayNameとは別に「カテゴリ_内容」の プレフィックスを付与し、固定メニューのpostback→カテゴリ名への変換テーブルを介して 現在StatusのProcesses一覧からプレフィックス一致するものを検索・実行する解決方式にする。 Name/DisplayNameは自由文字列既存実例実行予算WF申請サイトのprocesses.jsonで確認済み

3択button_templateのpostback値確定・2026-09-06、内部コード方式から変更

旧設計(内部コードMENU_SCHEDULE等、下記は不採用・履歴として残す): postbackを 英数字の内部コードにし、HC-WA側で変換テーブルを介してカテゴリ名へ変換する方式だった。 button_template方式への転換に伴い、旧Express実装や固定メニュー本体「健康診断について」と 表記を統一するため、ラベルと同じ日本語テキストをそのままpostbackにする方式に変更 button_templateは直前のBotメッセージという文脈に紐づく選択肢のため、固定メニューの 常時入口方式より手入力テキストとの誤衝突リスクが低いと判断)。

ボタン表示ラベルpostbackのtext カテゴリ名(内部) Processプレフィックス
健診日程 日程 日程_
受診・再検査報告 報告 報告_
診断書提出 診断書 診断書_

button_template送信時のボタン定義type:"message"labeltextを同一にする):

{
  "content": {
    "type": "button_template",
    "contentText": "ご用件を選んでください。",
    "actions": [
      { "type": "message", "label": "健診日程", "text": "健診日程" },
      { "type": "message", "label": "受診・再検査報告", "text": "受診・再検査報告" },
      { "type": "message", "label": "診断書提出", "text": "診断書提出" }
    ]
  }
}

このbutton_templateは、固定メニュー「健康診断について」タップテキスト受信を トリガーにHC-WAが返信する「最終設計確定」節参照

表示メニューの絞り込み確定・2026-09-06

3択は常に固定で出さず、現在のStatusに合致しないカテゴリはそもそもactionsに含めない ボタンを押させてから「現在対象外です」と弾く方式は不採用。button_template組み立て時に 508971の対象レコードの現在Statusを見て、以下の対応表で該当するカテゴリだけをactions配列に含める。

カテゴリ 対象Status
健診日程 300日程通知済み310日程確定済み、確定日照会のみ
受診・再検査報告 310受診報告待ち800再検査報告待ち
診断書提出 400受診済、診断書提出待ち

該当するカテゴリが1つもない場合Status=100〜250、410〜510、900〜930等は、 「現在ご案内できる項目はありません」とだけ返信し、button_template自体を送らない。

この絞り込みにより、旧「3カテゴリの対話フロー詳細」各節末尾の「それ以外のStatus: 『現在対象外です』」という分岐は、実運用では基本的に到達しない防御的なフォールバックとして 残る(固定メニュー経由ではなく直接テキスト送信されたイレギュラー入力への保険)。

3カテゴリの対話フロー詳細

1. 健診日程(日程_*

  • Status=300日程通知済み時: button_templateで案内確定・2026-09-06、旧Express実装 sendDateShortcutButtonsのショートカットボタン方式を踏襲。LINEWORKS Bot APIには 日付選択UIdatetimepickerアクションが存在しないため、ネイティブピッカーではなく ボタン+自由入力のハイブリッドで対応):
    {
      "type": "button_template",
      "contentText": "候補日は{Date001}です。この日程でよろしければ「承諾」、変更したい場合は候補から選ぶか日付を直接入力してください。",
      "actions": [
        { "type": "message", "label": "承諾", "text": "承諾" },
        { "type": "message", "label": "来週も同じ曜日", "text": "{Date001+7日}" },
        { "type": "message", "label": "再来週も同じ曜日", "text": "{Date001+14日}" }
      ]
    }
    
    • 承諾ワード「承諾」「OK」等受信 → Date001の値をそのままDate002へコピーして Process日程_確定実行
    • ショートカットボタン(Date001+7日/+14日の具体的な日付テキスト)受信 → その日付をDate002にセットしてProcess日程_確定実行
    • それ以外の自由入力テキスト受信 → 旧Express実装の和暦・月日省略対応パースロジックを 流用して日付として解釈を試みる → パース成功時は即確定せず、「{パース結果の日付}で よろしいですか?(はい/いいえ)」と確認を挟む(自由入力の誤爆防止、awaitInputyesno_confirm系の確認状態へ遷移) → 「はい」でDate002にセットしてProcess実行、 「いいえ」なら日程入力からやり直し。パース失敗時は「日付を認識できませんでした。 別の書き方でお試しください」と再案内。パース失敗が3回連続したら強制中断 2026-09-07確定、診断書提出のPDF判定失敗時と同じ仕様: 待機解除し「日付を 認識できないため、いったん受付を中断します。固定メニューから「健診日程」を 選び直してください」と案内(失敗回数カウンタはbot_conversation_stateで管理。 選び直したタイミングでカウンタはリセット)
    • キャンセルワード → 待機解除
  • Status=310日程確定時: 確定日Date002を表示するのみProcess不要、照会のみ
  • それ以外のStatus: 「現在対象外です」

2. 受診/再検査報告(報告_*

Status=310受診報告とStatus=800再検査報告で質問形式が異なる2026-09-06確定

Status=310時: 単純な受診確認のみ

  • ボタン押下 → 「健康診断の受診は完了しましたか?(はい/いいえ)」
  • 「はい」 → Process報告_受診済み実行310→400
  • 「いいえ」/キャンセル → 待機解除

Status=800時: 再検査結果の4項目をトークで1問ずつ収集確定・2026-09-06。 各項目、回答受信のたびに確認ステップを挟む2026-09-06確定、脱線・誤入力対策:

  • ボタン押下 → 「再検査の結果について、以下を順番にお伺いします。」に続けて 1問目「a. 再検査受診日を教えてください」を送信 → awaitInput:"report_form", awaitColumn:"a"で待機
  • a回答受信 → 「a. 再検査受診日:{回答}でよろしいですか?(はい/いいえ)」と確認 awaitInputreport_formのまま、確認中フラグを内部的に保持) → 「はい」なら一時保存して次の質問bへ進む。「いいえ」ならもう一度aを聞き直す (確認せず訂正入力を直接受け付ける)
  • 同様にb「受診医師名」→確認→c「検査項目、結果概要」→確認→d「就労の可否」→確認、 の順で1項目ずつ確認を挟みながら進める
  • d確認完了 → 4項目揃ったので、a〜dをまとめたテキスト(後述フォーマット)を 508971のDescriptionG(再検査報告)へ保存 → Process報告_再検査受診済み実行 800→810→ 「再検査の報告を受け付けました。ご対応ありがとうございました。」
  • 各ステップでキャンセルワード受信 → 一時保存していた回答も破棄し待機解除 4項目のうち一部だけ回答済みでも保存しない。やり直す場合は「受診・再検査報告」を 選び直せば最初(a)から)

DescriptionGへの保存フォーマットプレーンテキスト、4項目をまとめて1つの欄に:

a.再検査受診日:{aの回答}
b.受診医師名:{bの回答}
c.検査項目、結果(概要):{cの回答}
d.就労の可否:{dの回答}

対象Status310・800以外: 「現在対象外です」(ただし「表示メニューの絞り込み」節参照。 そもそもボタン自体を出さない設計に変更したため、この分岐は主に固定メニュー経由の 直接テキスト送信等イレギュラー入力への保険として残る)

3. 診断書提出(診断書_*

  • Status=400時のみ有効。ボタン押下 → 「診断書をPDFでスキャンしてアップロードして ください。写真は不可です。表裏が別ファイルの場合は複数枚送信できます。 すべて送り終わったら「完了」と送信してください。」
  • ファイル受信のたびに次を実施:
    1. PDF判定後述「PDF判定方式」参照。PDF以外 → 「診断結果をお送りいただきましたが、 画像での送信でしたので、PDFで再度お送り頂きますようおねがいいたします。」と再案内、 待機継続(受信済みファイルは破棄せず保持)。PDF以外の受信が3回連続したら強制中断 2026-09-06確定: 待機解除し「PDF形式での送信が確認できないため、いったん 受付を中断します。固定メニューから「診断書提出」を選び直してください」と案内 bot_conversation_stateに失敗回数カウンタが必要、report_formの一時保存と 同様の仕組みで管理)。固定メニューから「診断書提出」を選び直したタイミングで 失敗カウンタ・受信済みファイル一覧ともにリセットされる2026-09-06確定
    2. PDF確認OK → ダウンロード→Pleasanter添付アップロードAttachmentsへ追加、 Process実行はまだしない→「1件受け付けました。続けてファイルがあれば 送信、なければ「完了」と送信してください」と返す
  • 「完了」受信 → アップロード済み件数が1件以上ならProcess診断書_保存実行 400→410。0件ファイル未送信のまま「完了」受信なら 「まだファイルが送信されていません」と返し待機継続
  • キャンセル → 待機解除アップロード済みの一時分は破棄しない。Pleasanter側は Process未実行のためStatusは400のまま。再度「診断書提出」を選べば続きから やり直せる)
  • それ以外のStatus: 「現在対象外です」

10分タイムアウトによる自動確定2026-09-07確定: PDFを1枚以上アップロード済みの状態で 「完了」を送らないまま、最後にPDFを受信した時刻から10分経過したら、Process診断書_保存 を自動実行する400→410。自動確定時もユーザーへは通常の完了メッセージを送る本人が 「完了」を送った場合と同じ案内。PDFを1枚も送らずに10分経過した場合ボタン押下のみで 離脱はProcess実行せず待機解除のみ。監視は10分間隔の新規Scheduleワークフローで行う (既存方針「タイムアウト監視ワークフローは持たない」の例外、診断書提出フロー専用)。

離脱→選び直しでPleasanter側にアップロード済みファイルが混在するケース1回目に1枚 アップロード後に離脱、2回目に選び直してさらに送信→「完了」、のような流れで前回分と 今回分が両方Attachmentsに残る無視してよい2026-09-07確定。内容に問題があれば 管理者が確認後、再提出フローへ差し戻す運用でカバーする。

PDF判定方式

LINEWORKS BotコールバックのcontentにはfileIdのみが含まれ、MIME種別・ ファイル名は含まれない(公式ドキュメントbot-callback-messageで確認済み)。 コンテンツダウンロードAPIGET /v1.0/bots/{botId}/attachments/{fileId})も 302リダイレクト後の最終レスポンスヘッダー仕様が公式未記載のため、以下の 二段判定で実装する(実機確認しだい調整可):

  1. ダウンロード後のレスポンスヘッダーContent-Typeapplication/pdfなら確定
  2. 上記が取得できない/一致しない場合、ファイル本体の先頭バイトを見て マジックナンバー%PDF0x25 0x50 0x44 0x46で判定するフォールバックを入れる

キャンセル共通仕様

どのawaitInput状態でも、テキスト入力の先頭で「キャンセル」「やめる」「戻る」「中止」 「取消」「cancel」「stop」大文字小文字区別なしのいずれかのワード一致を最優先チェックし 2026-09-06、「中止」「取消」および英語表記を追加確定、一致したら待機状態をクリアして 「メニューからやり直してください」と返す。

担当者への連絡導線2026-09-07追加

自由入力での意図判別が難しいテキストベースの相談要望(日程調整の個別事情等)に対応するため、 選択肢固定メニュー・button_templateに「担当者に連絡」を常設し、選ばれたら固定の案内 メッセージを返す方式で対応する。

構成:

  1. 固定メニューpersistentmenuを「健康診断について」「担当者に連絡」の2ボタン構成に 変更する
  2. button_templateで選択肢を提示する全箇所の末尾に、共通で「担当者に連絡」ボタンを追加する 対象3箇所、いずれも最大10ボタンの制限に対し余裕あり。LINEWORKS公式ドキュメント bot-send-buttonで最大10ボタンと確認済み:
    • 「健康診断について」タップ後の3択健診日程受診・再検査報告診断書提出→4択に
    • 「健診日程」の候補日提示承諾来週も同じ曜日再来週も同じ曜日→4択に
    • 「受診・再検査報告」Status=310時の受診確認はいいいえ→3択に
  3. 「担当者に連絡」受信時の挙動は、経由した入口によって分ける2026-09-07確定:
    • button_template内の選択肢として選ばれた場合4択・3択の一部→ それまでの対話の 待機状態(awaitInput)はリセットせず維持したまま、案内メッセージだけ追加で返す (今の対話の一部としての相談、元のフローはそのまま続けられる)
    • 固定メニューから直接選ばれた場合 → 待機状態(awaitInput)もリセットしてから 案内メッセージを返す(対話を中断してでも相談したい、という利用シーンのため)
  4. 固定メニューの「担当者に連絡」は、対象者解決504412⇔508971照合を含め、 「健康診断について」と同じ処理フローを通す特別扱いしない、2026-09-07確定。 対象レコード0件新入社員等の場合は既存ルール通り「対象の健診情報がありません」が 返る
  5. 対象外: 診断書提出(ファイル受信待ち)・受診/再検査報告のStatus=800時a〜d自由記述 収集)は、選択肢を提示しないテキスト/ファイル入力中心のフローのため今回のスコープ外 button_templateへの追加なし。これらのフロー中でも固定メニューの「担当者に連絡」は 常時反応する4番の通り待機状態もリセットされる

案内メッセージ文言確定・2026-09-11更新、担当者窓口は「総務総合窓口」:

ご用の方は総務総合窓口へお問合せください🙇
《総務・契約関連窓口》
https://line.worksmobile.com/message/send?userNoList=800300000001350&version=25&type=counselor

awaitInput状態の拡張

既存(none/date/file)から以下へ拡張:

  • schedule_confirm: 日程承諾/ショートカットボタン選択/自由入力日付のパース/キャンセルの 分岐(健診日程用)。自由入力の場合はパース後さらにyesno_confirm(「この日付で よろしいですかへ遷移してから確定する2段階誤爆防止、2026-09-06確定
  • yesno_confirm: はい/いいえ/キャンセルの3方向分岐受診報告で使用
  • file: 既存を拡張し、PDF形式チェックを追加診断書提出用
  • report_form: 再検査報告4項目の順次収集用受診・再検査報告のStatus=800時のみawaitColumn"a"|"b"|"c"|"d"として現在どの項目を聞いているかを保持する。 a〜dの回答内容そのものは、既存のbot_conversation_stateの列だけでは保持できないため、 一時保存用の新規列(例: formDraft、JSON文字列 {"a":"...","b":"..."})を bot_conversation_stateデータテーブルに追加する必要がある(未実装、要追加)。 4項目揃った時点でDescriptionGへまとめて書き込み、この一時列はクリアする

課題1診断書ファイル添付処理との関係

診断書提出フローの「PDF受信→ダウンロード→Pleasanterアップロード→Process実行」部分は、 既存の未実装課題(NodeSrv/apps/healthcheck-survey-bot/workflows/hc-wa-lineworks-response.json のTODOコメント参照の実装がそのまま必要になる。設計は別途確定済み:

  • Pleasanter添付API: POST api/items/{id}/updateAttachmentsHash:{AttachmentsA:[{ContentType,Name,Base64}]}
  • LINEWORKS添付ダウンロード: GET https://www.worksapis.com/v1.0/bots/{botId}/attachments/{fileId} Bearer token、302→Locationへ再GET
  • ファイル名規則: {年度エリア(ClassZ)}_診断書_{名前(ClassC)}.{拡張子}
  • ノード構成変更案: 既存「IF: action==send」を「IF: action==error」に役割変更し、 false側をsend/download_file共通の経路にする詳細は本ファイル末尾の変更履歴、または 会話ログ参照。実装時にworkflows-status.mdへ反映すること)

Status別カウンタ項目Num031~046設計・反映済み2026-09-06追記

固定メニュー設計を進める過程で、508971のNum031~038旧: 全社員人数/対象人数/受診済み/ 再検査/就業判定-可/就業判定-不可/SC受診済み/健診終了が後付けでStatus15段階に対応しきれて いないことが判明。508971・513156双方のNum031~046を、Status全段階に1:1対応する 累積型カウンタとして再設計・反映済み。

前提となるStatus定義変更

ユーザーがPleasanter画面上でStatus定義自体を変更し、500就業判定済みを 「500,就業判定_可」「510,就業判定_不可」の2つに分割Class053の値による条件分岐が 不要になり、Process定義がシンプルになった。Status全16段階に確定:

100,新規登録 / 200,アンケート発行 / 210,アンケート回答 / 250,申込中 /
260,検査機関確定 / 300,日程通知済み / 310,日程確定 / 400,受診済 / 410,診断書保存 /
500,就業判定_可 / 510,就業判定_不可 / 800,再検査通知 / 810,再検査受診済み /
900,完了 / 910,対象外 / 920,保留 / 930,その他

260「検査機関確定」追加の経緯2026-09-07確定: 検査機関・候補日・コース等、日程通知に 必要な情報を管理者が入力する作業と、実際にBotへ通知を送る作業を分離するために新設。 Pleasanterのプロセス機能には「実行種別」設定があり、通常の「追加したボタン」手動クリックの ほかに「追加したボタン/作成・更新」を選ぶと、ボタンとして表示されつつ、標準の保存操作 アクション種別「保存」をトリガーにプロセスが自動実行もされる250→260用のProcessは この自動実行方式を使う。JSON上はExecutionType:10、2026-09-07に実機画面で名称確認済み。 本ファイル内で単に「作成または更新」と書いている箇所は同じ「追加したボタン/作成・更新」を 指す。260→300Bot通知は従来通り担当者がボタンを押す手動実行のまま将来的にn8n側の 別ワークフローで自動化する可能性があるが未確定)。

「追加したボタン/作成・更新」実行種別の発動条件 → 確定2026-09-07、ユーザーが実機の設定画面で確認: 「現在の状況」CurrentStatusがレコードの実際のStatusと一致し、かつ「条件」タブの フィルタ条件に合致した場合のみプロセスが処理される(両方を満たさないと発動しない)。 250→260のProcessをCurrentStatus=250申込中で作成しておけば、Status=260到達後に 同レコードを再度編集・保存してもCurrentStatus不一致のため再発火しない。 一方、「入力検証」タブValidateInputsはこの実行種別では処理されない(適用されるのは 「追加したボタン」実行種別のみ)。そのためClass003Date001Class004の必須化は ValidateInputsではなく「条件」タブのフィルタ条件で表現する必要がある旧記述の 「ValidateInputsが自動実行の発火条件として機能する」は誤り、下表の想定Process一覧を訂正

Num031~046対応表確定・反映済み

Num 項目 Status 初期値
031 新規登録人数 100 1DefaultInput、新規作成時に自動セット
032 アンケート発行 200 0
033 アンケート回答 210 0
034 申込中 250 0
047 検査機関確定 260 02026-09-07追加、Num047は空き列で確認済み
035 日程通知済み 300 0
036 日程確定 310 0
037 受診済み 400 0
038 診断書保存 410 0
039 就業判定_可 500 0
040 就業判定_不可 510 0
041 再検査通知 800 0
042 再検査受診済み 810 0
043 完了 900 0
044 対象外 910 0
045 保留 920 0
046 その他 930 0

集計方式は累積型(以上): 該当Statusへ遷移した時点でProcessのDataChanges Type:"InputValue"により該当Num列を1にセットする。一度1になったら0に戻さない (例: 「受診済み」は400以降のどのStatusに進んでもずっと1のまま

「全社員人数」「対象人数」相当の項目は廃止。全体件数は513156側でレコード件数 Count集計を使えば代用できるため、専用のNum列を持たない方針に確定。 SC受診済み旧Num037相当も今回のスコープから削除。CheckB自体は508971に残るが、 Status対応表には含めない固定メニュー「ストレスチェック」機能は今回の対象範囲外、 2026-09-07確定。冒頭の注記参照

反映済み内容2026-09-06、本番

  • 508971: Num031~038のLabelText置換DefaultInput設定、Num039~046新規追加。 EditorColumnHash._Tab-2カウンタータブ末尾へNum039~046を追加配置。 Style Id2数値エリア調整の対象セレクタへNum039~046を追加 (スクリプト: .claude/js/site-scripts/健康診断管理/redefine-num031-046-508971.js
  • 513156: 508971と同一のLabelText構成に統一。EditorColumnHash.General Num038の直後へNum039~046を追加配置。Style Id2も同様に追加 (スクリプト: redefine-num031-046-513156.js
  • 508971のSummaries513156への集計設定へNum039~046の8件を追加Id31~38。 既存Num031~038分Id1~8、508971→513156、Type:Total、LinkColumn:ClassZは 列の意味が変わっただけで設定自体は流用(スクリプト: add-summaries-num039-046-508971.js。Summaries合計42件Num031~046の16件 Num061~073/081~093の診断結果26件、2026-09-07時点。検査項目分割の経緯は次節参照

検査項目「聴力検査」の3分割2026-09-07追加

Num061のLabelText「力検査」はデータ不備による表記先頭の「聴」が欠落と判明。 実態は労働安全衛生規則の健診項目「聴力検査(その他の方法による検査を含む)」で、 実運用では聴力検査を1000Hz4000Hzその他オージオメータ以外の方法の3項目に 分けて記録する必要があることが確認できたため、検査項目別カウンタを11項目から 13項目へ拡張した。

  • 508971・513156ともにNum061~071実施人数→Num061~073、Num081~091有所見者数 →Num081~093へ拡張各11列→13列、新規4列はNum072/073/092/093
  • 項目順実施・有所見共通13項目: 聴力検査(1000Hz)/聴力検査(4000Hz) 聴力検査(その他)/胸部エックス線検査/喀痰検査/血圧/貧血検査/肝機能検査/ 血中脂質検査/血糖検査/尿検査(糖)/尿検査(蛋白/たん)/心電図検査
  • 「聴力検査(その他)」にのみDescription「その他の方法による検査」を設定旧Num061の Description流用。1000Hz/4000Hz側はDescriptionなし
  • 508971のEditorColumnHash._Tab-1・513156のEditorColumnHash.General・両サイトの Styles Id2数値エリア調整セレクタ・508971→513156のSummaries新規4件、 Num072/073/092/093、Type:Total、LinkColumn:ClassZを合わせて更新済み
  • 実施済みレコード13件はいずれもNum061~091が未入力0のみだったため、値の移行は 不要(ラベル・列追加のみで対応完了)。スクリプト: .claude/js/site-scripts/健康診断管理/restructure-hearing-test-508971-513156.js
  • 508971・513156のNum031~046 LabelTextが完全一致することを確認済み

実施済み2026-09-07、Process定義17件を本番反映

508971のProcesses定義17件全件検査機関確定含むをAPI経由で作成済み。

  • Id1~3,5~1713件: スクリプトadd-processes-batch1-508971.jsStatus遷移+OnClickのみの 単純グループ12件add-processes-batch2-508971.jsValidateInputs・Date/Check系 DataChangesを含む4件日程通知済み・日程_確定・診断書_保存・再検査通知。Date/Check系 DataChangesは社内実例で裏付けが取れた形式InputDate/InputValue)をそのまま使用
  • Id4「検査機関確定」250→260: スクリプトadd-process-260-508971.js。実行種別 「作成または更新」=ExecutionType:10社内189112実例で23件全一致、裏付け確定。 条件タブ(View.ColumnFilterHashは、否定フィルタUIがProcessの条件タブには 存在しないと実機確認できたため、Class003(検査機関)・Class004(コース)は 実行時点の実際の選択肢ResultIdを配列で列挙する方式、Date001(候補日)は公式マニュアル api-viewの日付範囲指定を使い広い範囲1900/01/01〜2999/12/31を指定して 「入力されていれば必ずヒットする」条件にした

Num列へのDataChanges各ProcessにNum0XX=1をセットする部分は全17件に反映済み 2026-09-07: 「アンケート発行」Id1にユーザーが実機でNum032=1を試験追加した 形式と同じ(InputValueValueFormulaNotUseDisplayName/ValueFormulaIsDisplayErrorは falseで、残り16件Id2~17へAPI経由で展開済みスクリプト: add-num-datachanges-remaining-508971.js)。実際にProcess実行してNum列が1になるかの 動作確認はこれから(ユーザーが後日まとめて確認予定)。

Processesの並び順を修正2026-09-07: batch1→batch2→260の投入順のまま追加していた ためPleasanter管理画面のプロセス一覧がId順になっておらず分かりにくいと指摘を受け、 Id昇順Status遷移の自然な流れ、1アンケート発行〜17その他に並べ替えた (スクリプト: reorder-processes-508971.js、各Processの中身は変更なし

不具合修正: Status列に260(検査機関確定)が未登録だった2026-09-07発見・修正: 500/510分割時のStatus定義変更前節「前提となるStatus定義変更」参照に260を含め 忘れており、Status列のChoicesTextに260のエントリが存在しなかった。このため 「検査機関確定」Processの「変更後の状況」欄が画面上で名前解決できず?260と表示される 不具合が発生ユーザーが実機で発見。250(申込中)と300(日程通知済み)の間に 260,検査機関確定,機関確定,new-status-purpleを追加して解消(スクリプト: add-status-260-508971.js。513156実施年度-集計にはStatus列自体が存在しないため 対応不要。

検査機関確定Processの発火条件を選択肢列挙方式からCheck列方式へ変更2026-09-07確定・ 実装済み): 実機でClass003/Class004の条件タブを確認したところ、選択肢を配列で 静的に列挙する方式では、511924/513284へ新しい選択肢が追加されるたびに条件タブの 更新が必要になり、メンテ漏れリスクがあると判明。そもそもClass003・Class004は単一選択 項目のため、値の有無だけを判定できれば十分という前提のもと、専用Check列 CheckCラベル「日程情報入力済」、EditorColumnHash.GeneralのDate002直後に配置を 新設し、ServerScriptで自動セットする方式に変更した。

  • ServerScript「検査機関確定準備完了同期スクリプト.js」BeforeCreate/BeforeUpdate 両方でtrue、Id0: Class003Date001Class004が全部値ありならCheckCをtrueに セットする。構造は社内実例新版営業積算システム504322「状況Class062自動同期 スクリプト」)の{Title,Name,BeforeCreate,BeforeUpdate,Body,Id}形式で裏付け済み
  • Process「検査機関確定」Id4View.ColumnFilterHash{"Class003":[...],"Date001":[...], "Class004":[...]}(選択肢列挙)から{"CheckC":"true"}(単純な条件)へ置き換え
  • これにより511924・513284へ新しい選択肢を追加してもProcess側のメンテは一切不要になった
  • スクリプト: .claude/js/site-scripts/健康診断管理/add-checkc-and-fix-process260-508971.js

運用上の注意: Class003Class004は選択肢を配列で静的に列挙しているため、 511924「受診病院一覧」・513284「検診種別マスタ」へ新しい選択肢を追加するたびに、 検査機関確定ProcessのView.ColumnFilterHashも更新しないと、新しい選択肢を選んだ レコードだけ発火条件から漏れる。病院・コース追加時のチェックリストに 「検査機関確定Processの条件更新add-process-260-508971.jsの再実行)」を含めること。 2026-09-07、CheckC方式への変更により解消・撤回。以後この対応は不要

HC-WPが送信するProcess2件のDescription欄へメッセージ本文を転記済み2026-09-07: Excel「メッセージ設定」シート①・⑤の本文をそのまま転記したプレースホルダーは {検査機関}等のラベル名形式のまま、HC-WP側で値に置換する設計

  • Process「日程通知済み」Id5: ①受診日のお知らせの本文
  • Process「再検査通知」Id11: ⑤再検査通知の本文
  • スクリプト: .claude/js/site-scripts/健康診断管理/set-description-508971.js
  • 他のProcess②③④⑥⑦はStatus変化トリガーではなく日次リマインダー/ユーザー起点のため Description欄は使わない。設計上Process経由でHC-WPが送るのは①⑤の2件のみ

Process定義一覧全17件、2026-09-07反映済み

Status遷移・DataChangesNum列含む・ValidateInputsを全件反映済みBot対話用4件 管理者操作用、詳細は本ファイル前半「Status遷移全体像」参照。Num列DataChangesの 実機動作確認Process実行して実際にNum列が1になるかはユーザーが後日実施予定。

Process名 Status遷移 DataChanges ValidateInputs
アンケート発行 100→200 Num032=1 なし
アンケート回答 200→210 Num033=1 なし
申込中 210→250 Num034=1 なし
検査機関確定2026-09-07追加 250→260実行種別「作成または更新」で自動実行、CurrentStatus=250指定 Num047=1 入力検証タブは不使用(この実行種別では処理されない)。条件タブの対象列は「日程通知済み」Processと同一Class003Date001Class004、2026-09-07確定。3列とも入力済みであることを発火条件にする
日程通知済み 260→300HC-WP経由でBot通知。**Class003「自分手配」ResultId 513480
レコードは対象外**専用トークフロー未確定、2026-09-07追加 Num035=1 **Class003(検査機関)・Date001
(健康診断候補日)・Class004コースを必須化確定・2026-09-06、①送信メッセージの
差込変数が空欄のまま送信されるのを防ぐ)。Class005/Class006/Class007は任意
(オプション自体が任意選択のため)
日程_確定 300→310Bot対話 Num036=1 Date002確定日、必須
報告_受診済み 310→400Bot対話 Num037=1 なし
診断書_保存 400→410Bot対話 Num038=1 AttachmentsA必須
就業判定_可 410→500 Num039=1 なし
就業判定_不可 410→510 Num040=1 なし
再検査通知 500→800HC-WP経由でBot通知 Num041=1、Date003(再検査通知日)に送信日をセット、
CheckA再検査連絡をtrueに なし(⑤本文は固定文言のみで差込変数なし)
報告_再検査受診済み 800→810Bot対話 Num042=1 なし(DescriptionGへの保存はBot対話側で実施、
Process自体の入力検証は不要
完了(再検査不要) 500→900 Num043=1 なし
完了(再検査済み) 810→900 Num043=1 なし
対象外 任意→910 Num044=1 なし
保留 任意→920 Num045=1 なし
その他 任意→930 Num046=1 なし

DataChangesの裏付け状況2026-09-07、社内の全production環境processes.jsonを横断調査:

  • 共通フィールド構造(実例確認済み): 各DataChangesは {"Id":n,"Type":"...","ColumnName":"...","Value":"...","ValueFormulaNotUseDisplayName":false,"ValueFormulaIsDisplayError":false} の形(InputDateTimeのみ追加でBaseDateTimeを持つ)
  • Check列 → 裏付けあり: {"Type":"InputValue","ColumnName":"CheckA","Value":"1"}で true相当にする実例が複数サイトに存在488755等CheckA再検査連絡をtrueにする DataChangesはこの形で実装してよい
  • Date列 → 裏付けあり: 「今日」をセットするなら {"Type":"InputDateTime","ColumnName":"Date0XX","BaseDateTime":"CurrentTime","Value":"0,Days"}、 「n日後」なら{"Type":"InputDate","ColumnName":"Date0XX","Value":"n,Days"}の実例が 複数サイトに存在。Date003/Date004の送信日セットはこの形で実装してよい
  • Num列 → 裏付けなし(要注意): {"Type":"InputValue","ColumnName":"Num0XX","Value":"1"} という組み合わせは、社内の全productionサイトのprocesses.jsonを横断検索しても実例が 1件も見つからなかった。Class列に対するInputValueValue:"1"等)の実例はあるため 類推は成り立つが、Num列で同様に動作する確証はない。Num031~047のカウンタ更新 DataChangesは、実装時にユーザーが実機で1件だけ試験設定し、動作確認してから残りに 展開すること(前節「実装の役割分担」参照)

【重大障害・原因判明】OnClickフィールドをAPI経由で指定すると個別レコード画面が

全件開けなくなる2026-09-07発生・解決

API経由でProcess定義17件を作成した際、OnClickフィールドに"$p.ex.processScript($(this));" 実行種別「追加したボタン」用の一般的な値、社内189112実例のコメントから引用したものを 明示的にセットしたところ、当該Processを1件でも含めるだけで508971の個別レコード編集画面が 全件(対象レコードに関わらず)「指定された情報は見つかりませんでした」で開けなくなる障害が 発生した。一覧画面グリッド・APIget/update)は正常に動作し続けたため発見が遅れた。

原因: ユーザーがPleasanter画面上で同じ17件を手動登録したところ、生成されたJSONには OnClickフィールドが一切含まれていなかった(実行種別が「追加したボタン」でも 「追加したボタン作成・更新」でも同様。189112実例で見えたOnClick値は、別の生成経路 (バージョン差・特殊な実装)による見た目上の値であり、汎用的にコピーしてよい値ではなかった。

追加検証2026-09-07、ユーザーが画面上でProcess1のOnClick欄に同じ値 $p.ex.processScript($(this));を手動入力→保存): この場合は編集画面が壊れなかった Seleniumで513409の正常表示を確認つまりOnClickの値自体が悪いのではなく、 「APIupdatesite経由でOnClickフィールドを含むJSON全体を送信する」という経路自体に 問題があった画面上の正規UIフローで保存されたOnClick値は無害。根本原因の内部的な メカニズムPleasanter側のバリデーション・整形処理のどこで衝突しているかは未解明の ままだが、実運用上の対処(下記ルール)には影響しない。

切り分け経緯: ServerScript疑い→Process4単体疑い→Processes全体除外で復旧確認→ バックアップから段階的に復元する二分探索でId2(アンケート回答)単体でも再現確認→ ユーザーが手動登録した17件と自分がAPI投入した17件のJSON構造を直接比較し、OnClickの 有無が唯一の違いと判明。切り分け作業はSeleniumpleasanter-selenium-html-scrape スキル)で「指定された情報は見つかりませんでした」の再現有無を自動確認しながら進めた。

さらに追加検証2026-09-07、API経由: 「既存の手動登録済みProcesses配列を getsiteで取得し、そのOnClick未設定のプロパティへ$p.ex.processScript($(this));を 追記してそのままupdatesiteで送信する」方式を、まずId2の1件→問題なければ残り15件へ一括、 の順で試したところ、いずれも編集画面は壊れなかったSelenium確認済み。最終的に 17件全件へOnClickを付与した状態でも正常動作。

最終結論: 当初の障害の真因は「OnClickフィールドの存在」そのものではなく、 「Processオブジェクトをゼロから自分で組み立ててAPI送信した」ことによる、Pleasanter側の 生成物と比べた際の何らかの欠落・不整合だったと考えられる(具体的にどのプロパティ/ 構造が欠けていたかは特定できていない。「既存のPleasanter生成済みオブジェクトに プロパティを追記するだけ」の更新であれば、OnClickを含め安全にAPI経由で操作できる。

教訓・今後のルール:

  • Process定義を新規にゼロから組み立ててAPIupdatesite)経由で送信するのは避ける 今回の障害の直接原因。新規Processの追加は画面上の手動登録を基本とする
  • 既存の(getsiteで取得したProcessオブジェクトに対して、特定プロパティを 追記・変更するだけの更新はAPI経由で問題なく行えるOnClickを含む。DataChanges・ Description・ValidateInputs・条件タブ・OnClick、いずれも2026-09-07に安全性を確認済み
  • 本番のProcess定義17件は、Process本体をユーザーが画面上で手動登録した後、 DataChanges・Description・条件タブ・ValidateInputs・OnClickをすべてAPI経由の 追記操作で完成させた全項目、Selenium確認済み

Process定義17件の最終状態2026-09-07、全項目実装完了・Seleniumで編集画面の正常動作を 都度確認済み):

  • Process本体Name/DisplayName/CurrentStatus/ChangedStatus/実行種別): ユーザーが Pleasanter画面上で17件全件を手動登録
  • OnClick$p.ex.processScript($(this));: 全17件へAPI経由既存Processオブジェクトへの 追記方式で追加済み。Selenium確認済み、編集画面への影響なし
  • 実行種別「追加したボタン/作成・更新」(検査機関確定=Id4を画面で選ぶと、JSON上は ExecutionType:20になると実機確認2026-09-06に189112実例で確認したExecutionType:10 とは異なる値。10と20の違いは未解明だが、20が「追加したボタン作成・更新」に対応する という事実だけで実装上は十分)
  • Num列DataChanges全17件: API経由で追加済みOnClickが存在しないことを事前チェックする 安全策付きスクリプトで実施。1件Id1を試験→Selenium確認後、残り16件を一括展開
  • Id5日程通知済み・Id11再検査通知のDescription欄: API経由で追加済み
  • Id4検査機関確定の条件タブView.ColumnFilterHash: API経由で{"CheckC":"true"}を 追加済み
  • Id5・Id6・Id8のValidateInputs: API経由で追加済みId5: Class003/Date001/Class004必須、Id6: Date002必須、Id8: AttachmentsA必須)
  • スクリプト一式: .claude/js/site-scripts/健康診断管理/add-num-datachange-single-508971.js (単発試験用)・add-num-datachanges-all-remaining-508971.js(一括展開)・ add-description-508971.jsadd-condition-process4-508971.jsadd-validateinputs-508971.js。いずれも対象ProcessのOnClickundefinedであることを 確認してから処理する安全策を組み込み済み
  • 動作確認方法: .claude/skills/pleasanter-selenium-html-scrapeスキルSeleniumで 本番513409の個別編集画面を都度取得し、「指定された情報は見つかりませんでした」 controller=errorsが出ないこと・HTMLサイズが正常範囲約20万文字であることを 確認する運用を今回確立した。同様の障害調査・確認作業でユーザーに手動確認を都度依頼する 代わりに使える

未確定・要検証事項2026-09-06 調査・確定分)

  • MIME種別/拡張子の取得方法 → 確定: 公式ドキュメントbot-callback-message でWebhookペイロードcontentにはfileIdのみが含まれ、fileName/mimeType等は ないことを確認。コンテンツダウンロードAPIbot-attachment-getも302 リダイレクト後の最終レスポンスヘッダー仕様は公式未記載。対応方針は上記 「PDF判定方式」節の二段判定Content-Typeヘッダー→ダメならマジックナンバー %PDF判定)に確定
  • 診断書の表裏提出方法 → 確定: 複数ファイル送信を受け付ける方式に確定。 詳細は上記「3. 診断書提出」節(ファイル受信のたびに逐次アップロード、 「完了」ワードでProcess実行参照
  • 固定メニューの表示方式・対話中のアクセス可否・リッチメニューとの選択 → 全て確定 2026-09-06表示方式確認、2026-09-07リッチメニュー不採用確定: 「背景・設計転換」節参照。スマホ版は常時表示ボタン列想定通り、PC版は三本線アイコンから 展開するポップアップ方式。対話中でもアクセス可能なことを確認済み。固定メニューのまま進め、 リッチメニューへの切替は不採用
  • LINEWORKS Bot Message API送信元認証の専用化・n8n実装の初回検証 → 完了2026-09-06: テスト用ワークフローHC-TEST: 添付アップロード検証r5KQCKPedZFgsuIc)で PDF送信→ダウンロード→Pleasanterアップロード→確認メッセージ送信の一連を実機確認済み
  • 固定メニュー登録Persistent Menu API → 完了2026-09-06: HC-SETUP: 固定メニュー登録 ワークフロー(0jVVF9WGlZrAygXXで4ボタンを実際に登録・実機確認済み
  • postback受信ペイロード構造 → 確定2026-09-06、実機確認: 4ボタンを実際にタップし、 Webhookペイロードが{"type":"message","source":{...},"content":{"type":"text", "text":"MENU_SCHEDULE"}}のように通常のテキストメッセージと全く同じ形式で届くことを確認 execution id 331〜334、テストワークフローr5KQCKPedZFgsuIcで受信)。「ボタン(type:"message") タップ時は通常のテキストメッセージと同じ形でBot Webhookに届く」という設計上の想定通り。 HC-WA本体側ではcontent.type==="text"かつcontent.textMENU_*のいずれかに一致する場合を 固定メニュー起点の分岐として扱う実装でよい
  • 重大な設計誤り発見・訂正 → 完了2026-09-06: 対象者解決の設計が誤っていたことが判明。 詳細はNodeSrv/docs/superpowers/specs/2026-09-05-healthcheck-lineworks-survey-n8n-design.md 2章「対象者解決の正しい照合ロジック」参照。LINEWORKS source.userIdはメールアドレスではなく UUID形式で、社員・組織マスタ管理テーブルSiteId 504412ClassAClass011経由の 2段階照合が必要本番HC-WAは未修正のまま、要反映

設計転換2026-09-06: 固定メニュー方式からbutton_template方式へ

固定メニューPersistent MenuはPC版で三本線アイコンからの展開操作が必要と判明し、 「トーク内にクリックするだけのボタンが出る」という当初のイメージと異なっていた。 旧Express実装oldCode/express/modules/lineworksSurvey.js)で使われていた button_template(メッセージ本文にボタンを埋め込む方式)に転換する。

実機検証済み2026-09-06、テストワークフローHC-TEST: button_templateメッセージ送信検証 To6uN6mgFhh2D3dP: POST /v1.0/bots/{botId}/users/{userId}/messagescontent{type:'button_template', contentText, actions:[{type:'message', label, text}, ...]}を 指定して送信 → HTTP 201成功、トーク上でBotメッセージ本文の直下に4つの選択肢が ボタンとして表示されることを確認。固定メニューのような「開く操作」は不要で、 Botがメッセージを送ったその場でボタンが見える。旧「固定メニューpostback値」節の 内部コード(MENU_SCHEDULEではなく、旧Express実装と同じくラベルとテキストを 一致させる方式(例: {type:'message', label:'健診日程', text:'健診日程'})で検証した button_templateはその場の1メッセージに紐づく選択肢のため、手入力テキストとの 誤衝突リスクは固定メニュー常時入口方式より低いと判断)。

固定メニュー関連の検証記録Persistent Menu API登録・PC/スマホ表示差異等)は 上記「背景・設計転換」「固定メニューpostback値」節に残すが、採用方式はbutton_templateに 変更。健康診断Botの固定メニュー自体は登録済みのままだが実質未使用になる (副作用はないため放置。削除する場合はHC-SETUP: 固定メニュー登録と同じ要領で 空のactionsを送信するか、Developer Console側で削除する

最終設計確定2026-09-06: 固定メニュー(1ボタン)button_template(3択)のハイブリッド方式

button_template方式は「Botが能動的にメッセージを送らないと選択肢が出ない」という課題がある Status変化時のHC-WPプッシュ通知では能動的送信で問題ないが、ユーザーが任意のタイミングで 自分からメニューを呼び出す手段がない。これを解決するため、固定メニューとbutton_templateを 併用するハイブリッド方式に確定する(固定メニュー/リッチメニューは互いに排他だが、 button_templateはメッセージコンテンツの一種で別レイヤーのため併用可能

構成:

  1. 固定メニューPersistent Menuはボタン1つだけに絞る: 「健康診断について」 textもラベルと同じ健康診断について。内部コード方式は不採用、button_template側と 合わせてラベル直接方式に統一)
  2. ユーザーが固定メニューから「健康診断について」をタップ → 通常のテキストメッセージ content.type:"text", content.text:"健康診断について"としてWebhookに届く
  3. HC-WA側でcontent.text === "健康診断について"を検知 → button_templateで 「ご用件を選んでください。」3択健診日程受診・再検査報告診断書提出を返信
  4. 3択のいずれかをタップ → 各カテゴリの対話フロー開始「3カテゴリの対話フロー詳細」節、 postbackはラベルと同じ日本語テキストで受信する前提に統一。旧MENU_SCHEDULE等の 内部コード方式は不採用)

実機検証済み2026-09-06、Android実機、テストワークフローr5KQCKPedZFgsuIc改修版): 固定メニュー「健康診断について」タップ→4択button_template表示、の一連の流れを確認済み 検証時点ではストレスチェックを含む4択、その後対象外化しているため現行は3択

固定メニューの更新: HC-SETUP: 固定メニュー登録0jVVF9WGlZrAygXX)のpersistentmenu 登録内容を4ボタンから1ボタン「健康診断について」に変更済みWebhook再実行でHTTP 201確認済み

確定2026-09-06: 3択button_templateは、固定メニュー「健康診断について」タップ content.text==="健康診断について"の完全一致)経由でのみ送信する。待機状態なし awaitInput:noneで任意のテキストを送っても3択は送らない(フォールバック方式は不採用)。 理由: 任意テキスト受信への自動応答は、意図しないタイミング(雑談・誤送信等)でもメニューが 飛んでくる形になり、固定メニューという明確な入口を用意した意味が薄れるため。 待機状態あり(awaitInputnone以外)での通常テキスト受信は、従来通りその待機中の 分岐処理(日付入力・はい/いいえ確認・ファイル受信等)に従う。

未確定(今後の検討事項):

  • HC-WA本体hc-wa-lineworks-response.json)への正式反映は別タスク。現状はテスト ワークフロー(r5KQCKPedZFgsuIc)上でのみ実装・検証済み

Bot送信メッセージ一覧・管理者からの自動送信2026-09-06追記

健康診断管理/プリザンターテーブル設計書_健康診断.xlsxの「LINE自動送信」シートに、 管理者からユーザーへ自動送信したいメッセージの実例6パターン①受診日のお知らせ〜 ⑥再検査受診日当日)があり、これまでの固定メニュー/button_template設計4カテゴリの 対話フロー)でカバーしていなかった要素を含む。同ファイルに新シート「メッセージ設定」を 追加し、メッセージID/名称/トリガー種別/トリガー詳細/条件分岐/差込変数/本文/ボタン/ 送信後処理の列で構造化・管理者が編集できる形にした(今後増える想定のメッセージも このシートに追記していく運用)。

確定事項

  • ①受診日のお知らせ: Status 250→300日程通知済みへの遷移そのものが 「LINE送信済み」の状態を表す。別途フラグ列は不要
  • ②③⑥(日付ベースの自動リマインダー): Status変化ではなく「受診日の◯日前」 「受診日当日」「再検査受診日当日」という日付トリガー。現行のHC-WPWebhookトリガー、 クライアントスクリプト起動)ではカバーできないため、新規にn8n専用ワークフロー 「日次リマインダー送信」仮称を用意し、1日1回のSchedule Triggerで自動実行する方針
    • リマインダー日数(②の「◯日前」)は全体共通の値とし、n8nのworkflow_config_valuesへ 環境変数として保持する方針に確定(例: HEALTHCHECK_REMINDER_DAYS_BEFORE。他の HEALTHCHECK_*キーと同じ場所で一元管理。レコードごとの個別設定ではない)。 具体値は3日前に確定2026-09-06
    • 日次リマインダーワークフローの実行時刻 → 確定2026-09-06: 毎日12:00に Schedule Triggerで実行
    • ワークフロー名 → 確定2026-09-06: HC-REMINDER既存のHC-SUB/HC-WP/HC-WAと 命名規則を統一)
    • 送信対象レコードの絞り込み条件 → 確定2026-09-06: 「受診済み返信が来ていないもの」 が共通条件。具体的には各リマインダーに対応するStatusのまま留まっているレコードのみを対象にする 次のStatusへ進んだ報告済みのレコードは自動的に対象から外れる
      • ②受診日アラート・③受診日当日: Status=310日程確定済みのまま
      • ⑥再検査報告の催促: Status=800再検査通知のまま「⑥の正しい仕様」節に訂正あり、 「受診日当日」ではない)
      • ⑦日程未確定の催促新規・2026-09-07追加: Status=300日程通知済みのまま。 起算点Date004日程通知日を1日経過するごとに繰り返し送信「⑦日程未確定の催促」節参照
      • 日付一致の判定条件「◯日前」「当日」の基準日をDate002等どの列から取るかは 日次リマインダーワークフロー実装時に詳細化する

⑥の正しい仕様2026-09-06訂正: 「再検査受診日当日」ではなく「再検査報告の催促」

当初「⑥再検査受診日当日(受診済み/未受診ボタン)」として設計していたが、実際のフローは 異なると判明した。

  • ⑤再検査通知を送信 → ユーザーが自発的に「受診・再検査報告」Status=800時の4項目 アンケート、「2. 受診/再検査報告」節参照)で【再検査結果報告書】(a〜d)を報告する
  • a.再検査受診日は事前の予定日ではなく、報告完了後に本人が事後入力する項目。 「再検査受診日当日」という独立したイベント自体が存在しない
  • ⑥は正しくは**「⑤送信から2週間ごとに繰り返す、報告未提出者への催促」**。まだ報告 Status=800→810への遷移が来ていない対象者に、2週間おきに定期送信する

催促の起算点管理確定・2026-09-06: 508971にDate003(ラベル「再検査通知日」、 CheckA直後に新規追加済み、スクリプト: .claude/js/site-scripts/健康診断管理/add-date003-508971.js)を追加。 513156実施年度-集計)へは追加しない508971のみでよいと確定済み。DescriptionGも 同様にテキスト集計不要のため513156には追加しない

  • ⑤送信時Status 500→800遷移、Process実行時のDataChangesDate003へ送信日をセット
  • 日次リマインダーワークフロー12:00実行Date003 + 14日 = 今日かつStatus=800の レコードを検出したら催促送信 → 送信後、Date003を「今日」に更新(次回起算点をリセット、 以降14日ごとに繰り返す
  • Status=800→810報告完了になった時点で対象から自然に外れるStatusチェックのみで足りる

⑥のメッセージ文言確定・2026-09-06: 「再検査の受診・ご報告はお済みでしょうか。 まだの場合は固定メニューから「健康診断について」→「受診・再検査報告」よりご報告を お願いいたします。」(ボタンなし、固定メニュー経由での自発的な報告を促す形)

  • ①受診日のお知らせの差込変数 → 確定2026-09-06: 医療機関=Class003(検査機関)、 日時=Date001健康診断候補日、Status250→300時点はまだ本人未承諾のため確定日Date002ではなく 候補日を使う)、コース=Class004(一般検診/節目検診/人間ドック)、自己負担金額=Num001 (ラベルは「窓口清算予定」のままだが、この用途に流用)。オプション内容はClass007単独では なく、Class005(バリウム検査、胃カメラ/バリウム/検査不可の選択)+Class006 (追加オプション、希望する/希望しない)+Class007(オプション追加内容、Class006が 「希望する」の場合のみ続けて表示の3列を組み合わせて表示する
    • データ入力元 → 確認済み2026-09-06、フェーズ1マスタ508959確認: 508959 LINEWORKSアンケート管理ResultId 508965「【テスト】2026年度 健康診断」の 質問マッピングJSONDescription001)で、Class004(節目検診・人間ドック希望)/ Class005(バリウム検査について)/Class006(追加オプション希望有無)/Class007 (オプション希望内容、複数選択)/DescriptionA(その他希望)が実際にアンケート 回答項目として定義済みと確認。これらはフェーズ1LINEWORKSアンケートフォーム回答→ 508971反映由来のデータ。一方Class003(検査機関)・Date001(健康診断候補日)・ Num001自己負担金額はこのマッピングJSONに含まれておらず、会社側(管理者)が 予約手配・金額計算した上で別途入力する項目と判断できる(アンケートには社員本人が 答えられない情報のため)
    • フェーズ1↔フェーズ2の紐付けキー一致確認: 508959のClass002(ユーザー照合列)が "ClassC"に設定されており、508971のClassCPleasanterUserIdと完全一致。 フェーズ2の対象者解決ロジック2章「対象者解決の正しい照合ロジック」と同じキーを フェーズ1も使っており、整合性が取れている
  • ①⑤のメッセージ送信トリガー → 確定2026-09-06: 既存のHC-WPWebhookトリガー、 管理者が508971でProcessボタンを押した起点で統一する。①は250→300、⑤は500→800の Process実行時にHC-WPが起動し案内を送信する
  • ②Class001保険種類未設定時の扱い → 確定2026-09-06: 追加文言は付けない Class001 === "東京土建"の場合のみ追加、それ以外(空欄含む)は何もしない安全側の判定)
  • 固定メニューがグループトークで押された場合 → 確定2026-09-06、現行設計継続: 特別な考慮はしない。個人対話前提のまま。実際に開発検証用グループへBotが招待された 実績はあるが、Botとの1:1対話フロー自体はグループ内でも個人のuserId単位で成立するため、 想定外の対話フローになっても実害はないと判断
  • ⑤再検査通知の本文からテンプレ部分を削除 → 確定2026-09-06: 【再検査結果報告書】 のa〜d項目説明テンプレは、実際の4項目収集がBot対話「2. 受診/再検査報告」Status=800時の 順次アンケート)で行われることになったため不要。本文は案内のみに簡略化する 具体的な新本文はExcel「メッセージ設定」シート⑤参照、「受診・再検査報告」の選び方を 案内する形に変更)
  • ①送信時の必須項目チェック → 確定2026-09-06: 医療機関Class003・日時Date001等が 未入力のまま管理者が①のProcessボタンを押せないよう、ProcessのValidateInputsで必須指定する。 Process定義250→300ValidateInputsに該当列を追加すること
  • 複数レコードヒット時の異常系 → 確定2026-09-06: 従来「Bot応答は保留」としていたが、 ユーザーには何も返さず放置するのではなく、エラー文言を返信する方式に変更 (例:「複数の対象レコードが見つかりました。お手数ですが管理者にお問い合わせください。」)。 6章「エラーハンドリング・異常系」の記述を更新すること
  • HC-SUBの役割整理 → 廃止・HC-WAへ吸収2026-09-07確定: button_template転換により 「4カテゴリいずれかの対話完了時にProcess実行固定文言の結果案内」という役割はHC-WA 自身で完結できるため、HC-SUBは独立したワークフローとして維持せず廃止し、HC-WAに機能を 統合する。ワークフローが1つ減りシンプルになる
  • 共通処理の実装方針 → 確定2026-09-06: HC-WA/HC-WP/HC-REMINDERの間で共通する処理 504412照合ロジック・JWT取得等はSub-workflow化せず、各ワークフローに個別実装する n8n運用ルールのード数抑制方針と、Execute Workflow呼び出しのオーバーヘッド回避を優先。 既存のHC-WA/HC-WPも同様の重複実装方針
  • HEALTHCHECK_REMINDER_DAYS_BEFOREの型 → 確定2026-09-06: workflow_config_valuesの 他のキーと同じ文字列型("3"で統一。n8n側でNumber()変換して使用する
  • 就業判定_可/不可410→500/510 → 確定2026-09-06: 自動判定ロジックはなし。 管理者/産業医が508971のClass053就業判定を見て、手動でProcessボタンを押して 遷移させるBot対話フローには含まれない、管理者操作のみ
  • 診断書ファイル名規則 → 本番採用確定2026-09-06: {年度エリア(ClassZ)}_診断書_ {名前(ClassC)}.{拡張子}。「課題1」節に記載済みの規則をそのまま正式採用する
  • 「完了」Process500→900・810→900 → 管理者手動のみ2026-09-07確定: 自動化は 今回のスコープ外とし、管理者が手動でProcessボタンを押す運用に一本化する 実装済みのProcess定義Id13/14、「追加したボタン」実行種別はこの方針と一致済み
  • 診断書ファイル名の重複対策 → 確定2026-09-06: {年度エリア(ClassZ)}_診断書_ {名前(ClassC)}.{拡張子}規則に、複数ファイル送信時は連番を付与する ..._1.pdf, ..._2.pdfのように送信順で採番)
  • LINEWORKS退職者からのメッセージ → 考慮不要2026-09-06: 504412のCheck062 LINEWORKS在籍フラグによる判定は不要。退職済みであればLINEWORKSアカウント自体が 削除されておりBotへメッセージを送れないため、対象外ケースとして扱う必要がない
  • 対象レコード0件新入社員等 → 確定2026-09-06: 固定メニュー「健康診断について」を 押した際、508971に対象レコードが1件もない場合は「対象の健診情報がありません」と返信する (複数ヒット時のエラー文言とは別扱い、正常系の一種として処理)
  • 再検査通知500→800の判断基準 → 確定2026-09-06: 管理者が508971のClass052 (健康診断結果)を見て手動判断する。就業判定と同様、自動判定ロジックはなし
  • 日程変更Date002再設定時の管理者通知 → 不要2026-09-06確定: 508971画面で 確認できれば十分なため、別途通知の仕組みは作らない
  • 診断書提出完了Status=410〜就業判定500/510の間 → Bot側は何もしない 2026-09-06確定: 産業医・管理者の判断待ちの間、Botからのアクションは発生しない
  • 同時進行セッション制限 → 確定2026-09-06: 1ユーザーにつき1つの待機状態のみを 想定する(bot_conversation_stateは1レコード=1行のまま。診断書提出フローと 再検査報告4項目アンケートを同時に進行することはないそもそも対象Statusが異なるため 同時発生しない)
  • HC-WPの汎用化 → 確定2026-09-06: ①⑤専用の実装にせず、Process名・DisplayName・ DescriptionPleasanter Process定義の実フィールド名。旧「ツールチップ」という呼称は 誤りだったため訂正、376872実行予算WF申請のprocesses.json実例で確認済み)をgetsiteから 取得してそのまま送信する汎用構造にする。新規の通知パターンExcel「メッセージ設定」 シートに今後追記される想定が増えても、508971へProcessを1つ追加するだけでn8n側の 改修なしに対応できるようにする4節「フロー定義」の既存方針と同じ考え方をHC-WP全体に適用
  • 条件分岐文言の実現方式 → 確定2026-09-06: ②「東京土建の人のみ追加文言」のような 条件分岐は、Description欄に条件分岐込みのテンプレート文字列を書けるようにし、HC-WP側で レコード値を見て解釈・置換してから送信する(具体的なテンプレート構文は実装時に確定。 例: {{#if Class001=='東京土建'}}資格確認証を必ずご持参ください。{{/if}}のような 記法を想定)。Descriptionは376872の実例では管理者向けメモとして使われていたが、 健康診断Botでは「Bot案内文言そのもの」を書く用途に転用する
  • ④再提出依頼 → 確定2026-09-06: Excelの丁寧な文言「診断結果をお送りいただきましたが、 画像での送信でしたので、PDFで再度お送り頂きますようおねがいいたします。」に統一する。 「3. 診断書提出」節のPDF判定失敗時メッセージ旧「PDF形式でアップロードしてください」を この文言に置き換える
  • ⑦日程未確定の催促新規・確定、2026-09-07: ①日程通知Status 250→300を送信後、 ユーザーが日程確定(固定メニュー「健診日程」から承諾/変更に応答しないまま1日経過したら 催促を送信する。以後も未確定の間は1日ごとに繰り返し送信する⑥再検査報告の催促と同じ 「起算点を都度リセットして一定間隔で繰り返す」方式、間隔だけ2週間→1日に短縮
    • 起算点管理: 508971に新規列Date004(ラベル「日程通知日」、Date003と同様の運用)を追加 空き列で確認済み、2026-09-07。Process「日程通知済み」250→300実行時のDataChanges でDate004へ送信日をセットする
    • 日次リマインダーワークフローHC-REMINDER、毎日12:00実行Date004 + 1日 = 今日かつ Status=300のレコードを検出したら催促送信 → 送信後、Date004を「今日」に更新
    • Status=300→310日程確定になった時点で対象から自然に外れるStatusチェックのみで足りる
    • メッセージ文言はExcel「メッセージ設定」シートに追記する本節では扱わない
  • ⑤再検査通知: Status 500→800再検査通知。返信は「a.再検査受診日b.受診医師名/ c.検査項目、結果概要d.就労の可否」の4項目テキスト入力形式。既存のawaitInput date/file/yesno_confirm/schedule_confirm)にない新パターンのため、 4項目をまとめて受け付ける新しい待機状態例: report_form)の追加が必要。 保存先列 → 確定・反映済み2026-09-06: a〜dの4項目は個別列に分けず、ユーザーが 入力したテキストをまとめて1つの欄にそのまま保存する方式。508971のClass055 (再検査就業判定)の直後にDescriptionG(ラベル「再検査報告」)を新規追加済み (スクリプト: .claude/js/site-scripts/健康診断管理/add-descriptionG-508971.js)。 なおCheckA(ラベル「再検査連絡」)が既存で確認済みのため、⑤送信後の「再検査連絡に チェック」処理はこのCheckAtrueにすればよい
  • 東京土建の人のみの追加文言(②)→ 確定: 508971のClass001(ラベル「保険種類」、 ChoicesText:"東京土建\n協会けんぽ")で判定。ClassHash.Class001 === "東京土建"の場合のみ 「資格確認証を必ずご持参ください。」を本文末尾に追加する

別途対応済み今回のBot専用化に伴う設定変更

  • workflow_config_valuesへ健康診断専用キー4件追加: HEALTHCHECK_LW_CLIENT_ID / HEALTHCHECK_LW_CLIENT_SECRET / HEALTHCHECK_LW_SERVICE_ACCOUNT / HEALTHCHECK_BOT_ID(=13078741)
  • LINEWORKS_BOT_SECRETを実値へ更新Callback URL設定用
  • Pleasanter 484184LINEWORKS Bot管理へ「健康診断Bot」レコード登録ResultId 513223
  • n8n Credential新規作成: 「LINEWORKS Bot Private Key健康診断Bot専用o2f2ljohvI62iBOvユーザーがn8n UI上で手動登録
  • HC-SUB/HC-WAのJWTード・コード内の認証情報参照LW_BOT_CLIENT_ID等の共用キー、 CredentialHw0qlEaGfLPnQWp1を上記の専用キー・専用Credentialへ差し替え → 完了 2026-09-07。下記「n8n実装フェーズ2完了」節参照

n8n実装フェーズ2完了2026-09-07

本ファイルの確定設計に基づき、n8nワークフロー本体を全面実装した。トークにBotを送る 利用者がまだ存在しないフェーズ2運用未開始ことを確認した上で、本番稼働中だった 旧設計Express移植直後のpendingProcesses方式を安全に全面書き換えした。

実装済みワークフロー

ワークフロー ID 状態 内容
HC-WA: LINEWORKS応答受信 0i0Ze3Gq0Waof3Fa active、11ード 全面書き換え。対象者解決2段階照合504412 ClassA⇔Class011・固定メニュー/button_template・3カテゴリ絞り込み・awaitInput拡張none/date/file/schedule_confirm/yesno_confirm/report_form・担当者連絡導線・診断書添付ダウンロードPleasanterアップロード・キャンセル共通仕様・3回失敗強制中断・10分タイムアウト対応lastFileReceivedAt記録
HC-WP: Statusプッシュ通知 swXfpoDtwZDT3Hwk active、8ード 全面書き換え。Process定義のDescription欄をテンプレートとして解釈(プレースホルダー置換+{{#if 列名=='値'}}条件分岐、504412経由の宛先解決、専用認証キーで送信。HC-SUB非依存化
HC-SUB: プロセス実行と案内送信 XRqcykbG2LuAjGG2 廃止・deactivate 役割をHC-WA/HC-WPへ吸収design-fixed-menu.md「HC-SUBの役割整理」確定事項通り。ワークフロー自体は削除せず無効化のみ
HC-SETUP: 固定メニュー登録 0jVVF9WGlZrAygXX active、編集済み・実行は未実施 actions配列を「健康診断について」1ボタンから「健康診断について」「担当者に連絡」の2ボタンへ編集済み。本番の固定メニューへの反映Webhook実行はユーザー確認の上、後日実施
HC-REMINDER: 日次リマインダー送信 kyyd1BHpUJkJSN3W 新規作成、inactive 毎日12:00 Schedule Trigger。②受診日アラートDate002-3日・③受診日当日Date002当日、返信をyesno_confirm(attendance_310)として予約・⑥再検査報告の催促Date003+14日、送信後Date003更新・⑦日程未確定の催促Date004+1日、送信後Date004更新を統合
HC-DOC-TIMEOUT: 診断書提出10分タイムアウト監視 ayXtZbP2jqVXaWyR 新規作成、inactive 10分間隔Schedule Trigger。lastFileReceivedAtから10分経過したawaitInput=file行を検出し、添付1件以上ならProcess診断書_保存実行通常の完了メッセージ、0件なら対象外のまま

【バグ修正】HC-WPの「検証」ードでheaders/body参照先が誤っていた2026-09-07発見・修正

実データでの動作テスト中、HC-WP Webhookを叩くと必ずUnauthorized: invalid API key (修正後はBad Request: resultId, processId は必須です)で失敗する不具合を発見。原因は 「検証」ノードのコードが$input.first()(=直前ノード「設定値一括取得」の出力、 {configKey, configValue}形式の行データ)を参照していたため、headersbodyも 存在せず常に検証に失敗していた。実際にWebhookが受信したheaders/bodyを得るには $('Webhook').first()と明示的にード名指定する必要があるHC-WA等では正しくこの形に なっていたが、HC-WPの「検証」ードだけ書き換え漏れがあった$('設定値一括取得').all()で 値自体は正しく取得できていたData Table Get自体は正常ため、APIキーの値そのものを 疑って文字コードレベルまで比較して初めて気づいた。修正後、HC-WP WebhookresultId=513409, processId=5{"result":"ok"}が返り、実機で正常動作を確認。

【未解明】ProcessId明示指定でのAPI実行時、一部DataChangesが発火しない

実データテスト中、実行種別「追加したボタン」のProcessId1〜3等ProcessIdを指定した API実行でNum列DataChangesが正しく発火したが、以下の2ケースでは発火しなかった:

  • 実行種別「追加したボタン作成・更新」ExecutionType:20のProcessId4:検査機関確定): ProcessId明示実行でStatus遷移250→260は成功したが、Num047のDataChanges InputValue型は発火しなかった
  • Id5日程通知済み: Num035InputValue型は発火したが、Date004InputDate型は 発火しなかった

InputValue型とInputDate型で挙動が違う、あるいは実行種別によって挙動が違う可能性があるが、 未検証・未解明。回避策として、これらのDataChangesが必要な場合は該当列をDateHash/ NumHashで明示的に直接updateする運用でカバーできる実データ検証時に実施。今後、 本番運用特に260への自動遷移・①日程通知のDate004起算点管理)でこの制約が問題になる 場合は、n8n側でProcess実行後に該当列を明示更新する処理を追加する等の対応を検討すること。

Data Table healthcheck_bot_statejqMDa2YZTI4f0iQ7)の変更

列構成を新設計に合わせて変更済み: targetEmaillineworksUserIdにリネーム、pendingProcesses列削除、 formDraftfailCountlastFileReceivedAt列を新規追加(最終列構成: resultId, lineworksUserId, currentStatus, awaitInput, awaitProcessId, awaitColumn, formDraft, failCount, lastFileReceivedAt。 変更時点で既存データ0件のため移行作業は不要だった。

未実施・残作業

  • HC-SETUPの実行固定メニュー2ボタン化を本番へ反映完了2026-09-07。 固定メニューは「健康診断について」「担当者に連絡」の2ボタン構成で本番反映済み Webhook実行、HTTP 201確認済み
  • LINEWORKS Bot API疎通確認完了2026-09-07。野木健一郎さんPleasanterUserId 460宛に、504412照合→専用Credentialでのアクセストークン取得→LINEWORKS Bot API送信、 という新実装の中核経路で一時テストワークフロー経由のテキスト送信を実施し、実機のトークで 受信を確認済みテストワークフローは実行後deactivate
  • 実データでの動作確認各Process実行・各awaitInput分岐・添付アップロード等、Bot対話の 一連の流れそのもの)は未実施
  • HC-REMINDER・HC-DOC-TIMEOUTのactivateSchedule Trigger起動は、実運用開始タイミングに 合わせて別途判断
  • workflow_config_valuesHEALTHCHECK_REMINDER_DAYS_BEFORE=3は今回追加済み
  • NodeSrv/apps/n8n/docs/n8n-guide.md(機密ファイル)を今回の変更内容 HC-WA/HC-WP全面書き換え・HC-SUB廃止・HC-SETUP実行・HC-REMINDER/HC-DOC-TIMEOUT新規作成・ 専用Credential使用・healthcheck_bot_state列構成・PLEASANTER_MASTER_SITE_ID_PRODの 誤記訂正)に合わせて更新済み

【方式転換】日程通知メッセージの組立を508971側クライアントスクリプトに一本化

n8nHC-WP側でitems/getによりProcess.Descriptionのテンプレートを解決する実装 resolve.jsのfillTemplateでは、Class003検査機関等の外部マスタ項目がResultId (内部値、例:「511926」のまま返り、表示名例:「日の出ヶ丘病院」)に変換されない不具合が あった実機のLINEWORKSトークで「医療機関511926」と表示される形で顕在化

対応として、n8n側でのテンプレート解決をやめ、508971のクライアントスクリプトで、担当者が 検査機関確定情報を保存する時点(画面に表示名が確定している時点)で通知文を組み立て、 DescriptionB列に保存しておく方式に変更した。日程通知HC-WPは組立済みのDescriptionB の値をそのまま送信するだけでよく、n8n側でのマスタ名称解決が不要になり確実性も上がる。

実装内容2026-09-07、508971へ反映済み:

  • Pleasanter/健康診断管理/configs/production/site-508971_社員別健康診断管理/scripts/2_検査機関確定通知文組立.js (クライアントスクリプト新規追加): $p.events.before_send_Updateで発火。Class003(検査機関)・Class004(コース)・ Class005(バリウム検査)・Class007(オプション追加内容、複数選択)は $('#Results_' + ColumnName).find('option:selected').text()で選択中の表示名を 取得(複数選択は区切りで結合)。Class006(追加オプション、希望する/希望しない、 マスタ参照でない選択肢)も同じselectパターンで取得。Date001Num001$p.getControl(...).val()で取得(画面表示形式のままでよいため変換不要。ただしNum001 はカスタム書式適用済みで既に¥0のような通貨記号付き文字列になっているため、末尾に 「円」を追加すると二重表記になる → 追加しない、そのまま出力に修正済み)。 検査機関・日程・コースの3項目が揃っていれば組み立てて$p.set($p.getControl('DescriptionB'), ...) で保存。
  • 508971のサイト設定にDescriptionB列を新規追加(LabelText: "検査機関確定通知文")、 EditorColumnHash.GeneralDescriptionAの直後に配置。Processesには一切触れていない OnClickフィールド事故の教訓を踏まえ、Columns/EditorColumnHash/Scriptsへの追記のみで、 Process配列は現状の17件をそのままコピーして送信
  • 反映用スクリプト: Pleasanter/.claude/js/site-scripts/健康診断管理/add-clientscript-notice-508971.js (新規追加時)、update-clientscript-notice-508971.jsBody更新時。いずれも --execute未指定時はプレビューのみで実際には送信しない安全策付き。
  • 動作確認: 513409野木健一郎さん、検査機関日の出ヶ丘病院で確定済みのレコードで Seleniumから保存ボタン#UpdateCommand)をクリックし、items/get APIで DescriptionHash.DescriptionBを直接確認。以下の内容で正しく組み立てられることを確認済み:
    医療機関:日の出ヶ丘病院
    日時2026/09/08 10:11
    コース:その他:そのた1
    バリウム検査:その他:そのた2
    追加オプション:希望する(その他:そのた3、便潜血、胃カメラ、前立腺、子宮頸がん)
    自己負担金額¥0
    
    変更がありましたらこちらのLINEに連絡ください
    
  • staging環境はこのプロジェクトに存在しない健康診断管理/configsproductionのみ)ため、 本番508971へ直接検証した。Processesを一切変更しない種類の変更Columns追加・ EditorColumnHash配置・Scripts追記であり、過去のOnClick事故Processオブジェクトを ゼロから構築した場合のみ発生)とはリスクの種類が異なると判断した。

完了2026-09-07: HC-WPswXfpoDtwZDT3Hwkード「レコード・Process・宛先解決」resolve.jsからfillTemplate・getsite呼び出し・Processes全件検索ロジックを撤去し、 ProcessIdごとに固定の取得方法Id5:検査機関確定通知 → record.DescriptionHash.DescriptionB をそのまま使用、Id11:再検査通知 → 固定文言をn8nコード内に直書きmessageTextを組み立てる 実装に簡略化してPUT反映済みupdatedAt: 2026-09-07T11:25:20.492Z。これにより508971への getsite呼び出しColumns/Processes全件を含む重いレスポンスが不要になった。

残作業: 今後Id5・Id11以外のProcessでもHC-WP経由の通知が必要になった場合、 resolve.jsFIXED_MESSAGESまたはProcessId分岐に追記が必要(対応する Description列を508971側にも用意すること

【設計確定】日程通知→日程確定は「キャッチボール」として自動連続、他カテゴリは非連続2026-09-07

固定メニュー「健康診断について」タップ起点の対話フロー164-165行目参照とは別に、 ①日程通知HC-WP、ProcessId=5実行時の直後は、日程確定/変更のbutton_template (承諾/来週も同じ曜日/再来週も同じ曜日/担当者に連絡)も自動で続けて送信する方式に 確定した。本人が固定メニューから「健診日程」を選び直さなくても、通知を受け取った流れの まま即座に承諾・変更できる(「日程通知↔日程確定はキャッチボールなので連続してよい」との 判断)。受診・再検査報告/診断書提出等、他のカテゴリはこれまで通り非連続(本人が 固定メニューから能動的にアクセスする既存フローのまま)。

実装内容2026-09-07、HC-WP swXfpoDtwZDT3Hwkへ反映済み、8→10ードに拡張:

  • resolve.jsード「レコード・Process・宛先解決」: 返却値にprocessIddate001record.DateHash.Date001)・currentStatusrecord.Status)を追加
  • send.jsード「アクセストークン取得・LINEWORKS送信」: 通知文(messageText)を text送信した直後、processId===5の場合のみ、HC-WA「健診日程」タップ時と同一の button_templatesendButtons相当、formatDateJp/addDaysIsoロジックをこのノード内に 複製)を続けて送信するよう拡張。送信後はnextAwaitInput="schedule_confirm"nextFormDraft=JSON.stringify({date001})を返す(processId!==5なら"none"のまま)
  • 新規ード「IF: 日程確定待ちにするか」(nextAwaitInput === "schedule_confirm"で分岐)→ Trueの場合のみ新規ード「日程確定待ち状態セット」n8n-nodes-base.dataTablehealthcheck_bot_stateへupsert、HC-WA「状態更新」ードと同じ列構成を実行してから Respond to Webhookへ。Falseはそのまま直接Respond to Webhookへ
  • 動作確認済み513409、野木健一郎さん: Webhook実行→通知文button_templateが 連続してLINEWORKSトークに届くことを確認。healthcheck_bot_stateawaitInput: "schedule_confirm", formDraft: {"date001":"2026-09-08T10:11:00"}が 正しくupsertされることも確認済み

【未解決・次回続き】HC-WA側「承諾」応答処理でエラー、原因はn8n Task Runnerのcrypto制限

上記のbutton_templateで「承諾」を押しても、HC-WA0i0Ze3Gq0Waof3Fa)側の処理が エラーで止まり、Pleasanter側Date002・Statusが更新されない不具合が発生し、 未解決のままセッション終了

判明した原因: HC-WAの「署名検証・対象レコード特定」ードidentity.js相当)で LINEWORKS Webhookの署名検証HMAC-SHA256、x-works-signatureヘッダー検証)に require("crypto")を使っていたが、n8nの実行環境がTask Runner方式に変わっており、 CodeードからrequireでNode.js組み込みモジュールを読み込むこと自体が許可されなくなっている Error: Module 'crypto' is disallowed)。

1回目の対処不十分だった: require("crypto")をやめ、requireなしで使えるグローバルの Web Crypto APIcrypto.subtle.importKey/crypto.subtle.signでHMAC-SHA256計算に 書き換えてPUT反映した。しかし再テストすると別のエラーcrypto is not defined [line 24]と なり、このn8n Task Runner環境ではグローバルのcryptoオブジェクト自体も公開されていない と判明したWeb Crypto API化だけでは解決しない

次回セッションで検討すべき対応案(いずれも未着手、方針未確定):

  1. pure JS実装への置き換え(推奨候補): requireにもグローバルcryptoにも依存しない、 JavaScriptのみで書かれた軽量なHMAC-SHA256/SHA-256実装60〜100行程度をコード内に 直接埋め込む。ワークフロー構造・Credential追加が不要で、このード内だけで完結する
  2. n8n組み込みCryptoードn8n-nodes-base.crypto)を使う: HMAC操作に対応しているが、 専用のCrypto CredentialHmac Secretを別途作成する必要があり、Webhookの生ボディ (バイナリ)を正しく渡せるか要検証。ワークフロー構造の変更(ノード追加)を伴う
  3. インフラ側でNode.js組み込みモジュールを許可する (環境変数NODE_FUNCTION_ALLOW_BUILTIN=crypto等をn8nのTask Runner側に設定: 影響範囲がn8n全体他の全ワークフローに及び、コンテナ再起動が必要になる可能性が 高いため、最終手段として位置づけ。まずは1.のコード側対応を優先すべき

セッション終了時点の状態(次回再開時の前提):

  • HC-WA0i0Ze3Gq0Waof3Fa)は現在このバグを含んだまま本番稼働中(active: true)。 署名検証に失敗する=現状は本人からの返信を一切処理できない状態
  • 513409野木健一郎さん: Status=300のまま、Date002は未設定1899-12-30=未設定 センチネル値のまま)。healthcheck_bot_stateの該当行はawaitInput: "schedule_confirm" のまま未消費。次回、identity.js側のcrypto問題を解決した後にもう一度「承諾」を 送信すれば、このまま処理が流れるはずPleasanter側・Data Table側の状態リセットは 不要、そのまま続きから検証できる)
  • HC-WP側日程通知→button_template連続送信は正常動作を確認済み、今回のバグとは無関係
  • n8n実行履歴: HC-WA実行ID 363・364がstatus: errorlastNodeExecuted: "署名検証・対象レコード特定"

Botトークフロー再設計2026-09-10確定・2026-09-11実装完了

2026-09-10-bot-flow-redesign.md(承認済み仕様書)・2026-09-10-bot-flow-redesign-plan.md 実装計画に基づき、「健康診断メニュー」3択受診日時について受診結果について 再検査についてへの呼称統一とパターンA受診日時・パターンB受診結果確認の 新規実装を全面反映した。実装前に判明した以下2件の緊急バグも合わせて修正済み。

実装前に修正した緊急バグ2件2026-09-11

  • resultId型エラーによる無限リトライ: 「署名検証・対象レコード特定」ノードが resultIdをPleasanter ItemIdのNumber型のまま渡していたため、後段「IF: resultIdあり」 ノード(typeValidation:strictのstring.notEmpty演算子が型エラーでワークフロー全体を 異常終了させ、Webhookレスポンス未返却→LINEWORKS側リトライ→同一メッセージ重複送信を 引き起こしていた。resultId: String(record.ResultId)に修正
  • LINEWORKS自動送信イベント"利用開始"への無条件反応: LINEWORKSがBotとのトーク開始・ グループ招待時に自動送信する定型テキスト"利用開始"を、ユーザーの実発言と誤認識して 無条件応答(「対象の健診情報がありません」「待機状態が不正です」等)を返していた。 content.text === "利用開始"を検知しresolveError: "system_event"として無反応にする 分岐を追加

いずれも発覚時点で健康診断関連Webhook全件HC-WA/HC-SETUP/HC-FORM-SYNC/HC-WPを 一時deactivateして対応した。

実装内容HC-WA 0i0Ze3Gq0Waof3Fa、ノード「分岐処理・実行・送信」)

  • PROCESS_ID.SELF_ARRANGE自分手配、508971 Process Id:18を追加
  • replaceDateLineInDescription/formatDateTimeSlash: DescriptionBの「日時」行のみを 確定日で書き換えるヘルパー
  • buildHospitalContactMessage: 511924受診病院一覧をResultIdで1件取得し、病院名 ClassB・電話番号ClassD・担当者ClassF、任意を組み立てて返す。1件にヒット しない場合は「検査機関へお問い合わせください。」にフォールバック
  • 「受診日時について」Status 300: 候補日提示+承諾/受診日時の変更/自分手配、 Status 310: DescriptionB照会受診日時の変更
  • 「受診結果について」Status 310: 受診完了/未受診、Status 400: 診断書提出フローへ直結)
  • 「再検査について」Status 800: 「受診・再検査報告」ボタンへの橋渡し)
  • 新規awaitInput状態retest_choice(未受診→再手配/自分手配の選択)・ reschedule_input(再手配時の新日時自由入力)を追加
  • yesno_confirmをpurpose横断schedule/reschedule/attendance_310の共通OPTIONS方式へ リファクタ
  • confirmSchedule共通関数化(承諾ルート・自由入力確定ルートの両方から呼ぶ、 スコープバグ回避のためトップレベル関数として定義)

HC-REMINDERkyyd1BHpUJkJSN3W、ノード「対象レコード取得・分類」)

kind:"three"(受診日当日リマインダー)のボタンラベルをはい/いいえから 受診完了/未受診へ変更HC-WA側のattendance_310判定と統一)。

Process「自分手配」(508971 Id:18) の設計修正

当初CurrentStatus=250で登録したが、Bot対話フローパターンA: Status=300、 パターンB未受診: Status=310からの呼び出しではCurrentStatus不一致で必ず400エラー (「要求が不正です」)になることが実機テストで判明。**CurrentStatus=-1任意 条件タブStatus in [300, 310]**に変更して解消ユーザーがPleasanter画面上で修正

実装漏れバグ(実機テスト中に発見・修正)

待機状態の妥当性検証リスト(["none","date","file","schedule_confirm","yesno_confirm","report_form"] に新規追加したretest_choicereschedule_inputを含め忘れており、未受診→再手配ルートの 2ステップ目で「待機状態が不正です」により強制リセットされる不具合があった。検証リストへ 両状態を追加して解消。

実機テスト結果2026-09-11、野木健一郎さん 513409、全シナリオ成功

  • シナリオA1承諾ルート: Status 300→310、Date002確定、DescriptionB書換確認
  • シナリオA2変更→自由入力→承諾: 検査機関連絡先表示→日付パース→確認→確定、Date002/DescriptionB正しく更新
  • シナリオA3自分手配: Status 300→400、Class003=513480自分手配
  • シナリオA4パース失敗3回: 3回目で強制中断メッセージ確認
  • シナリオB1受診完了: Status 310→400
  • シナリオB2未受診→再手配: 検査機関連絡先表示→新日時確定、Status 310のままProcessId無し更新維持確認
  • シナリオB3未受診→自分手配: Status 310→400、Class003=513480
  • シナリオB4診断書提出フローへの導線、Status=400時: 既存フロー無傷、PDF受付確認

テスト中、511924受診病院一覧のマスタが実機テスト当日に再構築されており、513409の 既存Class003値旧ResultIdが失効していたため、テスト時は514112実在値へ一時的に 書き換えて検証した(テスト後、スナップショットで元の値に復元済み)。

未対応事項

  • 診断書提出フローシナリオB4のテストで実際にPDFファイル1件を513409へ添付した (既存フローの動作確認が目的、削除要否は次回判断)
  • HC-REMINDERkind:"seven"(⑦日程未確定の催促)のメッセージ文言内に旧ラベル 「健診日程」への参照が残っている(固定メニューから「健康診断について」→「健診日程」より)。 ボタンラベル変更により古くなっているが、計画のスコープ外のため未修正

「担当者に連絡」実機テスト・文言修正2026-09-11

上記の一連の実機テストで未検証だった「担当者に連絡」を追加でテストした結果、 CONTACT_MESSAGEの文言が実際の窓口案内と不一致本節348-352行目の旧仕様のままと判明、修正した。

  • 旧: ご用の方は総務総合窓口へお問合せください🙇\nhttps://line.worksmobile.com/message/send?userNoList=800300000001350
  • 新: ご用の方は総務総合窓口へお問合せください🙇\n《総務・契約関連窓口》\nhttps://line.worksmobile.com/message/send?userNoList=800300000001350&version=25&type=counselor 《総務・契約関連窓口》行の追加、URLへ&version=25&type=counselorパラメータ追加)
  • HC-WA0i0Ze3Gq0Waof3Fa)のCONTACT_MESSAGE定数を修正しPUT反映済み。実機野木健一郎さん、 固定メニュー「健康診断について」経由のbutton_template内「担当者に連絡」で正しい文言・URLが 表示されることを確認済み