aureuserp/aureuserp · error · Exception

Invoice total positive TAX percentages must equal 100% (got

Error message

Invoice total positive TAX percentages must equal 100% (got {$positive}%).

What it means

Thrown by TaxResource::validateRepartitionData() when the sum of positive factor_percent values over TAX rows on the invoice side does not equal exactly 100.00. The comparison uses bccomp(number_format($positive, 2, '.', ''), '100', 2), so the sum must total 100.00 at two decimal places — a tax must fully allocate 100% of its computed amount across the positive tax repartition rows.

Source

Thrown at plugins/webkul/accounts/src/Filament/Resources/TaxResource.php:106

                ! $refLine ||
                $invLine['repartition_type'] !== $refLine['repartition_type'] ||
                $invPercent !== $refPercent

            ) {
                throw new Exception('Line #'.($index + 1).' does not match between Invoice and Refund.');
            }
        }

        $positive = $invoice
            ->filter(fn ($l) => $l['repartition_type'] === 'tax' && is_numeric($l['factor_percent'] ?? null) && $l['factor_percent'] > 0)
            ->sum(fn ($l) => (float) $l['factor_percent']);

        $negative = $invoice
            ->filter(fn ($l) => $l['repartition_type'] === 'tax' && is_numeric($l['factor_percent'] ?? null) && $l['factor_percent'] < 0)
            ->sum(fn ($l) => (float) $l['factor_percent']);

        if (bccomp(number_format($positive, 2, '.', ''), '100', 2) !== 0) {
            throw new Exception("Invoice total positive TAX percentages must equal 100% (got {$positive}%).");
        }

        if ($negative && bccomp(number_format($negative, 2, '.', ''), '-100', 2) !== 0) {
            throw new Exception("Invoice total negative TAX percentages must equal -100% (got {$negative}%).");
        }
    }
}

View on GitHub (pinned to bd7cbeeb0c)

Solutions

  1. Adjust positive TAX factor percents so they total exactly 100.00 (use 33.34 + 33.33 + 33.33 for thirds).
  2. Remove unused TAX rows instead of zeroing their factor — a 0% row is harmless to the sum but usually means a leftover row.
  3. For taxes with deductions, keep positive rows summing to 100 and put the deduction in negative rows (see the -100 check).

Example fix

// before (33.33 x 3 = 99.99)
$invoiceLines = [
    ['repartition_type' => 'base', 'factor_percent' => null],
    ['repartition_type' => 'tax', 'factor_percent' => 33.33],
    ['repartition_type' => 'tax', 'factor_percent' => 33.33],
    ['repartition_type' => 'tax', 'factor_percent' => 33.33],
];

// after (33.34 + 33.33 + 33.33 = 100.00)
$invoiceLines = [
    ['repartition_type' => 'base', 'factor_percent' => null],
    ['repartition_type' => 'tax', 'factor_percent' => 33.34],
    ['repartition_type' => 'tax', 'factor_percent' => 33.33],
    ['repartition_type' => 'tax', 'factor_percent' => 33.33],
];
Defensive patterns

Strategy: validation

Validate before calling

$positive = collect($invoiceLines)
    ->filter(fn ($l) => ($l['repartition_type'] ?? null) === 'tax' && ($l['factor_percent'] ?? 0) > 0)
    ->sum(fn ($l) => (float) $l['factor_percent']);
if (bccomp(number_format($positive, 2, '.', ''), '100', 2) !== 0) {
    // adjust factors to total exactly 100.00 before saving
}

Type guard

function positiveTaxFactorsTotal100(array $lines): bool
{
    $sum = collect($lines)
        ->filter(fn ($l) => ($l['repartition_type'] ?? null) === 'tax' && ($l['factor_percent'] ?? 0) > 0)
        ->sum(fn ($l) => (float) $l['factor_percent']);
    return bccomp(number_format($sum, 2, '.', ''), '100', 2) === 0;
}

Try / catch

catch (Exception $e) when (str_contains($e->getMessage(), 'positive TAX percentages')) { /* read the reported total from the message and rebalance */ }

Prevention

When it happens

Trigger: Saving a tax whose TAX rows sum to something other than 100: three rows of 33.33 (sums to 99.99), a split of 50/40/10 (sums to 100 but a typo makes 50/40/5), or a single row of 50 because a second row was removed after splitting.

Common situations: Rounding splits like 33.33 x 3 instead of 33.34 + 33.33 + 33.33; partial allocation in the mistaken belief the remaining percent can be left unassigned; currency-style percentages (e.g. 21.5 total plus a 50% deduction where the negative side is handled separately — positive rows must still total 100).

Related errors


AI-assisted analysis of aureuserp/aureuserp@bd7cbeeb0c (2026-08-21). Data as JSON: /api/errors/28038e911dcec7a0. Report an issue: GitHub.