1
0
forked from baron/baron-sso

feat(org): 조직도 렌더링 및 동기화 로직 대폭 개선, 역할(Role) 강제화, 탭 정리

- 조직도 렌더링 시 너비 동적 계산 및 스크롤 문제 해결
- 하위 조직(Leaf)을 부모 박스 내부에 임베딩하여 2열로 깔끔하게 표시되도록 조직도 UI 전면 개편
- 사용자 생성/수정 및 CSV 업로드 시 직급(Position)과 직무(JobTitle)가 정상적으로 Kratos 및 로컬 DB에 동기화되도록 백엔드 API 수정
- CSV 조직도 업로드 시 계층 구분을 '/' 대신 ' > '로 변경하여 이름에 '/'가 포함된 부서(예: 평면/셀)가 분리되지 않도록 보호
- 잘못 입력된 과거 직책 데이터(팀장, 그룹장 등)를 'user' 권한으로 일괄 초기화하고, 이후 'role' 필드에 시스템 권한(user, tenant_admin, super_admin) 외의 값이 들어오지 않도록 백엔드 정규화 로직 강화
- 사용자 목록 페이지의 페이지네이션 제한을 50명에서 1000명으로 상향 조정
- 테넌트 목록 페이지에 이름/슬러그 기반 검색 기능 추가
- 관리자 UI 전반에서 불필요한 배지(Admin only, System 등) 제거 및 테넌트 상세 페이지의 미사용 '외부 연동' 탭 삭제
This commit is contained in:
2026-04-10 13:48:12 +09:00
parent 5211842d47
commit 349cdf5fcd
10 changed files with 137 additions and 82 deletions

View File

@@ -200,13 +200,13 @@ func (s *orgChartService) ImportOrgChart(ctx context.Context, tenantID string, r
orgParts = append(orgParts, val)
}
}
orgPath := strings.Join(orgParts, "/")
orgPath := strings.Join(orgParts, " > ")
leafID := companyTenantID
if orgPath != "" && orgPath != "-" {
if len(orgParts) > 0 {
// [Matrix Fix] Build hierarchy under the Root Tenant (tenantID), NOT the individual company.
// This allows departments like '총괄기획실' to be shared across multiple companies without duplication.
leafID, err = s.ensureOrgPath(ctx, tenantID, orgPath, pathCache, result)
leafID, err = s.ensureOrgPath(ctx, tenantID, orgParts, pathCache, result)
if err != nil {
result.Errors = append(result.Errors, fmt.Sprintf("Row %d: Hierarchy fail: %v", rowIdx+2, err))
continue
@@ -435,8 +435,7 @@ func (s *orgChartService) ensureCompanyTenant(ctx context.Context, rootID, name,
return tenant.ID, nil
}
func (s *orgChartService) ensureOrgPath(ctx context.Context, rootTenantID, path string, cache map[string]string, res *ImportResult) (string, error) {
parts := strings.Split(path, "/")
func (s *orgChartService) ensureOrgPath(ctx context.Context, rootTenantID string, parts []string, cache map[string]string, res *ImportResult) (string, error) {
currentParentID := rootTenantID
currentPath := ""
for i, part := range parts {