Commit Graph

3865 Commits

Author SHA1 Message Date
johngreen 3c24956efd fix(대무자): insert SQL 의 start_date/end_date 도 CAST AS DATE 추가
insertSubstitute 공백 이 char varying 으로 전달되어 DATE 컴럼 에 ERROR. checkOverlap, updateSubstitute 처럼 CAST(#{...} AS DATE) 로 일관되게 수정.
2026-05-12 18:23:49 +09:00
johngreen c3e5d7fc1b fix(대무자): Select 후보 목록 - getUserList 응답 shape 호환
SubstituteSection 의 loadCandidates 가 res.data.list 를 가정했지만
getUserList(/api/admin/users) 응답은 { data: [...] } 형태 (data 가 list 자체).
결과로 모든 select 가 '지정 가능한 사용자가 없습니다' 로 표시됐음.

Array.isArray(res.data) 와 res.data.list 둘 다 fallback 으로 처리.
2026-05-12 18:10:07 +09:00
johngreen c4a62b7e35 fix(대무자): COMPANY_ADMIN 권한 허용 + 결재함 SQL 컬럼 오타 fix + UI 셀렉트 개선
운영 QA 에서 발견된 3가지 결함을 한 번에 수정.

1. SubstituteController.java:56 / SubstituteService.java:242 (requireAdmin)
   - role 비교에서 "COMPANY_ADMIN" 누락 → 운영 admin 이 대무자 지정 시 항상 403.
   - 운영 회사 admin 의 user_type 은 COMPANY_ADMIN 이 표준 (AdminAccountCreator 가 그렇게 생성).
   - "ADMIN" / "SUPER_ADMIN" 외 "COMPANY_ADMIN" 도 허용.

2. mapper/approval.xml (selectMyRequests, selectMyPendingLines)
   - ORDER BY / SELECT 의 R.CREATED_DATE 가 잘못된 컬럼명 (APPROVAL_REQUESTS 실제: created_at).
   - 결재함 /api/approval/my-pending, /api/approval/requests 가 항상 500.
   - 3군데 R.CREATED_DATE → R.CREATED_AT.

3. SubstituteSection.tsx
   - 대무자 ID 를 직접 타이핑하던 input 을 Select 로 교체.
   - getUserList 로 같은 회사 활성 사용자 목록 로드, 본인 + SUPER_ADMIN + 비활성 자동 제외.
   - 다이얼로그 열 때 한 번만 load (openDialog 시 loadCandidates).
   - 빈 결과/로딩 placeholder 처리.
2026-05-12 17:02:15 +09:00
johngreen af23fd0316 feat(대무자): StartupSchemaMigrator 에 RUN_086 자동 적용 등록
invyone 의 정상 마이그레이션 패턴(StartupSchemaMigrator)에 RUN_086 의 7개 idempotent
DDL/DML 등록. 다음 backend 부팅 시 메타 DB + 모든 활성 테넌트 DB 에 자동 적용됨.

- btree_gist 확장 (CREATE EXTENSION IF NOT EXISTS)
- USER_SUBSTITUTES 테이블 (PK, CHECK 2, EXCLUDE 제약, 인덱스 2)
- SYSTEM_AUDIT_LOG ALTER (PROCESSOR_ID/PROCESSOR_NAME ADD COLUMN IF NOT EXISTS)
- APPROVAL_PROXY_SETTINGS → USER_SUBSTITUTES idempotent 데이터 복사

호환성 보정:
- EXCLUDE 의 daterange lower 에 COALESCE(.., CURRENT_DATE) 사용 불가 (IMMUTABLE 만 허용)
  → daterange(START_DATE, END_DATE, '[]') 단순 형식. NULL lower = -infinity 자연 처리.
- APPROVAL_PROXY_SETTINGS 의 START_DATE/END_DATE 가 varchar → DATE cast 추가
- 원본 메타데이터(created/updated) 컬럼명 환경별 차이 회피 → 'migration_086' + NOW() 고정

실측: meta+3 tenants 모두 OK (test01/test02/siflex)
2026-05-12 08:20:59 +09:00
johngreen 6a9fc06f0e feat(대무자): 프론트엔드 UI — UserFormModal 대무자 섹션 + ProfileModal 조회 + 결재 뱃지
- frontend/lib/api/substitute.ts: 7개 API 함수 (Record<string, any> 컨벤션)
- components/admin/SubstituteSection.tsx (신규): 관리자용 대무자 지정 섹션
  · 활성/예정 대무 관계 테이블, 사전 겹침 검증
  · v5 토큰 (--v5-surface-solid, --v5-glow-sm) 사용, blur 금지
- components/admin/UserFormModal.tsx: 수정 모드일 때 SubstituteSection 노출
- components/layout/MySubstituteView.tsx (신규): ProfileModal 용 read-only 조회
  · 내 대무자 + 내가 대무 중인 사람 양방향, D-day 카운트다운
- components/layout/ProfileModal.tsx: MySubstituteView 삽입
- app/(main)/approval/page.tsx: 대기함 행에 "대무 ← {원본 결재자}" 뱃지
  · currentUser.user_id !== line.approver_id 비교 (별도 타입 필드 X)
2026-05-12 08:07:15 +09:00
johngreen c0bd420c66 feat(대무자): SYSTEM_AUDIT_LOG processor 분리 기록 + USER_INFO lookup
- auditLog.xml insertAuditLog INSERT 절에 PROCESSOR_ID/PROCESSOR_NAME 컬럼 추가
- auditLog.xml selectUserNameById — 처리자 이름 lookup
- AuditLogService.insertAuditLog:
  · processor_id null → user_id 로 자동 채움 (평시 = 동일)
  · processor_id != user_id 이고 processor_name null → USER_INFO 단건 조회 (대무 이벤트만)
- notes: 도메인 테이블 CREATED_BY/UPDATED_BY broad scan — actual processor(B) 통일 자동 만족
2026-05-12 08:06:55 +09:00
johngreen 6ab7c3e780 feat(대무자): 결재 시스템 어댑터 통합 — USER_SUBSTITUTES read + IN(effective_user_ids)
- approval.xml selectActiveProxyForLine: APPROVAL_PROXY_SETTINGS → USER_SUBSTITUTES 참조
  (BOOLEAN IS_ACTIVE, START_DATE NULL 허용)
- approval.xml 3곳 (selectRequests/countRequests/selectMyPendingLines):
  APPROVER_ID = #{user_id} → APPROVER_ID IN (effective_user_ids) foreach
- ApprovalService.ensureEffectiveUserIds helper — mybatis 빈 IN() 방지
- ApprovalController: getRequests/getMyPendingLines 에 @RequestAttribute(effective_user_ids) 추가
- ApprovalService.processApproval 마지막에 AuditLogService.insertAuditLog 호출 추가
  (user_id=A, processor_id=B 분리 기록)
2026-05-12 08:06:39 +09:00
johngreen 4a83bfc8e8 feat(대무자): SubstituteContextFilter — JWT 후단계 effective_user_ids 주입
- TenantConsistencyGuard 뒤, ForcePasswordChangeGuard 앞에 등록
- /api/** 요청에 effective_user_ids = [user_id, ...active_original_ids] attribute 세팅
- SUPER_ADMIN (company_code='*') 은 short-circuit
- DB 조회 실패 시 본 요청 차단 안 함 (가용성 우선, warn 로그)
2026-05-12 08:06:21 +09:00
johngreen 6a7d261d23 feat(대무자): SubstituteService/Controller/mapper — CRUD + 검증 + Filter 핫패스
- substitute.xml (namespace=substitute): selectSubstituteList/Cnt, selectMySubstitutes,
  selectActiveOriginalUserIds (Filter 핫패스), selectActiveProxyForLine (결재 어댑터),
  countOverlap, countUserInCompany, countSuperAdmin, insert/update/delete
- SubstituteService extends BaseService: 관리자 권한 검증, self-위임 차단,
  cross-company 검증, SUPER_ADMIN 을 proxy 로 지정 거부, 사전 겹침 검증
- SubstituteController: /api/substitutes CRUD + /mine (read-only) + /check-overlap
2026-05-12 08:06:03 +09:00
johngreen e4856dcae5 feat(대무자): RUN_086 DB 마이그레이션 — USER_SUBSTITUTES + SYSTEM_AUDIT_LOG processor 추적
- USER_SUBSTITUTES 테이블 (PK, CHECK 2개, EXCLUDE 제약, 인덱스 2개)
- btree_gist 확장 hard prerequisite
- SYSTEM_AUDIT_LOG.PROCESSOR_ID/PROCESSOR_NAME 컬럼 추가
- APPROVAL_PROXY_SETTINGS → USER_SUBSTITUTES idempotent 데이터 복사
- 사전/사후 검증 SQL + 롤백 섹션 포함
2026-05-12 08:05:47 +09:00
johngreen 63279296f8 Merge pull request 'fix(layout): 부서관리 탭 라벨 hardcoded 한글 fallback 추가' (#6) from johngreen into main
Build & Deploy to K8s / build-and-deploy (push) Successful in 8m28s
2026-05-11 04:03:39 +00:00
johngreen 1b9604f66e fix(layout): 부서관리 탭 라벨 hardcoded 한글 fallback 추가
SUPER_ADMIN cross-tenant 모드에서 menu API (/api/admin/menus) 가 500 응답을
내어 uiMenus 가 비어있고, 그 결과 우리 effect 가 매칭할 데이터가 없어
sessionStorage 의 영어 fallback title (deptMngList) 이 갱신되지 않던 문제.

AppLayout 의 fallback 두 곳에 ADMIN_PATH_LABELS 맵 추가:
1. URL 직접 진입 시 첫 openTab 의 fallback title
2. uiMenus 매칭 실패 시 한글 라벨 보강

근본 원인 (menu API 500) 은 별도 backend 이슈 — 본 fix 는 우회.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-11 13:03:05 +09:00
johngreen b16439098a Merge pull request 'fix(layout): admin 탭 영어 fallback title 을 메뉴 한글명으로 갱신' (#5) from johngreen into main
Build & Deploy to K8s / build-and-deploy (push) Successful in 10m59s
2026-05-11 02:11:23 +00:00
johngreen 36d93d91cf fix(layout): admin 탭 영어 fallback title 을 메뉴 한글명으로 갱신
URL 직접 진입 / sessionStorage 복원 시 AppLayout 의 fallback
(pathname.split('/').pop()) 이 path segment 를 그대로 탭 title 로
사용해서 '부서관리' 대신 'deptMngList' 같은 영어가 표시되던 문제.

- tabStore: updateTabTitle(tabId, title) 추가
- AppLayout: uiMenus 로드 후 admin 탭들의 admin_url 매칭하여
  menu_name_kor (tabTitle/label/name) 로 갱신

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-11 11:10:01 +09:00
johngreen f0781022de fix(�μ�����): 25�� ���� �ϰ� ���� + ������ ���Ἲ ��ȭ (#4)
Build & Deploy to K8s / build-and-deploy (push) Successful in 4m31s
johngreen �귣ġ�� �μ����� ���� + �м� ��Ʈ�� main ���� ����. �ڵ� ���� Ʈ����.
2026-05-08 09:48:19 +00:00
hjjeong 0a8be2df1e Merge pull request 'hjjeong' (#3) from hjjeong into main
Build & Deploy to K8s / build-and-deploy (push) Successful in 5m38s
Reviewed-on: #3
2026-05-08 08:29:46 +00:00
johngreen 9c658ffd36 docs(notes): 부서관리 버그 헌팅 분석 리포트 (frontend/backend/sql/ux)
4개 도메인 병렬 분석 결과 + 통합 요약 + 시나리오 중심 정리.
총 25개 버그 (CRITICAL 3 / HIGH 11 / MEDIUM 7 / LOW 4) 식별.
실제 수정은 별도 커밋 (commit 68c1cb5b).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-08 17:08:23 +09:00
johngreen 68c1cb5b14 fix(부서관리): 25개 버그 일괄 수정 + 데이터 무결성 강화
CRITICAL:
- searchUsers 회사/role 격리 가드 추가 (멀티테넌시 침해 차단)
- setPrimaryDept 멤버십 검증 추가 (주부서 데이터 손상 방지)
- parent_dept_code cross-tenant 검증 (validateParent 헬퍼)

HIGH:
- updateDepartment SQL WHERE 에 DELETED_AT IS NULL 추가 (silent corruption 방지)
- update/restore 부서명 중복 검증 추가
- 글로벌 부서 (*) write 작업 SUPER_ADMIN 전용 가드
- 부서코드 자동 생성으로 강제 (사용자 입력 받지 않음)
- 회사 변경 시 상세 패널 초기화
- handleMove 부분 실패 시 화면 동기화
- 검색 시 부모 체인 자동 포함 (broken tree 수정)
- start_date 기본값 today 강제 제거

MEDIUM:
- 멤버 fetch cancellation flag
- 삭제 다이얼로그 dept_code 클로저 캡처
- isDirty 시 X 버튼 폼 초기화 경고
- 변경이력 버튼 disabled (백엔드 API 미구현)
- 일괄등록 실패 상세 모달 (라인 + 사유)
- LIKE 와일드카드 ESCAPE 적용
- nullIfBlank 에 trim 통합

LOW + 새 기능:
- 부서원 추가/제거 UI 신규 구현 (UserSearchModal)
- selectDeptMembers LEFT JOIN 으로 변경
- DepartmentPicker allowRoot 옵션 (최상위로 이동)
- expandAll 전체 departments 사용
- dead code 정리

DB:
- RUN_085 마이그레이션: DEPT_INFO partial UNIQUE + USER_DEPT UNIQUE
- 모든 active 테넌트 DB (siflex/test01/test02_invyone) 적용 완료

Breaking changes:
- 일괄등록 CSV 4컬럼 → 3컬럼 (부서명,상위부서,유형)
- 부서코드 입력란 제거 (자동 부여 DEPT_n)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-08 17:08:03 +09:00
hjjeong 74ddc4936f Merge branch 'main' into hjjeong 2026-05-08 14:59:12 +09:00
johngreen 3d220373d8 Merge pull request 'feat(부서관리): V1 슬림 스코프 + UX 리디자인 + Windows dev HMR' (#2) from johngreen into main
Build & Deploy to K8s / build-and-deploy (push) Successful in 5m30s
2026-05-08 02:12:04 +00:00
johngreen 3d5b2a4911 docs(notes): 부서 vs SRM 갭 분석 (johngreen)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-08 08:35:02 +09:00
johngreen d2b77d348b chore(dev): Windows Docker Desktop 자동 HMR 복원
Docker Desktop on Windows 의 bind mount 가 host inotify 이벤트를
컨테이너로 전파하지 못해 Turbopack file watcher 가 host 편집을 감지 못 함.
webpack 은 WATCHPACK_POLLING=true 폴백을 지원하므로 Windows 에서만
Turbopack 을 끄고 webpack 으로 폴백 → 자동 HMR 복원.

- frontend/package.json: dev:docker:nopack 스크립트 추가 (next dev, no turbopack)
- docker/dev/docker-compose.windows.yml: Windows 전용 frontend command override
- scripts/start/invyone-start-docker-all.bat: windows.yml 자동 merge

Mac/Linux 진입점은 영향 없음 (start.bat 만 windows override 활성).
첫 컴파일은 약간 느려지지만 (~10-30%) 수정→반영 시간이 80s → 1~3s 로 단축.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-08 08:34:46 +09:00
johngreen 0e895a90fa feat(부서관리): V1 슬림 스코프 + 트리 컨텍스트 메뉴 UX 리디자인
백엔드:
- V018 soft-delete (deleted_at 컬럼) + 휴지통/복구 흐름
- V019 미사용 컬럼 cleanup (V1 슬림 스코프)
- DepartmentService.updateDepartment 에 parent_dept_code 사이클 가드
  (자기 자신/자손을 부모로 지정 시도 차단)
- DepartmentController, mapper 갱신

프론트:
- 부서관리 페이지(deptMngList) UX 리디자인
  - 트리 노드 ⋮ 컨텍스트 메뉴 (하위 추가, 다른 부서 아래로 이동, 정렬 4단계, 삭제)
  - 헤더 breadcrumb 으로 부서 위치 상시 표시
  - 폼의 상위부서 row 제거 (트리 ⋮ 로 진입점 일원화)
  - 빈 상태 placeholder + X 닫기 동작
  - 토글 버튼 토스 스타일 (아이콘 + 툴팁, 일정한 위치)
  - 부서유형 row 좁은 화면 가로 오버플로 fix
- DepartmentPicker 신규 재사용 컴포넌트 (자손 자동 exclude, 사이클 차단)
- 회사관리/프로비저닝 폼 개선 (Step1Basic, fields, CompanyTable, AdminPageRenderer)
- companyList/[companyCode]/departments 구버전 페이지 삭제

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-08 08:34:23 +09:00
DDD1542 59f5cf22f0 Merge remote-tracking branch 'origin/gbpark-node' into gbpark-node
Build & Deploy to K8s / build-and-deploy (push) Successful in 4m4s
2026-05-07 17:09:57 +09:00
DDD1542 c4631efbd2 중간저장 2026-05-07 17:06:26 +09:00
hjjeong 84b9060e4e Merge branch 'hjjeong' into gbpark-node
Build & Deploy to K8s / build-and-deploy (push) Successful in 4m36s
2026-05-07 17:04:57 +09:00
hjjeong 3280be8bd4 fix(rolesList): cross-tenant row 식별 + 메뉴 트리 스크롤 보강
cross-tenant fan-out 결과에서 회사 A·B 의 동일 objid 가 합본에 들어와
React key 중복 경고 발생 + isSelected 가 회사 구분 못 하던 문제.

- li key: role.objid → \`\${company_code}-\${objid}\` 조합으로 unique
- isSelected 비교: objid + company_code 둘 다 매칭
- selectedRole 유효성 체크(useEffect)에도 company_code 매칭 추가

추가:
- 메뉴 전체 트리구조에 자체 스크롤 (maxHeight: calc(100vh - 32rem))
- thead sticky top-0 + bg-muted (투명도 제거) → 스크롤 시 헤더 가려짐 해소

SUPER_ADMIN cross-tenant 정책 변경 없음 (모든 회사 합본 표시 유지),
React 식별만 정확해지는 fix.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-07 16:51:16 +09:00
hjjeong b782bb298f merge: origin/gbpark-node → hjjeong (60 commits, 5 conflicts resolved)
충돌 해결 5개 파일:
- .gitignore: .envrc/.direnv (hjjeong direnv 셋업) + .omc/ (gbpark) 양쪽 보존
- docs/MULTI_TENANCY_ARCHITECTURE.md: *.localhost dev 분기 + *.invyone.com/solution.invyone.com 통합
- frontend/lib/api/client.ts: 1-b *.localhost:8081 dev + 1-c DEV_TENANT_HOST(nip.io):8083 + invyone.com 신 도메인
- frontend/lib/tenant/subdomain.ts: IPv4 차단 + *.invyone.com + DEV_TENANT_HOST + *.localhost 모두 처리
- frontend/app/(auth)/login/page.tsx: B안 채택 — buttons 항상 렌더, className 만 mounted 가드 (next-themes 표준 패턴)

검증:
- backend: ./gradlew compileJava 성공 (Java 21)
- frontend: 머지된 4개 파일 관련 타입 에러 0개

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-07 16:51:06 +09:00
DDD1542 798fdf18b3 merge: gbpark-node → main (화재 알람 SCADA 경고 인디케이터)
Build & Deploy to K8s / build-and-deploy (push) Failing after 6m51s
- zone 중앙에 SCADA 스타일 경고 비콘 (펄스 링 + 빨간 배지 + 경고 삼각형)
- WARN(노란/정적) / ALARM(빨간/깜빡임) 색상·효과 분리
- ZONE 17 라벨/manual-call 겹침 해소

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-07 13:36:14 +09:00
DDD1542 8eb4e8c9a2 feat: 화재 알람 데모 SCADA 스타일 경고 인디케이터 + ZONE 17 콘텐츠 정렬
Build & Deploy to K8s / build-and-deploy (push) Successful in 5m29s
- 각 zone 중앙에 SCADA 스타일 경고 비콘 자동 삽입 (펄스 링 + 빨간 배지 + 노란 경고 삼각형)
- WARN/ALARM 별 색상 분리 (CSS 변수 --b-* 로 SVG <use> shadow DOM 통과)
  - WARN: 노란 톤 + 정적 표시
  - ALARM: 빨간 톤 + drop-shadow + brightness 깜빡임
- zone-area 점선 테두리: warn(노란/얇음), alarm(빨간/굵음+pulse)
- ZONE 17 콘텐츠를 ZONE 18 비례에 맞춰 재배치 (label y 453→396) — manual-call 과 라벨 겹침 해소

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-07 13:34:20 +09:00
DDD1542 48d74170fc merge: gbpark-node → main (SCADA/화재알람 데모 가독성 개선)
Build & Deploy to K8s / build-and-deploy (push) Failing after 6m31s
- SCADA 데모: 게이지 1.5x 확대, 설비 라벨 폰트 일괄 키움, 컴포넌트 위치 미세 조정
- SCADA 데모: dev-drag.js 추가 (Shift+D 임시 드래그 모드 + via/끝점 핸들)
- 화재 알람 데모: 건물 4종 색상 분류, 라벨/아이콘 폰트 확대
- chore: @anthropic-ai/claude-code dependency 추가

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-07 11:07:54 +09:00
DDD1542 e8ba13f52b chore: @anthropic-ai/claude-code 패키지 dependencies 추가
Build & Deploy to K8s / build-and-deploy (push) Successful in 4m3s
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-07 11:05:46 +09:00
DDD1542 5d2283cb47 feat: 화재 알람 데모 건물별 색상 분류 + 라벨/아이콘 가독성 개선
- 건물 4종(utility/service/factory1/office)에 배경 그라디언트 분기
- zone 영역도 같은 톤 색상 클래스 (za-utility/service/factory1/office)
- room-label 폰트 5.7 → 7.5, zone-label 10 → 13.5 키움
- 센서/manual-call 아이콘 26 → 34, 18 → 24 로 확대 + 위치 보정

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-07 11:05:42 +09:00
DDD1542 de0bfc1af4 feat: SCADA 데모 가독성 개선 + 컴포넌트 좌표 조정 도구 추가
- 압력 게이지 1.5x 확대, PRESS/판독값/라벨 폰트 강조
- 모든 설비(탱크/펌프/시스템/MBR/필터/카본) 라벨 폰트 +2~4 단계 키움
- 센서/타일 박스 및 폰트 확대, 위치 간격 보정
- 위쪽 처리 라인 30px 위로 + TSS-RAW 자기 자리 유지하도록 dy 보정
- AIR BLOWER 를 CIP 패널 내려간 만큼 같이 내림
- 게이지/밸브/모듈/탱크 및 파이프 라우팅 미세 조정 (드래그로 잡은 좌표 일괄 반영)
- dev-drag.js: Shift+D 임시 드래그 모드. 컴포넌트/파이프 via/절대 끝점 핸들로 좌표 인스펙션 후 토폴로지 재빌드, 변경 이력 누적 패널 + 전체 복사
2026-05-07 10:42:33 +09:00
gbpark f3c3087393 merge: gbpark-node → main (방재 화재 알람 데모 + SCADA 다중경고 dock 분할)
Build & Deploy to K8s / build-and-deploy (push) Failing after 6m29s
2026-05-06 22:52:59 +09:00
gbpark da77de58ac fix: SCADA 데모 다중 경고 모드에서 dock 잘림 해소 (emergency-stack)
Build & Deploy to K8s / build-and-deploy (push) Successful in 4m14s
- 메인 모달 + alarm-list-dock 을 .emergency-stack 으로 묶어 viewport 안에서
  flex 자동 분할 (어떤 해상도/줌에서도 dock 이 잘리지 않게)
- with-multi 진입 시 JS 가 stack 으로 동적 wrapping, 해제 시 원위치 복귀
- mini-modal 본문도 line-clamp 3 + min-height:0 로 길이 폭주 차단

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-06 22:48:37 +09:00
gbpark 59fbbd95fa feat: 방재 시스템 화재 알람 모니터링 데모 페이지 추가
Build & Deploy to K8s / build-and-deploy (push) Has been cancelled
- /fire-alarm 라우트에 invyone 브랜딩 적용된 모니터링 데모 추가
- CCTV 화면은 화재 감지 → 스프링쿨러 작동 2개 영상을 순차 재생
  (단일 합본 mp4 의 ended 이벤트 불안정 + 루프 이슈로 분리)
- v1 종료 시점에 자동 phase2 전환: 스프링쿨러/방화셔터 상태 활성화
- 정보 패널 스프링쿨러 상태 텍스트에 시안 글로우 펄스로 작동 표시
- 종료 검출 3중 방어 (timeupdate / ended / hard-stop timer)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-06 22:47:03 +09:00
johngreen e1be30f8ca fix: 메뉴 순서 V017 을 모든 활성 테넌트 DB 에도 적용
Build & Deploy to K8s / build-and-deploy (push) Failing after 6m54s
Flyway V017 은 메타 DB 만 갱신하지만 MENU_INFO 의 슈퍼관리자 메뉴
(COMPANY_CODE='*') 는 회사 프로비저닝 때 각 테넌트 DB 로 복사되어
박혀있다. StartupSchemaMigrator 에 동일 UPDATE 를 넣어 부팅 시 메타 +
모든 활성 테넌트에 자동 동기화. SEQ 만 갱신하므로 멱등.
2026-05-04 13:16:10 +09:00
johngreen 47a2f97da5 chore: 회사 관리 그룹 하위 관리자 메뉴 순서 재배열 (V017)
Build & Deploy to K8s / build-and-deploy (push) Failing after 6m56s
조직 계층(회사→부서→사용자) + 권한 체계(메뉴→권한→권한그룹) 으로 묶어
부서가 맨 끝에 빠지고 권한그룹이 권한관리 뒤에 오던 어색한 순서를 정리.
2026-05-04 11:23:21 +09:00
johngreen d6cfa9973f merge: main → gbpark-node (혼합 모드 병렬 그루핑 UI)
Build & Deploy to K8s / build-and-deploy (push) Successful in 4m5s
2026-05-04 08:06:09 +09:00
johngreen a6b66ac0d1 feat(ai-workspace): 혼합 모드 병렬 그루핑 UI + 카드별 분리
Build & Deploy to K8s / build-and-deploy (push) Successful in 4m3s
- 스텝 사이 화살표에 "병렬로 합치기" 버튼 추가 → 두 스텝을 같은 execution_order 로 묶음
- 병렬 스텝 카드별 분리 버튼 (trash 왼쪽) → 해당 카드만 다음 스텝으로 빼냄
- 병렬 스텝 헤더 amber 배경 +  "병렬 실행" 배지로 시각 차별화
- (순차)/(병렬) 부가 라벨 제거, 깔끔한 "Step N" 표기로 통일
- execution_order 정규화 헬퍼(renormalizeOrders) + 일괄 저장(persistOrders) 추가

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-04 08:05:19 +09:00
gbpark 4514275347 chore: SCADA 데모 CCTV 의 TARGET 라벨 박스 제거
Build & Deploy to K8s / build-and-deploy (push) Successful in 6s
실제 영상에서 BW-A1 위에 박스 정렬 어렵고 시연 임팩트 없음 — 그냥 영상 그대로 노출.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-03 07:38:45 +09:00
gbpark ec9ef74204 feat: 모바일 페이지 PWA 풀스크린 메타 추가
Build & Deploy to K8s / build-and-deploy (push) Successful in 7s
- apple-mobile-web-app-capable + status-bar-style: iOS Safari 의 홈 화면 추가 시 standalone (주소창 + 하단바 제거)
- viewportFit:cover: 노치/홈바 영역까지 사용
- userScalable:false + maximumScale:1: 시연 중 핀치 줌 방지
- themeColor: 알람 모드 배경(#0d0202)과 일치

iOS PT 폰: Safari 공유 → 홈 화면에 추가 → 풀스크린 standalone.
Android PT 폰일 경우: manifest.json + icon 추가 별도 필요 (다음 단계).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-03 07:21:25 +09:00
gbpark d0dd86371b chore: SCADA 데모의 알람 target 작업자를 siflex_user 로 기본 박음
Build & Deploy to K8s / build-and-deploy (push) Has been cancelled
데스크톱이 /scada?worker=siflex_user query 매번 안 박아도 자동으로 작업자 폰(siflex_user)에 push.
다른 작업자 시험할 일 있으면 ?worker=<id> 로 override 여전히 가능.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-03 07:16:11 +09:00
gbpark 11d46c98bf chore: db/migration 의 legacy V001/V002 SQL 을 notes/ archive 로 이동
Build & Deploy to K8s / build-and-deploy (push) Successful in 7s
Flyway 가 V001 두 개 (기존 V001__create_ai_llm_providers + 새로 들어온 V001__varchar_migration) 를 충돌로 거부 → backend pod CrashLoopBackOff.
운영 schema 와 호환 검토 전까지 db/migration/ 밖으로 빼서 archive.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-03 07:04:09 +09:00
gbpark 80cd2b2d07 fix: e70267f73 에서 누락된 untracked 파일 추가
Build & Deploy to K8s / build-and-deploy (push) Failing after 3m8s
- frontend/components/layout/MenuItemActions.tsx — AppLayout/TopNavBar 가 import 하는데 빠져서 webpack 빌드 fail
- backend-spring db migration V001 (varchar_migration) + V002 (create_missing_tables) 같이 누락분 정리

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-03 06:22:02 +09:00
gbpark e70267f738 feat: SCADA 데모 음성 인식 + 경고 버튼 디자인 통일
Build & Deploy to K8s / build-and-deploy (push) Failing after 1m14s
- 음성 인식 (scada-demo/js/voice.js) — 한국어 발화 → 키워드 매핑 → INVYONE_UI.select()
  · 사이드바 마이크 버튼 + transcript 라벨, 매칭 시 청록 펄스
  · Chrome/Edge HTTPS 환경 (운영 siflex.invyone.com OK)
- 경고시스템/다중경고 버튼을 음성 인식과 동일 톤
  · 🚨 emoji → SVG 삼각형 아이콘, voice-btn 패턴 (다크 솔리드 + 컬러 액센트)
  · 정적 (반짝 펄스 애니메이션 제거)
- client.ts stash pop conflict 정리 (DEV_TENANT_HOST + 도메인 정리 통합)
- ui.js 다중 경고 시연 wiring + scada 작업 노트 2건
- 기타 syncthing 보류분 batch (대시보드/레이아웃/로그인 layout 정리)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-03 05:39:43 +09:00
gbpark 3a0ab10ee6 Merge branch 'gbpark-node' of https://git.junggomoa.com/gbpark/invyone into gbpark-node
Build & Deploy to K8s / build-and-deploy (push) Successful in 4m51s
2026-05-03 01:29:07 +09:00
gbpark 7635412b7b feat: SCADA 시연용 모바일 알람 동반 화면 + Spring WebSocket
- 작업자 폰(/mobile)을 SCADA 데모와 ws 로 연결, 알람 발생 시 풀스크린 푸시
  · v5 솔리드+글로우 톤, 진동/Web Audio 비프/Wake Lock/auto reconnect
  · 시연 안전망: ?test=1 자동 발동, 우상단 hidden 트리거
- backend: com.erp.alarm 신규 패키지 (WebSocketConfig + Handshake + Handler + Controller)
  · JWT 토큰 핸드셰이크 검증, userId 기반 채널 매핑 (멀티 디바이스 지원)
  · spring-boot-starter-websocket 의존성 추가
  · path 를 /api/demo/* 안에 두어 Traefik 라우트 추가 불필요 + 정식 알람과 분리
- SCADA scenario.js 의 emergency 시퀀스(2700ms)에 fetch('/api/demo/alarm/trigger') 배선
  · /scada?worker=<user_id> query 로 target user 지정 (iframe src 로 전달)
- 운영 시연 URL: siflex.invyone.com/mobile (siflex_user) ↔ /scada?worker=siflex_user

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-03 01:18:12 +09:00
johngreen b999b425cb Merge pull request 'Sync main → gbpark-node: AI 모듈 JSONB 파싱 + audit-log fix' (#1) from main into gbpark-node
Build & Deploy to K8s / build-and-deploy (push) Successful in 4m31s
Reviewed-on: #1
2026-05-02 10:20:35 +00:00