"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); });