Skip to content

Commit 14461ab

Browse files
feat: add mediator role (#571)
Co-authored-by: Lupu Gheorghe <gheorghelupu17@gmail.com>
1 parent d68d9f6 commit 14461ab

87 files changed

Lines changed: 1321 additions & 232 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,3 +37,6 @@ GEMINI.md
3737
AGENTS.md
3838
boost.json
3939
/.github/copilot-instructions.md
40+
/.claude
41+
/.cursor
42+
/.junie

app/Concerns/BelongsToMediator.php

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace App\Concerns;
6+
7+
use App\Models\User;
8+
use Illuminate\Database\Eloquent\Builder;
9+
use Illuminate\Database\Eloquent\Relations\BelongsTo;
10+
11+
trait BelongsToMediator
12+
{
13+
public function initializeBelongsToMediator(): void
14+
{
15+
$this->fillable[] = 'mediator_id';
16+
}
17+
18+
public static function bootBelongsToMediator(): void
19+
{
20+
static::creating(function (self $model): void {
21+
if (auth()->user()?->isMediator()) {
22+
$model->mediator_id = auth()->id();
23+
}
24+
});
25+
}
26+
27+
public function mediator(): BelongsTo
28+
{
29+
return $this->belongsTo(User::class, 'mediator_id')->onlyMediators();
30+
}
31+
32+
public function scopeForMediator(Builder $query, User $user): Builder
33+
{
34+
return $query->where("{$query->getModel()->getTable()}.mediator_id", $user->id);
35+
}
36+
}

app/Concerns/BelongsToNurse.php

Lines changed: 5 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -17,12 +17,10 @@ public function initializeBelongsToNurse(): void
1717

1818
public static function bootBelongsToNurse(): void
1919
{
20-
static::addGlobalScope('forCurrentUser', function (Builder $builder) {
21-
if (! auth()->check()) {
22-
return;
20+
static::creating(function (self $model): void {
21+
if (auth()->user()?->isNurse()) {
22+
$model->nurse_id = auth()->id();
2323
}
24-
25-
$builder->forUser(auth()->user());
2624
});
2725
}
2826

@@ -31,18 +29,8 @@ public function nurse(): BelongsTo
3129
return $this->belongsTo(User::class)->onlyNurses();
3230
}
3331

34-
public function scopeForUser(Builder $query, User $user): Builder
32+
public function scopeForNurse(Builder $query, User $user): Builder
3533
{
36-
if ($user->isNurse()) {
37-
$table = $query->getModel()->getTable();
38-
39-
return $query->where("{$table}.nurse_id", $user->id);
40-
}
41-
42-
if ($user->isCoordinator()) {
43-
return $query->whereRelation('nurse', 'activity_county_id', $user->county_id);
44-
}
45-
46-
return $query;
34+
return $query->where("{$query->getModel()->getTable()}.nurse_id", $user->id);
4735
}
4836
}
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace App\Concerns;
6+
7+
use App\Models\User;
8+
use Illuminate\Database\Eloquent\Builder;
9+
10+
trait BelongsToNurseOrMediator
11+
{
12+
use BelongsToNurse;
13+
use BelongsToMediator;
14+
15+
public static function bootBelongsToNurseOrMediator(): void
16+
{
17+
static::addGlobalScope('forCurrentUser', function (Builder $builder) {
18+
if (! auth()->check()) {
19+
return;
20+
}
21+
22+
$builder->forUser(auth()->user());
23+
});
24+
}
25+
26+
public function scopeForUser(Builder $query, User $user): Builder
27+
{
28+
return match (true) {
29+
$user->isNurse() => $query->forNurse($user),
30+
$user->isMediator() => $query->forMediator($user),
31+
$user->isCoordinator() => $query->forCoordinator($user),
32+
$user->isAdmin() => $query,
33+
};
34+
}
35+
36+
public function scopeForCoordinator(Builder $query, User $user): Builder
37+
{
38+
return $query->where(
39+
fn (Builder $query): Builder => $query
40+
->whereRelation('nurse', 'activity_county_id', $user->county_id)
41+
->orWhereRelation('mediator', 'activity_county_id', $user->county_id)
42+
);
43+
}
44+
}

app/Concerns/BelongsToNurseThroughBeneficiary.php

Lines changed: 30 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -26,14 +26,37 @@ public static function bootBelongsToNurseThroughBeneficiary(): void
2626

2727
public function scopeForUser(Builder $query, User $user): Builder
2828
{
29-
if ($user->isNurse()) {
30-
return $query->whereRelation('beneficiary', 'nurse_id', $user->id);
31-
}
29+
return match (true) {
30+
$user->isNurse() => $query->forNurse($user),
31+
$user->isMediator() => $query->forMediator($user),
32+
$user->isCoordinator() => $query->forCoordinator($user),
33+
$user->isAdmin() => $query,
34+
};
35+
}
3236

33-
if ($user->isCoordinator()) {
34-
return $query->whereRelation('beneficiary.nurse', 'activity_county_id', $user->county_id);
35-
}
37+
public function scopeForNurse(Builder $query, User $user): Builder
38+
{
39+
return $query->whereRelation('beneficiary', 'nurse_id', $user->id);
40+
}
3641

37-
return $query;
42+
public function scopeForMediator(Builder $query, User $user): Builder
43+
{
44+
return $query->where(
45+
fn (Builder $query): Builder => $query
46+
->whereRelation('beneficiary', 'mediator_id', $user->id)
47+
->when(
48+
$this->isFillable('mediator_has_access'),
49+
fn (Builder $query): Builder => $query->where('mediator_has_access', true)
50+
)
51+
);
52+
}
53+
54+
public function scopeForCoordinator(Builder $query, User $user): Builder
55+
{
56+
return $query->where(
57+
fn (Builder $query): Builder => $query
58+
->whereRelation('beneficiary.nurse', 'activity_county_id', $user->county_id)
59+
->orWhereRelation('beneficiary.mediator', 'activity_county_id', $user->county_id)
60+
);
3861
}
3962
}

app/Concerns/BelongsToUser.php

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace App\Concerns;
6+
7+
use App\Models\User;
8+
use Illuminate\Database\Eloquent\Builder;
9+
use Illuminate\Database\Eloquent\Relations\BelongsTo;
10+
11+
trait BelongsToUser
12+
{
13+
public function initializeBelongsToUser(): void
14+
{
15+
$this->fillable[] = 'user_id';
16+
}
17+
18+
public static function bootBelongsToUser(): void
19+
{
20+
static::addGlobalScope('forCurrentUser', function (Builder $builder) {
21+
if (! auth()->check()) {
22+
return;
23+
}
24+
25+
$builder->forUser(auth()->user());
26+
});
27+
28+
static::creating(function (self $model): void {
29+
if (blank($model->user_id)) {
30+
$model->user_id = auth()?->id();
31+
}
32+
});
33+
}
34+
35+
public function user(): BelongsTo
36+
{
37+
return $this->belongsTo(User::class);
38+
}
39+
40+
public function restrictScopeToCurrentUser(): bool
41+
{
42+
return false;
43+
}
44+
45+
public function scopeForUser(Builder $query, User $user): Builder
46+
{
47+
if (
48+
$this->restrictScopeToCurrentUser() ||
49+
$user->isNurseOrMediator()
50+
) {
51+
return $query->where('user_id', $user->id);
52+
}
53+
54+
if ($user->isCoordinator()) {
55+
return $query->whereRelation('user', 'activity_county_id', $user->county_id);
56+
}
57+
58+
return $query;
59+
}
60+
}

app/Concerns/HasActivityAreas.php

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,11 @@ public function scopeActivatesInCounty(Builder $query, int $county_id): Builder
3232
return $query->where('activity_county_id', $county_id);
3333
}
3434

