import { and, eq, ne } from 'drizzle-orm'; import { NextRequest, NextResponse } from 'next/server'; import { trainingPolicies } from '@/db/schema'; import { AUDIT_ACTION, AUDIT_MODULE, getRequestMetadata, logAuditEvent, toAuditValue } from '@/features/audit-logs/server/audit-service'; import type { TrainingPolicyMutationPayload } from '@/features/training-policy/api/types'; import { getTrainingPolicyByIdForOrganization, getTrainingPolicyByYearForOrganization, getTrainingPolicyDetailForOrganization, normalizeTrainingPolicyPayload, serializeTrainingPolicy } from '@/features/training-policy/server/training-policy-data'; import { AuthError, requirePermission } from '@/lib/auth/session'; import { db } from '@/lib/db'; type Params = { params: Promise<{ id: string }> }; export async function GET(_request: NextRequest, { params }: Params) { try { const { organization } = await requirePermission('training_policy:read'); const { id } = await params; const policyId = Number(id); const policy = await getTrainingPolicyDetailForOrganization({ id: policyId, organizationId: organization.id }); if (!policy) { return NextResponse.json( { success: false, message: `ไม่พบนโยบายการอบรมรหัส ${id}` }, { status: 404 } ); } return NextResponse.json({ success: true, time: new Date().toISOString(), message: 'โหลดรายละเอียดนโยบายการอบรมเรียบร้อยแล้ว', policy }); } catch (error) { if (error instanceof AuthError) { return NextResponse.json({ message: error.message }, { status: error.status }); } console.error('GET /api/training-policies/[id] failed', error); return NextResponse.json({ message: 'ไม่สามารถโหลดนโยบายการอบรมได้' }, { status: 500 }); } } export async function PATCH(request: NextRequest, { params }: Params) { try { const { organization, session } = await requirePermission('training_policy:write'); const requestMetadata = getRequestMetadata(request); const { id } = await params; const policyId = Number(id); const body = normalizeTrainingPolicyPayload( (await request.json()) as TrainingPolicyMutationPayload ); const existingPolicy = await getTrainingPolicyByIdForOrganization({ id: policyId, organizationId: organization.id }); if (!existingPolicy) { return NextResponse.json( { success: false, message: `ไม่พบนโยบายการอบรมรหัส ${id}` }, { status: 404 } ); } const duplicatePolicy = await getTrainingPolicyByYearForOrganization({ year: body.year, organizationId: organization.id, excludeId: policyId }); if (duplicatePolicy) { return NextResponse.json( { success: false, message: `มีนโยบายการอบรมสำหรับปี ${body.year} อยู่แล้ว` }, { status: 409 } ); } const policy = await db.transaction(async (tx) => { if (body.isActive) { await tx .update(trainingPolicies) .set({ isActive: false, updatedAt: new Date() }) .where( and( eq(trainingPolicies.organizationId, organization.id), ne(trainingPolicies.id, policyId) ) ); } const [updatedPolicy] = await tx .update(trainingPolicies) .set({ year: body.year, totalHours: body.totalHours, kHours: body.kHours, sHours: body.sHours, aHours: body.aHours, isActive: body.isActive, updatedAt: new Date() }) .where(and(eq(trainingPolicies.id, policyId), eq(trainingPolicies.organizationId, organization.id))) .returning(); return updatedPolicy; }); const serializedPolicy = serializeTrainingPolicy(policy, { updatedByName: session.user.name ?? null }); await logAuditEvent({ organizationId: organization.id, userId: session.user.id, module: AUDIT_MODULE.TRAINING_POLICY, action: AUDIT_ACTION.UPDATE, entityName: `ปี ${policy.year}`, entityId: policy.id, oldValue: toAuditValue(serializeTrainingPolicy(existingPolicy)), newValue: toAuditValue(serializedPolicy), ...requestMetadata }); return NextResponse.json({ success: true, time: new Date().toISOString(), message: 'อัปเดตนโยบายการอบรมเรียบร้อยแล้ว', policy: serializedPolicy }); } catch (error) { if (error instanceof AuthError) { return NextResponse.json({ message: error.message }, { status: error.status }); } console.error('PATCH /api/training-policies/[id] failed', error); return NextResponse.json({ message: 'ไม่สามารถอัปเดตนโยบายการอบรมได้' }, { status: 500 }); } }