mirror of
https://gitlab.com/mbugroup/lti-web-client.git
synced 2026-05-20 13:32:00 +00:00
feat(FE-137): integrate API for daily recording with enhanced data structure and validation
This commit is contained in:
@@ -1,212 +1,167 @@
|
||||
import * as Yup from 'yup';
|
||||
import { RECORDING_FLAG_OPTIONS } from '@/config/constant';
|
||||
import { Recording } from '@/types/api/production/recording';
|
||||
import {
|
||||
Recording,
|
||||
CreateRecordingPayload,
|
||||
} from '@/types/api/production/recording';
|
||||
|
||||
export const RecordingFormSchema = Yup.object({
|
||||
flock: Yup.object({
|
||||
project_flock_kandang: Yup.object({
|
||||
value: Yup.number().min(1).required(),
|
||||
label: Yup.string().required(),
|
||||
}).nullable(),
|
||||
flock_id: Yup.number()
|
||||
project_flock_kandang_id: Yup.number()
|
||||
.default(0)
|
||||
.typeError('Flock wajib diisi!')
|
||||
.typeError('Project Flock Kandang wajib diisi!')
|
||||
.test(
|
||||
'is-valid-flock',
|
||||
'Flock wajib diisi!',
|
||||
'is-valid-project-flock-kandang',
|
||||
'Project Flock Kandang wajib diisi!',
|
||||
(value) => value !== undefined && value !== null && value > 0
|
||||
)
|
||||
.required('Flock wajib diisi!'),
|
||||
location: Yup.object({
|
||||
value: Yup.number().min(1).required(),
|
||||
label: Yup.string().required(),
|
||||
}).nullable(),
|
||||
location_id: Yup.number()
|
||||
.default(0)
|
||||
.typeError('Lokasi wajib diisi!')
|
||||
.test(
|
||||
'is-valid-location',
|
||||
'Lokasi wajib diisi!',
|
||||
(value) => value !== undefined && value !== null && value > 0
|
||||
)
|
||||
.required('Lokasi wajib diisi!'),
|
||||
coop: Yup.object({
|
||||
value: Yup.number().min(1).required(),
|
||||
label: Yup.string().required(),
|
||||
}).nullable(),
|
||||
coop_id: Yup.number()
|
||||
.default(0)
|
||||
.typeError('Kandang wajib diisi!')
|
||||
.test(
|
||||
'is-valid-coop',
|
||||
'Kandang wajib diisi!',
|
||||
(value) => value !== undefined && value !== null && value > 0
|
||||
)
|
||||
.required('Kandang wajib diisi!'),
|
||||
recording_date: Yup.date()
|
||||
.required('Tanggal recording wajib diisi')
|
||||
.typeError('Format tanggal tidak valid'),
|
||||
feed_data: Yup.array()
|
||||
.required('Project Flock Kandang wajib diisi!'),
|
||||
record_datetime: Yup.date()
|
||||
.required('Tanggal dan waktu recording wajib diisi')
|
||||
.typeError('Format tanggal dan waktu tidak valid'),
|
||||
status: Yup.number()
|
||||
.optional()
|
||||
.oneOf([0, 1, 2, 3], 'Status tidak valid')
|
||||
.typeError('Status harus berupa angka!'),
|
||||
ontime: Yup.boolean().optional(),
|
||||
body_weights: Yup.array()
|
||||
.of(
|
||||
Yup.object({
|
||||
feed_id: Yup.string().required('Nama pakan wajib diisi!'),
|
||||
feed_qty: Yup.mixed<number | ''>().notRequired(),
|
||||
feed_stock: Yup.number()
|
||||
.required('Jumlah pakan yang digunakan wajib diisi!')
|
||||
.min(1, 'Jumlah pakan minimal 1!')
|
||||
.typeError('Jumlah pakan yang digunakan harus berupa angka!')
|
||||
.test(
|
||||
'is-not-exceed-qty',
|
||||
'Jumlah pakan yang digunakan tidak boleh melebihi stok tersedia!',
|
||||
function (value) {
|
||||
const { feed_qty } = this.parent;
|
||||
if (value === undefined) return true;
|
||||
if (
|
||||
feed_qty === undefined ||
|
||||
feed_qty === '' ||
|
||||
typeof feed_qty !== 'number'
|
||||
)
|
||||
return true;
|
||||
return value <= feed_qty;
|
||||
}
|
||||
),
|
||||
})
|
||||
)
|
||||
.min(1, 'Minimal harus ada 1 data pakan!')
|
||||
.required('Data pakan wajib diisi!'),
|
||||
body_weight: Yup.array()
|
||||
.of(
|
||||
Yup.object({
|
||||
chicken_weight: Yup.number()
|
||||
weight: Yup.number()
|
||||
.required('Berat ayam wajib diisi!')
|
||||
.min(1, 'Berat ayam minimal 1 gram!')
|
||||
.typeError('Berat ayam harus berupa angka!'),
|
||||
chicken_count: Yup.number()
|
||||
qty: Yup.number()
|
||||
.required('Jumlah ayam wajib diisi!')
|
||||
.min(1, 'Jumlah ayam minimal 1 ekor!')
|
||||
.typeError('Jumlah ayam harus berupa angka!'),
|
||||
average_chicken_weight: Yup.number()
|
||||
.required('Rata-rata berat ayam wajib diisi!')
|
||||
.min(1, 'Rata-rata berat ayam minimal 1 gram!')
|
||||
.typeError('Rata-rata berat ayam harus berupa angka!'),
|
||||
.typeError('Jumlah ayam harus berupa angka!')
|
||||
.default(1),
|
||||
notes: Yup.string().optional(),
|
||||
})
|
||||
)
|
||||
.min(1, 'Minimal harus ada 1 data bobot badan!')
|
||||
.required('Data bobot badan wajib diisi!'),
|
||||
vaccination: Yup.array()
|
||||
stocks: Yup.array()
|
||||
.of(
|
||||
Yup.object({
|
||||
vaccine_id: Yup.string().required('Nama vaksin wajib diisi!'),
|
||||
total_stock: Yup.mixed<number | ''>().notRequired(),
|
||||
used_stock: Yup.number()
|
||||
.required('Jumlah vaksin yang digunakan wajib diisi!')
|
||||
.min(1, 'Jumlah vaksin minimal 1!')
|
||||
.typeError('Jumlah vaksin yang digunakan harus berupa angka!')
|
||||
.test(
|
||||
'is-not-exceed-total',
|
||||
'Jumlah vaksin yang digunakan tidak boleh melebihi stok tersedia!',
|
||||
function (value) {
|
||||
const { total_stock } = this.parent;
|
||||
if (value === undefined) return true;
|
||||
if (
|
||||
total_stock === undefined ||
|
||||
total_stock === '' ||
|
||||
typeof total_stock !== 'number'
|
||||
)
|
||||
return true;
|
||||
return value <= total_stock;
|
||||
}
|
||||
),
|
||||
product_warehouse_id: Yup.number()
|
||||
.required('Produk wajib diisi!')
|
||||
.min(1, 'Produk wajib diisi!')
|
||||
.typeError('Produk harus berupa angka!'),
|
||||
increase: Yup.number()
|
||||
.optional()
|
||||
.min(0, 'Penambahan tidak boleh negatif!')
|
||||
.typeError('Penambahan harus berupa angka!'),
|
||||
decrease: Yup.number()
|
||||
.optional()
|
||||
.min(0, 'Pengurangan tidak boleh negatif!')
|
||||
.typeError('Pengurangan harus berupa angka!'),
|
||||
usage_amount: Yup.number()
|
||||
.optional()
|
||||
.min(0, 'Jumlah penggunaan tidak boleh negatif!')
|
||||
.typeError('Jumlah penggunaan harus berupa angka!'),
|
||||
notes: Yup.string().optional(),
|
||||
})
|
||||
)
|
||||
.min(1, 'Minimal harus ada 1 data vaksinasi!')
|
||||
.required('Data vaksinasi wajib diisi!'),
|
||||
mortality: Yup.array()
|
||||
.min(1, 'Minimal harus ada 1 data stok!')
|
||||
.required('Data stok wajib diisi!'),
|
||||
depletions: Yup.array()
|
||||
.of(
|
||||
Yup.object({
|
||||
condition: Yup.mixed<string>()
|
||||
product_warehouse_id: Yup.number()
|
||||
.required('Produk wajib diisi!')
|
||||
.min(1, 'Produk wajib diisi!')
|
||||
.typeError('Produk harus berupa angka!'),
|
||||
condition: Yup.string()
|
||||
.required('Kondisi depletions wajib diisi!')
|
||||
.oneOf(
|
||||
RECORDING_FLAG_OPTIONS.map((opt) => opt.value),
|
||||
'Kondisi tidak valid!'
|
||||
RECORDING_FLAG_OPTIONS.map((option) => option.value),
|
||||
'Kondisi depletions tidak valid!'
|
||||
)
|
||||
.required('Kondisi wajib diisi!'),
|
||||
count: Yup.number()
|
||||
.required('Jumlah mortalitas wajib diisi!')
|
||||
.min(1, 'Jumlah mortalitas minimal 1 ekor!')
|
||||
.typeError('Jumlah mortalitas harus berupa angka!'),
|
||||
.typeError('Kondisi depletions harus berupa teks!')
|
||||
.min(1, 'Kondisi depletions wajib diisi!'),
|
||||
total: Yup.number()
|
||||
.required('Jumlah depletions wajib diisi!')
|
||||
.min(1, 'Jumlah depletions minimal 1!')
|
||||
.typeError('Jumlah depletions harus berupa angka!'),
|
||||
notes: Yup.string().optional(),
|
||||
})
|
||||
)
|
||||
.min(1, 'Minimal harus ada 1 data mortalitas!')
|
||||
.required('Data mortalitas wajib diisi!'),
|
||||
.min(1, 'Minimal harus ada 1 data depletions!')
|
||||
.required('Data depletions wajib diisi!'),
|
||||
});
|
||||
|
||||
export const UpdateRecordingFormSchema = RecordingFormSchema;
|
||||
|
||||
export type RecordingFormValues = Yup.InferType<typeof RecordingFormSchema>;
|
||||
|
||||
type RecordingFormData = Partial<Recording> & {
|
||||
body_weights?: CreateRecordingPayload['body_weights'];
|
||||
stocks?: CreateRecordingPayload['stocks'];
|
||||
depletions?: CreateRecordingPayload['depletions'];
|
||||
};
|
||||
|
||||
export const getRecordingFormInitialValues = (
|
||||
initialValues?: Recording
|
||||
initialValues?: RecordingFormData
|
||||
): RecordingFormValues => ({
|
||||
flock: initialValues?.flock
|
||||
project_flock_kandang: initialValues?.project_flock_kandang_id
|
||||
? {
|
||||
value: initialValues.flock.id,
|
||||
label: initialValues.flock.name,
|
||||
value: initialValues.project_flock_kandang_id,
|
||||
label: `Project Flock Kandang #${initialValues.project_flock_kandang_id}`,
|
||||
}
|
||||
: null,
|
||||
flock_id: initialValues?.flock?.id ?? 0,
|
||||
location: initialValues?.location
|
||||
? {
|
||||
value: initialValues.location.id,
|
||||
label: initialValues.location.name,
|
||||
}
|
||||
: null,
|
||||
location_id: initialValues?.location?.id ?? 0,
|
||||
coop: initialValues?.coop
|
||||
? {
|
||||
value: initialValues.coop.id,
|
||||
label: initialValues.coop.name,
|
||||
}
|
||||
: null,
|
||||
coop_id: initialValues?.coop?.id ?? 0,
|
||||
recording_date: initialValues?.recording_date
|
||||
? new Date(initialValues.recording_date)
|
||||
project_flock_kandang_id: initialValues?.project_flock_kandang_id ?? 0,
|
||||
record_datetime: initialValues?.record_datetime
|
||||
? new Date(initialValues.record_datetime)
|
||||
: new Date(),
|
||||
feed_data: initialValues?.feed_data
|
||||
? initialValues.feed_data.map((feed) => ({
|
||||
feed_id: feed.feed_name,
|
||||
feed_qty: feed.feed_qty,
|
||||
feed_stock: feed.feed_stock,
|
||||
}))
|
||||
: [
|
||||
{
|
||||
feed_id: '',
|
||||
feed_qty: '',
|
||||
feed_stock: 0,
|
||||
},
|
||||
],
|
||||
body_weight: initialValues?.body_weight ?? [
|
||||
status: initialValues?.status ?? 1,
|
||||
ontime: initialValues?.ontime ?? true,
|
||||
body_weights: initialValues?.body_weights?.map(
|
||||
(bw: NonNullable<CreateRecordingPayload['body_weights']>[0]) => ({
|
||||
weight: bw.weight,
|
||||
qty: bw.qty,
|
||||
notes: bw.notes || '',
|
||||
})
|
||||
) ?? [
|
||||
{
|
||||
chicken_weight: 0,
|
||||
chicken_count: 0,
|
||||
average_chicken_weight: 0,
|
||||
weight: 0,
|
||||
qty: 1,
|
||||
notes: '',
|
||||
},
|
||||
],
|
||||
vaccination: initialValues?.vaccination
|
||||
? initialValues.vaccination.map((vaccine) => ({
|
||||
vaccine_id: vaccine.vaccine_name,
|
||||
total_stock: vaccine.total_stock,
|
||||
used_stock: vaccine.used_stock,
|
||||
}))
|
||||
: [
|
||||
{
|
||||
vaccine_id: '',
|
||||
total_stock: '',
|
||||
used_stock: 0,
|
||||
},
|
||||
],
|
||||
mortality: initialValues?.mortality ?? [
|
||||
stocks: initialValues?.stocks?.map(
|
||||
(stock: NonNullable<CreateRecordingPayload['stocks']>[0]) => ({
|
||||
product_warehouse_id: stock.product_warehouse_id,
|
||||
increase: stock.increase,
|
||||
decrease: stock.decrease,
|
||||
usage_amount: stock.usage_amount,
|
||||
notes: stock.notes,
|
||||
})
|
||||
) ?? [
|
||||
{
|
||||
product_warehouse_id: 0,
|
||||
increase: 0,
|
||||
decrease: 0,
|
||||
usage_amount: 0,
|
||||
notes: '',
|
||||
},
|
||||
],
|
||||
depletions: initialValues?.depletions?.map(
|
||||
(depletion: NonNullable<CreateRecordingPayload['depletions']>[0]) => ({
|
||||
product_warehouse_id: depletion.product_warehouse_id,
|
||||
condition: depletion.condition,
|
||||
total: depletion.total,
|
||||
notes: depletion.notes,
|
||||
})
|
||||
) ?? [
|
||||
{
|
||||
product_warehouse_id: 0,
|
||||
condition: '',
|
||||
count: 0,
|
||||
total: 0,
|
||||
notes: '',
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
+39
-47
@@ -1,60 +1,52 @@
|
||||
import { BaseMetadata } from '@/types/api/api-general';
|
||||
import { Location } from '@/types/api/master-data/location';
|
||||
import { Kandang } from '@/types/api/master-data/kandang';
|
||||
import { Flock } from '@/types/api/master-data/flock';
|
||||
import { BaseMetadata, User } from '@/types/api/api-general';
|
||||
|
||||
export type ProductionMetrics = {
|
||||
total_depletion: number;
|
||||
cum_depletion_rate: number;
|
||||
daily_gain: number;
|
||||
avg_daily_gain: number;
|
||||
cum_intake: number;
|
||||
fcr_value: number;
|
||||
total_chick: number;
|
||||
daily_depletion_rate: number;
|
||||
cum_depletion: number;
|
||||
};
|
||||
|
||||
export type BaseRecording = {
|
||||
id: number;
|
||||
flock: Flock;
|
||||
recording_date: string;
|
||||
location: Location;
|
||||
coop: Kandang;
|
||||
feed_data: {
|
||||
feed_name: string;
|
||||
feed_qty: number;
|
||||
feed_stock: number;
|
||||
}[];
|
||||
body_weight: {
|
||||
chicken_weight: number;
|
||||
chicken_count: number;
|
||||
average_chicken_weight: number;
|
||||
}[];
|
||||
vaccination: {
|
||||
vaccine_name: string;
|
||||
total_stock: number;
|
||||
used_stock: number;
|
||||
}[];
|
||||
mortality: {
|
||||
condition: string;
|
||||
count: number;
|
||||
}[];
|
||||
};
|
||||
project_flock_kandang_id: number;
|
||||
record_datetime: string;
|
||||
record_date: string;
|
||||
status: number;
|
||||
ontime: boolean;
|
||||
day: number;
|
||||
created_user: User;
|
||||
} & ProductionMetrics;
|
||||
|
||||
export type Recording = BaseMetadata & BaseRecording;
|
||||
|
||||
export type CreateRecordingPayload = {
|
||||
flock_id: number;
|
||||
recording_date: string;
|
||||
location_id: number;
|
||||
coop_id: number;
|
||||
feed_data: {
|
||||
feed_id: string;
|
||||
feed_qty: number;
|
||||
feed_stock: number;
|
||||
project_flock_kandang_id: number;
|
||||
record_datetime: string;
|
||||
status?: number;
|
||||
ontime?: boolean;
|
||||
body_weights?: {
|
||||
weight: number;
|
||||
qty: number;
|
||||
notes?: string;
|
||||
}[];
|
||||
body_weight: {
|
||||
chicken_weight: number;
|
||||
chicken_count: number;
|
||||
average_chicken_weight: number;
|
||||
stocks?: {
|
||||
product_warehouse_id: number;
|
||||
increase?: number;
|
||||
decrease?: number;
|
||||
usage_amount?: number;
|
||||
notes?: string;
|
||||
}[];
|
||||
vaccination: {
|
||||
vaccine_id: string;
|
||||
total_stock: number;
|
||||
used_stock: number;
|
||||
}[];
|
||||
mortality: {
|
||||
depletions?: {
|
||||
product_warehouse_id: number;
|
||||
condition: string;
|
||||
count: number;
|
||||
total: number;
|
||||
notes?: string;
|
||||
}[];
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user