feat: MappingEngine + Override 실제 로직 + 프론트 주요 화면
Backend: - MappingEngine: company_field_mapping 기반 동적 변환 구현 - raw_content(JSON) → 표준 원장 (TRIM/UPPER/LOWER/DATE/DIVIDE/MULTIPLY/CODE_MAP) - policy_no 로 contract 매칭 → contract_id/agent_id 자동 - 실패 시 parse_error_log 자동 적재 - Recruit/Maintain Mapper.sumByAgentMonth 추가 - OrganizationMapper.selectAncestorIds (CTE 재귀 상향) 추가 - CalcOverrideStep 실제 동작: * lower agent 의 모집+유지 합계를 base 로 사용 * 자기 조직 → 상위 조직 순으로 to_grade 직급 ACTIVE 설계사 탐색 * (lowerOrgId, toGrade) 캐싱 Frontend (주요 화면): - 공통 컴포넌트: * CodeSelect (공통코드 드롭다운, React Query 캐시) * CodeBadge (상태 색상 자동 매핑) * MoneyText (천단위 콤마, 음수 빨강, 부호 옵션) * PermissionButton (권한 없으면 미렌더) * SearchForm (조건 배열 → 자동 폼) * ExcelExportButton (blob 다운로드) * PageContainer - 훅: useCommonCodes, usePermission (메뉴별 boolean) - API 모듈: agent, contract, ledger, settle, code - 페이지: AgentList, ContractList, RecruitLedger, SettleList * SettleList: 월 요약 카드 + 확정/보류 액션 + 권한 체크 - 라우터: /org/agents, /contracts, /ledger/recruit, /settle V16 fix: - PAYMENT 메뉴는 V12 에서 level1 directory 로 생성됨 → V16 에서 PAGE 로 UPDATE 후 권한 매트릭스 적용 (자식으로 또 만들면 unique 충돌)
This commit is contained in:
@@ -0,0 +1,15 @@
|
||||
import { useQuery } from '@tanstack/react-query';
|
||||
import { codeApi } from '@/api/code';
|
||||
|
||||
/**
|
||||
* 공통코드 그룹별 목록을 React Query 로 캐싱하여 반환.
|
||||
* staleTime: 1시간 (서버 변경 후 페이지 새로고침이면 충분)
|
||||
*/
|
||||
export function useCommonCodes(groupCode: string) {
|
||||
return useQuery({
|
||||
queryKey: ['commonCode', groupCode],
|
||||
queryFn: () => codeApi.byGroup(groupCode),
|
||||
staleTime: 60 * 60 * 1000,
|
||||
enabled: !!groupCode,
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
import { useQuery } from '@tanstack/react-query';
|
||||
import { menuApi, MenuResp } from '@/api/menu';
|
||||
import { useMemo } from 'react';
|
||||
|
||||
export interface MenuPermissions {
|
||||
canRead: boolean;
|
||||
canCreate: boolean;
|
||||
canUpdate: boolean;
|
||||
canDelete: boolean;
|
||||
canApprove: boolean;
|
||||
canExport: boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
* menuCode 별 사용자 권한 보유 여부.
|
||||
* 메뉴 트리에서 해당 menuCode 의 permissions 배열을 평탄화하여 boolean 으로 반환.
|
||||
*/
|
||||
export function usePermission(menuCode: string): MenuPermissions {
|
||||
const { data: tree = [] } = useQuery({
|
||||
queryKey: ['menu', 'my'],
|
||||
queryFn: menuApi.myMenus,
|
||||
staleTime: 5 * 60 * 1000,
|
||||
});
|
||||
|
||||
return useMemo(() => {
|
||||
const perms = findPermissions(tree, menuCode);
|
||||
return {
|
||||
canRead: perms.includes('READ'),
|
||||
canCreate: perms.includes('CREATE'),
|
||||
canUpdate: perms.includes('UPDATE'),
|
||||
canDelete: perms.includes('DELETE'),
|
||||
canApprove: perms.includes('APPROVE'),
|
||||
canExport: perms.includes('EXPORT'),
|
||||
};
|
||||
}, [tree, menuCode]);
|
||||
}
|
||||
|
||||
function findPermissions(nodes: MenuResp[], code: string): string[] {
|
||||
for (const n of nodes) {
|
||||
if (n.menuCode === code) return n.permissions ?? [];
|
||||
const found = findPermissions(n.children ?? [], code);
|
||||
if (found.length) return found;
|
||||
}
|
||||
return [];
|
||||
}
|
||||
Reference in New Issue
Block a user