Merge branch 'main' of http://39.117.244.52:3000/kjs/ERP-node into feature/dashboard-management
This commit is contained in:
commit
cf747b5fb3
|
|
@ -65,12 +65,26 @@ export class CommonCodeController {
|
||||||
|
|
||||||
// 프론트엔드가 기대하는 형식으로 데이터 변환
|
// 프론트엔드가 기대하는 형식으로 데이터 변환
|
||||||
const transformedData = result.data.map((code: any) => ({
|
const transformedData = result.data.map((code: any) => ({
|
||||||
|
// 새로운 필드명 (카멜케이스)
|
||||||
codeValue: code.code_value,
|
codeValue: code.code_value,
|
||||||
codeName: code.code_name,
|
codeName: code.code_name,
|
||||||
|
codeNameEng: code.code_name_eng,
|
||||||
description: code.description,
|
description: code.description,
|
||||||
sortOrder: code.sort_order,
|
sortOrder: code.sort_order,
|
||||||
isActive: code.is_active === "Y",
|
isActive: code.is_active,
|
||||||
useYn: code.is_active,
|
useYn: code.is_active,
|
||||||
|
|
||||||
|
// 기존 필드명도 유지 (하위 호환성)
|
||||||
|
code_category: code.code_category,
|
||||||
|
code_value: code.code_value,
|
||||||
|
code_name: code.code_name,
|
||||||
|
code_name_eng: code.code_name_eng,
|
||||||
|
sort_order: code.sort_order,
|
||||||
|
is_active: code.is_active,
|
||||||
|
created_date: code.created_date,
|
||||||
|
created_by: code.created_by,
|
||||||
|
updated_date: code.updated_date,
|
||||||
|
updated_by: code.updated_by,
|
||||||
}));
|
}));
|
||||||
|
|
||||||
return res.json({
|
return res.json({
|
||||||
|
|
|
||||||
|
|
@ -276,8 +276,11 @@ export class CommonCodeService {
|
||||||
updatedBy: string
|
updatedBy: string
|
||||||
) {
|
) {
|
||||||
try {
|
try {
|
||||||
// 디버깅: 받은 데이터 로그
|
// codeValue가 undefined이거나 빈 문자열인지 확인
|
||||||
logger.info(`코드 수정 데이터:`, { categoryCode, codeValue, data });
|
if (!codeValue || codeValue === 'undefined') {
|
||||||
|
throw new Error(`잘못된 코드 값입니다: ${codeValue}`);
|
||||||
|
}
|
||||||
|
|
||||||
const code = await prisma.code_info.update({
|
const code = await prisma.code_info.update({
|
||||||
where: {
|
where: {
|
||||||
code_category_code_value: {
|
code_category_code_value: {
|
||||||
|
|
|
||||||
|
|
@ -67,7 +67,7 @@ export function CodeDetailPanel({ categoryCode }: CodeDetailPanelProps) {
|
||||||
})),
|
})),
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
getItemId: (code: CodeInfo) => code.code_value,
|
getItemId: (code: CodeInfo) => code.codeValue || code.code_value,
|
||||||
});
|
});
|
||||||
|
|
||||||
// 새 코드 생성
|
// 새 코드 생성
|
||||||
|
|
@ -95,7 +95,7 @@ export function CodeDetailPanel({ categoryCode }: CodeDetailPanelProps) {
|
||||||
try {
|
try {
|
||||||
await deleteCodeMutation.mutateAsync({
|
await deleteCodeMutation.mutateAsync({
|
||||||
categoryCode,
|
categoryCode,
|
||||||
codeValue: deletingCode.code_value,
|
codeValue: deletingCode.codeValue || deletingCode.code_value,
|
||||||
});
|
});
|
||||||
|
|
||||||
setShowDeleteModal(false);
|
setShowDeleteModal(false);
|
||||||
|
|
@ -182,13 +182,13 @@ export function CodeDetailPanel({ categoryCode }: CodeDetailPanelProps) {
|
||||||
<div className="p-2">
|
<div className="p-2">
|
||||||
<DndContext {...dragAndDrop.dndContextProps}>
|
<DndContext {...dragAndDrop.dndContextProps}>
|
||||||
<SortableContext
|
<SortableContext
|
||||||
items={filteredCodes.map((code) => code.code_value)}
|
items={filteredCodes.map((code) => code.codeValue || code.code_value)}
|
||||||
strategy={verticalListSortingStrategy}
|
strategy={verticalListSortingStrategy}
|
||||||
>
|
>
|
||||||
<div className="space-y-1">
|
<div className="space-y-1">
|
||||||
{filteredCodes.map((code, index) => (
|
{filteredCodes.map((code, index) => (
|
||||||
<SortableCodeItem
|
<SortableCodeItem
|
||||||
key={`${code.code_value}-${index}`}
|
key={`${code.codeValue || code.code_value}-${index}`}
|
||||||
code={code}
|
code={code}
|
||||||
categoryCode={categoryCode}
|
categoryCode={categoryCode}
|
||||||
onEdit={() => handleEditCode(code)}
|
onEdit={() => handleEditCode(code)}
|
||||||
|
|
@ -208,20 +208,28 @@ export function CodeDetailPanel({ categoryCode }: CodeDetailPanelProps) {
|
||||||
<div className="flex items-start justify-between">
|
<div className="flex items-start justify-between">
|
||||||
<div className="min-w-0 flex-1">
|
<div className="min-w-0 flex-1">
|
||||||
<div className="flex items-center gap-2">
|
<div className="flex items-center gap-2">
|
||||||
<h3 className="font-medium text-gray-900">{activeCode.code_name}</h3>
|
<h3 className="font-medium text-gray-900">
|
||||||
|
{activeCode.codeName || activeCode.code_name}
|
||||||
|
</h3>
|
||||||
<Badge
|
<Badge
|
||||||
variant={activeCode.is_active === "Y" ? "default" : "secondary"}
|
variant={
|
||||||
|
activeCode.isActive === "Y" || activeCode.is_active === "Y"
|
||||||
|
? "default"
|
||||||
|
: "secondary"
|
||||||
|
}
|
||||||
className={cn(
|
className={cn(
|
||||||
"transition-colors",
|
"transition-colors",
|
||||||
activeCode.is_active === "Y"
|
activeCode.isActive === "Y" || activeCode.is_active === "Y"
|
||||||
? "bg-green-100 text-green-800"
|
? "bg-green-100 text-green-800"
|
||||||
: "bg-gray-100 text-gray-600",
|
: "bg-gray-100 text-gray-600",
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
{activeCode.is_active === "Y" ? "활성" : "비활성"}
|
{activeCode.isActive === "Y" || activeCode.is_active === "Y" ? "활성" : "비활성"}
|
||||||
</Badge>
|
</Badge>
|
||||||
</div>
|
</div>
|
||||||
<p className="mt-1 text-sm text-gray-600">{activeCode.code_value}</p>
|
<p className="mt-1 text-sm text-gray-600">
|
||||||
|
{activeCode.codeValue || activeCode.code_value}
|
||||||
|
</p>
|
||||||
{activeCode.description && (
|
{activeCode.description && (
|
||||||
<p className="mt-1 text-sm text-gray-500">{activeCode.description}</p>
|
<p className="mt-1 text-sm text-gray-500">{activeCode.description}</p>
|
||||||
)}
|
)}
|
||||||
|
|
|
||||||
|
|
@ -51,7 +51,7 @@ export function CodeFormModal({ isOpen, onClose, categoryCode, editingCode, code
|
||||||
categoryCode,
|
categoryCode,
|
||||||
"codeValue",
|
"codeValue",
|
||||||
validationStates.codeValue.value,
|
validationStates.codeValue.value,
|
||||||
isEditing ? editingCode?.code_value : undefined,
|
isEditing ? editingCode?.codeValue || editingCode?.code_value : undefined,
|
||||||
validationStates.codeValue.enabled,
|
validationStates.codeValue.enabled,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
@ -59,7 +59,7 @@ export function CodeFormModal({ isOpen, onClose, categoryCode, editingCode, code
|
||||||
categoryCode,
|
categoryCode,
|
||||||
"codeName",
|
"codeName",
|
||||||
validationStates.codeName.value,
|
validationStates.codeName.value,
|
||||||
isEditing ? editingCode?.code_value : undefined,
|
isEditing ? editingCode?.codeValue || editingCode?.code_value : undefined,
|
||||||
validationStates.codeName.enabled,
|
validationStates.codeName.enabled,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
@ -67,7 +67,7 @@ export function CodeFormModal({ isOpen, onClose, categoryCode, editingCode, code
|
||||||
categoryCode,
|
categoryCode,
|
||||||
"codeNameEng",
|
"codeNameEng",
|
||||||
validationStates.codeNameEng.value,
|
validationStates.codeNameEng.value,
|
||||||
isEditing ? editingCode?.code_value : undefined,
|
isEditing ? editingCode?.codeValue || editingCode?.code_value : undefined,
|
||||||
validationStates.codeNameEng.enabled,
|
validationStates.codeNameEng.enabled,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
@ -102,18 +102,18 @@ export function CodeFormModal({ isOpen, onClose, categoryCode, editingCode, code
|
||||||
if (isEditing && editingCode) {
|
if (isEditing && editingCode) {
|
||||||
// 수정 모드: 기존 데이터 로드 (codeValue는 표시용으로만 설정)
|
// 수정 모드: 기존 데이터 로드 (codeValue는 표시용으로만 설정)
|
||||||
form.reset({
|
form.reset({
|
||||||
codeName: editingCode.code_name,
|
codeName: editingCode.codeName || editingCode.code_name,
|
||||||
codeNameEng: editingCode.code_name_eng || "",
|
codeNameEng: editingCode.codeNameEng || editingCode.code_name_eng || "",
|
||||||
description: editingCode.description || "",
|
description: editingCode.description || "",
|
||||||
sortOrder: editingCode.sort_order,
|
sortOrder: editingCode.sortOrder || editingCode.sort_order,
|
||||||
isActive: editingCode.is_active as "Y" | "N", // 타입 캐스팅
|
isActive: (editingCode.isActive || editingCode.is_active) as "Y" | "N", // 타입 캐스팅
|
||||||
});
|
});
|
||||||
|
|
||||||
// codeValue는 별도로 설정 (표시용)
|
// codeValue는 별도로 설정 (표시용)
|
||||||
form.setValue("codeValue" as any, editingCode.code_value);
|
form.setValue("codeValue" as any, editingCode.codeValue || editingCode.code_value);
|
||||||
} else {
|
} else {
|
||||||
// 새 코드 모드: 자동 순서 계산
|
// 새 코드 모드: 자동 순서 계산
|
||||||
const maxSortOrder = codes.length > 0 ? Math.max(...codes.map((c) => c.sort_order)) : 0;
|
const maxSortOrder = codes.length > 0 ? Math.max(...codes.map((c) => c.sortOrder || c.sort_order)) : 0;
|
||||||
|
|
||||||
form.reset({
|
form.reset({
|
||||||
codeValue: "",
|
codeValue: "",
|
||||||
|
|
@ -132,7 +132,7 @@ export function CodeFormModal({ isOpen, onClose, categoryCode, editingCode, code
|
||||||
// 수정
|
// 수정
|
||||||
await updateCodeMutation.mutateAsync({
|
await updateCodeMutation.mutateAsync({
|
||||||
categoryCode,
|
categoryCode,
|
||||||
codeValue: editingCode.code_value,
|
codeValue: editingCode.codeValue || editingCode.code_value,
|
||||||
data: data as UpdateCodeData,
|
data: data as UpdateCodeData,
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
|
|
|
||||||
|
|
@ -26,7 +26,7 @@ export function SortableCodeItem({
|
||||||
isDragOverlay = false,
|
isDragOverlay = false,
|
||||||
}: SortableCodeItemProps) {
|
}: SortableCodeItemProps) {
|
||||||
const { attributes, listeners, setNodeRef, transform, transition, isDragging } = useSortable({
|
const { attributes, listeners, setNodeRef, transform, transition, isDragging } = useSortable({
|
||||||
id: code.code_value,
|
id: code.codeValue || code.code_value,
|
||||||
disabled: isDragOverlay,
|
disabled: isDragOverlay,
|
||||||
});
|
});
|
||||||
const updateCodeMutation = useUpdateCode();
|
const updateCodeMutation = useUpdateCode();
|
||||||
|
|
@ -39,14 +39,20 @@ export function SortableCodeItem({
|
||||||
// 활성/비활성 토글 핸들러
|
// 활성/비활성 토글 핸들러
|
||||||
const handleToggleActive = async (checked: boolean) => {
|
const handleToggleActive = async (checked: boolean) => {
|
||||||
try {
|
try {
|
||||||
|
// codeValue 또는 code_value가 없으면 에러 처리
|
||||||
|
const codeValue = code.codeValue || code.code_value;
|
||||||
|
if (!codeValue) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
await updateCodeMutation.mutateAsync({
|
await updateCodeMutation.mutateAsync({
|
||||||
categoryCode,
|
categoryCode,
|
||||||
codeValue: code.code_value,
|
codeValue: codeValue,
|
||||||
data: {
|
data: {
|
||||||
codeName: code.code_name,
|
codeName: code.codeName || code.code_name,
|
||||||
codeNameEng: code.code_name_eng || "",
|
codeNameEng: code.codeNameEng || code.code_name_eng || "",
|
||||||
description: code.description || "",
|
description: code.description || "",
|
||||||
sortOrder: code.sort_order,
|
sortOrder: code.sortOrder || code.sort_order,
|
||||||
isActive: checked ? "Y" : "N",
|
isActive: checked ? "Y" : "N",
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
@ -70,12 +76,12 @@ export function SortableCodeItem({
|
||||||
<div className="flex items-start justify-between">
|
<div className="flex items-start justify-between">
|
||||||
<div className="min-w-0 flex-1">
|
<div className="min-w-0 flex-1">
|
||||||
<div className="flex items-center gap-2">
|
<div className="flex items-center gap-2">
|
||||||
<h3 className="font-medium text-gray-900">{code.code_name}</h3>
|
<h3 className="font-medium text-gray-900">{code.codeName || code.code_name}</h3>
|
||||||
<Badge
|
<Badge
|
||||||
variant={code.is_active === "Y" ? "default" : "secondary"}
|
variant={code.isActive === "Y" || code.is_active === "Y" ? "default" : "secondary"}
|
||||||
className={cn(
|
className={cn(
|
||||||
"cursor-pointer transition-colors",
|
"cursor-pointer transition-colors",
|
||||||
code.is_active === "Y"
|
code.isActive === "Y" || code.is_active === "Y"
|
||||||
? "bg-green-100 text-green-800 hover:bg-green-200 hover:text-green-900"
|
? "bg-green-100 text-green-800 hover:bg-green-200 hover:text-green-900"
|
||||||
: "bg-gray-100 text-gray-600 hover:bg-gray-200 hover:text-gray-700",
|
: "bg-gray-100 text-gray-600 hover:bg-gray-200 hover:text-gray-700",
|
||||||
updateCodeMutation.isPending && "cursor-not-allowed opacity-50",
|
updateCodeMutation.isPending && "cursor-not-allowed opacity-50",
|
||||||
|
|
@ -84,16 +90,17 @@ export function SortableCodeItem({
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
if (!updateCodeMutation.isPending) {
|
if (!updateCodeMutation.isPending) {
|
||||||
handleToggleActive(code.is_active !== "Y");
|
const isActive = code.isActive === "Y" || code.is_active === "Y";
|
||||||
|
handleToggleActive(!isActive);
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
onPointerDown={(e) => e.stopPropagation()}
|
onPointerDown={(e) => e.stopPropagation()}
|
||||||
onMouseDown={(e) => e.stopPropagation()}
|
onMouseDown={(e) => e.stopPropagation()}
|
||||||
>
|
>
|
||||||
{code.is_active === "Y" ? "활성" : "비활성"}
|
{code.isActive === "Y" || code.is_active === "Y" ? "활성" : "비활성"}
|
||||||
</Badge>
|
</Badge>
|
||||||
</div>
|
</div>
|
||||||
<p className="mt-1 text-sm text-gray-600">{code.code_value}</p>
|
<p className="mt-1 text-sm text-gray-600">{code.codeValue || code.code_value}</p>
|
||||||
{code.description && <p className="mt-1 text-sm text-gray-500">{code.description}</p>}
|
{code.description && <p className="mt-1 text-sm text-gray-500">{code.description}</p>}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -17,13 +17,22 @@ export interface CodeCategory {
|
||||||
export type CategoryInfo = CodeCategory;
|
export type CategoryInfo = CodeCategory;
|
||||||
|
|
||||||
export interface CodeInfo {
|
export interface CodeInfo {
|
||||||
code_category: string;
|
// 백엔드 응답 필드 (변환된 형태)
|
||||||
code_value: string;
|
codeValue?: string;
|
||||||
code_name: string;
|
codeName?: string;
|
||||||
code_name_eng?: string | null;
|
codeNameEng?: string | null;
|
||||||
description?: string | null;
|
description?: string | null;
|
||||||
sort_order: number;
|
sortOrder?: number;
|
||||||
is_active: string;
|
isActive?: string | boolean;
|
||||||
|
useYn?: string;
|
||||||
|
|
||||||
|
// 기존 필드 (하위 호환성을 위해 유지)
|
||||||
|
code_category?: string;
|
||||||
|
code_value?: string;
|
||||||
|
code_name?: string;
|
||||||
|
code_name_eng?: string | null;
|
||||||
|
sort_order?: number;
|
||||||
|
is_active?: string;
|
||||||
created_date?: string | null;
|
created_date?: string | null;
|
||||||
created_by?: string | null;
|
created_by?: string | null;
|
||||||
updated_date?: string | null;
|
updated_date?: string | null;
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue