Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 10 additions & 8 deletions Block/Sales/Total/Surcharge.php
Original file line number Diff line number Diff line change
Expand Up @@ -35,31 +35,33 @@ public function initTotals(): self
}

$amount = (float)$source->getDataUsingMethod('two_surcharge_amount');
$taxAmount = (float)$source->getDataUsingMethod('two_surcharge_tax_amount');
if ($amount <= 0) {
return $this;
}

// Display gross (net + tax) so the row matches the invoice/order grand
// total math; tax is otherwise hidden in the Tax line.
$value = $amount + $taxAmount;
$baseAmount = (float)$source->getDataUsingMethod('base_two_surcharge_amount');
$baseTax = (float)$source->getDataUsingMethod('base_two_surcharge_tax_amount');
$baseValue = $baseAmount + $baseTax;
// Display the NET surcharge — its VAT lives in the Tax line, exactly as
// on checkout. The net rows (items + shipping + tax + net surcharge)
// then reconcile to the grand total. (Showing gross here double-
// presents the surcharge VAT — once in the Tax line, once in this row.)
$value = $amount;
$baseValue = (float)$source->getDataUsingMethod('base_two_surcharge_amount');

$label = $source->getDataUsingMethod('two_surcharge_description');
if (!$label) {
$label = (string)__('Two Surcharge');
}

// Place the surcharge row directly above the Tax line — the surcharge
// is part of the tax base, so net surcharge then tax reads naturally
// (and matches checkout ordering).
$parent->addTotalBefore(
new DataObject([
'code' => 'two_surcharge',
'value' => $value,
'base_value' => $baseValue,
'label' => $label,
]),
'grand_total'
'tax'
);

return $this;
Expand Down
5 changes: 3 additions & 2 deletions Model/Pdf/Total/Surcharge.php
Original file line number Diff line number Diff line change
Expand Up @@ -25,15 +25,16 @@ public function getTotalsForDisplay()
{
$source = $this->getSource();
$amount = (float)$source->getDataUsingMethod('two_surcharge_amount');
$tax = (float)$source->getDataUsingMethod('two_surcharge_tax_amount');
if ($amount <= 0) {
return [];
}

$label = $source->getDataUsingMethod('two_surcharge_description')
?: (string)__('Two Surcharge');

$value = $this->getAmountPrefix() . $this->getOrder()->formatPriceTxt($amount + $tax);
// NET surcharge — its VAT is shown in the Tax line, matching the
// on-screen totals, the checkout, and the grand total.
$value = $this->getAmountPrefix() . $this->getOrder()->formatPriceTxt($amount);

return [[
'amount' => $value,
Expand Down
13 changes: 13 additions & 0 deletions Test/Stubs/DataObject.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,19 @@ class DataObject
/** @var array */
protected $_data = [];

public function __construct(array $data = [])
{
$this->_data = $data;
}

public function getData($key = '')
{
if ($key === '') {
return $this->_data;
}
return $this->_data[$key] ?? null;
}

public function __call($method, $args)
{
$prefix = substr($method, 0, 3);
Expand Down
9 changes: 9 additions & 0 deletions Test/Stubs/SalesModels.php
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,15 @@ public function getData($key = '', $index = null)
return $this->_data[$key] ?? null;
}

/**
* Mirrors Magento\Framework\DataObject::getDataUsingMethod for the simple
* data-bag case the totals block exercises (no custom getter override).
*/
public function getDataUsingMethod($key, $args = null)
{
return $this->_data[$key] ?? null;
}

public function hasData($key = ''): bool
{
if ($key === '') {
Expand Down
102 changes: 102 additions & 0 deletions Test/Unit/Block/Sales/Total/SurchargeTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
<?php
/**
* Copyright © Two.inc All rights reserved.
* See COPYING.txt for license details.
*/
declare(strict_types=1);

namespace Two\Gateway\Test\Unit\Block\Sales\Total;

use Magento\Sales\Model\Order;
use PHPUnit\Framework\TestCase;
use Two\Gateway\Block\Sales\Total\Surcharge;

/**
* The order/invoice/creditmemo totals row for the surcharge must display the
* NET surcharge — its VAT belongs in the Tax line (as on checkout). Showing
* the gross value double-presents the VAT and stops the totals rows summing to
* the grand total. (ABN-443 follow-up.)
*/
class SurchargeTest extends TestCase
{
private const NET = 23.99;
private const TAX = 5.16;

private function makeSource(): Order
{
$s = new Order();
$s->setData('two_surcharge_amount', self::NET);
$s->setData('base_two_surcharge_amount', self::NET);
$s->setData('two_surcharge_tax_amount', self::TAX);
$s->setData('base_two_surcharge_tax_amount', self::TAX);
$s->setData('two_surcharge_description', 'Zakelijk op Rekening - 60 dagen');
return $s;
}

/**
* Build the block with its framework collaborators stubbed: a parent
* totals block exposing the source and capturing the registered row.
*/
private function makeBlock(Order $source, \stdClass $capture): Surcharge
{
$parent = new class($source, $capture) {
private $src;
private $cap;
public function __construct($src, $cap)
{
$this->src = $src;
$this->cap = $cap;
}
public function getSource()
{
return $this->src;
}
public function addTotalBefore($total, $before)
{
$this->cap->total = $total;
$this->cap->before = $before;
return $this;
}
};

return new class($parent) extends Surcharge {
private $p;
public function __construct($p)
{
$this->p = $p;
}
public function getParentBlock()
{
return $this->p;
}
};
}

public function testDisplaysSurchargeNetNotGross(): void
{
$capture = new \stdClass();
$block = $this->makeBlock($this->makeSource(), $capture);

$block->initTotals();

$this->assertNotNull($capture->total ?? null, 'a surcharge totals row must be registered');
$this->assertEqualsWithDelta(
self::NET,
(float)$capture->total->getValue(),
0.0001,
'surcharge row must show NET; its VAT belongs in the Tax line (matches checkout)'
);
$this->assertEqualsWithDelta(
self::NET,
(float)$capture->total->getData('base_value'),
0.0001,
'base_value must also be NET'
);
$this->assertSame('Zakelijk op Rekening - 60 dagen', $capture->total->getLabel());
$this->assertSame(
'tax',
$capture->before,
'surcharge row must sit directly above the Tax line (it contributes to the tax base)'
);
}
}
71 changes: 71 additions & 0 deletions Test/Unit/Model/Pdf/Total/SurchargeTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
<?php
/**
* Copyright © Two.inc All rights reserved.
* See COPYING.txt for license details.
*/
declare(strict_types=1);

namespace Two\Gateway\Test\Unit\Model\Pdf\Total;

use Magento\Sales\Model\Order;
use PHPUnit\Framework\TestCase;
use Two\Gateway\Model\Pdf\Total\Surcharge;

/**
* The invoice/credit-memo PDF surcharge row must show the NET surcharge —
* its VAT belongs in the Tax line, matching the on-screen totals and the
* grand total. (ABN-443 follow-up.)
*/
class SurchargeTest extends TestCase
{
public function testPdfShowsNetSurchargeNotGross(): void
{
$source = new Order();
$source->setData('two_surcharge_amount', 23.99);
$source->setData('two_surcharge_tax_amount', 5.16);
$source->setData('two_surcharge_description', 'Zakelijk op Rekening - 60 dagen');

$orderFmt = new class {
public function formatPriceTxt($v)
{
return number_format((float)$v, 2, '.', '');
}
};

$block = new class($source, $orderFmt) extends Surcharge {
private $s;
private $o;
public function __construct($s, $o)
{
$this->s = $s;
$this->o = $o;
}
public function getSource()
{
return $this->s;
}
public function getOrder()
{
return $this->o;
}
public function getAmountPrefix()
{
return '';
}
public function getFontSize()
{
return 7;
}
};

$rows = $block->getTotalsForDisplay();

$this->assertCount(1, $rows);
$this->assertSame(
'23.99',
$rows[0]['amount'],
'PDF surcharge row must show NET (23.99), not gross (29.15)'
);
$this->assertSame('Zakelijk op Rekening - 60 dagen:', $rows[0]['label']);
}
}