Skip to content

Commit

Permalink
Add bonus points deduct
Browse files Browse the repository at this point in the history
  • Loading branch information
patrick477 committed Aug 22, 2019
1 parent 320feac commit b312169
Show file tree
Hide file tree
Showing 12 changed files with 94 additions and 9 deletions.
61 changes: 58 additions & 3 deletions src/Assigner/BonusPointsAssigner.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,13 @@

use BitBag\SyliusBonusPointsPlugin\Calculator\DelegatingBonusPointsStrategyCalculatorInterface;
use BitBag\SyliusBonusPointsPlugin\Checker\Eligibility\BonusPointsStrategyEligibilityCheckerInterface;
use BitBag\SyliusBonusPointsPlugin\Entity\AdjustmentInterface;
use BitBag\SyliusBonusPointsPlugin\Entity\BonusPointsInterface;
use BitBag\SyliusBonusPointsPlugin\Entity\BonusPointsStrategyInterface;
use BitBag\SyliusBonusPointsPlugin\Entity\CustomerBonusPointsInterface;
use BitBag\SyliusBonusPointsPlugin\Repository\BonusPointsStrategyRepositoryInterface;
use Doctrine\ORM\EntityManagerInterface;
use Sylius\Component\Core\Distributor\ProportionalIntegerDistributorInterface;
use Sylius\Component\Core\Model\CustomerInterface;
use Sylius\Component\Core\Model\OrderInterface;
use Sylius\Component\Core\Model\OrderItemInterface;
Expand Down Expand Up @@ -42,6 +45,9 @@ final class BonusPointsAssigner implements BonusPointsAssignerInterface
/** @var FactoryInterface */
private $customerBonusPointsFactory;

/** @var ProportionalIntegerDistributorInterface */
private $proportionalIntegerDistributor;

public function __construct(
DelegatingBonusPointsStrategyCalculatorInterface $delegatingBonusPointsStrategyCalculator,
BonusPointsStrategyEligibilityCheckerInterface $bonusPointsStrategyEligibilityChecker,
Expand All @@ -50,7 +56,8 @@ public function __construct(
FactoryInterface $bonusPointsFactory,
EntityManagerInterface $bonusPointsEntityManager,
RepositoryInterface $customerBonusPointsRepository,
FactoryInterface $customerBonusPointsFactory
FactoryInterface $customerBonusPointsFactory,
ProportionalIntegerDistributorInterface $proportionalIntegerDistributor
) {
$this->delegatingBonusPointsStrategyCalculator = $delegatingBonusPointsStrategyCalculator;
$this->bonusPointsStrategyEligibilityChecker = $bonusPointsStrategyEligibilityChecker;
Expand All @@ -60,6 +67,7 @@ public function __construct(
$this->bonusPointsEntityManager = $bonusPointsEntityManager;
$this->customerBonusPointsRepository = $customerBonusPointsRepository;
$this->customerBonusPointsFactory = $customerBonusPointsFactory;
$this->proportionalIntegerDistributor = $proportionalIntegerDistributor;
}

public function assign(OrderInterface $order): void
Expand All @@ -68,12 +76,25 @@ public function assign(OrderInterface $order): void

$bonusPointsTotal = 0;

/** @var BonusPointsStrategyInterface $bonusPointsStrategy */
foreach ($bonusPointsStrategies as $bonusPointsStrategy) {
if ($this->delegatingBonusPointsStrategyCalculator->isPerOrderItem($bonusPointsStrategy)) {
if ($bonusPointsStrategy->isDeductBonusPoints()) {
$splitAmountOrderItems = $this->getProportionalIntegerToDeduct(
$bonusPointsStrategy,
$order->getItems()->toArray(),
$order->getAdjustmentsTotal(AdjustmentInterface::ORDER_BONUS_POINTS_ADJUSTMENT)
);
}

/** @var OrderItemInterface $orderItem */
foreach ($order->getItems() as $orderItem) {
if ($this->bonusPointsStrategyEligibilityChecker->isEligible($orderItem, $bonusPointsStrategy)) {
$bonusPointsTotal += $this->delegatingBonusPointsStrategyCalculator->calculate($orderItem, $bonusPointsStrategy);
$bonusPointsTotal += $this->delegatingBonusPointsStrategyCalculator->calculate(
$orderItem,
$bonusPointsStrategy,
$bonusPointsStrategy->isDeductBonusPoints() ? $splitAmountOrderItems[$orderItem->getId()] : 0
);
}
}
} else {
Expand All @@ -87,7 +108,11 @@ public function assign(OrderInterface $order): void
}

if (true === $status) {
$bonusPointsTotal += $this->delegatingBonusPointsStrategyCalculator->calculate($order, $bonusPointsStrategy);
$bonusPointsTotal += $this->delegatingBonusPointsStrategyCalculator->calculate(
$order,
$bonusPointsStrategy,
$order->getAdjustmentsTotal(AdjustmentInterface::ORDER_BONUS_POINTS_ADJUSTMENT)
);
}
}
}
Expand Down Expand Up @@ -125,4 +150,34 @@ private function getCustomerBonusPoints(CustomerInterface $customer): CustomerBo

return $customerBonusPoints;
}

