sum example

/** * Calculates discounts for delivery costs of cart * The calculation process will first determine if we have a delivery discount * (we use the same collector for all promotions) * after that it is calculating the shipping costs respecting absolute, fixed or percentage discounts * * @throws InvalidPriceDefinitionException * @throws CartException */
    public function calculate(LineItemCollection $discountLineItems, Cart $original, Cart $toCalculate, SalesChannelContext $context): void
    {
        $notDiscountedDeliveriesValue = $toCalculate->getDeliveries()->getShippingCosts()->sum()->getTotalPrice();

        // reduce discount lineItems if fixed price discounts are in collection         $checkedDiscountLineItems = $this->reduceDiscountLineItemsIfFixedPresent($discountLineItems);

        $exclusions = $this->buildExclusions($checkedDiscountLineItems);

        foreach ($checkedDiscountLineItems as $discountItem) {
            if ($notDiscountedDeliveriesValue <= 0.0) {
                continue;
            }

            
$this->calculateCollection($item->getChildren()$contextfn (LineItem $item) => $item->getPriceDefinition() instanceof CurrencyPriceDefinition);

            $this->calculateCollection($item->getChildren()$contextfn (LineItem $item) => $item->getPriceDefinition() instanceof PercentagePriceDefinition);

            if (!$this->validate($item)) {
                $scope->remove($item->getId());

                return;
            }

            $item->setPrice(
                $item->getChildren()->getPrices()->sum()
            );

            return;
        }

        $definition = $item->getPriceDefinition();

        if ($definition instanceof PercentagePriceDefinition) {
            $price = $this->percentageCalculator->calculate($definition->getPercentage()$scope->filterGoods()->getPrices()$context);
        } elseif ($definition instanceof CurrencyPriceDefinition) {
            $price = $this->currencyCalculator->calculate($definition->getPrice()$scope->filterGoods()->getPrices()$context);
        }
private function matches(Delivery $delivery, ShippingMethodPriceEntity $shippingMethodPrice, SalesChannelContext $context): bool
    {
        if ($shippingMethodPrice->getCalculationRuleId()) {
            return \in_array($shippingMethodPrice->getCalculationRuleId()$context->getRuleIds(), true);
        }

        $start = $shippingMethodPrice->getQuantityStart();
        $end = $shippingMethodPrice->getQuantityEnd();

        $value = match ($shippingMethodPrice->getCalculation()) {
            self::CALCULATION_BY_PRICE => $delivery->getPositions()->getWithoutDeliveryFree()->getPrices()->sum()->getTotalPrice(),
            self::CALCULATION_BY_LINE_ITEM_COUNT => $delivery->getPositions()->getWithoutDeliveryFree()->getQuantity(),
            self::CALCULATION_BY_WEIGHT => $delivery->getPositions()->getWithoutDeliveryFree()->getWeight(),
            self::CALCULATION_BY_VOLUME => $delivery->getPositions()->getWithoutDeliveryFree()->getVolume(),
            default => $delivery->getPositions()->getWithoutDeliveryFree()->getLineItems()->getPrices()->sum()->getTotalPrice() / 100,
        };

        // $end (optional) exclusive         return (!$start || FloatComparator::greaterThanOrEquals($value$start)) && (!$end || FloatComparator::lessThanOrEquals($value$end));
    }

    private function calculateShippingCosts(ShippingMethodEntity $shippingMethod, PriceCollection $priceCollection, LineItemCollection $calculatedLineItems, SalesChannelContext $context, ?CalculatedPrice $manualShippingCost = null): CalculatedPrice
    {
if (!$currency) {
            throw CartException::invalidPriceDefinition();
        }

        $value = $context->getTaxState() === CartPrice::TAX_STATE_GROSS ? $currency->getGross() : $currency->getNet();

        if ($currency->getCurrencyId() !== $context->getCurrencyId()) {
            $value *= $context->getCurrency()->getFactor();
        }

        $taxRules = $this->percentageTaxRuleBuilder->buildRules($prices->sum());

        $definition = new QuantityPriceDefinition($value$taxRules$quantity);

        return $this->priceCalculator->calculate($definition$context);
    }
}
/** * @internal */
    public function __construct(
        private readonly QuantityPriceCalculator $priceCalculator,
        private readonly PercentageTaxRuleBuilder $percentageTaxRuleBuilder
    ) {
    }

    public function calculate(float $price, PriceCollection $prices, SalesChannelContext $context, int $quantity = 1): CalculatedPrice
    {
        $taxRules = $this->percentageTaxRuleBuilder->buildRules($prices->sum());

        $definition = new QuantityPriceDefinition($price$taxRules$quantity);

        return $this->priceCalculator->calculate($definition$context);
    }
}
public function calculate(DiscountLineItem $discount, DiscountPackageCollection $packages, SalesChannelContext $context): DiscountCalculatorResult
    {
        /** @var AbsolutePriceDefinition $definition */
        $definition = $discount->getPriceDefinition();

        if (!$definition instanceof AbsolutePriceDefinition) {
            throw new InvalidPriceDefinitionException($discount->getLabel()$discount->getCode());
        }

        $affectedPrices = $packages->getAffectedPrices();

        $totalOriginalSum = $affectedPrices->sum()->getTotalPrice();
        $discountValue = -min(abs($definition->getPrice())$totalOriginalSum);

        $price = $this->priceCalculator->calculate(
            $discountValue,
            $affectedPrices,
            $context
        );

        $composition = $this->getCompositionItems(
            $discountValue,
            $packages,
            
private readonly PercentageTaxRuleBuilder $percentageTaxRuleBuilder
    ) {
    }

    /** * Provide a negative percentage value for discount or a positive percentage value for a surcharge * * @param float $percentage 10.00 for 10%, -10.0 for -10% */
    public function calculate(float $percentage, PriceCollection $prices, SalesChannelContext $context): CalculatedPrice
    {
        $price = $prices->sum();

        $discount = $this->round(
            $price->getTotalPrice() / 100 * $percentage,
            $context
        );

        $rules = $this->percentageTaxRuleBuilder->buildRules($price);

        $definition = new QuantityPriceDefinition($discount$rules, 1);

        return $this->priceCalculator->calculate($definition$context);
    }
case 'divide':
                case 'devide':
                    $builder->set("{$prefix}.$column", $builder->expr()->quot("{$prefix}.$column", $operationValue));
                    break;

                case 'multiply':
                    $builder->set("{$prefix}.$column", $builder->expr()->prod("{$prefix}.$column", $operationValue));
                    break;

                case 'add':
                    $builder->set("{$prefix}.$column", $builder->expr()->sum("{$prefix}.$column", $operationValue));
                    break;

                case 'subtract':
                    $builder->set("{$prefix}.$column", $builder->expr()->diff("{$prefix}.$column", $operationValue));
                    break;

                case 'append':
                    $builder->set("{$prefix}.$column", $builder->expr()->concat("{$prefix}.$column", $operationValue));
                    break;

                case 'prepend':
                    
            if (abs($actualDiscountPrice) > abs($maxValue)) {
                $calculatedPrice = $this->absolutePriceCalculator->calculate(
                    -abs($maxValue),
                    $affectedPrices,
                    $context
                );

                // now get the assessment basis of all line items                 // including their quantities that need to be discounted                 // based on our discount definition.                 // the basis might only be from a few items and quantities of the cart                 $assessmentBasis = $affectedPrices->sum()->getTotalPrice();

                // we have to get our new fictional and lower percentage.                 // we now calculate the percentage with MAX VALUE against our basis                 // to get the percentage to reach only the max value.                 $definedPercentage = ($maxValue / $assessmentBasis) * 100;
            }
        }

        $composition = $this->getCompositionItems($definedPercentage$packages);

        return new DiscountCalculatorResult($calculatedPrice$composition);
    }
