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

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

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                                                                                                                                                                   
'use server';

import { revalidatePath } from 'next/cache';
import { requireSession } from '@/lib/session';
import { canImportInventory } from '@/lib/permissions';
import { createProduct, setQcResult } from '@/lib/products';
import { logActivity } from '@/lib/activity';
import { prisma } from '@/lib/db';

export type ActionState = { error?: string; success?: string };

export async function importProductAction(_prev: ActionState, formData: FormData): Promise<ActionState> {
  const session = await requireSession();
  if (!canImportInventory(session.role)) return { error: 'ไม่มีสิทธิ์นำเข้าสินค้า' };

  const branchId   = String(formData.get('branchId') ?? '');
  const loginData  = String(formData.get('loginData') ?? '').trim();
  const subChoice  = String(formData.get('subtypeChoice') ?? '');
  const rawTypeRaw = String(formData.get('rawType') ?? '').trim();
  const email      = String(formData.get('email') ?? '').trim() || null;
  const bankInfo   = String(formData.get('bankInfo') ?? '').trim() || null;

  if (!branchId) return { error: 'กรุณาเลือกสาขา' };
  if (!loginData) return { error: 'กรุณากรอกข้อมูล ID | Password' };
  if (!subChoice) return { error: 'กรุณาเลือกประเภทสินค้า' };

  // Hybrid subtype handling (per client-approved exception 2026-05-21):
  //   subChoice = 'unspecified' → both subtypeId AND rawType null; Categorization team assigns later
  //   subChoice = 'other'       → rawType text only; Categorization team refines into a subtype later
  //   subChoice = '<subtypeId>' → use as Subtype FK directly (skip Categorization after QC)
  let subtypeId: string | null = null;
  let rawType:   string | null = null;
  let importNote = 'unspecified';

  if (subChoice === 'unspecified') {
    // both stay null
  } else if (subChoice === 'other') {
    if (!rawTypeRaw) return { error: 'กรุณาระบุประเภทสินค้า' };
    rawType = rawTypeRaw;
    importNote = `rawType=${rawType}`;
  } else {
    const exists = await prisma.productSubtype.findUnique({ where: { id: subChoice } });
    if (!exists) return { error: 'ประเภทสินค้าไม่ถูกต้อง' };
    subtypeId = subChoice;
    importNote = 'subtype set at import';
  }

  const product = await createProduct({
    branchId, loginData, subtypeId, rawType, email, bankInfo, createdById: session.sub,
  });
  await logActivity({
    userId: session.sub,
    action: 'product.create',
    detail: `${product.id} — ${importNote}`,
  });
  revalidatePath('/inventory');
  return { success: 'บันทึกข้อมูลและส่งเข้ารายการตรวจสอบแล้ว' };
}

export async function qcPassAction(_prev: ActionState, formData: FormData): Promise<ActionState> {
  const session = await requireSession();
  const id = String(formData.get('id') ?? '');
  if (!id) return { error: 'Missing product id' };

  await setQcResult({ productId: id, pass: true, qcByUserId: session.sub });
  await logActivity({ userId: session.sub, action: 'product.qc.pass', detail: id });
  revalidatePath('/inventory');
  return { success: 'ผ่านการตรวจสอบ (QC Pass)' };
}

export async function qcFailAction(_prev: ActionState, formData: FormData): Promise<ActionState> {
  const session = await requireSession();
  const id = String(formData.get('id') ?? '');
  const reason = String(formData.get('reason') ?? '').trim() || 'ไม่ระบุสาเหตุ';
  if (!id) return { error: 'Missing product id' };

  await setQcResult({ productId: id, pass: false, failReason: reason, qcByUserId: session.sub });
  await logActivity({ userId: session.sub, action: 'product.qc.fail', detail: `${id} — ${reason}` });
  revalidatePath('/inventory');
  return { success: 'บันทึกสถานะไม่ผ่านเรียบร้อย' };
}