feat(mgmt-perf): 대시보드 연도·분기 조회(스냅샷별 로드)
- getPayloadRowForPeriod, listDistinctPeriods - /dashboard/business-performance?year=&quarter= 및 상단 GET 폼 - 해당 기간 업로드 없을 때 샘플+안내 Made-with: Cursor
This commit is contained in:
@@ -142,6 +142,100 @@ async function getLatestPayloadRow(pgPool) {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* DB에 저장된 연도·분기별 최신 스냅샷 1건. 해당 기간 업로드가 없으면 기본 페이로드와 `_noSnapshotForPeriod`.
|
||||
* @param {import("pg").Pool | null} pgPool
|
||||
* @param {number} fiscalYear
|
||||
* @param {number} quarter 1–4
|
||||
*/
|
||||
async function getPayloadRowForPeriod(pgPool, fiscalYear, quarter) {
|
||||
const y = Math.min(2100, Math.max(2020, Math.floor(Number(fiscalYear)) || new Date().getFullYear()));
|
||||
const q = Math.min(4, Math.max(1, Math.floor(Number(quarter)) || 1));
|
||||
|
||||
if (pgPool) {
|
||||
const r = await pgPool.query(
|
||||
`
|
||||
SELECT s.payload, u.fiscal_year, u.quarter, u.original_filename, u.created_at
|
||||
FROM mgmt_perf_snapshots s
|
||||
JOIN mgmt_perf_uploads u ON u.id = s.upload_id
|
||||
WHERE u.fiscal_year = $1 AND u.quarter = $2
|
||||
ORDER BY u.created_at DESC
|
||||
LIMIT 1
|
||||
`,
|
||||
[y, q]
|
||||
);
|
||||
if (r.rows[0]) {
|
||||
const row = r.rows[0];
|
||||
return {
|
||||
payload: row.payload,
|
||||
fiscal_year: row.fiscal_year,
|
||||
quarter: row.quarter,
|
||||
original_filename: row.original_filename,
|
||||
created_at: row.created_at,
|
||||
_noSnapshotForPeriod: false,
|
||||
};
|
||||
}
|
||||
return {
|
||||
payload: loadDefaultPayload(),
|
||||
fiscal_year: y,
|
||||
quarter: q,
|
||||
original_filename: null,
|
||||
created_at: null,
|
||||
_noSnapshotForPeriod: true,
|
||||
};
|
||||
}
|
||||
|
||||
try {
|
||||
const j = JSON.parse(fs.readFileSync(FILE_STATE_PATH, "utf8"));
|
||||
const my = j.meta?.fiscalYear;
|
||||
const mq = j.meta?.quarter;
|
||||
if (my === y && mq === q) {
|
||||
return {
|
||||
payload: j.payload,
|
||||
fiscal_year: y,
|
||||
quarter: q,
|
||||
original_filename: j.meta?.originalFilename,
|
||||
created_at: j.meta?.savedAt ? new Date(j.meta.savedAt) : null,
|
||||
_noSnapshotForPeriod: false,
|
||||
};
|
||||
}
|
||||
} catch (_) {
|
||||
/* no file */
|
||||
}
|
||||
return {
|
||||
payload: loadDefaultPayload(),
|
||||
fiscal_year: y,
|
||||
quarter: q,
|
||||
original_filename: null,
|
||||
created_at: null,
|
||||
_noSnapshotForPeriod: true,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* 업로드가 존재하는 (연도, 분기) 목록 — 조회 셀렉트 옵션용
|
||||
* @param {import("pg").Pool | null} pgPool
|
||||
*/
|
||||
async function listDistinctPeriods(pgPool) {
|
||||
if (!pgPool) {
|
||||
try {
|
||||
const j = JSON.parse(fs.readFileSync(FILE_STATE_PATH, "utf8"));
|
||||
if (j.meta?.fiscalYear != null && j.meta?.quarter != null) {
|
||||
return [{ fiscal_year: j.meta.fiscalYear, quarter: j.meta.quarter }];
|
||||
}
|
||||
} catch (_) {
|
||||
/* empty */
|
||||
}
|
||||
return [];
|
||||
}
|
||||
const r = await pgPool.query(`
|
||||
SELECT DISTINCT fiscal_year, quarter
|
||||
FROM mgmt_perf_uploads
|
||||
ORDER BY fiscal_year DESC, quarter DESC
|
||||
`);
|
||||
return r.rows;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {import("pg").Pool | null} pgPool
|
||||
* @param {number} [limit=20]
|
||||
@@ -215,6 +309,8 @@ module.exports = {
|
||||
buildPayloadFromWorkbook,
|
||||
saveUploadAndSnapshot,
|
||||
getLatestPayloadRow,
|
||||
getPayloadRowForPeriod,
|
||||
listDistinctPeriods,
|
||||
listUploads,
|
||||
deleteUpload,
|
||||
FILE_STATE_PATH,
|
||||
|
||||
Reference in New Issue
Block a user