模倣(Mock)Users/Depts/Groupsテーブルの設計意図と実態乖離、
staging/production分離、config値修正、①③④④-1④-2④-3の
標準API化(models/groups/{id}/update等の実機検証結果込み)を記録。
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
16 KiB
org-master-sync n8n production移行 設計メモ
2026-09-04〜進行中。org-syncのn8nワークフロー群をproduction(本番プリザンター nextoffice.next-hd.co.jp)向けに構築する作業の設計意図・進捗記録。適宜追記していく。
1. 背景: 「模倣(Mock)テーブル」の設計意図
n8nのorg-sync系ワークフロー(①③④④-1④-2④-3)は、Pleasanter標準のUsers/Depts/Groups API(/api/users/get等)ではなく、staging環境に用意した「模倣テーブル」(SiteId 504737=ユーザー, 504736=組織, 504738=グループ、いずれもReferenceType: Resultsの通常テーブル)を参照して構築されていた。
意図(本人確認、2026-09-05): 開発当時は本番データを直接いじれなかったため、模倣テーブルでフロー構築を先に進め、「宛先(SiteId/BASE_URL)を変更するだけで本番化できる」ことを狙った設計だった。
判明した実態(2026-09-05調査): この狙いは実現できていなかった。
- 模倣テーブルはPleasanterのitems/export形式(表示名キーのJSON/CSV、例:
ログインID,組織)を返すが、本物の標準API(/api/users/get,/api/depts/get,/api/groups/get)はシステムフィールド名(UserId/LoginId/DeptId/GroupId等)+Offset/TotalCountページング必須という全く別の形式。「宛先を変えるだけ」では動かず、レスポンス変換層の追加が必要だった - LWグループマッピングテーブル(SiteId 504411、66件: 組織48・役職8・職級6・利用権限タイプ4)の「グループID(」列は模倣Groupsテーブル内の独自連番(1〜135+)で、本物のPleasanter Groups(GroupId実在範囲5〜69、全59件)とは無関係。名前での突合でも一致0件=本物のGroupsには1件も対応物が無い
2. n8nワークフロー構成(2026-09-04時点で判明した正式版一覧)
Proto系(org-master-sync prototypeフォルダに格納済み、検証用として維持、変更しない)とは別に、正式版として以下が存在:
| ワークフロー | ID |
|---|---|
| org-sync: ① LINEWORKSマスタ→プリザンターマスタ情報更新 | pJBj07V5p4Av8f6E |
| org-sync: ② バックアップ | HuKpZQEQeU4iUCUf |
| org-sync: ③ マージマスターメイン処理 | ScoUpIshCsdO2KdI |
| org-sync: ④ プリザンターマスタ更新(④-0〜④-3の統合版) | 82y3S515PbEBLSDv |
| org-sync: ④-0 状態判定 | UQ7vtaajy9O93jhW |
| org-sync: ④-1 新規ユーザー作成 | 6NwZXgXY2eK1Wt4g |
| org-sync: ④-2 ユーザー更新・退職処理 | I9NimeonT8rM51KW |
| org-sync: ④-3 グループ更新 | QPt4JRHOgSuN0nnS |
3. staging/production分離(2026-09-04実施)
上記8本を複製し、org-sync: staging: ...(既存の8本をリネーム)とorg-sync: production: ...(新規複製8本)に分離。
- production版はdataTable取得ノードのconfigKeyを
_TEST→_PRODへ全置換(④-0〜④-3内の「設定値統合」Codeノードにハードコードされてた_TEST参照も含む) - production版のWebhookパスは全部
-prodサフィックスで一意化(例:org-sync-01-lw-master-update-prod) - production版8本は全部
active: false(未有効化)で作成。稼働テストは今回のスコープ外、明示許可があるまで有効化しない - フォルダ構成:
org-master-sync(production版8本)/org-master-sync staging(staging版8本)/org-master-sync prototype(Proto系旧版15本)/LINEWORKS(通知系2本)
4. workflow_config_values(n8n Data Table)のPROD値修正
旧_PROD値(PLEASANTER_MASTER_SITE_ID_PROD=502552等)はいずれも404で存在しない廃止済みSiteIdだった。TESTが既に504406〜504412系列を使っていたのに対応させ、以下へ更新(2026-09-04、UI手動編集で完了):
| キー | 更新後の値 |
|---|---|
| PLEASANTER_MASTER_SITE_ID_PROD | 504412(社員・組織マスタ管理テーブル) |
| PLEASANTER_POSITION_MASTER_SITE_ID_PROD | 504408(LINEWORKS:役職マスタ) |
| PLEASANTER_LEVEL_MASTER_SITE_ID_PROD | 504410(LINEWORKS:職級マスタ) |
| PLEASANTER_USERTYPE_MASTER_SITE_ID_PROD | 504409(LINEWORKS:利用権限マスタ) |
| PLEASANTER_BACKUP_SITE_ID_PROD | 504407(社員・組織マスタ管理(副・バックアップ用)) |
| PLEASANTER_LW_GROUP_MAP_SITE_ID_PROD | 504411(LWグループマッピング、新規追加) |
n8n Data Table Public APIは行のupdate/delete専用エンドポイントが存在しない(PATCH/PUT/DELETEいずれも404か405、POSTのみ実装)。UI側の値セルはダブルクリックで編集・削除可能と判明(削除もUIから実施できた)。
5. 模倣テーブル→本物API移行の対応状況
| ワークフロー | 参照する模倣テーブル | 対応状況 |
|---|---|---|
| ③ マージマスターメイン処理(production版のみ) | Users(504737), Depts(504736) | 完了(2026-09-05)。下記5-1参照 |
| ① LINEWORKSマスタ→プリザンターマスタ情報更新(production版のみ) | Groups(504738) | 完了(2026-09-05)。下記5-2参照 |
| ④ プリザンターマスタ更新(統合版) | Users, Depts, Groups全部 | 完了(2026-09-05)。下記5-3参照 |
| ④-1 新規ユーザー作成 | Depts, Groups, Users(create先も504737) | 完了(2026-09-05)。下記5-4参照 |
| ④-2 ユーザー更新・退職処理 | Depts, Users, Groups | 完了(2026-09-05)。下記5-4参照 |
| ④-3 グループ更新 | Groups | 完了(2026-09-05)。下記5-4参照 |
これで①②③④④-0④-1④-2④-3、production版8本すべての模倣テーブル参照が解消された。
5-1. ③の対応内容(production版のみ、staging版は変更していない)
プリザンターUsers取得ノード:POST items/504737/export→POST api/users/get(View:{ApiGetMailAddresses:true}付き、Offset+TotalCountページング設定済み)プリザンターDepts取得ノード:POST items/504736/export→POST api/depts/get(同上ページング設定)- 「マージ計算」Codeノード: 標準APIの生データ(
UserId/LoginId/DeptId等)を、旧・模倣テーブルと同じキー名(ユーザID/ログインID/組織等)の中間形式へ変換する処理を先頭に追加。組織はDeptIdからプリザンターDepts取得の結果で逆引き(deptIdToNameマップ)。これにより後続のマージ判定ロジック(pleasanterUserToFields等)は無改造で流用できている SecretKey・Managerは本番データ上使用者ゼロを確認済み(該当者が出ても空文字扱いになるだけで実害小)
5-2. ①の対応内容(production版のみ、2026-09-05完了)
当初は「LWグループマッピング66件が本物のGroupsに1件も対応物を持たないため本物化には書込み移行が前提になり、構築のみでは完結しない」と判断していたが、①のワークフロー自体が元々「本物のGroupsに存在しないグループを自動で新規作成する」設計(差分計算→groupsToCreate→グループ作成実行)だったため、ワークフロー定義の書き換え自体は構築の範囲で完結できると整理し直した(実際の新規作成・無効化という書込みは、このワークフローを実際に実行したときに初めて発生する=稼働テスト禁止と同じ制約の範囲内)。
模倣Groups取得ノード →Groups取得へ改名、items/504738/export→api/groups/get(Offset+TotalCountページング設定込み)グループ作成実行ノード:items/504738/create(ClassA=独自連番,ClassB=グループ名) →api/groups/create(GroupNameのみ送信。Pleasanterが自動採番するGroupIdを使う設計に変更、独自連番のnextGroupId計算は廃止)グループ無効化更新実行ノード:items/{itemId}/update(CheckA) →api/groups/{groupId}/update(body{Disabled}のみ、GroupIdはURLパス側)。実機検証済み(2026-09-05、本人許可の下stagingのGroupId=40「テスト用グループ」で確認)。当初api/groups/update(bodyにGroupId)で試したところ404(nginxレベルで存在しないパス)、items系と同じ「IDをURLパスに含める」パターンが正解だった作成結果ペアリングノード: 独自連番をそのまま通していた処理から、グループ作成実行のレスポンス(Id)を実際に取得して使うよう変更差分計算ノード: 標準APIから取得した本物のGroups一覧(GroupName→GroupIdのマップ)を使い、LWグループマッピング66件の各行について「グループ名が本物のGroupsに実在するか」を追加でチェック。実在しなければgroupsToCreateに回して作り直し、実在するがグループID列がズレていればgroupsToFixIdとして修正対象に追加。これにより66件の移行問題もワークフロー実行時に自動的に解消される設計にした新規マッピングCSV組立ノード:groupsToFixIdも統合。ここでCSVの列を共通ヘッダーにする際、fixId行が持たない列(分類・sourceKey等)を空文字で送ると既存値を上書き消去してしまう危険があった(org-master-sync-n8n-mock-tables、8月の実データ事故と同種のパターン)ため、groupsToFixId側にもcategory/sourceKey/groupNameの元の値を保持させて対応
未検証・要注意点: グループ作成実行のレスポンス形式(Idをトップレベルで返す前提、createGroup関数の実装から類推)、SplitInBatches(グループ作成Loop)内での入出力アイテムの対応順序、いずれも稼働テストなしでは確証が持てない。①のproduction版を初めて実行する際は、必ず少数件(1件)に絞ってから全体を回すこと。
(2026-09-05追記)グループ更新のURL(/api/groups/{groupId}/update)は本人許可の下stagingのGroupId=40「テスト用グループ」で実機検証済み。詳細は8-2節参照。
5-3. ④(統合版)の対応内容(production版のみ、2026-09-05完了)
NodeSrv/apps/org-master-sync/sample/sampleアカウント作成スクリプト.js(本番プリザンターのフィールドスクリプトとして稼働実績あり)から、Users/Groups標準APIの正確な使用例が得られたため、これをベースに実装した。
プリザンターUsers取得/プリザンターGroups取得/プリザンターDepts取得: ①③と同様に標準API化(/api/users/get,/api/groups/get,/api/depts/get、Pagination込み)users_create実行:items/504737/create→/api/users/create。サンプルスクリプトのcreatePleasanterUser関数のbody構造をそのまま採用(LoginId/Name/Password/DeptId/DeptCode/MailAddresses等、フラットなフィールド名でHashネスト不要)users_update実行:items/{itemId}/update→/api/users/{userId}/update。このURL自体はサンプルスクリプトに例が無く実機未検証。Groups update(/api/groups/{groupId}/update)と同じ「IDをURLパスに含める」パターンからの類推グループ取得(メンバー判定用):items/504738/export(全件取得して対象1件をfind) →/api/groups/{groupId}/get(単体取得、対象1件だけ取得するよう効率化)グループ更新実行:items/{itemId}/update→/api/groups/{groupId}/update。サンプルスクリプトのaddUserGroup関数を参考に、GroupName/Body/GroupMembersをまとめて送る形に変更(Disabledには触れない)- 重要な発見: 模倣Groupsの「グループメンバー(種別,キー,管理者フラグ 1行1メンバー)」というテキスト行形式は、本物の標準API
GroupMembers配列の各要素('User,{userId},False'という文字列)と完全に同じフォーマットだった(サンプルスクリプトで確認)。改行区切りテキスト⇔配列という違いだけで、行内容自体の変換は不要だった 対象判定ロジックの変更点:- 新規ユーザー作成時のメールアドレスを、旧実装の
社員マスタのメールアドレスのローカル部 + '@nexthd.jp'固定ドメインから、LINEWORKS側のメールアドレスをそのまま使う方式に変更(本人指示、2026-09-05。ドメイン統一済みのため固定ドメイン付け替えは不要と判断) DeptIdはUsers create時に必須のため、Depts標準APIの結果からDeptName→DeptIdマップを新設(旧実装はDeptCodeしか計算していなかった)- 退職処理・組織変更の
userUpdateTasks.fieldsを、模倣テーブルの内部列名(無効/ロック/組織コード等)から標準APIのフィールド名(Disabled/Lockout/DeptCode/DeptId/MailAddresses)へ変更
- 新規ユーザー作成時のメールアドレスを、旧実装の
未検証点: /api/users/{userId}/updateの実在(ダミーユーザー作成テストは本人許可が得られていないため確認できていない)。④のproduction版を実行する前に、退職処理か組織変更いずれかの経路で必ず1件だけ実行して確認すること。
5-4. ④-1・④-2・④-3の対応内容(production版のみ、2026-09-05完了)
④(統合版)を機能別に分割した部分抜粋版のため、同じ修正パターンを適用した。
- ④-1新規ユーザー作成: ④と同じくUsers/Depts/Groups取得を標準API化、
users_create実行を/api/users/create化。新規ユーザーの初期グループ所属反映(書き戻しグループ反映組立)もGroupMembers配列ベースに変更 - ④-2ユーザー更新・退職処理: 同様にDepts/Users/Groups取得を標準API化。
対象展開(退職処理・組織変更)を/api/users/{userId}/update化。模倣Usersテーブル固有の「itemId」概念(userIdToItemIdによるUserId→模倣テーブル内部ID変換)は不要になった(標準APIはUserIdそのものが更新のキーになるため) - ④-3グループ更新: Groups取得を標準API化、グループメンバー反映を
/api/groups/{groupId}/update化
重要な発見(バグ): ④(統合版)の対象判定コードにconst NEXT_GROUP_ALL_ID = '4'という定義があったが、模倣Groupsテーブルにも本物のGroupsにもGroupId=4は存在しない誤った値だった(未使用の変数だったため実害はなかった)。④-1/④-2/④-3では同じ定数が正しく'27'(実在する「ネクストグループ全社員」グループ)になっていたため、そちらを正として全ワークフローで統一した。
検証結果(2026-09-05追記): /api/users/{userId}/updateは本人許可の下stagingのUserId=705「野木テストユーザ」で実機検証済み(Disabled:false送信、200 OK「"野木テストユーザ"を更新しました。」)。Groups/Depts系と同じ「IDをURLパスに含める」パターンで、④④④-1④-2の実装通りで問題なかった。①③④④-1④-2④-3、production版8本すべて未検証エンドポイントなしの状態になった。
6. 今回の制約(2026-09-05確認)
- n8nワークフロー定義の編集(PUT/POST /workflows、Data Table操作含む)は確認不要で全自動
- 本番プリザンター・LINEWORKSへの読み取り(GET系API、
items/{id}/export、items/{id}/get含む)は許可 - 本番プリザンターへの書き込み(create/update/import/bulkupsert等)は不可。特に①のグループ作成、③のマージ結果書き込みは明示的に禁止
- ワークフローの稼働テスト(Webhookを実際に叩く、Manual Trigger実行)は不可