Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add math calculator. Revise Rateable interface #4

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
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: 2 additions & 2 deletions src/Freemium/Command/CommandBus.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,12 @@ public function __construct(
$this->eventProvider = $eventProvider;
}

public function handle($command)
public function handle(object $command)
{
return $this->resolveHandler($command)->handle($command);
}

private function resolveHandler($command)
private function resolveHandler(object $command)
{
$resolver = $this->resolver;

Expand Down
23 changes: 6 additions & 17 deletions src/Freemium/Command/CreateSubscription/NewSubscription.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,35 +4,24 @@

namespace Freemium\Command\CreateSubscription;

use Freemium\RateTest;
use Freemium\Subscribable;
use Freemium\SubscriptionPlan;

class NewSubscription
{
/**
* @var Subscribable
*/
private $subscribable;

/**
* @var SubscriptionPlan
*/
private $subscriptionPlan;

public function __construct(
Subscribable $subscribable,
SubscriptionPlan $subscriptionPlan
private readonly string $customerId,
private readonly string $subscriptionPlan
) {
$this->subscribable = $subscribable;
$this->subscriptionPlan = $subscriptionPlan;
}

public function getSubscribable(): Subscribable
public function getCustomerId(): string
{
return $this->subscribable;
return $this->customerId;
}

public function getSubscriptionPlan(): SubscriptionPlan
public function getSubscriptionPlan(): string
{
return $this->subscriptionPlan;
}
Expand Down
20 changes: 12 additions & 8 deletions src/Freemium/Command/CreateSubscription/NewSubscriptionHandler.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,29 +7,33 @@
use Freemium\Subscription;
use Freemium\Event\EventProvider;
use Freemium\Command\AbstractCommandHandler;
use Freemium\Repository\SubscribableRepository;
use Freemium\Repository\SubscriptionRepository;
use Freemium\Repository\SubscriptionPlanRepository;

class NewSubscriptionHandler extends AbstractCommandHandler
{
private $repository;

public function __construct(
EventProvider $eventProvider,
SubscriptionRepository $repository
private readonly SubscriptionRepository $repository,
private readonly SubscribableRepository $subscribableRepository,
private readonly SubscriptionPlanRepository $subscriptionPlanRepository
) {
parent::__construct($eventProvider);
$this->repository = $repository;
}

public function handle(NewSubscription $command): void
{
$subscribable = $this->subscribableRepository->findByCustomerId($command->getCustomerId());
$subscriptionPlan = $this->subscriptionPlanRepository->findByName($command->getSubscriptionPlan());

$subscription = new Subscription(
$command->getSubscribable(),
$command->getSubscriptionPlan()
$subscribable,
$subscriptionPlan
);

$this->getEventProvider()->raise(new Event\SubscriptionCreated($subscription));

$this->repository->insert($subscription);

$this->getEventProvider()->raise(new Event\SubscriptionCreated($subscription));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ public function handle(StoreCreditCard $command)
throw new RuntimeException($response->message());
}

$subscribable->setBillingKey($response->authorization());
$subscribable->updateBillingKey($response->authorization());
$this->repository->insert($subscribable);
} catch (Throwable $e) {
$event = new Event\CreditCardFailed(
Expand Down
2 changes: 1 addition & 1 deletion src/Freemium/Coupon.php
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ public function __construct(Discount $discount, $redemptionKey = null)

/**
* Returns dicounted price for the given rate.
* @see Discount::getDiscountRate
* @see Discount::apply
*
* @param int $rate
* @return int
Expand Down
2 changes: 2 additions & 0 deletions src/Freemium/Event/DomainEvent.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@

abstract class DomainEvent
{
public const NAME = 'default';

public function getName(): string
{
return static::NAME;
Expand Down
18 changes: 18 additions & 0 deletions src/Freemium/Math/Calculator.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<?php

declare(strict_types=1);

namespace Freemium\Math;

class Calculator
{
public function divide(string $a, string $b, int $scale = 2): string
{
return bcdiv($a, $b, $scale);
}

public function multiple(string $a, string $b, int $scale = 2): string
{
return bcmul($a, $b, $scale);
}
}
10 changes: 5 additions & 5 deletions src/Freemium/PaidThrough/PaidThrough.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,22 +8,22 @@

class PaidThrough
{
private $paidThrough;
private $date;

private $inTrial;

private $expireOn;

public function __construct(?DateTime $paidThrough, ?bool $inTrial, ?DateTime $expires)
public function __construct(?DateTime $date, ?bool $inTrial, ?DateTime $expires)
{
$this->paidThrough = $paidThrough;
$this->date = $date;
$this->inTrial = $inTrial;
$this->expireOn = $expires;
}

public function getPaidThrough(): ?DateTime
public function getDate(): ?DateTime
{
return $this->paidThrough;
return $this->date;
}

public function isInTrial(): ?bool
Expand Down
31 changes: 19 additions & 12 deletions src/Freemium/PeriodCalculator.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,21 +4,27 @@

namespace Freemium;

use Freemium\Math\Calculator;

/**
* Calculates monthly rate of a plan for a give period and frequency.
*
* @author Andreas Kollaros <[email protected]>
*/
class PeriodCalculator
{
private $period;
private int $period;

private int $frequency;

private $frequency;
private Calculator $calculator;

public function __construct(int $period, int $frequency)
{
$this->period = $period;
$this->frequency = $frequency;
$this->calculator = new Calculator();

}

/**
Expand All @@ -30,23 +36,24 @@ public function __construct(int $period, int $frequency)
*/
public function monthlyRate(int $rate): int
{
switch (true) {
case $this->period == SubscriptionPlan::PERIOD_DAY:
$months = $this->frequency / 30;

switch ($this->period) {
case SubscriptionPlan::PERIOD_DAY:
$months = $this->calculator->divide(strval($this->frequency), '30', 4);
return $this->rate($months, $rate);
case $this->period == SubscriptionPlan::PERIOD_WEEK:
$months = $this->frequency / 4;
case SubscriptionPlan::PERIOD_WEEK:
$months = $this->calculator->divide(strval($this->frequency), '4', 4);
return $this->rate($months, $rate);
case $this->period == SubscriptionPlan::PERIOD_YEAR:
$months = $this->frequency * 12;
case SubscriptionPlan::PERIOD_YEAR:
$months = $this->calculator->multiple(strval($this->frequency), '12');
return $this->rate($months, $rate);
default:
return $this->rate($this->frequency, $rate);
return $this->rate(strval($this->frequency), $rate);
}
}

private function rate(float $months, int $rate): int
private function rate(string $months, int $rate): int
{
return (int) round($rate / $months, 0);
return intval($this->calculator->divide(strval($rate), $months, 0));
}
}
60 changes: 20 additions & 40 deletions src/Freemium/Rate.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,82 +8,62 @@

trait Rate
{
protected $rate;
/**
* {@inheritdoc}
*/
abstract public function getRate(): int;

/**
* Return the monthly rate based on date and plan.
*
* @param DateTime|null $data
* @param SubscriptionPlan|null $plan
*
* @return int
* {@inheritdoc}
*/
abstract public function rate(
DateTime $date = null,
SubscriptionPlan $plan = null
): int;
abstract public function rate(?DateTime $date = null): int;

/**
* Gets the daily cost in cents.
* @see RateInterface::rate method.
* @see Rateable::rate method.
*
* @param DateTime $date
* @param SubscriptionPlan|null $plan
* @param DateTime|null $date
* @return int
*/
public function getDailyRate(
DateTime $date = null,
SubscriptionPlan $plan = null
?DateTime $date = null
): int {
return (int) round($this->getYearlyRate($date, $plan) / 365, 0);
return (int) round($this->getYearlyRate($date) / 365, 0);
}

/**
* Gets the monthly cost in cents.
* @see RateInterface::rate method.
* @see Rateable::rate method.
*
* @param DateTime $date
* @param SubscriptionPlan|null $plan
* @param DateTime|null $date
* @return int
*/
public function getMonthlyRate(
DateTime $date = null,
SubscriptionPlan $plan = null
?DateTime $date = null
): int {
return $this->rate($date, $plan);
return $this->rate($date);
}

/**
* Gets the yearly cost in cents.
* @see RateInterface::rate method.
* @see Rateable::rate method.
*
* @param DateTime $date
* @param SubscriptionPlan|null $plan
* @param DateTime|null $date
* @return int
*/
public function getYearlyRate(
DateTime $date = null,
SubscriptionPlan $plan = null
DateTime $date = null
): int {
return $this->rate($date, $plan) * 12;
return $this->rate($date) * 12;
}

/**
* Chack if object can be paid or not.
* Check if an object can be paid or not.
*
* @return bool
*/
public function isPaid(): bool
{
if ($this->rate) {
return $this->rate > 0;
}

return false;
}

public function getRate(): int
{
return $this->rate;
return $this->getRate() > 0 ?: false;
}
}
22 changes: 0 additions & 22 deletions src/Freemium/RateInterface.php

This file was deleted.

23 changes: 23 additions & 0 deletions src/Freemium/Rateable.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<?php

declare(strict_types=1);

namespace Freemium;

use DateTime;

interface Rateable
{
/**
* Calculate monthly rate amount according to given date.
*
* @param DateTime|null $date The date to check available coupons for subscription.
* @return int
*/
public function rate(?DateTime $date = null): int;

/**
* Return the fixed rate of the object
*/
public function getRate(): int;
}
11 changes: 11 additions & 0 deletions src/Freemium/Repository/Exception/EntityNotFoundException.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<?php

declare(strict_types=1);

namespace Freemium\Repository\Exception;

use InvalidArgumentException;

class EntityNotFoundException extends InvalidArgumentException
{
}
Loading