35+
public function scopeActivatesInCurrentUserCounty(Builder $query): Builder
36+
{
37+
return $query->where('activity_county_id', auth()->user()->activity_county_id ?? auth()->user()->county_id);
38+
}
39+
3540
public function scopeWithActivityAreas(Builder $query): Builder
3641
{
3742
return $query->with('activityCounty', 'activityCities');

app/Concerns/Users/HasRole.php

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,16 @@ public function isNurse(): bool
3131
return $this->role->is(Role::NURSE);
3232
}
3333

34+
public function isMediator(): bool
35+
{
36+
return $this->role->is(Role::MEDIATOR);
37+
}
38+
39+
public function isNurseOrMediator(): bool
40+
{
41+
return $this->isNurse() || $this->isMediator();
42+
}
43+
3444
public function scopeOnlyAdmins(Builder $query): Builder
3545
{
3646
return $query->where('role', Role::ADMIN);
@@ -45,4 +55,14 @@ public function scopeOnlyNurses(Builder $query): Builder
4555
{
4656
return $query->where('role', Role::NURSE);
4757
}
58+
59+
public function scopeOnlyMediators(Builder $query): Builder
60+
{
61+
return $query->where('role', Role::MEDIATOR);
62+
}
63+
64+
public function scopeOnlyNursesAndMediators(Builder $query): Builder
65+
{
66+
return $query->whereIn('role', [Role::NURSE, Role::MEDIATOR]);
67+
}
4868
}

app/Contracts/Enums/CanBeFiltered.php

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,9 @@
44

55
namespace App\Contracts\Enums;
66

7-
use App\Enums\Report\Type;
87
use BackedEnum;
98

109
interface CanBeFiltered extends BackedEnum
1110
{
12-
public function isVisible(?Type $type = null): bool;
11+
public function isVisible(): bool;
1312
}

app/Contracts/UserScopable.php

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace App\Contracts;
6+
7+
use App\Models\User;
8+
use Illuminate\Database\Eloquent\Builder;
9+
10+
interface UserScopable
11+
{
12+
public function scopeForUser(Builder $query, User $user): Builder;
13+
}

0 commit comments

Comments
 (0)