From c6fcb17b4d784b93f2b9a23a7a9da9539ab5800c Mon Sep 17 00:00:00 2001 From: rstubryan Date: Wed, 29 Oct 2025 20:31:31 +0700 Subject: [PATCH] feat(FE-212): add validation schemas for purchase request and update forms --- .../purchase/form/PurchaseForm.schema.ts | 165 ++++++++++++++++++ src/types/api/purchasing/purchasing.d.ts | 16 +- 2 files changed, 167 insertions(+), 14 deletions(-) create mode 100644 src/components/pages/purchase/form/PurchaseForm.schema.ts diff --git a/src/components/pages/purchase/form/PurchaseForm.schema.ts b/src/components/pages/purchase/form/PurchaseForm.schema.ts new file mode 100644 index 00000000..49292e95 --- /dev/null +++ b/src/components/pages/purchase/form/PurchaseForm.schema.ts @@ -0,0 +1,165 @@ +import * as Yup from 'yup'; +import { CreatePurchaseRequestPayload } from '@/types/api/purchasing/purchasing'; +import { Supplier } from '@/types/api/master-data/supplier'; +import { Warehouse } from '@/types/api/master-data/warehouse'; + +export const PurchaseRequestFormSchema = Yup.object({ + supplier: Yup.object({ + value: Yup.number().min(1).required(), + label: Yup.string().required(), + }).nullable(), + supplier_id: Yup.number() + .default(0) + .typeError('Supplier wajib diisi!') + .test( + 'is-valid-supplier', + 'Supplier wajib diisi!', + (value) => value !== undefined && value !== null && value > 0 + ) + .required('Supplier wajib diisi!'), + warehouse: Yup.array() + .of( + Yup.object({ + value: Yup.number().min(1).required(), + label: Yup.string().required(), + }) + ) + .min(1, 'Minimal harus ada 1 warehouse!') + .required('Warehouse wajib diisi!') + .nullable(), + warehouse_ids: Yup.array() + .of(Yup.number().min(1)) + .min(1, 'Minimal harus ada 1 warehouse!') + .required('Warehouse wajib diisi!'), + credit_term: Yup.number() + .required('Termin kredit wajib diisi!') + .min(0, 'Termin kredit tidak boleh negatif!') + .typeError('Termin kredit harus berupa angka!'), + notes: Yup.string().optional().nullable(), + purchase_items: Yup.array() + .of( + Yup.object({ + product_id: Yup.number() + .required('Produk wajib diisi!') + .min(1, 'Produk wajib diisi!') + .typeError('Produk harus berupa angka!'), + product_warehouse_id: Yup.number() + .optional() + .nullable() + .typeError('Product warehouse harus berupa angka!'), + total_qty: Yup.number() + .required('Jumlah total wajib diisi!') + .min(0, 'Jumlah total tidak boleh negatif!') + .typeError('Jumlah total harus berupa angka!'), + price: Yup.number() + .required('Harga wajib diisi!') + .min(0, 'Harga tidak boleh negatif!') + .typeError('Harga harus berupa angka!'), + }) + ) + .min(1, 'Minimal harus ada 1 item pembelian!') + .required('Item pembelian wajib diisi!'), +}); + +export const UpdatePurchaseRequestFormSchema = Yup.object({ + supplier: Yup.object({ + value: Yup.number().min(1).required(), + label: Yup.string().required(), + }).nullable(), + supplier_id: Yup.number() + .default(0) + .typeError('Supplier wajib diisi!') + .test( + 'is-valid-supplier', + 'Supplier wajib diisi!', + (value) => value !== undefined && value !== null && value > 0 + ) + .required('Supplier wajib diisi!'), + warehouse: Yup.array() + .of( + Yup.object({ + value: Yup.number().min(1).required(), + label: Yup.string().required(), + }) + ) + .min(1, 'Minimal harus ada 1 warehouse!') + .required('Warehouse wajib diisi!') + .nullable(), + warehouse_ids: Yup.array() + .of(Yup.number().min(1)) + .min(1, 'Minimal harus ada 1 warehouse!') + .required('Warehouse wajib diisi!'), + credit_term: Yup.number() + .required('Termin kredit wajib diisi!') + .min(0, 'Termin kredit tidak boleh negatif!') + .typeError('Termin kredit harus berupa angka!'), + notes: Yup.string().optional().nullable(), + purchase_items: Yup.array() + .of( + Yup.object({ + product_id: Yup.number() + .required('Produk wajib diisi!') + .min(1, 'Produk wajib diisi!') + .typeError('Produk harus berupa angka!'), + product_warehouse_id: Yup.number() + .optional() + .nullable() + .typeError('Product warehouse harus berupa angka!'), + total_qty: Yup.number() + .required('Jumlah total wajib diisi!') + .min(0, 'Jumlah total tidak boleh negatif!') + .typeError('Jumlah total harus berupa angka!'), + price: Yup.number() + .required('Harga wajib diisi!') + .min(0, 'Harga tidak boleh negatif!') + .typeError('Harga harus berupa angka!'), + }) + ) + .min(1, 'Minimal harus ada 1 item pembelian!') + .required('Item pembelian wajib diisi!'), +}); + +export type PurchaseRequestFormValues = Yup.InferType< + typeof PurchaseRequestFormSchema +>; + +type PurchaseRequestFormData = Partial & { + supplier?: Supplier; + warehouse?: Warehouse[]; + purchase_items?: CreatePurchaseRequestPayload['purchase_items']; +}; + +export const getPurchaseRequestFormInitialValues = ( + initialValues?: PurchaseRequestFormData +): PurchaseRequestFormValues => ({ + supplier: initialValues?.supplier + ? { + value: initialValues.supplier.id, + label: initialValues.supplier.name, + } + : null, + supplier_id: initialValues?.supplier_id ?? 0, + warehouse: + initialValues?.warehouse?.map((warehouse) => ({ + value: warehouse.id, + label: warehouse.name, + })) ?? [], + warehouse_ids: initialValues?.warehouse_ids ?? [], + credit_term: initialValues?.credit_term ?? 0, + notes: initialValues?.notes ?? '', + purchase_items: initialValues?.purchase_items?.map( + (item: NonNullable[0]) => ({ + product_id: item.product_id, + product_warehouse_id: item.product_warehouse_id, + total_qty: item.total_qty, + price: item.price, + }) + ) ?? [ + { + product_id: 0, + product_warehouse_id: null, + total_qty: 0, + price: 0, + }, + ], +}); diff --git a/src/types/api/purchasing/purchasing.d.ts b/src/types/api/purchasing/purchasing.d.ts index 479efd9c..eea53e1d 100644 --- a/src/types/api/purchasing/purchasing.d.ts +++ b/src/types/api/purchasing/purchasing.d.ts @@ -19,29 +19,17 @@ export type BasePurchase = { export type Purchase = BaseMetadata & BasePurchase; -export type CreatePurchasePayload = { - pr_number: string; - po_number: string; - po_date: string; +export type CreatePurchaseRequestPayload = { supplier_id: number; warehouse_ids: number[]; credit_term: number; - due_date: string; - grand_total: number; notes?: string | null; purchase_items: { product_id: number; product_warehouse_id?: number | null; - received_date?: string | null; - travel_number?: string | null; - travel_number_docs?: string | null; - vehicle_number?: string | null; - sub_qty: number; total_qty: number; - total_used: number; price: number; - total_price: number; }[]; }; -export type UpdatePurchasePayload = CreatePurchasePayload; +export type UpdatePurchaseRequestPayload = CreatePurchaseRequestPayload;