From 79e3420ff331ac26885df5344399b9af5451aeda Mon Sep 17 00:00:00 2001 From: kjs Date: Mon, 16 Mar 2026 09:35:23 +0900 Subject: [PATCH] refactor: update production controller to use AuthenticatedRequest - Modified the production controller to replace the generic Request type with AuthenticatedRequest for better type safety and to ensure user authentication is handled correctly. - This change enhances the security and clarity of the API endpoints related to production plan management, ensuring that user-specific data is accessed appropriately. Made-with: Cursor --- .../src/controllers/productionController.ts | 21 +++--- .../TimelineSchedulerComponent.tsx | 64 +++++++++---------- .../components/ResourceRow.tsx | 8 +-- .../components/ScheduleBar.tsx | 16 ++--- .../components/TimelineHeader.tsx | 10 +-- 5 files changed, 60 insertions(+), 59 deletions(-) diff --git a/backend-node/src/controllers/productionController.ts b/backend-node/src/controllers/productionController.ts index 9d6c56c4..aa3f3a36 100644 --- a/backend-node/src/controllers/productionController.ts +++ b/backend-node/src/controllers/productionController.ts @@ -2,13 +2,14 @@ * 생산계획 컨트롤러 */ -import { Request, Response } from "express"; +import { Response } from "express"; +import { AuthenticatedRequest } from "../types/auth"; import * as productionService from "../services/productionPlanService"; import { logger } from "../utils/logger"; // ─── 수주 데이터 조회 (품목별 그룹핑) ─── -export async function getOrderSummary(req: Request, res: Response) { +export async function getOrderSummary(req: AuthenticatedRequest, res: Response) { try { const companyCode = req.user!.companyCode; const { excludePlanned, itemCode, itemName } = req.query; @@ -28,7 +29,7 @@ export async function getOrderSummary(req: Request, res: Response) { // ─── 안전재고 부족분 조회 ─── -export async function getStockShortage(req: Request, res: Response) { +export async function getStockShortage(req: AuthenticatedRequest, res: Response) { try { const companyCode = req.user!.companyCode; const data = await productionService.getStockShortage(companyCode); @@ -41,7 +42,7 @@ export async function getStockShortage(req: Request, res: Response) { // ─── 생산계획 상세 조회 ─── -export async function getPlanById(req: Request, res: Response) { +export async function getPlanById(req: AuthenticatedRequest, res: Response) { try { const companyCode = req.user!.companyCode; const planId = parseInt(req.params.id, 10); @@ -59,7 +60,7 @@ export async function getPlanById(req: Request, res: Response) { // ─── 생산계획 수정 ─── -export async function updatePlan(req: Request, res: Response) { +export async function updatePlan(req: AuthenticatedRequest, res: Response) { try { const companyCode = req.user!.companyCode; const planId = parseInt(req.params.id, 10); @@ -78,7 +79,7 @@ export async function updatePlan(req: Request, res: Response) { // ─── 생산계획 삭제 ─── -export async function deletePlan(req: Request, res: Response) { +export async function deletePlan(req: AuthenticatedRequest, res: Response) { try { const companyCode = req.user!.companyCode; const planId = parseInt(req.params.id, 10); @@ -96,7 +97,7 @@ export async function deletePlan(req: Request, res: Response) { // ─── 자동 스케줄 생성 ─── -export async function generateSchedule(req: Request, res: Response) { +export async function generateSchedule(req: AuthenticatedRequest, res: Response) { try { const companyCode = req.user!.companyCode; const createdBy = req.user!.userId; @@ -116,7 +117,7 @@ export async function generateSchedule(req: Request, res: Response) { // ─── 스케줄 병합 ─── -export async function mergeSchedules(req: Request, res: Response) { +export async function mergeSchedules(req: AuthenticatedRequest, res: Response) { try { const companyCode = req.user!.companyCode; const mergedBy = req.user!.userId; @@ -142,7 +143,7 @@ export async function mergeSchedules(req: Request, res: Response) { // ─── 반제품 계획 자동 생성 ─── -export async function generateSemiSchedule(req: Request, res: Response) { +export async function generateSemiSchedule(req: AuthenticatedRequest, res: Response) { try { const companyCode = req.user!.companyCode; const createdBy = req.user!.userId; @@ -167,7 +168,7 @@ export async function generateSemiSchedule(req: Request, res: Response) { // ─── 스케줄 분할 ─── -export async function splitSchedule(req: Request, res: Response) { +export async function splitSchedule(req: AuthenticatedRequest, res: Response) { try { const companyCode = req.user!.companyCode; const splitBy = req.user!.userId; diff --git a/frontend/lib/registry/components/v2-timeline-scheduler/TimelineSchedulerComponent.tsx b/frontend/lib/registry/components/v2-timeline-scheduler/TimelineSchedulerComponent.tsx index f6fbaea2..e7da45a6 100644 --- a/frontend/lib/registry/components/v2-timeline-scheduler/TimelineSchedulerComponent.tsx +++ b/frontend/lib/registry/components/v2-timeline-scheduler/TimelineSchedulerComponent.tsx @@ -226,11 +226,11 @@ export function TimelineSchedulerComponent({ // 디자인 모드 플레이스홀더 if (isDesignMode) { return ( -
+
- -

