同步页面权限、业务功能、SQL脚本及项目文档
This commit is contained in:
@@ -0,0 +1,206 @@
|
||||
// 修改人:Ld 修改时间:2026-09-17 11:20:00; 生成正式库本月订单与所属合同关联明细 Excel。
|
||||
import fs from "node:fs/promises";
|
||||
import path from "node:path";
|
||||
import { SpreadsheetFile, Workbook } from "@oai/artifact-tool";
|
||||
|
||||
const outputDir = path.resolve("outputs/order_contract_links_202609");
|
||||
const jsonPath = path.join(outputDir, "order_contract_links_202609.json");
|
||||
const summaryPath = path.join(outputDir, "extract_summary.json");
|
||||
const outputPath = path.join(outputDir, "正式库订单关联合同明细_2026-09.xlsx");
|
||||
|
||||
const rows = JSON.parse(await fs.readFile(jsonPath, "utf8"));
|
||||
const extractSummary = JSON.parse(await fs.readFile(summaryPath, "utf8"));
|
||||
|
||||
const workbook = Workbook.create();
|
||||
const summarySheet = workbook.worksheets.add("汇总");
|
||||
const detailSheet = workbook.worksheets.add("明细");
|
||||
summarySheet.tabColor = "#1F4E78";
|
||||
detailSheet.tabColor = "#5B9BD5";
|
||||
summarySheet.showGridLines = false;
|
||||
detailSheet.showGridLines = false;
|
||||
|
||||
const headers = [
|
||||
"订单流水号",
|
||||
"订单编号",
|
||||
"订单类型",
|
||||
"订单类型名称",
|
||||
"补货类型",
|
||||
"项目流水号",
|
||||
"所属合同编号",
|
||||
"所属合同类型",
|
||||
"所属合同类型名称",
|
||||
"关联类型",
|
||||
"是否已关联合同",
|
||||
"下单日期",
|
||||
"下单人",
|
||||
"客户名称",
|
||||
"收货人员",
|
||||
"合同经手人",
|
||||
"合同签订日期",
|
||||
"合同交货日期",
|
||||
"审核期限",
|
||||
"通用装配期限",
|
||||
"采购期限",
|
||||
"精工期限",
|
||||
"专机装配期限",
|
||||
"订单备注",
|
||||
"合同备注",
|
||||
"合同状态",
|
||||
"订单状态",
|
||||
"下达部门",
|
||||
];
|
||||
|
||||
const detailValues = [
|
||||
headers,
|
||||
...rows.map((row) => headers.map((header) => row[header] ?? "")),
|
||||
];
|
||||
|
||||
detailSheet.getRangeByIndexes(0, 0, detailValues.length, headers.length).values = detailValues;
|
||||
const detailRange = detailSheet.getRangeByIndexes(0, 0, detailValues.length, headers.length);
|
||||
detailRange.format.font = { name: "Arial", size: 10, color: "#1F2937" };
|
||||
detailSheet.getRangeByIndexes(0, 0, 1, headers.length).format = {
|
||||
fill: "#1F4E78",
|
||||
font: { name: "Arial", size: 10, bold: true, color: "#FFFFFF" },
|
||||
};
|
||||
detailSheet.getRangeByIndexes(0, 0, detailValues.length, headers.length).format.borders = {
|
||||
preset: "all",
|
||||
style: "thin",
|
||||
color: "#D9E2F3",
|
||||
};
|
||||
detailSheet.freezePanes.freezeRows(1);
|
||||
detailSheet.freezePanes.freezeColumns(2);
|
||||
detailSheet.getRange("A:A").format.numberFormat = "0";
|
||||
detailSheet.getRange("C:C").format.numberFormat = "0";
|
||||
detailSheet.getRange("F:F").format.numberFormat = "0";
|
||||
detailSheet.getRange("H:H").format.numberFormat = "0";
|
||||
detailSheet.getRange("L:L").format.numberFormat = "yyyy-mm-dd hh:mm";
|
||||
detailSheet.getRange("Q:W").format.numberFormat = "yyyy-mm-dd";
|
||||
detailSheet.getRange("N:N").format.columnWidth = 24;
|
||||
detailSheet.getRange("X:Y").format.columnWidth = 34;
|
||||
detailSheet.getRange("A:AB").format.autofitColumns();
|
||||
detailSheet.getRange("A1:AB1").format.verticalAlignment = "center";
|
||||
detailSheet.getRange("A1:AB1").format.wrapText = true;
|
||||
detailSheet.getRange("A:AB").format.verticalAlignment = "center";
|
||||
detailSheet.tables.add(`A1:AB${Math.max(detailValues.length, 2)}`, true, "OrderContractLinks");
|
||||
|
||||
const total = rows.length;
|
||||
const linked = rows.filter((row) => row["是否已关联合同"] === "是").length;
|
||||
const missing = total - linked;
|
||||
const replenishment = rows.filter((row) => Number(row["订单类型"]) === 3).length;
|
||||
const linkedReplenishment = rows.filter((row) => row["关联类型"] === "补货挂销售合同").length;
|
||||
const independentReplenishment = rows.filter((row) => row["关联类型"] === "补货独立合同").length;
|
||||
const typeCounts = new Map();
|
||||
const relationCounts = new Map();
|
||||
for (const row of rows) {
|
||||
const typeName = row["订单类型名称"] || "未定义";
|
||||
typeCounts.set(typeName, (typeCounts.get(typeName) || 0) + 1);
|
||||
const relation = row["关联类型"] || "未定义";
|
||||
relationCounts.set(relation, (relationCounts.get(relation) || 0) + 1);
|
||||
}
|
||||
|
||||
summarySheet.getRange("B2").values = [["正式库订单关联合同明细"]];
|
||||
summarySheet.getRange("B3").values = [[`期间:${extractSummary.开始日期} 至 ${extractSummary.结束日期}(不含结束日)`]];
|
||||
summarySheet.getRange("B4").values = [[`数据源:${extractSummary.数据库},导出时间:${extractSummary.导出时间}`]];
|
||||
summarySheet.getRange("B2").format.font = { name: "Arial", size: 14, bold: true, color: "#111827" };
|
||||
summarySheet.getRange("B3:B4").format.font = { name: "Arial", size: 10, italic: true, color: "#4B5563" };
|
||||
summarySheet.getRange("B5:I5").format.borders = { preset: "doubleBottom", style: "thin", color: "#1F4E78" };
|
||||
|
||||
summarySheet.getRange("B7:C12").values = [
|
||||
["指标", "数量"],
|
||||
["本月订单数", total],
|
||||
["已关联合同数", linked],
|
||||
["未关联合同数", missing],
|
||||
["补货订单数", replenishment],
|
||||
["补货挂销售合同数", linkedReplenishment],
|
||||
];
|
||||
summarySheet.getRange("E8:F8").values = [["补货独立合同数", independentReplenishment]];
|
||||
summarySheet.getRange("B7:C7").format = {
|
||||
fill: "#1F4E78",
|
||||
font: { name: "Arial", size: 10, bold: true, color: "#FFFFFF" },
|
||||
};
|
||||
summarySheet.getRange("E8:F8").format = {
|
||||
fill: "#EAF2F8",
|
||||
font: { name: "Arial", size: 10, bold: true, color: "#1F2937" },
|
||||
};
|
||||
summarySheet.getRange("B7:C12").format.borders = { preset: "all", style: "thin", color: "#D9E2F3" };
|
||||
summarySheet.getRange("E8:F8").format.borders = { preset: "all", style: "thin", color: "#D9E2F3" };
|
||||
summarySheet.getRange("C8:C12").format.numberFormat = "#,##0";
|
||||
summarySheet.getRange("F8:F8").format.numberFormat = "#,##0";
|
||||
|
||||
const typeRows = [["订单类型名称", "数量"], ...Array.from(typeCounts.entries()).sort((a, b) => b[1] - a[1])];
|
||||
summarySheet.getRangeByIndexes(14, 1, typeRows.length, 2).values = typeRows;
|
||||
summarySheet.getRangeByIndexes(14, 1, 1, 2).format = {
|
||||
fill: "#1F4E78",
|
||||
font: { name: "Arial", size: 10, bold: true, color: "#FFFFFF" },
|
||||
};
|
||||
summarySheet.getRangeByIndexes(14, 1, typeRows.length, 2).format.borders = {
|
||||
preset: "all",
|
||||
style: "thin",
|
||||
color: "#D9E2F3",
|
||||
};
|
||||
summarySheet.getRangeByIndexes(15, 2, Math.max(typeRows.length - 1, 1), 1).format.numberFormat = "#,##0";
|
||||
|
||||
const relationRows = [["关联类型", "数量"], ...Array.from(relationCounts.entries()).sort((a, b) => b[1] - a[1])];
|
||||
summarySheet.getRangeByIndexes(14, 4, relationRows.length, 2).values = relationRows;
|
||||
summarySheet.getRangeByIndexes(14, 4, 1, 2).format = {
|
||||
fill: "#1F4E78",
|
||||
font: { name: "Arial", size: 10, bold: true, color: "#FFFFFF" },
|
||||
};
|
||||
summarySheet.getRangeByIndexes(14, 4, relationRows.length, 2).format.borders = {
|
||||
preset: "all",
|
||||
style: "thin",
|
||||
color: "#D9E2F3",
|
||||
};
|
||||
summarySheet.getRangeByIndexes(15, 5, Math.max(relationRows.length - 1, 1), 1).format.numberFormat = "#,##0";
|
||||
|
||||
summarySheet.getRange("B24").values = [["说明"]];
|
||||
summarySheet.getRange("B25").values = [["订单所属合同按 合同管理_订单信息_基础表.项目流水号 = PDM_项目名称.项目流水号 关联。"]];
|
||||
summarySheet.getRange("B26").values = [["普通补货通常关联系统生成的补货合同,关联合同补货会指向对应销售合同。"]];
|
||||
summarySheet.getRange("B24").format.font = { name: "Arial", size: 11, bold: true, color: "#111827" };
|
||||
summarySheet.getRange("B25:B26").format.font = { name: "Arial", size: 10, color: "#374151" };
|
||||
summarySheet.getRange("B:I").format.autofitColumns();
|
||||
summarySheet.getRange("B:B").format.columnWidth = 22;
|
||||
summarySheet.getRange("E:E").format.columnWidth = 22;
|
||||
summarySheet.getRange("B2:I26").format.verticalAlignment = "center";
|
||||
|
||||
workbook.recalculate();
|
||||
|
||||
const summaryPreview = await workbook.render({
|
||||
sheetName: "汇总",
|
||||
range: "B2:F26",
|
||||
scale: 1,
|
||||
format: "png",
|
||||
});
|
||||
await fs.writeFile(path.join(outputDir, "summary_preview.png"), new Uint8Array(await summaryPreview.arrayBuffer()));
|
||||
|
||||
const detailPreview = await workbook.render({
|
||||
sheetName: "明细",
|
||||
range: "A1:AB20",
|
||||
scale: 1,
|
||||
format: "png",
|
||||
});
|
||||
await fs.writeFile(path.join(outputDir, "detail_preview.png"), new Uint8Array(await detailPreview.arrayBuffer()));
|
||||
|
||||
const check = await workbook.inspect({
|
||||
kind: "table",
|
||||
sheetId: "汇总",
|
||||
range: "B7:F20",
|
||||
include: "values",
|
||||
tableMaxRows: 20,
|
||||
tableMaxCols: 6,
|
||||
});
|
||||
console.log(check.ndjson);
|
||||
|
||||
const errors = await workbook.inspect({
|
||||
kind: "match",
|
||||
searchTerm: "#REF!|#DIV/0!|#VALUE!|#NAME\\?|#N/A|#NUM!|#NULL!|#SPILL!|#CALC!",
|
||||
options: { useRegex: true, maxResults: 300 },
|
||||
summary: "final formula error scan",
|
||||
});
|
||||
console.log(errors.ndjson);
|
||||
|
||||
await fs.mkdir(outputDir, { recursive: true });
|
||||
const xlsx = await SpreadsheetFile.exportXlsx(workbook);
|
||||
await xlsx.save(outputPath);
|
||||
console.log(`xlsx=${outputPath}`);
|
||||
console.log(`rows=${rows.length}`);
|
||||
BIN
outputs/order_contract_links_202609/detail_preview.png
Normal file
BIN
outputs/order_contract_links_202609/detail_preview.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 304 KiB |
@@ -0,0 +1,117 @@
|
||||
# 修改人:Ld 修改时间:2026-09-17 11:20:00; 从正式库导出本月订单与所属合同关联数据,供 Excel 生成脚本使用。
|
||||
$ErrorActionPreference = 'Stop'
|
||||
|
||||
$outputDir = Join-Path (Get-Location) 'outputs/order_contract_links_202609'
|
||||
New-Item -ItemType Directory -Force -Path $outputDir | Out-Null
|
||||
|
||||
$connectionString = 'Server=192.168.1.27;Database=ERPTOOL_JY;User ID=sa;Password=126.com;TrustServerCertificate=True;Connection Timeout=10'
|
||||
$connection = New-Object System.Data.SqlClient.SqlConnection $connectionString
|
||||
$connection.Open()
|
||||
|
||||
try {
|
||||
$command = $connection.CreateCommand()
|
||||
$command.CommandTimeout = 120
|
||||
$command.CommandText = @"
|
||||
DECLARE @开始日期 DATETIME = '2026-09-01';
|
||||
DECLARE @结束日期 DATETIME = '2026-10-01';
|
||||
|
||||
SELECT
|
||||
o.订单流水号,
|
||||
o.订单编号,
|
||||
o.订单类型,
|
||||
CASE
|
||||
WHEN o.订单类型 = 1 THEN N'模块销售订单'
|
||||
WHEN o.订单类型 = 2 THEN N'专机销售订单'
|
||||
WHEN o.订单类型 = 3 AND o.订单编号 LIKE N'BHWG%' THEN N'外购补货订单'
|
||||
WHEN o.订单类型 = 3 AND o.订单编号 LIKE N'BHZZ%' THEN N'自制补货订单'
|
||||
WHEN o.订单类型 = 3 THEN N'补货订单'
|
||||
WHEN o.订单类型 = 5 THEN N'售后订单'
|
||||
WHEN o.订单类型 = 6 THEN N'新模块订单'
|
||||
WHEN o.订单类型 = 7 THEN N'新专机订单'
|
||||
ELSE N'未定义'
|
||||
END AS 订单类型名称,
|
||||
CASE
|
||||
WHEN o.订单类型 = 3 AND o.订单编号 LIKE N'BHWG%' THEN N'外购补货'
|
||||
WHEN o.订单类型 = 3 AND o.订单编号 LIKE N'BHZZ%' THEN N'自制补货'
|
||||
ELSE N''
|
||||
END AS 补货类型,
|
||||
o.项目流水号,
|
||||
p.合同编号 AS 所属合同编号,
|
||||
p.合同类型 AS 所属合同类型,
|
||||
CASE
|
||||
WHEN p.合同类型 = 1 THEN N'模块合同'
|
||||
WHEN p.合同类型 = 2 THEN N'专机合同'
|
||||
WHEN p.合同类型 = 3 THEN N'补货/仓库备货合同'
|
||||
WHEN p.合同类型 = 5 THEN N'售后合同'
|
||||
WHEN p.合同类型 = 6 THEN N'新模块合同'
|
||||
WHEN p.合同类型 = 7 THEN N'新专机合同'
|
||||
ELSE N'未定义'
|
||||
END AS 所属合同类型名称,
|
||||
CASE
|
||||
WHEN o.订单类型 = 3 AND p.合同类型 <> 3 THEN N'补货挂销售合同'
|
||||
WHEN o.订单类型 = 3 AND p.合同类型 = 3 THEN N'补货独立合同'
|
||||
WHEN o.订单编号 = p.合同编号 THEN N'订单号同合同号'
|
||||
ELSE N'订单关联销售合同'
|
||||
END AS 关联类型,
|
||||
CASE WHEN p.项目流水号 IS NULL THEN N'否' ELSE N'是' END AS 是否已关联合同,
|
||||
CONVERT(varchar(19), o.下单日期, 120) AS 下单日期,
|
||||
ISNULL(d.姓名, N'') AS 下单人,
|
||||
ISNULL(pv.客户名称, N'') AS 客户名称,
|
||||
ISNULL(pv.收货人员, N'') AS 收货人员,
|
||||
ISNULL(pv.经手人, N'') AS 合同经手人,
|
||||
CONVERT(varchar(10), p.签订日期, 120) AS 合同签订日期,
|
||||
CONVERT(varchar(10), p.交货日期, 120) AS 合同交货日期,
|
||||
CONVERT(varchar(10), o.审核期限, 120) AS 审核期限,
|
||||
CONVERT(varchar(10), o.通用装配期限, 120) AS 通用装配期限,
|
||||
CONVERT(varchar(10), o.采购期限, 120) AS 采购期限,
|
||||
CONVERT(varchar(10), o.精工期限, 120) AS 精工期限,
|
||||
CONVERT(varchar(10), o.专机装配期限, 120) AS 专机装配期限,
|
||||
ISNULL(o.订单备注, N'') AS 订单备注,
|
||||
ISNULL(p.合同备注, N'') AS 合同备注,
|
||||
ISNULL(pv.状态, N'') AS 合同状态,
|
||||
ISNULL(ov.订单状态, N'') AS 订单状态,
|
||||
ISNULL(ov.下达部门, N'') AS 下达部门
|
||||
FROM dbo.合同管理_订单信息_基础表 o
|
||||
LEFT JOIN dbo.PDM_项目名称 p ON o.项目流水号 = p.项目流水号
|
||||
LEFT JOIN dbo.PDM_项目名称_视图 pv ON o.项目流水号 = pv.项目流水号
|
||||
LEFT JOIN dbo.PDM_订单信息_视图 ov ON o.订单流水号 = ov.订单流水号
|
||||
LEFT JOIN dbo.人事档案管理_人员名单 d ON o.下单人 = d.人员编号
|
||||
WHERE o.下单日期 >= @开始日期
|
||||
AND o.下单日期 < @结束日期
|
||||
ORDER BY o.下单日期 DESC, o.订单流水号 DESC;
|
||||
"@
|
||||
|
||||
$adapter = New-Object System.Data.SqlClient.SqlDataAdapter $command
|
||||
$table = New-Object System.Data.DataTable
|
||||
[void]$adapter.Fill($table)
|
||||
|
||||
$rows = foreach ($row in $table.Rows) {
|
||||
$object = [ordered]@{}
|
||||
foreach ($column in $table.Columns) {
|
||||
$value = $row[$column.ColumnName]
|
||||
if ($value -is [System.DBNull]) {
|
||||
$object[$column.ColumnName] = $null
|
||||
} else {
|
||||
$object[$column.ColumnName] = $value
|
||||
}
|
||||
}
|
||||
[pscustomobject]$object
|
||||
}
|
||||
|
||||
$jsonPath = Join-Path $outputDir 'order_contract_links_202609.json'
|
||||
$rows | ConvertTo-Json -Depth 4 | Set-Content -LiteralPath $jsonPath -Encoding UTF8
|
||||
|
||||
$summary = [ordered]@{
|
||||
数据库 = 'ERPTOOL_JY'
|
||||
开始日期 = '2026-09-01'
|
||||
结束日期 = '2026-10-01'
|
||||
导出时间 = (Get-Date -Format 'yyyy-MM-dd HH:mm:ss')
|
||||
记录数 = $table.Rows.Count
|
||||
}
|
||||
$summary | ConvertTo-Json -Depth 3 | Set-Content -LiteralPath (Join-Path $outputDir 'extract_summary.json') -Encoding UTF8
|
||||
|
||||
Write-Output "exported=$($table.Rows.Count)"
|
||||
Write-Output "json=$jsonPath"
|
||||
} finally {
|
||||
$connection.Close()
|
||||
}
|
||||
7
outputs/order_contract_links_202609/extract_summary.json
Normal file
7
outputs/order_contract_links_202609/extract_summary.json
Normal file
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"数据库": "ERPTOOL_JY",
|
||||
"开始日期": "2026-09-01",
|
||||
"结束日期": "2026-10-01",
|
||||
"导出时间": "2026-09-17 11:32:33",
|
||||
"记录数": 276
|
||||
}
|
||||
8282
outputs/order_contract_links_202609/order_contract_links_202609.json
Normal file
8282
outputs/order_contract_links_202609/order_contract_links_202609.json
Normal file
File diff suppressed because it is too large
Load Diff
BIN
outputs/order_contract_links_202609/summary_preview.png
Normal file
BIN
outputs/order_contract_links_202609/summary_preview.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 64 KiB |
BIN
outputs/order_contract_links_202609/正式库订单关联合同明细_2026-09.xlsx
Normal file
BIN
outputs/order_contract_links_202609/正式库订单关联合同明细_2026-09.xlsx
Normal file
Binary file not shown.
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user