summaryrefslogtreecommitdiff
path: root/lib/vendor-regular-registrations
diff options
context:
space:
mode:
Diffstat (limited to 'lib/vendor-regular-registrations')
-rw-r--r--lib/vendor-regular-registrations/safety-qualification-update-sheet.tsx143
-rw-r--r--lib/vendor-regular-registrations/service.ts62
-rw-r--r--lib/vendor-regular-registrations/table/major-items-update-dialog.tsx (renamed from lib/vendor-regular-registrations/major-items-update-sheet.tsx)38
-rw-r--r--lib/vendor-regular-registrations/table/safety-qualification-update-dialog.tsx (renamed from lib/vendor-regular-registrations/table/safety-qualification-update-sheet.tsx)36
-rw-r--r--lib/vendor-regular-registrations/table/vendor-regular-registrations-table-columns.tsx22
5 files changed, 102 insertions, 199 deletions
diff --git a/lib/vendor-regular-registrations/safety-qualification-update-sheet.tsx b/lib/vendor-regular-registrations/safety-qualification-update-sheet.tsx
deleted file mode 100644
index a93fbf22..00000000
--- a/lib/vendor-regular-registrations/safety-qualification-update-sheet.tsx
+++ /dev/null
@@ -1,143 +0,0 @@
-"use client"
-
-import * as React from "react"
-import { useForm } from "react-hook-form"
-import { zodResolver } from "@hookform/resolvers/zod"
-import { z } from "zod"
-import { toast } from "sonner"
-
-import {
- Sheet,
- SheetContent,
- SheetDescription,
- SheetHeader,
- SheetTitle,
-} from "@/components/ui/sheet"
-import {
- Form,
- FormControl,
- FormField,
- FormItem,
- FormLabel,
- FormMessage,
-} from "@/components/ui/form"
-import { Button } from "@/components/ui/button"
-import { Textarea } from "@/components/ui/textarea"
-import { updateSafetyQualification } from "./service"
-
-const formSchema = z.object({
- safetyQualificationContent: z.string().min(1, "안전적격성 평가 내용을 입력해주세요."),
-})
-
-interface SafetyQualificationUpdateSheetProps {
- open: boolean
- onOpenChange: (open: boolean) => void
- registrationId?: number
- vendorName?: string
- currentContent?: string | null
- onSuccess?: () => void
-}
-
-export function SafetyQualificationUpdateSheet({
- open,
- onOpenChange,
- registrationId,
- vendorName,
- currentContent,
- onSuccess,
-}: SafetyQualificationUpdateSheetProps) {
- const [isLoading, setIsLoading] = React.useState(false)
-
- const form = useForm<z.infer<typeof formSchema>>({
- resolver: zodResolver(formSchema),
- defaultValues: {
- safetyQualificationContent: currentContent || "",
- },
- })
-
- // 폼 값 초기화
- React.useEffect(() => {
- if (open) {
- form.reset({
- safetyQualificationContent: currentContent || "",
- })
- }
- }, [open, currentContent, form])
-
- async function onSubmit(values: z.infer<typeof formSchema>) {
- if (!registrationId) {
- toast.error("등록 ID가 없습니다.")
- return
- }
-
- setIsLoading(true)
- try {
- const result = await updateSafetyQualification(
- registrationId,
- values.safetyQualificationContent
- )
-
- if (result.success) {
- toast.success("안전적격성 평가가 등록되었습니다.")
- onOpenChange(false)
- onSuccess?.()
- } else {
- toast.error(result.error || "안전적격성 평가 등록에 실패했습니다.")
- }
- } catch (error) {
- console.error("안전적격성 평가 등록 오류:", error)
- toast.error("안전적격성 평가 등록 중 오류가 발생했습니다.")
- } finally {
- setIsLoading(false)
- }
- }
-
- return (
- <Sheet open={open} onOpenChange={onOpenChange}>
- <SheetContent className="w-[400px] sm:w-[540px]">
- <SheetHeader>
- <SheetTitle>안전적격성 평가 입력</SheetTitle>
- <SheetDescription>
- {vendorName && `${vendorName}의 `}안전적격성 평가 내용을 입력해주세요.
- </SheetDescription>
- </SheetHeader>
-
- <Form {...form}>
- <form onSubmit={form.handleSubmit(onSubmit)} className="space-y-6 mt-6">
- <FormField
- control={form.control}
- name="safetyQualificationContent"
- render={({ field }) => (
- <FormItem>
- <FormLabel>안전적격성 평가 내용</FormLabel>
- <FormControl>
- <Textarea
- placeholder="안전적격성 평가 결과 및 내용을 입력해주세요..."
- className="min-h-[200px]"
- {...field}
- />
- </FormControl>
- <FormMessage />
- </FormItem>
- )}
- />
-
- <div className="flex justify-end space-x-2">
- <Button
- type="button"
- variant="outline"
- onClick={() => onOpenChange(false)}
- disabled={isLoading}
- >
- 취소
- </Button>
- <Button type="submit" disabled={isLoading}>
- {isLoading ? "저장 중..." : "저장"}
- </Button>
- </div>
- </form>
- </Form>
- </SheetContent>
- </Sheet>
- )
-}
diff --git a/lib/vendor-regular-registrations/service.ts b/lib/vendor-regular-registrations/service.ts
index 51f4e82b..d64c7b8b 100644
--- a/lib/vendor-regular-registrations/service.ts
+++ b/lib/vendor-regular-registrations/service.ts
@@ -25,7 +25,46 @@ import {
basicContractTemplates
} from "@/db/schema";
import db from "@/db/db";
-import { inArray, eq, desc } from "drizzle-orm";
+import { inArray, eq, desc, and, lt } from "drizzle-orm";
+
+// 3개월 이상 정규등록검토 상태인 등록을 장기미등록으로 변경
+async function updatePendingApprovals() {
+ try {
+ const threeMonthsAgo = new Date();
+ threeMonthsAgo.setMonth(threeMonthsAgo.getMonth() - 3);
+
+ // 3개월 이상 정규등록검토 상태인 등록들을 조회
+ const outdatedRegistrations = await db
+ .select()
+ .from(vendorRegularRegistrations)
+ .where(
+ and(
+ eq(vendorRegularRegistrations.status, "in_review"),
+ lt(vendorRegularRegistrations.updatedAt, threeMonthsAgo)
+ )
+ );
+
+ // 장기미등록으로 상태 변경
+ if (outdatedRegistrations.length > 0) {
+ await db
+ .update(vendorRegularRegistrations)
+ .set({
+ status: "pending_approval",
+ updatedAt: new Date(),
+ })
+ .where(
+ and(
+ eq(vendorRegularRegistrations.status, "in_review"),
+ lt(vendorRegularRegistrations.updatedAt, threeMonthsAgo)
+ )
+ );
+
+ console.log(`${outdatedRegistrations.length}개의 등록이 장기미등록으로 변경되었습니다.`);
+ }
+ } catch (error) {
+ console.error("장기미등록 상태 업데이트 오류:", error);
+ }
+}
// 캐싱과 에러 핸들링이 포함된 조회 함수
export async function fetchVendorRegularRegistrations(input?: {
@@ -37,6 +76,9 @@ export async function fetchVendorRegularRegistrations(input?: {
return unstable_cache(
async () => {
try {
+ // 장기미등록 상태 업데이트 실행
+ await updatePendingApprovals();
+
const registrations = await getVendorRegularRegistrations();
let filteredData = registrations;
@@ -113,6 +155,7 @@ export async function createVendorRegistration(data: {
const registration = await createVendorRegularRegistration({
...data,
+ status: data.status || "under_review", // 기본 상태를 '검토중'으로 설정
majorItems: majorItemsJson,
});
@@ -438,7 +481,7 @@ export async function skipLegalReview(vendorIds: number[], skipReason: string) {
// 새로 생성
const newRegistration = await createVendorRegularRegistration({
vendorId: vendorId,
- status: "cp_finished", // CP완료로 변경
+ status: "under_review", // 검토중으로 변경
remarks: `GTC Skip: ${skipReason}`,
});
registrationId = newRegistration.id;
@@ -451,7 +494,6 @@ export async function skipLegalReview(vendorIds: number[], skipReason: string) {
: `GTC Skip: ${skipReason}`;
await updateVendorRegularRegistration(registrationId, {
- status: "cp_finished", // CP완료로 변경
gtcSkipped: true, // GTC Skip 여부 설정
remarks: newRemarks,
});
@@ -630,7 +672,7 @@ export async function fetchVendorRegistrationStatus(vendorId: number) {
}
}
- // 정규업체 등록 정보
+ // 정규업체 등록 정보 (없을 수도 있음 - 기존 정규업체이거나 아직 등록 진행 안함)
const registration = await db
.select({
id: vendorRegularRegistrations.id,
@@ -653,6 +695,15 @@ export async function fetchVendorRegistrationStatus(vendorId: number) {
.where(eq(vendorRegularRegistrations.vendorId, vendorId))
.limit(1)
+ // 정규업체 등록 정보가 없는 경우 (정상적인 상황)
+ if (!registration[0]) {
+ return {
+ success: false,
+ error: "정규업체 등록 진행 정보가 없습니다.", // 에러가 아닌 정보성 메시지
+ noRegistration: true // 등록 정보가 없음을 명시적으로 표시
+ }
+ }
+
// 벤더 첨부파일 조회
const vendorFiles = await db
.select()
@@ -783,7 +834,8 @@ export async function fetchVendorRegistrationStatus(vendorId: number) {
missingDocuments,
businessContacts,
missingContactTypes,
- additionalInfo: additionalInfoCompleted, // boolean 값으로 변경
+ additionalInfo: additionalInfo[0] || null, // 실제 추가정보 데이터 반환
+ additionalInfoCompleted, // 완료 여부는 별도 필드로 추가
pqSubmission: pqSubmission[0] || null,
auditPassed: investigationFiles.length > 0,
basicContracts: vendorContracts, // 기본계약 정보 추가
diff --git a/lib/vendor-regular-registrations/major-items-update-sheet.tsx b/lib/vendor-regular-registrations/table/major-items-update-dialog.tsx
index ba125bbe..26741a1b 100644
--- a/lib/vendor-regular-registrations/major-items-update-sheet.tsx
+++ b/lib/vendor-regular-registrations/table/major-items-update-dialog.tsx
@@ -6,18 +6,18 @@ import { toast } from "sonner"
import { X, Plus, Search } from "lucide-react"
import {
- Sheet,
- SheetContent,
- SheetDescription,
- SheetHeader,
- SheetTitle,
-} from "@/components/ui/sheet"
+ Dialog,
+ DialogContent,
+ DialogDescription,
+ DialogHeader,
+ DialogTitle,
+} from "@/components/ui/dialog"
import { Button } from "@/components/ui/button"
import { Input } from "@/components/ui/input"
import { Badge } from "@/components/ui/badge"
import { Label } from "@/components/ui/label"
import { searchItemsForPQ } from "@/lib/items/service"
-import { updateMajorItems } from "./service"
+import { updateMajorItems } from "../service"
// PQ 대상 품목 타입 정의
interface PQItem {
@@ -25,7 +25,7 @@ interface PQItem {
itemName: string
}
-interface MajorItemsUpdateSheetProps {
+interface MajorItemsUpdateDialogProps {
open: boolean
onOpenChange: (open: boolean) => void
registrationId?: number
@@ -34,14 +34,14 @@ interface MajorItemsUpdateSheetProps {
onSuccess?: () => void
}
-export function MajorItemsUpdateSheet({
+export function MajorItemsUpdateDialog({
open,
onOpenChange,
registrationId,
vendorName,
currentItems,
onSuccess,
-}: MajorItemsUpdateSheetProps) {
+}: MajorItemsUpdateDialogProps) {
const [isLoading, setIsLoading] = useState(false)
const [selectedItems, setSelectedItems] = useState<PQItem[]>([])
@@ -144,14 +144,14 @@ export function MajorItemsUpdateSheet({
}
return (
- <Sheet open={open} onOpenChange={onOpenChange}>
- <SheetContent className="w-[400px] sm:w-[540px]">
- <SheetHeader>
- <SheetTitle>주요품목 등록</SheetTitle>
- <SheetDescription>
+ <Dialog open={open} onOpenChange={onOpenChange}>
+ <DialogContent className="w-[400px] sm:w-[540px] max-h-[90vh] overflow-y-auto">
+ <DialogHeader>
+ <DialogTitle>주요품목 등록</DialogTitle>
+ <DialogDescription>
{vendorName && `${vendorName}의 `}주요품목을 등록해주세요.
- </SheetDescription>
- </SheetHeader>
+ </DialogDescription>
+ </DialogHeader>
<div className="space-y-6 mt-6">
{/* 선택된 아이템들 표시 */}
@@ -239,7 +239,7 @@ export function MajorItemsUpdateSheet({
{isLoading ? "저장 중..." : "저장"}
</Button>
</div>
- </SheetContent>
- </Sheet>
+ </DialogContent>
+ </Dialog>
)
}
diff --git a/lib/vendor-regular-registrations/table/safety-qualification-update-sheet.tsx b/lib/vendor-regular-registrations/table/safety-qualification-update-dialog.tsx
index c2aeba70..80084732 100644
--- a/lib/vendor-regular-registrations/table/safety-qualification-update-sheet.tsx
+++ b/lib/vendor-regular-registrations/table/safety-qualification-update-dialog.tsx
@@ -7,12 +7,12 @@ import { z } from "zod"
import { toast } from "sonner"
import {
- Sheet,
- SheetContent,
- SheetDescription,
- SheetHeader,
- SheetTitle,
-} from "@/components/ui/sheet"
+ Dialog,
+ DialogContent,
+ DialogDescription,
+ DialogHeader,
+ DialogTitle,
+} from "@/components/ui/dialog"
import {
Form,
FormControl,
@@ -29,7 +29,7 @@ const formSchema = z.object({
safetyQualificationContent: z.string().min(1, "안전적격성 평가 내용을 입력해주세요."),
})
-interface SafetyQualificationUpdateSheetProps {
+interface SafetyQualificationUpdateDialogProps {
open: boolean
onOpenChange: (open: boolean) => void
registrationId?: number
@@ -38,14 +38,14 @@ interface SafetyQualificationUpdateSheetProps {
onSuccess?: () => void
}
-export function SafetyQualificationUpdateSheet({
+export function SafetyQualificationUpdateDialog({
open,
onOpenChange,
registrationId,
vendorName,
currentContent,
onSuccess,
-}: SafetyQualificationUpdateSheetProps) {
+}: SafetyQualificationUpdateDialogProps) {
const [isLoading, setIsLoading] = React.useState(false)
const form = useForm<z.infer<typeof formSchema>>({
@@ -93,14 +93,14 @@ export function SafetyQualificationUpdateSheet({
}
return (
- <Sheet open={open} onOpenChange={onOpenChange}>
- <SheetContent className="w-[400px] sm:w-[540px]">
- <SheetHeader>
- <SheetTitle>안전적격성 평가 입력</SheetTitle>
- <SheetDescription>
+ <Dialog open={open} onOpenChange={onOpenChange}>
+ <DialogContent className="w-[400px] sm:w-[540px] max-h-[90vh] overflow-y-auto">
+ <DialogHeader>
+ <DialogTitle>안전적격성 평가 입력</DialogTitle>
+ <DialogDescription>
{vendorName && `${vendorName}의 `}안전적격성 평가 내용을 입력해주세요.
- </SheetDescription>
- </SheetHeader>
+ </DialogDescription>
+ </DialogHeader>
<Form {...form}>
<form onSubmit={form.handleSubmit(onSubmit)} className="space-y-6 mt-6">
@@ -137,7 +137,7 @@ export function SafetyQualificationUpdateSheet({
</div>
</form>
</Form>
- </SheetContent>
- </Sheet>
+ </DialogContent>
+ </Dialog>
)
}
diff --git a/lib/vendor-regular-registrations/table/vendor-regular-registrations-table-columns.tsx b/lib/vendor-regular-registrations/table/vendor-regular-registrations-table-columns.tsx
index 765b0279..7446716b 100644
--- a/lib/vendor-regular-registrations/table/vendor-regular-registrations-table-columns.tsx
+++ b/lib/vendor-regular-registrations/table/vendor-regular-registrations-table-columns.tsx
@@ -13,29 +13,23 @@ import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigge
import { Eye, FileText, Ellipsis, Shield, Package } from "lucide-react"
import { toast } from "sonner"
import { useState } from "react"
-import { SafetyQualificationUpdateSheet } from "./safety-qualification-update-sheet"
-import { MajorItemsUpdateSheet } from "../major-items-update-sheet"
+import { SafetyQualificationUpdateDialog } from "./safety-qualification-update-dialog"
+import { MajorItemsUpdateDialog } from "./major-items-update-dialog"
const statusLabels = {
- audit_pass: "실사통과",
- cp_submitted: "CP등록",
- cp_review: "CP검토",
- cp_finished: "CP완료",
+ under_review: "검토중",
approval_ready: "조건충족",
- registration_requested: "등록요청됨",
in_review: "정규등록검토",
+ completed: "등록완료",
pending_approval: "장기미등록",
}
const statusColors = {
- audit_pass: "bg-blue-100 text-blue-800",
- cp_submitted: "bg-green-100 text-green-800",
- cp_review: "bg-yellow-100 text-yellow-800",
- cp_finished: "bg-purple-100 text-purple-800",
+ under_review: "bg-blue-100 text-blue-800",
approval_ready: "bg-emerald-100 text-emerald-800",
- registration_requested: "bg-indigo-100 text-indigo-800",
in_review: "bg-orange-100 text-orange-800",
+ completed: "bg-green-100 text-green-800",
pending_approval: "bg-red-100 text-red-800",
}
@@ -295,7 +289,7 @@ export function getColumns(): ColumnDef<VendorRegularRegistration>[] {
</DropdownMenuContent>
</DropdownMenu>
- <SafetyQualificationUpdateSheet
+ <SafetyQualificationUpdateDialog
open={safetyQualificationSheetOpen}
onOpenChange={setSafetyQualificationSheetOpen}
registrationId={registration.id}
@@ -306,7 +300,7 @@ export function getColumns(): ColumnDef<VendorRegularRegistration>[] {
window.location.reload()
}}
/>
- <MajorItemsUpdateSheet
+ <MajorItemsUpdateDialog
open={majorItemsSheetOpen}
onOpenChange={setMajorItemsSheetOpen}
registrationId={registration.id}