From 138ad6a7c91f8c590919958707d518c1b2c38ff1 Mon Sep 17 00:00:00 2001 From: randy-ar Date: Sat, 17 Jan 2026 15:59:08 +0700 Subject: [PATCH 01/53] hotfix(FE): change select input component to disabled --- .../product/detail/InventoryProductDetail.tsx | 2 +- .../pages/marketing/MarketingTable.tsx | 50 ++++++++++++++++++- .../marketing/detail/MarketingDetail.tsx | 47 ++++++++++++++++- .../pages/marketing/form/MarketingForm.tsx | 4 +- 4 files changed, 98 insertions(+), 5 deletions(-) diff --git a/src/components/pages/inventory/product/detail/InventoryProductDetail.tsx b/src/components/pages/inventory/product/detail/InventoryProductDetail.tsx index 42c177d7..39609b06 100644 --- a/src/components/pages/inventory/product/detail/InventoryProductDetail.tsx +++ b/src/components/pages/inventory/product/detail/InventoryProductDetail.tsx @@ -91,7 +91,7 @@ const InventoryProductDetail = ({ : {inventoryProduct?.tax - ? formatCurrency(inventoryProduct?.tax) + ? formatNumber(inventoryProduct?.tax) + '%' : '-'} diff --git a/src/components/pages/marketing/MarketingTable.tsx b/src/components/pages/marketing/MarketingTable.tsx index 467c2e00..8f1a6cf9 100644 --- a/src/components/pages/marketing/MarketingTable.tsx +++ b/src/components/pages/marketing/MarketingTable.tsx @@ -16,7 +16,7 @@ import { TableRowSizeSelector } from '@/components/table/TableRowSizeSelector'; import { TableToolbar } from '@/components/table/TableToolbar'; import { ROWS_OPTIONS } from '@/config/constant'; import { isResponseError, isResponseSuccess } from '@/lib/api-helper'; -import { cn, formatCurrency, formatDate } from '@/lib/helper'; +import { cn, formatCurrency, formatDate, formatTitleCase } from '@/lib/helper'; import { MarketingApi, SalesOrderApi, @@ -33,6 +33,7 @@ import RequirePermission from '@/components/helper/RequirePermission'; import { useAuth } from '@/services/hooks/useAuth'; import { CustomerApi, ProductApi } from '@/services/api/master-data'; import { MARKETING_APPROVAL_LINE } from '@/config/approval-line'; +import Badge from '@/components/Badge'; const RowsOptionsMenu = ({ type = 'dropdown', @@ -520,8 +521,53 @@ const MarketingTable = () => { }, }, { - accessorKey: 'latest_approval.step_name', + accessorKey: 'approval.step_name', header: 'Status', + cell: (props) => { + const approval = props.row.original.latest_approval; + const isRejected = approval?.action == 'REJECTED'; + const isApproved = approval?.action == 'APPROVED'; + return ( + + + {isRejected + ? 'Ditolak' + : formatTitleCase(approval?.step_name || '')} + + ); + }, }, { accessorKey: 'customer.name', diff --git a/src/components/pages/marketing/detail/MarketingDetail.tsx b/src/components/pages/marketing/detail/MarketingDetail.tsx index 12ebda20..91e02928 100644 --- a/src/components/pages/marketing/detail/MarketingDetail.tsx +++ b/src/components/pages/marketing/detail/MarketingDetail.tsx @@ -16,6 +16,7 @@ import { formatCurrency, formatDate, formatNumber, + formatTitleCase, formatVechicleNumber, } from '@/lib/helper'; import { @@ -34,6 +35,7 @@ import toast from 'react-hot-toast'; import SalesOrderExport from '@/components/pages/marketing/pdf/SalesOrderExport'; import DeliveryOrderExport from '@/components/pages/marketing/pdf/DeliveryOrderExport'; import RequirePermission from '@/components/helper/RequirePermission'; +import Badge from '@/components/Badge'; const MarketingDetail = ({ initialValues, @@ -121,6 +123,10 @@ const MarketingDetail = ({ ); }; + const approval = initialValues?.latest_approval; + const isRejected = approval?.action == 'REJECTED'; + const isApproved = approval?.action == 'APPROVED'; + return ( <>
@@ -230,7 +236,46 @@ const MarketingDetail = ({ Status : - {initialValues?.latest_approval?.step_name} + + + + {isRejected + ? 'Ditolak' + : formatTitleCase(approval?.step_name || '')} + + Tanggal Penjualan diff --git a/src/components/pages/marketing/form/MarketingForm.tsx b/src/components/pages/marketing/form/MarketingForm.tsx index be4367cb..f20a44b5 100644 --- a/src/components/pages/marketing/form/MarketingForm.tsx +++ b/src/components/pages/marketing/form/MarketingForm.tsx @@ -621,7 +621,9 @@ const MarketingForm = ({ isClearable placeholder='Pilih Pelanggan' isDisabled={ - formType === 'add_deliver' || formType === 'edit_deliver' + formType === 'add_deliver' || + formType === 'edit_deliver' || + formType === 'edit' } /> Date: Sat, 17 Jan 2026 16:16:34 +0700 Subject: [PATCH 02/53] refactor(FE): Rename price to unit_price in customer payments --- .../report/finance/export/CustomerPaymentExportPDF.tsx | 4 ++-- .../report/finance/export/CustomerPaymentExportXLSX.tsx | 6 +++--- .../pages/report/finance/tab/CustomerPaymentTab.tsx | 8 ++++---- src/types/api/report/customer-payment.d.ts | 2 +- 4 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/components/pages/report/finance/export/CustomerPaymentExportPDF.tsx b/src/components/pages/report/finance/export/CustomerPaymentExportPDF.tsx index 9b1fd640..aa04b4f0 100644 --- a/src/components/pages/report/finance/export/CustomerPaymentExportPDF.tsx +++ b/src/components/pages/report/finance/export/CustomerPaymentExportPDF.tsx @@ -300,7 +300,7 @@ const createPDFDocument = (params: CustomerPaymentExportPDFParams) => { Rata-Rata - Harga Awal + Harga/Unit Harga Akhir @@ -378,7 +378,7 @@ const createPDFDocument = (params: CustomerPaymentExportPDFParams) => { {formatNumber(item.average_weight)} - {formatCurrency(item.price)} + {formatCurrency(item.unit_price)} {formatCurrency(item.final_price)} diff --git a/src/components/pages/report/finance/export/CustomerPaymentExportXLSX.tsx b/src/components/pages/report/finance/export/CustomerPaymentExportXLSX.tsx index 3fb21488..830df633 100644 --- a/src/components/pages/report/finance/export/CustomerPaymentExportXLSX.tsx +++ b/src/components/pages/report/finance/export/CustomerPaymentExportXLSX.tsx @@ -38,7 +38,7 @@ export const generateCustomerPaymentExcel = ( 'Ekor/Qty': formatNumber(item.qty || 0), 'Berat (Kg)': formatNumber(item.weight || 0), AVG: formatNumber(item.average_weight || 0), - 'Harga Awal': formatCurrency(item.price || 0), + 'Harga/Unit': formatCurrency(item.unit_price || 0), 'Harga Akhir': formatCurrency(item.final_price || 0), Total: formatCurrency(item.total_price || 0), Pembayaran: formatCurrency(item.payment_amount || 0), @@ -62,7 +62,7 @@ export const generateCustomerPaymentExcel = ( 'Ekor/Qty': formatNumber(customerReport.summary.total_qty || 0), 'Berat (Kg)': formatNumber(customerReport.summary.total_weight || 0), AVG: '', - 'Harga Awal': '', + 'Harga/Unit': '', 'Harga Akhir': formatCurrency( customerReport.summary.total_final_amount || 0 ), @@ -89,7 +89,7 @@ export const generateCustomerPaymentExcel = ( { wch: 10 }, // Ekor/Qty { wch: 12 }, // Berat { wch: 10 }, // AVG - { wch: 15 }, // Harga Awal + { wch: 15 }, // Harga/Unit { wch: 15 }, // Harga Akhir { wch: 15 }, // Total { wch: 15 }, // Pembayaran diff --git a/src/components/pages/report/finance/tab/CustomerPaymentTab.tsx b/src/components/pages/report/finance/tab/CustomerPaymentTab.tsx index ef748b5f..0e3afe40 100644 --- a/src/components/pages/report/finance/tab/CustomerPaymentTab.tsx +++ b/src/components/pages/report/finance/tab/CustomerPaymentTab.tsx @@ -405,12 +405,12 @@ const CustomerPaymentTab = () => { ), }, { - id: 'price', - header: 'Harga Awal', - accessorKey: 'price', + id: 'unit_price', + header: 'Harga/Unit', + accessorKey: 'unit_price', enableSorting: false, cell: (props) => { - const value = props.row.original.price; + const value = props.row.original.unit_price; return
{formatCurrency(value)}
; }, footer: () => ( diff --git a/src/types/api/report/customer-payment.d.ts b/src/types/api/report/customer-payment.d.ts index 9169c99b..90834cdc 100644 --- a/src/types/api/report/customer-payment.d.ts +++ b/src/types/api/report/customer-payment.d.ts @@ -11,7 +11,7 @@ export type CustomerPaymentRow = { qty: number; weight: number; average_weight: number; - price: number; + unit_price: number; final_price: number; total_price: number; payment_amount: number; From 36da05890a4376ef38eb1bbba5b6f3d033ccfa56 Mon Sep 17 00:00:00 2001 From: randy-ar Date: Sat, 17 Jan 2026 16:45:56 +0700 Subject: [PATCH 03/53] hotfix(FE): fixing failed test scenario in module finance --- .../pages/finance/FinanceDetail.tsx | 41 ++++---- src/components/pages/finance/FinanceTable.tsx | 99 +++++++++++-------- .../pages/finance/add/FormFinanceAdd.tsx | 41 ++++++-- .../FormFinanceAddInitialBalance.schema.ts | 8 +- .../FormFinanceAddInitialBalance.tsx | 29 ++++-- .../add/injection/FormFinanceInjection.tsx | 20 +++- 6 files changed, 151 insertions(+), 87 deletions(-) diff --git a/src/components/pages/finance/FinanceDetail.tsx b/src/components/pages/finance/FinanceDetail.tsx index 03291420..76d2d1a0 100644 --- a/src/components/pages/finance/FinanceDetail.tsx +++ b/src/components/pages/finance/FinanceDetail.tsx @@ -34,7 +34,7 @@ const FinanceDetail = ({ finance }: { finance: Finance }) => { }, { label: 'Pihak', - value: finance.party.id ? finance.party.name : '-', + value: finance.party?.id ? finance.party?.name : '-', }, { label: 'Tanggal', @@ -56,25 +56,21 @@ const FinanceDetail = ({ finance }: { finance: Finance }) => { }, { label: 'Nomor Rekening', - value: `${finance.bank.alias} - ${finance.bank.account_number} - ${finance.bank.owner}`, + value: `${finance.bank?.alias} - ${finance.bank?.account_number} - ${finance.bank?.owner}`, }, { - label: `Rekening ${formatTitleCase(finance.party.type)}`, - value: finance.party.account_number, + label: `Rekening ${formatTitleCase(finance.party?.type)}`, + value: finance.party?.account_number, }, { label: 'Nominal', - value: formatCurrency(finance.expense_amount), - }, - { - label: 'Sisa', - value: formatCurrency(finance.income_amount), + value: formatCurrency(finance.nominal), }, ].filter((item) => { // Hide party account number row if transaction type is INJECTION if ( FINANCE_INJECTION_STATUS.includes(finance.transaction_type) && - item.label === `Rekening ${formatTitleCase(finance.party.type)}` + item.label === `Rekening ${formatTitleCase(finance.party?.type)}` ) { return false; } @@ -148,18 +144,19 @@ const FinanceDetail = ({ finance }: { finance: Finance }) => {
- {FINANCE_TRANSACTION_STATUS.includes(finance.transaction_type) && ( - - - - )} + {FINANCE_TRANSACTION_STATUS.includes(finance.transaction_type) && + finance.party?.type !== 'SUPPLIER' && ( + + + + )} {FINANCE_INITIAL_BALANCE_STATUS.includes(finance.transaction_type) && ( - - )} + ) && + props.row.original.party?.type !== 'SUPPLIER' && ( + + + + )} {FINANCE_INITIAL_BALANCE_STATUS.includes( props.row.original.transaction_type @@ -194,20 +199,25 @@ const FinanceTable = () => { // ===== Options ===== const transactionTypeOptions = useMemo(() => { - return [ - { label: 'Transfer', value: 'TRANSFER' }, - { label: 'Cash', value: 'CASH' }, - { label: 'Card', value: 'CARD' }, - { label: 'Cheque', value: 'CHEQUE' }, - { label: 'Saldo', value: 'SALDO' }, - ]; - }, []); - const partyTypeOptions = useMemo(() => { return [ { label: 'Customer', value: 'CUSTOMER' }, { label: 'Supplier', value: 'SUPPLIER' }, ]; }, []); + const { + options: partyTypeOptions, + isLoadingOptions: partyTypeIsLoadingOptions, + setInputValue: partyTypeInputValue, + loadMore: partyTypeLoadMore, + } = useSelect( + selectedTransactionType + ? selectedTransactionType.value === 'CUSTOMER' + ? CustomerApi.basePath + : SupplierApi.basePath + : '', + 'id', + 'name' + ); const sortByOptions = useMemo(() => { return [ { label: 'Tanggal Pembayaran', value: 'payment_date' }, @@ -336,10 +346,10 @@ const FinanceTable = () => { }, { header: 'Pihak', - accessorFn: (finance: Finance) => finance.party.name, + accessorFn: (finance: Finance) => finance.party?.name, cell: (props: CellContext) => { - if (props.row.original.party.id) { - return {props.row.original.party.name}; + if (props.row.original.party?.id) { + return {props.row.original.party?.name}; } return {'-'}; }, @@ -360,12 +370,12 @@ const FinanceTable = () => { { header: 'Bank', accessorFn: (finance: Finance) => - `${finance.bank.alias} - ${finance.bank.account_number} - ${finance.bank.owner}`, + `${finance.bank?.alias} - ${finance.bank?.account_number} - ${finance.bank?.owner}`, }, { header: 'Pengeluaran (Rp)', accessorFn: (finance: Finance) => - formatCurrency(finance.expense_amount), + formatCurrency(Math.abs(finance.expense_amount)), }, { header: 'Pemasukan (Rp)', @@ -468,25 +478,41 @@ const FinanceTable = () => {
+ ({ label: - bankRawData.data.find((data) => data.id === bank.value) + bankRawData.data.find((data) => data.id === bank?.value) ?.alias + ' - ' + - bankRawData.data.find((data) => data.id === bank.value) + bankRawData.data.find((data) => data.id === bank?.value) ?.account_number + ' - ' + - bankRawData.data.find((data) => data.id === bank.value) + bankRawData.data.find((data) => data.id === bank?.value) ?.owner, - value: bank.value, + value: bank?.value, })) : [] } @@ -497,13 +523,6 @@ const FinanceTable = () => { onMenuScrollToBottom={bankLoadMore} isClearable /> - { const router = useRouter(); + const [serverErrorMessage, setServerErrorMessage] = useState(''); + const [isSupplier, setIsSupplier] = useState( + initialValues?.party?.type === 'SUPPLIER' + ); // ===== Formik ===== const formikInitialValues = useMemo((): FinanceFormValues => { return { party_type_option: FINANCE_PARTY_TYPE_OPTIONS.find( - (option) => option.value === initialValues?.party.type + (option) => option.value === initialValues?.party?.type ) || null, party_id_option: initialValues?.party ? { - label: initialValues?.party.name || '', - value: initialValues?.party.id || 0, + label: initialValues?.party?.name || '', + value: initialValues?.party?.id || 0, } : null, payment_date: initialValues?.payment_date || '', @@ -72,11 +78,11 @@ const FormFinanceAdd = ({ ) || null, bank_id_option: initialValues?.bank ? { - label: initialValues.bank.name, - value: initialValues.bank.id, + label: initialValues?.bank?.name, + value: initialValues?.bank?.id, } : null, - party_account_number: initialValues?.party.account_number || '', + party_account_number: initialValues?.party?.account_number || '', reference_number: initialValues?.reference_number || '', nominal: initialValues?.nominal.toString() || '', notes: initialValues?.notes || '', @@ -153,6 +159,7 @@ const FormFinanceAdd = ({ if (isResponseError(response)) { toast.error(response.message); + setServerErrorMessage(response.message); return; } @@ -168,6 +175,7 @@ const FormFinanceAdd = ({ if (isResponseError(response)) { toast.error(response.message); + setServerErrorMessage(response.message); return; } @@ -207,6 +215,7 @@ const FormFinanceAdd = ({ ? formik.errors.party_type_option : '' } + isDisabled={type === 'edit' || isSupplier} required isClearable /> @@ -245,7 +254,7 @@ const FormFinanceAdd = ({ } required isClearable - isDisabled={!formik.values.party_type_option?.value} + isDisabled={!formik.values.party_type_option?.value || isSupplier} />