$filter = $this->filter;
        if ($filter !== null) {
            $context = $scope->getSalesChannelContext();

            $goods = $goods->filter(static function DLineItem $lineItem) use ($filter$context) {
                $scope = new LineItemScope($lineItem$context);

                return $filter->match($scope);
            });
        }

        return RuleComparison::numeric($goods->getPrices()->sum()->getTotalPrice()$this->amount, $this->operator);
    }

    public function getConstraints(): array
    {
        return [
            'amount' => RuleConstraints::float(),
            'operator' => RuleConstraints::numericOperators(false),
        ];
    }
}
$this->createTestFixturePercentagePromotion($promotionId$code$percentage$maxValueGlobal$this->getContainer(), PromotionDiscountEntity::SCOPE_DELIVERY);

        $cart = $this->cartService->getCart($this->context->getToken()$this->context);

        // create product and add to cart         $cart = $this->addProduct($productId, 1, $cart$this->cartService, $this->context);

        // create promotion and add to cart         $cart = $this->addPromotionCode($code$cart$this->cartService, $this->context);

        static::assertEquals($expectedPrice$cart->getDeliveries()->getShippingCosts()->sum()->getTotalPrice());
        static::assertEquals($expectedTotal$cart->getPrice()->getTotalPrice());
        static::assertEquals(2, $cart->getLineItems()->count());
        static::assertEquals(2, $cart->getDeliveries()->count());
    }

    /** * This test verifies that we use the max value of our currency * instead of the global max value, if existing. * Thus we create a promotion with 50% for a 100 EUR price. * That would lead to 50 EUR for shipping costs, which we avoid by setting * a max global threshold of 40 EUR. * But for your currency, we use 30 EUR instead. * Our test needs to verify that we use 30 EUR, and end with a product sum of 70 EUR in the end. * * @group promotions */
