ken_nogi/NodeSrv/apps/org-master-sync/scripts/push-classx-choices-production.js
Kenichiro NOGI ce58cb4be4 初回コミット: dev配下(NodeSrv/Pleasanter等)をGitea管理下に統合
GitHub(nextgroup2706/ken_nogi)は今後使わず自社Gitea運用に切替え。
NodeSrvは旧リポジトリの履歴を破棄しファイルのみ統合(Dokploy用サービスアカウントは
別途mygit-admin/NodeSrv.gitに履歴あり)。notepmエクスポート(12GB)とPleasanter
インストーラzip(208MB)はサイズが大きいため.gitignoreで除外。

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-04 15:37:06 +09:00

124 lines
4.8 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"use strict";
/*
* production側SiteId=504407/504412のClassX(状態)ChoicesTextに、staging側で追加済みの
* 中間状態4件退職判定/新規登録判定/ユーザー更新判定/グループ更新判定)が欠落している
* scripts/compare-master-sites-staging-prod.js で検出。staging側の値をそのままproductionへ反映する。
* 既定はドライラン。実際に送信するには --execute を付ける。
*
* 実行: node scripts/push-classx-choices-production.js [--execute]
*/
const fs = require("fs");
const path = require("path");
const { getSite: fetchSite } = require("../src/lib/pleasanterClient");
const { saveSiteSnapshot } = require("../src/lib/siteConfigStore");
function parseEnv(text) {
const result = {};
for (const line of text.split(/\r?\n/)) {
const m = line.match(/^\s*([A-Za-z_][A-Za-z0-9_]*)\s*=\s*(.*)\s*$/);
if (!m || line.trim().startsWith("#")) continue;
result[m[1]] = m[2];
}
return result;
}
function loadEnv(file) {
const result = parseEnv(fs.readFileSync(path.join(__dirname, "..", file), "utf8"));
return { baseUrl: result.PLEASANTER_BASE_URL, apiKey: result.PLEASANTER_API_KEY };
}
const TARGET_SITE_IDS = [504407, 504412];
// staging側の完全な選択肢scripts/compare-master-sites-staging-prod.js実行結果より
const WANT_CHOICES_TEXT =
"0,在籍中,在籍中,status-blue\n" +
"1,退職済み,退職,status-red\n" +
"2,退職判定,退職判定,status-black\n" +
"3,新規登録判定,新規登録判定,status-yellow\n" +
"4,ユーザー更新判定,ユーザー更新判定,status-green\n" +
"5,グループ更新判定,グループ更新判定,status-purple\n" +
"8,要確認,要確認,status-yellow\n" +
"9,その他,その他,status-green\n";
async function getSite(baseUrl, apiKey, siteId) {
const data = await fetchSite({ baseUrl, apiKey, siteId });
saveSiteSnapshot(siteId, data);
return data;
}
async function updateSite(baseUrl, apiKey, siteId, body) {
const res = await fetch(`${baseUrl.replace(/\/$/, "")}/api/items/${siteId}/updatesite`, {
method: "POST",
headers: { "Content-Type": "application/json; charset=utf-8" },
body: JSON.stringify(body),
});
const data = await res.json();
if (!res.ok || data.StatusCode !== 200) {
throw new Error(`updatesite failed(SiteId=${siteId}): ${res.status} ${JSON.stringify(data)}`);
}
return data;
}
async function main() {
const execute = process.argv.includes("--execute");
const production = loadEnv(".env.production");
if (!production.baseUrl || !production.apiKey) {
console.error("production の PLEASANTER_BASE_URL / PLEASANTER_API_KEY が読み取れなかった");
process.exit(1);
}
for (const siteId of TARGET_SITE_IDS) {
console.log(`\n=== SiteId=${siteId} ===`);
const current = await getSite(production.baseUrl, production.apiKey, siteId);
const currentColumns = (current.SiteSettings && current.SiteSettings.Columns) || [];
const classXCol = currentColumns.find((c) => c.ColumnName === "ClassX");
if (!classXCol) {
console.error(` ClassX列が見つからない、スキップ`);
continue;
}
if (classXCol.ChoicesText === WANT_CHOICES_TEXT) {
console.log(` すでに一致、変更不要`);
continue;
}
console.log(` 現状 ChoicesText:\n ${JSON.stringify(classXCol.ChoicesText)}`);
console.log(` 変更後 ChoicesText:\n ${JSON.stringify(WANT_CHOICES_TEXT)}`);
const mergedColumns = currentColumns.map((col) =>
col.ColumnName === "ClassX" ? { ...col, ChoicesText: WANT_CHOICES_TEXT } : col
);
const body = {
ApiVersion: "1.1",
ApiKey: production.apiKey,
Title: current.Title,
ReferenceType: current.ReferenceType,
ParentId: current.ParentId,
InheritPermission: current.InheritPermission,
Permissions: current.Permissions,
SiteSettings: { ...current.SiteSettings, Columns: mergedColumns },
};
if (!execute) {
console.log(` [ドライラン] --execute を付けずに実行したため送信していません`);
continue;
}
const result = await updateSite(production.baseUrl, production.apiKey, siteId, body);
console.log(` [OK] 送信結果: ${JSON.stringify(result)}`);
const after = await getSite(production.baseUrl, production.apiKey, siteId);
const afterClassX = ((after.SiteSettings && after.SiteSettings.Columns) || []).find((c) => c.ColumnName === "ClassX");
if (afterClassX && afterClassX.ChoicesText === WANT_CHOICES_TEXT) {
console.log(` [OK] 再取得で反映確認済み`);
} else {
console.error(` [NG] 再取得結果が期待値と不一致: ${JSON.stringify(afterClassX && afterClassX.ChoicesText)}`);
}
}
}
main().catch((e) => {
console.error(e);
process.exit(1);
});