private function getProportionalIntegerToDeduct(BonusPointsStrategyInterface $bonusPointsStrategy, array $orderItems, int $bonusPointsAmount): array
{
/** @var OrderItemInterface[] $itemsEligible */
$itemsEligible = [];

foreach ($orderItems as $orderItem) {
if ($this->bonusPointsStrategyEligibilityChecker->isEligible($orderItem, $bonusPointsStrategy)) {
$itemsEligible[] = $orderItem;
}
}

$totals = [];

foreach ($itemsEligible as $item) {
$totals[] = $item->getTotal();
}

$splitAmount = $this->proportionalIntegerDistributor->distribute($totals, $bonusPointsAmount);

$splitAmountOrderItems = [];

$i = 0;

foreach ($itemsEligible as $item) {
$splitAmountOrderItems[$item->getId()] = $splitAmount[$i++];
}

return $splitAmountOrderItems;
}
}
2 changes: 1 addition & 1 deletion src/Calculator/BonusPointsStrategyCalculatorInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

interface BonusPointsStrategyCalculatorInterface
{
public function calculate($subject, array $configuration): int;
public function calculate($subject, array $configuration, int $amountToDeduct = 0): int;

public function isPerOrderItem(): bool;

Expand Down
4 changes: 2 additions & 2 deletions src/Calculator/DelegatingBonusPointsStrategyCalculator.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,12 @@ public function __construct(ServiceRegistryInterface $registry)
$this->registry = $registry;
}

public function calculate($subject, BonusPointsStrategyInterface $bonusPointsStrategy): int
public function calculate($subject, BonusPointsStrategyInterface $bonusPointsStrategy, int $amountToDeduct = 0): int
{
/** @var BonusPointsStrategyCalculatorInterface $calculator */
$calculator = $this->registry->get($bonusPointsStrategy->getCalculatorType());

return $calculator->calculate($subject, $bonusPointsStrategy->getCalculatorConfiguration());
return $calculator->calculate($subject, $bonusPointsStrategy->getCalculatorConfiguration(), $amountToDeduct);
}

public function isPerOrderItem(BonusPointsStrategyInterface $bonusPointsStrategy): bool
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@

interface DelegatingBonusPointsStrategyCalculatorInterface
{
public function calculate($subject, BonusPointsStrategyInterface $bonusPointsStrategy): int;
public function calculate($subject, BonusPointsStrategyInterface $bonusPointsStrategy, int $amountToDeduct): int;

public function isPerOrderItem(BonusPointsStrategyInterface $bonusPointsStrategy): bool;
}
10 changes: 8 additions & 2 deletions src/Calculator/PerOrderItemPercentageCalculator.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@

