既存17Processと同じパターンでカウンタ列・DataChanges・Summaries設定を 508971/513156両サイトへ追加し、実機でフラグ立ちと集計テーブルへの 反映を確認した。 Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
141 KiB
健康診断Bot 対話メニュー機能 設計メモ(2026-09-06)
508971(社員別健康診断管理)× LINEWORKS Bot連携で、3機能(健診日程/受診・再検査報告/
診断書提出)を追加する設計。既存のhealthcheck-lineworks-survey-n8n-design.md
(HC-SUB/HC-WA/HC-WPの基本構成)を前提に、その上に対話メニュー方式を追加する。
ストレスチェックは対象範囲外(2026-09-07確定): 508971のCheckB(SC受診済)・
Class056(SC判定)は項目として残すが、運用(誰がいつどう更新するか)が未確定のため、
今回の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定義Description欄(Bot案内文の実体)の同期運用 → 確定
(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"、labelとtextを同一にする):
{
"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には 日付選択UI/datetimepickerアクションが存在しないため、ネイティブピッカーではなく ボタン+自由入力のハイブリッドで対応):{ "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実装の和暦・月日省略対応パースロジックを
流用して日付として解釈を試みる → パース成功時は即確定せず、「{パース結果の日付}で
よろしいですか?(はい/いいえ)」と確認を挟む(自由入力の誤爆防止、
awaitInputをyesno_confirm系の確認状態へ遷移) → 「はい」でDate002にセットしてProcess実行、 「いいえ」なら日程入力からやり直し。パース失敗時は「日付を認識できませんでした。 別の書き方でお試しください」と再案内。パース失敗が3回連続したら強制中断 (2026-09-07確定、診断書提出のPDF判定失敗時と同じ仕様): 待機解除し「日付を 認識できないため、いったん受付を中断します。固定メニューから「健診日程」を 選び直してください」と案内(失敗回数カウンタはbot_conversation_stateで管理。 選び直したタイミングでカウンタはリセット) - キャンセルワード → 待機解除
- 承諾ワード(「承諾」「OK」等)受信 → Date001の値をそのままDate002へコピーして
Process
- 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. 再検査受診日:{回答}でよろしいですか?(はい/いいえ)」と確認
(
awaitInputはreport_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の回答}
対象Status(310・800)以外: 「現在対象外です」(ただし「表示メニューの絞り込み」節参照。 そもそもボタン自体を出さない設計に変更したため、この分岐は主に固定メニュー経由の 直接テキスト送信等イレギュラー入力への保険として残る)
3. 診断書提出(診断書_*)
- Status=400時のみ有効。ボタン押下 → 「診断書をPDFでスキャンしてアップロードして ください。写真は不可です。表裏が別ファイルの場合は複数枚送信できます。 すべて送り終わったら「完了」と送信してください。」
- ファイル受信のたびに次を実施:
- PDF判定(後述「PDF判定方式」参照)。PDF以外 → 「診断結果をお送りいただきましたが、
画像での送信でしたので、PDFで再度お送り頂きますようおねがいいたします。」と再案内、
待機継続(受信済みファイルは破棄せず保持)。PDF以外の受信が3回連続したら強制中断
(2026-09-06確定): 待機解除し「PDF形式での送信が確認できないため、いったん
受付を中断します。固定メニューから「診断書提出」を選び直してください」と案内
(
bot_conversation_stateに失敗回数カウンタが必要、report_formの一時保存と 同様の仕組みで管理)。固定メニューから「診断書提出」を選び直したタイミングで 失敗カウンタ・受信済みファイル一覧ともにリセットされる(2026-09-06確定) - PDF確認OK → ダウンロード→Pleasanter添付アップロード(Attachmentsへ追加、 Process実行はまだしない)→「1件受け付けました。続けてファイルがあれば 送信、なければ「完了」と送信してください」と返す
- PDF判定(後述「PDF判定方式」参照)。PDF以外 → 「診断結果をお送りいただきましたが、
画像での送信でしたので、PDFで再度お送り頂きますようおねがいいたします。」と再案内、
待機継続(受信済みファイルは破棄せず保持)。PDF以外の受信が3回連続したら強制中断
(2026-09-06確定): 待機解除し「PDF形式での送信が確認できないため、いったん
受付を中断します。固定メニューから「診断書提出」を選び直してください」と案内
(
- 「完了」受信 → アップロード済み件数が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で確認済み)。
コンテンツダウンロードAPI(GET /v1.0/bots/{botId}/attachments/{fileId})も
302リダイレクト後の最終レスポンスヘッダー仕様が公式未記載のため、以下の
二段判定で実装する(実機確認しだい調整可):
- ダウンロード後のレスポンスヘッダー
Content-Typeがapplication/pdfなら確定 - 上記が取得できない/一致しない場合、ファイル本体の先頭バイトを見て
マジックナンバー
%PDF(0x25 0x50 0x44 0x46)で判定するフォールバックを入れる
キャンセル共通仕様
どのawaitInput状態でも、テキスト入力の先頭で「キャンセル」「やめる」「戻る」「中止」 「取消」「cancel」「stop」(大文字小文字区別なし)のいずれかのワード一致を最優先チェックし (2026-09-06、「中止」「取消」および英語表記を追加確定)、一致したら待機状態をクリアして 「メニューからやり直してください」と返す。
担当者への連絡導線(2026-09-07追加)
自由入力での意図判別が難しいテキストベースの相談要望(日程調整の個別事情等)に対応するため、 選択肢(固定メニュー・button_template)に「担当者に連絡」を常設し、選ばれたら固定の案内 メッセージを返す方式で対応する。
構成:
- 固定メニュー(persistentmenu)を「健康診断について」「担当者に連絡」の2ボタン構成に 変更する
- button_templateで選択肢を提示する全箇所の末尾に、共通で「担当者に連絡」ボタンを追加する
(対象3箇所、いずれも最大10ボタンの制限に対し余裕あり。LINEWORKS公式ドキュメント
bot-send-buttonで最大10ボタンと確認済み):- 「健康診断について」タップ後の3択(健診日程/受診・再検査報告/診断書提出)→4択に
- 「健診日程」の候補日提示(承諾/来週も同じ曜日/再来週も同じ曜日)→4択に
- 「受診・再検査報告」(Status=310時)の受診確認(はい/いいえ)→3択に
- 「担当者に連絡」受信時の挙動は、経由した入口によって分ける(2026-09-07確定):
- button_template内の選択肢として選ばれた場合(4択・3択の一部)→ それまでの対話の
待機状態(
awaitInput)はリセットせず維持したまま、案内メッセージだけ追加で返す (今の対話の一部としての相談、元のフローはそのまま続けられる) - 固定メニューから直接選ばれた場合 → 待機状態(
awaitInput)もリセットしてから 案内メッセージを返す(対話を中断してでも相談したい、という利用シーンのため)
- button_template内の選択肢として選ばれた場合(4択・3択の一部)→ それまでの対話の
待機状態(
- 固定メニューの「担当者に連絡」は、対象者解決(504412⇔508971照合)を含め、 「健康診断について」と同じ処理フローを通す(特別扱いしない、2026-09-07確定)。 対象レコード0件(新入社員等)の場合は既存ルール通り「対象の健診情報がありません」が 返る
- 対象外: 診断書提出(ファイル受信待ち)・受診/再検査報告の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}/update、AttachmentsHash:{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→300(Bot通知)は従来通り担当者がボタンを押す手動実行のまま(将来的にn8n側の
別ワークフローで自動化する可能性があるが未確定)。
「追加したボタン/作成・更新」実行種別の発動条件 → 確定(2026-09-07、ユーザーが実機の設定画面で確認):
「現在の状況」(CurrentStatus)がレコードの実際のStatusと一致し、かつ「条件」タブの
フィルタ条件に合致した場合のみプロセスが処理される(両方を満たさないと発動しない)。
250→260のProcessをCurrentStatus=250(申込中)で作成しておけば、Status=260到達後に
同レコードを再度編集・保存してもCurrentStatus不一致のため再発火しない。
一方、「入力検証」タブ(ValidateInputs)はこの実行種別では処理されない(適用されるのは
「追加したボタン」実行種別のみ)。そのためClass003・Date001・Class004の必須化は
ValidateInputsではなく「条件」タブのフィルタ条件で表現する必要がある(旧記述の
「ValidateInputsが自動実行の発火条件として機能する」は誤り、下表の想定Process一覧を訂正)。
Num031~046対応表(確定・反映済み)
| Num | 項目 | Status | 初期値 |
|---|---|---|---|
| 031 | 新規登録人数 | 100 | 1(DefaultInput、新規作成時に自動セット) |
| 032 | アンケート発行 | 200 | 0 |
| 033 | アンケート回答 | 210 | 0 |
| 034 | 申込中 | 250 | 0 |
| 047 | 検査機関確定 | 260 | 0(2026-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のSummaries(513156への集計設定)へ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「力検査」はデータ不備による表記(先頭の「聴」が欠落)と判明。 実態は労働安全衛生規則の健診項目「聴力検査(その他の方法による検査を含む)」で、 実運用では聴力検査を1000Hz/4000Hz/その他(オージオメータ以外の方法)の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~17(13件): スクリプト
add-processes-batch1-508971.js(Status遷移+OnClickのみの 単純グループ12件)・add-processes-batch2-508971.js(ValidateInputs・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を試験追加した
形式と同じ(InputValue、ValueFormulaNotUseDisplayName/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):Class003・Date001・Class004が全部値ありならCheckCをtrueに セットする。構造は社内実例(新版営業積算システム504322「状況Class062自動同期 スクリプト」)の{Title,Name,BeforeCreate,BeforeUpdate,Body,Id}形式で裏付け済み - Process「検査機関確定」(Id4)の
View.ColumnFilterHashを{"Class003":[...],"Date001":[...], "Class004":[...]}(選択肢列挙)から{"CheckC":"true"}(単純な条件)へ置き換え - これにより511924・513284へ新しい選択肢を追加してもProcess側のメンテは一切不要になった
- スクリプト:
.claude/js/site-scripts/健康診断管理/add-checkc-and-fix-process260-508971.js
運用上の注意:
(2026-09-07、CheckC方式への変更により解消・撤回。以後この対応は不要)Class003・Class004は選択肢を配列で静的に列挙しているため、
511924「受診病院一覧」・513284「検診種別マスタ」へ新しい選択肢を追加するたびに、
検査機関確定ProcessのView.ColumnFilterHashも更新しないと、新しい選択肢を選んだ
レコードだけ発火条件から漏れる。病院・コース追加時のチェックリストに
「検査機関確定Processの条件更新(add-process-260-508971.jsの再実行)」を含めること。
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遷移・DataChanges(Num列含む)・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と同一(Class003・Date001・Class004、2026-09-07確定)。3列とも入力済みであることを発火条件にする |
| 日程通知済み | 260→300(HC-WP経由でBot通知)。**Class003=「自分手配」(ResultId 513480)の |
||
| レコードは対象外**(専用トークフロー未確定、2026-09-07追加) | Num035=1 | **Class003(検査機関)・Date001 |
|
(健康診断候補日)・Class004(コース)を必須化(確定・2026-09-06、①送信メッセージの |
|||
差込変数が空欄のまま送信されるのを防ぐ)。Class005/Class006/Class007は任意 |
|||
| (オプション自体が任意選択のため) | |||
| 日程_確定 | 300→310(Bot対話) | Num036=1 | Date002(確定日、必須) |
| 報告_受診済み | 310→400(Bot対話) | Num037=1 | なし |
| 診断書_保存 | 400→410(Bot対話) | Num038=1 | AttachmentsA(必須) |
| 就業判定_可 | 410→500 | Num039=1 | なし |
| 就業判定_不可 | 410→510 | Num040=1 | なし |
| 再検査通知 | 500→800(HC-WP経由でBot通知) | Num041=1、Date003(再検査通知日)に送信日をセット、 |
|
CheckA(再検査連絡)をtrueに |
なし(⑤本文は固定文言のみで差込変数なし) | ||
| 報告_再検査受診済み | 800→810(Bot対話) | 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列に対するInputValue(Value:"1"等)の実例はあるため 類推は成り立つが、Num列で同様に動作する確証はない。Num031~047のカウンタ更新 DataChangesは、実装時にユーザーが実機で1件だけ試験設定し、動作確認してから残りに 展開すること(前節「実装の役割分担」参照)
【重大障害・原因判明】OnClickフィールドをAPI経由で指定すると個別レコード画面が
全件開けなくなる(2026-09-07発生・解決)
API経由でProcess定義17件を作成した際、OnClickフィールドに"$p.ex.processScript($(this));"
(実行種別「追加したボタン」用の一般的な値、社内189112実例のコメントから引用したもの)を
明示的にセットしたところ、当該Processを1件でも含めるだけで508971の個別レコード編集画面が
全件(対象レコードに関わらず)「指定された情報は見つかりませんでした」で開けなくなる障害が
発生した。一覧画面(グリッド)・API(get/update)は正常に動作し続けたため発見が遅れた。
原因: ユーザーがPleasanter画面上で同じ17件を手動登録したところ、生成されたJSONには
OnClickフィールドが一切含まれていなかった(実行種別が「追加したボタン」でも
「追加したボタン/作成・更新」でも同様)。189112実例で見えたOnClick値は、別の生成経路
(バージョン差・特殊な実装)による見た目上の値であり、汎用的にコピーしてよい値ではなかった。
追加検証(2026-09-07、ユーザーが画面上でProcess1のOnClick欄に同じ値
$p.ex.processScript($(this));を手動入力→保存): この場合は編集画面が壊れなかった
(Seleniumで513409の正常表示を確認)。つまりOnClickの値自体が悪いのではなく、
「API(updatesite)経由でOnClickフィールドを含むJSON全体を送信する」という経路自体に
問題があった(画面上の正規UIフローで保存されたOnClick値は無害)。根本原因の内部的な
メカニズム(Pleasanter側のバリデーション・整形処理のどこで衝突しているか)は未解明の
ままだが、実運用上の対処(下記ルール)には影響しない。
切り分け経緯: ServerScript疑い→Process4単体疑い→Processes全体除外で復旧確認→
バックアップから段階的に復元する二分探索でId2(アンケート回答)単体でも再現確認→
ユーザーが手動登録した17件と自分がAPI投入した17件のJSON構造を直接比較し、OnClickの
有無が唯一の違いと判明。切り分け作業はSelenium(pleasanter-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定義を新規にゼロから組み立ててAPI(
updatesite)経由で送信するのは避ける (今回の障害の直接原因)。新規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.js・add-condition-process4-508971.js・add-validateinputs-508971.js。いずれも対象ProcessのOnClickがundefinedであることを 確認してから処理する安全策を組み込み済み - 動作確認方法:
.claude/skills/pleasanter-selenium-html-scrapeスキル(Selenium)で 本番513409の個別編集画面を都度取得し、「指定された情報は見つかりませんでした」 (controller=errors)が出ないこと・HTMLサイズが正常範囲(約20万文字)であることを 確認する運用を今回確立した。同様の障害調査・確認作業でユーザーに手動確認を都度依頼する 代わりに使える
未確定・要検証事項(2026-09-06 調査・確定分)
- MIME種別/拡張子の取得方法 → 確定: 公式ドキュメント
bot-callback-messageでWebhookペイロード(content)にはfileIdのみが含まれ、fileName/mimeType等は ないことを確認。コンテンツダウンロードAPI(bot-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.textがMENU_*のいずれかに一致する場合を 固定メニュー起点の分岐として扱う実装でよい - 重大な設計誤り発見・訂正 → 完了(2026-09-06): 対象者解決の設計が誤っていたことが判明。
詳細は
NodeSrv/docs/superpowers/specs/2026-09-05-healthcheck-lineworks-survey-n8n-design.md2章「対象者解決の正しい照合ロジック」参照。LINEWORKSsource.userIdはメールアドレスではなく UUID形式で、社員・組織マスタ管理テーブル(SiteId 504412)のClassA⇔Class011経由の 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}/messagesのcontentに
{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はメッセージコンテンツの一種で別レイヤーのため併用可能)。
構成:
- 固定メニュー(Persistent Menu)はボタン1つだけに絞る: 「健康診断について」
(
textもラベルと同じ健康診断について。内部コード方式は不採用、button_template側と 合わせてラベル直接方式に統一) - ユーザーが固定メニューから「健康診断について」をタップ → 通常のテキストメッセージ
(
content.type:"text",content.text:"健康診断について")としてWebhookに届く - HC-WA側で
content.text === "健康診断について"を検知 → button_templateで 「ご用件を選んでください。」+3択(健診日程/受診・再検査報告/診断書提出)を返信 - 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択は送らない(フォールバック方式は不採用)。
理由: 任意テキスト受信への自動応答は、意図しないタイミング(雑談・誤送信等)でもメニューが
飛んでくる形になり、固定メニューという明確な入口を用意した意味が薄れるため。
待機状態あり(awaitInputがnone以外)での通常テキスト受信は、従来通りその待機中の
分岐処理(日付入力・はい/いいえ確認・ファイル受信等)に従う。
未確定(今後の検討事項):
- 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-WP(Webhookトリガー、
クライアントスクリプト起動)ではカバーできないため、新規に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等どの列から取るか)は 日次リマインダーワークフロー実装時に詳細化する
- リマインダー日数(②の「◯日前」)は全体共通の値とし、n8nの
⑥の正しい仕様(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実行時のDataChanges)に
Date003へ送信日をセット - 日次リマインダーワークフロー(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年度 健康診断」の
質問マッピングJSON(
Description001)で、Class004(節目検診・人間ドック希望)/Class005(バリウム検査について)/Class006(追加オプション希望有無)/Class007(オプション希望内容、複数選択)/DescriptionA(その他希望)が実際にアンケート 回答項目として定義済みと確認。これらはフェーズ1(LINEWORKSアンケートフォーム回答→ 508971反映)由来のデータ。一方Class003(検査機関)・Date001(健康診断候補日)・Num001(自己負担金額)はこのマッピングJSONに含まれておらず、会社側(管理者)が 予約手配・金額計算した上で別途入力する項目と判断できる(アンケートには社員本人が 答えられない情報のため) - フェーズ1↔フェーズ2の紐付けキー一致確認: 508959の
Class002(ユーザー照合列)が"ClassC"に設定されており、508971のClassC(PleasanterUserId)と完全一致。 フェーズ2の対象者解決ロジック(2章「対象者解決の正しい照合ロジック」)と同じキーを フェーズ1も使っており、整合性が取れている
- データ入力元 → 確認済み(2026-09-06、フェーズ1マスタ508959確認): 508959
(LINEWORKSアンケート管理)ResultId 508965「【テスト】2026年度 健康診断」の
質問マッピングJSON(
- ①⑤のメッセージ送信トリガー → 確定(2026-09-06): 既存のHC-WP(Webhookトリガー、 管理者が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→300)の
ValidateInputsに該当列を追加すること - 複数レコードヒット時の異常系 → 確定(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」節に記載済みの規則をそのまま正式採用する - 「完了」Process(500→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・
Description(Pleasanter 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「メッセージ設定」シートに追記する(本節では扱わない)
- 起算点管理: 508971に新規列
- ⑤再検査通知: 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(ラベル「再検査連絡」)が既存で確認済みのため、⑤送信後の「再検査連絡に チェック」処理はこのCheckAをtrueにすればよい - 東京土建の人のみの追加文言(②)→ 確定: 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 484184(LINEWORKS 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}形式の行データ)を参照していたため、headersもbodyも
存在せず常に検証に失敗していた。実際にWebhookが受信したheaders/bodyを得るには
$('Webhook').first()と明示的にノード名指定する必要がある(HC-WA等では正しくこの形に
なっていたが、HC-WPの「検証」ノードだけ書き換え漏れがあった)。$('設定値一括取得').all()で
値自体は正しく取得できていた(Data Table Get自体は正常)ため、APIキーの値そのものを
疑って文字コードレベルまで比較して初めて気づいた。修正後、HC-WP Webhook(resultId=513409,
processId=5)で{"result":"ok"}が返り、実機で正常動作を確認。
【未解明】ProcessId明示指定でのAPI実行時、一部DataChangesが発火しない
実データテスト中、実行種別「追加したボタン」のProcess(Id1〜3等)はProcessIdを指定した
API実行でNum列DataChangesが正しく発火したが、以下の2ケースでは発火しなかった:
- 実行種別「追加したボタン/作成・更新」(ExecutionType:20)のProcess(Id4:検査機関確定):
ProcessId明示実行でStatus遷移(250→260)は成功したが、
Num047のDataChanges (InputValue型)は発火しなかった - Id5(日程通知済み):
Num035(InputValue型)は発火したが、Date004(InputDate型)は 発火しなかった
InputValue型とInputDate型で挙動が違う、あるいは実行種別によって挙動が違う可能性があるが、
未検証・未解明。回避策として、これらのDataChangesが必要な場合は該当列をDateHash/
NumHashで明示的に直接updateする運用でカバーできる(実データ検証時に実施)。今後、
本番運用(特に260への自動遷移・①日程通知のDate004起算点管理)でこの制約が問題になる
場合は、n8n側でProcess実行後に該当列を明示更新する処理を追加する等の対応を検討すること。
Data Table healthcheck_bot_state(jqMDa2YZTI4f0iQ7)の変更
列構成を新設計に合わせて変更済み: targetEmail→lineworksUserIdにリネーム、pendingProcesses列削除、
formDraft・failCount・lastFileReceivedAt列を新規追加(最終列構成: 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のactivate(Schedule Trigger起動)は、実運用開始タイミングに 合わせて別途判断
workflow_config_valuesのHEALTHCHECK_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側(クライアントスクリプト)に一本化
n8n(HC-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パターンで取得。Date001・Num001は$p.getControl(...).val()で取得(画面表示形式のままでよいため変換不要。ただしNum001はカスタム書式適用済みで既に¥0のような通貨記号付き文字列になっているため、末尾に 「円」を追加すると二重表記になる → 追加しない、そのまま出力に修正済み)。 検査機関・日程・コースの3項目が揃っていれば組み立てて$p.set($p.getControl('DescriptionB'), ...)で保存。- 508971のサイト設定に
DescriptionB列を新規追加(LabelText: "検査機関確定通知文")、EditorColumnHash.GeneralのDescriptionAの直後に配置。Processesには一切触れていない (OnClickフィールド事故の教訓を踏まえ、Columns/EditorColumnHash/Scriptsへの追記のみで、 Process配列は現状の17件をそのままコピーして送信)。 - 反映用スクリプト:
Pleasanter/.claude/js/site-scripts/健康診断管理/add-clientscript-notice-508971.js(新規追加時)、update-clientscript-notice-508971.js(Body更新時)。いずれも--execute未指定時はプレビューのみで実際には送信しない安全策付き。 - 動作確認: 513409(野木健一郎さん、検査機関=日の出ヶ丘病院で確定済みのレコード)で
Seleniumから保存ボタン(
#UpdateCommand)をクリックし、items/getAPIでDescriptionHash.DescriptionBを直接確認。以下の内容で正しく組み立てられることを確認済み:医療機関:日の出ヶ丘病院 日時:2026/09/08 10:11 コース:その他:そのた1 バリウム検査:その他:そのた2 追加オプション:希望する(その他:そのた3、便潜血、胃カメラ、前立腺、子宮頸がん) 自己負担金額:¥0 変更がありましたらこちらのLINEに連絡ください - staging環境はこのプロジェクトに存在しない(
健康診断管理/configsはproductionのみ)ため、 本番508971へ直接検証した。Processesを一切変更しない種類の変更(Columns追加・ EditorColumnHash配置・Scripts追記)であり、過去のOnClick事故(Processオブジェクトを ゼロから構築した場合のみ発生)とはリスクの種類が異なると判断した。
完了(2026-09-07): HC-WP(swXfpoDtwZDT3Hwk、ノード「レコード・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.jsのFIXED_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・宛先解決」): 返却値にprocessId・date001(record.DateHash.Date001)・currentStatus(record.Status)を追加send.js(ノード「アクセストークン取得・LINEWORKS送信」): 通知文(messageText)を text送信した直後、processId===5の場合のみ、HC-WA「健診日程」タップ時と同一の button_template(sendButtons相当、formatDateJp/addDaysIsoロジックをこのノード内に 複製)を続けて送信するよう拡張。送信後はnextAwaitInput="schedule_confirm"・nextFormDraft=JSON.stringify({date001})を返す(processId!==5なら"none"のまま)- 新規ノード「IF: 日程確定待ちにするか」(
nextAwaitInput === "schedule_confirm"で分岐)→ Trueの場合のみ新規ノード「日程確定待ち状態セット」(n8n-nodes-base.dataTable、healthcheck_bot_stateへupsert、HC-WA「状態更新」ノードと同じ列構成)を実行してから Respond to Webhookへ。Falseはそのまま直接Respond to Webhookへ - 動作確認済み(513409、野木健一郎さん): Webhook実行→通知文+button_templateが
連続してLINEWORKSトークに届くことを確認。
healthcheck_bot_stateにawaitInput: "schedule_confirm",formDraft: {"date001":"2026-09-08T10:11:00"}が 正しくupsertされることも確認済み
【未解決・次回続き】HC-WA側「承諾」応答処理でエラー、原因はn8n Task Runnerのcrypto制限
上記のbutton_templateで「承諾」を押しても、HC-WA(0i0Ze3Gq0Waof3Fa)側の処理が
エラーで止まり、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 API(crypto.subtle.importKey/crypto.subtle.signでHMAC-SHA256計算)に
書き換えてPUT反映した。しかし再テストすると別のエラーcrypto is not defined [line 24]と
なり、このn8n Task Runner環境ではグローバルのcryptoオブジェクト自体も公開されていない
と判明した(Web Crypto API化だけでは解決しない)。
次回セッションで検討すべき対応案(いずれも未着手、方針未確定):
- pure JS実装への置き換え(推奨候補): requireにもグローバル
cryptoにも依存しない、 JavaScriptのみで書かれた軽量なHMAC-SHA256/SHA-256実装(60〜100行程度)をコード内に 直接埋め込む。ワークフロー構造・Credential追加が不要で、このノード内だけで完結する - n8n組み込みCryptoノード(
n8n-nodes-base.crypto)を使う: HMAC操作に対応しているが、 専用のCrypto Credential(Hmac Secret)を別途作成する必要があり、Webhookの生ボディ (バイナリ)を正しく渡せるか要検証。ワークフロー構造の変更(ノード追加)を伴う - インフラ側でNode.js組み込みモジュールを許可する
(環境変数
NODE_FUNCTION_ALLOW_BUILTIN=crypto等をn8nのTask Runner側に設定): 影響範囲がn8n全体(他の全ワークフロー)に及び、コンテナ再起動が必要になる可能性が 高いため、最終手段として位置づけ。まずは1.のコード側対応を優先すべき
セッション終了時点の状態(次回再開時の前提):
- HC-WA(
0i0Ze3Gq0Waof3Fa)は現在このバグを含んだまま本番稼働中(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: error(lastNodeExecuted: "署名検証・対象レコード特定")
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-REMINDER(kyyd1BHpUJkJSN3W、ノード「対象レコード取得・分類」)
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_choice・reschedule_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-REMINDER
kind:"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-WA(
0i0Ze3Gq0Waof3Fa)のCONTACT_MESSAGE定数を修正しPUT反映済み。実機(野木健一郎さん、 固定メニュー「健康診断について」経由のbutton_template内「担当者に連絡」)で正しい文言・URLが 表示されることを確認済み
パターンC・HC-WP実機テストで発見した追加バグ2件(2026-09-11)
- HC-WP側の①日程通知button_templateが旧仕様のまま: HC-WA branch.jsのボタンラベルは
「受診日時について」仕様に変更済みだったが、HC-WP(
swXfpoDtwZDT3Hwk、ノード 「アクセストークン取得・LINEWORKS送信」)内に複製されていた同等ロジック(processId===5の場合に続けて送るbutton_template)の更新が計画から漏れていた。旧ラベル「承諾/来週も 同じ曜日/再来週も同じ曜日」のまま送信される不具合を実機で発見、新ラベル 「承諾/受診日時の変更/自分手配」に修正しPUT反映・実機確認済み - 待機状態検証リストの漏れ(Task3/4実機テスト中に発見・修正済み): 「実機テスト結果」節 参照
パターンC実機テスト結果(2026-09-11、既存ロジック変更なし・正常動作確認)
シナリオ: Status=800→「健康診断について」→「再検査について」→「受診・再検査報告」→ a〜d 4項目回答(ボタンでの確認込み)→DescriptionG保存、Status 800→810、 「再検査の報告を受け付けました」で完了。全ステップ正常動作。
HC-WP実機テスト結果(2026-09-11)
- ①日程通知(Process 260→300、Webhook
healthcheck-status-pushにresultId/processId=5で POST): 通知文+button_template連続送信を確認(上記バグ修正後、新ラベルで正常表示) - ⑤再検査通知(Process 510→800、processId=11): 固定文言メッセージの送信を確認
bの質問文言変更(2026-09-11)
パターンC・受診/再検査報告4項目アンケートのb項目文言をユーザー指示により変更。
QUESTIONS.b: 「b. 受診医師名を教えてください」→「b. 受診病院および医師名を教えてください」
(LABELS.bは「受診医師名」のまま据え置き、質問文言のみ変更)。HC-WAへPUT反映済み。
①日程通知本文へタイトル行追加(2026-09-11)
ユーザー指示により、日程通知本文(DescriptionB、2_検査機関確定通知文組立.js)冒頭へ
タイトル行「■本年度の健康診断が手配されました」を追加。update-clientscript-notice-508971.js
で本番反映済み(HTTP 200)、Seleniumで513409編集画面の正常動作も確認済み。実際の組立動作は
次回このクライアントスクリプトが発火するタイミング(担当者が検査機関確定情報を画面保存した
時点)で確認される。
DescriptionBの構造変更: 「通知文」→「健康診断確定内容」本体のみ保持(2026-09-11)
ユーザー指示により、DescriptionBの性質を「通知文そのもの」から「健康診断確定内容の本体
データのみ」へ変更。冒頭のタイトル行・末尾の案内文は、Bot側で送信経路に応じて動的に
付加する方式にした(担当者からのプッシュ通知と本人による自発照会でタイトルを出し分ける
ため)。
2_検査機関確定通知文組立.js(508971クライアントスクリプト): タイトル行・末尾行を削除、 本体(医療機関/日時/コース/バリウム検査/追加オプション/自己負担金額)のみをDescriptionBへ保存するよう変更。update-clientscript-notice-508971.jsで本番反映済み- HC-WP(
swXfpoDtwZDT3Hwk、ノード「レコード・Process・宛先解決」):processId===5(①日程通知)のmessageText組立時、■本年度の健康診断が手配されました\n\n{DescriptionB}\n\n 変更がありましたらこちらのLINEに連絡くださいの形で動的に組み立てるよう変更 - HC-WA(
0i0Ze3Gq0Waof3Fa、ノード「分岐処理・実行・送信」): 「受診日時について」 Status=310時(本人が固定メニューから自発的に確定日を照会するケース)の表示を、■あなたの本年度の健康診断について\n\n{DescriptionB}\n\n変更がありましたらこちらのLINEに 連絡くださいの形で動的に組み立てるよう変更
3箇所ともPUT/updatesite反映済み。実機(野木健一郎さん、513409)で①日程通知(HC-WP経由、
「■本年度の健康診断が手配されました」表示)・本人照会(HC-WA経由、「■あなたの本年度の
健康診断について」表示)の両方を確認済み。confirmScheduleのreplaceDateLineInDescription
(「日時:」行の書き換え)はDescriptionBの構造変更後も正規表現ベースで問題なく動作すること
を確認済み。
未対応事項3件、全て対応完了(2026-09-11)
- テスト用添付PDF削除: 513409の
513158_診断書_460_1.pdf(シナリオB4テスト分)を ユーザーがPleasanter画面から手動削除(Attachments削除はAPI経由(DeleteAttachments・AttachmentsHash.AttachmentsA空配列いずれも試行)では反映されず、UI操作限定と判明) - HC-REMINDER
kind:"seven"文言修正: 「固定メニューから「健康診断について」→ 「健診日程」より」→「→「受診日時について」より」に修正、PUT反映済み - HC-WP再検査通知(Id:11)文言修正: 「固定メニューから「健康診断について」→ 「受診・再検査報告」を選び」→「→「再検査について」→「受診・再検査報告」を選び」 (新3段階導線に合わせて中間ステップを明記)、PUT反映済み
DescriptionB列のLabelText変更(2026-09-11、ユーザーがPleasanter画面で実施)
「通知文」→「健康診断内容」に変更(性質変更(上記「DescriptionBの構造変更」節参照)に
合わせた表示名変更)。内部列名DescriptionB自体は変更なし、n8n側コードは内部列名を
参照するため影響なし。
【バグ発見・修正】待機状態中に固定メニュー「健康診断について」を再タップすると誤動作(2026-09-12)
マニュアル用スクリーンショット撮影中に発見。手順: 513409(Status=310)で「受診日時について」 →照会表示(「■あなたの本年度の健康診断について」+受診日時の変更ボタン)→直後に固定メニュー から「健康診断について」を再タップ→想定は3択メニューの再表示だが、実際は 「日付形式で回答してください(例: 2026-03-01 や 令和6年3月1日)」という無関係な応答が返った。
根本原因(n8n実行履歴、execution 464/465のrunDataで特定): 「受診日時について」(Status=300
の候補日提示、Status=310の照会表示いずれも)はボタン提示後にawaitInput: "schedule_confirm"を
セットする。この待機状態中に来たテキストは、text === "承諾" / "自分手配" / "受診日時の変更"
のいずれにも一致しない場合、フォールバックとして自由入力の日付パース(parseDateInput)に渡る
実装になっている(「分岐処理・実行・送信」ノード306行目以降)。「健康診断について」の処理は
state.awaitInput === "none"のブロック内(224行目)にしか存在しないため、schedule_confirm等の
待機状態中は素通りされず、日付パースのエラーメッセージが返っていた。「担当者に連絡」・キャンセル
ワード(「キャンセル」「やめる」等)は待機状態に関わらず横断的に処理される共通仕様として実装
済みだったが、「健康診断について」自体は同様の横断処理から漏れていた。
修正: 「分岐処理・実行・送信」ノードの「キャンセル共通仕様」ブロック直後に、待機状態が
none以外かつテキストが「健康診断について」の場合、state.awaitInputを"none"へ書き換えて
から後続のメニュー表示ロジックへ自然にフォールスルーさせる処理を追加(2.5節として新設)。
これにより、schedule_confirm・yesno_confirm・report_form・retest_choice・
reschedule_inputいずれの待機中でも、「健康診断について」を選び直せば通常の3択メニューへ
戻れるようになった(進行中の入力は破棄され、キャンセルと同等の挙動になる。これは仕様として
妥当と判断)。HC-WAへPUT反映済み(2026-09-12 00:07 UTC)。実機再検証は未実施(撮影テスト自体を
中断、後日再開時に確認する)。
撮影テスト(2026-09-12-screenshot-test-plan.md)は担当者プッシュ通知(ケース6-1/6-2、
Status260→300→承諾→日程確定→メニュー3択表示)まで実施し、このバグ発見を機に一旦中断。
HC-WA/HC-WPは検証後の原則通りdeactivateへ戻した。取得済みスクリーンショットは
Pleasanter/健康診断管理/ScreenShot/に保存済み(①②通知本文+button_template、承諾→日程確定、
固定メニュー3択、Status=310照会表示、計6枚)。
撮影テスト再開(2026-09-12): 追加バグ2件発見・修正
上記の待機状態リセット修正確認を兼ねて撮影テストを再開。ケース1〜4(メニュー出し分け・受診日時 について・受診結果について・健康診断結果の提出)を実施し、以下2件を追加で発見・修正した。
1. テストデータ不整合(実装バグではない): 513409のClass003(検査機関)が511924に実在しない
ResultId 511926 を指しており、buildHospitalContactMessageが該当なしで空の連絡先メッセージ
(病院名・電話番号が空欄)を返していた。511924の実データを確認し、正しいResultId 514112
(日の出が丘病院 健診センター)へ手動update。以後の検証は正しい連絡先表示を確認済み。
Status=300へ戻す操作を繰り返す中でClass003が自分手配(513480)のまま残存するケースが再発し、
その都度514112へ再修正しながら撮影を続行した(テスト運用上の注意点として記録)。
2. 過去日付が日程確定できてしまう不具合(ユーザー指摘・2026-09-12): parseDateInputの
共通ヘルパーfinalizeDatePartsは実在日付かどうかのみ検証しており、過去日付でもそのまま
受理していた(例: 「2026年7月20日」が「2026-09-12」時点で承諾可能な候補として提示された)。
finalizeDatePartsに「今日(時刻0時基準)より前ならError("過去の日付は指定できません")」の
チェックを追加。tryParseEraDate・tryParseMonthDay・parseDateInputの全経路が
finalizeDatePartsを通るため、この1箇所の修正で全入力経路に反映される。HC-WAへPUT反映済み
(2026-09-12 04:44 UTC)。実機で「7/20」(過去日付)→「過去の日付は指定できません」を確認済み。
3. 文字化け修正(2026-09-11の緊急バグ修正時に混入): 日付3回連続失敗時の中断メッセージ
(awaitInput=schedule_confirm側)が「固定メニュー<EFBFBD><EFBFBD><EFBFBD>ら「受診日時について」を選び直して
ください」と文字化けしていた(await sendText.call(this, "...固定メニュー<E383A5><E383BC><EFBFBD>ら...")")。
同じ文言を持つretest_choice側(399行目、正しい表記)と比較して発見。「固定メニューから」に
修正し、ファイル全体を文字化け文字(U+FFFD)でスキャンして他に無いことを確認済み。HC-WAへ
PUT反映済み(2026-09-12 04:59 UTC)。実機でケース2-7(過去日付・存在しない日付・認識不能文字列
の3回連続失敗)を再現し、正しい文言での中断メッセージを確認済み。
いずれも撮影テストと並行してn8n実行履歴(execution runData)を都度確認しながら根本原因を 特定・修正する形で対応した。
4. CONTACT_MESSAGEが旧文言へ巻き戻っていた(撮影テスト完了後、ケース7のスクリーンショット
確認中に発見): ケース7(担当者に連絡)の実機スクリーンショットで、案内文言が
「ご用の方は総務総合窓口へお問合せください🙇\nhttps://line.worksmobile.com/message/send?
userNoList=800300000001350」という2026-09-11修正前の旧仕様のまま送信されていることが判明
(《総務・契約関連窓口》行と、URLの&version=25&type=counselorパラメータが欠落)。
2026-09-11時点で一度PUT反映済みのはずだったが、本セッション冒頭の緊急バグ修正(2.5節追加)で
n8nから再取得したワークフローJSONの時点で既に旧文言に戻っていた(反映が実際には反映されて
いなかったか、その後の操作で上書きされたか、原因は未特定)。正しい文言
ご用の方は総務総合窓口へお問合せください🙇\n《総務・契約関連窓口》\n https://line.worksmobile.com/message/send?userNoList=800300000001350&version=25&type=counselor
へ再修正し、HC-WAへPUT反映済み(2026-09-12 05:05 UTC)。教訓: 定数値の修正はPUT成功
レスポンスだけでなく、後続の別修正時に取得したワークフローJSON上で値が保持されているか
都度確認すること。次に「担当者に連絡」を撮影・検証する際は、この文言で実機確認すること
(今回はケース7実機スクリーンショット確認時点で旧文言のまま撮影済みのため、撮り直しが必要)。
HC-WA再activate→固定メニューから「担当者に連絡」を直接タップして撮り直し、正しい文言
(《総務・契約関連窓口》行+&version=25&type=counselor込み)を実機確認済み。続けてURL
リンクをクリックし、ブラウザ版LINEWORKSで「総務・契約関連窓口」トークルームへ正しく遷移する
ことも確認済み(マニュアル7章の導線説明に使える画像)。
撮影テスト完了(2026-09-12)
2026-09-12-screenshot-test-plan.mdの全ケース(1-1〜1-4、2-1〜2-8、3-1〜3-7、4-1〜4-3、
5-1〜5-6、6-1〜6-3、7-2+URL遷移確認)を実機で撮影完了。Pleasanter/健康診断管理/ScreenShot/
に計50枚保存済み(トーク一覧・固定メニュー単体・ファイル送信ダイアログ等の周辺画像を含む)。
撮影と並行してn8n実行履歴を都度確認しながら根本原因を特定する形で、上記4件のバグ・不整合
(待機状態リセット漏れ、テストデータ不整合、過去日付バリデーション欠如、文字化け、
CONTACT_MESSAGE巻き戻り)を発見・修正し、いずれも実機再検証済み。HC-WA/HC-WPは検証完了後
両方deactivateへ戻した。
残作業: テスト添付ファイル(513409の診断結果.pdf・診断結果.txt、ケース4検証分)は
Pleasanter画面から手動削除が必要(API削除は反映されないことを2026-09-11に確認済み)。
マニュアル(健康診断Bot機能_仕様(管理担当者向け).md)への画像挿入は次回対応。
撮影完了後の追加要望4件(2026-09-12、ケース4関連)
撮影完了後、実際にPleasanterへ保存された添付ファイル名を見たユーザーから、ファイル名規則・ 未対応ケースへの指摘が続き、以下4件を追加実装した。いずれもHC-WA/HC-WPへPUT反映・実機確認済み。
1. 診断書PDFファイル名の命名規則変更: 従来{ClassZ}_診断書_{ClassC}_{連番}.pdf
(例: 513158_診断書_460_2.pdf)は、ClassZ(実施年度エリア、外部マスタ513156参照)・
ClassC(名前、Users参照)いずれも内部の生ID(ResultId/UserId)がそのまま出力され、
担当者が見て意味不明な数値になっていた。ユーザー指定の新形式
{ClassZ表示名}■診断書■{ClassC表示名}({ClassD})_yyyyMMdd-hhmmss.pdfへ変更。
ClassZ表示名は513156のItemTitle(例:「2026■東京」)をAPI取得、ClassC表示名は
api/users/{userId}/getのNameをAPI取得、ClassDはレコード自身のフリガナ列をそのまま使用。
連番方式(既存添付件数+1)からアップロード時刻ベースへ変更(複数人が同時アップロードしても
衝突しない)。半角スペースは全て除去(.replace(/ /g, ""))。
実機確認: 2026■東京■診断書■野木健一郎(ノギケンイチロウ)_20260912-142512.pdf。
2. タイムスタンプのタイムゾーン修正: 上記1のタイムスタンプが当初n8nサーバーのシステム
時刻(UTC)でGMT基準になっていた不具合。new Date(Date.now() + 9*60*60*1000)+UTC系
getterでJST(UTC+9)に変換する実装へ修正。
3. ステータス「診断書保存」(410)でもPDF再提出できるよう対応: 従来、Status=410では
固定メニュー「健康診断について」が「現在ご案内できる項目はありません」を返し、提出済み後に
誤ったファイルを送ってしまった場合等の再提出手段がなかった(ユーザー指摘)。「受診結果に
ついて」ボタンの表示条件・処理条件(メニュー出し分け・text分岐両方)へcurrentStatus===410
を追加し、Status=400と同じPDF提出フローへ合流させた。ただし「完了」時のProcess実行
(PROCESS_ID.DOCUMENT_SAVE、400→410)はStatus=400の場合のみに限定(410で再実行すると
CurrentStatus不一致でエラーになるため)。実機確認: Status=410で「受診結果について」→
PDF再提出案内→送信→受付完了、いずれも正常動作。
4. 担当者操作「診断書の再提出依頼」プロセス新設(Id19): 担当者が能動的に「診断書に
不備があるので再提出してほしい」と伝えるための新規Process。ユーザーがPleasanter画面上で
手動登録済み(CurrentStatus:-1、条件タブStatus in ["400","410"]、ChangedStatus:410
=実質Status変化なし)。Description欄(通知文言)が未設定だったため、API経由で追記:
「健康診断結果の再提出をお願いいたします。\n\n固定メニューから「健康診断について」→
「受診結果について」を選び、PDFを再度送信してください。」。HC-WP「レコード・Process・
宛先解決」ノードのFIXED_MESSAGESへ19のエントリを追加(タイトル行「■健康診断結果の
再提出について」を冒頭付加)し、PUT反映済み。「アクセストークン取得・LINEWORKS送信」
ノードのnextAwaitInput分岐はprocessId===5限定のため、processId=19は影響なし(単純な
テキスト送信のみ、待機状態も変更しない)。実機確認: Process19実行→HC-WP Webhook
(processId=19)→「■健康診断結果の再提出について」文言が正しく届くことを確認済み。
【重要】Process実行→HC-WP通知の連携が手動2段階だった問題を解消(2026-09-12)
これまでの運用(①日程通知・⑤再検査通知・⑲診断書再提出依頼、いずれも)は「①Pleasanter画面で Process実行→②担当者が別途n8n Webhookを手動でPOST」という2段階だった(設計時点で「現状は 手動。将来n8n側で自動化する可能性あり、未確定」と記載していた未解決事項)。本番運用では 担当者がcurl等を叩けないため、このままでは機能しない。
対応: 508971にユーザーが新規用意したクライアントスクリプト「プロセス実行スクリプト」
(configs/production/site-508971_社員別健康診断管理/scripts/3_プロセス実行スクリプト.js、
全17→19件のProcessのOnClickへ$p.ex.processScript($(this));を追加済み)へ、Process実行
前にHC-WP Webhookを自動POSTする処理を追加した。
- OnClickスクリプトはProcess本体の処理(Status遷移・DataChanges)より前に実行される
(ユーザー確認済み)。
$p.execProcess()はページ遷移を伴うため、実行後にWebhookを叩く 設計は成立しない。よって通知は必ずexecProcess呼び出し前に行う - Process 5(日程通知済み)・11(再検査通知)・19(診断書再提出依頼)のswitch文case内で
confirmAndNotify(procName, $p.id(), procNum)を呼び、確認ダイアログ→HC-WP Webhook POST (https://n8n32.next-hd.net/webhook/healthcheck-status-push、resultIdは$p.id()で取得) →失敗時はalertしてプロセス自体を中断(returnでcase内から関数全体を抜けるため、後続の$p.execProcessは実行されない。ユーザーからの懸念に対し、JS仕様上switch内のreturnは breakと異なり外側の関数から脱出することを確認済み) - 全Processで共通して、実行前にコメント欄へ「実行者:氏名(UserId:xxx)/プロセス:名前」を
記録する処理を追加。Pleasanter標準の
#Comments要素へ$p.set()でセットしておくと、execProcessによるレコード更新と同時にコメントとして保存される(ユーザー提供の他サイト 実装例$p.set($('#Comments'), history);に倣った。api/items/{id}/updateへCommentパラメータを直接POSTする方式は試したが反映されず不採用——Hashネストしないフラットな パラメータが黙って無視される8章の既知挙動と同様の非対称動作)
反映は.claude/js/site-scripts/健康診断管理/update-clientscript-process-508971.js
(update-clientscript-notice-508971.jsと同一パターン、Title="プロセス実行スクリプト")で実施。
事故: 実装中にget-site-config.js --env=productionを実行してキャッシュを更新した際、
個別ファイル抽出処理によりローカル編集中の3_プロセス実行スクリプト.jsが本番の未反映
(編集前)内容で上書きされる事故が発生(設計時点で既知だった「クライアントスクリプトの
ローカル編集後にget-site-config.jsを再実行すると上書きされる」パターンそのもの)。編集を
再適用して復旧。実機確認は未実施(次回、担当者がPleasanter画面からProcess5/11/19いずれかを
実行し、LINEWORKS通知とコメント記録の両方が機能するか確認すること)。
実機テストで発見・修正した2件の追加バグ(2026-09-12)
1. $btn is not defined: 雛形コード37行目let procName = $btn.text()...が未定義変数
$btnを参照していた(引数名はproccessButton)。ユーザーが$p.ex.processScript = async function (target) { let $btn = $(target); if (!$btn.length) {...return false;} ... }の形へ
修正($btn.lengthチェック込み)。以降$btn[0].id・$btn.text()とも正しく動作。
2. ブラウザからのWebhook直叩きがCORSでブロック: fetch()でHC-WP Webhookを直接POSTすると
Access to fetch ... has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is presentで失敗
(サーバー間のcurl/node実行では発生しない、ブラウザ固有の制約)。HC-WP Webhookノードの
parameters.optionsへallowedOrigins: "*"を追加しPUT反映して解消(n8n Webhookノード標準の
CORS設定。ユーザー承認の上で実施——自動モード分類器が「Security Weaken」でブロックしたため
AskUserQuestionで確認を取った)。
実機確認完了: Process5「日程通知」(ユーザーがDisplayNameを「日程通知済み」→「日程通知」
へ変更済み)をPleasanter画面のボタンクリックのみで実行し、①確認ダイアログ→②HC-WP Webhook
自動POST→③LINEWORKS通知(「■本年度の健康診断が手配されました」+候補日確認ボタン)が
担当者の手動Webhook操作なしで届くことを確認。Status「日程通知済み」への遷移、コメント欄への
「実行者:野木 健一郎(UserId:xxx)/プロセス:日程通知」自動記録も確認済み。これにより
Process実行→通知の連携が完全自動化され、前回セッションで挙げた最優先の未実装課題(A)が
解消した(2026-09-12-screenshot-test-plan.md作成時点では手動2段階操作だった)。
フェーズ2残課題の検討・実機テスト(2026-09-12)
前回セッションで挙げた残5項目のうち、HC-REMINDER(日次リマインダー4種)の実機テストに着手。
n8n Public APIにはSchedule Triggerワークフローの手動実行手段が無い(POST /workflows/{id}/run
は405)ため、n8n UI上の「Execute workflow」ボタンをユーザーが手動で押す形で実施した。
前提確認: n8nコンテナのタイムゾーン
Schedule Triggerのcron式0 12 * * *が「JST 12:00」を意図しているか懸念があったため、SSH
(ubuntu@dokploy45.next-hd.net、ユーザー承認の上で読み取り専用のdateコマンドのみ実行)で
n8n-rga09v-n8n-1コンテナ内を確認。GENERIC_TIMEZONE・TZともAsia/Tokyo設定済みで、
コンテナのシステム時刻自体もJSTだった。Schedule Triggerは正しくJST 12:00に発火する設計で
問題なし(懸念は杞憂)。なお以前確認した「ファイル名タイムスタンプがGMTになるバグ」は
別レイヤー(Task RunnerのCode node実行環境)の話で、日付境界(JST 0〜9時)を跨がない限り
実害は無いと判断。
②受診日アラート・③受診日当日
513409のStatus=310・Date002を「今日+3日」「今日」にそれぞれ調整しExecute workflowで実行。
いずれも実機で正常送信を確認。③では届いた「受診完了/未受診」ボタンに実際に「受診完了」を
タップし、HC-WA側のattendance_310purpose処理(既存のyesno_confirmハンドラ)が正しく動作
してStatus 310→400へ遷移することも確認済み。
⑥再検査報告の催促: 文言バグ発見・修正
Status=800・Date003=「今日-14日」で実行したところ、送信文言が「固定メニューから「健康診断
について」→「受診・再検査報告」よりご報告を」となっており、実際の遷移(「健康診断について」
→「再検査について」→「受診・再検査報告」の3段階)と一致していなかった(2026-09-11に⑦
(kind:"seven")だけ同種の文言修正を行い、⑥(kind:"six")を見落としていた)。
「対象レコード取得・分類」ノードのkind:"six"メッセージへ「→「再検査について」」を追加し
PUT反映。実機で修正後の正しい3段階文言、およびパターンCへの導線(a質問まで到達)を確認済み。
⑦日程未確定の催促: Date004列が存在しないバグ発見・修正
Status=300・Date004=「今日-1日」を設定して初回実行した際、targetsが空のまま何も送信され
なかった。Pleasanter APIでレコードのDate004を直接確認したところnullのまま——508971の
SiteSettings.ColumnsにDate004列自体が定義されていなかった(DateA=生年月日、Date001〜
Date003は別用途で使用中、Date004は無し)。設計時点(2026-09-07、design-fixed-menu.md
「⑦日程未確定の催促」新規追加時)に列追加を忘れていた不具合で、機能自体が実装当初から
一度も動作していなかったことになる。
対応(ユーザー承認の上、updatesiteで実施):
SiteSettings.Columnsへ{ColumnName:"Date004", LabelText:"日程未確定催促送信日"}を追記EditorColumnHash.GeneralのDate003直後へ"Date004"を挿入(列追加のみではitems/updateで値が書き込めず、過去のNum039〜046・CheckC等の列追加時と同様、EditorColumnHashへの配置も 必須と判明——1回目のCoumns追記のみのupdateではDateHash.Date004へ値を送っても反映されずnullのままだった)
修正後、実機で「健診日程のご連絡はお済みでしょうか。まだの場合は固定メニューから「健康診断 について」→「受診日時について」よりご確認をお願いいたします。」の正常送信を確認済み。
Date004の役割: ⑦の起算点管理用。「Status=300のままDate004+1日=今日」が送信条件で、
送信の都度Date004を送信日(今日)へ更新するため、Status=300が続く限り毎日連続で催促が
飛ぶ設計。本来はProcess5(日程通知済み、260→300遷移)実行時に自動セットされるべきだが、
既知の未解明課題(「Id5のNum035は発火するがDate004(InputDate型)は発火しない」、本ファイル
「【未解明】ProcessId明示指定でのAPI実行時、一部DataChangesが発火しない」節)が残っており、
現状は自動セットされない。今後、n8n側でProcess5実行時にDate004を明示更新する処理を追加する
(HC-WPまたはクライアントスクリプト側)か、この既知課題自体を解決する対応が別途必要。
HC-REMINDERの4パターン(②③⑥⑦)すべて実機確認完了。
HC-DOC-TIMEOUT実機テスト: n8n Data Tableノードの重複返却バグを発見・修正
Status=400・PDF1件送信済み(lastFileReceivedAtセット済み)の状態で10分経過後にExecute
workflowを実行したところ、実機に「診断書を受け付けました。」が届いた(結果的に1通のみ)。
ただしn8n実行履歴を確認したところ、「対象抽出」ノードのtargets配列に同一行
(513409、healthcheck_bot_stateには1行しか存在しない)が45件重複していることが判明。
「待機中(file)取得」ノード(n8n-nodes-base.dataTable、operation:"get"・filters・
returnAll:true)の生出力を直接確認したところ、45個の完全に同一のアイテムが返っていた
(Pleasanter側のn8n Public API GET /data-tables/{id}/rowsで直接確認すると1件のみ)。
n8n Data TableノードのreturnAll:true使用時に同一行を重複して返す不具合と判断。
実際にLINEWORKSへ届いたのが1通のみだった理由: 「実行」ノードのfor (const target of targets)ループが45回中1回目でStatus 400→410(Process 8実行)に遷移させ、2回目以降は
同一resultIdへ同じProcessId=8を再実行しようとしてCurrentStatus不一致エラーとなり、
try/catchのcontinueで握りつぶされたため(sendTextはupdate成功後にのみ呼ばれる
設計だった)。たまたま実害を免れただけで、異なるresultIdが複数同時に対象となる
状況では重複送信が実際に発生しうる、根本的に修正が必要なバグだった。
修正: 「対象抽出」ノードのstateRows取得直後にresultIdでユニーク化する処理を追加
(Setで既出resultIdを弾く)。HC-DOC-TIMEOUTへPUT反映済み。
他ワークフローへの影響確認: 同じData Table(healthcheck_bot_state)をoperation:"get"・
returnAll:trueで読む箇所はHC-WAの「待機状態取得」ノードにもあるが、コード側が
stateRows[0]と最初の1件のみ参照する設計のため実害なし。HC-REMINDER/HC-WPの
workflow_config_values取得もObject.fromEntriesでキー集約するため実害なし。複数の
異なるresultIdをforループで個別処理する設計だったHC-DOC-TIMEOUTのみが実害リスクを
抱えていたため、修正はこの1箇所で十分と判断。
再検証完了: 修正反映後、PDF再送信→10分経過→Execute workflow実行(execution 564)で
「対象抽出」のtargetsが正しく1件のみになっていることをn8n実行履歴で確認済み。「実行」
「状態リセット」ノードとも1件のみ処理・実機に「診断書を受け付けました。」が1通のみ届いた。
HC-DOC-TIMEOUTの重複バグ修正・実機確認、完了。inactiveへ戻した。
なお、HC-DOC-TIMEOUT(10分間隔*/10 * * * *)自体は現在active:falseのまま
(今回の検証はすべてn8n UIの「Execute workflow」手動実行)。実運用で自動化するには
別途activate判断が必要(Task「全ワークフロー本番activate」に含める)。
Process19「診断書再提出依頼」にカウンタ列(Num047)を追加・集計テーブル反映(2026-09-12)
フェーズ2残課題の1つとして、Process19の実行回数集計が必要かユーザーに確認したところ 「必要」との回答。既存17Process(Num031〜046)と同一パターンで以下4点を反映した。
- 508971:
ColumnsへNum047(ラベル「診断書再提出依頼」、単位「人」)を追加、EditorColumnHash._Tab-2(カウンタタブ)の末尾へ配置 - 508971: Process19の
DataChangesへ{Type:"InputValue", ColumnName:"Num047", Value:"1"}を追加(既存Process同様、実行有無を示す0/1フラグとして機能。同一レコードで 複数回実行しても値は1のまま=累積加算ではない。年度エリア単位の合計人数は3.のSummaries 機能が別途算出する設計) - 508971:
Summariesへ{SiteId:513156, DestinationColumn:"Num047", LinkColumn:"ClassZ", Type:"Total", SourceColumn:"Num047"}を追加(既存Num031〜046と同一パターン、508971の Num047をClassZ=実施年度エリアをリンクキーに513156(実施年度-集計サイト)の対応 レコードへ合計集計する) - 513156:
Columnsへ508971と同一のNum047列を追加、EditorColumnHash.GeneralのNum046直後へ配置
実機確認: 513409でProcessId:19を直接実行し、508971側Num047が1(フラグ立ち)、
513156側(実施年度エリア513158=「2026■東京」)のNum047も1へ正しく集計されることを
確認済み。過去のNum列追加時の教訓(Columns定義だけではitems/updateで値が書き込めず、
EditorColumnHashへの配置が必須)を踏まえ、両サイトとも配置まで一括で実施したため
今回は一度で正常動作した。