타임라인 스케줄러

-

+ +

타임라인 스케줄러

+

{config.selectedTable ? `테이블: ${config.selectedTable}` : "테이블을 선택하세요"} @@ -244,12 +244,12 @@ export function TimelineSchedulerComponent({ if (isLoading) { return (

- - 로딩 중... + + 로딩 중...
); @@ -259,12 +259,12 @@ export function TimelineSchedulerComponent({ if (error) { return (
-

오류 발생

-

{error}

+

오류 발생

+

{error}

); @@ -274,13 +274,13 @@ export function TimelineSchedulerComponent({ if (schedules.length === 0) { return (
- -

스케줄 데이터가 없습니다

-

+ +

스케줄 데이터가 없습니다

+

좌측 테이블에서 품목을 선택하거나,
스케줄 생성 버튼을 눌러 스케줄을 생성하세요

@@ -292,7 +292,7 @@ export function TimelineSchedulerComponent({ return (
{/* 툴바 */} {config.showToolbar !== false && ( -
+
{/* 네비게이션 */} -
+
{config.showNavigation !== false && ( <> @@ -325,15 +325,15 @@ export function TimelineSchedulerComponent({ variant="ghost" size="sm" onClick={goToNext} - className="h-7 px-2" + className="h-6 px-1.5 sm:h-7 sm:px-2" > - + )} {/* 현재 날짜 범위 표시 */} - + {viewStartDate.getFullYear()}년 {viewStartDate.getMonth() + 1}월{" "} {viewStartDate.getDate()}일 ~{" "} {viewEndDate.getMonth() + 1}월 {viewEndDate.getDate()}일 @@ -341,20 +341,20 @@ export function TimelineSchedulerComponent({
{/* 오른쪽 컨트롤 */} -
+
{/* 줌 컨트롤 */} {config.showZoomControls !== false && ( -
+
- + {zoomLevelOptions.find((o) => o.value === zoomLevel)?.label}
)} @@ -375,9 +375,9 @@ export function TimelineSchedulerComponent({ variant="default" size="sm" onClick={handleAddClick} - className="h-7" + className="h-6 text-xs sm:h-7 sm:text-sm" > - + 추가 )} diff --git a/frontend/lib/registry/components/v2-timeline-scheduler/components/ResourceRow.tsx b/frontend/lib/registry/components/v2-timeline-scheduler/components/ResourceRow.tsx index 407bdd14..75a465a3 100644 --- a/frontend/lib/registry/components/v2-timeline-scheduler/components/ResourceRow.tsx +++ b/frontend/lib/registry/components/v2-timeline-scheduler/components/ResourceRow.tsx @@ -138,13 +138,13 @@ export function ResourceRow({ > {/* 리소스 컬럼 */}
-
{resource.name}
+
{resource.name}
{resource.group && ( -
+
{resource.group}
)} @@ -170,7 +170,7 @@ export function ResourceRow({
)} {/* 제목 */} -
+
{schedule.title}
{/* 진행률 텍스트 */} {config.showProgress && schedule.progress !== undefined && ( -
+
{schedule.progress}%
)} @@ -165,7 +165,7 @@ export function ScheduleBar({ {/* 리사이즈 핸들 - 왼쪽 */} {resizable && (
handleResizeStart("start", e)} /> )} @@ -173,7 +173,7 @@ export function ScheduleBar({ {/* 리사이즈 핸들 - 오른쪽 */} {resizable && (
handleResizeStart("end", e)} /> )} diff --git a/frontend/lib/registry/components/v2-timeline-scheduler/components/TimelineHeader.tsx b/frontend/lib/registry/components/v2-timeline-scheduler/components/TimelineHeader.tsx index 52afc2e2..b3f89cfc 100644 --- a/frontend/lib/registry/components/v2-timeline-scheduler/components/TimelineHeader.tsx +++ b/frontend/lib/registry/components/v2-timeline-scheduler/components/TimelineHeader.tsx @@ -140,7 +140,7 @@ export function TimelineHeader({
{/* 리소스 컬럼 헤더 */}
리소스 @@ -150,7 +150,7 @@ export function TimelineHeader({ {monthGroups.map((group, idx) => (
{group.year}년 {group.month} @@ -162,7 +162,7 @@ export function TimelineHeader({
{/* 리소스 컬럼 (빈칸) */}
@@ -171,7 +171,7 @@ export function TimelineHeader({
)}