final class PerOrderItemPercentageCalculator implements BonusPointsStrategyCalculatorInterface
{
public function calculate($subject, array $configuration): int
public function calculate($subject, array $configuration, int $amountToDeduct = 0): int
{
/** @var OrderItemInterface $subject */
Assert::isInstanceOf($subject, OrderItemInterface::class);
Expand All @@ -20,7 +20,13 @@ public function calculate($subject, array $configuration): int

$configuration = $configuration[$order->getChannel()->getCode()];

return intval($subject->getTotal() * $configuration['percentToCalculatePoints']);
$total = $subject->getTotal();

if ($amountToDeduct < 0) {
$total += $amountToDeduct;
}

return intval(round($total * $configuration['percentToCalculatePoints']));
}

public function isPerOrderItem(): bool
Expand Down
13 changes: 13 additions & 0 deletions src/Entity/BonusPointsStrategy.php
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,9 @@ class BonusPointsStrategy implements BonusPointsStrategyInterface
/** @var Collection|BonusPointsStrategyRuleInterface[] */
protected $rules;

/** @var bool */
protected $isDeductBonusPoints = false;

public function __construct()
{
$this->createdAt = new \DateTime();
Expand Down Expand Up @@ -111,4 +114,14 @@ public function removeRule(BonusPointsStrategyRuleInterface $rule): void
$rule->setBonusPointsStrategy(null);
$this->rules->removeElement($rule);
}

public function isDeductBonusPoints(): bool
{
return $this->isDeductBonusPoints;
}

public function setIsDeductBonusPoints(bool $isDeductBonusPoints): void
{
$this->isDeductBonusPoints = $isDeductBonusPoints;
}
}
4 changes: 4 additions & 0 deletions src/Entity/BonusPointsStrategyInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -41,4 +41,8 @@ public function removeRule(BonusPointsStrategyRuleInterface $rule): void;
public function getCalculatorType(): ?string;

public function setCalculatorType(?string $calculatorType): void;

public function isDeductBonusPoints(): bool;

public function setIsDeductBonusPoints(bool $isDeductBonusPoints): void;
}
3 changes: 3 additions & 0 deletions src/Form/Type/BonusPointsStrategyType.php
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,9 @@ public function buildForm(FormBuilderInterface $builder, array $options): void
->add('enabled', CheckboxType::class, [
'label' => 'bitbag_sylius_bonus_points.ui.enabled',
])
->add('isDeductBonusPoints', CheckboxType::class, [
'label' => 'bitbag_sylius_bonus_points.ui.is_deduct_bonus_points',
])
->add('rules', BonusPointsStrategyRuleCollectionType::class, [
'label' => 'bitbag_sylius_bonus_points.ui.rules',
])
Expand Down
1 change: 1 addition & 0 deletions src/Resources/config/doctrine/BonusPointsStrategy.orm.xml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
<field name="calculatorType" column="calculator_type" type="string"/>
<field name="calculatorConfiguration" column="calculator_configuration" type="array"/>
<field name="enabled" type="boolean"/>
<field name="isDeductBonusPoints" column="is_deduct_bonus_points" type="boolean"/>

<field name="createdAt" column="created_at" type="datetime">
<gedmo:timestampable on="create"/>
Expand Down
1 change: 1 addition & 0 deletions src/Resources/config/services.xml
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
<argument type="service" id="bitbag_sylius_bonus_points.manager.bonus_points" />
<argument type="service" id="bitbag_sylius_bonus_points.repository.customer_bonus_points" />
<argument type="service" id="bitbag_sylius_bonus_points.factory.customer_bonus_points" />
<argument type="service" id="sylius.proportional_integer_distributor" />
</service>

<service id="bitbag_sylius_bonus_points.context.customer_bonus_points" class="BitBag\SyliusBonusPointsPlugin\Context\CustomerBonusPointsContext">
Expand Down
1 change: 1 addition & 0 deletions src/Resources/translations/messages.en.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,3 +17,4 @@ bitbag_sylius_bonus_points:
apply_points: Apply points
bonus_points_total: Bonus points total
you_have_bonus_points_available: You have bonus points available
is_deduct_bonus_points: Is deduct bonus points
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
<div class="column">
<div class="ui segment">
{{ form_row(form.calculatorType) }}
{{ form_row(form.isDeductBonusPoints) }}
{% for name, calculatorConfigurationPrototype in form.vars.prototypes %}
<div id="{{ form.calculatorType.vars.id }}_{{ name }}" data-container=".configuration"
data-prototype="{{ form_widget(calculatorConfigurationPrototype)|e }}">
Expand Down

0 comments on commit b312169

Please sign in to comment.