feat: enhance category value retrieval with company code filtering

- Updated the `getCategoryValues` function to allow filtering based on a specified company code when requested by a super admin.
- Modified the service layer to ensure that super admins can retrieve common category values while preventing data mixing from different companies.
- Adjusted the frontend component to include the filter parameter in API requests, ensuring that the correct company-specific categories are displayed.

Made-with: Cursor
This commit is contained in:
kjs
2026-03-11 17:53:41 +09:00
parent d890155354
commit 62a5ae5f4b
3 changed files with 35 additions and 24 deletions

View File

@@ -713,7 +713,7 @@ export const TableListComponent: React.FC<TableListComponentProps> = ({
const [categoryMappings, setCategoryMappings] = useState<
Record<string, Record<string, { label: string; color?: string }>>
>({});
const [categoryMappingsKey, setCategoryMappingsKey] = useState(0); // 강제 리렌더링용
const [categoryMappingsKey, setCategoryMappingsKey] = useState(0);
const [searchValues, setSearchValues] = useState<Record<string, any>>({});
const [selectedRows, setSelectedRows] = useState<Set<string>>(new Set());
const [columnWidths, setColumnWidths] = useState<Record<string, number>>({});
@@ -1047,9 +1047,14 @@ export const TableListComponent: React.FC<TableListComponentProps> = ({
const getColumnUniqueValues = async (columnName: string) => {
const { apiClient } = await import("@/lib/api/client");
// 최고관리자가 특정 회사 프리뷰 시 해당 회사 카테고리만 필터링
const filterParam = companyCode && companyCode !== "*"
? `?filterCompanyCode=${encodeURIComponent(companyCode)}`
: "";
// 1단계: 카테고리 API 시도 (columnMeta 무관하게 항상 시도)
try {
const response = await apiClient.get(`/table-categories/${tableConfig.selectedTable}/${columnName}/values`);
const response = await apiClient.get(`/table-categories/${tableConfig.selectedTable}/${columnName}/values${filterParam}`);
if (response.data.success && response.data.data && response.data.data.length > 0) {
return response.data.data.map((item: any) => ({
value: item.valueCode,
@@ -1154,15 +1159,13 @@ export const TableListComponent: React.FC<TableListComponentProps> = ({
tableConfig.selectedTable,
tableConfig.columns,
columnLabels,
columnMeta, // columnMeta가 변경되면 재등록 (inputType 정보 필요)
categoryMappings, // 카테고리 매핑 변경 시 재등록 (필터 라벨 변환용)
columnMeta,
categoryMappings,
columnWidths,
tableLabel,
data, // 데이터 자체가 변경되면 재등록 (고유 값 조회용)
totalItems, // 전체 항목 수가 변경되면 재등록
data,
totalItems,
registerTable,
// unregisterTable은 의존성에서 제외 - 무한 루프 방지
// unregisterTable 함수는 의존성이 없어 안정적임
]);
// 🎯 초기 로드 시 localStorage에서 정렬 상태 불러오기 (없으면 defaultSort 적용)
@@ -1406,7 +1409,13 @@ export const TableListComponent: React.FC<TableListComponentProps> = ({
const mappings: Record<string, Record<string, { label: string; color?: string }>> = {};
const apiClient = (await import("@/lib/api/client")).apiClient;
// 최고관리자가 특정 회사 프리뷰 시 해당 회사 카테고리만 필터링
const filterCompanyParam = companyCode && companyCode !== "*"
? `&filterCompanyCode=${encodeURIComponent(companyCode)}`
: "";
// 트리 구조를 평탄화하는 헬퍼 함수 (메인 테이블 + 엔티티 조인 공통 사용)
// valueCode만 키로 사용 (valueId까지 넣으면 같은 라벨이 2번 나옴)
const flattenTree = (items: any[], mapping: Record<string, { label: string; color?: string }>) => {
items.forEach((item: any) => {
if (item.valueCode) {
@@ -1415,12 +1424,6 @@ export const TableListComponent: React.FC<TableListComponentProps> = ({
color: item.color,
};
}
if (item.valueId !== undefined && item.valueId !== null) {
mapping[String(item.valueId)] = {
label: item.valueLabel,
color: item.color,
};
}
if (item.children && Array.isArray(item.children) && item.children.length > 0) {
flattenTree(item.children, mapping);
}
@@ -1448,7 +1451,7 @@ export const TableListComponent: React.FC<TableListComponentProps> = ({
}
// 비활성화된 카테고리도 라벨로 표시하기 위해 includeInactive=true
const response = await apiClient.get(`/table-categories/${targetTable}/${targetColumn}/values?includeInactive=true`);
const response = await apiClient.get(`/table-categories/${targetTable}/${targetColumn}/values?includeInactive=true${filterCompanyParam}`);
if (response.data.success && response.data.data && Array.isArray(response.data.data)) {
const mapping: Record<string, { label: string; color?: string }> = {};
@@ -1531,7 +1534,7 @@ export const TableListComponent: React.FC<TableListComponentProps> = ({
// inputType이 category인 경우 카테고리 매핑 로드
if (inputTypeInfo?.inputType === "category" && !mappings[col.columnName]) {
try {
const response = await apiClient.get(`/table-categories/${joinedTable}/${col.actualColumn}/values?includeInactive=true`);
const response = await apiClient.get(`/table-categories/${joinedTable}/${col.actualColumn}/values?includeInactive=true${filterCompanyParam}`);
if (response.data.success && response.data.data && Array.isArray(response.data.data)) {
const mapping: Record<string, { label: string; color?: string }> = {};
@@ -1601,6 +1604,7 @@ export const TableListComponent: React.FC<TableListComponentProps> = ({
JSON.stringify(categoryColumns),
JSON.stringify(tableConfig.columns),
columnMeta,
companyCode,
]);
// ========================================