From 08a0b87dcf2a9772ab93b2ef243b74c4413f544f Mon Sep 17 00:00:00 2001 From: Kenichiro NOGI Date: Sat, 5 Sep 2026 14:04:06 +0900 Subject: [PATCH] =?UTF-8?q?=E5=AE=9F=E8=A3=85=E8=A8=88=E7=94=BB=E3=81=ABTa?= =?UTF-8?q?sk13(=E7=A4=BE=E5=93=A1=E3=83=9E=E3=82=B9=E3=82=BF504412?= =?UTF-8?q?=E7=85=A7=E5=90=88=E3=83=AD=E3=82=B8=E3=83=83=E3=82=AF)?= =?UTF-8?q?=E3=82=92=E8=BF=BD=E5=8A=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit メールアドレス整合性チェック・フリガナ補完の判定/補完ロジックを TDDで実装するタスクを追加。実行タイミング(保存時/定期バッチ/ 手動)は未確定のため、呼び出しトリガーは意図的にスコープ外とし、 決まり次第別タスクとして追加する方針を明記した。 Co-Authored-By: Claude Sonnet 5 --- ...-09-05-healthcheck-lineworks-survey-n8n.md | 138 ++++++++++++++++++ 1 file changed, 138 insertions(+) diff --git a/NodeSrv/docs/superpowers/plans/2026-09-05-healthcheck-lineworks-survey-n8n.md b/NodeSrv/docs/superpowers/plans/2026-09-05-healthcheck-lineworks-survey-n8n.md index a448aa1c..fbea1ab2 100644 --- a/NodeSrv/docs/superpowers/plans/2026-09-05-healthcheck-lineworks-survey-n8n.md +++ b/NodeSrv/docs/superpowers/plans/2026-09-05-healthcheck-lineworks-survey-n8n.md @@ -1257,10 +1257,148 @@ git commit -m "feat: 508971にStatusプッシュ通知用クライアントス --- +### Task 13: employeeMasterCheck.js — 社員マスタ(504412)によるメール整合性チェック・フリガナ補完ロジック + +設計書8章(Bot対話フローとは独立した補助機能)に対応。**実行タイミング(保存時/定期バッチ/手動)はまだ決まっていない**ため、本タスクは判定・補完の純粋ロジックとテストのみを作る。504412へのAPI呼び出しをどこから叩くか(クライアントスクリプト/n8n Schedule Trigger/Process)は、タイミングが決まった時点で別タスクとして追加する。 + +**Files:** +- Create: `NodeSrv/apps/healthcheck-survey-bot/src/lib/employeeMasterCheck.js` +- Test: `NodeSrv/apps/healthcheck-survey-bot/test/employeeMasterCheck.test.js` + +**Interfaces:** +- Consumes: なし(Task 3〜6とは独立) +- Produces: + - `checkEmailConsistency(pleasanterEmail: string, masterRecord: {Class036?: string, ClassB?: string}): { consistent: boolean, masterEmail: string | null }` + - `resolveKanaFromMaster(masterRecord: {Class003?: string, Class004?: string}): string` + - `needsKanaFill(currentKana: string | null | undefined): boolean` + +`masterRecord`は504412の`api/items/{id}/get`レスポンスの`ClassHash`(`Class011`=ユーザID、`Class036`=PLメールアドレス、`ClassB`=メールアドレス、`Class003`=姓(カナ)、`Class004`=名(カナ)を含む)を想定する。整合性チェックは`Class036`(PLメールアドレス)を優先し、無ければ`ClassB`にフォールバックする。 + +- [ ] **Step 1: 失敗するテストを書く** + +```javascript +// test/employeeMasterCheck.test.js +const { test } = require("node:test"); +const assert = require("node:assert"); +const { + checkEmailConsistency, + resolveKanaFromMaster, + needsKanaFill, +} = require("../src/lib/employeeMasterCheck"); + +test("checkEmailConsistency: PLメールアドレス(Class036)と一致すればconsistent:true", () => { + const result = checkEmailConsistency("taro.yamada@next-hd.co.jp", { + Class036: "taro.yamada@next-hd.co.jp", + ClassB: "taro.yamada@example.com", + }); + assert.deepStrictEqual(result, { consistent: true, masterEmail: "taro.yamada@next-hd.co.jp" }); +}); + +test("checkEmailConsistency: Class036が無ければClassBにフォールバックする", () => { + const result = checkEmailConsistency("taro.yamada@example.com", { + ClassB: "taro.yamada@example.com", + }); + assert.deepStrictEqual(result, { consistent: true, masterEmail: "taro.yamada@example.com" }); +}); + +test("checkEmailConsistency: 不一致ならconsistent:false", () => { + const result = checkEmailConsistency("taro.yamada@next-hd.co.jp", { + Class036: "different@next-hd.co.jp", + }); + assert.deepStrictEqual(result, { consistent: false, masterEmail: "different@next-hd.co.jp" }); +}); + +test("checkEmailConsistency: マスタ側にメールが無ければmasterEmail:null・consistent:false", () => { + const result = checkEmailConsistency("taro.yamada@next-hd.co.jp", {}); + assert.deepStrictEqual(result, { consistent: false, masterEmail: null }); +}); + +test("resolveKanaFromMaster: 姓カナ+名カナを空白区切りで結合する", () => { + assert.strictEqual( + resolveKanaFromMaster({ Class003: "ヤマダ", Class004: "タロウ" }), + "ヤマダ タロウ" + ); +}); + +test("resolveKanaFromMaster: 片方欠けていても結合できる", () => { + assert.strictEqual(resolveKanaFromMaster({ Class003: "ヤマダ" }), "ヤマダ"); +}); + +test("needsKanaFill: 空文字・未定義はtrue", () => { + assert.strictEqual(needsKanaFill(""), true); + assert.strictEqual(needsKanaFill(undefined), true); + assert.strictEqual(needsKanaFill(null), true); +}); + +test("needsKanaFill: 値が入っていればfalse", () => { + assert.strictEqual(needsKanaFill("ヤマダ タロウ"), false); +}); +``` + +- [ ] **Step 2: テストが失敗することを確認** + +```bash +cd "C:\Users\k.nogi\#GitHub\ken_nogi\dev\NodeSrv\apps\healthcheck-survey-bot" +node --test test/employeeMasterCheck.test.js +``` + +Expected: `Cannot find module '../src/lib/employeeMasterCheck'`で失敗 + +- [ ] **Step 3: 実装を書く** + +```javascript +// src/lib/employeeMasterCheck.js +function checkEmailConsistency(pleasanterEmail, masterRecord) { + const masterEmail = masterRecord.Class036 || masterRecord.ClassB || null; + if (!masterEmail) { + return { consistent: false, masterEmail: null }; + } + return { consistent: masterEmail === pleasanterEmail, masterEmail }; +} + +function resolveKanaFromMaster(masterRecord) { + return [masterRecord.Class003, masterRecord.Class004].filter(Boolean).join(" "); +} + +function needsKanaFill(currentKana) { + return currentKana === null || currentKana === undefined || currentKana === ""; +} + +module.exports = { checkEmailConsistency, resolveKanaFromMaster, needsKanaFill }; +``` + +- [ ] **Step 4: テストが通ることを確認** + +```bash +node --test test/employeeMasterCheck.test.js +``` + +Expected: 8 tests、全てPASS + +- [ ] **Step 5: 全テストを通しで実行** + +```bash +node --test test/*.test.js +``` + +Expected: 6ファイル・36テスト、全てPASS + +- [ ] **Step 6: コミット** + +```bash +git add src/lib/employeeMasterCheck.js test/employeeMasterCheck.test.js +git commit -m "feat: 社員マスタ(504412)照合ロジック(メール整合性チェック・フリガナ補完)を追加" +``` + +**次に必要な作業(本計画のスコープ外):** 実行タイミングが決まったら、(a) 504412から`Class011`=対象PleasanterUserIdでレコードを取得する呼び出し元(クライアントスクリプト/n8nワークフロー/Process)、(b) 不一致・補完が見つかった場合の通知・自動反映方法、を別タスクとして設計する。 + +--- + ## Self-Review **Spec coverage:** - 全体アーキテクチャ(WP/WA + Process流用)→ Task 9〜11でカバー +- 社員マスタ(504412)連携(設計書8章)→ Task 13でロジックのみカバー。呼び出しトリガーは実行タイミング未確定のため意図的にスコープ外 - Data Table「bot_conversation_state」→ Task 8(実装上は`healthcheck_bot_state`という名前にしたが、設計書の構造要件は満たす。理由: 既存のorg-master-sync用テーブルと並んだ一覧で識別しやすくするため) - Process定義(ツールチップ・入力検証タブ)→ Task 2(実機調査)・Task 5(ロジック)・Task 9(利用) - 対象者解決(メール=LINEWORKS userId)→ Task 9・11のPleasanter `api/users/get`呼び出し