회사별 메뉴 분리 및 권한 관리

This commit is contained in:
kjs
2025-10-28 10:07:07 +09:00
parent 35581ac8d2
commit 25f6217433
13 changed files with 1273 additions and 370 deletions

View File

@@ -8,6 +8,7 @@ export interface CodeCategory {
description?: string | null;
sort_order: number;
is_active: string;
company_code: string; // 추가
created_date?: Date | null;
created_by?: string | null;
updated_date?: Date | null;
@@ -22,6 +23,7 @@ export interface CodeInfo {
description?: string | null;
sort_order: number;
is_active: string;
company_code: string; // 추가
created_date?: Date | null;
created_by?: string | null;
updated_date?: Date | null;
@@ -64,7 +66,7 @@ export class CommonCodeService {
/**
* 카테고리 목록 조회
*/
async getCategories(params: GetCategoriesParams) {
async getCategories(params: GetCategoriesParams, userCompanyCode?: string) {
try {
const { search, isActive, page = 1, size = 20 } = params;
@@ -72,6 +74,17 @@ export class CommonCodeService {
const values: any[] = [];
let paramIndex = 1;
// 회사별 필터링 (최고 관리자가 아닌 경우)
if (userCompanyCode && userCompanyCode !== "*") {
whereConditions.push(`company_code = $${paramIndex}`);
values.push(userCompanyCode);
paramIndex++;
logger.info(`회사별 코드 카테고리 필터링: ${userCompanyCode}`);
} else if (userCompanyCode === "*") {
// 최고 관리자는 모든 데이터 조회 가능
logger.info(`최고 관리자: 모든 코드 카테고리 조회`);
}
if (search) {
whereConditions.push(
`(category_name ILIKE $${paramIndex} OR category_code ILIKE $${paramIndex})`
@@ -110,7 +123,7 @@ export class CommonCodeService {
const total = parseInt(countResult?.count || "0");
logger.info(
`카테고리 조회 완료: ${categories.length}개, 전체: ${total}`
`카테고리 조회 완료: ${categories.length}개, 전체: ${total} (회사: ${userCompanyCode || "전체"})`
);
return {
@@ -126,7 +139,11 @@ export class CommonCodeService {
/**
* 카테고리별 코드 목록 조회
*/
async getCodes(categoryCode: string, params: GetCodesParams) {
async getCodes(
categoryCode: string,
params: GetCodesParams,
userCompanyCode?: string
) {
try {
const { search, isActive, page = 1, size = 20 } = params;
@@ -134,6 +151,16 @@ export class CommonCodeService {
const values: any[] = [categoryCode];
let paramIndex = 2;
// 회사별 필터링 (최고 관리자가 아닌 경우)
if (userCompanyCode && userCompanyCode !== "*") {
whereConditions.push(`company_code = $${paramIndex}`);
values.push(userCompanyCode);
paramIndex++;
logger.info(`회사별 코드 필터링: ${userCompanyCode}`);
} else if (userCompanyCode === "*") {
logger.info(`최고 관리자: 모든 코드 조회`);
}
if (search) {
whereConditions.push(
`(code_name ILIKE $${paramIndex} OR code_value ILIKE $${paramIndex})`
@@ -169,7 +196,7 @@ export class CommonCodeService {
const total = parseInt(countResult?.count || "0");
logger.info(
`코드 조회 완료: ${categoryCode} - ${codes.length}개, 전체: ${total}`
`코드 조회 완료: ${categoryCode} - ${codes.length}개, 전체: ${total} (회사: ${userCompanyCode || "전체"})`
);
return { data: codes, total };
@@ -182,13 +209,17 @@ export class CommonCodeService {
/**
* 카테고리 생성
*/
async createCategory(data: CreateCategoryData, createdBy: string) {
async createCategory(
data: CreateCategoryData,
createdBy: string,
companyCode: string
) {
try {
const category = await queryOne<CodeCategory>(
`INSERT INTO code_category
(category_code, category_name, category_name_eng, description, sort_order,
is_active, created_by, updated_by, created_date, updated_date)
VALUES ($1, $2, $3, $4, $5, 'Y', $6, $7, NOW(), NOW())
is_active, company_code, created_by, updated_by, created_date, updated_date)
VALUES ($1, $2, $3, $4, $5, 'Y', $6, $7, $8, NOW(), NOW())
RETURNING *`,
[
data.categoryCode,
@@ -196,12 +227,15 @@ export class CommonCodeService {
data.categoryNameEng || null,
data.description || null,
data.sortOrder || 0,
companyCode,
createdBy,
createdBy,
]
);
logger.info(`카테고리 생성 완료: ${data.categoryCode}`);
logger.info(
`카테고리 생성 완료: ${data.categoryCode} (회사: ${companyCode})`
);
return category;
} catch (error) {
logger.error("카테고리 생성 중 오류:", error);
@@ -215,11 +249,12 @@ export class CommonCodeService {
async updateCategory(
categoryCode: string,
data: Partial<CreateCategoryData>,
updatedBy: string
updatedBy: string,
companyCode?: string
) {
try {
// 디버깅: 받은 데이터 로그
logger.info(`카테고리 수정 데이터:`, { categoryCode, data });
logger.info(`카테고리 수정 데이터:`, { categoryCode, data, companyCode });
// 동적 UPDATE 쿼리 생성
const updateFields: string[] = [
@@ -256,15 +291,28 @@ export class CommonCodeService {
values.push(activeValue);
}
// WHERE 절 구성
let whereClause = `WHERE category_code = $${paramIndex}`;
values.push(categoryCode);
// 회사 필터링 (최고 관리자가 아닌 경우)
if (companyCode && companyCode !== "*") {
paramIndex++;
whereClause += ` AND company_code = $${paramIndex}`;
values.push(companyCode);
}
const category = await queryOne<CodeCategory>(
`UPDATE code_category
SET ${updateFields.join(", ")}
WHERE category_code = $${paramIndex}
${whereClause}
RETURNING *`,
[...values, categoryCode]
values
);
logger.info(`카테고리 수정 완료: ${categoryCode}`);
logger.info(
`카테고리 수정 완료: ${categoryCode} (회사: ${companyCode || "전체"})`
);
return category;
} catch (error) {
logger.error(`카테고리 수정 중 오류 (${categoryCode}):`, error);
@@ -275,13 +323,22 @@ export class CommonCodeService {
/**
* 카테고리 삭제
*/
async deleteCategory(categoryCode: string) {
async deleteCategory(categoryCode: string, companyCode?: string) {
try {
await query(`DELETE FROM code_category WHERE category_code = $1`, [
categoryCode,
]);
let sql = `DELETE FROM code_category WHERE category_code = $1`;
const values: any[] = [categoryCode];
logger.info(`카테고리 삭제 완료: ${categoryCode}`);
// 회사 필터링 (최고 관리자가 아닌 경우)
if (companyCode && companyCode !== "*") {
sql += ` AND company_code = $2`;
values.push(companyCode);
}
await query(sql, values);
logger.info(
`카테고리 삭제 완료: ${categoryCode} (회사: ${companyCode || "전체"})`
);
} catch (error) {
logger.error(`카테고리 삭제 중 오류 (${categoryCode}):`, error);
throw error;
@@ -294,14 +351,15 @@ export class CommonCodeService {
async createCode(
categoryCode: string,
data: CreateCodeData,
createdBy: string
createdBy: string,
companyCode: string
) {
try {
const code = await queryOne<CodeInfo>(
`INSERT INTO code_info
(code_category, code_value, code_name, code_name_eng, description, sort_order,
is_active, created_by, updated_by, created_date, updated_date)
VALUES ($1, $2, $3, $4, $5, $6, 'Y', $7, $8, NOW(), NOW())
is_active, company_code, created_by, updated_by, created_date, updated_date)
VALUES ($1, $2, $3, $4, $5, $6, 'Y', $7, $8, $9, NOW(), NOW())
RETURNING *`,
[
categoryCode,
@@ -310,12 +368,15 @@ export class CommonCodeService {
data.codeNameEng || null,
data.description || null,
data.sortOrder || 0,
companyCode,
createdBy,
createdBy,
]
);
logger.info(`코드 생성 완료: ${categoryCode}.${data.codeValue}`);
logger.info(
`코드 생성 완료: ${categoryCode}.${data.codeValue} (회사: ${companyCode})`
);
return code;
} catch (error) {
logger.error(
@@ -333,11 +394,17 @@ export class CommonCodeService {
categoryCode: string,
codeValue: string,
data: Partial<CreateCodeData>,
updatedBy: string
updatedBy: string,
companyCode?: string
) {
try {
// 디버깅: 받은 데이터 로그
logger.info(`코드 수정 데이터:`, { categoryCode, codeValue, data });
logger.info(`코드 수정 데이터:`, {
categoryCode,
codeValue,
data,
companyCode,
});
// 동적 UPDATE 쿼리 생성
const updateFields: string[] = [
@@ -374,15 +441,28 @@ export class CommonCodeService {
values.push(activeValue);
}
// WHERE 절 구성
let whereClause = `WHERE code_category = $${paramIndex++} AND code_value = $${paramIndex}`;
values.push(categoryCode, codeValue);
// 회사 필터링 (최고 관리자가 아닌 경우)
if (companyCode && companyCode !== "*") {
paramIndex++;
whereClause += ` AND company_code = $${paramIndex}`;
values.push(companyCode);
}
const code = await queryOne<CodeInfo>(
`UPDATE code_info
SET ${updateFields.join(", ")}
WHERE code_category = $${paramIndex++} AND code_value = $${paramIndex}
${whereClause}
RETURNING *`,
[...values, categoryCode, codeValue]
values
);
logger.info(`코드 수정 완료: ${categoryCode}.${codeValue}`);
logger.info(
`코드 수정 완료: ${categoryCode}.${codeValue} (회사: ${companyCode || "전체"})`
);
return code;
} catch (error) {
logger.error(`코드 수정 중 오류 (${categoryCode}.${codeValue}):`, error);
@@ -393,14 +473,26 @@ export class CommonCodeService {
/**
* 코드 삭제
*/
async deleteCode(categoryCode: string, codeValue: string) {
async deleteCode(
categoryCode: string,
codeValue: string,
companyCode?: string
) {
try {
await query(
`DELETE FROM code_info WHERE code_category = $1 AND code_value = $2`,
[categoryCode, codeValue]
);
let sql = `DELETE FROM code_info WHERE code_category = $1 AND code_value = $2`;
const values: any[] = [categoryCode, codeValue];
logger.info(`코드 삭제 완료: ${categoryCode}.${codeValue}`);
// 회사 필터링 (최고 관리자가 아닌 경우)
if (companyCode && companyCode !== "*") {
sql += ` AND company_code = $3`;
values.push(companyCode);
}
await query(sql, values);
logger.info(
`코드 삭제 완료: ${categoryCode}.${codeValue} (회사: ${companyCode || "전체"})`
);
} catch (error) {
logger.error(`코드 삭제 중 오류 (${categoryCode}.${codeValue}):`, error);
throw error;
@@ -410,20 +502,30 @@ export class CommonCodeService {
/**
* 카테고리별 옵션 조회 (화면관리용)
*/
async getCodeOptions(categoryCode: string) {
async getCodeOptions(categoryCode: string, userCompanyCode?: string) {
try {
let sql = `SELECT code_value, code_name, code_name_eng, sort_order
FROM code_info
WHERE code_category = $1 AND is_active = 'Y'`;
const values: any[] = [categoryCode];
// 회사별 필터링 (최고 관리자가 아닌 경우)
if (userCompanyCode && userCompanyCode !== "*") {
sql += ` AND company_code = $2`;
values.push(userCompanyCode);
logger.info(`회사별 코드 옵션 필터링: ${userCompanyCode}`);
} else if (userCompanyCode === "*") {
logger.info(`최고 관리자: 모든 코드 옵션 조회`);
}
sql += ` ORDER BY sort_order ASC, code_value ASC`;
const codes = await query<{
code_value: string;
code_name: string;
code_name_eng: string | null;
sort_order: number;
}>(
`SELECT code_value, code_name, code_name_eng, sort_order
FROM code_info
WHERE code_category = $1 AND is_active = 'Y'
ORDER BY sort_order ASC, code_value ASC`,
[categoryCode]
);
}>(sql, values);
const options = codes.map((code) => ({
value: code.code_value,
@@ -431,7 +533,9 @@ export class CommonCodeService {
labelEng: code.code_name_eng,
}));
logger.info(`코드 옵션 조회 완료: ${categoryCode} - ${options.length}`);
logger.info(
`코드 옵션 조회 완료: ${categoryCode} - ${options.length}개 (회사: ${userCompanyCode || "전체"})`
);
return options;
} catch (error) {
logger.error(`코드 옵션 조회 중 오류 (${categoryCode}):`, error);