This commit is contained in:
2026-07-16 09:53:14 +07:00
parent 0fc112a2e8
commit 29cec708a3
1236 changed files with 212848 additions and 0 deletions

View File

@@ -0,0 +1,155 @@
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 });
}
}