From a8fee201332a9bbc3ab77acc0c7a554aa58ade6c Mon Sep 17 00:00:00 2001 From: rstubryan Date: Thu, 30 Oct 2025 10:39:23 +0700 Subject: [PATCH] refactor(FE-208,212): enhance PurchaseRequestForm with product and product warehouse fields --- .../form/PurchaseRequestForm.schema.ts | 50 ++++++++++++++----- .../purchase/form/PurchaseRequestForm.tsx | 36 ++++++++----- .../form/usePurchaseRequestFormHandlers.ts | 9 ++-- src/services/api/purchasing.ts | 10 ++-- 4 files changed, 73 insertions(+), 32 deletions(-) diff --git a/src/components/pages/purchase/form/PurchaseRequestForm.schema.ts b/src/components/pages/purchase/form/PurchaseRequestForm.schema.ts index 204d3e46..c885af99 100644 --- a/src/components/pages/purchase/form/PurchaseRequestForm.schema.ts +++ b/src/components/pages/purchase/form/PurchaseRequestForm.schema.ts @@ -2,6 +2,8 @@ import * as Yup from 'yup'; import { Supplier } from '@/types/api/master-data/supplier'; import { Warehouse } from '@/types/api/master-data/warehouse'; import { CreatePurchaseRequestPayload } from '@/types/api/purchase/purchase'; +import { Product } from '@/types/api/master-data/product'; +import { ProductWarehouse } from '@/types/api/inventory/product-warehouse'; export const PurchaseRequestFormSchema = Yup.object({ supplier: Yup.object({ @@ -28,10 +30,18 @@ export const PurchaseRequestFormSchema = Yup.object({ .required('Warehouse wajib diisi!') .min(1, 'Produk wajib diisi!') .typeError('Warehouse harus berupa angka!'), + product: Yup.object({ + value: Yup.number().min(1).required(), + label: Yup.string().required(), + }).nullable(), product_id: Yup.number() .required('Produk wajib diisi!') .min(1, 'Produk wajib diisi!') .typeError('Produk harus berupa angka!'), + product_warehouse: Yup.object({ + value: Yup.number().min(1).required(), + label: Yup.string().required(), + }).nullable(), product_warehouse_id: Yup.number() .required('Product warehouse wajib diisi!') .min(1, 'Product warehouse wajib diisi!') @@ -57,10 +67,16 @@ export type PurchaseRequestFormValues = Yup.InferType< typeof PurchaseRequestFormSchema >; -type PurchaseRequestFormData = Partial & { +type PurchaseRequestFormData = { supplier?: Supplier; - warehouse?: Warehouse[]; - purchase_items?: CreatePurchaseRequestPayload['purchase_items']; + supplier_id?: number; + credit_term?: number; + notes?: string | null; + purchase_items?: (CreatePurchaseRequestPayload['purchase_items'][0] & { + warehouse?: Warehouse; + product?: Product; + product_warehouse?: ProductWarehouse; + })[]; }; export const getPurchaseRequestFormInitialValues = ( @@ -73,22 +89,30 @@ export const getPurchaseRequestFormInitialValues = ( } : null, supplier_id: initialValues?.supplier_id ?? 0, - credit_term: initialValues?.credit_term ?? 0, + credit_term: initialValues?.credit_term ?? 1, notes: initialValues?.notes ?? '', purchase_items: initialValues?.purchase_items?.map( - (item: NonNullable[0]) => ({ - warehouse: initialValues?.warehouse?.find( - (w) => w.id === item.warehouse_ids - ) + (item: NonNullable[0]) => ({ + warehouse: item.warehouse ? { - value: item.warehouse_ids, - label: - initialValues.warehouse.find((w) => w.id === item.warehouse_ids) - ?.name || '', + value: item.warehouse.id, + label: item.warehouse.name, } : null, warehouse_ids: item.warehouse_ids, + product: item.product + ? { + value: item.product.id, + label: item.product.name, + } + : null, product_id: item.product_id, + product_warehouse: item.product_warehouse + ? { + value: item.product_warehouse.id, + label: item.product_warehouse.product.name, + } + : null, product_warehouse_id: item.product_warehouse_id, total_qty: item.total_qty, price: item.price, @@ -97,7 +121,9 @@ export const getPurchaseRequestFormInitialValues = ( { warehouse: null, warehouse_ids: 0, + product: null, product_id: 0, + product_warehouse: null, product_warehouse_id: 0, total_qty: 0, price: 0, diff --git a/src/components/pages/purchase/form/PurchaseRequestForm.tsx b/src/components/pages/purchase/form/PurchaseRequestForm.tsx index bd0399d8..2c5c7b97 100644 --- a/src/components/pages/purchase/form/PurchaseRequestForm.tsx +++ b/src/components/pages/purchase/form/PurchaseRequestForm.tsx @@ -97,21 +97,18 @@ const PurchaseRequestForm = ({ validateOnBlur: true, onSubmit: async (values) => { const payload: CreatePurchaseRequestPayload = { - supplier_id: values.supplier_id, + supplier_id: values.supplier_id || 0, credit_term: values.credit_term || 0, notes: values.notes || '', purchase_items: (values.purchase_items || []).map((item) => ({ - warehouse_ids: item.warehouse_ids, - product_id: item.product_id, - product_warehouse_id: item.product_warehouse_id, - total_qty: - typeof item.total_qty === 'number' - ? item.total_qty - : parseFloat(String(item.total_qty)) || 0, + warehouse_ids: item.warehouse_ids || 0, + product_id: item.product_id || 0, + product_warehouse_id: item.product_warehouse_id || 0, + total_qty: item.total_qty || 0, price: typeof item.price === 'number' ? item.price - : parseFloat(String(item.price)) || 0, + : parseFloat(item.price) || 0, })), }; @@ -149,8 +146,11 @@ const PurchaseRequestForm = ({ const newPurchaseItems = [ ...(formik.values.purchase_items || []), { + warehouse: null, warehouse_ids: 0, + product: null, product_id: 0, + product_warehouse: null, product_warehouse_id: 0, total_qty: 0, price: 0, @@ -179,12 +179,23 @@ const PurchaseRequestForm = ({ field: string, value: string | number ) => { - if (field === 'warehouse_ids') { - formik.setFieldValue(`purchase_items.${idx}.${field}`, value); - } else { + const integerFields = [ + 'warehouse_ids', + 'product_id', + 'product_warehouse_id', + 'total_qty', + ]; + const floatFields = ['price']; + + if (integerFields.includes(field)) { + const numValue = typeof value === 'string' ? parseInt(value) || 0 : value; + formik.setFieldValue(`purchase_items.${idx}.${field}`, numValue); + } else if (floatFields.includes(field)) { const numValue = typeof value === 'string' ? parseFloat(value) || 0 : value; formik.setFieldValue(`purchase_items.${idx}.${field}`, numValue); + } else { + formik.setFieldValue(`purchase_items.${idx}.${field}`, value); } }; @@ -388,6 +399,7 @@ const PurchaseRequestForm = ({ diff --git a/src/components/pages/purchase/form/usePurchaseRequestFormHandlers.ts b/src/components/pages/purchase/form/usePurchaseRequestFormHandlers.ts index 0594c0f8..c5fb1e48 100644 --- a/src/components/pages/purchase/form/usePurchaseRequestFormHandlers.ts +++ b/src/components/pages/purchase/form/usePurchaseRequestFormHandlers.ts @@ -6,7 +6,7 @@ import { PurchaseApi } from '@/services/api/purchasing'; import { CreatePurchaseRequestPayload, UpdatePurchaseRequestPayload, -} from '@/types/api/purchase/purchasing'; +} from '@/types/api/purchase/purchase'; import { isResponseError } from '@/lib/api-helper'; export const usePurchaseRequestFormHandlers = (initialValuesId?: number) => { @@ -30,7 +30,10 @@ export const usePurchaseRequestFormHandlers = (initialValuesId?: number) => { ); const updatePurchaseRequestHandler = useCallback( - async (purchaseRequestId: number, payload: UpdatePurchaseRequestPayload) => { + async ( + purchaseRequestId: number, + payload: UpdatePurchaseRequestPayload + ) => { const res = await PurchaseApi.update(purchaseRequestId, payload); if (res?.status === 'error') { setPurchaseRequestFormErrorMessage(res.message); @@ -67,4 +70,4 @@ export const usePurchaseRequestFormHandlers = (initialValuesId?: number) => { deletePurchaseRequestClickHandler, confirmationModalDeleteClickHandler, }; -}; \ No newline at end of file +}; diff --git a/src/services/api/purchasing.ts b/src/services/api/purchasing.ts index 6f0fd8ee..2ed23193 100644 --- a/src/services/api/purchasing.ts +++ b/src/services/api/purchasing.ts @@ -1,12 +1,12 @@ import { BaseApiService } from './base'; import { - CreatePurchasePayload, + CreatePurchaseRequestPayload, Purchase, - UpdatePurchasePayload, -} from '@/types/api/purchase/purchasing'; + UpdatePurchaseRequestPayload, +} from '@/types/api/purchase/purchase'; export const PurchaseApi = new BaseApiService< Purchase, - CreatePurchasePayload, - UpdatePurchasePayload + CreatePurchaseRequestPayload, + UpdatePurchaseRequestPayload >('/purchase-requests');