feat: enhance audit logging and add company name to audit entries

- Integrated detailed audit logging for update and delete actions in the CommonCodeController and DDLController.
- Added company name retrieval to the audit log entries for better traceability.
- Updated the audit log service to include company name in the log entries.
- Modified the frontend audit log page to display company names alongside company codes for improved clarity.

Made-with: Cursor
This commit is contained in:
kjs
2026-03-12 05:14:27 +09:00
parent fd90e3d761
commit b1e50f2e0a
14 changed files with 462 additions and 142 deletions

View File

@@ -5,71 +5,45 @@ import { AutoRegisteringComponentRenderer } from "../../AutoRegisteringComponent
import { V2InputDefinition } from "./index";
import { V2Input } from "@/components/v2/V2Input";
import { isColumnRequiredByMeta } from "../../DynamicComponentRenderer";
import { v2EventBus, V2_EVENTS } from "@/lib/v2-core";
/**
* dataBinding이 설정된 v2-input을 위한 wrapper
* v2-table-list의 TABLE_DATA_CHANGE 이벤트를 구독하여
* v2-table-list의 선택 이벤트를 window CustomEvent로 수신하여
* 선택된 행의 특정 컬럼 값을 자동으로 formData에 반영
*/
function DataBindingWrapper({
dataBinding,
columnName,
onFormDataChange,
isInteractive,
children,
}: {
dataBinding: { sourceComponentId: string; sourceColumn: string };
columnName: string;
onFormDataChange?: (field: string, value: any) => void;
isInteractive?: boolean;
children: React.ReactNode;
}) {
const lastBoundValueRef = useRef<any>(null);
const onFormDataChangeRef = useRef(onFormDataChange);
onFormDataChangeRef.current = onFormDataChange;
useEffect(() => {
if (!dataBinding?.sourceComponentId || !dataBinding?.sourceColumn) return;
console.log("[DataBinding] 구독 시작:", {
sourceComponentId: dataBinding.sourceComponentId,
sourceColumn: dataBinding.sourceColumn,
targetColumn: columnName,
isInteractive,
hasOnFormDataChange: !!onFormDataChange,
});
const handler = (e: Event) => {
const detail = (e as CustomEvent).detail;
if (!detail || detail.source !== dataBinding.sourceComponentId) return;
const unsubscribe = v2EventBus.subscribe(V2_EVENTS.TABLE_DATA_CHANGE, (payload: any) => {
console.log("[DataBinding] TABLE_DATA_CHANGE 수신:", {
payloadSource: payload.source,
expectedSource: dataBinding.sourceComponentId,
dataLength: payload.data?.length,
match: payload.source === dataBinding.sourceComponentId,
});
if (payload.source !== dataBinding.sourceComponentId) return;
const selectedData = payload.data;
if (selectedData && selectedData.length > 0) {
const value = selectedData[0][dataBinding.sourceColumn];
console.log("[DataBinding] 바인딩 값:", { column: dataBinding.sourceColumn, value, columnName });
if (value !== lastBoundValueRef.current) {
lastBoundValueRef.current = value;
if (onFormDataChange && columnName) {
onFormDataChange(columnName, value ?? "");
}
}
} else {
if (lastBoundValueRef.current !== null) {
lastBoundValueRef.current = null;
if (onFormDataChange && columnName) {
onFormDataChange(columnName, "");
}
}
const selectedRow = detail.data?.[0];
const value = selectedRow?.[dataBinding.sourceColumn] ?? "";
if (value !== lastBoundValueRef.current) {
lastBoundValueRef.current = value;
onFormDataChangeRef.current?.(columnName, value);
}
});
};
return () => unsubscribe();
}, [dataBinding?.sourceComponentId, dataBinding?.sourceColumn, columnName, onFormDataChange, isInteractive]);
window.addEventListener("v2-table-selection", handler);
return () => window.removeEventListener("v2-table-selection", handler);
}, [dataBinding?.sourceComponentId, dataBinding?.sourceColumn, columnName]);
return <>{children}</>;
}
@@ -102,18 +76,6 @@ export class V2InputRenderer extends AutoRegisteringComponentRenderer {
const dataBinding = config.dataBinding || (component as any).dataBinding || config.componentConfig?.dataBinding;
if (dataBinding || (config as any).dataBinding || (component as any).dataBinding) {
console.log("[V2InputRenderer] dataBinding 탐색:", {
componentId: component.id,
columnName,
configKeys: Object.keys(config),
configDataBinding: config.dataBinding,
componentDataBinding: (component as any).dataBinding,
nestedDataBinding: config.componentConfig?.dataBinding,
finalDataBinding: dataBinding,
});
}
const inputElement = (
<V2Input
id={component.id}
@@ -153,7 +115,6 @@ export class V2InputRenderer extends AutoRegisteringComponentRenderer {
dataBinding={dataBinding}
columnName={columnName}
onFormDataChange={onFormDataChange}
isInteractive={isInteractive}
>
{inputElement}
</DataBindingWrapper>