feat: Enhance routing details and subcontractor mapping functionality

- Updated the `getRoutingDetails` function to enrich routing details with subcontractor codes, improving data retrieval for routing information.
- Implemented a mapping mechanism to associate subcontractor codes with routing details, ensuring accurate representation of outsourcing suppliers.
- Enhanced the `saveRoutingDetails` function to handle subcontractor mappings during the save operation, ensuring data integrity and consistency.
- Updated the BOM service to improve unit handling and added inventory unit information for better clarity in item representation.
- Refactored production plan management to streamline modal handling and improve error messaging for better user feedback.
This commit is contained in:
kjs
2026-04-17 18:25:35 +09:00
parent 78e102fd45
commit 48b9ba3d2a
31 changed files with 2234 additions and 546 deletions
@@ -223,6 +223,9 @@ export default function TimelineScheduler({
const gridRef = useRef<HTMLDivElement>(null);
const scrollRef = useRef<HTMLDivElement>(null);
// 드래그 이동(move) 직후 자동 발생하는 click 이벤트 1회를 무시하기 위한 플래그.
// 드래그로 일정이 변경된 직후에 모달이 자동 오픈되면서 이전 날짜가 표시되는 버그(TASK:ERP-006) 방지용.
const justDraggedRef = useRef(false);
// 줌 레벨 동기화
useEffect(() => {
@@ -404,6 +407,12 @@ export default function TimelineScheduler({
const newStart = toDateStr(addDays(origStart, dayOffset));
const newEnd = toDateStr(addDays(origEnd, dayOffset));
onEventMove?.(dragState.eventId, newStart, newEnd);
// 드래그 직후 브라우저가 자동 디스패치하는 click 이벤트 1회를 무시해
// 모달이 이전 날짜로 자동 오픈되는 버그(TASK:ERP-006) 방지.
justDraggedRef.current = true;
setTimeout(() => {
justDraggedRef.current = false;
}, 0);
} else if (dragState.mode === "resize-left") {
const newStart = toDateStr(addDays(origStart, dayOffset));
const newEnd = dragState.origEndDate.split("T")[0];
@@ -411,12 +420,20 @@ export default function TimelineScheduler({
if (parseDate(newStart) <= parseDate(newEnd)) {
onEventResize?.(dragState.eventId, newStart, newEnd);
}
justDraggedRef.current = true;
setTimeout(() => {
justDraggedRef.current = false;
}, 0);
} else if (dragState.mode === "resize-right") {
const newStart = dragState.origStartDate.split("T")[0];
const newEnd = toDateStr(addDays(origEnd, dayOffset));
if (parseDate(newStart) <= parseDate(newEnd)) {
onEventResize?.(dragState.eventId, newStart, newEnd);
}
justDraggedRef.current = true;
setTimeout(() => {
justDraggedRef.current = false;
}, 0);
}
}
@@ -770,6 +787,11 @@ export default function TimelineScheduler({
}}
title={`${ev.label || ""} | ${ev.startDate.split("T")[0]} ~ ${ev.endDate.split("T")[0]}${progress > 0 ? ` | ${progress}%` : ""}`}
onClick={(e) => {
// 드래그 직후 자동 발생하는 click은 무시 (TASK:ERP-006).
if (justDraggedRef.current) {
e.stopPropagation();
return;
}
if (!isDragging) {
e.stopPropagation();
onEventClick?.(ev);