ken_nogi/Pleasanter/.claude/js/xwiki/build-pleasanter-scheme.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

380 lines
20 KiB
JavaScript
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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.

/**
* adminテナントに「プリザンター」ページツリーを一括構築するスキーム投入スクリプト。
* 参照: ClaudePleasanter/xwiki-doc-upload-scheme.md
*
* 使い方:
* node xwiki-pleasanter-scheme.js --dry-run … PUT先URLとタイトルのみ出力(実際には投げない)
* node xwiki-pleasanter-scheme.js --execute … 実際にXWikiへPUTする
*/
const fs = require("fs");
const path = require("path");
const ENV_PATH = "c:/Users/k.nogi/#GitHub/NodeSrv/apps/xwiki/.env";
function loadEnv(p) {
const text = fs.readFileSync(p, "utf8");
const env = {};
for (const line of text.split(/\r?\n/)) {
const m = line.match(/^([A-Za-z_][A-Za-z0-9_]*)=(.*)$/);
if (!m) continue;
let v = m[2];
if ((v.startsWith('"') && v.endsWith('"')) || (v.startsWith("'") && v.endsWith("'"))) {
v = v.slice(1, -1);
}
env[m[1]] = v;
}
return env;
}
const env = loadEnv(ENV_PATH);
const BASE_URL = env.XWIKI_BASE_URL;
const AUTH = "Basic " + Buffer.from(`${env.XWIKI_ADMIN_USER}:${env.XWIKI_ADMIN_PASSWORD}`).toString("base64");
const WIKI_ID = "admin";
function xmlEscape(s) {
return String(s)
.replace(/&/g, "&amp;")
.replace(/</g, "&lt;")
.replace(/>/g, "&gt;");
}
function buildUrl(spacePath) {
const segs = spacePath.map((s) => "spaces/" + encodeURIComponent(s));
return `${BASE_URL}/rest/wikis/${WIKI_ID}/${segs.join("/")}/pages/WebHome`;
}
async function putPage(spacePath, title, content) {
const url = buildUrl(spacePath);
const body = `<?xml version="1.0" encoding="UTF-8"?>
<page xmlns="http://www.xwiki.org">
<title>${xmlEscape(title)}</title>
<syntax>markdown/1.2</syntax>
<content>${xmlEscape(content)}</content>
</page>`;
const res = await fetch(url, {
method: "PUT",
headers: {
"Content-Type": "application/xml; charset=utf-8",
Authorization: AUTH,
},
body,
});
const text = await res.text();
return { status: res.status, ok: res.status === 201 || res.status === 202, url, text };
}
// ------------------------------------------------------------
// ツリー定義
// ------------------------------------------------------------
// spaceName: XWikiスペース名。SiteId_サイト名 の形式(末端以外もこの形式で統一)
// repoPath: リポジトリ内の対応パス(あれば)。無ければ null → 未取得と明記
// note: 補足(共有参照など)
const REPO_ROOT = "新・稟議申請システム、★マスターシート等は ClaudePleasanter直下の各プロジェクトフォルダ";
function space(siteId, title) {
return `${siteId}_${title}`;
}
// 各ツリーノード: { siteId, title, repoPath, note, children: [...] }
const tree63543 = {
siteId: 63543, title: "契約コード管理(全社)",
repoPath: "★マスターシート/configs/site-63543_契約コード管理全社",
children: [
{ siteId: 61259, title: "契約コード(全社)", repoPath: "★マスターシート/configs/site-61259_契約コード全社" },
{ siteId: 64583, title: "派生契約コード(全社)", repoPath: "★マスターシート/configs/site-64583_派生契約コード全社" },
{
siteId: 319014, title: "新・稟議申請",
repoPath: "新・稟議申請システム/configs/site-319014_新・稟議申請",
children: [
{ siteId: 319015, title: "新・稟議申請書", repoPath: "新・稟議申請システム/configs/site-319015_新・稟議申請書" },
{ siteId: 319016, title: "【ISO】稟議管理", repoPath: "新・稟議申請システム/configs/site-319016_【ISO】稟議管理" },
{ siteId: 319017, title: "【ISO】部署担当者別稟議集計", repoPath: "新・稟議申請システム/configs/site-319017_【ISO】部署担当者別稟議集計" },
{ siteId: 319022, title: "【部署別】稟議改善", repoPath: "新・稟議申請システム/configs/site-319022_【部署別】稟議改善" },
{
siteId: 319018, title: "マスタ", repoPath: null,
note: "ParentId実測で新規判明(旧docsでは63543とは別系統と誤記載されていた)。ローカル未取得。",
children: [
{ siteId: 319020, title: "稟議項目", repoPath: "新・稟議申請システム/configs/site-319020_稟議項目" },
{ siteId: 319021, title: "稟議通知管理", repoPath: "新・稟議申請システム/configs/site-319021_稟議通知管理" },
{ siteId: 335730, title: "組織エリアマスタ", repoPath: "新・稟議申請システム/configs/site-335730_組織エリアマスタ" },
{ siteId: 319027, title: "事前稟議一覧", repoPath: "新・稟議申請システム/configs/site-319027_事前稟議一覧" },
],
},
],
},
{ siteId: 160926, title: "稟議コード管理", repoPath: "新・稟議申請システム/configs/site-160926_稟議コード管理" },
],
};
const tree96230 = {
siteId: 96230, title: "【新版】注文住宅MSS", repoPath: null,
note: "IC(東京)/MSS回覧板/★マスターシート/事業計画(実績計上)が共有する外部ルート。ローカル未取得。",
children: [
{ siteId: 373518, title: "IC(東京)【引継依頼】", repoPath: "IC(東京)【引継依頼】/configs/site-373518_IC(東京)【引継依頼】" },
{
siteId: 471918, title: "【試作】MSS回覧版", repoPath: "MSS回覧板システム/configs/site-471918_【試作】MSS回覧版",
children: [
{
siteId: 475431, title: "M", repoPath: "MSS回覧板システム/configs/site-475431_M",
children: [
{
siteId: 471919, title: "マスタ", repoPath: "MSS回覧板システム/configs/site-471919_マスタ",
children: [
{
siteId: 475388, title: "図確回覧マスタ", repoPath: "MSS回覧板システム/configs/site-475388_図確回覧マスタ",
children: [
{ siteId: 471920, title: "図確回覧エリア別担当者", repoPath: "MSS回覧板システム/configs/site-471920_図確回覧エリア別担当者" },
{ siteId: 471921, title: "図確回覧テンプレート", repoPath: "MSS回覧板システム/configs/site-471921_図確回覧テンプレート" },
{ siteId: 475389, title: "図確回覧共通担当者", repoPath: "MSS回覧板システム/configs/site-475389_図確回覧共通担当者" },
],
},
{ siteId: 483434, title: "回覧資料マスタ", repoPath: "MSS回覧板システム/configs/site-483434_回覧資料マスタ" },
{
siteId: 492050, title: "四者回覧マスタ", repoPath: "MSS回覧板システム/configs/site-492050_四者回覧マスタ",
children: [
{ siteId: 492020, title: "四者MTG回覧テンプレート", repoPath: "MSS回覧板システム/configs/site-492020_四者MTG回覧テンプレート" },
{ siteId: 492051, title: "四者MTG回覧エリア別担当者", repoPath: "MSS回覧板システム/configs/site-492051_四者MTG回覧エリア別担当者" },
{ siteId: 492052, title: "四者MTG回覧共通担当者", repoPath: "MSS回覧板システム/configs/site-492052_四者MTG回覧共通担当者" },
],
},
{
siteId: 492182, title: "承認図回覧マスタ", repoPath: "MSS回覧板システム/configs/site-492182_承認図回覧マスタ",
children: [
{ siteId: 492183, title: "承認図回覧テンプレート", repoPath: "MSS回覧板システム/configs/site-492183_承認図回覧テンプレート" },
{ siteId: 492184, title: "承認図回覧エリア別担当者", repoPath: "MSS回覧板システム/configs/site-492184_承認図回覧エリア別担当者" },
{ siteId: 492185, title: "承認図回覧共通担当者", repoPath: "MSS回覧板システム/configs/site-492185_承認図回覧共通担当者" },
],
},
],
},
],
},
{ siteId: 475384, title: "図確回覧", repoPath: "MSS回覧板システム/configs/site-475384_図確回覧" },
{ siteId: 492045, title: "四者MTG回覧", repoPath: "MSS回覧板システム/configs/site-492045_四者MTG回覧" },
{ siteId: 492169, title: "承認図回覧", repoPath: "MSS回覧板システム/configs/site-492169_承認図回覧" },
],
},
{ siteId: 189112, title: "★マスターシート", repoPath: "★マスターシート/configs/site-189112_★マスターシート", note: "営業積算システムからも参照(neo999環境、実体はここ)" },
{ siteId: 116503, title: "★リードタイム算定", repoPath: "★マスターシート/configs/site-116503_★リードタイム算定" },
{ siteId: 189113, title: "★粗利益確認書", repoPath: "★マスターシート/configs/site-189113_★粗利益確認書" },
{ siteId: 190731, title: "★追加変更工事", repoPath: "★マスターシート/configs/site-190731_★追加変更工事" },
{ siteId: 203147, title: "★工期計算表", repoPath: "★マスターシート/configs/site-203147_★工期計算表" },
{ siteId: 212512, title: "お客様データファイル", repoPath: "★マスターシート/configs/site-212512_お客様データファイル", note: "MSS回覧板システムのconfigsにも同一SiteIdの取得コピーあり" },
{ siteId: 212533, title: "【WF】追加変更申請", repoPath: "★マスターシート/configs/site-212533_【WF】追加変更申請" },
{ siteId: 263191, title: "実績計上", repoPath: "★マスターシート/configs/site-263191_実績計上", note: "事業計画のconfigsにも同一SiteIdの取得コピーあり" },
{ siteId: 488755, title: "【開発中】★建売マスターシート", repoPath: "★マスターシート/configs/site-488755_【開発中】★建売マスターシート" },
{
siteId: 96233, title: "M", repoPath: null, note: "ローカル未取得",
children: [
{
siteId: 96234, title: "マスターデータ", repoPath: "★マスターシート/configs/site-96234_マスターデータ", note: "営業積算システムのconfigsにも同一SiteIdの取得コピーあり",
children: [
{ siteId: 109029, title: "施工会社", repoPath: "★マスターシート/configs/site-109029_施工会社" },
{ siteId: 109100, title: "ブランド", repoPath: "★マスターシート/configs/site-109100_ブランド", note: "営業積算システムにも同一SiteIdの取得コピーあり" },
{ siteId: 109109, title: "ブランド別タイプ", repoPath: "★マスターシート/configs/site-109109_ブランド別タイプ" },
{ siteId: 210699, title: "エリア", repoPath: "★マスターシート/configs/site-210699_エリア", note: "営業積算システムにも同一SiteIdの取得コピーあり" },
{ siteId: 210707, title: "担当IC", repoPath: "★マスターシート/configs/site-210707_担当IC" },
{ siteId: 210711, title: "担当設計", repoPath: "★マスターシート/configs/site-210711_担当設計" },
{ siteId: 210712, title: "担当監督", repoPath: "★マスターシート/configs/site-210712_担当監督", note: "営業積算システムにも同一SiteIdの取得コピーあり" },
{ siteId: 211715, title: "集客事由", repoPath: "★マスターシート/configs/site-211715_集客事由" },
{ siteId: 96235, title: "契約会社", repoPath: "★マスターシート/configs/site-96235_契約会社" },
{ siteId: 96243, title: "営業所", repoPath: "★マスターシート/configs/site-96243_営業所", note: "営業積算システムにも同一SiteIdの取得コピーあり" },
],
},
],
},
],
};
const tree214975 = {
siteId: 214975, title: "NEXTGROUP経営計画", repoPath: null, note: "ローカル未取得",
children: [
{ siteId: 214737, title: "事業計画", repoPath: "事業計画/configs/site-214737_事業計画" },
{ siteId: 214922, title: "事業計画-集計", repoPath: "事業計画/configs/site-214922_事業計画-集計" },
],
};
const tree426945 = {
siteId: 426945, title: "【開発中】新・着工要因管理",
repoPath: "新・着工要因システム/configs/site-426945_新・着工要因管理",
children: [
{ siteId: 480111, title: "新・着工要因(東京)", repoPath: "新・着工要因システム/configs/site-480111_新・着工要因(東京)" },
{ siteId: 496626, title: "新・着工要因(東京)v2", repoPath: "新・着工要因システム/configs/site-496626_新・着工要因(東京)v2" },
],
};
const tree320332 = {
siteId: 320332, title: "助っ人クラウド",
repoPath: "助っ人クラウド/configs/site-collection_spec.md",
note: "config.jsonはMSS回覧板システムの値が誤ってコピーされたもの(参考にしない)。実体はsite-collection_spec.md。個別サイトフォルダは一部のみ存在。",
children: [
{ siteId: 439118, title: "機能要望・改善案", repoPath: null, note: "site-collection_spec.mdに記載あり、個別フォルダ未取得" },
{ siteId: 397527, title: "案件情報", repoPath: "助っ人クラウド/configs/site-397527_spec.md" },
{ siteId: 397526, title: "物件情報", repoPath: "助っ人クラウド/configs/site-397526_spec.md" },
{ siteId: 397528, title: "顧客情報", repoPath: "助っ人クラウド/configs/site-397528_spec.md" },
{
siteId: 423099, title: "フォルダ", repoPath: null, note: "旧データ用フォルダ。site-collection_spec.mdに記載あり、個別フォルダ未取得",
children: [
{ siteId: 320563, title: "顧客情報old", repoPath: null },
{ siteId: 320356, title: "物件情報old", repoPath: null },
{ siteId: 320562, title: "案件情報old", repoPath: null },
{ siteId: 320333, title: "ログ", repoPath: null },
],
},
],
};
const tree74663 = {
siteId: 74663, title: "積算問合せ",
repoPath: "営業積算システム/configs/site-74663_積算問合せ",
children: [
{ siteId: 335410, title: "①物件基本情報 Ver0.3", repoPath: "営業積算システム/configs/site-335410_①物件基本情報 Ver0.3" },
{ siteId: 335411, title: "②問い合わせ内容管理 Ver0.3", repoPath: "営業積算システム/configs/site-335411_②問い合わせ内容管理 Ver0.3" },
{ siteId: 335450, title: "遅延理由テンプレ管理", repoPath: "営業積算システム/configs/site-335450_遅延理由テンプレ管理" },
{ siteId: 335603, title: "問い合わせ不要理由テンプレ管理", repoPath: "営業積算システム/configs/site-335603_問い合わせ不要理由テンプレ管理" },
],
};
// ------------------------------------------------------------
// ページ生成
// ------------------------------------------------------------
const pages = []; // { spacePath: [...], title, content }
function pageContent({ siteId, title, repoPath, note, baseUrl, hasChildren }) {
const lines = [];
lines.push(`# ${title}`);
lines.push("");
lines.push(`- SiteId: ${siteId}`);
if (baseUrl) lines.push(`- Pleasanter環境: ${baseUrl}`);
lines.push(`- リポジトリ内パス: ${repoPath ? "\`" + repoPath + "\`" : "未取得(このサイトのローカルJSON/仕様書は未取得)"}`);
if (note) lines.push(`- 備考: ${note}`);
lines.push("");
if (hasChildren) {
lines.push("子サイトは下記ページツリー参照。");
} else {
lines.push("仕様書・バックアップ・取得情報mdファイルは未投入。指示があり次第このページ配下にアップロードする。");
}
return lines.join("\n");
}
function walk(node, spacePath, baseUrl) {
const sp = spacePath.concat(space(node.siteId, node.title));
pages.push({
spacePath: sp,
title: `${node.title}SiteId:${node.siteId}`,
content: pageContent({ ...node, baseUrl, hasChildren: !!(node.children && node.children.length) }),
});
if (node.children) {
for (const child of node.children) walk(child, sp, baseUrl);
}
}
// ルート: プリザンター
pages.push({
spacePath: ["プリザンター"],
title: "プリザンター",
content: [
"# プリザンター",
"",
"プリザンター(Pleasanter)の仕様書・取得情報md・バックアップの保管スキーム。",
"環境(ホスト名)別にページを分け、各配下にPleasanterの実サイトツリー構造(親子関係)をそのまま再現している。",
"",
"## 環境一覧",
"- [[nextoffice]] : 本番/検証環境 (nextoffice.next-hd.co.jp)",
"- [[nextoffice2]] : 予約(現時点で対応案件なし)",
"- [[neo999]] : 開発環境 (neo999.next-hd.net)",
"",
"各末端サイトページに、Claude Code側リポジトリ(ClaudePleasanter)内の対応パスを記載している。",
"仕様書・バックアップの実ファイルは指示があった際に個別ページへアップロードする(本構築ではスキームのみ)。",
].join("\n"),
});
pages.push({
spacePath: ["プリザンター", "nextoffice"],
title: "nextoffice",
content: [
"# nextoffice",
"",
"- Pleasanterホスト: `https://nextoffice.next-hd.co.jp/pleasanter/`",
"- 用途: 本番/検証環境",
"",
"配下ページはPleasanter上の実サイトツリー(ParentId階層)をそのまま再現したもの。",
"スペース名は `SiteId_サイト名` 形式。",
].join("\n"),
});
pages.push({
spacePath: ["プリザンター", "nextoffice2"],
title: "nextoffice2",
content: [
"# nextoffice2",
"",
"現時点で対応するPleasanter案件なし。将来の環境追加用に予約したページ。",
].join("\n"),
});
pages.push({
spacePath: ["プリザンター", "neo999"],
title: "neo999",
content: [
"# neo999",
"",
"- Pleasanterホスト: `https://neo999.next-hd.net/pleasanter/`",
"- 用途: 開発環境",
"",
"配下ページはPleasanter上の実サイトツリー(ParentId階層)をそのまま再現したもの。",
"スペース名は `SiteId_サイト名` 形式。",
].join("\n"),
});
const NEXTOFFICE_BASE = "https://nextoffice.next-hd.co.jp/pleasanter/";
const NEO999_BASE = "https://neo999.next-hd.net/pleasanter/";
for (const root of [tree63543, tree96230, tree214975, tree426945, tree320332]) {
walk(root, ["プリザンター", "nextoffice"], NEXTOFFICE_BASE);
}
walk(tree74663, ["プリザンター", "neo999"], NEO999_BASE);
// ------------------------------------------------------------
// 実行
// ------------------------------------------------------------
async function main() {
const args = process.argv.slice(2);
const dryRun = args.includes("--dry-run") || !args.includes("--execute");
console.log(`[INFO] 総ページ数: ${pages.length}`);
console.log(`[INFO] モード: ${dryRun ? "dry-run(投げない)" : "execute(実投入)"}`);
console.log("");
let ok = 0, ng = 0;
for (const p of pages) {
const url = buildUrl(p.spacePath);
if (dryRun) {
console.log(`[DRY] ${p.spacePath.join(" / ")}`);
console.log(` ${url}`);
continue;
}
const result = await putPage(p.spacePath, p.title, p.content);
if (result.ok) {
ok++;
console.log(`[OK ${result.status}] ${p.spacePath.join(" / ")}`);
} else {
ng++;
console.log(`[NG ${result.status}] ${p.spacePath.join(" / ")}`);
console.log(` ${result.text.slice(0, 300)}`);
}
}
if (!dryRun) {
console.log("");
console.log(`[SUMMARY] OK=${ok} NG=${ng} / TOTAL=${pages.length}`);
}
}
main();