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>
170 lines
5.4 KiB
JavaScript
170 lines
5.4 KiB
JavaScript
const path = require("path");
|
||
const fs = require("fs");
|
||
const ExcelJS = require(path.join(__dirname, "..", "..", "node_modules", "exceljs"));
|
||
|
||
const siteDir = path.join(
|
||
__dirname,
|
||
"..",
|
||
"configs",
|
||
"production",
|
||
"site-504322_【デモ版】②問い合わせ内容管理"
|
||
);
|
||
|
||
const siteSettingsRaw = JSON.parse(
|
||
fs.readFileSync(
|
||
path.join(siteDir, "sitesettings", "site-504322_latest.json"),
|
||
"utf8"
|
||
)
|
||
);
|
||
const siteSettings =
|
||
siteSettingsRaw.Response.Data.SiteSettings || siteSettingsRaw.Response.Data;
|
||
const columns = siteSettings.Columns || [];
|
||
|
||
const processes = JSON.parse(
|
||
fs.readFileSync(path.join(siteDir, "processes.json"), "utf8")
|
||
);
|
||
|
||
const labelMap = new Map();
|
||
columns.forEach((c) => {
|
||
if (c.ColumnName && c.LabelText) labelMap.set(c.ColumnName, c.LabelText);
|
||
});
|
||
|
||
// [ColumnName] → [表示名] に変換。辞書にない([Url]や固定文字列等)はそのまま。
|
||
function toLabel(text) {
|
||
if (!text) return "";
|
||
return text.replace(/\[([A-Za-z0-9]+)\]/g, (m, name) => {
|
||
return labelMap.has(name) ? `[${labelMap.get(name)}]` : m;
|
||
});
|
||
}
|
||
|
||
const rows = [];
|
||
processes.forEach((p) => {
|
||
const n = (p.Notifications || [])[0];
|
||
if (!n) return;
|
||
rows.push({
|
||
process: p.DisplayName || p.Name,
|
||
from: `${p.CurrentStatus} → ${p.ChangedStatus}`,
|
||
subject: toLabel(n.Subject),
|
||
to: toLabel(n.Address) || "(なし)",
|
||
cc: toLabel(n.CcAddress) || "(なし)",
|
||
bcc: toLabel(n.BccAddress) || "(なし)",
|
||
body: toLabel(n.Body),
|
||
});
|
||
});
|
||
|
||
// ChoicesTextがUsersテーブル参照([[Users*]] 全件、または TableName:"Users" の絞込参照)のカラム
|
||
// = メール宛先に指定できる項目
|
||
const usersStarColumns = columns.filter(
|
||
(c) =>
|
||
typeof c.ChoicesText === "string" &&
|
||
(c.ChoicesText.replace(/\s/g, "").includes("[[Users*]]") ||
|
||
/"TableName"\s*:\s*"Users"/.test(c.ChoicesText))
|
||
);
|
||
|
||
function usersFilterNote(c) {
|
||
if (c.ChoicesText.replace(/\s/g, "").includes("[[Users*]]")) return "全ユーザー対象";
|
||
const notes = [];
|
||
if (/"DeptId"\s*:\s*"\[\\"25\\"\]"/.test(c.ChoicesText)) notes.push("部署ID25(積算担当)に絞込");
|
||
if (/"UserId"\s*:\s*"=\[@Class153\]"/.test(c.ChoicesText)) notes.push(`[${labelMap.get("Class153") || "Class153"}] を参照して絞込`);
|
||
if (/"Disabled"\s*:\s*"false"/.test(c.ChoicesText)) notes.push("有効ユーザーのみ");
|
||
return notes.length ? notes.join("/") : "Usersテーブル参照(絞込条件あり)";
|
||
}
|
||
|
||
async function main() {
|
||
const wb = new ExcelJS.Workbook();
|
||
wb.creator = "野木 健一郎";
|
||
wb.created = new Date();
|
||
|
||
// 転置レイアウト: A列=項目名、B列以降=各プロセス
|
||
const ws1 = wb.addWorksheet("504322_プロセス通知メール仕様", {
|
||
views: [{ state: "frozen", xSplit: 1, ySplit: 1 }],
|
||
});
|
||
|
||
const itemLabels = ["ステータス遷移", "件名", "宛先(To)", "CC", "BCC", "本文"];
|
||
const itemKeys = ["from", "subject", "to", "cc", "bcc", "body"];
|
||
|
||
ws1.getColumn(1).width = 14;
|
||
rows.forEach((_, i) => {
|
||
ws1.getColumn(i + 2).width = 32;
|
||
});
|
||
|
||
const headerRow = ws1.addRow(["プロセス名", ...rows.map((r) => r.process)]);
|
||
headerRow.font = { bold: true };
|
||
headerRow.fill = {
|
||
type: "pattern",
|
||
pattern: "solid",
|
||
fgColor: { argb: "FFD9E1F2" },
|
||
};
|
||
headerRow.alignment = { vertical: "middle", horizontal: "center" };
|
||
|
||
itemLabels.forEach((label, i) => {
|
||
const key = itemKeys[i];
|
||
const row = ws1.addRow([label, ...rows.map((r) => r[key])]);
|
||
row.alignment = { vertical: "top", wrapText: true };
|
||
row.getCell(1).font = { bold: true };
|
||
row.getCell(1).fill = {
|
||
type: "pattern",
|
||
pattern: "solid",
|
||
fgColor: { argb: "FFF2F2F2" },
|
||
};
|
||
});
|
||
|
||
const ws2 = wb.addWorksheet("メール宛先指定可能項目(Users_)", {
|
||
views: [{ state: "frozen", ySplit: 1 }],
|
||
});
|
||
ws2.columns = [
|
||
{ header: "項目名", key: "label", width: 26 },
|
||
{ header: "複数選択", key: "multi", width: 12 },
|
||
{ header: "初期値", key: "default", width: 14 },
|
||
{ header: "備考", key: "note", width: 55 },
|
||
];
|
||
ws2.getRow(1).font = { bold: true };
|
||
ws2.getRow(1).fill = {
|
||
type: "pattern",
|
||
pattern: "solid",
|
||
fgColor: { argb: "FFD9E1F2" },
|
||
};
|
||
ws2.getRow(1).alignment = { vertical: "middle", horizontal: "center" };
|
||
usersStarColumns.forEach((c) => {
|
||
const notes = [usersFilterNote(c)];
|
||
if (c.Hide) notes.push("画面非表示項目");
|
||
ws2.addRow({
|
||
label: `[${c.LabelText}]`,
|
||
multi: c.MultipleSelections ? "○" : "",
|
||
default:
|
||
c.DefaultInput === "[[Self]]"
|
||
? "自分自身"
|
||
: c.DefaultInput
|
||
? c.DefaultInput
|
||
: "",
|
||
note: notes.join("/"),
|
||
});
|
||
});
|
||
|
||
[ws1, ws2].forEach((ws) => {
|
||
ws.eachRow((row) => {
|
||
row.eachCell((cell) => {
|
||
cell.border = {
|
||
top: { style: "thin", color: { argb: "FFBFBFBF" } },
|
||
left: { style: "thin", color: { argb: "FFBFBFBF" } },
|
||
bottom: { style: "thin", color: { argb: "FFBFBFBF" } },
|
||
right: { style: "thin", color: { argb: "FFBFBFBF" } },
|
||
};
|
||
});
|
||
});
|
||
});
|
||
|
||
const outPath = path.join(
|
||
__dirname,
|
||
"site-504322_プロセス通知メール仕様.xlsx"
|
||
);
|
||
await wb.xlsx.writeFile(outPath);
|
||
console.log("[OK] 保存しました:", outPath);
|
||
console.log("Users*項目件数:", usersStarColumns.length);
|
||
}
|
||
|
||
main().catch((e) => {
|
||
console.error(e);
|
||
process.exit(1);
|
||
});
|