# easy-invoice/2.4.0/includes/Traits/PaymentCalculationTrait.php

Easy Invoice – Invoice Generator, PDF Quotes &amp; Payments, version 2.4.0. 152 lines.

- Page: https://pluginprobe.com/plugins/easy-invoice/2.4.0/code/includes/Traits/PaymentCalculationTrait.php
- Raw: https://pluginprobe.com/plugins/easy-invoice/2.4.0/raw/includes/Traits/PaymentCalculationTrait.php
- Modified: 2026-09-15T12:31:20+00:00

Line numbers below start at 1. Link to a line or a range by appending a fragment to the
page URL, for example `https://pluginprobe.com/plugins/easy-invoice/2.4.0/code/includes/Traits/PaymentCalculationTrait.php#L10-L20`.

```php
<?php

namespace EasyInvoice\Traits;

/**
 * Trait for calculating payment totals
 * 
 * This trait provides shared functionality for calculating total payments
 * for invoices across different payment gateways.
 */
trait PaymentCalculationTrait
{
    /**
     * Calculate total payments for a specific invoice
     *
     * @param int $invoice_id
     * @return float
     */
    private function calculateTotalPaymentsForInvoice($invoice_id): float
    {
        // Get all payment records for this invoice
        $payments = get_posts([
            'post_type' => 'easy_invoice_payment',
            'post_status' => 'publish',
            'meta_query' => [
                [
                    'key' => '_invoice_id',
                    'value' => $invoice_id,
                    'compare' => '='
                ],
                [
                    'key' => '_status',
                    'value' => 'completed',
                    'compare' => '='
                ]
            ],
            'numberposts' => -1
        ]);
        
        $total_payments = 0.0;
        
        foreach ($payments as $payment) {
            $amount = get_post_meta($payment->ID, '_amount', true);
            if ($amount && is_numeric($amount)) {
                $total_payments += floatval($amount);
            }
        }
        
        return $total_payments;
    }
    
    /**
     * Amount of the most recently completed payment on an invoice.
     *
     * @param int $invoice_id
     * @return float Zero when there is none.
     */
    private function latestCompletedPaymentAmount($invoice_id): float
    {
        $payments = get_posts([
            'post_type'   => 'easy_invoice_payment',
            'post_status' => 'publish',
            'numberposts' => 1,
            'orderby'     => 'date',
            'order'       => 'DESC',
            'meta_query'  => [
                ['key' => '_invoice_id', 'value' => $invoice_id, 'compare' => '='],
                ['key' => '_status', 'value' => 'completed', 'compare' => '='],
            ],
        ]);
        return $payments ? (float) get_post_meta($payments[0]->ID, '_amount', true) : 0.0;
    }

    /**
     * Check if invoice should be marked as paid based on total payments
     *
     * @param int $invoice_id
     * @param \EasyInvoice\Models\Invoice $invoice
     * @return bool
     */
    private function shouldMarkInvoiceAsPaid($invoice_id, $invoice): bool
    {
        $total_payments = $this->calculateTotalPaymentsForInvoice($invoice_id);
        $invoice_total = (float) $invoice->getTotal();
        // Credit notes reduce what is owed, so they count towards settlement.
        $credited = class_exists('\\EasyInvoice\\Services\\InvoiceBalance') ? \EasyInvoice\Services\InvoiceBalance::credited((int) $invoice_id) : 0.0;

        return $total_payments + $credited + 0.005 >= $invoice_total;
    }
    
    /**
     * Update invoice status to paid only if total payments are sufficient
     *
     * @param int $invoice_id
     * @param \EasyInvoice\Models\Invoice $invoice
     * @param string $gateway_name
     * @return bool True if status was updated, false otherwise
     */
    private function updateInvoiceStatusIfPaid($invoice_id, $invoice, $gateway_name = ''): bool
    {
        if ($this->shouldMarkInvoiceAsPaid($invoice_id, $invoice)) {
            $invoice->setStatus('paid');
            $invoice->save();
            
            // Log the status update
            if (method_exists($this, 'log')) {
                $this->log("Invoice #$invoice_id status updated to 'paid' - payments complete", 'info');
            } else {
                error_log("Easy Invoice: Invoice #$invoice_id status updated to 'paid' - payments complete");
            }
            
            // Trigger hook when invoice is marked as paid (for email notifications, etc.)
            // Get payment method and transaction ID from the most recent payment
            $payment_method = get_post_meta($invoice_id, '_payment_method', true) ?: $gateway_name ?: 'online';
            $transaction_id = get_post_meta($invoice_id, '_transaction_id', true) ?: '';
            // The receipt names the payment that settled the invoice, which
            // is the whole total only when it was paid in one go.
            $payment_amount = $this->latestCompletedPaymentAmount($invoice_id) ?: $invoice->getTotal();
            
            do_action('easy_invoice_payment_completed', $invoice_id, $invoice, [
                'payment_method' => $payment_method,
                'gateway_name' => $gateway_name,
                'transaction_id' => $transaction_id,
                'amount' => $payment_amount
            ]);
            
            return true;
        } else {
            // Something has been received but not everything: say so, unless
            // the invoice is in a state that should not change (draft,
            // cancelled) or already reads as part paid.
            $current = strtolower((string) $invoice->getStatus());
            $received = $this->calculateTotalPaymentsForInvoice($invoice_id);
            if (in_array($current, ['available', 'unpaid', 'overdue'], true) && $received > 0) {
                $invoice->setStatus('partial');
                $invoice->save();
            }
            if ($received > 0) {
                /** This action is documented in includes/Controllers/PaymentController.php */
                do_action('easy_invoice_payment_received', $invoice_id, $invoice, [
                    'payment_method' => get_post_meta($invoice_id, '_payment_method', true) ?: $gateway_name ?: 'online',
                    'gateway_name'   => $gateway_name,
                    'transaction_id' => get_post_meta($invoice_id, '_transaction_id', true) ?: '',
                    'amount'         => $this->latestCompletedPaymentAmount($invoice_id),
                ]);
            }

            return false;
        }
    }
}

```
