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
4 changes: 3 additions & 1 deletion docs/formula-and-modifiers.md
Original file line number Diff line number Diff line change
Expand Up @@ -71,9 +71,10 @@ discount.since('08.2018').grows('1%').every('month').min('10 USD')
discount.since('08.2000').grows('30%').every('year').max('100%')
discount.since('08.2018').grows('20 USD').every('2 months').min('15 USD').max('80 USD')
discount.since('08.2018').till('12.2018').grows('10pp').every('month')
discount.since('08.2018').grows('10 USD').every('month').stopsGrowing('10.2018')
```

Supports absolute (`USD`), relative (`%`), and percentage point (`pp`) steps. `min`/`max` cap the accumulated discount.
Supports absolute (`USD`), relative (`%`), and percentage point (`pp`) steps. `min`/`max` cap the accumulated discount. `stopsGrowing()` caps the growth calculation at the given month while the discount continues to apply.

### Increase

Expand Down Expand Up @@ -159,6 +160,7 @@ Modifiers use a composable addon system for configuration:
| `MonthPeriod` / `YearPeriod` / `DayPeriod` | Time periods for `every()` and `lasts()` |
| `Discount` | Discount value (absolute, relative %, or percentage point) |
| `Step` | Growth step for GrowingDiscount |
| `StopsGrowing` | Last month when GrowingDiscount grows |
| `Reason` | Human-readable comment attached to modifier charges |
| `Minimum` / `Maximum` | Bounds for accumulated discount values |

Expand Down
23 changes: 22 additions & 1 deletion src/charge/modifiers/GrowingDiscount.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
use hiqdev\php\billing\charge\modifiers\addons\Period;
use hiqdev\php\billing\charge\modifiers\addons\Since;
use hiqdev\php\billing\charge\modifiers\addons\Step;
use hiqdev\php\billing\charge\modifiers\addons\StopsGrowing;
use Money\Money;

/**
Expand All @@ -32,6 +33,7 @@ class GrowingDiscount extends FixedDiscount
public const STEP = 'step';
public const MIN = 'min';
public const MAX = 'max';
public const STOPS_GROWING = 'stopsGrowing';

public function __construct($step, $min = null, array $addons = [])
{
Expand Down Expand Up @@ -90,6 +92,16 @@ public function every($string = 1)
return $this->addAddon(self::PERIOD, Period::fromString($string));
}

public function stopsGrowing($month)
{
return $this->addAddon(self::STOPS_GROWING, new StopsGrowing($month));
}

public function getStopsGrowing(): ?StopsGrowing
{
return $this->getAddon(self::STOPS_GROWING);
}

#[\Override]
public function calculateSum(?ChargeInterface $charge = null): Money
{
Expand Down Expand Up @@ -126,6 +138,15 @@ protected function countPeriodsPassed(DateTimeImmutable $time)
throw new \Exception('no period given for growing discount');
}

return $period->countPeriodsPassed($since->getValue(), $time);
$sinceTime = $since->getValue();
$stopsGrowing = $this->getStopsGrowing();
if ($stopsGrowing instanceof StopsGrowing && $stopsGrowing->getValue() < $time) {
$time = $stopsGrowing->getValue();
}
if ($time < $sinceTime) {
$time = $sinceTime;
}

return $period->countPeriodsPassed($sinceTime, $time);
}
}
25 changes: 25 additions & 0 deletions src/charge/modifiers/addons/StopsGrowing.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
<?php

declare(strict_types=1);

/**
* PHP Billing Library
*
* @link https://github.com/hiqdev/php-billing
* @package php-billing
* @license BSD-3-Clause
* @copyright Copyright (c) 2017-2020, HiQDev (http://hiqdev.com/)
*/

namespace hiqdev\php\billing\charge\modifiers\addons;

use hiqdev\php\billing\charge\modifiers\AddonInterface;

/**
* Stops growing addon.
*
* @author Andrii Vasyliev <sol@hiqdev.com>
*/
class StopsGrowing extends Date implements AddonInterface
{
}
34 changes: 34 additions & 0 deletions tests/behat/GrowingDiscount.feature
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,40 @@ Feature: Growing discount
| 2019-01-01 | monthly 100 USD | discount -80 USD |
| 2028-11-01 | monthly 100 USD | discount -80 USD |

Scenario Outline: absolute discount stops growing but keeps applying
Given formula is discount.since('08.2018').grows('20 USD').every('2 months').min('15 USD').max('80 USD').stopsGrowing('10.2018')
When action date is <date>
Then first charge is <first>
And second charge is <second>
Examples:
| date | first | second |
| 2018-07-31 | monthly 100 USD | |
| 2018-08-01 | monthly 100 USD | discount -30 USD |
| 2018-09-01 | monthly 100 USD | discount -30 USD |
| 2018-10-01 | monthly 100 USD | discount -70 USD |
| 2018-11-01 | monthly 100 USD | discount -70 USD |
| 2018-12-01 | monthly 100 USD | discount -70 USD |
| 2019-01-01 | monthly 100 USD | discount -70 USD |
| 2028-11-01 | monthly 100 USD | discount -70 USD |

Scenario Outline: relative discount stops growing but keeps applying
Given formula is discount.since('08.2000').grows('30%').every('year').max('100%').stopsGrowing('08.2003')
When action date is <date>
Then first charge is <first>
And second charge is <second>
Examples:
| date | first | second |
| 2000-07-31 | monthly 100 USD | |
| 2000-08-01 | monthly 100 USD | discount -30.00 USD |
| 2001-08-01 | monthly 100 USD | discount -51.00 USD |
| 2002-08-01 | monthly 100 USD | discount -65.70 USD |
| 2003-01-01 | monthly 100 USD | discount -65.70 USD |
| 2003-08-01 | monthly 100 USD | discount -75.99 USD |
| 2004-08-01 | monthly 100 USD | discount -75.99 USD |
| 2005-08-01 | monthly 100 USD | discount -75.99 USD |
| 2011-08-01 | monthly 100 USD | discount -75.99 USD |
| 2024-08-01 | monthly 100 USD | discount -75.99 USD |

Scenario Outline: discount maximum may not match step: relative step but absolute max
Given formula is discount.since('08.2018').grows('20pp').every('month').min('30%').max('77 USD')
When action date is <date>
Expand Down
Loading