All files / app/(authed)/transfer actions.ts

0% Statements 0/88
0% Branches 0/1
0% Functions 0/1
0% Lines 0/88

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} รายการเข้าระบบเรียบร้อย` };
}