feat(FE): Add credit_term to purchase forms and types

This commit is contained in:
rstubryan
2025-12-10 23:54:59 +07:00
parent 0d7dd0a110
commit 4ec455b3b7
7 changed files with 99 additions and 11 deletions
+1 -1
View File
@@ -160,6 +160,6 @@ deploy:dev:
# variables:
# S3_BUCKET: "lti-erp.mbugroup.id"
# CLOUDFRONT_DISTRIBUTION_ID: "ddfd"
# environment:
# environment:
# name: production
@@ -314,7 +314,9 @@ const PurchaseOrderStaffApprovalForm = ({
const isNewItemForm =
!formItem.purchase_item_id || formItem.purchase_item_id === 0;
let cleanPayload: UpdateStaffApprovalRequestPayload['items'][0];
let cleanPayload: NonNullable<
UpdateStaffApprovalRequestPayload['items']
>[0];
if (isNewItemForm) {
cleanPayload = {
@@ -362,7 +364,9 @@ const PurchaseOrderStaffApprovalForm = ({
const isNewItemForm =
!formItem.purchase_item_id || formItem.purchase_item_id === 0;
let cleanPayload: UpdateStaffApprovalRequestPayload['items'][0];
let cleanPayload: NonNullable<
UpdateStaffApprovalRequestPayload['items']
>[0];
if (isNewItemForm) {
cleanPayload = {
@@ -7,6 +7,7 @@ type PurchaseRequestFormSchemaType = {
label: string;
} | null;
supplier_id: number;
credit_term: number;
area?: {
value: number;
label: string;
@@ -81,6 +82,10 @@ export const PurchaseRequestFormSchema: Yup.ObjectSchema<PurchaseRequestFormSche
.required('Supplier wajib dipilih!')
.min(1, 'Supplier wajib dipilih!')
.typeError('Supplier wajib dipilih!'),
credit_term: Yup.number()
.required('Jangka waktu kredit wajib diisi!')
.min(0, 'Jangka waktu kredit tidak boleh kurang dari 0!')
.typeError('Jangka waktu kredit wajib diisi!'),
area: Yup.object({
value: Yup.number().min(1).required(),
label: Yup.string().required(),
@@ -119,6 +124,7 @@ export const getPurchaseRequestFormInitialValues = (
}
: null,
supplier_id: initialValues?.supplier?.id ?? 0,
credit_term: initialValues?.credit_term ?? 0,
area: initialValues?.area
? {
value: initialValues.area.id,
@@ -185,6 +185,10 @@ const PurchaseRequestForm = ({
typeof values.supplier_id === 'string'
? parseInt(values.supplier_id) || 0
: values.supplier_id || 0,
credit_term:
typeof values.credit_term === 'string'
? parseInt(values.credit_term) || 0
: values.credit_term || 0,
notes: values.notes || '',
items: (values.items || []).map((item) => ({
warehouse_id: Number(item.warehouse_id) || 0,
@@ -338,6 +342,27 @@ const PurchaseRequestForm = ({
};
// ===== UTILITY FUNCTIONS =====
const updateCreditTermBasedOnSupplier = useCallback(
(supplierId: number) => {
if (supplierId > 0 && isResponseSuccess(supplierRawData)) {
const supplierData = supplierRawData.data.find(
(s: Supplier) => s.id === supplierId
);
if (supplierData?.due_date) {
formik.setFieldTouched('credit_term', false);
formik.setFieldValue('credit_term', supplierData.due_date.toString());
} else {
formik.setFieldTouched('credit_term', false);
formik.setFieldValue('credit_term', '');
}
} else {
formik.setFieldTouched('credit_term', false);
formik.setFieldValue('credit_term', '');
}
},
[supplierRawData]
);
const resetPurchaseItems = useCallback(() => {
if (formik.values.items) {
formik.values.items.forEach((_, idx) => {
@@ -352,6 +377,16 @@ const PurchaseRequestForm = ({
}, []);
// ===== SIDE EFFECTS =====
useEffect(() => {
if (formik.values.supplier_id && Number(formik.values.supplier_id) > 0) {
updateCreditTermBasedOnSupplier(Number(formik.values.supplier_id));
resetPurchaseItems();
} else {
formik.setFieldTouched('credit_term', false);
formik.setFieldValue('credit_term', '');
resetPurchaseItems();
}
}, [formik.values.supplier_id]);
// ===== FORM HANDLERS =====
const handleSupplierChange = useCallback(
@@ -367,6 +402,23 @@ const PurchaseRequestForm = ({
[]
);
const handleCreditTermChange = useCallback(
(e: React.ChangeEvent<HTMLInputElement>) => {
const value = e.target.value;
formik.setFieldTouched('credit_term', true);
formik.setFieldValue('credit_term', value);
},
[]
);
const handleCreditTermBlur = useCallback(
(e: React.FocusEvent<HTMLInputElement>) => {
formik.handleBlur(e);
},
[formik]
);
const handleAreaChange = useCallback(
(val: OptionType | OptionType[] | null) => {
const area = val as OptionType | null;
@@ -447,7 +499,7 @@ const PurchaseRequestForm = ({
body: 'flex flex-col gap-6',
}}
>
<div className={'grid grid-cols-1 md:grid-cols-3 gap-6'}>
<div className={'grid grid-cols-1 md:grid-cols-2 gap-6'}>
<SelectInput
required
label='Vendor'
@@ -466,6 +518,29 @@ const PurchaseRequestForm = ({
isClearable
/>
<NumberInput
required={!!formik.values.supplier_id}
label='Jatuh tempo (hari)'
name='credit_term'
value={formik.values.credit_term || ''}
onChange={handleCreditTermChange}
onBlur={handleCreditTermBlur}
isError={
formik.touched.credit_term &&
Boolean(formik.errors.credit_term)
}
errorMessage={formik.errors.credit_term as string}
readOnly={type === 'detail' || !formik.values.supplier_id}
disabled={type === 'detail' || !formik.values.supplier_id}
allowNegative={false}
decimalScale={0}
placeholder={
!formik.values.supplier_id
? 'Pilih Vendor terlebih dahulu'
: 'Masukkan jumlah hari jatuh tempo'
}
/>
<SelectInput
label='Area'
placeholder='Pilih Area...'
@@ -490,7 +565,7 @@ const PurchaseRequestForm = ({
isClearable={type !== 'detail'}
/>
<div className={'md:col-span-3'}>
<div className={'col-span-2'}>
<TextInput
label='Notes'
name='notes'
@@ -1052,7 +1052,6 @@ const PurchaseOrderDetail = ({
const payload: CreateStaffApprovalRequestPayload = {
action: 'REJECTED',
notes: notes || null,
items: [],
};
await createStaffApprovalHandler(payload);
@@ -1080,7 +1079,6 @@ const PurchaseOrderDetail = ({
const payload: CreateAcceptApprovalRequestPayload = {
action: 'REJECTED',
notes: notes || null,
items: [],
};
await createAcceptApprovalHandler(payload);
@@ -309,6 +309,9 @@ const PurchaseOrderInvoice = ({ data }: PurchaseOrderInvoiceProps) => {
{purchaseData?.supplier?.alias || ''})
</Text>
<Text>{purchaseData?.supplier?.category || '-'}</Text>
<Text>
Credit Term: {purchaseData?.credit_term || 0} hari
</Text>
<Text>
Due Date:{' '}
{purchaseData?.due_date
+6 -4
View File
@@ -51,6 +51,7 @@ export type BasePurchase = {
po_document_path?: string | null;
po_date: string;
supplier: Supplier;
credit_term?: number;
due_date: string;
notes?: string | null;
deleted_at?: string | null;
@@ -66,8 +67,9 @@ export type Purchase = BaseMetadata & BasePurchase;
export type CreatePurchaseRequestPayload = {
supplier_id: number;
credit_term: number;
notes?: string | null;
items: {
items?: {
warehouse_id: number;
product_id: number;
qty: number;
@@ -77,7 +79,7 @@ export type CreatePurchaseRequestPayload = {
export type CreateStaffApprovalRequestPayload = {
action: 'APPROVED' | 'REJECTED';
notes?: string | null;
items: {
items?: {
purchase_item_id: number;
qty: number;
price: number;
@@ -88,7 +90,7 @@ export type CreateStaffApprovalRequestPayload = {
export type UpdateStaffApprovalRequestPayload = {
action: 'APPROVED' | 'REJECTED';
notes?: string | null;
items: Array<{
items?: Array<{
purchase_item_id?: number;
product_id?: number;
warehouse_id?: number;
@@ -106,7 +108,7 @@ export type CreateManagerApprovalRequestPayload = {
export type CreateAcceptApprovalRequestPayload = {
action: 'APPROVED' | 'REJECTED';
notes?: string | null;
items: {
items?: {
purchase_item_id: number;
received_date: string;
travel_number: string;