mirror of
https://github.com/wearepixel/laravel-cart.git
synced 2026-11-14 22:01:48 +00:00
feat: add TaxRule base class
This commit is contained in:
@@ -0,0 +1,48 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace Wearepixel\Cart\Tax;
|
||||||
|
|
||||||
|
use Wearepixel\Cart\CartCondition;
|
||||||
|
use Wearepixel\Cart\Contracts\CartConditionable;
|
||||||
|
use Wearepixel\Cart\Exceptions\InvalidTaxRuleException;
|
||||||
|
|
||||||
|
abstract class TaxRule implements CartConditionable
|
||||||
|
{
|
||||||
|
protected string $name;
|
||||||
|
|
||||||
|
protected string $value;
|
||||||
|
|
||||||
|
protected string $target = 'subtotal';
|
||||||
|
|
||||||
|
protected ?float $minimum = null;
|
||||||
|
|
||||||
|
protected ?float $maximum = null;
|
||||||
|
|
||||||
|
abstract public function isApplicable(): bool;
|
||||||
|
|
||||||
|
public function toCondition(): CartCondition
|
||||||
|
{
|
||||||
|
if (! $this->isApplicable()) {
|
||||||
|
throw new InvalidTaxRuleException("Tax rule [{$this->name}] is not applicable.");
|
||||||
|
}
|
||||||
|
|
||||||
|
$data = [
|
||||||
|
'name' => $this->name,
|
||||||
|
'type' => 'tax',
|
||||||
|
'value' => $this->value,
|
||||||
|
'target' => $this->target,
|
||||||
|
];
|
||||||
|
|
||||||
|
if ($this->minimum !== null) {
|
||||||
|
$data['minimum'] = $this->minimum;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($this->maximum !== null) {
|
||||||
|
$data['maximum'] = $this->maximum;
|
||||||
|
}
|
||||||
|
|
||||||
|
return new CartCondition($data);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,68 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
use Wearepixel\Cart\CartCondition;
|
||||||
|
use Wearepixel\Cart\Tax\TaxRule;
|
||||||
|
use Wearepixel\Cart\Exceptions\InvalidTaxRuleException;
|
||||||
|
|
||||||
|
class AuGst extends TaxRule
|
||||||
|
{
|
||||||
|
protected string $name = 'GST';
|
||||||
|
protected string $value = '10%';
|
||||||
|
|
||||||
|
public function isApplicable(): bool
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class NotApplicableTax extends TaxRule
|
||||||
|
{
|
||||||
|
protected string $name = 'VAT';
|
||||||
|
protected string $value = '20%';
|
||||||
|
|
||||||
|
public function isApplicable(): bool
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
describe('TaxRule', function () {
|
||||||
|
test('converts to a CartCondition', function () {
|
||||||
|
$condition = (new AuGst)->toCondition();
|
||||||
|
|
||||||
|
expect($condition)->toBeInstanceOf(CartCondition::class);
|
||||||
|
expect($condition->getName())->toBe('GST');
|
||||||
|
expect($condition->getValue())->toBe('10%');
|
||||||
|
expect($condition->getType())->toBe('tax');
|
||||||
|
expect($condition->getTarget())->toBe('subtotal');
|
||||||
|
});
|
||||||
|
|
||||||
|
test('isApplicable() returning false causes toCondition() to throw', function () {
|
||||||
|
expect(fn() => (new NotApplicableTax)->toCondition())
|
||||||
|
->toThrow(InvalidTaxRuleException::class);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('supports total as target', function () {
|
||||||
|
$tax = new class extends TaxRule {
|
||||||
|
protected string $name = 'Sales Tax';
|
||||||
|
protected string $value = '8%';
|
||||||
|
protected string $target = 'total';
|
||||||
|
public function isApplicable(): bool { return true; }
|
||||||
|
};
|
||||||
|
|
||||||
|
expect($tax->toCondition()->getTarget())->toBe('total');
|
||||||
|
});
|
||||||
|
|
||||||
|
test('supports minimum threshold', function () {
|
||||||
|
$tax = new class extends TaxRule {
|
||||||
|
protected string $name = 'Luxury Tax';
|
||||||
|
protected string $value = '15%';
|
||||||
|
protected ?float $minimum = 500.0;
|
||||||
|
public function isApplicable(): bool { return true; }
|
||||||
|
};
|
||||||
|
|
||||||
|
expect($tax->toCondition()->getMinimum())->toBe(500.0);
|
||||||
|
});
|
||||||
|
});
|
||||||
Reference in New Issue
Block a user