ccb0c8df4c
- Created a new .env.example file to provide a template for environment variables, including database connection details, JWT settings, encryption keys, and external API keys. - Updated .gitignore to include additional test output directories and archive files, ensuring that unnecessary files are not tracked by Git. - Removed outdated approval test reports and scripts that are no longer needed, streamlining the project structure. These changes improve the clarity of environment configuration and maintain a cleaner repository.
23 KiB
23 KiB
POP 화면 배포서버 마이그레이션 가이드
작성일: 2026-03-23 목적: 로컬(탑씰 COMPANY_7) POP 화면 5종을 배포서버 COMPANY_21(테스트회사)로 복사 대상 화면: 4173, 4479, 4480, 4576, 4577 주의: DB 작업 전 반드시 백업 후 진행
0. 개념 정리 (먼저 읽기)
PopDeployModal이란?
POP 관리 화면 내 내장된 화면 배포 도구입니다.
- 접근: POP 디자이너 > 카테고리 트리 > 그룹 우클릭 또는 배포 버튼
- 하는 일:
- 선택한 화면들을 다른 회사 계정으로 복사 (
screen_definitions새 행 생성) - POP 레이아웃 JSON 복사 (
screen_layouts_pop) - layout_json 내 화면 ID 참조 자동 리매핑 (screenId, cartScreenId, sourceScreenId, targetScreenId)
- 카테고리 그룹 구조 생성 (
screen_groups,screen_group_screens) - numberingRuleId 자동 제거 (회사별 고유값이므로)
- 선택한 화면들을 다른 회사 계정으로 복사 (
- 제약: 같은 서버 안에서만 동작 (로컬 → 배포 서버 간 복사 불가)
- 권장 사용 시점: 배포 DB COMPANY_7에 화면이 먼저 세팅된 후, 같은 배포 서버 내 테스트 계정으로 복사할 때
마이그레이션 전체 흐름
[로컬 DB / COMPANY_7] ──── SQL 직접 복사 ────→ [배포 DB / COMPANY_7]
│
PopDeployModal
(배포서버 내)
│
↓
[배포 DB / COMPANY_21]
(테스트 환경)
1. 현황 요약
1-1. 환경 정보
| 구분 | 로컬 DB | 배포 DB |
|---|---|---|
| Host | 39.117.244.52:11132 | 211.115.91.141:11134 |
| Database | plm | plm |
| 소스 회사 | COMPANY_7 (탑씰) | - |
| 1차 타겟 | - | COMPANY_7 (탑씰, SQL 직접 삽입) |
| 2차 타겟 | - | COMPANY_21 (테스트회사, PopDeployModal) |
1-2. 복사 대상 화면
| 화면 ID | screen_code | screen_name | 역할 |
|---|---|---|---|
| 4479 | COMPANY_7_179 | 홈 | POP 메인 홈 화면 |
| 4576 | COMPANY_7_194 | 입고메뉴 | 입고 카테고리 메뉴 |
| 4173 | COMPANY_7_169 | 구매입고 담기 | 구매입고 항목 선택/담기 |
| 4577 | COMPANY_7_195 | 구매입고 장바구니 | 장바구니 확인/입고 확정 |
| 4480 | COMPANY_7_180 | MES공정 | MES 생산실적 관리 |
1-3. POP 카테고리 구조 (screen_groups)
탑씰 (id:3134, code:TOPSSEAL)
├── 홈 #4479
├── 입고관리 (id:3216, code:INBOUND_MENU)
│ ├── 입고메뉴 #4576
│ └── 구매입고 (id:3221, code:PURCHASE RECEIPT)
│ ├── 구매입고 담기 #4173
│ └── 구매입고 장바구니 #4577
└── 생산실적 (id:3220, code:PRODUCTION RESULTS)
└── MES공정 #4480
1-4. 화면 간 상호참조 (layout_json 내부)
| 출발 화면 | 참조 방식 | 대상 화면 | JSON 키 |
|---|---|---|---|
| 4479 홈 | navigate | 4480 MES공정 | screenId: "4480" |
| 4479 홈 | navigate | 4576 입고메뉴 | screenId: "4576" |
| 4576 입고메뉴 | navigate | 4173 구매입고 | screenId: "4173" |
| 4173 구매입고 | cart-save | 4577 장바구니 | cartScreenId: "4577" |
| 4577 장바구니 | source | 4173 구매입고 | sourceScreenId: 4173 (숫자) |
| 4577 장바구니 | navigate | 4173 구매입고 | targetScreenId: "4173" |
PopDeployModal을 사용하면 이 참조들이 모두 자동 리매핑됩니다.
2. 배포 DB 현황 점검 결과
2-1. 테이블 누락 상태
| 테이블 | 로컬 | 배포 | MES/기능 의존도 |
|---|---|---|---|
| work_order_process | O (37컬럼) | 없음 | MES공정 화면 전체 동작 불가 |
| process_work_result | O (35컬럼) | 없음 | MES 체크리스트 기능 불가 |
| work_order_process_log | O (12컬럼+트리거) | 없음 | 공정 변경 이력 로깅 불가 |
| cart_items | O (16컬럼) | 없음 | 구매입고 장바구니 전체 불가 |
2-2. 컬럼 누락 상태
| 테이블 | 누락 컬럼 | 영향 |
|---|---|---|
| work_instruction | reason, completed_qty |
MES 완료수량 업데이트 실패 |
2-3. COMPANY_21 (테스트회사) 현황
| 항목 | 상태 |
|---|---|
| 회사 존재 | O (active) |
| 기존 POP 레이아웃 | 없음 (깨끗한 상태) |
| 로그인 가능 계정 | 0개 (계정 없음!) |
| 기존 화면 수 | 23개 (일반 ERP 화면들) |
중요: COMPANY_21에는 현재 등록된 사용자가 없습니다. 테스트 전에 사용자 계정을 먼저 생성해야 로그인 및 POP 테스트가 가능합니다.
2-4. COMPANY_7 (탑씰) 배포 서버 현황
- 기존 POP 레이아웃:
screen_id 4114(테스트용 1개만 존재) - 로그인 계정:
topseal_admin,topseal_admin2,topseal_user,test1,test2 - 5개 화면(4173, 4479, 4480, 4576, 4577) 모두 배포 DB에 없음 → 안전하게 삽입 가능
3. 누락 테이블/컬럼 추가 방법
3-1. Vexplor DDL 시스템으로 가능한 작업
Vexplor에는 관리자 DDL 실행 시스템이 내장되어 있습니다.
- 접근: 관리자 > 시스템관리 > 테이블관리 (
/admin/systemMng/tableMngList) - 가능한 작업:
- 테이블 생성 (
POST /api/ddl/tables) - 컬럼 추가 (
POST /api/ddl/tables/:tableName/columns) - 생성 시
table_type_columns메타데이터 자동 등록
- 테이블 생성 (
- 권한: 슈퍼 어드민 계정 (
company_code = '*')만 사용 가능 - 불가능한 것: 트리거 함수 생성 (이건 psql 직접 실행 필요)
3-2. 작업 분류
| 작업 | 방법 | 비고 |
|---|---|---|
| work_order_process 생성 | psql 직접 실행 | 컬럼 37개 + 인덱스 7개, UI 입력보다 SQL이 효율적 |
| process_work_result 생성 | psql 직접 실행 | 컬럼 35개 |
| cart_items 생성 | psql 직접 실행 | 컬럼 16개 + 인덱스 5개 |
| work_order_process_log 생성 | psql 직접 실행 | 트리거 함수 포함 필수 |
| work_instruction 컬럼 추가 | DDL UI 또는 psql | 컬럼 2개, 어느 방법이든 가능 |
| table_type_columns 메타데이터 | psql COPY 명령 | 로컬에서 추출 후 배포에 삽입 |
결론: DDL UI는 컬럼 추가(
work_instruction) 정도에 활용하고, 테이블 생성은 모두 psql SQL 직접 실행이 현실적입니다.
4. 실행 절차 (단계별)
STEP 0: 배포 DB 백업
-- 배포 DB에서 실행
CREATE TABLE backup_20260323_screen_definitions AS
SELECT * FROM screen_definitions WHERE company_code = 'COMPANY_7';
CREATE TABLE backup_20260323_screen_layouts_pop AS
SELECT * FROM screen_layouts_pop WHERE company_code = 'COMPANY_7';
CREATE TABLE backup_20260323_screen_groups AS
SELECT * FROM screen_groups WHERE company_code = 'COMPANY_7';
CREATE TABLE backup_20260323_screen_group_screens AS
SELECT * FROM screen_group_screens WHERE company_code = 'COMPANY_7';
STEP 1: 누락 테이블 생성 (배포 DB에서 psql 실행)
PGPASSWORD='$DB_PASSWORD' psql -h 211.115.91.141 -p 11134 -U postgres -d plm
1-1. work_order_process
CREATE TABLE work_order_process (
id character varying(500) NOT NULL DEFAULT (gen_random_uuid())::text,
created_date timestamp without time zone DEFAULT now(),
updated_date timestamp without time zone DEFAULT now(),
writer character varying(255),
company_code character varying(255),
wo_id character varying(500),
seq_no character varying(255),
process_code character varying(255),
process_name character varying(255),
is_required character varying(255),
is_fixed_order character varying(255),
standard_time character varying(255),
status character varying(255),
accepted_by character varying(255),
accepted_at character varying(255),
started_at character varying(255),
completed_at character varying(255),
plan_qty character varying(255),
input_qty character varying(255),
good_qty character varying(255),
defect_qty character varying(255),
equipment_code character varying(255),
remark character varying(500),
paused_at character varying(500),
total_paused_time character varying(500) DEFAULT '0',
routing_detail_id character varying(500),
actual_work_time character varying(500) DEFAULT NULL::character varying,
completed_by character varying(500) DEFAULT NULL::character varying,
total_production_qty character varying(500),
defect_detail character varying(500),
result_note character varying(500),
result_status character varying(500) DEFAULT 'draft'::character varying,
attachments character varying(500),
parent_process_id character varying(500) DEFAULT NULL::character varying,
concession_qty character varying(500) DEFAULT '0'::character varying,
is_rework character varying(500) DEFAULT 'N'::character varying,
rework_source_id character varying(500) DEFAULT NULL::character varying,
CONSTRAINT work_order_process_pkey PRIMARY KEY (id)
);
CREATE INDEX idx_wop_company ON work_order_process (company_code);
CREATE INDEX idx_wop_wo_id ON work_order_process (wo_id);
CREATE INDEX idx_wop_wo_id_seq_no ON work_order_process (wo_id, seq_no);
CREATE INDEX idx_wop_process ON work_order_process (company_code, process_code);
CREATE INDEX idx_wop_status ON work_order_process (company_code, process_code, status);
CREATE INDEX idx_wop_parent_process_id ON work_order_process (parent_process_id);
1-2. process_work_result
CREATE TABLE process_work_result (
id character varying(500) NOT NULL DEFAULT (gen_random_uuid())::text,
created_date timestamp without time zone DEFAULT now(),
updated_date timestamp without time zone DEFAULT now(),
writer character varying(500) DEFAULT NULL::character varying,
company_code character varying(500),
work_order_process_id character varying(500),
source_work_item_id character varying(500),
source_detail_id character varying(500),
work_phase character varying(500),
item_title character varying(500),
item_sort_order character varying(500),
detail_content character varying(500),
detail_type character varying(500),
detail_sort_order character varying(500),
is_required character varying(500),
inspection_code character varying(500),
inspection_method character varying(500),
unit character varying(500),
lower_limit character varying(500),
upper_limit character varying(500),
input_type character varying(500),
lookup_target character varying(500),
display_fields character varying(500),
duration_minutes character varying(500),
status character varying(500),
result_value character varying(500),
is_passed character varying(500),
remark character varying(500),
recorded_by character varying(500),
recorded_at character varying(500),
started_at character varying(500) DEFAULT NULL::character varying,
group_started_at character varying(500) DEFAULT NULL::character varying,
group_paused_at character varying(500) DEFAULT NULL::character varying,
group_total_paused_time character varying(500) DEFAULT NULL::character varying,
group_completed_at character varying(500) DEFAULT NULL::character varying,
CONSTRAINT process_work_result_pkey PRIMARY KEY (id)
);
1-3. work_order_process_log + 트리거
-- 로그 테이블
CREATE TABLE work_order_process_log (
log_id SERIAL PRIMARY KEY,
operation_type character varying(10) NOT NULL,
original_id character varying(100),
changed_column character varying(100),
old_value text,
new_value text,
changed_by character varying(50),
changed_at timestamp without time zone DEFAULT CURRENT_TIMESTAMP,
ip_address character varying(50),
user_agent text,
full_row_before jsonb,
full_row_after jsonb
);
-- 트리거 함수 (로컬 DB에서 정확한 정의 먼저 추출)
-- 로컬에서: SELECT pg_get_functiondef(oid) FROM pg_proc WHERE proname = 'work_order_process_log_trigger_func';
-- 추출한 함수 정의를 아래에 붙여넣기
-- 트리거 등록 (함수 생성 후 실행)
CREATE TRIGGER work_order_process_audit_trigger
AFTER INSERT OR UPDATE OR DELETE ON work_order_process
FOR EACH ROW EXECUTE FUNCTION work_order_process_log_trigger_func();
1-4. cart_items
CREATE TABLE cart_items (
id character varying(255) NOT NULL DEFAULT (gen_random_uuid())::text,
created_date timestamp without time zone DEFAULT now(),
updated_date timestamp without time zone DEFAULT now(),
company_code character varying(20),
cart_type character varying(255),
screen_id character varying(255),
user_id character varying(255),
source_table character varying(255),
row_key text,
row_data text,
quantity character varying(255),
unit character varying(255),
package_unit character varying(255),
package_entries text,
status character varying(255),
memo text,
CONSTRAINT cart_items_pkey PRIMARY KEY (id)
);
CREATE INDEX idx_cart_items_company ON cart_items (company_code);
CREATE INDEX idx_cart_items_screen_user ON cart_items (screen_id, user_id);
CREATE INDEX idx_cart_items_type ON cart_items (cart_type);
CREATE INDEX idx_cart_items_status ON cart_items (status);
STEP 2: 기존 테이블 컬럼 추가
방법 A: DDL UI (관리자 화면)
- 슈퍼 어드민 계정으로 배포서버 접속
- 관리자 > 시스템관리 > 테이블관리
work_instruction테이블 선택- 컬럼 추가 버튼 →
reason(varchar 500) 추가 - 컬럼 추가 버튼 →
completed_qty(varchar 500, 기본값: '0') 추가
방법 B: SQL 직접
ALTER TABLE work_instruction
ADD COLUMN IF NOT EXISTS reason character varying(500),
ADD COLUMN IF NOT EXISTS completed_qty character varying(500) DEFAULT '0'::character varying;
STEP 3: table_type_columns 메타데이터 복사 (로컬 → 배포)
# 로컬 DB에서 추출
PGPASSWORD='ph0909!!' psql -h 39.117.244.52 -p 11132 -U postgres -d plm -c "
COPY (
SELECT * FROM table_type_columns
WHERE table_name IN ('work_order_process', 'cart_items', 'process_work_result')
) TO STDOUT WITH CSV HEADER" > /tmp/ttc_export.csv
# 배포 DB에 삽입 (충돌 시 무시)
PGPASSWORD='$DB_PASSWORD' psql -h 211.115.91.141 -p 11134 -U postgres -d plm -c "
COPY table_type_columns FROM STDIN WITH CSV HEADER
ON CONFLICT DO NOTHING" < /tmp/ttc_export.csv
STEP 4: 화면 5종 → 배포 COMPANY_7 복사 (SQL)
화면 ID 4173~4577은 배포 DB에 없으므로 동일 ID로 안전하게 삽입 가능
# 로컬에서 screen_definitions 추출
PGPASSWORD='ph0909!!' psql -h 39.117.244.52 -p 11132 -U postgres -d plm -c "
COPY (
SELECT * FROM screen_definitions
WHERE screen_id IN (4173, 4479, 4480, 4576, 4577)
) TO STDOUT WITH CSV HEADER" > /tmp/screen_def.csv
# 배포에 삽입
PGPASSWORD='$DB_PASSWORD' psql -h 211.115.91.141 -p 11134 -U postgres -d plm -c "
COPY screen_definitions FROM STDIN WITH CSV HEADER
ON CONFLICT DO NOTHING" < /tmp/screen_def.csv
# screen_layouts_pop 추출 (layout_id 제외)
PGPASSWORD='ph0909!!' psql -h 39.117.244.52 -p 11132 -U postgres -d plm -c "
COPY (
SELECT screen_id, company_code, layout_data, created_at, updated_at, created_by, updated_by
FROM screen_layouts_pop
WHERE screen_id IN (4173, 4479, 4480, 4576, 4577)
) TO STDOUT WITH CSV HEADER" > /tmp/screen_layouts.csv
# 배포에 삽입
PGPASSWORD='$DB_PASSWORD' psql -h 211.115.91.141 -p 11134 -U postgres -d plm -c "
COPY screen_layouts_pop (screen_id, company_code, layout_data, created_at, updated_at, created_by, updated_by)
FROM STDIN WITH CSV HEADER
ON CONFLICT (screen_id, company_code) DO NOTHING" < /tmp/screen_layouts.csv
# screen_groups 추출 (그룹 4개: 3134, 3216, 3220, 3221)
PGPASSWORD='ph0909!!' psql -h 39.117.244.52 -p 11132 -U postgres -d plm -c "
COPY (
SELECT * FROM screen_groups
WHERE id IN (3134, 3216, 3220, 3221)
) TO STDOUT WITH CSV HEADER" > /tmp/screen_groups.csv
# 배포에 삽입
PGPASSWORD='$DB_PASSWORD' psql -h 211.115.91.141 -p 11134 -U postgres -d plm -c "
COPY screen_groups FROM STDIN WITH CSV HEADER
ON CONFLICT DO NOTHING" < /tmp/screen_groups.csv
# screen_group_screens 추출
PGPASSWORD='ph0909!!' psql -h 39.117.244.52 -p 11132 -U postgres -d plm -c "
COPY (
SELECT * FROM screen_group_screens
WHERE screen_id IN (4173, 4479, 4480, 4576, 4577)
) TO STDOUT WITH CSV HEADER" > /tmp/screen_group_screens.csv
# 배포에 삽입
PGPASSWORD='$DB_PASSWORD' psql -h 211.115.91.141 -p 11134 -U postgres -d plm -c "
COPY screen_group_screens FROM STDIN WITH CSV HEADER
ON CONFLICT DO NOTHING" < /tmp/screen_group_screens.csv
# 시퀀스 동기화 (배포 DB에서 실행)
SELECT setval('screen_definitions_screen_id_seq',
GREATEST((SELECT MAX(screen_id) FROM screen_definitions),
(SELECT last_value FROM screen_definitions_screen_id_seq)));
SELECT setval('screen_layouts_pop_layout_id_seq',
GREATEST((SELECT MAX(layout_id) FROM screen_layouts_pop),
(SELECT last_value FROM screen_layouts_pop_layout_id_seq)));
SELECT setval('screen_groups_id_seq',
GREATEST((SELECT MAX(id) FROM screen_groups),
(SELECT last_value FROM screen_groups_id_seq)));
SELECT setval('screen_group_screens_id_seq',
GREATEST((SELECT MAX(id) FROM screen_group_screens),
(SELECT last_value FROM screen_group_screens_id_seq)));
STEP 5: COMPANY_21 테스트 계정 사용자 생성
COMPANY_21에 현재 등록된 사용자가 없습니다. 로그인하려면 계정이 필요합니다.
배포서버 관리자 화면(슈퍼 어드민)에서 COMPANY_21 소속 사용자를 추가합니다:
- 관리자 > 회사관리 > COMPANY_21 > 사용자 추가
- 또는 SQL:
-- user_info 테이블에 테스트 사용자 추가 (기존 패턴 참고)
-- 실제 password 해시는 기존 계정 방식과 동일하게 처리 필요
INSERT INTO user_info (user_id, user_name, company_code, user_type, status, password)
VALUES ('test21', '테스트계정', 'COMPANY_21', 'COMPANY_ADMIN', 'active', '-- 해시된 비밀번호 --');
STEP 6: PopDeployModal로 COMPANY_7 → COMPANY_21 복사
- 배포서버에서
topseal_admin계정으로 로그인 - POP 디자이너 > POP 관리 화면 > 카테고리 트리 접속
- "탑씰" 그룹에서 배포 버튼 클릭
- 대상 회사: COMPANY_21 (테스트회사) 선택
- 5개 화면 포함 여부 확인 후 배포 실행
- PopDeployModal이 COMPANY_21 전용 새 화면 ID 자동 부여 + 참조 자동 리매핑
STEP 7: 검증
-- 배포 DB에서 실행 --
-- 7-1. 누락 테이블 생성 확인
SELECT table_name FROM information_schema.tables
WHERE table_schema = 'public'
AND table_name IN ('work_order_process', 'cart_items', 'process_work_result', 'work_order_process_log');
-- 예상: 4건
-- 7-2. work_instruction 컬럼 확인
SELECT column_name FROM information_schema.columns
WHERE table_name = 'work_instruction' AND column_name IN ('reason', 'completed_qty');
-- 예상: 2건
-- 7-3. COMPANY_7 화면 삽입 확인
SELECT screen_id, screen_name, company_code FROM screen_definitions
WHERE screen_id IN (4173, 4479, 4480, 4576, 4577);
-- 예상: 5건 (COMPANY_7)
-- 7-4. COMPANY_21 화면 복사 확인 (PopDeployModal 후)
SELECT sd.screen_id, sd.screen_name, sd.company_code,
CASE WHEN slp.layout_id IS NOT NULL THEN 'Y' ELSE 'N' END as has_layout
FROM screen_definitions sd
LEFT JOIN screen_layouts_pop slp ON sd.screen_id = slp.screen_id
WHERE sd.company_code = 'COMPANY_21'
AND sd.screen_name IN ('홈', 'MES공정', '입고메뉴', '구매입고 담기', '구매입고 장바구니');
-- 예상: 5건 + has_layout = Y
-- 7-5. 화면 간 참조 무결성 (COMPANY_21 기준 새 ID로 리매핑됐는지 확인)
SELECT slp.screen_id,
layout_data::text LIKE '%screenId%' as has_nav_ref,
layout_data::text LIKE '%cartScreenId%' as has_cart_ref
FROM screen_layouts_pop slp
JOIN screen_definitions sd ON slp.screen_id = sd.screen_id
WHERE sd.company_code = 'COMPANY_21'
AND sd.screen_name IN ('홈', '입고메뉴', '구매입고 담기', '구매입고 장바구니');
-- 7-6. 시퀀스 정합성
SELECT 'screen_definitions' as tbl,
(SELECT MAX(screen_id) FROM screen_definitions) as max_id,
(SELECT last_value FROM screen_definitions_screen_id_seq) as seq_val,
CASE WHEN (SELECT last_value FROM screen_definitions_screen_id_seq)
>= (SELECT MAX(screen_id) FROM screen_definitions)
THEN 'OK' ELSE 'MISMATCH' END as status;
5. COMPANY_21 테스트 환경 수정 가능 여부
| 항목 | 수정 가능? | 방법 |
|---|---|---|
| 회사명/정보 | O | 관리자 > 회사관리 |
| 사용자 추가/수정 | O | 관리자 > 사용자관리 |
| POP 화면 수정 | O | POP 디자이너에서 직접 편집 |
| 화면 삭제 후 재배포 | O | PopDeployModal 재실행 |
| 기존 ERP 화면 영향 없음 | O | POP 레이아웃 별도 테이블 관리 |
COMPANY_21은 테스트 전용 계정이므로 자유롭게 수정/삭제 가능합니다. 기존 23개 ERP 화면(구매관리, 영업관리 등)은 POP과 무관하므로 건드리지 않아도 됩니다.
6. 요약: 실행 순서
| 순서 | 작업 | 방법 | 담당 |
|---|---|---|---|
| STEP 0 | 배포 DB 백업 | psql | DB 담당자 |
| STEP 1 | 누락 테이블 4개 생성 | psql SQL | DB 담당자 |
| STEP 2 | work_instruction 컬럼 추가 | DDL UI 또는 psql | DB 담당자 |
| STEP 3 | table_type_columns 메타데이터 복사 | psql COPY | DB 담당자 |
| STEP 4 | 화면 5종 COMPANY_7에 삽입 | psql COPY | DB 담당자 |
| STEP 5 | COMPANY_21 테스트 사용자 생성 | 관리자 UI 또는 SQL | 어드민 계정 |
| STEP 6 | PopDeployModal로 COMPANY_21 복사 | 배포서버 UI | 어드민 계정 |
| STEP 7 | 검증 쿼리 실행 | psql | DB 담당자 |
| STEP 8 | 브라우저 POP 화면 테스트 | 브라우저 | 테스터 |
7. 롤백 방법
-- COMPANY_21 POP 화면 삭제 (PopDeployModal로 생성된 것)
DELETE FROM screen_group_screens
WHERE screen_id IN (
SELECT screen_id FROM screen_definitions WHERE company_code = 'COMPANY_21'
AND screen_name IN ('홈', 'MES공정', '입고메뉴', '구매입고 담기', '구매입고 장바구니')
);
DELETE FROM screen_layouts_pop
WHERE screen_id IN (
SELECT screen_id FROM screen_definitions WHERE company_code = 'COMPANY_21'
AND screen_name IN ('홈', 'MES공정', '입고메뉴', '구매입고 담기', '구매입고 장바구니')
);
DELETE FROM screen_definitions
WHERE company_code = 'COMPANY_21'
AND screen_name IN ('홈', 'MES공정', '입고메뉴', '구매입고 담기', '구매입고 장바구니');
-- COMPANY_7 화면 삭제 (SQL로 삽입한 것)
DELETE FROM screen_group_screens WHERE screen_id IN (4173, 4479, 4480, 4576, 4577);
DELETE FROM screen_layouts_pop WHERE screen_id IN (4173, 4479, 4480, 4576, 4577);
DELETE FROM screen_definitions WHERE screen_id IN (4173, 4479, 4480, 4576, 4577);
DELETE FROM screen_groups WHERE id IN (3134, 3216, 3220, 3221)
AND id NOT IN (SELECT id FROM backup_20260323_screen_groups);
-- 생성한 테이블 제거
DROP TABLE IF EXISTS work_order_process_log;
DROP TABLE IF EXISTS process_work_result;
DROP TABLE IF EXISTS work_order_process;
DROP TABLE IF EXISTS cart_items;
-- 추가 컬럼 제거
ALTER TABLE work_instruction DROP COLUMN IF EXISTS reason;
ALTER TABLE work_instruction DROP COLUMN IF EXISTS completed_qty;
이 문서는 로컬 DB와 배포 DB를 읽기 전용으로 점검한 결과를 바탕으로 작성되었습니다. 실제 실행 전 반드시 배포 DB 백업을 완료하세요.