実装計画にTask13(社員マスタ504412照合ロジック)を追加

メールアドレス整合性チェック・フリガナ補完の判定/補完ロジックを
TDDで実装するタスクを追加。実行タイミング(保存時/定期バッチ/
手動)は未確定のため、呼び出しトリガーは意図的にスコープ外とし、
決まり次第別タスクとして追加する方針を明記した。

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
Kenichiro NOGI 2026-09-05 14:04:06 +09:00
parent bee42dc56d
commit 08a0b87dcf

View File

@ -1257,10 +1257,148 @@ git commit -m "feat: 508971にStatusプッシュ通知用クライアントス
---
### Task 13: employeeMasterCheck.js — 社員マスタ(504412)によるメール整合性チェック・フリガナ補完ロジック
設計書8章Bot対話フローとは独立した補助機能に対応。**実行タイミング(保存時/定期バッチ/手動)はまだ決まっていない**ため、本タスクは判定・補完の純粋ロジックとテストのみを作る。504412へのAPI呼び出しをどこから叩くかクライアントスクリプトn8n Schedule TriggerProcessは、タイミングが決まった時点で別タスクとして追加する。
**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`呼び出し