Merge pull request 'feature/RVRNEXT-5-main-currency-of-community-should-be-a-general-currency' (!34) from feature/RVRNEXT-5-main-currency-of-community-should-be-a-general-currency into master
All checks were successful
rvr-nextgen/pipeline/head This commit looks good

Reviewed-on: #34
This commit is contained in:
Bence Pőcze 2023-04-28 21:44:18 +02:00 committed by Gitea
commit 7b45069904
Signed by: Gitea
GPG Key ID: 7B89B83EED9AD2C6
11 changed files with 154 additions and 67 deletions

View File

@ -17,9 +17,9 @@ class Container
static SokoWeb\Interfaces\Database\IConnection $dbConnection; static SokoWeb\Interfaces\Database\IConnection $dbConnection;
static SokoWeb\Interfaces\Database\IAuditLogger $auditLogger; static SokoWeb\Interfaces\Database\IAuditLogger $auditLogger;
static SokoWeb\Interfaces\PersistentData\IPersistentDataManager $persistentDataManager; static SokoWeb\Interfaces\PersistentData\IPersistentDataManager $persistentDataManager;
static SokoWeb\Interfaces\Routing\IRouteCollection $routeCollection; static ?SokoWeb\Interfaces\Routing\IRouteCollection $routeCollection = null;
static SokoWeb\Interfaces\Session\ISessionHandler $sessionHandler; static ?SokoWeb\Interfaces\Session\ISessionHandler $sessionHandler = null;
static SokoWeb\Interfaces\Request\IRequest $request; static ?SokoWeb\Interfaces\Request\IRequest $request = null;
} }
Container::$dbConnection = new SokoWeb\Database\Mysql\Connection($_ENV['DB_HOST'], $_ENV['DB_USER'], $_ENV['DB_PASSWORD'], $_ENV['DB_NAME']); Container::$dbConnection = new SokoWeb\Database\Mysql\Connection($_ENV['DB_HOST'], $_ENV['DB_USER'], $_ENV['DB_PASSWORD'], $_ENV['DB_NAME']);

View File

@ -0,0 +1,19 @@
<?php
use RVR\PersistentData\Model\Community;
use RVR\PersistentData\Model\Currency;
use SokoWeb\Database\Query\Select;
$select = new Select(Container::$dbConnection);
$communities = Container::$persistentDataManager->selectMultipleFromDb($select, Community::class);
foreach ($communities as $community) {
$mainCurrency = new Currency();
$mainCurrency->setCommunity($community);
$mainCurrency->setCode($community->getCurrency());
$mainCurrency->setRoundDigits(0);
Container::$persistentDataManager->saveToDb($mainCurrency);
$community->setMainCurrency($mainCurrency);
Container::$persistentDataManager->saveToDb($community);
}

View File

@ -0,0 +1,4 @@
ALTER TABLE `communities`
ADD `main_currency_id` int(10) unsigned DEFAULT NULL,
ADD KEY `main_currency_id` (`main_currency_id`),
ADD CONSTRAINT `communities_main_currency_id` FOREIGN KEY (`main_currency_id`) REFERENCES `currencies` (`id`);

View File

