ken_nogi/ClaudePleasanter/★マスターシート/.claude/js/apply-9item-phase2-496626.js
Kenichiro NOGI ed33892f08 chore: 作業中の変更を整理しコミット(複数プロジェクト分)
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-02 11:09:50 +09:00

191 lines
7.4 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.

/**
* apply-9item-phase2-496626.js
* ------------------------------------------------------------
* site-496626「新・着工要因(東京)v2」9項目改修のitem8
* 「引越し」工程削除後続20工程の内部カラム番号一括リネーム
* SiteSettings構造変更Sections/Columns/EditorColumnHash/GridColumnsを反映する。
*
* 対象: Date028(引越し)を削除し、Date029〜04820工程を Date028〜047 へ、
* 対応する実績列(Date1xx)・備考列(Class0xx)・無しチェック列(Check1xx)・Section Idも
* 全て1つずつ前へリネームする。工程名LabelText/GridLabelText自体は変更しない。
*
* ★このスクリプトはSiteSettings構造のみを変更する。既存レコードのデータ
* Date029等の実際の値はこの反映だけでは移行されない。データ移行は
* migrate-process028-rename-496626.js を別途実行すること。構造変更を先に
* 反映し、その直後にデータ移行を実行する運用を想定している。
*
* 使い方:
* node apply-9item-phase2-496626.js … 差分表示のみ(送信なし)
* node apply-9item-phase2-496626.js --execute … 上記に加えて実際に送信する
* ------------------------------------------------------------
*/
const fs = require("fs");
const path = require("path");
const { findSiteDir, newModifyDir, latestModifyDir } = require("./site-paths");
const SITE_ID = 496626;
const baseDir = path.join(__dirname, "..", "..");
const configsDir = path.join(baseDir, "configs");
const execute = process.argv.includes("--execute");
function loadJson(p) {
return JSON.parse(fs.readFileSync(p, "utf-8"));
}
function maskApiKey(key) {
if (!key) return key;
return key.length > 8 ? key.slice(0, 4) + "****" + key.slice(-4) : "****";
}
function timestamp() {
return new Date().toISOString().replace(/[:.]/g, "-");
}
const config = loadJson(path.join(baseDir, "config.json"));
const siteDir = findSiteDir(configsDir, SITE_ID);
// ---- リネームマッピング構築 ----
const REMOVE_COLUMNS = new Set(["Date028", "Date128", "Class028", "Check128"]);
const RENAME_MAP = {};
const SECTION_ID_MAP = {};
for (let n = 29; n <= 48; n++) {
const newN = n - 1;
const pad = (x) => String(x).padStart(3, "0");
RENAME_MAP["Date" + pad(n)] = "Date" + pad(newN);
RENAME_MAP["Date" + (n + 100)] = "Date" + (newN + 100);
RENAME_MAP["Class" + pad(n)] = "Class" + pad(newN);
RENAME_MAP["Check" + (n + 100)] = "Check" + (newN + 100);
SECTION_ID_MAP[n] = newN;
}
function renameGridDesign(text) {
if (!text) return text;
return text.replace(/\[([A-Za-z]+\d+)\]/g, (m, colName) => {
return RENAME_MAP[colName] ? `[${RENAME_MAP[colName]}]` : m;
});
}
function renameTokenArray(arr) {
return arr
.filter((t) => t !== "_Section-28" && !REMOVE_COLUMNS.has(t))
.map((t) => {
if (t.startsWith("_Section-")) {
const id = parseInt(t.replace("_Section-", ""), 10);
return SECTION_ID_MAP[id] ? `_Section-${SECTION_ID_MAP[id]}` : t;
}
return RENAME_MAP[t] || t;
});
}
function transform(ss) {
const log = [];
// ---- Columns ----
ss.Columns = ss.Columns.filter((c) => !REMOVE_COLUMNS.has(c.ColumnName));
ss.Columns.forEach((c) => {
if (RENAME_MAP[c.ColumnName]) {
c.ColumnName = RENAME_MAP[c.ColumnName];
}
if (c.GridDesign) {
c.GridDesign = renameGridDesign(c.GridDesign);
}
});
log.push("Columns: Date028系4項目削除、Date029〜048系80項目をリネーム(GridDesign内参照含む)");
// ---- Sections ----
ss.Sections = ss.Sections.filter((s) => s.Id !== 28);
ss.Sections.forEach((s) => {
if (SECTION_ID_MAP[s.Id]) {
s.Id = SECTION_ID_MAP[s.Id];
}
});
log.push("Sections: Id28削除、Id29〜48をId28〜47へリネーム(LabelTextは変更なし)");
// ---- EditorColumnHash5タブ全て ----
["_Tab-1", "_Tab-2", "_Tab-3", "_Tab-4", "_Tab-5"].forEach((tab) => {
if (ss.EditorColumnHash[tab]) {
const before = ss.EditorColumnHash[tab].length;
ss.EditorColumnHash[tab] = renameTokenArray(ss.EditorColumnHash[tab]);
log.push(`EditorColumnHash.${tab}: ${before}トークン -> ${ss.EditorColumnHash[tab].length}トークン`);
}
});
// ---- GridColumnsメイン + View2/5/6 ----
ss.GridColumns = renameTokenArray(ss.GridColumns);
ss.Views.forEach((v) => {
if (v.GridColumns) {
v.GridColumns = renameTokenArray(v.GridColumns);
}
});
log.push("GridColumns: メイン・View2・View5・View6の4箇所をリネーム");
return log;
}
(async () => {
console.log("[INFO] 現在のサイト情報を取得しています...");
const getUrl = `${config.BaseUrl.replace(/\/+$/, "")}/api/items/${SITE_ID}/getsite`;
const getRes = await fetch(getUrl, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ ApiVersion: config.ApiVersion || "1.1", ApiKey: config.ApiKey }),
});
const getJson = await getRes.json();
if (getJson.StatusCode !== 200) {
console.error("[エラー] getsiteに失敗しました:", JSON.stringify(getJson).slice(0, 500));
process.exit(1);
}
const data = getJson.Response.Data;
console.log(`[OK] 取得しました現在のVer: ${data.Ver}, UpdatedTime: ${data.UpdatedTime}`);
const siteSettings = JSON.parse(JSON.stringify(data.SiteSettings));
console.log("========================================");
console.log(` 9項目改修 Phase2item8引越し削除+20工程番号リネームupdatesite全体更新${execute ? "(実行)" : "(プレビューのみ)"}`);
console.log("========================================");
const log = transform(siteSettings);
log.forEach((l) => console.log(" " + l));
const body = {
ApiVersion: config.ApiVersion || "1.1",
ApiKey: config.ApiKey,
SiteId: SITE_ID,
Title: data.Title,
ReferenceType: data.ReferenceType,
ParentId: data.ParentId,
InheritPermission: data.InheritPermission,
Permissions: data.Permissions,
SiteSettings: siteSettings,
};
const modifyDir = latestModifyDir(siteDir) || newModifyDir(siteDir, "9item-revision");
const ts = timestamp();
const maskedBody = { ...body, ApiKey: maskApiKey(body.ApiKey) };
const previewPath = path.join(modifyDir, `site-${SITE_ID}_phase2_update_preview_${ts}.json`);
fs.writeFileSync(previewPath, JSON.stringify(maskedBody, null, 2), "utf-8");
console.log(`\n[OK] 送信予定内容を保存しました: ${previewPath}`);
if (!execute) {
console.log("\n[注意] --execute が指定されていないため、送信は行っていません。");
console.log("内容を確認の上、問題なければ次を実行してください: node apply-9item-phase2-496626.js --execute");
process.exit(0);
}
console.log("\n実際に送信しますupdatesite...");
const url = `${config.BaseUrl.replace(/\/+$/, "")}/api/items/${SITE_ID}/updatesite`;
const res = await fetch(url, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify(body),
});
const text = await res.text();
const resultOutPath = path.join(modifyDir, `site-${SITE_ID}_phase2_update_result_${ts}.json`);
fs.writeFileSync(resultOutPath, text, "utf-8");
console.log(`HTTP ${res.status} ${res.statusText}`);
console.log(`[OK] 応答を保存しました: ${resultOutPath}`);
console.log(text);
})();