Merge remote-tracking branch 'origin/jskim-node' into gbpark-node

This commit is contained in:
DDD1542
2026-04-23 14:03:57 +09:00
285 changed files with 24705 additions and 4629 deletions

View File

@@ -60,8 +60,9 @@ export async function getBomHeader(bomId: string, tableName?: string) {
const sql = `
SELECT b.*,
i.item_name, i.item_number, i.division as item_type,
COALESCE(b.unit, i.unit) as unit,
COALESCE(NULLIF(b.unit, ''), NULLIF(i.unit, ''), NULLIF(i.inventory_unit, '')) as unit,
i.unit as item_unit,
i.inventory_unit as item_inventory_unit,
i.division, i.size, i.material
FROM ${table} b
LEFT JOIN item_info i ON b.item_id = i.id

View File

@@ -223,13 +223,14 @@ class CategoryTreeService {
const query = `
INSERT INTO category_values (
table_name, column_name, value_code, value_label, value_order,
value_id, table_name, column_name, value_code, value_label, value_order,
parent_value_id, depth, path, description, color, icon,
is_active, is_default, company_code, created_by, updated_by
) VALUES (
(SELECT COALESCE(MAX(value_id), 0) + 1 FROM category_values),
$1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $15
)
RETURNING
RETURNING
value_id AS "valueId",
table_name AS "tableName",
column_name AS "columnName",

View File

@@ -694,13 +694,16 @@ export async function mergeSchedules(
[companyCode, ...scheduleIds]
);
// 병합된 스케줄 생성
// 병합된 스케줄 생성 (PP-YYYYMMDD-NNNN 형식)
const todayStr = new Date().toISOString().split("T")[0].replace(/-/g, "");
const planNoResult = await client.query(
`SELECT COALESCE(MAX(CAST(REPLACE(plan_no, 'PP-', '') AS INTEGER)), 0) + 1 AS next_no
FROM production_plan_mng WHERE company_code = $1`,
[companyCode]
`SELECT COUNT(*) + 1 AS next_no
FROM production_plan_mng
WHERE company_code = $1 AND plan_no LIKE $2`,
[companyCode, `PP-${todayStr}-%`]
);
const planNo = `PP-${String(planNoResult.rows[0].next_no || 1).padStart(6, "0")}`;
const nextNo = parseInt(planNoResult.rows[0].next_no, 10) || 1;
const planNo = `PP-${todayStr}-${String(nextNo).padStart(4, "0")}`;
const insertResult = await client.query(
`INSERT INTO production_plan_mng (
@@ -1017,13 +1020,16 @@ export async function splitSchedule(
[originalQty - splitQty, splitBy, planId, companyCode]
);
// 분할된 새 계획 생성
// 분할된 새 계획 생성 (PP-YYYYMMDD-NNNN 형식)
const todayStr = new Date().toISOString().split("T")[0].replace(/-/g, "");
const planNoResult = await client.query(
`SELECT COALESCE(MAX(CAST(REPLACE(plan_no, 'PP-', '') AS INTEGER)), 0) + 1 AS next_no
FROM production_plan_mng WHERE company_code = $1`,
[companyCode]
`SELECT COUNT(*) + 1 AS next_no
FROM production_plan_mng
WHERE company_code = $1 AND plan_no LIKE $2`,
[companyCode, `PP-${todayStr}-%`]
);
const planNo = `PP-${String(planNoResult.rows[0].next_no || 1).padStart(6, "0")}`;
const nextNo = parseInt(planNoResult.rows[0].next_no, 10) || 1;
const planNo = `PP-${todayStr}-${String(nextNo).padStart(4, "0")}`;
const insertResult = await client.query(
`INSERT INTO production_plan_mng (

View File

@@ -884,18 +884,23 @@ export class ReportService {
menuObjid: number,
companyCode: string
): Promise<{ items: ReportMaster[]; total: number }> {
// 매핑 없는 리포트(글로벌)는 어느 메뉴에서나 보이고,
// 매핑 있는 리포트는 해당 menu_objid에 매핑된 경우에만 보임.
const companyFilter = companyCode !== "*" ? " AND rm.company_code = $2" : "";
const params = companyCode !== "*" ? [menuObjid, companyCode] : [menuObjid];
const items = await query<ReportMaster>(
`SELECT rm.report_id, rm.report_name_kor, rm.report_name_eng,
`SELECT DISTINCT rm.report_id, rm.report_name_kor, rm.report_name_eng,
rm.template_id, rt.template_name_kor AS template_name,
rm.report_type, rm.company_code, rm.description, rm.use_yn,
rm.created_at, rm.created_by, rm.updated_at, rm.updated_by
FROM report_master rm
JOIN report_menu_mapping rmm ON rm.report_id = rmm.report_id
LEFT JOIN report_template rt ON rm.template_id = rt.template_id
WHERE rmm.menu_objid = $1 AND rm.use_yn = 'Y'${companyFilter}
WHERE rm.use_yn = 'Y'${companyFilter}
AND (
NOT EXISTS (SELECT 1 FROM report_menu_mapping WHERE report_id = rm.report_id)
OR EXISTS (SELECT 1 FROM report_menu_mapping WHERE report_id = rm.report_id AND menu_objid = $1)
)
ORDER BY rm.report_name_kor ASC`,
params
);

View File

@@ -167,7 +167,8 @@ class TableCategoryValueService {
columnName: string,
companyCode: string,
includeInactive: boolean = false,
menuObjid?: number
menuObjid?: number,
topLevelOnly: boolean = false
): Promise<TableCategoryValue[]> {
try {
logger.info("카테고리 값 목록 조회 (메뉴 스코프)", {
@@ -235,6 +236,10 @@ class TableCategoryValueService {
query += ` AND is_active = true`;
}
if (topLevelOnly) {
query += ` AND (depth = 1 OR depth IS NULL OR parent_value_id IS NULL)`;
}
query += ` ORDER BY value_order, value_label`;
const result = await pool.query(query, params);