@ -48,6 +48,8 @@ class CommunityController implements IAuthenticationRequired
return null; return null;
} }
\Container::$persistentDataManager->loadRelationsFromDb($community, false);
return new HtmlContent('communities/community', [ return new HtmlContent('communities/community', [
'community' => $community, 'community' => $community,
'members' => $this->getMembers($community), 'members' => $this->getMembers($community),
@ -73,6 +75,63 @@ class CommunityController implements IAuthenticationRequired
]); ]);
} }
public function saveCommunity(): ?IContent
{
$name = \Container::$request->post('name');
if (strlen($name) === 0) {
return new JsonContent([
'error' => ['errorText' => 'Please fill all required fields!']
]);
}
$communityId = \Container::$request->query('communityId');
if ($communityId){
if (!$this->checkPermission($communityId, true, $community, $ownCommunityMember)) {
return null;
}
} else {
$mainCurrencyCode = \Container::$request->post('main_currency_code');
$mainCurrencyRoundDigits = \Container::$request->post('main_currency_round_digits');
if (strlen($mainCurrencyCode) === 0 || strlen($mainCurrencyCode) > 3 || $mainCurrencyRoundDigits < 0 || $mainCurrencyRoundDigits > 9) {
return new JsonContent([
'error' => ['errorText' => 'Please fill all required fields!']
]);
}
$community = new Community();
$community->setCreatedDate(new DateTime());
}
$community->setName($name);
\Container::$persistentDataManager->saveToDb($community);
if (!$communityId) {
/**
* @var User $user
*/
$user = \Container::$request->user();
$communityMember = new CommunityMember();
$communityMember->setCommunity($community);
$communityMember->setUser($user);
$communityMember->setOwner(true);
\Container::$persistentDataManager->saveToDb($communityMember);
$mainCurrency = new Currency();
$mainCurrency->setCommunity($community);
$mainCurrency->setCode($mainCurrencyCode);
$mainCurrency->setRoundDigits($mainCurrencyRoundDigits);
\Container::$persistentDataManager->saveToDb($mainCurrency);
$community->setMainCurrency($mainCurrency);
\Container::$persistentDataManager->saveToDb($community);
}
return new JsonContent([
'redirect' => ['target' => \Container::$routeCollection->getRoute('community')->generateLink(['communityId' => $community->getId()])]
]);
}
public function getMembersEdit(): ?IContent public function getMembersEdit(): ?IContent
{ {
if (!$this->checkPermission(\Container::$request->query('communityId'), true, $community, $ownCommunityMember)) { if (!$this->checkPermission(\Container::$request->query('communityId'), true, $community, $ownCommunityMember)) {
@ -185,6 +244,10 @@ class CommunityController implements IAuthenticationRequired
} }
$currency = $this->currencyRepository->getById(\Container::$request->query('currency_id')); $currency = $this->currencyRepository->getById(\Container::$request->query('currency_id'));
if ($currency->getId() === $community->getMainCurrencyId()) {
return null;
}
\Container::$persistentDataManager->deleteFromDb($currency); \Container::$persistentDataManager->deleteFromDb($currency);
return new JsonContent(['success' => true]); return new JsonContent(['success' => true]);
@ -197,7 +260,7 @@ class CommunityController implements IAuthenticationRequired
} }
$currency = $this->currencyRepository->getByCommunityAndCurrencyCode($community, \Container::$request->query('code')); $currency = $this->currencyRepository->getByCommunityAndCurrencyCode($community, \Container::$request->query('code'));
if ($currency === null) { if ($currency === null || $currency->getId() === $community->getMainCurrencyId()) {
return null; return null;
} }
@ -261,51 +324,9 @@ class CommunityController implements IAuthenticationRequired
return new JsonContent(['success' => true]); return new JsonContent(['success' => true]);
} }
public function saveCommunity(): ?IContent
{
$name = \Container::$request->post('name');
$currency = \Container::$request->post('currency');
if (strlen($name) === 0 || strlen($currency) === 0 || strlen($currency) > 3) {
return new JsonContent([
'error' => ['errorText' => 'Please fill all required fields!']
]);
}
$communityId = \Container::$request->query('communityId');
if ($communityId){
if (!$this->checkPermission($communityId, true, $community, $ownCommunityMember)) {
return null;
}
} else {
$community = new Community();
$community->setCreatedDate(new DateTime());
}
$community->setName($name);
$community->setCurrency($currency);
\Container::$persistentDataManager->saveToDb($community);
if (!$communityId) {
/**
* @var User $user
*/
$user = \Container::$request->user();
$communityMember = new CommunityMember();
$communityMember->setCommunity($community);
$communityMember->setUser($user);
$communityMember->setOwner(true);
\Container::$persistentDataManager->saveToDb($communityMember);
}
return new JsonContent([
'redirect' => ['target' => \Container::$routeCollection->getRoute('community')->generateLink(['communityId' => $community->getId()])]
]);
}
private function getMembers(Community $community): array private function getMembers(Community $community): array
{ {
$members = iterator_to_array($this->communityMemberRepository->getAllByCommunity($community, true)); $members = iterator_to_array($this->communityMemberRepository->getAllByCommunity($community, true, [User::class]));
usort($members, function($a, $b) { usort($members, function($a, $b) {
return strnatcmp($a->getUser()->getDisplayName(), $b->getUser()->getDisplayName()); return strnatcmp($a->getUser()->getDisplayName(), $b->getUser()->getDisplayName());
}); });
@ -318,6 +339,9 @@ class CommunityController implements IAuthenticationRequired
usort($currencies, function($a, $b) { usort($currencies, function($a, $b) {
return strnatcmp($a->getCode(), $b->getCode()); return strnatcmp($a->getCode(), $b->getCode());
}); });
usort($currencies, function($a, $b) use ($community) {
return (int)($b->getId() === $community->getMainCurrencyId()) - (int)($a->getId() === $community->getMainCurrencyId());
});
return $currencies; return $currencies;
} }

