Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 | 'use server'; import { revalidatePath } from 'next/cache'; import type { TransferProblem } from '@prisma/client'; import { requireSession } from '@/lib/session'; import { canApproveTransfer, canBulkAcceptTransfer, transferInitialStatus, } from '@/lib/permissions'; import { approveAllPendingTransfers, createTransfer } from '@/lib/transfers'; import { searchCategorizedProducts } from '@/lib/products'; import { logActivity } from '@/lib/activity'; export type ActionState = { error?: string; success?: string }; function parseProblem(v: unknown): TransferProblem { switch (v) { case 'CANT_LOGIN': return 'CANT_LOGIN'; case 'VERIFICATION': return 'VERIFICATION'; case 'RED_ACCOUNT': return 'RED_ACCOUNT'; case 'OTHER': return 'OTHER'; default: return 'NONE'; } } export async function initiateTransferAction(_prev: ActionState, formData: FormData): Promise<ActionState> { const session = await requireSession(); const productId = String(formData.get('productId') ?? ''); const toBranchId = String(formData.get('toBranchId') ?? ''); if (!productId) return { error: 'กรุณาเลือกสินค้า' }; if (!toBranchId) return { error: 'กรุณาเลือกสาขาปลายทาง' }; const problem = parseProblem(formData.get('problem')); const customerName = String(formData.get('customerName') ?? '').trim() || null; const notes = String(formData.get('notes') ?? '').trim() || null; const status = transferInitialStatus(session.role); // MASTER → COMPLETED, STAFF → PENDING await createTransfer({ productId, fromBranchId: null, toBranchId, problem, customerName, notes, initiatedByUserId: session.sub, status, }); await logActivity({ userId: session.sub, action: status === 'COMPLETED' ? 'transfer.complete' : 'transfer.request', detail: `${productId} → ${toBranchId}`, }); revalidatePath('/transfer'); return { success: status === 'COMPLETED' ? 'โอนย้ายสำเร็จ' : 'ส่งคำขอ รอ Master อนุมัติ' }; } /** * Server-side product search for the Transfer picker. Returns a small slice * of matching products as `[{ value, label, group }]` ready for SearchableSelect. */ export async function searchProductsAction(query: string): Promise< { value: string; label: string; group: string }[] > { await requireSession(); const rows = await searchCategorizedProducts(query, 50); return rows.map((p) => ({ value: p.id, label: `${p.branchCode ?? '?'} — ${p.loginData ?? '?'} (${p.subtypeName ?? '—'})`, group: p.subtypeName ?? 'ไม่ระบุ', })); } export async function bulkAcceptAction(_prev: ActionState, _formData: FormData): Promise<ActionState> { const session = await requireSession(); if (!canBulkAcceptTransfer(session.role)) return { error: 'ไม่มีสิทธิ์ดำเนินการ' }; if (!canApproveTransfer(session.role)) return { error: 'ไม่มีสิทธิ์อนุมัติ' }; const n = await approveAllPendingTransfers(session.sub); await logActivity({ userId: session.sub, action: 'transfer.bulk-accept', detail: `approved ${n} pending transfer(s)`, }); revalidatePath('/transfer'); return { success: `ยืนยันรับเฟส ${n} รายการเข้าระบบเรียบร้อย` }; } |