refactor(FE-208,212): enhance PurchaseRequestForm with product and product warehouse fields

This commit is contained in:
rstubryan
2025-10-30 10:39:23 +07:00
parent b0e8a460fd
commit a8fee20133
4 changed files with 73 additions and 32 deletions
@@ -2,6 +2,8 @@ import * as Yup from 'yup';
import { Supplier } from '@/types/api/master-data/supplier'; import { Supplier } from '@/types/api/master-data/supplier';
import { Warehouse } from '@/types/api/master-data/warehouse'; import { Warehouse } from '@/types/api/master-data/warehouse';
import { CreatePurchaseRequestPayload } from '@/types/api/purchase/purchase'; 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({ export const PurchaseRequestFormSchema = Yup.object({
supplier: Yup.object({ supplier: Yup.object({
@@ -28,10 +30,18 @@ export const PurchaseRequestFormSchema = Yup.object({
.required('Warehouse wajib diisi!') .required('Warehouse wajib diisi!')
.min(1, 'Produk wajib diisi!') .min(1, 'Produk wajib diisi!')
.typeError('Warehouse harus berupa angka!'), .typeError('Warehouse harus berupa angka!'),
product: Yup.object({
value: Yup.number().min(1).required(),
label: Yup.string().required(),
}).nullable(),
product_id: Yup.number() product_id: Yup.number()
.required('Produk wajib diisi!') .required('Produk wajib diisi!')
.min(1, 'Produk wajib diisi!') .min(1, 'Produk wajib diisi!')
.typeError('Produk harus berupa angka!'), .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() product_warehouse_id: Yup.number()
.required('Product warehouse wajib diisi!') .required('Product warehouse wajib diisi!')
.min(1, 'Product warehouse wajib diisi!') .min(1, 'Product warehouse wajib diisi!')
@@ -57,10 +67,16 @@ export type PurchaseRequestFormValues = Yup.InferType<
typeof PurchaseRequestFormSchema typeof PurchaseRequestFormSchema
>; >;
type PurchaseRequestFormData = Partial<CreatePurchaseRequestPayload> & { type PurchaseRequestFormData = {
supplier?: Supplier; supplier?: Supplier;
warehouse?: Warehouse[]; supplier_id?: number;
purchase_items?: CreatePurchaseRequestPayload['purchase_items']; credit_term?: number;
notes?: string | null;
purchase_items?: (CreatePurchaseRequestPayload['purchase_items'][0] & {
warehouse?: Warehouse;
product?: Product;
product_warehouse?: ProductWarehouse;
})[];
}; };
export const getPurchaseRequestFormInitialValues = ( export const getPurchaseRequestFormInitialValues = (
@@ -73,22 +89,30 @@ export const getPurchaseRequestFormInitialValues = (
} }
: null, : null,
supplier_id: initialValues?.supplier_id ?? 0, supplier_id: initialValues?.supplier_id ?? 0,
credit_term: initialValues?.credit_term ?? 0, credit_term: initialValues?.credit_term ?? 1,
notes: initialValues?.notes ?? '', notes: initialValues?.notes ?? '',
purchase_items: initialValues?.purchase_items?.map( purchase_items: initialValues?.purchase_items?.map(
(item: NonNullable<CreatePurchaseRequestPayload['purchase_items']>[0]) => ({ (item: NonNullable<PurchaseRequestFormData['purchase_items']>[0]) => ({
warehouse: initialValues?.warehouse?.find( warehouse: item.warehouse
(w) => w.id === item.warehouse_ids
)
? { ? {
value: item.warehouse_ids, value: item.warehouse.id,
label: label: item.warehouse.name,
initialValues.warehouse.find((w) => w.id === item.warehouse_ids)
?.name || '',
} }
: null, : null,
warehouse_ids: item.warehouse_ids, warehouse_ids: item.warehouse_ids,
product: item.product
? {
value: item.product.id,
label: item.product.name,
}
: null,
product_id: item.product_id, 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, product_warehouse_id: item.product_warehouse_id,
total_qty: item.total_qty, total_qty: item.total_qty,
price: item.price, price: item.price,
@@ -97,7 +121,9 @@ export const getPurchaseRequestFormInitialValues = (
{ {
warehouse: null, warehouse: null,
warehouse_ids: 0, warehouse_ids: 0,
product: null,
product_id: 0, product_id: 0,
product_warehouse: null,
product_warehouse_id: 0, product_warehouse_id: 0,
total_qty: 0, total_qty: 0,
price: 0, price: 0,
@@ -97,21 +97,18 @@ const PurchaseRequestForm = ({
validateOnBlur: true, validateOnBlur: true,
onSubmit: async (values) => { onSubmit: async (values) => {
const payload: CreatePurchaseRequestPayload = { const payload: CreatePurchaseRequestPayload = {
supplier_id: values.supplier_id, supplier_id: values.supplier_id || 0,
credit_term: values.credit_term || 0, credit_term: values.credit_term || 0,
notes: values.notes || '', notes: values.notes || '',
purchase_items: (values.purchase_items || []).map((item) => ({ purchase_items: (values.purchase_items || []).map((item) => ({
warehouse_ids: item.warehouse_ids, warehouse_ids: item.warehouse_ids || 0,
product_id: item.product_id, product_id: item.product_id || 0,
product_warehouse_id: item.product_warehouse_id, product_warehouse_id: item.product_warehouse_id || 0,
total_qty: total_qty: item.total_qty || 0,
typeof item.total_qty === 'number'
? item.total_qty
: parseFloat(String(item.total_qty)) || 0,
price: price:
typeof item.price === 'number' typeof item.price === 'number'
? item.price ? item.price
: parseFloat(String(item.price)) || 0, : parseFloat(item.price) || 0,
})), })),
}; };
@@ -149,8 +146,11 @@ const PurchaseRequestForm = ({
const newPurchaseItems = [ const newPurchaseItems = [
...(formik.values.purchase_items || []), ...(formik.values.purchase_items || []),
{ {
warehouse: null,
warehouse_ids: 0, warehouse_ids: 0,
product: null,
product_id: 0, product_id: 0,
product_warehouse: null,
product_warehouse_id: 0, product_warehouse_id: 0,
total_qty: 0, total_qty: 0,
price: 0, price: 0,
@@ -179,12 +179,23 @@ const PurchaseRequestForm = ({
field: string, field: string,
value: string | number value: string | number
) => { ) => {
if (field === 'warehouse_ids') { const integerFields = [
formik.setFieldValue(`purchase_items.${idx}.${field}`, value); 'warehouse_ids',
} else { '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 = const numValue =
typeof value === 'string' ? parseFloat(value) || 0 : value; typeof value === 'string' ? parseFloat(value) || 0 : value;
formik.setFieldValue(`purchase_items.${idx}.${field}`, numValue); formik.setFieldValue(`purchase_items.${idx}.${field}`, numValue);
} else {
formik.setFieldValue(`purchase_items.${idx}.${field}`, value);
} }
}; };
@@ -388,6 +399,7 @@ const PurchaseRequestForm = ({
</td> </td>
<td> <td>
<TextInput <TextInput
required
name={`purchase_items.${idx}.product_warehouse_id`} name={`purchase_items.${idx}.product_warehouse_id`}
value={item.product_warehouse_id || ''} value={item.product_warehouse_id || ''}
onChange={(e) => onChange={(e) =>
@@ -6,7 +6,7 @@ import { PurchaseApi } from '@/services/api/purchasing';
import { import {
CreatePurchaseRequestPayload, CreatePurchaseRequestPayload,
UpdatePurchaseRequestPayload, UpdatePurchaseRequestPayload,
} from '@/types/api/purchase/purchasing'; } from '@/types/api/purchase/purchase';
import { isResponseError } from '@/lib/api-helper'; import { isResponseError } from '@/lib/api-helper';
export const usePurchaseRequestFormHandlers = (initialValuesId?: number) => { export const usePurchaseRequestFormHandlers = (initialValuesId?: number) => {
@@ -30,7 +30,10 @@ export const usePurchaseRequestFormHandlers = (initialValuesId?: number) => {
); );
const updatePurchaseRequestHandler = useCallback( const updatePurchaseRequestHandler = useCallback(
async (purchaseRequestId: number, payload: UpdatePurchaseRequestPayload) => { async (
purchaseRequestId: number,
payload: UpdatePurchaseRequestPayload
) => {
const res = await PurchaseApi.update(purchaseRequestId, payload); const res = await PurchaseApi.update(purchaseRequestId, payload);
if (res?.status === 'error') { if (res?.status === 'error') {
setPurchaseRequestFormErrorMessage(res.message); setPurchaseRequestFormErrorMessage(res.message);
@@ -67,4 +70,4 @@ export const usePurchaseRequestFormHandlers = (initialValuesId?: number) => {
deletePurchaseRequestClickHandler, deletePurchaseRequestClickHandler,
confirmationModalDeleteClickHandler, confirmationModalDeleteClickHandler,
}; };
}; };
+5 -5
View File
@@ -1,12 +1,12 @@
import { BaseApiService } from './base'; import { BaseApiService } from './base';
import { import {
CreatePurchasePayload, CreatePurchaseRequestPayload,
Purchase, Purchase,
UpdatePurchasePayload, UpdatePurchaseRequestPayload,
} from '@/types/api/purchase/purchasing'; } from '@/types/api/purchase/purchase';
export const PurchaseApi = new BaseApiService< export const PurchaseApi = new BaseApiService<
Purchase, Purchase,
CreatePurchasePayload, CreatePurchaseRequestPayload,
UpdatePurchasePayload UpdatePurchaseRequestPayload
>('/purchase-requests'); >('/purchase-requests');