mirror of
https://gitlab.com/mbugroup/lti-web-client.git
synced 2026-05-20 13:32:00 +00:00
Merge branch 'dev/restu' into 'development'
[HOTFIX/FE][US#281-391] Adjustment Uniformity, Purchase and Expense See merge request mbugroup/lti-web-client!138
This commit is contained in:
@@ -33,6 +33,7 @@ const FileInput = ({
|
|||||||
isError,
|
isError,
|
||||||
errorMessage,
|
errorMessage,
|
||||||
disabled = false,
|
disabled = false,
|
||||||
|
required = false,
|
||||||
onChange,
|
onChange,
|
||||||
onBlur,
|
onBlur,
|
||||||
readOnly = false,
|
readOnly = false,
|
||||||
@@ -56,6 +57,13 @@ const FileInput = ({
|
|||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
{label}
|
{label}
|
||||||
|
{required && (
|
||||||
|
<>
|
||||||
|
<span className='tooltip tooltip-error' data-tip='required'>
|
||||||
|
<span className='text-error'> *</span>
|
||||||
|
</span>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
</label>
|
</label>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
|||||||
@@ -140,17 +140,17 @@ const ExpenseRequestContent = ({
|
|||||||
const confirmationModalDeleteClickHandler = async () => {
|
const confirmationModalDeleteClickHandler = async () => {
|
||||||
setIsDeleteLoading(true);
|
setIsDeleteLoading(true);
|
||||||
|
|
||||||
try {
|
const deleteResponse = await ExpenseApi.delete(initialValues?.id as number);
|
||||||
await ExpenseApi.delete(initialValues?.id as number);
|
|
||||||
|
|
||||||
|
if (isResponseSuccess(deleteResponse)) {
|
||||||
toast.success('Berhasil menghapus data biaya operasional!');
|
toast.success('Berhasil menghapus data biaya operasional!');
|
||||||
router.push('/expense');
|
router.push('/expense');
|
||||||
} catch (error) {
|
} else {
|
||||||
toast.error('Gagal menghapus data biaya operasional!');
|
toast.error('Gagal menghapus data biaya operasional!');
|
||||||
} finally {
|
|
||||||
deleteModal.closeModal();
|
|
||||||
setIsDeleteLoading(false);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
deleteModal.closeModal();
|
||||||
|
setIsDeleteLoading(false);
|
||||||
};
|
};
|
||||||
|
|
||||||
const confirmationModalCompleteClickHandler = async () => {
|
const confirmationModalCompleteClickHandler = async () => {
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ const ExpenseStatusBadge = ({ approval }: ExpenseStatusBadgeProps) => {
|
|||||||
|
|
||||||
switch (latestApprovalStepNumber) {
|
switch (latestApprovalStepNumber) {
|
||||||
case 1:
|
case 1:
|
||||||
expenseStatusPillBadgeColor = 'yellow';
|
expenseStatusPillBadgeColor = 'gray';
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 2:
|
case 2:
|
||||||
@@ -33,7 +33,7 @@ const ExpenseStatusBadge = ({ approval }: ExpenseStatusBadgeProps) => {
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case 4:
|
case 4:
|
||||||
expenseStatusPillBadgeColor = 'red';
|
expenseStatusPillBadgeColor = 'yellow';
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 5:
|
case 5:
|
||||||
|
|||||||
@@ -420,11 +420,19 @@ const ExpensesTable = () => {
|
|||||||
const confirmationModalDeleteClickHandler = async () => {
|
const confirmationModalDeleteClickHandler = async () => {
|
||||||
setIsDeleteLoading(true);
|
setIsDeleteLoading(true);
|
||||||
|
|
||||||
await ExpenseApi.delete(selectedExpense?.id as number);
|
const deleteResponse = await ExpenseApi.delete(
|
||||||
refreshExpenses();
|
selectedExpense?.id as number
|
||||||
|
);
|
||||||
|
|
||||||
|
if (isResponseSuccess(deleteResponse)) {
|
||||||
|
refreshExpenses();
|
||||||
|
deleteModal.closeModal();
|
||||||
|
toast.success('Berhasil menghapus biaya operasional!');
|
||||||
|
} else {
|
||||||
|
deleteModal.closeModal();
|
||||||
|
toast.error('Gagal menghapus biaya operasional!');
|
||||||
|
}
|
||||||
|
|
||||||
deleteModal.closeModal();
|
|
||||||
toast.success('Berhasil menghapus biaya operasional!');
|
|
||||||
setIsDeleteLoading(false);
|
setIsDeleteLoading(false);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -1562,7 +1562,9 @@ const MovementForm = ({ type = 'add', initialValues }: MovementFormProps) => {
|
|||||||
width={20}
|
width={20}
|
||||||
height={20}
|
height={20}
|
||||||
/>
|
/>
|
||||||
{delivery.document.name}
|
<span className='truncate max-w-[200px]'>
|
||||||
|
{delivery.document.name}
|
||||||
|
</span>
|
||||||
</Button>
|
</Button>
|
||||||
) : (
|
) : (
|
||||||
<Button
|
<Button
|
||||||
@@ -1582,6 +1584,7 @@ const MovementForm = ({ type = 'add', initialValues }: MovementFormProps) => {
|
|||||||
</>
|
</>
|
||||||
) : (
|
) : (
|
||||||
<FileInput
|
<FileInput
|
||||||
|
accept='.pdf,.jpg,.jpeg,.png'
|
||||||
name={`deliveries.${idx}.document`}
|
name={`deliveries.${idx}.document`}
|
||||||
onChange={(e) => {
|
onChange={(e) => {
|
||||||
const file = e.target.files?.[0];
|
const file = e.target.files?.[0];
|
||||||
|
|||||||
@@ -51,8 +51,10 @@ import MenuItem from '@/components/menu/MenuItem';
|
|||||||
|
|
||||||
const UniformityConfirmationPreview = ({
|
const UniformityConfirmationPreview = ({
|
||||||
uniformity,
|
uniformity,
|
||||||
|
uniformityDetail,
|
||||||
}: {
|
}: {
|
||||||
uniformity?: Uniformity;
|
uniformity?: Uniformity;
|
||||||
|
uniformityDetail?: UniformityDetail;
|
||||||
}) => {
|
}) => {
|
||||||
const data: DetailOptionType[] = [
|
const data: DetailOptionType[] = [
|
||||||
{
|
{
|
||||||
@@ -60,32 +62,42 @@ const UniformityConfirmationPreview = ({
|
|||||||
label: 'Tanggal',
|
label: 'Tanggal',
|
||||||
value: uniformity
|
value: uniformity
|
||||||
? formatDate(uniformity.applied_at, 'DD MMM YYYY')
|
? formatDate(uniformity.applied_at, 'DD MMM YYYY')
|
||||||
: '-',
|
: uniformityDetail
|
||||||
|
? formatDate(uniformityDetail.info_umum.tanggal, 'DD MMM YYYY')
|
||||||
|
: '-',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 'lokasi-farm',
|
id: 'lokasi-farm',
|
||||||
label: 'Lokasi Farm',
|
label: 'Lokasi Farm',
|
||||||
value: uniformity?.location_name || '-',
|
value:
|
||||||
|
uniformity?.location_name ||
|
||||||
|
uniformityDetail?.info_umum?.lokasi_farm ||
|
||||||
|
'-',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 'project-flock',
|
id: 'project-flock',
|
||||||
label: 'Project Flock',
|
label: 'Project Flock',
|
||||||
value: uniformity?.flock_name || '-',
|
value:
|
||||||
|
uniformity?.flock_name ||
|
||||||
|
uniformityDetail?.info_umum?.project_flock ||
|
||||||
|
'-',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 'kandang',
|
id: 'kandang',
|
||||||
label: 'Kandang',
|
label: 'Kandang',
|
||||||
value: uniformity?.kandang_name || '-',
|
value:
|
||||||
|
uniformity?.kandang_name || uniformityDetail?.info_umum?.kandang || '-',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 'file-uniformity',
|
id: 'file-uniformity',
|
||||||
label: 'File Uniformity',
|
label: 'File Uniformity',
|
||||||
value: '-',
|
value:
|
||||||
|
uniformity?.file_name || uniformityDetail?.info_umum?.file_name || '-',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 'status',
|
id: 'status',
|
||||||
label: 'Status',
|
label: 'Status',
|
||||||
value: uniformity?.status || '-',
|
value: uniformity?.status || (uniformityDetail ? 'CREATED' : '-'),
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
@@ -448,9 +460,15 @@ const UniformityTable = () => {
|
|||||||
const canApproveReject = useMemo(() => {
|
const canApproveReject = useMemo(() => {
|
||||||
return (
|
return (
|
||||||
selectedUniformities.length > 0 &&
|
selectedUniformities.length > 0 &&
|
||||||
selectedUniformities.every(
|
selectedUniformities.every((u) => {
|
||||||
(u) => u.status === 'CREATED' || u.status === 'Pengajuan'
|
const approvalAction = u.latest_approval?.action;
|
||||||
)
|
return (
|
||||||
|
approvalAction === 'CREATED' ||
|
||||||
|
approvalAction === 'Pengajuan' ||
|
||||||
|
(!approvalAction &&
|
||||||
|
(u.status === 'CREATED' || u.status === 'Pengajuan'))
|
||||||
|
);
|
||||||
|
})
|
||||||
);
|
);
|
||||||
}, [selectedUniformities]);
|
}, [selectedUniformities]);
|
||||||
|
|
||||||
@@ -805,7 +823,9 @@ const UniformityTable = () => {
|
|||||||
accessorKey: 'status',
|
accessorKey: 'status',
|
||||||
header: 'Status',
|
header: 'Status',
|
||||||
cell: (props) => {
|
cell: (props) => {
|
||||||
const status = props.row.original.status;
|
const uniformity = props.row.original;
|
||||||
|
const status =
|
||||||
|
uniformity.latest_approval?.action ?? uniformity.status;
|
||||||
return (
|
return (
|
||||||
<div className='w-full'>
|
<div className='w-full'>
|
||||||
<Badge
|
<Badge
|
||||||
@@ -938,34 +958,7 @@ const UniformityTable = () => {
|
|||||||
<div className='flex flex-col gap-4 mt-4'>
|
<div className='flex flex-col gap-4 mt-4'>
|
||||||
{createdUniformity ? (
|
{createdUniformity ? (
|
||||||
<UniformityConfirmationPreview
|
<UniformityConfirmationPreview
|
||||||
uniformity={{
|
uniformityDetail={createdUniformity}
|
||||||
id: createdUniformity.id,
|
|
||||||
location_name: createdUniformity.info_umum.lokasi_farm,
|
|
||||||
flock_name: createdUniformity.info_umum.project_flock,
|
|
||||||
kandang_name: createdUniformity.info_umum.kandang,
|
|
||||||
applied_at: createdUniformity.info_umum.tanggal,
|
|
||||||
week: 0,
|
|
||||||
status: 'Pengajuan',
|
|
||||||
uniformity: createdUniformity.result.uniformity,
|
|
||||||
cv: createdUniformity.result.cv,
|
|
||||||
chick_qty_of_weight:
|
|
||||||
createdUniformity.sampling.chick_qty_of_weight,
|
|
||||||
uniform_qty: createdUniformity.result.uniform_qty,
|
|
||||||
mean_up: createdUniformity.sampling.mean_up,
|
|
||||||
mean_down: createdUniformity.sampling.mean_down,
|
|
||||||
standard_mean_weight: null,
|
|
||||||
standard_uniformity: null,
|
|
||||||
created_at: '',
|
|
||||||
created_by: 0,
|
|
||||||
project_flock_kandang_id: 0,
|
|
||||||
created_user: {
|
|
||||||
id: 0,
|
|
||||||
id_user: 0,
|
|
||||||
email: '',
|
|
||||||
name: '',
|
|
||||||
},
|
|
||||||
updated_at: '',
|
|
||||||
}}
|
|
||||||
/>
|
/>
|
||||||
) : selectedRowIds.length === 1 ? (
|
) : selectedRowIds.length === 1 ? (
|
||||||
<UniformityConfirmationPreview
|
<UniformityConfirmationPreview
|
||||||
|
|||||||
@@ -689,6 +689,16 @@ const PurchaseOrderAcceptApprovalForm = ({
|
|||||||
accept='.pdf,.jpg,.jpeg,.png'
|
accept='.pdf,.jpg,.jpeg,.png'
|
||||||
onChange={(e) => {
|
onChange={(e) => {
|
||||||
const files = Array.from(e.target.files || []);
|
const files = Array.from(e.target.files || []);
|
||||||
|
const invalidFiles = files.filter(
|
||||||
|
(file) => file.size > 2 * 1024 * 1024
|
||||||
|
);
|
||||||
|
|
||||||
|
if (invalidFiles.length > 0) {
|
||||||
|
toast.error('Ukuran dokumen maksimal 2 MB!');
|
||||||
|
e.target.value = '';
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
formik.setFieldValue('travel_documents', files);
|
formik.setFieldValue('travel_documents', files);
|
||||||
}}
|
}}
|
||||||
onBlur={formik.handleBlur}
|
onBlur={formik.handleBlur}
|
||||||
|
|||||||
@@ -312,7 +312,8 @@ export const PurchaseRequestStaffApprovalFormInitialValues: PurchaseRequestStaff
|
|||||||
};
|
};
|
||||||
|
|
||||||
export const PurchaseRequestStaffApprovalFormDefaultValues = (
|
export const PurchaseRequestStaffApprovalFormDefaultValues = (
|
||||||
purchase?: Purchase
|
purchase?: Purchase,
|
||||||
|
type?: 'add' | 'edit'
|
||||||
): PurchaseRequestStaffApprovalFormSchemaType => {
|
): PurchaseRequestStaffApprovalFormSchemaType => {
|
||||||
return {
|
return {
|
||||||
action: 'APPROVED',
|
action: 'APPROVED',
|
||||||
@@ -331,8 +332,18 @@ export const PurchaseRequestStaffApprovalFormDefaultValues = (
|
|||||||
label: item.warehouse?.name || '',
|
label: item.warehouse?.name || '',
|
||||||
},
|
},
|
||||||
qty: item.sub_qty || item.qty || 0,
|
qty: item.sub_qty || item.qty || 0,
|
||||||
price: item.price,
|
price:
|
||||||
total_price: item.total_price,
|
type === 'add'
|
||||||
|
? 'ProductPrice' in item.product
|
||||||
|
? item.product.ProductPrice || item.price || ''
|
||||||
|
: item.price
|
||||||
|
: item.price,
|
||||||
|
total_price:
|
||||||
|
type === 'add'
|
||||||
|
? ('ProductPrice' in item.product
|
||||||
|
? item.product.ProductPrice || item.price || 0
|
||||||
|
: item.price) * (item.sub_qty || item.qty || 0)
|
||||||
|
: item.total_price,
|
||||||
}))
|
}))
|
||||||
: [
|
: [
|
||||||
{
|
{
|
||||||
@@ -381,7 +392,15 @@ export const PurchaseRequestAcceptApprovalFormSchema: Yup.ObjectSchema<PurchaseR
|
|||||||
.required('Item pembelian wajib diisi!')
|
.required('Item pembelian wajib diisi!')
|
||||||
.typeError('Item pembelian wajib diisi!'),
|
.typeError('Item pembelian wajib diisi!'),
|
||||||
travel_documents: Yup.array()
|
travel_documents: Yup.array()
|
||||||
.of(Yup.mixed<File>().required())
|
.of(
|
||||||
|
Yup.mixed<File>()
|
||||||
|
.required('Dokumen surat jalan wajib diupload!')
|
||||||
|
.test('fileSize', 'Ukuran dokumen maksimal 2 MB', (value) => {
|
||||||
|
if (!value) return true;
|
||||||
|
if (value instanceof File) return value.size <= 2 * 1024 * 1024;
|
||||||
|
return true;
|
||||||
|
})
|
||||||
|
)
|
||||||
.required('Dokumen surat jalan wajib diupload!')
|
.required('Dokumen surat jalan wajib diupload!')
|
||||||
.min(1, 'Minimal upload 1 dokumen surat jalan!')
|
.min(1, 'Minimal upload 1 dokumen surat jalan!')
|
||||||
.typeError('Dokumen surat jalan wajib diupload!'),
|
.typeError('Dokumen surat jalan wajib diupload!'),
|
||||||
|
|||||||
@@ -294,9 +294,9 @@ const PurchaseOrderStaffApprovalForm = ({
|
|||||||
// ===== FORM CONFIGURATION =====
|
// ===== FORM CONFIGURATION =====
|
||||||
const formikInitialValues = useMemo(() => {
|
const formikInitialValues = useMemo(() => {
|
||||||
return initialValues
|
return initialValues
|
||||||
? PurchaseRequestStaffApprovalFormDefaultValues(initialValues)
|
? PurchaseRequestStaffApprovalFormDefaultValues(initialValues, type)
|
||||||
: PurchaseRequestStaffApprovalFormInitialValues;
|
: PurchaseRequestStaffApprovalFormInitialValues;
|
||||||
}, [initialValues]);
|
}, [initialValues, type]);
|
||||||
|
|
||||||
const formik = useFormik({
|
const formik = useFormik({
|
||||||
initialValues: formikInitialValues,
|
initialValues: formikInitialValues,
|
||||||
@@ -485,9 +485,18 @@ const PurchaseOrderStaffApprovalForm = ({
|
|||||||
},
|
},
|
||||||
warehouse_id: purchaseItem.warehouse_id || 0,
|
warehouse_id: purchaseItem.warehouse_id || 0,
|
||||||
qty: originalItem?.qty || purchaseItem.quantity || 0,
|
qty: originalItem?.qty || purchaseItem.quantity || 0,
|
||||||
price: type === 'edit' && originalItem ? originalItem.price : '',
|
price:
|
||||||
|
type === 'edit' && originalItem
|
||||||
|
? originalItem.price
|
||||||
|
: originalItem?.product && 'ProductPrice' in originalItem.product
|
||||||
|
? originalItem.product.ProductPrice || ''
|
||||||
|
: '',
|
||||||
total_price:
|
total_price:
|
||||||
type === 'edit' && originalItem ? originalItem.total_price : '',
|
type === 'edit' && originalItem
|
||||||
|
? originalItem.total_price
|
||||||
|
: (originalItem?.product && 'ProductPrice' in originalItem.product
|
||||||
|
? originalItem.product.ProductPrice || 0
|
||||||
|
: 0) * (originalItem?.qty || purchaseItem.quantity || 0),
|
||||||
};
|
};
|
||||||
return itemData;
|
return itemData;
|
||||||
});
|
});
|
||||||
@@ -1140,6 +1149,7 @@ const PurchaseOrderStaffApprovalForm = ({
|
|||||||
color='warning'
|
color='warning'
|
||||||
className='px-4'
|
className='px-4'
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
|
formik.setValues(formikInitialValues);
|
||||||
formik.resetForm();
|
formik.resetForm();
|
||||||
setPurchaseOrderFormErrorMessage('');
|
setPurchaseOrderFormErrorMessage('');
|
||||||
onCancel?.();
|
onCancel?.();
|
||||||
|
|||||||
Vendored
+2
@@ -10,6 +10,8 @@ export type BaseInventoryProduct = {
|
|||||||
name: string;
|
name: string;
|
||||||
brand: string;
|
brand: string;
|
||||||
sku: string;
|
sku: string;
|
||||||
|
ProductPrice: number;
|
||||||
|
SellingPrice?: number;
|
||||||
product_price: number;
|
product_price: number;
|
||||||
selling_price?: number;
|
selling_price?: number;
|
||||||
tax?: number;
|
tax?: number;
|
||||||
|
|||||||
+1
-3
@@ -1,7 +1,4 @@
|
|||||||
import { BaseMetadata } from '@/types/api/api-general';
|
import { BaseMetadata } from '@/types/api/api-general';
|
||||||
import { Location } from '@/types/api/location/location';
|
|
||||||
import { ProjectFlock } from '@/types/api/project-flock/project-flock';
|
|
||||||
import { Kandang } from '@/types/api/kandang/kandang';
|
|
||||||
import { BaseApproval } from '@/types/api/approval/approval';
|
import { BaseApproval } from '@/types/api/approval/approval';
|
||||||
|
|
||||||
// ==================== GET ALL RESPONSE ====================
|
// ==================== GET ALL RESPONSE ====================
|
||||||
@@ -11,6 +8,7 @@ export type Uniformity = BaseMetadata & {
|
|||||||
location_name: string;
|
location_name: string;
|
||||||
flock_name: string;
|
flock_name: string;
|
||||||
kandang_name: string;
|
kandang_name: string;
|
||||||
|
file_name: string;
|
||||||
applied_at: string;
|
applied_at: string;
|
||||||
week: number;
|
week: number;
|
||||||
status: string;
|
status: string;
|
||||||
|
|||||||
Vendored
+2
@@ -10,6 +10,8 @@ export type PurchaseItemProduct = {
|
|||||||
id: number;
|
id: number;
|
||||||
name: string;
|
name: string;
|
||||||
flags?: string[];
|
flags?: string[];
|
||||||
|
ProductPrice?: number;
|
||||||
|
SellingPrice?: number;
|
||||||
uom?: {
|
uom?: {
|
||||||
name: string;
|
name: string;
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user