From ac702397a6301c22dda0138eb1839b8d1d214889 Mon Sep 17 00:00:00 2001 From: Deon George Date: Sat, 17 May 2025 22:19:31 +1000 Subject: [PATCH] Fixes for invoice rounding, where invoice total was different from reporting --- app/Models/Account.php | 23 +++++++---------------- app/Models/Invoice.php | 2 +- app/Models/InvoiceItem.php | 32 +++++++++++++++++++++++++++++--- app/Models/Payment.php | 2 +- 4 files changed, 38 insertions(+), 21 deletions(-) diff --git a/app/Models/Account.php b/app/Models/Account.php index b4d4198..8d7ca14 100644 --- a/app/Models/Account.php +++ b/app/Models/Account.php @@ -329,11 +329,11 @@ class Account extends Model implements IDs ->from( (new Payment) ->select([ - 'invoice_id', DB::raw('0 as item'), DB::raw('0 as tax'), DB::raw('0 as discount'), DB::raw('0 as item_total'), + 'invoice_id', DB::raw('SUM(amount) AS payments'), DB::raw('SUM(fees_amt) AS payment_fees'), ]) @@ -342,22 +342,13 @@ class Account extends Model implements IDs ->where('payment_items.active',TRUE) ->groupBy(['payment_items.invoice_id']) ->union( - (new InvoiceItem) - ->select([ - 'invoice_id', - DB::raw('ROUND(CAST(SUM(quantity*price_base) AS NUMERIC),2) AS item'), - DB::raw('ROUND(CAST(SUM(COALESCE(amount,0)) AS NUMERIC),2) AS tax'), - DB::raw('ROUND(CAST(SUM(COALESCE(invoice_items.discount_amt,0)) AS NUMERIC),2) AS discount'), - DB::raw('ROUND(CAST(SUM(ROUND(CAST(quantity*(price_base-COALESCE(invoice_items.discount_amt,0)) AS NUMERIC),2))+SUM(ROUND(CAST(COALESCE(amount,0) AS NUMERIC),2)) AS NUMERIC),2) AS item_total'), - DB::raw('0 as payments'), - DB::raw('0 as payment_fees'), - ]) - ->leftjoin('invoice_item_taxes',['invoice_item_taxes.invoice_item_id'=>'invoice_items.id']) + InvoiceItem::invoice_items() + ->addSelect('invoice_items.invoice_id') + ->addSelect(DB::raw('0 as payments')) + ->addSelect(DB::raw('0 as payment_fees')) ->rightjoin('invoices',['invoices.id'=>'invoice_items.invoice_id']) - ->where('invoice_items.active',TRUE) - ->where(fn($query)=>$query->where('invoice_item_taxes.active',TRUE)->orWhereNull('invoice_item_taxes.active')) ->where('invoices.active',TRUE) - ->groupBy(['invoice_items.invoice_id']), + ->groupBy(['invoice_items.invoice_id']) ),'p') ->join('invoices',['invoices.id'=>'invoice_id']) ->when(($all === FALSE),fn($query)=>$query->where('invoices.account_id',$this->id)) @@ -384,7 +375,7 @@ class Account extends Model implements IDs ->join('payment_items',['payment_items.invoice_id'=>'invoices.id']) ->join('payments',['payments.id'=>'payment_items.payment_id']) ->addSelect(DB::raw('max(paid_at) as _paid_at')) - ->havingRaw('ROUND(CAST(SUM(item_total)-COALESCE(invoices.discount_amt,0)-SUM(payments) AS NUMERIC),2) <= 0'); + ->havingRaw('ROUND(CAST(SUM(item_total)-COALESCE(invoices.discount_amt,0)-SUM(payments) AS NUMERIC),2) = 0'); } /** diff --git a/app/Models/Invoice.php b/app/Models/Invoice.php index 7655b45..db499b5 100644 --- a/app/Models/Invoice.php +++ b/app/Models/Invoice.php @@ -422,7 +422,7 @@ class Invoice extends Model implements IDs */ public function getDueAttribute(): float { - return sprintf('%3.2f',$this->getTotalAttribute()-$this->getPaidAttribute()); + return round($this->getTotalAttribute()-$this->getPaidAttribute(),2); } /** diff --git a/app/Models/InvoiceItem.php b/app/Models/InvoiceItem.php index afc59ad..0c0a262 100644 --- a/app/Models/InvoiceItem.php +++ b/app/Models/InvoiceItem.php @@ -2,9 +2,11 @@ namespace App\Models; +use Illuminate\Database\Eloquent\Builder; use Illuminate\Database\Eloquent\Collection; use Illuminate\Database\Eloquent\Model; use Illuminate\Support\Arr; +use Illuminate\Support\Facades\DB; use Leenooks\Carbon as LeenooksCarbon; use App\Traits\PushNew; @@ -68,6 +70,30 @@ class InvoiceItem extends Model }); } + public static function invoice_items(): Builder + { + // Choose your select tag and group by tag + return (new InvoiceItem) + ->select([ + //'invoice_id', + DB::raw('ROUND(CAST(SUM(quantity*price_base) AS NUMERIC),2) AS item'), + DB::raw('ROUND(CAST(SUM(COALESCE(amount,0)) AS NUMERIC),2) AS tax'), + DB::raw('ROUND(CAST(SUM(COALESCE(invoice_items.discount_amt,0)) AS NUMERIC),2) AS discount'), + DB::raw('ROUND(CAST(SUM(ROUND(CAST(ROUND(CAST(quantity*(price_base-COALESCE(invoice_items.discount_amt,0)) AS NUMERIC),2)+COALESCE(amount,0) AS NUMERIC),2)) AS NUMERIC),2) AS item_total'), + //DB::raw('0 as payments'), + //DB::raw('0 as payment_fees'), + ]) + ->leftjoin('invoice_item_taxes',['invoice_item_taxes.invoice_item_id'=>'invoice_items.id']) + //->rightjoin('invoices',['invoices.id'=>'invoice_items.invoice_id']) + ->where('invoice_items.active',TRUE) + ->where(fn($query)=>$query + ->where('invoice_item_taxes.active',TRUE) + ->orWhereNull('invoice_item_taxes.active')) + //->where('invoices.active',TRUE) + //->groupBy(['invoice_id']) + ; + } + /* RELATIONS */ public function invoice() @@ -144,7 +170,7 @@ class InvoiceItem extends Model */ public function getSubTotalAttribute(): float { - return sprintf('%3.2f',$this->quantity * ($this->price_base - $this->discount_amt)); + return round($this->quantity*($this->price_base-$this->discount_amt),2); } /** @@ -154,7 +180,7 @@ class InvoiceItem extends Model */ public function getTaxAttribute(): float { - return sprintf('%3.2f',$this->taxes->sum('amount')); + return round($this->taxes->sum('amount'),2); } /** @@ -164,7 +190,7 @@ class InvoiceItem extends Model */ public function getTotalAttribute(): float { - return sprintf('%3.2f',$this->getSubTotalAttribute()+$this->getTaxAttribute()); + return round($this->getSubTotalAttribute()+$this->getTaxAttribute(),2); } /* METHODS */ diff --git a/app/Models/Payment.php b/app/Models/Payment.php index 7d1ebdc..472f592 100644 --- a/app/Models/Payment.php +++ b/app/Models/Payment.php @@ -130,6 +130,6 @@ class Payment extends Model implements IDs */ public function getTotalAttribute(): float { - return sprintf('%3.2f',$this->total_amt); + return round($this->total_amt,2); } } \ No newline at end of file