TaxRule example

public static function serializerProvider()
    {
        $rule = new AndRule([
            new OrRule([
                new CurrencyRule(CurrencyRule::OPERATOR_EQ, [Defaults::CURRENCY]),
            ]),
            new CurrencyRule(CurrencyRule::OPERATOR_EQ, [Defaults::CURRENCY]),
        ]);

        yield 'Test quantity price definition' => [
            new QuantityPriceDefinition(100, new TaxRuleCollection([new TaxRule(19, 50)new TaxRule(7, 50)]), 3),
        ];

        yield 'Test absolute price definition' => [
            new AbsolutePriceDefinition(20, $rule),
        ];

        yield 'Test percentage price definition' => [
            new PercentagePriceDefinition(-20, $rule),
        ];

        yield 'Test currency price definition' => [
            
static::assertSame($expected->getTotalPrice()$cartPrice->getTotalPrice());
        static::assertEquals($expected->getTaxRules()$cartPrice->getTaxRules());
        static::assertEquals($expected->getCalculatedTaxes()$cartPrice->getCalculatedTaxes());
        static::assertSame($expected->getNetPrice()$cartPrice->getNetPrice());
    }

    /** * @return list<array{0: CartPrice, 1: PriceCollection}> */
    public static function calculateAmountForNetDeliveriesProvider(): array
    {
        $highTax = new TaxRuleCollection([new TaxRule(19)]);
        $lowTax = new TaxRuleCollection([new TaxRule(7)]);

        return [
            [
                new CartPrice(19.5, 19.5, 19.5, new CalculatedTaxCollection()new TaxRuleCollection(), CartPrice::TAX_STATE_FREE),
                new PriceCollection([
                    new CalculatedPrice(19.50, 19.50, new CalculatedTaxCollection([new CalculatedTax(3.11, 19, 19.5)])$highTax),
                ]),
            ][
                new CartPrice(33.7, 33.7, 33.7, new CalculatedTaxCollection()new TaxRuleCollection(), CartPrice::TAX_STATE_FREE),
                new PriceCollection([
                    
'calculated' => false,
        ]);

        static::assertEquals(
            new CalculatedPrice(
                $expectedPrice,
                $expectedPrice,
                new CalculatedTaxCollection([
                    new CalculatedTax($expectedTax$tax['taxRate']$expectedPrice),
                ]),
                new TaxRuleCollection([
                    new TaxRule($tax['taxRate'], 100),
                ])
            ),
            $price
        );
    }

    /** * @param array{id: string, name: string, taxRate: float, areaRules?: list<array<string, mixed>>} $tax * * @dataProvider dataProviderTestNetToNet */
    

        $tax = $this->taxRules->get($taxId);

        if ($tax === null || $tax->getRules() === null) {
            throw new TaxNotFoundException($taxId);
        }

        if ($tax->getRules()->first() !== null) {
            // NEXT-21735 - This is covered randomly             // @codeCoverageIgnoreStart             return new TaxRuleCollection([
                new TaxRule($tax->getRules()->first()->getTaxRate(), 100),
            ]);
            // @codeCoverageIgnoreEnd         }

        return new TaxRuleCollection([
            new TaxRule($tax->getTaxRate(), 100),
        ]);
    }

    public function getCustomer(): ?CustomerEntity
    {
        
$lineItemPrice = $calculator->calculate($priceDefinition$context);

        static::assertEquals($expected$lineItemPrice);
    }

    /** * @return list<array{0: CalculatedPrice, 1: QuantityPriceDefinition}> */
    public static function netPrices(): array
    {
        $highTaxRules = new TaxRuleCollection([new TaxRule(19)]);

        return [
            [
                new CalculatedPrice(13.44, 13.44, new CalculatedTaxCollection([new CalculatedTax(2.55, 19, 13.44)])$highTaxRules),
                new QuantityPriceDefinition(13.436974789916, $highTaxRules),
            ],
        ];
    }

    /** * @return list<array{0: CalculatedPrice, 1: QuantityPriceDefinition}> */
class TaxRuleCollectionTest extends TestCase
{
    public function testCollectionIsCountable(): void
    {
        $collection = new TaxRuleCollection();
        static::assertCount(0, $collection);
    }

    public function testCountReturnsCorrectValue(): void
    {
        $collection = new TaxRuleCollection([
            new TaxRule(19),
            new TaxRule(18),
            new TaxRule(17),
        ]);
        static::assertCount(3, $collection);
    }

    public function testTaxRateIsUsedAsUniqueIdentifier(): void
    {
        $collection = new TaxRuleCollection([
            new TaxRule(19),
            new TaxRule(19),
            

        if ($value === null) {
            return null;
        }

        $decoded = parent::decode($field$value);
        if (!\is_array($decoded)) {
            return null;
        }

        $taxRules = array_map(
            fn (array $tax) => new TaxRule(
                (float) $tax['taxRate'],
                (float) $tax['percentage']
            ),
            $decoded['taxRules']
        );

        $calculatedTaxes = array_map(
            fn (array $tax) => new CalculatedTax(
                (float) $tax['tax'],
                (float) $tax['taxRate'],
                (float) $tax['price']
            ),

        ];

        $this->getContainer()->get('product.repository')
            ->create([$product], Context::createDefaultContext());

        $this->addTaxDataToSalesChannel($this->context, $tax);

        $taxForCustomItem = 20;

        $productLineItem = new LineItem($productId, LineItem::PRODUCT_LINE_ITEM_TYPE, $productId, 1);
        $taxRulesCustomItem = new TaxRuleCollection([new TaxRule($taxForCustomItem)]);
        $customLineItem = (new LineItem($customItemId, LineItem::CUSTOM_LINE_ITEM_TYPE, $customItemId, 1))
            ->setLabel('custom')
            ->setPriceDefinition(new QuantityPriceDefinition(200, $taxRulesCustomItem, 2));

        $creditLineItem = (new LineItem($creditId, LineItem::CREDIT_LINE_ITEM_TYPE, $creditId, 1))
            ->setLabel('credit')
            ->setPriceDefinition(new AbsolutePriceDefinition(-100));

        $cart->addLineItems(new LineItemCollection([$productLineItem$customLineItem$creditLineItem]));

        $calculated = $this->processor->process($cart$this->context, new CartBehavior());

        
return $this->isCalculated;
    }

    public function setQuantity(int $quantity): void
    {
        $this->quantity = $quantity;
    }

    public static function fromArray(array $data): self
    {
        $taxRules = array_map(
            fn (array $tax) => new TaxRule(
                (float) $tax['taxRate'],
                (float) $tax['percentage']
            ),
            $data['taxRules']
        );

        $self = new self(
            (float) $data['price'],
            new TaxRuleCollection($taxRules),
            \array_key_exists('quantity', $data) ? $data['quantity'] : 1
        );

        
/** * @return array<mixed> */
    private function calculatePrice(float $price, float $taxRate, int $quantity, string $output, bool $preCalculated): array
    {
        $calculator = $this->grossCalculator;
        if ($output === 'net') {
            $calculator = $this->netCalculator;
        }

        $taxRules = new TaxRuleCollection([new TaxRule($taxRate)]);

        $definition = new QuantityPriceDefinition($price$taxRules$quantity);
        $definition->setIsCalculated($preCalculated);

        $config = new CashRoundingConfig(50, 0.01, true);

        $calculated = $calculator->calculate($definition$config);

        return json_decode((string) json_encode($calculated, \JSON_PRESERVE_ZERO_FRACTION), true, 512, \JSON_THROW_ON_ERROR);
    }
}
use Shopware\Core\Checkout\Cart\Tax\Struct\TaxRuleCollection;
use Shopware\Core\Framework\Log\Package;

/** * @internal */
#[Package('checkout')] class HighTaxes extends TaxRuleCollection
{
    public function __construct()
    {
        parent::__construct([new TaxRule(19)]);
    }
}


    /** * @dataProvider taxStateWillBeUsedProvider */
    public function testTaxStateWillBeUsed(Entity $product, string $state, float $expected): void
    {
        $context = $this->createMock(SalesChannelContext::class);
        $context->method('getCurrencyId')->willReturn(Defaults::CURRENCY);
        $context->method('getContext')->willReturn(Context::createDefaultContext());
        $context->method('getTaxState')->willReturn($state);
        $context->method('buildTaxRules')->willReturn(new TaxRuleCollection([new TaxRule(10)]));
        $context->method('getItemRounding')->willreturn(new CashRoundingConfig(2, 0.01, true));

        $this->calculator->calculate([$product]$context);

        $price = $product->get('calculatedPrice');

        static::assertInstanceOf(CalculatedPrice::class$price);

        static::assertEquals($expected$price->getTotalPrice());
    }

    
new GrossPriceCalculator(new TaxCalculator()new CashRounding()),
            new NetPriceCalculator(new TaxCalculator()new CashRounding())
        );

        $stubs = new ScriptPriceStubs(
            // not necessary for this test             $this->createMock(Connection::class),
            $quantityCalculator,
            new PercentagePriceCalculator(new CashRounding()$quantityCalculatornew PercentageTaxRuleBuilder()),
        );

        $original = new CalculatedPrice(10, 10, new CalculatedTaxCollection()new TaxRuleCollection(new TaxRuleCollection([new TaxRule(10)])));

        // mock context to simulate currency and tax states         $context = $this->createMock(SalesChannelContext::class);

        // currency key will be provided, we want to test different currencies are taking into account         $context->expects(static::any())->method('getCurrencyId')->willReturn($ids->get($currencyKey));

        // we also want to test different tax states (gross/net)         $context->expects(static::any())->method('getTaxState')->willReturn($taxState);
        $context->expects(static::any())->method('getItemRounding')->willReturn(new CashRoundingConfig(2, 0.01, true));

        

        return [
            'small-discounts' => [self::getSmallDiscountCase()],
            '100%' => [self::getOneHundredPercentageDiscountCase()],
        ];
    }

    private static function getSmallDiscountCase(): AbsoluteCalculation
    {
        $calculator = self::createQuantityPriceCalculator();

        $definition = new QuantityPriceDefinition(30, new TaxRuleCollection([new TaxRule(19)]));
        $price1 = $calculator->calculate($definition, Generator::createSalesChannelContext());

        $definition = new QuantityPriceDefinition(30, new TaxRuleCollection([new TaxRule(7)]));
        $price2 = $calculator->calculate($definition, Generator::createSalesChannelContext());

        return new AbsoluteCalculation(
            -6,
            new CalculatedPrice(
                -6,
                -6,
                new CalculatedTaxCollection([
                    
$context->expects(static::atLeastOnce())->method('getContext')->willReturn($baseContext);
        $context->expects(static::atLeastOnce())->method('getRuleIds')->willReturn([]);
        $context->expects(static::atLeastOnce())->method('getShippingMethod')->willReturn($shippingMethod);

        $firstLineItem = $this->createLineItem(
            new DeliveryInformation(10, 12.0, false, null, $this->deliveryTime),
            new CalculatedPrice(
                10,
                10,
                new CalculatedTaxCollection([new CalculatedTax(5, 19, 5)]),
                new TaxRuleCollection([new TaxRule(19)])
            )
        );

        $secondLineItem = $this->createLineItem(
            new DeliveryInformation(10, 12.0, false, null, $this->deliveryTime),
            new CalculatedPrice(
                10,
                10,
                new CalculatedTaxCollection([new CalculatedTax(5, 7, 5)]),
                new TaxRuleCollection([new TaxRule(7)])
            )
        );
Home | Imprint | This part of the site doesn't use cookies.