From 2d1cabb86b61def72179d476554db95b6798adfb Mon Sep 17 00:00:00 2001 From: ValdiANS Date: Sun, 7 Dec 2025 14:59:25 +0700 Subject: [PATCH 1/3] refactor: update CreateExpensePayload, UpdateExpensePayload, and CreateExpenseRealizationPayload types --- .../expense/ExpenseRealizationContent.tsx | 8 +-- .../pages/expense/ExpenseRequestContent.tsx | 13 ++--- .../form/ExpenseRealizationForm.schema.ts | 8 +-- .../expense/form/ExpenseRealizationForm.tsx | 9 +--- ...ExpenseRealizationKandangDetailExpense.tsx | 12 ++--- .../expense/form/ExpenseRequestForm.schema.ts | 16 +++--- .../pages/expense/form/ExpenseRequestForm.tsx | 53 ++++++++++--------- .../ExpenseRequestKandangDetailExpense.tsx | 49 +++++++++-------- .../pages/expense/pdf/ExpensePDF.tsx | 14 ++--- src/services/api/expense.ts | 8 +-- src/types/api/expense.d.ts | 34 +++++------- 11 files changed, 107 insertions(+), 117 deletions(-) diff --git a/src/components/pages/expense/ExpenseRealizationContent.tsx b/src/components/pages/expense/ExpenseRealizationContent.tsx index 478cdadf..2b5b0a0a 100644 --- a/src/components/pages/expense/ExpenseRealizationContent.tsx +++ b/src/components/pages/expense/ExpenseRealizationContent.tsx @@ -207,7 +207,7 @@ const ExpenseRealizationContent = ({ let expenseGrandTotal = 0; kandangExpense.pengajuans?.forEach( - (item) => (expenseGrandTotal += item.total_price) + (item) => (expenseGrandTotal += item.price) ); return ( @@ -238,7 +238,7 @@ const ExpenseRealizationContent = ({ {pengajuanItem.nonstock.name} {pengajuanItem.qty} - {formatCurrency(pengajuanItem.total_price)} + {formatCurrency(pengajuanItem.price)} {pengajuanItem.note ?? '-'} ) @@ -269,7 +269,7 @@ const ExpenseRealizationContent = ({ let expenseGrandTotal = 0; kandangExpense.realisasi?.forEach( - (item) => (expenseGrandTotal += item.total_price) + (item) => (expenseGrandTotal += item.price) ); return ( @@ -300,7 +300,7 @@ const ExpenseRealizationContent = ({ {realisasiItem.nonstock.name} {realisasiItem.qty} - {formatCurrency(realisasiItem.total_price)} + {formatCurrency(realisasiItem.price)} {realisasiItem.note ?? '-'} ) diff --git a/src/components/pages/expense/ExpenseRequestContent.tsx b/src/components/pages/expense/ExpenseRequestContent.tsx index af8ceddc..0d7d959d 100644 --- a/src/components/pages/expense/ExpenseRequestContent.tsx +++ b/src/components/pages/expense/ExpenseRequestContent.tsx @@ -402,7 +402,10 @@ const ExpenseRequestContent = ({ Tanggal Transaksi : - {formatDate(initialValues?.expense_date, 'DD MMMM YYYY')} + {formatDate( + initialValues?.transaction_date, + 'DD MMMM YYYY' + )} @@ -529,7 +532,7 @@ const ExpenseRequestContent = ({ let expenseGrandTotal = 0; kandangExpense.pengajuans?.forEach( - (item) => (expenseGrandTotal += item.total_price) + (item) => (expenseGrandTotal += item.price) ); return ( @@ -550,7 +553,7 @@ const ExpenseRequestContent = ({ Nonstock Total Kuantitas - Total Biaya + Harga Satuan Catatan @@ -560,9 +563,7 @@ const ExpenseRequestContent = ({ {pengajuanItem.nonstock.name} {pengajuanItem.qty} - - {formatCurrency(pengajuanItem.total_price)} - + {formatCurrency(pengajuanItem.price)} {pengajuanItem.note ?? '-'} diff --git a/src/components/pages/expense/form/ExpenseRealizationForm.schema.ts b/src/components/pages/expense/form/ExpenseRealizationForm.schema.ts index 863238b9..77db761c 100644 --- a/src/components/pages/expense/form/ExpenseRealizationForm.schema.ts +++ b/src/components/pages/expense/form/ExpenseRealizationForm.schema.ts @@ -27,7 +27,7 @@ type ExpenseRealizationFormSchemaType = { label: string; }; quantity?: number; - total_cost?: number; + price?: number; notes?: string; }[]; }[]; @@ -82,7 +82,7 @@ export const ExpenseRealizationFormSchema: Yup.ObjectSchema { realization.cost_items.forEach((costItem) => { - const unitPrice = - parseFloat(String(costItem.total_cost)) / - parseFloat(String(costItem.quantity)); - const realizationItem = { expense_nonstock_id: costItem.nonstock?.value as number, qty: parseFloat(String(costItem.quantity)) as number, - unit_price: unitPrice, - total_price: parseFloat(String(costItem.total_cost)) as number, + price: parseFloat(String(costItem.price)) as number, notes: costItem.notes ?? '', }; @@ -177,7 +172,7 @@ const ExpenseRealizationForm = ({ { nonstock: undefined, quantity: undefined, - total_cost: undefined, + price: undefined, notes: '', }, ], diff --git a/src/components/pages/expense/form/ExpenseRealizationKandangDetailExpense.tsx b/src/components/pages/expense/form/ExpenseRealizationKandangDetailExpense.tsx index 8b889c5b..017a733e 100644 --- a/src/components/pages/expense/form/ExpenseRealizationKandangDetailExpense.tsx +++ b/src/components/pages/expense/form/ExpenseRealizationKandangDetailExpense.tsx @@ -48,7 +48,7 @@ const ExpenseRealizationKandangDetailExpense: React.FC< }; const isExpenseRepeaterInputError = ( - column: 'nonstock' | 'quantity' | 'total_cost' | 'notes', + column: 'nonstock' | 'quantity' | 'price' | 'notes', kandangExpenseIdx: number, expenseIdx: number ) => { @@ -112,7 +112,7 @@ const ExpenseRealizationKandangDetailExpense: React.FC< Nonstock Total Kuantitas - Total Biaya + Harga Satuan Catatan @@ -163,17 +163,17 @@ const ExpenseRealizationKandangDetailExpense: React.FC< = documents: Yup.array().of(Yup.mixed().required()).optional(), - cost_per_kandangs: Yup.array() + expense_nonstocks: Yup.array() .of( Yup.object({ kandang_id: Yup.number().min(1, 'Wajib memilih kandang!').required(), @@ -86,7 +86,7 @@ export const ExpenseRequestFormSchema: Yup.ObjectSchema = label: Yup.string().required(), }).required('Nonstock wajib diisi!'), quantity: Yup.number().required('Total kuantitas wajib diisi!'), - total_cost: Yup.number().required('Total biaya wajib diisi!'), + price: Yup.number().required('Harga satuan wajib diisi!'), notes: Yup.string(), }) ) @@ -128,8 +128,8 @@ export const getExpenseFormInitialValues = ( label: initialValues.location.name, } : undefined, - transaction_date: initialValues?.expense_date - ? formatDate(initialValues.expense_date, 'YYYY-MM-DD') + transaction_date: initialValues?.transaction_date + ? formatDate(initialValues.transaction_date, 'YYYY-MM-DD') : undefined, kandangs: initialValues?.kandangs.map((kandang) => ({ id: kandang.kandang_id, @@ -148,7 +148,7 @@ export const getExpenseFormInitialValues = ( })), deleted_documents: [], documents: [], - cost_per_kandangs: initialValues?.kandangs + expense_nonstocks: initialValues?.kandangs ? initialValues.kandangs.map((kandangExpense) => ({ kandang_id: kandangExpense.kandang_id, cost_items: kandangExpense.pengajuans @@ -158,7 +158,7 @@ export const getExpenseFormInitialValues = ( label: expenseItem.nonstock.name, }, quantity: expenseItem.qty, - total_cost: expenseItem.total_price, + price: expenseItem.price, notes: expenseItem.note, })) : [], diff --git a/src/components/pages/expense/form/ExpenseRequestForm.tsx b/src/components/pages/expense/form/ExpenseRequestForm.tsx index e47f2f76..d52bde0d 100644 --- a/src/components/pages/expense/form/ExpenseRequestForm.tsx +++ b/src/components/pages/expense/form/ExpenseRequestForm.tsx @@ -110,12 +110,12 @@ const ExpenseRequestForm = ({ transaction_date: values?.transaction_date as string, supplier_id: values.supplier?.value as number, documents: values.documents as File[], - cost_per_kandangs: values.cost_per_kandangs.map((costPerKandang) => ({ - kandang_id: costPerKandang.kandang_id, - cost_items: costPerKandang.cost_items.map((costItem) => ({ + expense_nonstocks: values.expense_nonstocks.map((expenseNonstock) => ({ + kandang_id: expenseNonstock.kandang_id, + cost_items: expenseNonstock.cost_items.map((costItem) => ({ nonstock_id: costItem.nonstock?.value as number, quantity: parseFloat(String(costItem.quantity)) as number, - total_cost: parseFloat(String(costItem.total_cost)) as number, + price: parseFloat(String(costItem.price)) as number, notes: costItem.notes ?? '', })), })), @@ -132,13 +132,13 @@ const ExpenseRequestForm = ({ transaction_date: values?.transaction_date as string, supplier_id: values.supplier?.value as number, documents: values.documents as File[], - cost_per_kandang: values.cost_per_kandangs.map( - (costPerKandang) => ({ - kandang_id: costPerKandang.kandang_id, - cost_items: costPerKandang.cost_items.map((costItem) => ({ + expense_nonstocks: values.expense_nonstocks.map( + (expenseNonstock) => ({ + kandang_id: expenseNonstock.kandang_id, + cost_items: expenseNonstock.cost_items.map((costItem) => ({ nonstock_id: costItem.nonstock?.value as number, quantity: parseFloat(String(costItem.quantity)) as number, - total_cost: parseFloat(String(costItem.total_cost)) as number, + price: parseFloat(String(costItem.price)) as number, notes: costItem.notes ?? '', })), }) @@ -179,53 +179,54 @@ const ExpenseRequestForm = ({ formik.setFieldValue('location', val); formik.setFieldValue('kandangs', []); - formik.setFieldValue('cost_per_kandangs', []); + formik.setFieldValue('expense_nonstocks', []); }; const kandangsChangeHandler = (kandangs: { id: number; name: string }[]) => { formik.setFieldTouched('kandangs', true); formik.setFieldValue('kandangs', kandangs); - const newCostPerKandangs = [...(formik.values.cost_per_kandangs ?? [])]; + const newExpenseNonstocks = [...(formik.values.expense_nonstocks ?? [])]; - // add new cost_per_kandangs + // add new expense_nonstocks kandangs.forEach((kandangItem) => { - const isKandangExistInCostPerKandangs = newCostPerKandangs.find( - (costPerKandangItem) => costPerKandangItem.kandang_id === kandangItem.id + const isKandangExistInExpenseNonstocks = newExpenseNonstocks.find( + (expenseNonstockItem) => + expenseNonstockItem.kandang_id === kandangItem.id ); - if (isKandangExistInCostPerKandangs) return; + if (isKandangExistInExpenseNonstocks) return; - newCostPerKandangs.push({ + newExpenseNonstocks.push({ kandang_id: kandangItem.id, cost_items: [ { nonstock: undefined, quantity: undefined, - total_cost: undefined, + price: undefined, notes: '', }, ], }); }); - // prune cost_per_kandangs + // prune expense_nonstocks const kandangIds = new Set(kandangs.map((kandang) => kandang.id)); - const deletedCostPerKandangsIdx: number[] = []; + const deletedExpenseNonstocksIdx: number[] = []; - newCostPerKandangs.forEach((costPerKandang, idx) => { - const isCostPerKandangValid = kandangIds.has(costPerKandang.kandang_id); + newExpenseNonstocks.forEach((expenseNonstock, idx) => { + const isExpenseNonstockValid = kandangIds.has(expenseNonstock.kandang_id); - if (!isCostPerKandangValid) { - deletedCostPerKandangsIdx.push(idx); + if (!isExpenseNonstockValid) { + deletedExpenseNonstocksIdx.push(idx); } }); - deletedCostPerKandangsIdx.forEach((deletedCostPerKandangIdx) => { - newCostPerKandangs.splice(deletedCostPerKandangIdx, 1); + deletedExpenseNonstocksIdx.forEach((deletedExpenseNonstockIdx) => { + newExpenseNonstocks.splice(deletedExpenseNonstockIdx, 1); }); - formik.setFieldValue('cost_per_kandangs', newCostPerKandangs); + formik.setFieldValue('expense_nonstocks', newExpenseNonstocks); }; const supplierChangeHandler = (val: OptionType | OptionType[] | null) => { diff --git a/src/components/pages/expense/form/ExpenseRequestKandangDetailExpense.tsx b/src/components/pages/expense/form/ExpenseRequestKandangDetailExpense.tsx index 73e6c9b7..11f54585 100644 --- a/src/components/pages/expense/form/ExpenseRequestKandangDetailExpense.tsx +++ b/src/components/pages/expense/form/ExpenseRequestKandangDetailExpense.tsx @@ -41,28 +41,28 @@ const ExpenseRequestKandangDetailExpense: React.FC< val: OptionType | OptionType[] | null ) => { formik.setFieldTouched( - `cost_per_kandangs[${kandangExpenseIdx}].cost_items[${expenseIdx}].nonstock`, + `expense_nonstocks[${kandangExpenseIdx}].cost_items[${expenseIdx}].nonstock`, true ); formik.setFieldValue( - `cost_per_kandangs[${kandangExpenseIdx}].cost_items[${expenseIdx}].nonstock`, + `expense_nonstocks[${kandangExpenseIdx}].cost_items[${expenseIdx}].nonstock`, val ); }; const addExpenseItemHandler = (kandangExpenseIdx: number) => { const newExpensesValue = [ - ...formik.values.cost_per_kandangs[kandangExpenseIdx].cost_items, + ...formik.values.expense_nonstocks[kandangExpenseIdx].cost_items, { nonstock: undefined, - total_cost: undefined, + price: undefined, quantity: undefined, notes: '', }, ]; formik.setFieldValue( - `cost_per_kandangs[${kandangExpenseIdx}].cost_items`, + `expense_nonstocks[${kandangExpenseIdx}].cost_items`, newExpensesValue ); }; @@ -71,28 +71,28 @@ const ExpenseRequestKandangDetailExpense: React.FC< kandangExpenseIdx: number, expenseIdx: number ) => { - const path = `cost_per_kandangs[${kandangExpenseIdx}].cost_items`; + const path = `expense_nonstocks[${kandangExpenseIdx}].cost_items`; // trims values, errors, and touched at expenseIdx removeArrayItemAndSync(formik, path, expenseIdx); }; const isExpenseRepeaterInputError = ( - column: 'nonstock' | 'quantity' | 'total_cost' | 'notes', + column: 'nonstock' | 'quantity' | 'price' | 'notes', kandangExpenseIdx: number, expenseIdx: number ) => { return ( - formik.touched.cost_per_kandangs?.[kandangExpenseIdx]?.cost_items?.[ + formik.touched.expense_nonstocks?.[kandangExpenseIdx]?.cost_items?.[ expenseIdx ]?.[column] && Boolean( - formik.errors.cost_per_kandangs?.[kandangExpenseIdx] instanceof + formik.errors.expense_nonstocks?.[kandangExpenseIdx] instanceof Object && - formik.errors.cost_per_kandangs?.[kandangExpenseIdx].cost_items?.[ + formik.errors.expense_nonstocks?.[kandangExpenseIdx].cost_items?.[ expenseIdx ] instanceof Object && - formik.errors.cost_per_kandangs?.[kandangExpenseIdx].cost_items?.[ + formik.errors.expense_nonstocks?.[kandangExpenseIdx].cost_items?.[ expenseIdx ]?.[column] ) @@ -113,7 +113,7 @@ const ExpenseRequestKandangDetailExpense: React.FC<
- {(formik.values.cost_per_kandangs.length === 0 || + {(formik.values.expense_nonstocks.length === 0 || !formik.values.supplier?.value) && (

@@ -122,9 +122,9 @@ const ExpenseRequestKandangDetailExpense: React.FC<

)} - {formik.values.cost_per_kandangs.length > 0 && + {formik.values.expense_nonstocks.length > 0 && formik.values.supplier?.value && - formik.values.cost_per_kandangs.map( + formik.values.expense_nonstocks.map( (kandangExpense, kandangExpenseIdx) => { const kandangName = formik.values.kandangs?.find( (kandang) => kandang.id === kandangExpense.kandang_id @@ -147,7 +147,7 @@ const ExpenseRequestKandangDetailExpense: React.FC< Nonstock Total Kuantitas - Total Biaya + Harga Satuan Catatan {type !== 'detail' && Aksi} @@ -178,10 +178,10 @@ const ExpenseRequestKandangDetailExpense: React.FC< { { label: 'Vendor', value: expense?.supplier.name }, { label: 'Tanggal Transaksi', - value: formatDate(expense?.expense_date, 'DD MMMM YYYY'), + value: formatDate(expense?.transaction_date, 'DD MMMM YYYY'), }, { label: 'Tanggal Realisasi', @@ -326,7 +326,7 @@ const ExpensePDF = ({ expense }: ExpensePDFProps) => { let expenseRequestTotal = 0; kandangExpense.pengajuans?.forEach( - (item) => (expenseRequestTotal += item.total_price) + (item) => (expenseRequestTotal += item.price) ); return ( @@ -374,7 +374,7 @@ const ExpensePDF = ({ expense }: ExpensePDFProps) => { - Total Biaya + Harga Satuan { ]} > - {formatCurrency(pengajuan.total_price)} + {formatCurrency(pengajuan.price)} { let expenseRealizationTotal = 0; kandangExpense.realisasi?.forEach( - (item) => (expenseRealizationTotal += item.total_price) + (item) => (expenseRealizationTotal += item.price) ); return ( @@ -532,7 +532,7 @@ const ExpensePDF = ({ expense }: ExpensePDFProps) => { - Total Biaya + Harga Satuan { ]} > - {formatCurrency(realisasi.total_price)} + {formatCurrency(realisasi.price)} ; - project_flock_kandang: { - id: number; - kandang_id: number; - }; + created_at: string; }[]; realisasi?: { id: number; + expense_nonstock_id: number; qty: number; - unit_price: number; - total_price: number; - date: string; + price: number; note?: string; nonstock: Pick; - project_flock_kandang: { - id: number; - kandang_id: number; - }; + created_at: string; }[]; }[]; total_pengajuan: number; @@ -65,12 +60,12 @@ export type CreateExpensePayload = { transaction_date: string; supplier_id: number; documents: File[]; - cost_per_kandangs: { + expense_nonstocks: { kandang_id: number; cost_items: { nonstock_id: number; quantity: number; - total_cost: number; + price: number; notes: string; }[]; }[]; @@ -81,12 +76,12 @@ export type UpdateExpensePayload = { transaction_date: string; supplier_id: number; documents: File[]; - cost_per_kandang: { + expense_nonstocks: { kandang_id: number; cost_items: { nonstock_id: number; quantity: number; - total_cost: number; + price: number; notes: string; }[]; }[]; @@ -98,8 +93,7 @@ export type CreateExpenseRealizationPayload = { realizations: { expense_nonstock_id: number; qty: number; - unit_price: number; - total_price: number; + price: number; notes: string; }[]; }; From 5782abb531d974ec05eb18a98fd005eb6ceabf4b Mon Sep 17 00:00:00 2001 From: ValdiANS Date: Sun, 7 Dec 2025 14:59:51 +0700 Subject: [PATCH 2/3] refactor: change expense_date to transaction_date --- src/components/pages/expense/ExpensesTable.tsx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/components/pages/expense/ExpensesTable.tsx b/src/components/pages/expense/ExpensesTable.tsx index 3a50f233..bbcb6c4e 100644 --- a/src/components/pages/expense/ExpensesTable.tsx +++ b/src/components/pages/expense/ExpensesTable.tsx @@ -263,11 +263,11 @@ const ExpensesTable = () => { }, }, { - accessorKey: 'expense_date', + accessorKey: 'transaction_date', header: 'Tanggal Pengajuan', cell: (props) => - props.row.original.expense_date - ? formatDate(props.row.original.expense_date, 'DD MMM YYYY') + props.row.original.transaction_date + ? formatDate(props.row.original.transaction_date, 'DD MMM YYYY') : '-', }, { From dc0fd7a3ed121ee43588b4fcf7ec116abd181cfd Mon Sep 17 00:00:00 2001 From: ValdiANS Date: Sun, 7 Dec 2025 15:00:25 +0700 Subject: [PATCH 3/3] chore: format code --- .gitlab-ci.yml | 2 -- 1 file changed, 2 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 91da62b9..c37bfd35 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -140,7 +140,6 @@ deploy:dev: environment: name: development url: https://dev-lti-erp.mbugroup.id - # ====== PRODUCTION ====== # build:production: # <<: *build_template @@ -163,4 +162,3 @@ deploy:dev: # environment: # name: production -