$successCallback($order);
    }

    public static function creditNoteRendererCustomerGroupDataProvider(): \Generator
    {
        yield 'render credit_note with customer group gross' => [
            false,
            [7],
            [-100],
            function DOrderEntity $order): void {
                static::assertNotNull($lineItems = $order->getLineItems());
                $taxAmount = $lineItems->getPrices()->sum()->getCalculatedTaxes()->getAmount();

                static::assertEquals($order->getPrice()->getTotalPrice(), 100);
                static::assertEquals($order->getAmountNet(), -(-100 - $taxAmount));
            },
        ];

        yield 'render credit_note with customer group net' => [
            true,
            [7],
            [-100],
            function DOrderEntity $order): void {
                
$filter = $this->filter;
        if ($filter !== null) {
            $context = $scope->getSalesChannelContext();

            $promotions = $promotions->filter(static function DLineItem $lineItem) use ($filter$context) {
                $scope = new LineItemScope($lineItem$context);

                return $filter->match($scope);
            });
        }

        $promotionAmount = $promotions->getPrices()->sum()->getTotalPrice() * -1;

        return RuleComparison::numeric($promotionAmount$this->amount, $this->operator);
    }

    public function getConstraints(): array
    {
        return [
            'amount' => RuleConstraints::float(),
            'operator' => RuleConstraints::numericOperators(false),
        ];
    }

    
$composition = $this->getCompositionItems(
            $discountPrice->getTotalPrice(),
            $packages,
            $affectedPrices
        );

        return new DiscountCalculatorResult($discountPrice$composition);
    }

    private function getTotalDiscountDiffSum(float $fixedPackagePrice, DiscountPackageCollection $packages, PriceCollection $affectedPrices): float
    {
        $totalProductPrices = $affectedPrices->sum()->getTotalPrice();

        return $totalProductPrices - ($fixedPackagePrice * $packages->count());
    }

    /** * @return array<DiscountCompositionItem> */
    private function getCompositionItems(float $discountValue, DiscountPackageCollection $packages, PriceCollection $affectedPrices): array
    {
        $totalOriginalSum = $affectedPrices->sum()->getTotalPrice();

        


    public function setTransactions(TransactionCollection $transactions): self
    {
        $this->transactions = $transactions;

        return $this;
    }

    public function getShippingCosts(): CalculatedPrice
    {
        return $this->deliveries->getShippingCosts()->sum();
    }

    public function getData(): CartDataCollection
    {
        if (!$this->data) {
            $this->data = new CartDataCollection();
        }

        return $this->data;
    }

    
Home | Imprint | This part of the site doesn't use cookies.