All checks were successful
rvr-nextgen/pipeline/pr-master This commit looks good
441 lines
16 KiB
PHP
441 lines
16 KiB
PHP
<?php namespace RVR\Controller;
|
|
|
|
use DateTime;
|
|
use RVR\Finance\BalanceCalculator;
|
|
use RVR\PersistentData\Model\Community;
|
|
use RVR\PersistentData\Model\CommunityMember;
|
|
use RVR\PersistentData\Model\Currency;
|
|
use RVR\PersistentData\Model\CurrencyExchangeRate;
|
|
use RVR\PersistentData\Model\User;
|
|
use RVR\Repository\CommunityRepository;
|
|
use RVR\Repository\CommunityMemberRepository;
|
|
use RVR\Repository\CurrencyExchangeRateRepository;
|
|
use RVR\Repository\CurrencyRepository;
|
|
use RVR\Repository\TransactionRepository;
|
|
use RVR\Repository\UserRepository;
|
|
use SokoWeb\Interfaces\Authentication\IAuthenticationRequired;
|
|
use SokoWeb\Interfaces\Response\IContent;
|
|
use SokoWeb\Response\HtmlContent;
|
|
use SokoWeb\Response\JsonContent;
|
|
|
|
class CommunityController implements IAuthenticationRequired
|
|
{
|
|
private UserRepository $userRepository;
|
|
|
|
private CommunityRepository $communityRepository;
|
|
|
|
private CommunityMemberRepository $communityMemberRepository;
|
|
|
|
private CurrencyRepository $currencyRepository;
|
|
|
|
private CurrencyExchangeRateRepository $currencyExchangeRatesRepository;
|
|
|
|
private TransactionRepository $transactionRepository;
|
|
|
|
public function __construct()
|
|
{
|
|
$this->userRepository = new UserRepository();
|
|
$this->communityRepository = new CommunityRepository();
|
|
$this->communityMemberRepository = new CommunityMemberRepository();
|
|
$this->currencyRepository = new CurrencyRepository();
|
|
$this->currencyExchangeRatesRepository = new CurrencyExchangeRateRepository();
|
|
$this->transactionRepository = new TransactionRepository();
|
|
}
|
|
|
|
public function isAuthenticationRequired(): bool
|
|
{
|
|
return true;
|
|
}
|
|
|
|
public function getCommunityHome(): ?IContent
|
|
{
|
|
if (!$this->checkPermission(\Container::$request->query('communitySlug'), false, $community, $ownCommunityMember)) {
|
|
return null;
|
|
}
|
|
|
|
\Container::$persistentDataManager->loadRelationsFromDb($community, false, ['main_currency']);
|
|
|
|
$balanceCalculator = new BalanceCalculator($community);
|
|
$debts = $balanceCalculator->calculate();
|
|
$debtItems = [];
|
|
$debtBalance = 0.0;
|
|
$outstandingItems = [];
|
|
$outstandingBalance = 0.0;
|
|
foreach ($debts as $debt) {
|
|
if ($debt['payer']->getId() === \Container::$request->user()->getUniqueId()) {
|
|
$debtBalance += $debt['amount'];
|
|
$debtItems[] = $debt;
|
|
}
|
|
if ($debt['payee']->getId() === \Container::$request->user()->getUniqueId()) {
|
|
$outstandingBalance += $debt['amount'];
|
|
$outstandingItems[] = $debt;
|
|
}
|
|
}
|
|
$balance = $outstandingBalance - $debtBalance;
|
|
|
|
return new HtmlContent('communities/community', [
|
|
'community' => $community,
|
|
'upcomingEvents' => [],
|
|
'debtItems' => $debtItems,
|
|
'debtBalance' => $debtBalance,
|
|
'outstandingItems' => $outstandingItems,
|
|
'outstandingBalance' => $outstandingBalance,
|
|
'balance' => $balance,
|
|
'editPermission' => $ownCommunityMember->getOwner()
|
|
]);
|
|
}
|
|
|
|
public function getCommunitySettings(): ?IContent
|
|
{
|
|
if (!$this->checkPermission(\Container::$request->query('communitySlug'), false, $community, $ownCommunityMember)) {
|
|
return null;
|
|
}
|
|
|
|
return new HtmlContent('communities/community_settings', [
|
|
'community' => $community,
|
|
'members' => $this->getMembers($community),
|
|
'currencies' => $this->getCurrencies($community),
|
|
'editPermission' => $ownCommunityMember->getOwner()
|
|
]);
|
|
}
|
|
|
|
public function getCommunityNew(): IContent
|
|
{
|
|
return new HtmlContent('communities/community_edit');
|
|
}
|
|
|
|
public function getCommunityEdit(): ?IContent
|
|
{
|
|
if (!$this->checkPermission(\Container::$request->query('communitySlug'), true, $community, $ownCommunityMember)) {
|
|
return null;
|
|
}
|
|
|
|
return new HtmlContent('communities/community_edit', [
|
|
'community' => $community
|
|
]);
|
|
}
|
|
|
|
public function saveCommunity(): ?IContent
|
|
{
|
|
$name = \Container::$request->post('name');
|
|
if (strlen($name) === 0) {
|
|
return new JsonContent([
|
|
'error' => ['errorText' => 'Please fill all required fields!']
|
|
]);
|
|
}
|
|
|
|
$communitySlug = \Container::$request->query('communitySlug');
|
|
if ($communitySlug){
|
|
if (!$this->checkPermission($communitySlug, 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 (!$communitySlug) {
|
|
/**
|
|
* @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(['communitySlug' => $community->getSlug()])]
|
|
]);
|
|
}
|
|
|
|
public function getMembersEdit(): ?IContent
|
|
{
|
|
if (!$this->checkPermission(\Container::$request->query('communitySlug'), true, $community, $ownCommunityMember)) {
|
|
return null;
|
|
}
|
|
|
|
return new HtmlContent('communities/community_members', [
|
|
'community' => $community,
|
|
'members' => $this->getMembers($community)
|
|
]);
|
|
}
|
|
|
|
public function saveMember(): ?IContent
|
|
{
|
|
if (!$this->checkPermission(\Container::$request->query('communitySlug'), true, $community, $ownCommunityMember)) {
|
|
return null;
|
|
}
|
|
|
|
$communityMemberId = \Container::$request->query('community_member_id');
|
|
if ($communityMemberId) {
|
|
$communityMember = $this->communityMemberRepository->getById($communityMemberId);
|
|
if ($communityMember->getUserId() === $ownCommunityMember->getUserId()) {
|
|
return new JsonContent([
|
|
'error' => ['errorText' => 'Own user cannot be edited.']
|
|
]);
|
|
}
|
|
} else {
|
|
if ($this->transactionRepository->isAnyCommon()) {
|
|
return new JsonContent([
|
|
'error' => ['errorText' => 'There are transactions with common payee!']
|
|
]);
|
|
}
|
|
|
|
$user = $this->userRepository->getById(\Container::$request->post('user_id'));
|
|
if ($this->communityMemberRepository->getByCommunityAndUser($community, $user) !== null) {
|
|
return new JsonContent([
|
|
'error' => ['errorText' => 'This user is already a member of this community.']
|
|
]);
|
|
}
|
|
|
|
$communityMember = new CommunityMember();
|
|
$communityMember->setCommunity($community);
|
|
$communityMember->setUser($user);
|
|
}
|
|
|
|
$communityMember->setOwner((bool)\Container::$request->post('owner'));
|
|
\Container::$persistentDataManager->saveToDb($communityMember);
|
|
|
|
return new JsonContent(['success' => true]);
|
|
}
|
|
|
|
public function deleteMember(): ?IContent
|
|
{
|
|
if (!$this->checkPermission(\Container::$request->query('communitySlug'), true, $community, $ownCommunityMember)) {
|
|
return null;
|
|
}
|
|
|
|
$communityMember = $this->communityMemberRepository->getById(\Container::$request->query('community_member_id'));
|
|
if ($communityMember->getUserId() === \Container::$request->user()->getUniqueId()) {
|
|
return new JsonContent([
|
|
'error' => ['errorText' => 'Own user cannot be deleted.']
|
|
]);
|
|
}
|
|
|
|
\Container::$persistentDataManager->loadRelationsFromDb($communityMember, false, ['user']);
|
|
if ($this->transactionRepository->isAnyForUser($communityMember->getUser())) {
|
|
return new JsonContent([
|
|
'error' => ['errorText' => 'There are transactions where the member is payer or payee!']
|
|
]);
|
|
}
|
|
|
|
\Container::$persistentDataManager->deleteFromDb($communityMember);
|
|
|
|
return new JsonContent(['success' => true]);
|
|
}
|
|
|
|
public function getCurrenciesEdit(): ?IContent
|
|
{
|
|
if (!$this->checkPermission(\Container::$request->query('communitySlug'), true, $community, $ownCommunityMember)) {
|
|
return null;
|
|
}
|
|
|
|
return new HtmlContent('communities/community_currencies', [
|
|
'community' => $community,
|
|
'currencies' => $this->getCurrencies($community)
|
|
]);
|
|
}
|
|
|
|
public function saveCurrency(): ?IContent
|
|
{
|
|
if (!$this->checkPermission(\Container::$request->query('communitySlug'), true, $community, $ownCommunityMember)) {
|
|
return null;
|
|
}
|
|
|
|
$code = \Container::$request->post('code');
|
|
$roundDigits = (int)\Container::$request->post('round_digits');
|
|
if (strlen($code) === 0 || strlen($code) > 3 || $roundDigits < 0 || $roundDigits > 9) {
|
|
return new JsonContent([
|
|
'error' => ['errorText' => 'Please fill all required fields!']
|
|
]);
|
|
}
|
|
|
|
$currencyId = \Container::$request->query('currency_id');
|
|
if ($currencyId){
|
|
$currency = $this->currencyRepository->getById($currencyId);
|
|
} else {
|
|
$currency = new Currency();
|
|
$currency->setCommunity($community);
|
|
}
|
|
|
|
$existingCurrency = $this->currencyRepository->getByCommunityAndCurrencyCode($community, $code);
|
|
if ($existingCurrency !== null && $currency->getId() !== $existingCurrency->getId()) {
|
|
return new JsonContent([
|
|
'error' => ['errorText' => 'A currency with the same code exists for this community.']
|
|
]);
|
|
}
|
|
|
|
$currency->setCode($code);
|
|
$currency->setRoundDigits($roundDigits);
|
|
\Container::$persistentDataManager->saveToDb($currency);
|
|
|
|
return new JsonContent(['success' => true]);
|
|
}
|
|
|
|
public function deleteCurrency(): ?IContent
|
|
{
|
|
if (!$this->checkPermission(\Container::$request->query('communitySlug'), true, $community, $ownCommunityMember)) {
|
|
return null;
|
|
}
|
|
|
|
$currency = $this->currencyRepository->getById(\Container::$request->query('currency_id'));
|
|
if ($currency->getId() === $community->getMainCurrencyId()) {
|
|
return null;
|
|
}
|
|
|
|
if ($this->transactionRepository->isAnyForCurrency($currency)) {
|
|
return new JsonContent([
|
|
'error' => ['errorText' => 'There are transactions with this currency!']
|
|
]);
|
|
}
|
|
|
|
foreach ($this->currencyExchangeRatesRepository->getAllByCurrency($currency) as $currencyExchangeRate) {
|
|
\Container::$persistentDataManager->deleteFromDb($currencyExchangeRate);
|
|
}
|
|
|
|
\Container::$persistentDataManager->deleteFromDb($currency);
|
|
|
|
return new JsonContent(['success' => true]);
|
|
}
|
|
|
|
public function getCurrencyExchangeRates(): ?IContent
|
|
{
|
|
if (!$this->checkPermission(\Container::$request->query('communitySlug'), true, $community, $ownCommunityMember)) {
|
|
return null;
|
|
}
|
|
|
|
$currency = $this->currencyRepository->getByCommunityAndCurrencyCode($community, \Container::$request->query('code'));
|
|
if ($currency === null || $currency->getId() === $community->getMainCurrencyId()) {
|
|
return null;
|
|
}
|
|
|
|
$currencyExchangeRates = $this->currencyExchangeRatesRepository->getAllByCurrency($currency);
|
|
|
|
return new HtmlContent('communities/currency_exchange_rates', [
|
|
'community' => $community,
|
|
'currency' => $currency,
|
|
'currencyExchangeRates' => $currencyExchangeRates,
|
|
'editPermission' => $ownCommunityMember->getOwner()
|
|
]);
|
|
}
|
|
|
|
public function saveCurrencyExchangeRate(): ?IContent
|
|
{
|
|
if (!$this->checkPermission(\Container::$request->query('communitySlug'), true, $community, $ownCommunityMember)) {
|
|
return null;
|
|
}
|
|
|
|
$currency = $this->currencyRepository->getByCommunityAndCurrencyCode($community, \Container::$request->query('code'));
|
|
if ($currency === null) {
|
|
return null;
|
|
}
|
|
|
|
$exchangeRate = (float)\Container::$request->post('exchange_rate');
|
|
if ($exchangeRate < 0) {
|
|
return new JsonContent([
|
|
'error' => ['errorText' => 'Please fill all required fields!']
|
|
]);
|
|
}
|
|
|
|
$currencyExchangeRateId = \Container::$request->query('currency_exchange_rate_id');
|
|
if ($currencyExchangeRateId){
|
|
$currencyExchangeRate = $this->currencyExchangeRatesRepository->getById($currencyExchangeRateId);
|
|
} else {
|
|
$currencyExchangeRate = new CurrencyExchangeRate();
|
|
$currencyExchangeRate->setCurrency($currency);
|
|
}
|
|
|
|
$currencyExchangeRate->setExchangeRate($exchangeRate);
|
|
$currencyExchangeRate->setValidFromDate(new DateTime(\Container::$request->post('valid_from')));
|
|
\Container::$persistentDataManager->saveToDb($currencyExchangeRate);
|
|
|
|
return new JsonContent(['success' => true]);
|
|
}
|
|
|
|
public function deleteCurrencyExchangeRate(): ?IContent
|
|
{
|
|
if (!$this->checkPermission(\Container::$request->query('communitySlug'), true, $community, $ownCommunityMember)) {
|
|
return null;
|
|
}
|
|
|
|
$currency = $this->currencyRepository->getByCommunityAndCurrencyCode($community, \Container::$request->query('code'));
|
|
if ($currency === null) {
|
|
return null;
|
|
}
|
|
|
|
$currencyExchangeRate = $this->currencyExchangeRatesRepository->getById(\Container::$request->query('currency_exchange_rate_id'));
|
|
\Container::$persistentDataManager->deleteFromDb($currencyExchangeRate);
|
|
|
|
return new JsonContent(['success' => true]);
|
|
}
|
|
|
|
private function getMembers(Community $community): array
|
|
{
|
|
$members = iterator_to_array($this->communityMemberRepository->getAllByCommunity($community, true, ['user']));
|
|
usort($members, function($a, $b) {
|
|
return strnatcmp($a->getUser()->getDisplayName(), $b->getUser()->getDisplayName());
|
|
});
|
|
return $members;
|
|
}
|
|
|
|
private function getCurrencies(Community $community): array
|
|
{
|
|
$currencies = iterator_to_array($this->currencyRepository->getAllByCommunity($community));
|
|
usort($currencies, function($a, $b) {
|
|
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;
|
|
}
|
|
|
|
private function checkPermission(
|
|
string $communitySlug,
|
|
bool $needToBeOwner,
|
|
?Community &$community,
|
|
?CommunityMember &$ownCommunityMember): bool
|
|
{
|
|
$community = $this->communityRepository->getBySlug($communitySlug);
|
|
if ($community === null) {
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* @var User $user
|
|
*/
|
|
$user = \Container::$request->user();
|
|
|
|
$ownCommunityMember = $this->communityMemberRepository->getByCommunityAndUser($community, $user);
|
|
if ($ownCommunityMember === null || ($needToBeOwner && !$ownCommunityMember->getOwner())) {
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
}
|