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

Merge development to master. #4

Merged
merged 6 commits into from
Jan 20, 2024
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
2 changes: 1 addition & 1 deletion .github/workflows/php_build_and_qa_test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -95,5 +95,5 @@ jobs:
npm run build-only

## —— Testing ————————————————————————————————————————————————————————————
# - name: Execute tests (Unit & Integration Tests) via PestPHP
# - name: Execute tests (Unit & Feature Tests) via PestPHP
# run: ./vendor/bin/pest
18 changes: 16 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ Yoshi-Kan Website + Ledenbeheer

---

<p style="padding-top:9px;">
<p>
<img src="https://img.shields.io/github/license/koencaerels/yoshikan?style=flat" alt="GitHub license">
<img src="https://github.com/koencaerels/yoshikan/actions/workflows/php_build_and_qa_test.yml/badge.svg">
</p>
Expand All @@ -12,7 +12,21 @@ Yoshi-Kan Website + Ledenbeheer

## Requirements

...
* A webserver (Apache, NGINX, ...) with PHP 8.2 or higher.
* [Symfony](https://symfony.com/): PHP 8.2 or higher and these PHP extensions (which are installed and enabled by default in most PHP 8 installations):
Ctype, iconv, PCRE, Session, SimpleXML, and Tokenizer.
* [Composer](https://getcomposer.org/download/), which is used to install PHP packages.
* A database server (MySQL, PostgreSQL, SQLite, ... ) that is compatible with [Doctrine](https://www.doctrine-project.org/).
* Node.js,Yarn & NPM for the frontends build process.

### Third party services

* https://www.resend.com/ for sending emails concerning the two factor authentication
* https://www.brevo.com/ for sending the transactional emails
* https://www.mollie.com/ for the online payment services
* https://www.sentry.io/ for error logging and monitoring

You can configure these services in the `.env` file.

## Getting Started

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,19 @@ public function __construct(
) {
}

public function resetItemsFromSubscription(Subscription $subscription): bool
{
$subscription = $this->subscriptionRepository->getById($subscription->getId());
$items = $this->subscriptionItemRepository->getBySubscription($subscription);
foreach ($items as $item) {
$this->subscriptionItemRepository->delete($item);
}
$subscription->clearItems();
$this->subscriptionRepository->save($subscription);

return true;
}

public function saveItemsFromSubscription(
Subscription $subscription,
Federation $federation,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
<?php

/*
* This file is part of the Yoshi-Kan software.
*
* (c) Koen Caerels
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

declare(strict_types=1);

namespace App\YoshiKan\Application\Command\Member\ChangeLicense;

class ChangeLicense
{
// —————————————————————————————————————————————————————————————————————————
// Constructor
// —————————————————————————————————————————————————————————————————————————

private function __construct(
protected int $memberId,
protected int $federationId,
) {
}

// —————————————————————————————————————————————————————————————————————————
// Hydrate from a json command
// —————————————————————————————————————————————————————————————————————————

public static function hydrateFromJson(\stdClass $json): self
{
return new self(
$json->memberId,
$json->federationId,
);
}

// —————————————————————————————————————————————————————————————————————————
// Getters
// —————————————————————————————————————————————————————————————————————————

public function getMemberId(): int
{
return $this->memberId;
}

public function getFederationId(): int
{
return $this->federationId;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
<?php

/*
* This file is part of the Yoshi-Kan software.
*
* (c) Koen Caerels
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

declare(strict_types=1);

namespace App\YoshiKan\Application\Command\Member\ChangeLicense;

use App\YoshiKan\Application\Command\Common\SubscriptionItemsFactory;
use App\YoshiKan\Application\Query\Member\Readmodel\SettingsReadModel;
use App\YoshiKan\Domain\Model\Member\MemberRepository;
use App\YoshiKan\Domain\Model\Member\SettingsCode;
use App\YoshiKan\Domain\Model\Member\Subscription;
use App\YoshiKan\Domain\Model\Member\SubscriptionItemRepository;
use App\YoshiKan\Domain\Model\Member\SubscriptionStatus;
use App\YoshiKan\Domain\Model\Member\SubscriptionType;
use App\YoshiKan\Infrastructure\Database\Member\FederationRepository;
use App\YoshiKan\Infrastructure\Database\Member\LocationRepository;
use App\YoshiKan\Infrastructure\Database\Member\SettingsRepository;
use App\YoshiKan\Infrastructure\Database\Member\SubscriptionRepository;
use Doctrine\ORM\EntityManagerInterface;

class ChangeLicenseHandler
{
// ———————————————————————————————————————————————————————————————
// Constructor
// ———————————————————————————————————————————————————————————————

public function __construct(
protected MemberRepository $memberRepository,
protected SubscriptionRepository $subscriptionRepository,
protected SubscriptionItemRepository $subscriptionItemRepository,
protected FederationRepository $federationRepository,
protected LocationRepository $locationRepository,
protected SettingsRepository $settingsRepository,
protected EntityManagerInterface $entityManager,
) {
}

// ———————————————————————————————————————————————————————————————
// Handle
// ———————————————————————————————————————————————————————————————

public function change(ChangeLicense $command): \stdClass
{
$member = $this->memberRepository->getById($command->getMemberId());
$federation = $this->federationRepository->getById($command->getFederationId());
$settings = $this->settingsRepository->findByCode(SettingsCode::ACTIVE->value);

$extraTraining = false;
if (3 === $member->getNumberOfTraining()) {
$extraTraining = true;
}

// -- calculate the new license dates -------------------------------

$now = new \DateTimeImmutable();
$licenseStart = $now->setDate((int) $now->format('Y'), (int) $now->format('m'), 1);
$licenseEnd = $licenseStart->modify('+1 year');

// -- create a new subscription -------------------------------------

$subscription = Subscription::make(
$this->subscriptionRepository->nextIdentity(),
$member->getContactFirstname(),
$member->getContactLastname(),
$member->getContactEmail(),
$member->getContactPhone(),
$member->getFirstname(),
$member->getLastname(),
$member->getDateOfBirth(),
$member->getGender(),
SubscriptionType::RENEWAL_LICENSE,
$member->getNumberOfTraining(),
$extraTraining,
false,
false,
false,
'Wijziging vergunning naar '.$federation->getName(),
$member->getLocation(),
json_decode(json_encode(SettingsReadModel::hydrateFromModel($settings)), true),
$federation,
$member->getMemberSubscriptionStart(),
$member->getMemberSubscriptionEnd(),
0,
false,
false,
true,
$licenseStart,
$licenseEnd,
$federation->getYearlySubscriptionFee(),
true,
false,
);

$subscription->setMember($member);
$subscription->changeStatus(SubscriptionStatus::AWAITING_PAYMENT);
$subscription->calculate();
$this->subscriptionRepository->save($subscription);
$this->entityManager->flush();

// -- make some subscription lines ----------------------------------

$subscriptionItemFactory = new SubscriptionItemsFactory(
$this->subscriptionRepository,
$this->subscriptionItemRepository
);
$resultItems = $subscriptionItemFactory->saveItemsFromSubscription(
$subscription,
$federation,
$settings
);

// -- flag new dates in the member ----------------------------------

$member->setLicenseDates(
$subscription->getLicenseStart(),
$subscription->getLicenseEnd()
);
$member->syncFromSubscription(
federation: $federation,
numberOfTraining: $subscription->getNumberOfTraining(),
isHalfYearSubscription: $subscription->isMemberSubscriptionIsHalfYear(),
);

$this->memberRepository->save($member);
$this->entityManager->flush();

// -- compile a result class ----------------------------------------

$subscriptionId = $this->subscriptionRepository->getMaxId();
$result = new \stdClass();
$result->id = $subscriptionId;
$result->reference = 'YKS-'.$subscriptionId.': '.$member->getFirstname().' '.$member->getLastName();

return $result;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
<?php

/*
* This file is part of the Yoshi-Kan software.
*
* (c) Koen Caerels
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

declare(strict_types=1);

namespace App\YoshiKan\Application\Command\Member\ChangeLicense;

trait ChangeLicenseTrait
{
public function changeLicense(\stdClass $jsonCommand): \stdClass
{
$this->permission->CheckRole(['ROLE_DEVELOPER', 'ROLE_ADMIN', 'ROLE_CHIEF_EDITOR']);

$command = ChangeLicense::hydrateFromJson($jsonCommand);
$handler = new ChangeLicenseHandler(
memberRepository: $this->memberRepository,
subscriptionRepository: $this->subscriptionRepository,
subscriptionItemRepository: $this->subscriptionItemRepository,
federationRepository: $this->federationRepository,
locationRepository: $this->locationRepository,
settingsRepository: $this->settingsRepository,
entityManager: $this->entityManager,
);

$result = $handler->change($command);
$this->entityManager->flush();

return $result;
}
}
Loading
Loading