View File

@ -1,5 +1,6 @@
<?php namespace RVR\Controller; <?php namespace RVR\Controller;
use RVR\PersistentData\Model\Community;
use RVR\PersistentData\Model\User; use RVR\PersistentData\Model\User;
use RVR\Repository\CommunityMemberRepository; use RVR\Repository\CommunityMemberRepository;
use SokoWeb\Interfaces\Authentication\IAuthenticationRequired; use SokoWeb\Interfaces\Authentication\IAuthenticationRequired;
@ -27,7 +28,7 @@ class HomeController implements IAuthenticationRequired
*/ */
$user = \Container::$request->user(); $user = \Container::$request->user();
$ownCommunityMembers = $this->communityMemberRepository->getAllByUser($user, true); $ownCommunityMembers = $this->communityMemberRepository->getAllByUser($user, true, [Community::class]);
$communities = []; $communities = [];
foreach ($ownCommunityMembers as $ownCommunityMember) { foreach ($ownCommunityMembers as $ownCommunityMember) {
$communities[] = $ownCommunityMember->getCommunity(); $communities[] = $ownCommunityMember->getCommunity();

View File

@ -6,6 +6,9 @@ class AuditLogger extends AuditLoggerBase
{ {
protected function getModifierId() protected function getModifierId()
{ {
if (\Container::$request === null) {
return null;
}
$user = \Container::$request->user(); $user = \Container::$request->user();
if ($user === null) { if ($user === null) {
return null; return null;

View File

@ -7,12 +7,18 @@ class Community extends Model
{ {
protected static string $table = 'communities'; protected static string $table = 'communities';
protected static array $fields = ['name', 'currency', 'created']; protected static array $fields = ['name', 'currency', 'main_currency_id', 'created'];
protected static array $relations = ['main_currency' => Currency::class];
private string $name = ''; private string $name = '';
private string $currency = ''; private string $currency = '';
private ?Currency $mainCurrency = null;
private ?int $mainCurrencyId = null;
private DateTime $created; private DateTime $created;
public function setName(string $name): void public function setName(string $name): void
@ -25,6 +31,16 @@ class Community extends Model
$this->currency = $currency; $this->currency = $currency;
} }
public function setMainCurrency(Currency $mainCurrency): void
{
$this->mainCurrency = $mainCurrency;
}
public function setMainCurrencyId(int $mainCurrencyId): void
{
$this->mainCurrencyId = $mainCurrencyId;
}
public function setCreatedDate(DateTime $created): void public function setCreatedDate(DateTime $created): void
{ {
$this->created = $created; $this->created = $created;
@ -45,6 +61,16 @@ class Community extends Model
return $this->currency; return $this->currency;
} }
public function getMainCurrency(): ?Currency
{
return $this->mainCurrency;
}
public function getMainCurrencyId(): ?int
{
return $this->mainCurrencyId;
}
public function getCreatedDate(): DateTime public function getCreatedDate(): DateTime
{ {
return $this->created; return $this->created;

View File

@ -13,20 +13,20 @@ class CommunityMemberRepository
return \Container::$persistentDataManager->selectFromDbById($id, CommunityMember::class); return \Container::$persistentDataManager->selectFromDbById($id, CommunityMember::class);
} }
public function getAllByCommunity(Community $community, bool $useRelations = false): Generator public function getAllByCommunity(Community $community, bool $useRelations = false, array $withRelations = []): Generator
{ {
$select = new Select(\Container::$dbConnection); $select = new Select(\Container::$dbConnection);
$select->where('community_id', '=', $community->getId()); $select->where('community_id', '=', $community->getId());
yield from \Container::$persistentDataManager->selectMultipleFromDb($select, CommunityMember::class, $useRelations); yield from \Container::$persistentDataManager->selectMultipleFromDb($select, CommunityMember::class, $useRelations, $withRelations);
} }
public function getAllByUser(User $user, bool $useRelations = false): Generator public function getAllByUser(User $user, bool $useRelations = false, array $withRelations = []): Generator
{ {
$select = new Select(\Container::$dbConnection); $select = new Select(\Container::$dbConnection);
$select->where('user_id', '=', $user->getId()); $select->where('user_id', '=', $user->getId());
yield from \Container::$persistentDataManager->selectMultipleFromDb($select, CommunityMember::class, $useRelations); yield from \Container::$persistentDataManager->selectMultipleFromDb($select, CommunityMember::class, $useRelations, $withRelations);
} }
public function getByCommunityAndUser(Community $community, User $user) : ?CommunityMember public function getByCommunityAndUser(Community $community, User $user) : ?CommunityMember

View File

@ -16,14 +16,15 @@
</div> </div>
<div> <div>
<h3 class="marginBottom">Currencies</h3> <h3 class="marginBottom">Currencies</h3>
<p>Main currency: <b><?= $community->getCurrency() ?></b></p> <?php foreach ($currencies as $currency): ?>
<?php if (count($currencies) > 0): ?> <p>
<p>Further currencies: <b> <?php if ($currency->getId() === $community->getMainCurrencyId()): ?>
<?php foreach ($currencies as $currency): ?> <b><?= $currency->getCode() ?></b>
<?php else: ?>
<a href="<?= Container::$routeCollection->getRoute('community-currency-exchange-rates')->generateLink(['communityId' => $community->getId(), 'code' => $currency->getCode()]) ?>"><?= $currency->getCode() ?></a> <a href="<?= Container::$routeCollection->getRoute('community-currency-exchange-rates')->generateLink(['communityId' => $community->getId(), 'code' => $currency->getCode()]) ?>"><?= $currency->getCode() ?></a>
<?php endforeach; ?> <?php endif; ?>
</b></p> </p>
<?php endif; ?> <?php endforeach; ?>
<?php if ($editPermission): ?> <?php if ($editPermission): ?>
<hr> <hr>
<p><a href="<?= Container::$routeCollection->getRoute('community-currencies')->generateLink(['communityId' => $community->getId()]) ?>">Edit currencies</a></p> <p><a href="<?= Container::$routeCollection->getRoute('community-currencies')->generateLink(['communityId' => $community->getId()]) ?>">Edit currencies</a></p>
@ -40,19 +41,23 @@
<?php endif; ?> <?php endif; ?>
</div> </div>
<div> <div>
<?php
$mainCurrencyCode = $community->getMainCurrency()->getCode();
$mainCurrencyRoundDigits = $community->getMainCurrency()->getRoundDigits();
?>
<h3 class="marginBottom">Finances</h3> <h3 class="marginBottom">Finances</h3>
<table class="fullWidth"> <table class="fullWidth">
<tr> <tr>
<td>You owe</td> <td>You owe</td>
<td style="text-align: right; color: red;">0 <?= $community->getCurrency() ?></td> <td style="text-align: right; color: red;"><?= number_format(0, $mainCurrencyRoundDigits) ?> <?= $mainCurrencyCode ?></td>
</tr> </tr>
<tr> <tr>
<td>You're owed</td> <td>You're owed</td>
<td style="text-align: right; color: green;">0 <?= $community->getCurrency() ?></td> <td style="text-align: right; color: green;"><?= number_format(0, $mainCurrencyRoundDigits) ?> <?= $mainCurrencyCode ?></td>
</tr> </tr>
<tr> <tr>
<td>Your balance</td> <td>Your balance</td>
<td style="text-align: right;">0 <?= $community->getCurrency() ?></td> <td style="text-align: right;"><?= number_format(0, $mainCurrencyRoundDigits) ?> <?= $mainCurrencyCode ?></td>
</tr> </tr>
</table> </table>
</div> </div>

View File

@ -21,9 +21,11 @@
<td> <td>
<input type="number" form="editCurrency_<?= $currency->getId() ?>" class="text fullWidth" name="round_digits" value="<?= $currency->getRoundDigits() ?>" min="0" max="9" required> <input type="number" form="editCurrency_<?= $currency->getId() ?>" class="text fullWidth" name="round_digits" value="<?= $currency->getRoundDigits() ?>" min="0" max="9" required>
</td> </td>
<td style="text-align: right;"> <td style="text-align: right; font-size: 0;">
<button type="submit" form="editCurrency_<?= $currency->getId() ?>" name="submit" class="small marginRight" disabled>Save</button><!-- <button type="submit" form="editCurrency_<?= $currency->getId() ?>" name="submit" class="small" disabled>Save</button>
--><button type="submit" form="deleteCurrency_<?= $currency->getId() ?>" class="small red">Delete</button> <?php if ($currency->getId() !== $community->getMainCurrencyId()): ?>
<button type="submit" form="deleteCurrency_<?= $currency->getId() ?>" class="small red marginLeft">Delete</button>
<?php endif; ?>
</td> </td>
</tr> </tr>
<?php endforeach; ?> <?php endforeach; ?>

View File

@ -16,7 +16,10 @@
?> ?>
<form id="communityForm" action="<?= $formAction ?>" method="post" data-redirect-on-success="true"> <form id="communityForm" action="<?= $formAction ?>" method="post" data-redirect-on-success="true">
<input type="text" class="text big fullWidth" name="name" placeholder="Name" value="<?= isset($community) ? $community->getName() : '' ?>" required> <input type="text" class="text big fullWidth" name="name" placeholder="Name" value="<?= isset($community) ? $community->getName() : '' ?>" required>
<input type="text" class="text big fullWidth marginTop" name="currency" value="<?= isset($community) ? $community->getCurrency() : '' ?>" placeholder="Default currency" maxlength="3" required> <?php if (!isset($community)): ?>
<input type="text" class="text big fullWidth marginTop" name="main_currency_code" placeholder="Main currency" maxlength="3" required>
<input type="number" class="text big fullWidth marginTop" name="main_currency_round_digits" placeholder="Main currency round digits" min="0" max="9" required>
<?php endif; ?>
<p id="communityFormError" class="formError justify marginTop"></p> <p id="communityFormError" class="formError justify marginTop"></p>
<div class="right marginTop"> <div class="right marginTop">
<button type="submit" name="submit"><?= isset($community) ? 'Save' : 'Create' ?></button> <button type="submit" name="submit"><?= isset($community) ? 'Save' : 'Create' ?></button>