Compare commits

..

3 Commits

Author SHA1 Message Date
ValdiANS 7b4bd7605b fix: remove transition restriction for recording 2026-06-02 09:45:19 +07:00
Rivaldi A N S 9bd646294b Merge branch 'fix/laying-transition-logic-removal' into 'development'
[FIX/FE] Laying Transition Restrict Logic Removal

See merge request mbugroup/lti-web-client!499
2026-05-30 02:19:24 +00:00
ValdiANS 366260608f fix: remove transition restrict logic 2026-05-30 09:13:56 +07:00
6 changed files with 94 additions and 253 deletions
@@ -1,6 +1,6 @@
'use client';
import { RefObject, useCallback, useMemo, useState } from 'react';
import { RefObject, useCallback, useMemo } from 'react';
import { useFormik } from 'formik';
import { Icon } from '@iconify/react';
import Modal from '@/components/Modal';
@@ -9,8 +9,6 @@ import SelectInput, {
OptionType,
useSelect,
} from '@/components/input/SelectInput';
import DateInput from '@/components/input/DateInput';
import SelectInputRadio from '@/components/input/SelectInputRadio';
import { MARKETING_APPROVAL_LINE } from '@/config/approval-line';
import {
MarketingFilterFormValues,
@@ -19,17 +17,12 @@ import {
import { MarketingFilter } from '@/types/api/marketing/marketing';
import SelectInputCheckbox from '@/components/input/SelectInputCheckbox';
import { MarketingApi } from '@/services/api/marketing/marketing';
import {
CustomerApi,
ProductApi,
WarehouseApi,
} from '@/services/api/master-data';
import { CustomerApi, ProductApi } from '@/services/api/master-data';
import { isResponseSuccess } from '@/lib/api-helper';
import { BaseMarketing, BaseSalesOrder } from '@/types/api/marketing/marketing';
import { ProjectFlockApi } from '@/services/api/production';
import { ProjectFlock } from '@/types/api/production/project-flock';
import { Product } from '@/types/api/master-data/product';
import { Warehouse } from '@/types/api/master-data/warehouse';
interface MarketingFilterModal {
ref: RefObject<HTMLDialogElement | null>;
@@ -41,10 +34,6 @@ interface MarketingFilterModal {
customer: OptionType<number> | null;
project_flock: OptionType<number> | null;
project_flock_kandang: OptionType<number> | null;
warehouse: OptionType<number> | null;
start_date: string;
end_date: string;
filter_by: OptionType<string> | null;
};
}
@@ -90,13 +79,6 @@ const MarketingFilterModal = ({
'search'
);
const {
options: warehouseOptions,
isLoadingOptions: isLoadingWarehouseOptions,
setInputValue: setWarehouseInputValue,
loadMore: loadMoreWarehouses,
} = useSelect<Warehouse>(WarehouseApi.basePath, 'id', 'name', 'search');
const statusOptions = [
...MARKETING_APPROVAL_LINE.map((item) => ({
value: item.step_name.split(' ').join('_').toUpperCase(),
@@ -105,13 +87,6 @@ const MarketingFilterModal = ({
{ value: 'DITOLAK', label: 'Ditolak' },
];
const filterByOptions = [
{ value: 'so_date', label: 'Tanggal SO' },
{ value: 'created_at', label: 'Tanggal Dibuat' },
];
const [hasDateError, setHasDateError] = useState(false);
const formik = useFormik<MarketingFilterFormValues>({
initialValues: initialValues || {
product_ids: [],
@@ -119,10 +94,6 @@ const MarketingFilterModal = ({
customer: null,
project_flock: null,
project_flock_kandang: null,
warehouse: null,
start_date: '',
end_date: '',
filter_by: null,
},
validationSchema: MarketingFilterSchema,
@@ -140,12 +111,6 @@ const MarketingFilterModal = ({
Number(values.project_flock_kandang?.value) || undefined,
project_flock_kandang_name:
values.project_flock_kandang?.label || undefined,
warehouse_id: Number(values.warehouse?.value) || undefined,
warehouse_name: values.warehouse?.label || undefined,
start_date: values.start_date || undefined,
end_date: values.end_date || undefined,
filter_by: values.filter_by?.value || undefined,
filter_by_name: values.filter_by?.label || undefined,
};
onSubmit?.(formattedValues);
@@ -168,37 +133,12 @@ const MarketingFilterModal = ({
customer: null,
project_flock: null,
project_flock_kandang: null,
warehouse: null,
start_date: '',
end_date: '',
filter_by: null,
},
});
setHasDateError(false);
onReset?.();
closeModalHandler();
}, [resetForm, onReset, closeModalHandler]);
const handleStartDateChange = (e: React.ChangeEvent<HTMLInputElement>) => {
const value = e.target.value;
formik.setFieldValue('start_date', value);
if (value && formik.values.end_date) {
setHasDateError(new Date(formik.values.end_date) < new Date(value));
} else {
setHasDateError(false);
}
};
const handleEndDateChange = (e: React.ChangeEvent<HTMLInputElement>) => {
const value = e.target.value;
formik.setFieldValue('end_date', value);
if (value && formik.values.start_date) {
setHasDateError(new Date(value) < new Date(formik.values.start_date));
} else {
setHasDateError(false);
}
};
const productChangeHandler = (val: OptionType | OptionType[] | null) => {
formik.setFieldValue('product_ids', val as OptionType[]);
};
@@ -267,44 +207,6 @@ const MarketingFilterModal = ({
{/* Modal Body */}
<div className='p-4 flex flex-col gap-1.5'>
<div>
<label className='block text-xs font-semibold text-base-content py-2'>
Tanggal
</label>
<div className='flex flex-row gap-1.5 items-center justify-between'>
<DateInput
name='start_date'
value={formik.values.start_date || ''}
onChange={handleStartDateChange}
className={{ wrapper: 'w-full' }}
isNestedModal
/>
<hr className='w-full max-w-3 h-px border-base-content/10' />
<DateInput
name='end_date'
value={formik.values.end_date || ''}
onChange={handleEndDateChange}
className={{ wrapper: 'w-full' }}
isNestedModal
isError={hasDateError}
/>
</div>
</div>
<SelectInputRadio
label='Filter Berdasarkan'
placeholder='Pilih Filter Berdasarkan'
options={filterByOptions}
value={formik.values.filter_by ?? null}
onChange={(val) =>
formik.setFieldValue(
'filter_by',
!Array.isArray(val) ? (val ?? null) : null
)
}
isClearable
/>
{/* select multiple product */}
<SelectInputCheckbox
label='Product'
@@ -370,22 +272,6 @@ const MarketingFilterModal = ({
}
isDisabled={!formik.values.project_flock}
/>
<SelectInput
label='Gudang'
isClearable
placeholder='Pilih Gudang'
options={warehouseOptions}
isLoading={isLoadingWarehouseOptions}
value={formik.values.warehouse}
onChange={(val) =>
formik.setFieldValue(
'warehouse',
!Array.isArray(val) ? (val as OptionType<number> | null) : null
)
}
onInputChange={setWarehouseInputValue}
onMenuScrollToBottom={loadMoreWarehouses}
/>
</div>
{/* Modal Footer */}
@@ -402,7 +288,6 @@ const MarketingFilterModal = ({
<Button
type='submit'
className='p-3 rounded-lg w-fit sm:w-full max-w-40 text-base-100 text-sm'
disabled={hasDateError}
>
Apply Filter
</Button>
@@ -203,12 +203,6 @@ const MarketingTable = () => {
project_flock_name: '',
project_flock_kandang_id: '',
project_flock_kandang_name: '',
warehouse_id: '',
warehouse_name: '',
start_date: '',
end_date: '',
filter_by: '',
filter_by_name: '',
sort_by: '',
order_by: '',
},
@@ -220,10 +214,6 @@ const MarketingTable = () => {
customer_id: 'customer_id',
project_flock_id: 'project_flock_id',
project_flock_kandang_id: 'project_flock_kandang_id',
warehouse_id: 'warehouse_id',
start_date: 'start_date',
end_date: 'end_date',
filter_by: 'filter_by',
sort_by: 'sort_by',
order_by: 'sort_order',
},
@@ -233,8 +223,6 @@ const MarketingTable = () => {
'customer_name',
'project_flock_name',
'project_flock_kandang_name',
'warehouse_name',
'filter_by_name',
],
persist: true,
@@ -305,16 +293,6 @@ const MarketingTable = () => {
values.project_flock_kandang_name ?? '',
true
);
updateFilter(
'warehouse_id',
values.warehouse_id ? values.warehouse_id.toString() : '',
true
);
updateFilter('warehouse_name', values.warehouse_name ?? '', true);
updateFilter('start_date', values.start_date ?? '', true);
updateFilter('end_date', values.end_date ?? '', true);
updateFilter('filter_by', values.filter_by ?? '', true);
updateFilter('filter_by_name', values.filter_by_name ?? '', true);
};
const [isLoadingExportingToExcel, setIsLoadingExportingToExcel] =
@@ -333,12 +311,6 @@ const MarketingTable = () => {
updateFilter('project_flock_name', '', true);
updateFilter('project_flock_kandang_id', '', true);
updateFilter('project_flock_kandang_name', '', true);
updateFilter('warehouse_id', '', true);
updateFilter('warehouse_name', '', true);
updateFilter('start_date', '', true);
updateFilter('end_date', '', true);
updateFilter('filter_by', '', true);
updateFilter('filter_by_name', '', true);
};
const approveClickHandler = () => {
@@ -461,20 +433,6 @@ const MarketingTable = () => {
label: tableFilterState.project_flock_kandang_name,
}
: null,
warehouse: tableFilterState.warehouse_id
? {
value: Number(tableFilterState.warehouse_id),
label: tableFilterState.warehouse_name,
}
: null,
start_date: tableFilterState.start_date,
end_date: tableFilterState.end_date,
filter_by: tableFilterState.filter_by
? {
value: tableFilterState.filter_by,
label: tableFilterState.filter_by_name,
}
: null,
};
const approveMarketingHandler = async (notes: string) => {
@@ -749,7 +707,7 @@ const MarketingTable = () => {
},
{
accessorKey: 'so_date',
header: 'Tanggal SO',
header: 'Tanggal',
cell: (props) => {
return formatDate(props.row.original.so_date, 'DD MMM yyyy');
},
@@ -795,17 +753,18 @@ const MarketingTable = () => {
cell: (props) => props.row.original.customer.name,
},
{
accessorKey: 'grand_total_so',
header: 'Grand Total SO',
accessorKey: 'grand_total',
accessorFn: (row) =>
row.sales_order
?.map((product) => product.total_price)
.reduce((a, b) => a + b, 0) ?? 0,
header: 'Grand Total',
cell: (props) => {
return formatCurrency(props.row.original?.grand_total_so);
},
},
{
accessorKey: 'grand_total_do',
header: 'Grand Total DO',
cell: (props) => {
return formatCurrency(props.row.original?.grand_total_do);
return formatCurrency(
props.row.original?.sales_order
?.map((product) => product.total_price)
.reduce((a, b) => a + b, 0) ?? 0
);
},
},
{
@@ -952,8 +911,6 @@ const MarketingTable = () => {
'customer_name',
'project_flock_name',
'project_flock_kandang_name',
'warehouse_name',
'filter_by_name',
'sort_by',
'order_by',
]}
@@ -1,4 +1,4 @@
import { array, mixed, object, string } from 'yup';
import { array, mixed, object } from 'yup';
import { OptionType } from '@/components/input/SelectInput';
export const MarketingFilterSchema = object({
@@ -7,10 +7,6 @@ export const MarketingFilterSchema = object({
customer: mixed<OptionType<number>>().nullable(),
project_flock: mixed<OptionType<number>>().nullable(),
project_flock_kandang: mixed<OptionType<number>>().nullable(),
warehouse: mixed<OptionType<number>>().nullable(),
start_date: string().optional(),
end_date: string().optional(),
filter_by: mixed<OptionType<string>>().nullable(),
});
export type MarketingFilterFormValues = {
@@ -19,8 +15,4 @@ export type MarketingFilterFormValues = {
customer: OptionType<number> | null;
project_flock: OptionType<number> | null;
project_flock_kandang: OptionType<number> | null;
warehouse: OptionType<number> | null;
start_date: string;
end_date: string;
filter_by: OptionType<string> | null;
};
@@ -463,13 +463,16 @@ const RecordingForm = ({ type = 'add', initialValues }: RecordingFormProps) => {
}, [selectedKandang]);
// ===== TRANSITION RESTRICTION LOGIC =====
const isTransitionPeriod = useMemo(() => {
return (
initialValues?.is_transition ??
projectFlockKandangLookup?.is_transition ??
false
);
}, [initialValues, projectFlockKandangLookup]);
// const isTransitionPeriod = useMemo(() => {
// return (
// initialValues?.is_transition ??
// projectFlockKandangLookup?.is_transition ??
// false
// );
// }, [initialValues, projectFlockKandangLookup]);
// set to false by request: 30 May 2026, 09:11
const isTransitionPeriod = false;
const recordingRestriction = useMemo(() => {
let isLaying: boolean;
@@ -483,10 +486,13 @@ const RecordingForm = ({ type = 'add', initialValues }: RecordingFormProps) => {
false;
}
const isTransition =
initialValues?.is_transition ??
projectFlockKandangLookup?.is_transition ??
false;
// const isTransition =
// initialValues?.is_transition ??
// projectFlockKandangLookup?.is_transition ??
// false;
// set to false by request: 30 May 2026, 09:11
const isTransition = false;
const currentIsLaying =
type === 'edit'
@@ -11,63 +11,72 @@ export const getRecordingRestriction = (
isTransition: boolean,
currentIsLaying?: boolean
): RecordingRestriction => {
if (isTransition && !isLaying) {
const isLayingKandangInTransition = currentIsLaying === true;
// if (isTransition && !isLaying) {
// const isLayingKandangInTransition = currentIsLaying === true;
if (isLayingKandangInTransition) {
return {
canEditStock: false,
canEditDepletion: true,
canEditEgg: true,
isLocked: false,
lockReason: undefined,
};
} else {
return {
canEditStock: true,
canEditDepletion: false,
canEditEgg: false,
isLocked: false,
lockReason: undefined,
};
}
}
// if (isLayingKandangInTransition) {
// return {
// canEditStock: false,
// canEditDepletion: true,
// canEditEgg: true,
// isLocked: false,
// lockReason: undefined,
// };
// } else {
// return {
// canEditStock: true,
// canEditDepletion: false,
// canEditEgg: false,
// isLocked: false,
// lockReason: undefined,
// };
// }
// }
if (!isLaying && !isTransition && currentIsLaying) {
return {
canEditStock: false,
canEditDepletion: false,
canEditEgg: false,
isLocked: true,
lockReason:
'Recording Growing telah terkunci karena Project Flock sudah masuk fase Laying',
};
}
// if (!isLaying && !isTransition && currentIsLaying) {
// return {
// canEditStock: false,
// canEditDepletion: false,
// canEditEgg: false,
// isLocked: true,
// lockReason:
// 'Recording Growing telah terkunci karena Project Flock sudah masuk fase Laying',
// };
// }
if (!isLaying && !isTransition) {
return {
canEditStock: true,
canEditDepletion: true,
canEditEgg: false,
isLocked: false,
lockReason: undefined,
};
}
if (isLaying && !isTransition) {
return {
canEditStock: true,
canEditDepletion: true,
canEditEgg: true,
isLocked: false,
lockReason: undefined,
};
}
// if (!isLaying && !isTransition) {
// return {
// canEditStock: true,
// canEditDepletion: true,
// canEditEgg: false,
// isLocked: false,
// lockReason: undefined,
// };
// }
// if (isLaying && !isTransition) {
// return {
// canEditStock: true,
// canEditDepletion: true,
// canEditEgg: true,
// isLocked: false,
// lockReason: undefined,
// };
// }
// return {
// canEditStock: false,
// canEditDepletion: false,
// canEditEgg: false,
// isLocked: true,
// lockReason: 'Kondisi transisi tidak valid',
// };
// remove recording transition restriction by request: 30 May 2026, 09:11
return {
canEditStock: false,
canEditDepletion: false,
canEditEgg: false,
isLocked: true,
lockReason: 'Kondisi transisi tidak valid',
canEditStock: true,
canEditDepletion: true,
canEditEgg: true,
isLocked: false,
lockReason: undefined,
};
};
-8
View File
@@ -23,8 +23,6 @@ export type BaseMarketing = {
latest_approval: BaseApproval;
sales_order: BaseSalesOrder[];
delivery_order: BaseDeliveryOrder[];
grand_total_do: number;
grand_total_so: number;
};
export type BaseSalesOrder = {
@@ -106,12 +104,6 @@ export type MarketingFilter = {
project_flock_name?: string;
project_flock_kandang_id?: number;
project_flock_kandang_name?: string;
start_date?: string;
end_date?: string;
filter_by?: string;
filter_by_name?: string;
warehouse_id?: number;
warehouse_name?: string;
};
/**