Merge branch 'feature/v2-renewal' of http://39.117.244.52:3000/kjs/ERP-node into feature/v2-unified-renewal
This commit is contained in:
@@ -635,7 +635,76 @@ export class ScreenManagementService {
|
||||
|
||||
// 트랜잭션으로 화면 삭제와 메뉴 할당 정리를 함께 처리 (Raw Query)
|
||||
await transaction(async (client) => {
|
||||
// 소프트 삭제 (휴지통으로 이동)
|
||||
// 1. 화면에서 사용하는 flowId 수집 (V2 레이아웃)
|
||||
const layoutResult = await client.query<{ layout_data: any }>(
|
||||
`SELECT layout_data FROM screen_layouts_v2
|
||||
WHERE screen_id = $1 AND (company_code = $2 OR company_code = '*')
|
||||
ORDER BY CASE WHEN company_code = $2 THEN 0 ELSE 1 END
|
||||
LIMIT 1`,
|
||||
[screenId, userCompanyCode],
|
||||
);
|
||||
|
||||
const layoutData = layoutResult.rows[0]?.layout_data;
|
||||
const flowIds = this.collectFlowIdsFromLayoutData(layoutData);
|
||||
|
||||
// 2. 각 flowId가 다른 화면에서도 사용되는지 체크 후 삭제
|
||||
if (flowIds.size > 0) {
|
||||
for (const flowId of flowIds) {
|
||||
// 다른 화면에서 사용 중인지 확인 (같은 회사 내, 삭제되지 않은 화면 기준)
|
||||
const companyFilterForCheck = userCompanyCode === "*" ? "" : " AND sd.company_code = $3";
|
||||
const checkParams = userCompanyCode === "*"
|
||||
? [screenId, flowId]
|
||||
: [screenId, flowId, userCompanyCode];
|
||||
|
||||
const otherUsageResult = await client.query<{ count: string }>(
|
||||
`SELECT COUNT(*) as count FROM screen_layouts_v2 slv
|
||||
JOIN screen_definitions sd ON slv.screen_id = sd.screen_id
|
||||
WHERE slv.screen_id != $1
|
||||
AND sd.is_active != 'D'
|
||||
${companyFilterForCheck}
|
||||
AND (
|
||||
slv.layout_data::text LIKE '%"flowId":' || $2 || '%'
|
||||
OR slv.layout_data::text LIKE '%"flowId":"' || $2 || '"%'
|
||||
)`,
|
||||
checkParams,
|
||||
);
|
||||
|
||||
const otherUsageCount = parseInt(otherUsageResult.rows[0]?.count || "0");
|
||||
|
||||
// 다른 화면에서 사용하지 않는 경우에만 플로우 삭제
|
||||
if (otherUsageCount === 0) {
|
||||
// 해당 회사의 플로우만 삭제 (멀티테넌시)
|
||||
const companyFilter = userCompanyCode === "*" ? "" : " AND company_code = $2";
|
||||
const flowParams = userCompanyCode === "*" ? [flowId] : [flowId, userCompanyCode];
|
||||
|
||||
// 1. flow_definition 관련 데이터 먼저 삭제 (외래키 순서)
|
||||
await client.query(
|
||||
`DELETE FROM flow_step_connection WHERE flow_definition_id = $1`,
|
||||
[flowId],
|
||||
);
|
||||
await client.query(
|
||||
`DELETE FROM flow_step WHERE flow_definition_id = $1`,
|
||||
[flowId],
|
||||
);
|
||||
await client.query(
|
||||
`DELETE FROM flow_definition WHERE id = $1${companyFilter}`,
|
||||
flowParams,
|
||||
);
|
||||
|
||||
// 2. node_flows 테이블에서도 삭제 (제어플로우)
|
||||
await client.query(
|
||||
`DELETE FROM node_flows WHERE flow_id = $1${companyFilter}`,
|
||||
flowParams,
|
||||
);
|
||||
|
||||
logger.info("화면 삭제 시 플로우 삭제 (flow_definition + node_flows)", { screenId, flowId, companyCode: userCompanyCode });
|
||||
} else {
|
||||
logger.debug("플로우가 다른 화면에서 사용 중 - 삭제 스킵", { screenId, flowId, otherUsageCount });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 3. 소프트 삭제 (휴지통으로 이동)
|
||||
await client.query(
|
||||
`UPDATE screen_definitions
|
||||
SET is_active = 'D',
|
||||
@@ -655,7 +724,7 @@ export class ScreenManagementService {
|
||||
],
|
||||
);
|
||||
|
||||
// 메뉴 할당도 비활성화
|
||||
// 4. 메뉴 할당도 비활성화
|
||||
await client.query(
|
||||
`UPDATE screen_menu_assignments
|
||||
SET is_active = 'N'
|
||||
@@ -2946,7 +3015,7 @@ export class ScreenManagementService {
|
||||
* - current_sequence는 0으로 초기화
|
||||
*/
|
||||
/**
|
||||
* 채번 규칙 복제 (numbering_rules_test 테이블 사용)
|
||||
* 채번 규칙 복제 (numbering_rules 테이블 사용)
|
||||
* - menu_objid 의존성 제거됨
|
||||
* - table_name + column_name + company_code 기반
|
||||
*/
|
||||
@@ -2964,10 +3033,10 @@ export class ScreenManagementService {
|
||||
|
||||
console.log(`🔄 채번 규칙 복사 시작: ${ruleIds.size}개 규칙`);
|
||||
|
||||
// 1. 원본 채번 규칙 조회 (numbering_rules_test 테이블)
|
||||
// 1. 원본 채번 규칙 조회 (numbering_rules 테이블)
|
||||
const ruleIdArray = Array.from(ruleIds);
|
||||
const sourceRulesResult = await client.query(
|
||||
`SELECT * FROM numbering_rules_test WHERE rule_id = ANY($1)`,
|
||||
`SELECT * FROM numbering_rules WHERE rule_id = ANY($1)`,
|
||||
[ruleIdArray],
|
||||
);
|
||||
|
||||
@@ -2980,7 +3049,7 @@ export class ScreenManagementService {
|
||||
|
||||
// 2. 대상 회사의 기존 채번 규칙 조회 (이름 기준)
|
||||
const existingRulesResult = await client.query(
|
||||
`SELECT rule_id, rule_name FROM numbering_rules_test WHERE company_code = $1`,
|
||||
`SELECT rule_id, rule_name FROM numbering_rules WHERE company_code = $1`,
|
||||
[targetCompanyCode],
|
||||
);
|
||||
const existingRulesByName = new Map<string, string>(
|
||||
@@ -3001,9 +3070,9 @@ export class ScreenManagementService {
|
||||
// 새로 복사 - 새 rule_id 생성
|
||||
const newRuleId = `rule-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
|
||||
|
||||
// numbering_rules_test 복사 (current_sequence = 0으로 초기화)
|
||||
// numbering_rules 복사 (current_sequence = 0으로 초기화)
|
||||
await client.query(
|
||||
`INSERT INTO numbering_rules_test (
|
||||
`INSERT INTO numbering_rules (
|
||||
rule_id, rule_name, description, separator, reset_period,
|
||||
current_sequence, table_name, column_name, company_code,
|
||||
created_at, updated_at, created_by, last_generated_date,
|
||||
@@ -3028,15 +3097,15 @@ export class ScreenManagementService {
|
||||
],
|
||||
);
|
||||
|
||||
// numbering_rule_parts_test 복사
|
||||
// numbering_rule_parts 복사
|
||||
const partsResult = await client.query(
|
||||
`SELECT * FROM numbering_rule_parts_test WHERE rule_id = $1 ORDER BY part_order`,
|
||||
`SELECT * FROM numbering_rule_parts WHERE rule_id = $1 ORDER BY part_order`,
|
||||
[rule.rule_id],
|
||||
);
|
||||
|
||||
for (const part of partsResult.rows) {
|
||||
await client.query(
|
||||
`INSERT INTO numbering_rule_parts_test (
|
||||
`INSERT INTO numbering_rule_parts (
|
||||
rule_id, part_order, part_type, generation_method,
|
||||
auto_config, manual_config, company_code, created_at
|
||||
) VALUES ($1, $2, $3, $4, $5, $6, $7, $8)`,
|
||||
@@ -4542,7 +4611,8 @@ export class ScreenManagementService {
|
||||
);
|
||||
|
||||
if (menuInfo.rows.length > 0) {
|
||||
const isAdminMenu = menuInfo.rows[0].menu_type === "1";
|
||||
// menu_type: "0" = 관리자 메뉴, "1" = 사용자 메뉴
|
||||
const isAdminMenu = menuInfo.rows[0].menu_type === "0";
|
||||
const newMenuUrl = isAdminMenu
|
||||
? `/screens/${newScreenId}?mode=admin`
|
||||
: `/screens/${newScreenId}`;
|
||||
@@ -4707,7 +4777,7 @@ export class ScreenManagementService {
|
||||
}
|
||||
|
||||
/**
|
||||
* 카테고리 값 복제 (category_values_test 테이블 사용)
|
||||
* 카테고리 값 복제 (category_values 테이블 사용)
|
||||
* - menu_objid 의존성 제거됨
|
||||
* - table_name + column_name + company_code 기반
|
||||
*/
|
||||
@@ -4741,13 +4811,13 @@ export class ScreenManagementService {
|
||||
|
||||
// 1. 기존 대상 회사 데이터 삭제 (다른 회사로 복제 시에만)
|
||||
await client.query(
|
||||
`DELETE FROM category_values_test WHERE company_code = $1`,
|
||||
`DELETE FROM category_values WHERE company_code = $1`,
|
||||
[targetCompanyCode],
|
||||
);
|
||||
|
||||
// 2. category_values_test 복제
|
||||
// 2. category_values 복제
|
||||
const values = await client.query(
|
||||
`SELECT * FROM category_values_test WHERE company_code = $1`,
|
||||
`SELECT * FROM category_values WHERE company_code = $1`,
|
||||
[sourceCompanyCode],
|
||||
);
|
||||
|
||||
@@ -4756,7 +4826,7 @@ export class ScreenManagementService {
|
||||
|
||||
for (const v of values.rows) {
|
||||
const insertResult = await client.query(
|
||||
`INSERT INTO category_values_test
|
||||
`INSERT INTO category_values
|
||||
(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)
|
||||
@@ -4791,7 +4861,7 @@ export class ScreenManagementService {
|
||||
const newValueId = valueIdMap.get(v.value_id);
|
||||
if (newParentId && newValueId) {
|
||||
await client.query(
|
||||
`UPDATE category_values_test SET parent_value_id = $1 WHERE value_id = $2`,
|
||||
`UPDATE category_values SET parent_value_id = $1 WHERE value_id = $2`,
|
||||
[newParentId, newValueId],
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user