diff --git a/app/Console/Commands/SetupProduction.php b/app/Console/Commands/SetupProduction.php index e2a975b004f..1a309bc9590 100644 --- a/app/Console/Commands/SetupProduction.php +++ b/app/Console/Commands/SetupProduction.php @@ -3,6 +3,7 @@ namespace App\Console\Commands; use function Safe\touch; +use App\Helpers\InstanceHelper; use App\Models\Account\Account; use Illuminate\Console\Command; @@ -67,7 +68,7 @@ public function handle() $this->info('| You can now sign in to your account:'); $this->line('| username: '.$email); $this->line('| password: '); - } elseif (Account::hasAny()) { + } elseif (InstanceHelper::hasAtLeastOneAccount()) { $this->info('| You can now log in to your account'); } else { $this->info('| You can now register to the first account by opening the application:'); diff --git a/app/Helpers/AccountHelper.php b/app/Helpers/AccountHelper.php new file mode 100644 index 00000000000..ddf72731a85 --- /dev/null +++ b/app/Helpers/AccountHelper.php @@ -0,0 +1,202 @@ +has_access_to_paid_version_for_free) { + return false; + } + + if (! config('monica.requires_subscription')) { + return false; + } + + if ($account->isSubscribed()) { + return false; + } + + return true; + } + + /** + * Indicate whether an account has reached the contact limit if the account + * is on a free trial. + * + * @param Account $account + * @return bool + */ + public static function hasReachedContactLimit(Account $account): bool + { + return $account->contacts()->real()->active()->count() >= config('monica.number_of_allowed_contacts_free_account'); + } + + /** + * Check if the account can be downgraded, based on a set of rules. + * + * @param Account $account + * @return bool + */ + public static function canDowngrade(Account $account): bool + { + $canDowngrade = true; + $numberOfUsers = $account->users()->count(); + $numberPendingInvitations = $account->invitations()->count(); + $numberContacts = $account->contacts()->count(); + + // number of users in the account should be == 1 + if ($numberOfUsers > 1) { + $canDowngrade = false; + } + + // there should not be any pending user invitations + if ($numberPendingInvitations > 0) { + $canDowngrade = false; + } + + // there should not be more than the number of contacts allowed + if ($numberContacts > config('monica.number_of_allowed_contacts_free_account')) { + $canDowngrade = false; + } + + return $canDowngrade; + } + + /** + * Get the default gender for this account. + * + * @param Account $account + * @return string + */ + public static function getDefaultGender(Account $account): string + { + $defaultGenderType = Gender::MALE; + + if ($account->default_gender_id) { + $defaultGender = Gender::where([ + 'account_id' => $account->id, + ])->find($account->default_gender_id); + + if ($defaultGender) { + $defaultGenderType = $defaultGender->type; + } + } + + return $defaultGenderType; + } + + /** + * Get the reminders for the month given in parameter. + * - 0 means current month + * - 1 means month+1 + * - 2 means month+2... + * + * @param Account $account + * @param int $month + */ + public static function getUpcomingRemindersForMonth(Account $account, int $month) + { + $startOfMonth = now(DateHelper::getTimezone())->addMonthsNoOverflow($month)->startOfMonth(); + + // don't get reminders for past events: + if ($startOfMonth->isPast()) { + $startOfMonth = now(DateHelper::getTimezone()); + } + + $endOfMonth = now(DateHelper::getTimezone())->addMonthsNoOverflow($month)->endOfMonth(); + + return $account->reminderOutboxes() + ->with(['reminder', 'reminder.contact']) + ->whereBetween('planned_date', [$startOfMonth, $endOfMonth]) + ->where('nature', 'reminder') + ->orderBy('planned_date', 'asc') + ->get(); + } + + /** + * Get the number of activities grouped by year. + * + * @param Account $account + * @return Collection + */ + public static function getYearlyActivitiesStatistics(Account $account): Collection + { + $activitiesStatistics = collect([]); + $activities = $account->activities() + ->select('happened_at') + ->latest('happened_at') + ->get(); + $years = []; + + foreach ($activities as $activity) { + $yearStatistic = $activity->happened_at->format('Y'); + $foundInYear = false; + + foreach ($years as $year => $number) { + if ($year == $yearStatistic) { + $years[$year] = $number + 1; + $foundInYear = true; + } + } + + if (! $foundInYear) { + $years[$yearStatistic] = 1; + } + } + + foreach ($years as $year => $number) { + $activitiesStatistics->put($year, $number); + } + + return $activitiesStatistics; + } + + /** + * Get the number of calls grouped by year. + * + * @return Collection + */ + public static function getYearlyCallStatistics(Account $account): Collection + { + $callsStatistics = collect([]); + $calls = $account->calls() + ->select('called_at') + ->latest('called_at') + ->get(); + $years = []; + + foreach ($calls as $call) { + $yearStatistic = $call->called_at->format('Y'); + $foundInYear = false; + + foreach ($years as $year => $number) { + if ($year == $yearStatistic) { + $years[$year] = $number + 1; + $foundInYear = true; + } + } + + if (! $foundInYear) { + $years[$yearStatistic] = 1; + } + } + + foreach ($years as $year => $number) { + $callsStatistics->put($year, $number); + } + + return $callsStatistics; + } +} diff --git a/app/Helpers/GenderHelper.php b/app/Helpers/GenderHelper.php new file mode 100644 index 00000000000..1f009bc98db --- /dev/null +++ b/app/Helpers/GenderHelper.php @@ -0,0 +1,48 @@ +user()->account->genders->map(function ($gender) { + return [ + 'id' => $gender->id, + 'name' => $gender->name, + ]; + }); + $genders = CollectionHelper::sortByCollator($genders, 'name'); + $genders->prepend(['id' => '', 'name' => trans('app.gender_no_gender')]); + + return $genders; + } + + /** + * Replaces a specific gender of all the contacts in the account with another + * gender. + * + * @param Account $account + * @param Gender $genderToDelete + * @param Gender $genderToReplaceWith + * @return bool + */ + public static function replace(Account $account, Gender $genderToDelete, Gender $genderToReplaceWith): bool + { + Contact::where('account_id', $account->id) + ->where('gender_id', $genderToDelete->id) + ->update(['gender_id' => $genderToReplaceWith->id]); + + return true; + } +} diff --git a/app/Helpers/GendersHelper.php b/app/Helpers/GendersHelper.php deleted file mode 100644 index 807d16182f0..00000000000 --- a/app/Helpers/GendersHelper.php +++ /dev/null @@ -1,25 +0,0 @@ -user()->account->genders->map(function ($gender) { - return [ - 'id' => $gender->id, - 'name' => $gender->name, - ]; - }); - $genders = CollectionHelper::sortByCollator($genders, 'name'); - $genders->prepend(['id' => '', 'name' => trans('app.gender_no_gender')]); - - return $genders; - } -} diff --git a/app/Helpers/InstanceHelper.php b/app/Helpers/InstanceHelper.php index 17ac223602d..668565195b2 100644 --- a/app/Helpers/InstanceHelper.php +++ b/app/Helpers/InstanceHelper.php @@ -4,7 +4,9 @@ use function Safe\json_decode; use App\Models\Account\Account; +use App\Models\Instance\Instance; use App\Models\Settings\Currency; +use Illuminate\Support\Facades\DB; use function Safe\file_get_contents; class InstanceHelper @@ -60,4 +62,14 @@ public static function getChangelogEntries($limit = null) return $changelogs; } + + /** + * Check if the instance has at least one account. + * + * @return bool + */ + public static function hasAtLeastOneAccount(): bool + { + return DB::table('accounts')->count() > 0; + } } diff --git a/app/Helpers/StorageHelper.php b/app/Helpers/StorageHelper.php new file mode 100644 index 00000000000..cba4f8ab387 --- /dev/null +++ b/app/Helpers/StorageHelper.php @@ -0,0 +1,44 @@ +where('account_id', $account->id) + ->sum('filesize'); + $photosSize = DB::table('photos') + ->where('account_id', $account->id) + ->sum('filesize'); + + return $documentsSize + $photosSize; + } + + /** + * Indicates whether the account has the reached the maximum storage size. + * + * @param Account $account + * @return bool + */ + public static function hasReachedAccountStorageLimit(Account $account): bool + { + if (! config('monica.requires_subscription')) { + return false; + } + + $currentAccountSize = self::getAccountStorageSize($account); + + return $currentAccountSize > (config('monica.max_storage_size') * 1000000); + } +} diff --git a/app/Http/Controllers/Api/ApiActivitiesController.php b/app/Http/Controllers/Api/ApiActivitiesController.php index 7d224034d9f..29d67bc60ae 100644 --- a/app/Http/Controllers/Api/ApiActivitiesController.php +++ b/app/Http/Controllers/Api/ApiActivitiesController.php @@ -3,6 +3,7 @@ namespace App\Http\Controllers\Api; use Illuminate\Http\Request; +use App\Helpers\AccountHelper; use App\Models\Contact\Contact; use App\Models\Account\Activity; use Illuminate\Database\QueryException; @@ -31,7 +32,7 @@ public function index(Request $request) } return ActivityResource::collection($activities)->additional(['meta' => [ - 'statistics' => auth()->user()->account->getYearlyActivitiesStatistics(), + 'statistics' => AccountHelper::getYearlyActivitiesStatistics(auth()->user()->account), ]]); } @@ -158,7 +159,7 @@ public function activities(Request $request, $contactId) } return ActivityResource::collection($activities)->additional(['meta' => [ - 'statistics' => auth()->user()->account->getYearlyActivitiesStatistics(), + 'statistics' => AccountHelper::getYearlyActivitiesStatistics(auth()->user()->account), ]]); } } diff --git a/app/Http/Controllers/Api/Contact/ApiCallController.php b/app/Http/Controllers/Api/Contact/ApiCallController.php index 1b5d4a920a3..f73619043d9 100644 --- a/app/Http/Controllers/Api/Contact/ApiCallController.php +++ b/app/Http/Controllers/Api/Contact/ApiCallController.php @@ -4,6 +4,7 @@ use App\Models\Contact\Call; use Illuminate\Http\Request; +use App\Helpers\AccountHelper; use App\Models\Contact\Contact; use Illuminate\Database\QueryException; use App\Services\Contact\Call\CreateCall; @@ -32,7 +33,7 @@ public function index(Request $request) } return CallResource::collection($calls)->additional(['meta' => [ - 'statistics' => auth()->user()->account->getYearlyCallStatistics(), + 'statistics' => AccountHelper::getYearlyCallStatistics(auth()->user()->account), ]]); } @@ -159,7 +160,7 @@ public function calls(Request $request, $contactId) ->paginate($this->getLimitPerPage()); return CallResource::collection($calls)->additional(['meta' => [ - 'statistics' => auth()->user()->account->getYearlyCallStatistics(), + 'statistics' => AccountHelper::getYearlyCallStatistics(auth()->user()->account), ]]); } } diff --git a/app/Http/Controllers/Auth/LoginController.php b/app/Http/Controllers/Auth/LoginController.php index 4f921ff991f..cb33945b5ce 100644 --- a/app/Http/Controllers/Auth/LoginController.php +++ b/app/Http/Controllers/Auth/LoginController.php @@ -2,7 +2,7 @@ namespace App\Http\Controllers\Auth; -use App\Models\Account\Account; +use App\Helpers\InstanceHelper; use App\Http\Controllers\Controller; use Illuminate\Foundation\Auth\AuthenticatesUsers; @@ -40,7 +40,7 @@ public function __construct() public function showLoginOrRegister() { - $first = ! Account::hasAny(); + $first = ! InstanceHelper::hasAtLeastOneAccount(); if ($first) { return redirect()->route('register'); } diff --git a/app/Http/Controllers/Auth/RegisterController.php b/app/Http/Controllers/Auth/RegisterController.php index 961a961900b..f37d2d63e1d 100644 --- a/app/Http/Controllers/Auth/RegisterController.php +++ b/app/Http/Controllers/Auth/RegisterController.php @@ -7,6 +7,7 @@ use App\Helpers\LocaleHelper; use App\Helpers\RequestHelper; use App\Jobs\SendNewUserAlert; +use App\Helpers\InstanceHelper; use App\Models\Account\Account; use Illuminate\Support\Facades\Log; use App\Http\Controllers\Controller; @@ -52,7 +53,7 @@ public function __construct() */ public function showRegistrationForm(Request $request) { - $first = ! Account::hasAny(); + $first = ! InstanceHelper::hasAtLeastOneAccount(); if (config('monica.disable_signup') == 'true' && ! $first) { abort(403, trans('auth.signup_disabled')); } @@ -87,7 +88,7 @@ protected function validator(array $data) */ protected function create(array $data): ?User { - $first = ! Account::hasAny(); + $first = ! InstanceHelper::hasAtLeastOneAccount(); if (config('monica.disable_signup') == 'true' && ! $first) { abort(403, trans('auth.signup_disabled')); } diff --git a/app/Http/Controllers/Contacts/RelationshipsController.php b/app/Http/Controllers/Contacts/RelationshipsController.php index fffac00abba..264ae96a6e5 100644 --- a/app/Http/Controllers/Contacts/RelationshipsController.php +++ b/app/Http/Controllers/Contacts/RelationshipsController.php @@ -2,14 +2,16 @@ namespace App\Http\Controllers\Contacts; +use Illuminate\View\View; use App\Helpers\DateHelper; use App\Helpers\FormHelper; use Illuminate\Http\Request; -use App\Helpers\GendersHelper; +use App\Helpers\GenderHelper; use App\Models\Contact\Contact; use Illuminate\Support\Collection; use App\Http\Controllers\Controller; use Illuminate\Support\Facades\Auth; +use Illuminate\Http\RedirectResponse; use App\Models\Relationship\Relationship; use Illuminate\Support\Facades\Validator; use App\Services\Contact\Contact\CreateContact; @@ -26,7 +28,7 @@ class RelationshipsController extends Controller * * @param Contact $contact * - * @return \Illuminate\View\View + * @return View */ public function create(Request $request, Contact $contact) { @@ -35,7 +37,7 @@ public function create(Request $request, Contact $contact) return view('people.relationship.new') ->withContact($contact) ->withPartner(new Contact) - ->withGenders(GendersHelper::getGendersInput()) + ->withGenders(GenderHelper::getGendersInput()) ->withRelationshipTypes($this->getRelationshipTypesList($contact)) ->withDefaultGender(auth()->user()->account->default_gender_id) ->withDays(DateHelper::getListOfDays()) @@ -52,7 +54,7 @@ public function create(Request $request, Contact $contact) * @param Request $request * @param Contact $contact * - * @return \Illuminate\Http\RedirectResponse + * @return RedirectResponse */ public function store(Request $request, Contact $contact) { @@ -91,7 +93,7 @@ public function store(Request $request, Contact $contact) * @param Contact $contact * @param Relationship $relationship * - * @return \Illuminate\View\View + * @return View */ public function edit(Contact $contact, Relationship $relationship) { @@ -119,7 +121,7 @@ public function edit(Contact $contact, Relationship $relationship) ->withDay($day) ->withMonth($month) ->withAge($age) - ->withGenders(GendersHelper::getGendersInput()) + ->withGenders(GenderHelper::getGendersInput()) ->withHasBirthdayReminder($hasBirthdayReminder) ->withFormNameOrder(FormHelper::getNameOrderForForms(auth()->user())); } @@ -131,7 +133,7 @@ public function edit(Contact $contact, Relationship $relationship) * @param Contact $contact * @param Relationship $relationship * - * @return \Illuminate\Http\RedirectResponse + * @return RedirectResponse */ public function update(Request $request, Contact $contact, Relationship $relationship) { @@ -219,7 +221,7 @@ private function validateAndGetDatas(Request $request) * @param Contact $contact * @param Relationship $relationship * - * @return \Illuminate\Http\RedirectResponse + * @return RedirectResponse */ public function destroy(Contact $contact, Relationship $relationship) { diff --git a/app/Http/Controllers/ContactsController.php b/app/Http/Controllers/ContactsController.php index afb2b288a93..87b2317e2f9 100644 --- a/app/Http/Controllers/ContactsController.php +++ b/app/Http/Controllers/ContactsController.php @@ -9,9 +9,11 @@ use App\Models\Contact\Tag; use Illuminate\Support\Str; use Illuminate\Http\Request; +use App\Helpers\GenderHelper; use App\Helpers\LocaleHelper; use App\Helpers\SearchHelper; -use App\Helpers\GendersHelper; +use App\Helpers\AccountHelper; +use App\Helpers\StorageHelper; use App\Models\Contact\Contact; use App\Services\VCard\ExportVCard; use Illuminate\Support\Facades\Log; @@ -123,7 +125,10 @@ private function contacts(Request $request, bool $active) $contactsCount += $deceasedCount; } + $accountHasLimitations = AccountHelper::hasLimitations(auth()->user()->account); + return view('people.index') + ->withAccountHasLimitations($accountHasLimitations) ->with('hidingDeceased', $showDeceased != 'true') ->with('deceasedCount', $deceasedCount) ->withActive($active) @@ -165,15 +170,18 @@ public function missing() */ private function createForm($isContactMissing = false) { - if (auth()->user()->account->hasReachedContactLimit() - && auth()->user()->account->hasLimitations() + if (AccountHelper::hasReachedContactLimit(auth()->user()->account) + && AccountHelper::hasLimitations(auth()->user()->account) && ! auth()->user()->account->legacy_free_plan_unlimited_contacts) { return redirect()->route('settings.subscriptions.index'); } + $accountHasLimitations = AccountHelper::hasLimitations(auth()->user()->account); + return view('people.create') + ->withAccountHasLimitations($accountHasLimitations) ->withIsContactMissing($isContactMissing) - ->withGenders(GendersHelper::getGendersInput()) + ->withGenders(GenderHelper::getGendersInput()) ->withDefaultGender(auth()->user()->account->default_gender_id) ->withFormNameOrder(FormHelper::getNameOrderForForms(auth()->user())); } @@ -283,7 +291,12 @@ public function show(Contact $contact) 'name' => '---', ]); + $hasReachedAccountStorageLimit = StorageHelper::hasReachedAccountStorageLimit($contact->account); + $accountHasLimitations = AccountHelper::hasLimitations($contact->account); + return view('people.profile') + ->withHasReachedAccountStorageLimit($hasReachedAccountStorageLimit) + ->withAccountHasLimitations($accountHasLimitations) ->withLoveRelationships($loveRelationships) ->withFamilyRelationships($familyRelationships) ->withFriendRelationships($friendRelationships) @@ -316,7 +329,10 @@ public function edit(Contact $contact) $hasBirthdayReminder = ! is_null($contact->birthday_reminder_id); $hasDeceasedReminder = ! is_null($contact->deceased_reminder_id); + $accountHasLimitations = AccountHelper::hasLimitations(auth()->user()->account); + return view('people.edit') + ->withAccountHasLimitations($accountHasLimitations) ->withContact($contact) ->withDays(DateHelper::getListOfDays()) ->withMonths(DateHelper::getListOfMonths()) @@ -328,7 +344,7 @@ public function edit(Contact $contact) ->withAge($age) ->withHasBirthdayReminder($hasBirthdayReminder) ->withHasDeceasedReminder($hasDeceasedReminder) - ->withGenders(GendersHelper::getGendersInput()) + ->withGenders(GenderHelper::getGendersInput()) ->withFormNameOrder(FormHelper::getNameOrderForForms(auth()->user())); } @@ -489,7 +505,10 @@ public function updateWork(Request $request, Contact $contact) */ public function editFoodPreferences(Request $request, Contact $contact) { + $accountHasLimitations = AccountHelper::hasLimitations(auth()->user()->account); + return view('people.food-preferences.edit') + ->withAccountHasLimitations($accountHasLimitations) ->withContact($contact); } @@ -568,7 +587,7 @@ public function stayInTouch(Request $request, Contact $contact) $frequency = intval($request->input('frequency')); $state = $request->input('state'); - if (auth()->user()->account->hasLimitations()) { + if (AccountHelper::hasLimitations(auth()->user()->account)) { throw new \LogicException(trans('people.stay_in_touch_premium')); } diff --git a/app/Http/Controllers/DashboardController.php b/app/Http/Controllers/DashboardController.php index 5fd9e75cf62..4d91539d8b8 100644 --- a/app/Http/Controllers/DashboardController.php +++ b/app/Http/Controllers/DashboardController.php @@ -6,6 +6,7 @@ use App\Helpers\DateHelper; use App\Models\Contact\Debt; use Illuminate\Http\Request; +use App\Helpers\AccountHelper; use function Safe\json_encode; use App\Helpers\InstanceHelper; use Illuminate\Support\Collection; @@ -69,9 +70,9 @@ public function index() // Load the reminderOutboxes for the upcoming three months $reminderOutboxes = [ - 0 => auth()->user()->account->getRemindersForMonth(0), - 1 => auth()->user()->account->getRemindersForMonth(1), - 2 => auth()->user()->account->getRemindersForMonth(2), + 0 => AccountHelper::getUpcomingRemindersForMonth(auth()->user()->account, 0), + 1 => AccountHelper::getUpcomingRemindersForMonth(auth()->user()->account, 1), + 2 => AccountHelper::getUpcomingRemindersForMonth(auth()->user()->account, 2), ]; $data = [ diff --git a/app/Http/Controllers/Settings/AuditLogController.php b/app/Http/Controllers/Settings/AuditLogController.php index 516a45260c7..dda3e6ed737 100644 --- a/app/Http/Controllers/Settings/AuditLogController.php +++ b/app/Http/Controllers/Settings/AuditLogController.php @@ -2,6 +2,7 @@ namespace App\Http\Controllers\Settings; +use App\Helpers\AccountHelper; use App\Helpers\AuditLogHelper; use App\Http\Controllers\Controller; @@ -17,8 +18,11 @@ public function index() ->orderBy('created_at', 'desc') ->paginate(15); + $accountHasLimitations = AccountHelper::hasLimitations(auth()->user()->account); + return view('settings.auditlog.index') ->withLogsCollection(AuditLogHelper::getCollectionOfAuditForSettings($logs)) + ->withAccountHasLimitations($accountHasLimitations) ->withLogsPagination($logs); } } diff --git a/app/Http/Controllers/Settings/GendersController.php b/app/Http/Controllers/Settings/GendersController.php index 1417d810523..feac4a3b7af 100644 --- a/app/Http/Controllers/Settings/GendersController.php +++ b/app/Http/Controllers/Settings/GendersController.php @@ -3,6 +3,7 @@ namespace App\Http\Controllers\Settings; use Illuminate\Http\Request; +use App\Helpers\GenderHelper; use App\Models\Contact\Gender; use App\Helpers\CollectionHelper; use App\Http\Controllers\Controller; @@ -118,7 +119,7 @@ public function destroyAndReplaceGender(GendersRequest $request, Gender $gender, } // We get the new gender to associate the contacts with. - $account->replaceGender($gender, $genderToReplaceWith); + GenderHelper::replace($account, $gender, $genderToReplaceWith); if ($gender->isDefault()) { $account->default_gender_id = $genderToReplaceWith->id; diff --git a/app/Http/Controllers/Settings/PersonalizationController.php b/app/Http/Controllers/Settings/PersonalizationController.php index 1d2def57ced..75c63a59486 100644 --- a/app/Http/Controllers/Settings/PersonalizationController.php +++ b/app/Http/Controllers/Settings/PersonalizationController.php @@ -3,6 +3,7 @@ namespace App\Http\Controllers\Settings; use Illuminate\Http\Request; +use App\Helpers\AccountHelper; use App\Http\Controllers\Controller; use App\Traits\JsonRespondController; use App\Models\Contact\ContactFieldType; @@ -19,7 +20,10 @@ class PersonalizationController extends Controller */ public function index() { - return view('settings.personalization.index'); + $accountHasLimitations = AccountHelper::hasLimitations(auth()->user()->account); + + return view('settings.personalization.index') + ->withAccountHasLimitations($accountHasLimitations); } /** diff --git a/app/Http/Controllers/Settings/StorageController.php b/app/Http/Controllers/Settings/StorageController.php index 98875d963eb..4fbe675030f 100644 --- a/app/Http/Controllers/Settings/StorageController.php +++ b/app/Http/Controllers/Settings/StorageController.php @@ -3,6 +3,8 @@ namespace App\Http\Controllers\Settings; use App\Models\Account\Photo; +use App\Helpers\AccountHelper; +use App\Helpers\StorageHelper; use App\Models\Contact\Document; use App\Http\Controllers\Controller; @@ -22,7 +24,7 @@ public function index() ->get(); // size is in bytes in the database - $currentAccountSize = auth()->user()->account->getStorageSize(); + $currentAccountSize = StorageHelper::getAccountStorageSize(auth()->user()->account); if ($currentAccountSize != 0) { $currentAccountSize = round($currentAccountSize / 1000000); @@ -31,7 +33,10 @@ public function index() // correspondingPercent $percentUsage = round($currentAccountSize * 100 / config('monica.max_storage_size')); + $accountHasLimitations = AccountHelper::hasLimitations(auth()->user()->account); + return view('settings.storage.index') + ->withAccountHasLimitations($accountHasLimitations) ->withDocuments($documents) ->withPhotos($photos) ->withCurrentAccountSize($currentAccountSize) diff --git a/app/Http/Controllers/Settings/SubscriptionsController.php b/app/Http/Controllers/Settings/SubscriptionsController.php index 56a1c1dc8ef..f9411fa40d2 100644 --- a/app/Http/Controllers/Settings/SubscriptionsController.php +++ b/app/Http/Controllers/Settings/SubscriptionsController.php @@ -8,6 +8,7 @@ use Laravel\Cashier\Cashier; use Laravel\Cashier\Payment; use Illuminate\Http\Response; +use App\Helpers\AccountHelper; use App\Helpers\InstanceHelper; use App\Exceptions\StripeException; use Illuminate\Support\Facades\App; @@ -28,28 +29,30 @@ class SubscriptionsController extends Controller */ public function index() { + $account = auth()->user()->account; + if (! config('monica.requires_subscription')) { return redirect()->route('settings.index'); } - $subscription = auth()->user()->account->getSubscribedPlan(); - if (! auth()->user()->account->isSubscribed() && (! $subscription || $subscription->ended())) { + $subscription = $account->getSubscribedPlan(); + if (! $account->isSubscribed() && (! $subscription || $subscription->ended())) { return view('settings.subscriptions.blank', [ 'numberOfCustomers' => InstanceHelper::getNumberOfPaidSubscribers(), ]); } - $planId = auth()->user()->account->getSubscribedPlanId(); + $planId = $account->getSubscribedPlanId(); try { - $nextBillingDate = auth()->user()->account->getNextBillingDate(); + $nextBillingDate = $account->getNextBillingDate(); } catch (StripeException $e) { $nextBillingDate = trans('app.unknown'); } - $hasInvoices = auth()->user()->account->hasStripeId() && auth()->user()->account->hasInvoices(); + $hasInvoices = $account->hasStripeId() && $account->hasInvoices(); $invoices = null; if ($hasInvoices) { - $invoices = auth()->user()->account->invoices(); + $invoices = $account->invoices(); } return view('settings.subscriptions.account', [ @@ -58,6 +61,7 @@ public function index() 'subscription' => $subscription, 'hasInvoices' => $hasInvoices, 'invoices' => $invoices, + 'accountHasLimitations' => AccountHelper::hasLimitations($account), ]); } @@ -168,15 +172,18 @@ public function downgrade() return redirect()->route('settings.index'); } - $subscription = auth()->user()->account->getSubscribedPlan(); - if (! auth()->user()->account->isSubscribed() && ! $subscription) { + $subscription = $account->getSubscribedPlan(); + if (! $account->isSubscribed() && ! $subscription) { return redirect()->route('settings.index'); } return view('settings.subscriptions.downgrade-checklist') ->with('numberOfActiveContacts', $account->contacts()->active()->count()) ->with('numberOfPendingInvitations', $account->invitations()->count()) - ->with('numberOfUsers', $account->users()->count()); + ->with('numberOfUsers', $account->users()->count()) + ->with('accountHasLimitations', AccountHelper::hasLimitations($account)) + ->with('hasReachedContactLimit', AccountHelper::hasReachedContactLimit($account)) + ->with('canDowngrade', AccountHelper::canDowngrade($account)); } /** @@ -186,7 +193,7 @@ public function downgrade() */ public function processDowngrade() { - if (! auth()->user()->account->canDowngrade()) { + if (! AccountHelper::canDowngrade(auth()->user()->account)) { return redirect()->route('settings.subscriptions.downgrade'); } @@ -238,10 +245,10 @@ public function processPayment(Request $request) /** * Download the invoice as PDF. * - * @param int $invoiceId + * @param mixed $invoiceId * @return Response */ - public function downloadInvoice(int $invoiceId) + public function downloadInvoice($invoiceId) { return auth()->user()->account->downloadInvoice($invoiceId, [ 'vendor' => 'Monica', diff --git a/app/Http/Controllers/SettingsController.php b/app/Http/Controllers/SettingsController.php index 660d7224dd2..a2efdcd3586 100644 --- a/app/Http/Controllers/SettingsController.php +++ b/app/Http/Controllers/SettingsController.php @@ -8,6 +8,7 @@ use Illuminate\Support\Str; use Illuminate\Http\Request; use App\Helpers\LocaleHelper; +use App\Helpers\AccountHelper; use App\Helpers\TimezoneHelper; use App\Jobs\ExportAccountAsSQL; use App\Jobs\AddContactFromVCard; @@ -50,7 +51,10 @@ public function index() 'nickname', ]; + $accountHasLimitations = AccountHelper::hasLimitations(auth()->user()->account); + return view('settings.index') + ->withAccountHasLimitations($accountHasLimitations) ->withNamesOrder($namesOrder) ->withLocales(LocaleHelper::getLocaleList()->sortByCollator('name-orig')) ->withHours(DateHelper::getListOfHours()) @@ -152,7 +156,8 @@ public function reset(Request $request) */ public function export() { - return view('settings.export'); + return view('settings.export') + ->with('accountHasLimitations', AccountHelper::hasLimitations(auth()->user()->account)); } /** @@ -178,11 +183,15 @@ public function exportToSql() */ public function import() { + $accountHasLimitations = AccountHelper::hasLimitations(auth()->user()->account); + if (auth()->user()->account->importjobs->count() == 0) { - return view('settings.imports.blank'); + return view('settings.imports.blank') + ->withAccountHasLimitations($accountHasLimitations); } - return view('settings.imports.index'); + return view('settings.imports.index') + ->withAccountHasLimitations($accountHasLimitations); } /** @@ -235,12 +244,15 @@ public function report($importJobId) public function users() { $users = auth()->user()->account->users; + $accountHasLimitations = AccountHelper::hasLimitations(auth()->user()->account); if ($users->count() == 1 && auth()->user()->account->invitations()->count() == 0) { - return view('settings.users.blank'); + return view('settings.users.blank') + ->withAccountHasLimitations($accountHasLimitations); } - return view('settings.users.index', compact('users')); + return view('settings.users.index', compact('users')) + ->withAccountHasLimitations($accountHasLimitations); } /** @@ -347,7 +359,8 @@ public function deleteAdditionalUser($userID) */ public function tags() { - return view('settings.tags'); + return view('settings.tags') + ->with('accountHasLimitations', AccountHelper::hasLimitations(auth()->user()->account)); } /** @@ -370,7 +383,8 @@ public function deleteTag($tagId) public function api() { - return view('settings.api.index'); + return view('settings.api.index') + ->with('accountHasLimitations', AccountHelper::hasLimitations(auth()->user()->account)); } public function dav() @@ -382,7 +396,8 @@ public function dav() ->withDavRoute($davroute) ->withCardDavRoute("{$davroute}/addressbooks/{$email}/contacts") ->withCalDavBirthdaysRoute("{$davroute}/calendars/{$email}/birthdays") - ->withCalDavTasksRoute("{$davroute}/calendars/{$email}/tasks"); + ->withCalDavTasksRoute("{$davroute}/calendars/{$email}/tasks") + ->with('accountHasLimitations', AccountHelper::hasLimitations(auth()->user()->account)); } public function security() @@ -395,7 +410,8 @@ public function security() return view('settings.security.index') ->with('is2FAActivated', Google2FA::isActivated()) ->with('currentkeys', U2fKeyResource::collection($u2fKeys)) - ->withWebauthnKeys(WebauthnKeyResource::collection($webauthnKeys)); + ->withWebauthnKeys(WebauthnKeyResource::collection($webauthnKeys)) + ->with('accountHasLimitations', AccountHelper::hasLimitations(auth()->user()->account)); } /** diff --git a/app/Http/Middleware/CheckAccountLimitations.php b/app/Http/Middleware/CheckAccountLimitations.php index 74db09f2e8a..40a98e090b5 100644 --- a/app/Http/Middleware/CheckAccountLimitations.php +++ b/app/Http/Middleware/CheckAccountLimitations.php @@ -3,6 +3,7 @@ namespace App\Http\Middleware; use Closure; +use App\Helpers\AccountHelper; use Illuminate\Support\Facades\Auth; class CheckAccountLimitations @@ -16,7 +17,7 @@ class CheckAccountLimitations */ public function handle($request, Closure $next) { - if (Auth::check() && auth()->user()->account->hasLimitations()) { + if (Auth::check() && AccountHelper::hasLimitations(auth()->user()->account)) { abort(402); } diff --git a/app/Jobs/Reminder/NotifyUserAboutReminder.php b/app/Jobs/Reminder/NotifyUserAboutReminder.php index df979df92d5..a4e78438329 100644 --- a/app/Jobs/Reminder/NotifyUserAboutReminder.php +++ b/app/Jobs/Reminder/NotifyUserAboutReminder.php @@ -3,6 +3,7 @@ namespace App\Jobs\Reminder; use Illuminate\Bus\Queueable; +use App\Helpers\AccountHelper; use App\Notifications\UserNotified; use App\Notifications\UserReminded; use App\Interfaces\MailNotification; @@ -44,7 +45,9 @@ public function handle() if (! is_null($message)) { // send the notification to this user - if (! $this->reminderOutbox->user->account->hasLimitations()) { + $account = $this->reminderOutbox->user->account; + $hasLimitations = AccountHelper::hasLimitations($account); + if (! $hasLimitations) { Notification::send($this->reminderOutbox->user, $message); } diff --git a/app/Jobs/StayInTouch/ScheduleStayInTouch.php b/app/Jobs/StayInTouch/ScheduleStayInTouch.php index b7c67775ef7..c34ffb3e978 100644 --- a/app/Jobs/StayInTouch/ScheduleStayInTouch.php +++ b/app/Jobs/StayInTouch/ScheduleStayInTouch.php @@ -3,6 +3,7 @@ namespace App\Jobs\StayInTouch; use Illuminate\Bus\Queueable; +use App\Helpers\AccountHelper; use App\Models\Contact\Contact; use Illuminate\Queue\SerializesModels; use App\Notifications\StayInTouchEmail; @@ -39,7 +40,7 @@ public function handle() $users = []; foreach ($account->users as $user) { if ($user->isTheRightTimeToBeReminded($this->contact->stay_in_touch_trigger_date) - && ! $account->hasLimitations()) { + && ! AccountHelper::hasLimitations($account)) { array_push($users, $user); } } diff --git a/app/Models/Account/Account.php b/app/Models/Account/Account.php index 55edcdc9533..be83bab97ee 100644 --- a/app/Models/Account/Account.php +++ b/app/Models/Account/Account.php @@ -3,7 +3,6 @@ namespace App\Models\Account; use App\Models\User\User; -use App\Helpers\DateHelper; use App\Models\Contact\Tag; use App\Models\Journal\Day; use App\Models\User\Module; @@ -481,7 +480,7 @@ public function occupations() } /** - * Get the Audit log records associated with the account. + * * Get the Audit log records associated with the account. * * @return HasMany */ @@ -490,86 +489,6 @@ public function auditLogs() return $this->hasMany(AuditLog::class); } - /** - * Check if the account can be downgraded, based on a set of rules. - * - * @return bool - */ - public function canDowngrade() - { - $canDowngrade = true; - $numberOfUsers = $this->users()->count(); - $numberPendingInvitations = $this->invitations()->count(); - $numberContacts = $this->contacts()->count(); - - // number of users in the account should be == 1 - if ($numberOfUsers > 1) { - $canDowngrade = false; - } - - // there should not be any pending user invitations - if ($numberPendingInvitations > 0) { - $canDowngrade = false; - } - - // there should not be more than the number of contacts allowed - if ($numberContacts > config('monica.number_of_allowed_contacts_free_account')) { - $canDowngrade = false; - } - - return $canDowngrade; - } - - /** - * Indicates whether the current account has limitations with her current - * plan. - * - * @return bool - */ - public function hasLimitations() - { - if ($this->has_access_to_paid_version_for_free) { - return false; - } - - if (! config('monica.requires_subscription')) { - return false; - } - - if ($this->isSubscribed()) { - return false; - } - - return true; - } - - /** - * Indicate whether an account has reached the contact limit if the account - * is on a free trial. - * - * @return bool - */ - public function hasReachedContactLimit() - { - return $this->contacts()->real()->active()->count() >= config('monica.number_of_allowed_contacts_free_account'); - } - - /** - * Get the timezone of the user. In case an account has multiple timezones, - * takes the first it finds. - * @return string - */ - public function timezone() - { - try { - $user = $this->users()->firstOrFail(); - } catch (ModelNotFoundException $e) { - return ''; - } - - return $user->timezone; - } - /** * Populates the Activity Type table right after an account is * created. @@ -672,77 +591,6 @@ public function populateRelationshipTypesTable($migrateOnlyNewTypes = false) } } - /** - * Get the reminders for the month given in parameter. - * - 0 means current month - * - 1 means month+1 - * - 2 means month+2... - * @param int $month - */ - public function getRemindersForMonth(int $month) - { - $startOfMonth = now(DateHelper::getTimezone())->addMonthsNoOverflow($month)->startOfMonth(); - // don't get reminders for past events: - if ($startOfMonth->isPast()) { - $startOfMonth = now(DateHelper::getTimezone()); - } - $endOfMonth = now(DateHelper::getTimezone())->addMonthsNoOverflow($month)->endOfMonth(); - - return $this->reminderOutboxes() - ->with(['reminder', 'reminder.contact']) - ->whereBetween('planned_date', [$startOfMonth, $endOfMonth]) - ->where('nature', 'reminder') - ->orderBy('planned_date', 'asc') - ->get(); - } - - /** - * Replaces a specific gender of all the contacts in the account with another - * gender. - * - * @param Gender $genderToDelete - * @param Gender $genderToReplaceWith - * @return bool - */ - public function replaceGender(Gender $genderToDelete, Gender $genderToReplaceWith) - { - Contact::where('account_id', $this->id) - ->where('gender_id', $genderToDelete->id) - ->update(['gender_id' => $genderToReplaceWith->id]); - - return true; - } - - /** - * Get the default gender for this account. - * - * @return string - */ - public function defaultGender() - { - $defaultGenderType = Gender::MALE; - if ($this->default_gender_id) { - $defaultGender = Gender::where([ - 'account_id' => $this->id, - ])->find($this->default_gender_id); - if ($defaultGender) { - $defaultGenderType = $defaultGender->type; - } - } - - return $defaultGenderType; - } - - /** - * Get if any account exists on the database. - * - * @return bool - */ - public static function hasAny() - { - return DB::table('accounts')->count() > 0; - } - /** * Create a new account and associate a new User. * @@ -832,76 +680,6 @@ public function getRelationshipTypeGroupByType(string $relationshipTypeGroupName return $this->relationshipTypeGroups->where('name', $relationshipTypeGroupName)->first(); } - /** - * Get the statistics of the number of calls grouped by year. - * - * @return \Illuminate\Support\Collection - */ - public function getYearlyCallStatistics() - { - $callsStatistics = collect([]); - $calls = $this->calls()->latest('called_at')->get(); - $years = []; - - // Create a table that contains the combo year/number of - foreach ($calls as $call) { - $yearStatistic = $call->called_at->format('Y'); - $foundInYear = false; - - foreach ($years as $year => $number) { - if ($year == $yearStatistic) { - $years[$year] = $number + 1; - $foundInYear = true; - } - } - - if (! $foundInYear) { - $years[$yearStatistic] = 1; - } - } - - foreach ($years as $year => $number) { - $callsStatistics->put($year, $number); - } - - return $callsStatistics; - } - - /** - * Get the statistics of the number of activities grouped by year. - * - * @return \Illuminate\Support\Collection - */ - public function getYearlyActivitiesStatistics() - { - $activitiesStatistics = collect([]); - $activities = $this->activities()->latest('happened_at')->get(); - $years = []; - - // Create a table that contains the combo year/number of - foreach ($activities as $call) { - $yearStatistic = $call->happened_at->format('Y'); - $foundInYear = false; - - foreach ($years as $year => $number) { - if ($year == $yearStatistic) { - $years[$year] = $number + 1; - $foundInYear = true; - } - } - - if (! $foundInYear) { - $years[$yearStatistic] = 1; - } - } - - foreach ($years as $year => $number) { - $activitiesStatistics->put($year, $number); - } - - return $activitiesStatistics; - } - /** * Get the first available locale in an account. This gets the first user * in the account and reads his locale. @@ -920,44 +698,4 @@ public function getFirstLocale() return $user->locale; } - - /** - * Indicates whether the account has the reached the maximum storage size - * for document upload. - * - * @return bool - */ - public function hasReachedAccountStorageLimit() - { - if (! config('monica.requires_subscription')) { - return false; - } - - $currentAccountSize = $this->getStorageSize(); - - return $currentAccountSize > (config('monica.max_storage_size') * 1000000); - } - - /** - * Get the storage size of the account, in bytes. - * - * @return int - */ - public function getStorageSize() - { - $documents = Document::where('account_id', $this->id) - ->orderBy('created_at', 'desc')->get(); - $photos = Photo::where('account_id', $this->id) - ->orderBy('created_at', 'desc')->get(); - - $currentAccountSize = 0; - foreach ($documents as $document) { - $currentAccountSize += $document->filesize; - } - foreach ($photos as $photo) { - $currentAccountSize += $photo->filesize; - } - - return $currentAccountSize; - } } diff --git a/app/Models/Relationship/RelationshipType.php b/app/Models/Relationship/RelationshipType.php index 7ca5c63d3af..ab905eae84c 100644 --- a/app/Models/Relationship/RelationshipType.php +++ b/app/Models/Relationship/RelationshipType.php @@ -2,6 +2,7 @@ namespace App\Models\Relationship; +use App\Helpers\AccountHelper; use App\Models\Contact\Gender; use App\Models\Account\Account; use App\Models\Contact\Contact; @@ -71,7 +72,8 @@ public function reverseRelationshipType() */ public function getLocalizedName(Contact $contact = null, bool $includeOpposite = false, string $gender = null) { - $defaultGender = $this->account->defaultGender(); + $defaultGender = AccountHelper::getDefaultGender($this->account); + if (is_null($gender)) { $gender = $defaultGender; } diff --git a/app/Services/Contact/Contact/SetMeContact.php b/app/Services/Contact/Contact/SetMeContact.php index 378298df0ee..5e43f2f6a30 100644 --- a/app/Services/Contact/Contact/SetMeContact.php +++ b/app/Services/Contact/Contact/SetMeContact.php @@ -4,6 +4,7 @@ use App\Models\User\User; use App\Services\BaseService; +use App\Helpers\AccountHelper; use App\Models\Contact\Contact; class SetMeContact extends BaseService @@ -35,7 +36,7 @@ public function execute(array $data): User $user = User::where('account_id', $data['account_id']) ->findOrFail($data['user_id']); - if ($user->account->hasLimitations()) { + if (AccountHelper::hasLimitations($user->account)) { abort(402); } diff --git a/resources/views/auth/login.blade.php b/resources/views/auth/login.blade.php index fcc4f5b788a..bd40da67b8c 100644 --- a/resources/views/auth/login.blade.php +++ b/resources/views/auth/login.blade.php @@ -70,7 +70,7 @@ diff --git a/resources/views/auth/oauthlogin.blade.php b/resources/views/auth/oauthlogin.blade.php index 650d9a7cf13..e99f3d5683e 100644 --- a/resources/views/auth/oauthlogin.blade.php +++ b/resources/views/auth/oauthlogin.blade.php @@ -46,7 +46,7 @@ diff --git a/resources/views/partials/components/people-upgrade-sidebar.blade.php b/resources/views/partials/components/people-upgrade-sidebar.blade.php index 9e2efe96254..c8fafb29cde 100644 --- a/resources/views/partials/components/people-upgrade-sidebar.blade.php +++ b/resources/views/partials/components/people-upgrade-sidebar.blade.php @@ -1,4 +1,4 @@ -@if (auth()->user()->account->hasLimitations()) +@if ($accountHasLimitations)
@@ -8,4 +8,4 @@
-@endif \ No newline at end of file +@endif diff --git a/resources/views/people/_header.blade.php b/resources/views/people/_header.blade.php index a07022cc915..8e65cdf1175 100644 --- a/resources/views/people/_header.blade.php +++ b/resources/views/people/_header.blade.php @@ -111,7 +111,7 @@ @if(!$contact->is_dead)
  • @include('partials.icons.header_stayintouch') - +
  • @endif diff --git a/resources/views/people/create.blade.php b/resources/views/people/create.blade.php index 83d3becfadc..05e43967030 100644 --- a/resources/views/people/create.blade.php +++ b/resources/views/people/create.blade.php @@ -10,7 +10,7 @@

    {{ trans('people.people_add_title') }}

    @endif - @if (! auth()->user()->account->hasLimitations()) + @if (! $accountHasLimitations)

    {!! trans('people.people_add_import', ['url' => route('settings.import')]) !!}

    @endif diff --git a/resources/views/people/documents/index.blade.php b/resources/views/people/documents/index.blade.php index 2e839465c3e..ecbd7a1c6f8 100644 --- a/resources/views/people/documents/index.blade.php +++ b/resources/views/people/documents/index.blade.php @@ -1,7 +1,7 @@
    - @if (config('monica.requires_subscription') && auth()->user()->account->hasLimitations()) + @if (config('monica.requires_subscription') && $accountHasLimitations)

    @@ -15,7 +15,7 @@ @else - + @endif

    diff --git a/resources/views/people/edit.blade.php b/resources/views/people/edit.blade.php index 8037348dc9e..18d2499af81 100644 --- a/resources/views/people/edit.blade.php +++ b/resources/views/people/edit.blade.php @@ -8,7 +8,7 @@

    < {{ $contact->name }}

    {{ trans('people.information_edit_title', ['name' => $contact->first_name]) }}

    - @if (! auth()->user()->account->hasLimitations()) + @if (! $accountHasLimitations)

    {!! trans('people.people_add_import', ['url' => 'settings/import']) !!}

    @endif
    diff --git a/resources/views/people/gifts/index.blade.php b/resources/views/people/gifts/index.blade.php index ce1c5ea0ff4..e8dcc640e4d 100644 --- a/resources/views/people/gifts/index.blade.php +++ b/resources/views/people/gifts/index.blade.php @@ -9,7 +9,7 @@ 'name' => $familyRelationship->ofContact->first_name, ]; }) }}" - :reach-limit="{{ \Safe\json_encode(auth()->user()->account->hasReachedAccountStorageLimit()) }}" + :reach-limit="{{ \Safe\json_encode($hasReachedAccountStorageLimit) }}" >
    diff --git a/resources/views/people/photos/index.blade.php b/resources/views/people/photos/index.blade.php index 5750ae4e88f..5565ee78067 100644 --- a/resources/views/people/photos/index.blade.php +++ b/resources/views/people/photos/index.blade.php @@ -5,7 +5,7 @@ contact-id="{{ $contact->id }}" contact-name="'{{ $contact->first_name }}''" current-photo-id-as-avatar="{{ $contact->avatar_photo_id }}" - reach-limit="{{ \Safe\json_encode($contact->account->hasReachedAccountStorageLimit()) }}" + reach-limit="{{ \Safe\json_encode($hasReachedAccountStorageLimit) }}" > diff --git a/resources/views/people/reminders/index.blade.php b/resources/views/people/reminders/index.blade.php index 51b95fe441c..f329f23da82 100644 --- a/resources/views/people/reminders/index.blade.php +++ b/resources/views/people/reminders/index.blade.php @@ -23,7 +23,7 @@
    - @if (! auth()->user()->account->hasLimitations()) + @if (! $accountHasLimitations)

    {{ trans('people.reminders_description') }}

    @else

    {{ trans('people.reminders_free_plan_warning') }}

    diff --git a/resources/views/settings/_sidebar.blade.php b/resources/views/settings/_sidebar.blade.php index 63e948cada7..282340b8a50 100644 --- a/resources/views/settings/_sidebar.blade.php +++ b/resources/views/settings/_sidebar.blade.php @@ -57,7 +57,7 @@ 'title' => 'settings.sidebar_settings_api']) @endcomponent - @if (config('laravelsabre.enabled') && ! auth()->user()->account->hasLimitations()) + @if (config('laravelsabre.enabled') && ! $accountHasLimitations) @component('components.sidebar', [ 'route' => 'settings.dav', 'icon' => 'fa fa-calendar', diff --git a/resources/views/settings/imports/blank.blade.php b/resources/views/settings/imports/blank.blade.php index 86dc93978b9..47dc809b878 100644 --- a/resources/views/settings/imports/blank.blade.php +++ b/resources/views/settings/imports/blank.blade.php @@ -45,7 +45,7 @@

    {{ trans('settings.import_blank_cta') }}

    - @if (config('monica.requires_subscription') && auth()->user()->account->hasLimitations()) + @if (config('monica.requires_subscription') && $accountHasLimitations)

    {{ trans('settings.import_need_subscription') }}

    @endif
    diff --git a/resources/views/settings/personalization/index.blade.php b/resources/views/settings/personalization/index.blade.php index 6051b0a7266..1e7caefd114 100644 --- a/resources/views/settings/personalization/index.blade.php +++ b/resources/views/settings/personalization/index.blade.php @@ -57,13 +57,13 @@
    - +
    - +
    diff --git a/resources/views/settings/subscriptions/downgrade-checklist.blade.php b/resources/views/settings/subscriptions/downgrade-checklist.blade.php index a940d9dc002..4c7d8a579b0 100644 --- a/resources/views/settings/subscriptions/downgrade-checklist.blade.php +++ b/resources/views/settings/subscriptions/downgrade-checklist.blade.php @@ -49,11 +49,11 @@ {!! trans_choice('settings.subscriptions_downgrade_rule_invitations_constraint', $numberOfPendingInvitations, ['url' => route('settings.users.index'), 'count' => $numberOfPendingInvitations]) !!} -
  • +
  • {{ trans('settings.subscriptions_downgrade_rule_contacts', ['number' => config('monica.number_of_allowed_contacts_free_account')]) }} {!! trans_choice('settings.subscriptions_downgrade_rule_contacts_constraint', $numberOfActiveContacts, ['url' => '/people', 'count' => $numberOfActiveContacts]) !!} - @if ((auth()->user()->account->hasReachedContactLimit() == true)) + @if ($hasReachedContactLimit) We can also archive all your contacts for you - that would clear this rule and let you proceed with your account’s downgrade process. @endif
  • @@ -63,7 +63,7 @@
    @csrf - @if (auth()->user()->account->canDowngrade()) + @if ($canDowngrade)

    @else

    diff --git a/resources/views/settings/users/blank.blade.php b/resources/views/settings/users/blank.blade.php index a4df5e56528..986b91f25f8 100644 --- a/resources/views/settings/users/blank.blade.php +++ b/resources/views/settings/users/blank.blade.php @@ -45,7 +45,7 @@

    {{ trans('settings.users_blank_cta') }}

    - @if (config('monica.requires_subscription') && auth()->user()->account->hasLimitations()) + @if (config('monica.requires_subscription') && $accountHasLimitations)

    {{ trans('settings.users_invitation_need_subscription') }}

    @endif diff --git a/tests/Unit/Helpers/AccountHelperTest.php b/tests/Unit/Helpers/AccountHelperTest.php new file mode 100644 index 00000000000..aa010c63434 --- /dev/null +++ b/tests/Unit/Helpers/AccountHelperTest.php @@ -0,0 +1,267 @@ +make([ + 'has_access_to_paid_version_for_free' => true, + ]); + + $this->assertEquals( + false, + AccountHelper::hasLimitations($account) + ); + + // Check that if the ENV variable REQUIRES_SUBSCRIPTION has an effect + $account = factory(Account::class)->make([ + 'has_access_to_paid_version_for_free' => false, + ]); + + config(['monica.requires_subscription' => false]); + + $this->assertEquals( + false, + AccountHelper::hasLimitations($account) + ); + } + + /** @test */ + public function account_has_reached_contact_limit_on_free_plan(): void + { + $account = factory(Account::class)->create(); + factory(Contact::class, 2)->create([ + 'account_id' => $account->id, + ]); + + config(['monica.number_of_allowed_contacts_free_account' => 1]); + $this->assertTrue( + AccountHelper::hasReachedContactLimit($account) + ); + + factory(Contact::class)->state('partial')->create([ + 'account_id' => $account->id, + ]); + + config(['monica.number_of_allowed_contacts_free_account' => 3]); + $this->assertFalse( + AccountHelper::hasReachedContactLimit($account) + ); + + config(['monica.number_of_allowed_contacts_free_account' => 100]); + $this->assertFalse( + AccountHelper::hasReachedContactLimit($account) + ); + + $account = factory(Account::class)->create(); + factory(Contact::class, 2)->create([ + 'account_id' => $account->id, + 'is_active' => false, + ]); + factory(Contact::class, 3)->create([ + 'account_id' => $account->id, + 'is_active' => true, + ]); + + config(['monica.number_of_allowed_contacts_free_account' => 3]); + $this->assertTrue( + AccountHelper::hasReachedContactLimit($account) + ); + } + + /** @test */ + public function user_can_downgrade_with_only_one_user_and_no_pending_invitations_and_under_contact_limit(): void + { + config(['monica.number_of_allowed_contacts_free_account' => 1]); + $contact = factory(Contact::class)->create(); + + factory(User::class)->create([ + 'account_id' => $contact->account->id, + ]); + + $this->assertEquals( + true, + AccountHelper::canDowngrade($contact->account) + ); + } + + /** @test */ + public function user_cant_downgrade_with_two_users(): void + { + $contact = factory(Contact::class)->create(); + + factory(User::class, 3)->create([ + 'account_id' => $contact->account->id, + ]); + + $this->assertEquals( + false, + AccountHelper::canDowngrade($contact->account) + ); + } + + /** @test */ + public function user_cant_downgrade_with_pending_invitations(): void + { + $account = factory(Account::class)->create(); + + factory(Invitation::class)->create([ + 'account_id' => $account->id, + ]); + + $this->assertEquals( + false, + AccountHelper::canDowngrade($account) + ); + } + + /** @test */ + public function user_cant_downgrade_with_too_many_contacts(): void + { + config(['monica.number_of_allowed_contacts_free_account' => 1]); + $account = factory(Account::class)->create(); + + factory(Contact::class, 2)->create([ + 'account_id' => $account->id, + ]); + + $this->assertFalse( + AccountHelper::canDowngrade($account) + ); + } + + /** @test */ + public function it_gets_the_default_gender_for_the_account(): void + { + $account = factory(Account::class)->create(); + + $this->assertEquals( + Gender::MALE, + AccountHelper::getDefaultGender($account) + ); + + $gender = factory(Gender::class)->create([ + 'account_id' => $account->id, + ]); + $account->default_gender_id = $gender->id; + $account->save(); + + $this->assertEquals( + $gender->type, + AccountHelper::getDefaultGender($account) + ); + } + + /** @test */ + public function get_reminders_for_month_returns_no_reminders(): void + { + $account = factory(Account::class)->create(); + + Carbon::setTestNow(Carbon::create(2017, 1, 1)); + factory(Reminder::class, 3)->create([ + 'account_id' => $account->id, + ]); + + // check if there are reminders for the month of March + $this->assertEquals( + 0, + AccountHelper::getUpcomingRemindersForMonth($account, 3)->count() + ); + } + + /** @test */ + public function get_reminders_for_month_returns_reminders_for_given_month(): void + { + $account = factory(Account::class)->create(); + $user = factory(User::class)->create([ + 'account_id' => $account->id, + ]); + + Carbon::setTestNow(Carbon::create(2017, 1, 1)); + + // add 3 reminders for the month of March + for ($i = 0; $i < 3; $i++) { + $reminder = factory(Reminder::class)->create([ + 'account_id' => $account->id, + 'initial_date' => '2017-03-03 00:00:00', + ]); + + $reminder->schedule($user); + } + + $this->assertEquals( + 3, + AccountHelper::getUpcomingRemindersForMonth($account, 2)->count() + ); + } + + /** @test */ + public function it_retrieves_yearly_activities_statistics(): void + { + $account = factory(Account::class)->create(); + factory(Activity::class, 4)->create([ + 'account_id' => $account->id, + 'happened_at' => '2018-03-02', + ]); + + factory(Activity::class, 2)->create([ + 'account_id' => $account->id, + 'happened_at' => '1992-03-02', + ]); + + $statistics = AccountHelper::getYearlyActivitiesStatistics($account); + + $this->assertEquals( + [ + 1992 => 2, + 2018 => 4, + ], + $statistics->toArray() + ); + } + + /** @test */ + public function it_retrieves_yearly_call_statistics(): void + { + $contact = factory(Contact::class)->create(); + factory(Call::class, 4)->create([ + 'account_id' => $contact->account_id, + 'contact_id' => $contact->id, + 'called_at' => '2018-03-02', + ]); + + factory(Call::class, 2)->create([ + 'account_id' => $contact->account_id, + 'contact_id' => $contact->id, + 'called_at' => '1992-03-02', + ]); + + $statistics = AccountHelper::getYearlyCallStatistics($contact->account); + + $this->assertEquals( + [ + 1992 => 2, + 2018 => 4, + ], + $statistics->toArray() + ); + } +} diff --git a/tests/Unit/Helpers/GenderHelperTest.php b/tests/Unit/Helpers/GenderHelperTest.php index 2f90b68a359..654c1b60fe4 100644 --- a/tests/Unit/Helpers/GenderHelperTest.php +++ b/tests/Unit/Helpers/GenderHelperTest.php @@ -3,7 +3,10 @@ namespace Tests\Unit\Helpers; use Tests\FeatureTestCase; -use App\Helpers\GendersHelper; +use App\Helpers\GenderHelper; +use App\Models\Contact\Gender; +use App\Models\Account\Account; +use App\Models\Contact\Contact; class GenderHelperTest extends FeatureTestCase { @@ -12,7 +15,7 @@ public function it_gets_all_the_gender_inputs() { $this->signIn(); - $genders = GendersHelper::getGendersInput(); + $genders = GenderHelper::getGendersInput(); $this->assertCount(4, $genders); $this->assertEquals([ @@ -20,4 +23,32 @@ public function it_gets_all_the_gender_inputs() 'name' => 'No gender', ], $genders[0]); } + + /** @test */ + public function it_replaces_gender_with_another_gender() + { + $account = factory(Account::class)->create(); + $male = factory(Gender::class)->create([ + 'account_id' => $account->id, + ]); + $female = factory(Gender::class)->create([ + 'account_id' => $account->id, + ]); + + factory(Contact::class, 2)->create([ + 'account_id' => $account->id, + 'gender_id' => $male, + ]); + factory(Contact::class)->create([ + 'account_id' => $account->id, + 'gender_id' => $female, + ]); + + GenderHelper::replace($account, $male, $female); + + $this->assertEquals( + 3, + $female->contacts->count() + ); + } } diff --git a/tests/Unit/Helpers/InstanceHelperTest.php b/tests/Unit/Helpers/InstanceHelperTest.php index 03d8bea98fe..342e5061dcc 100644 --- a/tests/Unit/Helpers/InstanceHelperTest.php +++ b/tests/Unit/Helpers/InstanceHelperTest.php @@ -6,6 +6,7 @@ use function Safe\json_decode; use App\Helpers\InstanceHelper; use App\Models\Account\Account; +use Illuminate\Support\Facades\DB; use Illuminate\Foundation\Testing\DatabaseTransactions; class InstanceHelperTest extends TestCase @@ -118,4 +119,19 @@ public function it_gets_latest_changelog_entries() InstanceHelper::getChangelogEntries(3) ); } + + /** @test */ + public function it_checks_if_the_instance_has_at_least_one_account() + { + DB::table('accounts')->delete(); + + $this->assertFalse( + InstanceHelper::hasAtLeastOneAccount() + ); + + factory(Account::class)->create(); + $this->assertTrue( + InstanceHelper::hasAtLeastOneAccount() + ); + } } diff --git a/tests/Unit/Helpers/StorageHelperTest.php b/tests/Unit/Helpers/StorageHelperTest.php new file mode 100644 index 00000000000..c2694001f7d --- /dev/null +++ b/tests/Unit/Helpers/StorageHelperTest.php @@ -0,0 +1,68 @@ +create([]); + + factory(Document::class)->create([ + 'filesize' => 1000000, + 'account_id' => $account->id, + ]); + + factory(Photo::class)->create([ + 'filesize' => 1000000, + 'account_id' => $account->id, + ]); + + $this->assertEquals( + 2000000, + StorageHelper::getAccountStorageSize($account) + ); + } + + /** @test */ + public function it_tests_account_storage_limit(): void + { + config(['monica.requires_subscription' => true]); + $account = factory(Account::class)->create([]); + + factory(Document::class)->create([ + 'filesize' => 1000000, + 'account_id' => $account->id, + ]); + + config(['monica.max_storage_size' => 0.1]); + $this->assertTrue(StorageHelper::hasReachedAccountStorageLimit($account)); + + config(['monica.max_storage_size' => 1]); + $this->assertFalse(StorageHelper::hasReachedAccountStorageLimit($account)); + + factory(Photo::class)->create([ + 'filesize' => 1000000, + 'account_id' => $account->id, + ]); + + config(['monica.max_storage_size' => 2]); + $this->assertFalse(StorageHelper::hasReachedAccountStorageLimit($account)); + + config(['monica.max_storage_size' => 1]); + $this->assertTrue(StorageHelper::hasReachedAccountStorageLimit($account)); + + config(['monica.requires_subscription' => false]); + $this->assertFalse(StorageHelper::hasReachedAccountStorageLimit($account)); + } +} diff --git a/tests/Unit/Models/AccountTest.php b/tests/Unit/Models/AccountTest.php index a52dd312fcb..f9b2d053da6 100644 --- a/tests/Unit/Models/AccountTest.php +++ b/tests/Unit/Models/AccountTest.php @@ -2,11 +2,9 @@ namespace Tests\Unit\Models; -use Carbon\Carbon; use App\Models\User\User; use Tests\FeatureTestCase; use App\Models\User\Module; -use App\Models\Contact\Call; use App\Models\Account\Photo; use App\Models\Account\Place; use App\Models\Contact\Gender; @@ -16,12 +14,9 @@ use App\Models\Contact\Address; use App\Models\Contact\Contact; use App\Models\Contact\Message; -use App\Models\Account\Activity; use App\Models\Contact\Document; -use App\Models\Contact\Reminder; use App\Models\Contact\LifeEvent; use App\Models\Instance\AuditLog; -use App\Models\Account\Invitation; use App\Models\Contact\Occupation; use Illuminate\Support\Facades\DB; use App\Models\Account\ActivityType; @@ -264,73 +259,6 @@ public function it_has_many_logs() $this->assertTrue($account->auditLogs()->exists()); } - /** @test */ - public function user_can_downgrade_with_only_one_user_and_no_pending_invitations_and_under_contact_limit() - { - config(['monica.number_of_allowed_contacts_free_account' => 1]); - $contact = factory(Contact::class)->create(); - $account = $contact->account; - - $user = factory(User::class)->create([ - 'account_id' => $account->id, - ]); - - $this->assertEquals( - true, - $account->canDowngrade() - ); - } - - /** @test */ - public function user_cant_downgrade_with_two_users() - { - $contact = factory(Contact::class)->create(); - $account = $contact->account; - - $user = factory(User::class)->create([ - 'account_id' => $account->id, - ]); - - $user = factory(User::class)->create([ - 'account_id' => $account->id, - ]); - - $this->assertEquals( - false, - $account->canDowngrade() - ); - } - - /** @test */ - public function user_cant_downgrade_with_pending_invitations() - { - $account = factory(Account::class)->create(); - - $invitation = factory(Invitation::class)->create([ - 'account_id' => $account->id, - ]); - - $this->assertEquals( - false, - $account->canDowngrade() - ); - } - - /** @test */ - public function user_cant_downgrade_with_too_many_contacts() - { - config(['monica.number_of_allowed_contacts_free_account' => 1]); - $account = factory(Account::class)->create(); - - $contact = factory(Contact::class, 2)->create([ - 'account_id' => $account->id, - ]); - - $this->assertFalse( - $account->canDowngrade() - ); - } - /** @test */ public function user_is_subscribed_if_user_can_access_to_paid_version_for_free() { @@ -408,52 +336,6 @@ public function user_is_subscribed_returns_false_if_no_plan_is_set() ); } - /** @test */ - public function user_has_limitations_if_not_subscribed_or_exempted_of_subscriptions() - { - $account = factory(Account::class)->make([ - 'has_access_to_paid_version_for_free' => true, - ]); - - $this->assertEquals( - false, - $account->hasLimitations() - ); - - // Check that if the ENV variable REQUIRES_SUBSCRIPTION has an effect - $account = factory(Account::class)->make([ - 'has_access_to_paid_version_for_free' => false, - ]); - - config(['monica.requires_subscription' => false]); - - $this->assertEquals( - false, - $account->hasLimitations() - ); - } - - /** @test */ - public function get_timezone_gets_the_first_timezone_it_finds() - { - $account = factory(Account::class)->create(); - - $user1 = factory(User::class)->create([ - 'account_id' => $account->id, - 'timezone' => 'EN_en', - ]); - - $user2 = factory(User::class)->create([ - 'account_id' => $account->id, - 'timezone' => 'DE_de', - ]); - - $this->assertEquals( - 'EN_en', - $account->timezone() - ); - } - /** @test */ public function has_invoices_returns_true_if_a_plan_exists() { @@ -477,48 +359,6 @@ public function has_invoices_returns_false_if_a_plan_does_not_exist() $this->assertFalse($account->hasInvoices()); } - /** @test */ - public function get_reminders_for_month_returns_no_reminders() - { - $user = $this->signIn(); - - $account = $user->account; - - Carbon::setTestNow(Carbon::create(2017, 1, 1)); - factory(Reminder::class, 3)->create(['account_id' => $account->id]); - - // check if there are reminders for the month of March - $this->assertEquals( - 0, - $account->getRemindersForMonth(3)->count() - ); - } - - /** @test */ - public function get_reminders_for_month_returns_reminders_for_given_month() - { - $user = $this->signIn(); - - $account = $user->account; - - Carbon::setTestNow(Carbon::create(2017, 1, 1)); - - // add 3 reminders for the month of March - for ($i = 0; $i < 3; $i++) { - $reminder = factory(Reminder::class)->create([ - 'account_id' => $account->id, - 'initial_date' => '2017-03-03 00:00:00', - ]); - - $reminder->schedule($user); - } - - $this->assertEquals( - 3, - $account->getRemindersForMonth(2)->count() - ); - } - /** @test */ public function it_gets_the_id_of_the_subscribed_plan() { @@ -603,28 +443,6 @@ public function it_populates_the_account_with_the_right_default_genders() ); } - /** @test */ - public function it_replaces_gender_with_another_gender() - { - $account = factory(Account::class)->create(); - $gender1 = factory(Gender::class)->create([ - 'account_id' => $account->id, - ]); - $gender2 = factory(Gender::class)->create([ - 'account_id' => $account->id, - ]); - - $contact = factory(Contact::class)->create(['account_id' => $account->id, 'gender_id' => $gender1]); - $contact = factory(Contact::class)->create(['account_id' => $account->id, 'gender_id' => $gender1]); - $contact = factory(Contact::class)->create(['account_id' => $account->id, 'gender_id' => $gender2]); - - $account->replaceGender($gender1, $gender2); - $this->assertEquals( - 3, - $gender2->contacts->count() - ); - } - /** @test */ public function it_gets_default_time_reminder_is_sent_attribute() { @@ -777,58 +595,6 @@ public function it_skips_default_relationship_types_table_for_types_already_migr ]); } - /** @test */ - public function it_retrieves_yearly_call_statistics() - { - $contact = factory(Contact::class)->create(); - $calls = factory(Call::class, 4)->create([ - 'account_id' => $contact->account_id, - 'contact_id' => $contact->id, - 'called_at' => '2018-03-02', - ]); - - $calls = factory(Call::class, 2)->create([ - 'account_id' => $contact->account_id, - 'contact_id' => $contact->id, - 'called_at' => '1992-03-02', - ]); - - $statistics = $contact->account->getYearlyCallStatistics(); - - $this->assertTrue( - $statistics->contains(4) - ); - - $this->assertTrue( - $statistics->contains(2) - ); - } - - /** @test */ - public function it_retrieves_yearly_activities_statistics() - { - $account = factory(Account::class)->create(); - $contact = factory(Activity::class, 4)->create([ - 'account_id' => $account->id, - 'happened_at' => '2018-03-02', - ]); - - $contact = factory(Activity::class, 2)->create([ - 'account_id' => $account->id, - 'happened_at' => '1992-03-02', - ]); - - $statistics = $account->getYearlyActivitiesStatistics(); - - $this->assertTrue( - $statistics->contains(4) - ); - - $this->assertTrue( - $statistics->contains(2) - ); - } - /** @test */ public function it_create_default_account() { @@ -858,50 +624,6 @@ public function it_throw_an_exception_if_user_already_exist() $account = Account::createDefault('John', 'Doe', 'john@doe.com', 'password'); } - /** @test */ - public function account_has_reached_contact_limit_on_free_plan() - { - $account = factory(Account::class)->create(); - factory(Contact::class, 11)->create([ - 'account_id' => $account->id, - ]); - - config(['monica.number_of_allowed_contacts_free_account' => 10]); - - $this->assertTrue( - $account->hasReachedContactLimit() - ); - - factory(Contact::class, 5)->state('partial')->create([ - 'account_id' => $account->id, - ]); - - config(['monica.number_of_allowed_contacts_free_account' => 15]); - - $this->assertFalse( - $account->hasReachedContactLimit() - ); - config(['monica.number_of_allowed_contacts_free_account' => 100]); - - $this->assertFalse( - $account->hasReachedContactLimit() - ); - - config(['monica.number_of_allowed_contacts_free_account' => 3]); - $account = factory(Account::class)->create(); - factory(Contact::class, 2)->create([ - 'account_id' => $account->id, - 'is_active' => false, - ]); - factory(Contact::class, 3)->create([ - 'account_id' => $account->id, - 'is_active' => true, - ]); - $this->assertTrue( - $account->hasReachedContactLimit() - ); - } - /** @test */ public function it_gets_first_user_locale() { @@ -949,57 +671,4 @@ public function it_populates_default_life_event_tables_upon_creation() DB::table('life_event_types')->where('account_id', $account->id)->get()->count() ); } - - /** @test */ - public function it_tests_account_storage_limit() - { - config(['monica.requires_subscription' => true]); - $account = factory(Account::class)->create([]); - - $document = factory(Document::class)->create([ - 'filesize' => 1000000, - 'account_id' => $account->id, - ]); - - config(['monica.max_storage_size' => 0.1]); - $this->assertTrue($account->hasReachedAccountStorageLimit()); - - config(['monica.max_storage_size' => 1]); - $this->assertFalse($account->hasReachedAccountStorageLimit()); - - $photo = factory(Photo::class)->create([ - 'filesize' => 1000000, - 'account_id' => $account->id, - ]); - - config(['monica.max_storage_size' => 2]); - $this->assertFalse($account->hasReachedAccountStorageLimit()); - - config(['monica.max_storage_size' => 1]); - $this->assertTrue($account->hasReachedAccountStorageLimit()); - - config(['monica.requires_subscription' => false]); - $this->assertFalse($account->hasReachedAccountStorageLimit()); - } - - /** @test */ - public function it_calculates_storage_size() - { - $account = factory(Account::class)->create([]); - - $document = factory(Document::class)->create([ - 'filesize' => 1000000, - 'account_id' => $account->id, - ]); - - $photo = factory(Photo::class)->create([ - 'filesize' => 1000000, - 'account_id' => $account->id, - ]); - - $this->assertEquals( - 2000000, - $account->getStorageSize() - ); - } }