From 6d6d1271263bd29f6076efefcabb40066d78e5a5 Mon Sep 17 00:00:00 2001 From: Firman Ramdhani <33869609+firmanramdhani@users.noreply.github.com> Date: Thu, 1 Oct 2026 13:42:01 +0700 Subject: [PATCH] fix: accurately calculate user balances based on order and payment status --- src/app/(app)/my-orders/[id]/page.tsx | 6 ++++-- src/app/actions.ts | 15 ++++++++++++++- src/components/PiutangManager.tsx | 16 +++++++++++++++- src/components/ReportByPersonGrid.tsx | 22 +++++++++++++++++++--- 4 files changed, 52 insertions(+), 7 deletions(-) diff --git a/src/app/(app)/my-orders/[id]/page.tsx b/src/app/(app)/my-orders/[id]/page.tsx index b9a67d2..22451cf 100644 --- a/src/app/(app)/my-orders/[id]/page.tsx +++ b/src/app/(app)/my-orders/[id]/page.tsx @@ -506,11 +506,13 @@ function SubmissionRow({ useEffect(() => { if (currentBalance !== undefined) { let balanceBeforeThisOrder = currentBalance - if (sub.payment_status === 'LUNAS') { + const shouldCountBill = sub.bill != null && (sub.order.status === 'CLOSE' || sub.payment_status === 'LUNAS') + if (shouldCountBill) { const diff = (sub.paid_amount || 0) - (sub.bill || 0) balanceBeforeThisOrder -= diff } else { - balanceBeforeThisOrder += sub.saldo_used || 0 + const diff = (sub.paid_amount || 0) - (sub.saldo_used || 0) + balanceBeforeThisOrder -= diff } setAvailableBalance(Math.max(0, balanceBeforeThisOrder)) } diff --git a/src/app/actions.ts b/src/app/actions.ts index 82ea379..b42bb82 100644 --- a/src/app/actions.ts +++ b/src/app/actions.ts @@ -438,6 +438,19 @@ export async function processBulkPayment(data: { // Sort by order date ascending (oldest first) submissions.sort((a, b) => new Date(a.order.date).getTime() - new Date(b.order.date).getTime()) + // Reverse the effect of these submissions on currentBalance to get true available balance + if (data.use_balance) { + for (const sub of submissions) { + const shouldCountBill = sub.bill != null && (sub.order.status === 'CLOSE' || sub.payment_status === 'LUNAS') + if (shouldCountBill) { + currentBalance -= ((sub.paid_amount || 0) - (sub.bill || 0)) + } else { + currentBalance -= ((sub.paid_amount || 0) - (sub.saldo_used || 0)) + } + } + currentBalance = Math.max(0, currentBalance) + } + let remainingBalance = currentBalance let remainingCash = data.cash_amount let totalAvailable = remainingBalance + remainingCash @@ -948,7 +961,7 @@ export async function getPiutangSummary(creator_id: string) { select: { id: true, name: true, photo: true }, }, order: { - select: { id: true, title: true, date: true }, + select: { id: true, title: true, date: true, status: true }, }, }, orderBy: { diff --git a/src/components/PiutangManager.tsx b/src/components/PiutangManager.tsx index 7a75df2..d07a24e 100644 --- a/src/components/PiutangManager.tsx +++ b/src/components/PiutangManager.tsx @@ -96,7 +96,21 @@ export default function PiutangManager({ creatorId }: { creatorId: string }) { u.user.name.toLowerCase().includes(searchQuery.toLowerCase()) ) - const targetUserBalance = balancesData.find((b) => b.user.id === target.userId)?.amount || 0 + let rawTargetUserBalance = balancesData.find((b) => b.user.id === target.userId)?.amount || 0 + const userObj = data.find((u) => u.user.id === target.userId) + + if (userObj) { + userObj.submissions.forEach((sub: any) => { + const shouldCountBill = sub.bill != null && (sub.order.status === 'CLOSE' || sub.payment_status === 'LUNAS') + if (shouldCountBill) { + rawTargetUserBalance -= ((sub.paid_amount || 0) - (sub.bill || 0)) + } else { + rawTargetUserBalance -= ((sub.paid_amount || 0) - (sub.saldo_used || 0)) + } + }) + } + + const targetUserBalance = Math.max(0, rawTargetUserBalance) if (loading) { return ( diff --git a/src/components/ReportByPersonGrid.tsx b/src/components/ReportByPersonGrid.tsx index 0e2fcfa..1ca4202 100644 --- a/src/components/ReportByPersonGrid.tsx +++ b/src/components/ReportByPersonGrid.tsx @@ -92,7 +92,7 @@ export default function ReportByPersonGrid({ const unpaid = Math.max(0, bill - paid) obj.totalPiutang += unpaid obj.totalPaid += paid - obj.submissions.push({ ...sub, orderTitle: order.title, orderDate: order.date, paid, unpaid }) + obj.submissions.push({ ...sub, orderTitle: order.title, orderDate: order.date, orderStatus: order.status, paid, unpaid }) }) }) @@ -148,8 +148,24 @@ export default function ReportByPersonGrid({ } } - const targetUserBalanceObj = balancesData.find((b) => b.user.id === target.userId) - const targetUserBalance = targetUserBalanceObj ? targetUserBalanceObj.amount : 0 + let rawTargetUserBalance = balancesData.find((b) => b.user.id === target.userId)?.amount || 0 + const userObj = userList.find((u) => u.user.id === target.userId) + + if (userObj) { + userObj.submissions.forEach((sub: any) => { + // Only add back submissions that are part of the payment target + if (target.ids.includes(sub.id)) { + const shouldCountBill = sub.bill != null && (sub.orderStatus === 'CLOSE' || sub.payment_status === 'LUNAS') + if (shouldCountBill) { + rawTargetUserBalance -= ((sub.paid_amount || 0) - (sub.bill || 0)) + } else { + rawTargetUserBalance -= ((sub.paid_amount || 0) - (sub.saldo_used || 0)) + } + } + }) + } + + const targetUserBalance = Math.max(0, rawTargetUserBalance) return ( <>