@@ -41,7 +41,7 @@ class ConflictDeclaration extends Model
|
||||
/** @param Builder<ConflictDeclaration> $query */
|
||||
public function scopeVisibleTo(Builder $query, User $user): void
|
||||
{
|
||||
if (! in_array($user->purchasing_role, [PurchasingRole::Admin, PurchasingRole::Finance])) {
|
||||
if (! $user->hasFunctions([PurchasingRole::Admin, PurchasingRole::Finance])) {
|
||||
$query->where('user_id', $user->id);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ namespace App\Models;
|
||||
|
||||
use App\Models\Concerns\AppendOnlyInventoryRecord;
|
||||
use App\Models\Concerns\BelongsToTenant;
|
||||
use Carbon\CarbonInterface;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\Relations\HasMany;
|
||||
|
||||
@@ -12,6 +13,7 @@ use Illuminate\Database\Eloquent\Relations\HasMany;
|
||||
* @property int $tenant_id
|
||||
* @property int $purchase_order_id
|
||||
* @property int $received_by
|
||||
* @property CarbonInterface $received_on
|
||||
* @property string $payload_hash
|
||||
* @property array<string, mixed> $snapshot
|
||||
*/
|
||||
|
||||
@@ -18,11 +18,11 @@ class PurchasePlanItem extends Model
|
||||
/** @param Builder<PurchasePlanItem> $query */
|
||||
public function scopeVisibleTo(Builder $query, User $user): void
|
||||
{
|
||||
match ($user->purchasing_role) {
|
||||
PurchasingRole::Admin, PurchasingRole::Procurement, PurchasingRole::Finance => null,
|
||||
PurchasingRole::DepartmentHead => $query->where(fn ($visible) => $visible->where('department_id', $user->department_id)->orWhere('responsible_id', $user->id)),
|
||||
default => $query->where('responsible_id', $user->id),
|
||||
};
|
||||
if ($user->departmentScoped()) {
|
||||
$query->where(fn ($visible) => $visible->where('department_id', $user->department_id)->orWhere('responsible_id', $user->id));
|
||||
} elseif (! $user->hasFunctions([PurchasingRole::Admin, PurchasingRole::Procurement, PurchasingRole::Finance])) {
|
||||
$query->where('responsible_id', $user->id);
|
||||
}
|
||||
}
|
||||
|
||||
protected static function booted(): void
|
||||
|
||||
@@ -7,7 +7,7 @@ use App\Models\Concerns\BelongsToTenant;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
/**
|
||||
* @property array{analyst:array{id:int,name:string,purchasing_role:string},basis_hash:string} $snapshot
|
||||
* @property array{analyst:array{id:int,name:string,purchasing_role:string,profile_label?:string},basis_hash:string} $snapshot
|
||||
* @property list<array{criterion_id:int,result:string,evidence:string,reason:string}> $answers
|
||||
*/
|
||||
class QualificationAssessment extends Model
|
||||
|
||||
@@ -68,11 +68,11 @@ class Requisition extends Model
|
||||
/** @param Builder<Requisition> $query */
|
||||
public function scopeVisibleTo(Builder $query, User $user): void
|
||||
{
|
||||
match ($user->purchasing_role) {
|
||||
PurchasingRole::Admin, PurchasingRole::Procurement, PurchasingRole::Finance => null,
|
||||
PurchasingRole::DepartmentHead => $query->where('department_id', $user->department_id),
|
||||
default => $query->where('requester_id', $user->id),
|
||||
};
|
||||
if ($user->departmentScoped()) {
|
||||
$query->where('department_id', $user->department_id);
|
||||
} elseif (! $user->hasFunctions([PurchasingRole::Admin, PurchasingRole::Procurement, PurchasingRole::Finance])) {
|
||||
$query->where('requester_id', $user->id);
|
||||
}
|
||||
}
|
||||
|
||||
public function canDecide(User $user): bool
|
||||
@@ -87,7 +87,7 @@ class Requisition extends Model
|
||||
|
||||
$next = $this->steps->firstWhere('decision', 'pending');
|
||||
|
||||
return $next !== null && $next->role === $user->purchasing_role->value
|
||||
return $next !== null && $user->hasFunctions([$next->role])
|
||||
&& ($next->role !== 'department_head' || $this->department_id === $user->department_id)
|
||||
&& ! app(ConflictGuard::class)->participationBlocked($user, $this);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,52 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use App\Models\Concerns\BelongsToTenant;
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
/** @property int $id
|
||||
* @property int $tenant_id
|
||||
* @property int $supplier_id
|
||||
* @property int|null $department_id
|
||||
* @property int $created_by
|
||||
* @property int $version
|
||||
* @property int $revision
|
||||
* @property string $status
|
||||
* @property array<string,mixed> $payload
|
||||
* @property array<string,mixed> $supplier_snapshot
|
||||
* @property list<int> $contributors
|
||||
*/
|
||||
class SupplierEvaluation extends Model
|
||||
{
|
||||
use BelongsToTenant;
|
||||
|
||||
protected $guarded = ['id'];
|
||||
|
||||
protected $attributes = ['version' => 1, 'revision' => 1, 'status' => 'draft'];
|
||||
|
||||
protected function casts(): array
|
||||
{
|
||||
return ['payload' => 'array', 'supplier_snapshot' => 'array', 'contributors' => 'array', 'reviewed_at' => 'datetime'];
|
||||
}
|
||||
|
||||
/** @param Builder<SupplierEvaluation> $query */
|
||||
public function scopeVisibleTo(Builder $query, User $actor): void
|
||||
{
|
||||
$query->where('tenant_id', $actor->tenant_id);
|
||||
if ($actor->departmentScoped()) {
|
||||
$query->where('department_id', $actor->department_id ?? 0);
|
||||
}
|
||||
}
|
||||
|
||||
protected static function booted(): void
|
||||
{
|
||||
static::updating(function (self $evaluation) {
|
||||
if ($evaluation->getRawOriginal('status') === 'approved') {
|
||||
throw new \LogicException('A avaliação aprovada conserva-se; prepare uma nova revisão.');
|
||||
}
|
||||
});
|
||||
static::deleting(fn () => throw new \LogicException('Preservar o histórico de avaliações.'));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use App\Models\Concerns\BelongsToTenant;
|
||||
use Carbon\CarbonInterface;
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||
|
||||
/**
|
||||
* @property int $id
|
||||
* @property int $tenant_id
|
||||
* @property int $supplier_evaluation_id
|
||||
* @property int $created_by
|
||||
* @property int $responsible_id
|
||||
* @property int $version
|
||||
* @property string $status
|
||||
* @property list<int> $contributors
|
||||
* @property CarbonInterface|null $reviewed_at
|
||||
*/
|
||||
class SupplierImprovement extends Model
|
||||
{
|
||||
use BelongsToTenant;
|
||||
|
||||
protected $guarded = ['id'];
|
||||
|
||||
protected $attributes = ['version' => 1, 'status' => 'open'];
|
||||
|
||||
protected function casts(): array
|
||||
{
|
||||
return ['contributors' => 'array', 'reviewed_at' => 'datetime'];
|
||||
}
|
||||
|
||||
/** @param Builder<SupplierImprovement> $query */
|
||||
public function scopeVisibleTo(Builder $query, User $actor): void
|
||||
{
|
||||
$query->where('tenant_id', $actor->tenant_id)->whereIn('supplier_evaluation_id', SupplierEvaluation::query()->visibleTo($actor)->select('id'));
|
||||
}
|
||||
|
||||
/** @return BelongsTo<SupplierEvaluation, $this> */
|
||||
public function evaluation(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(SupplierEvaluation::class, 'supplier_evaluation_id');
|
||||
}
|
||||
|
||||
/** @return BelongsTo<User, $this> */
|
||||
public function responsible(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(User::class, 'responsible_id');
|
||||
}
|
||||
|
||||
protected static function booted(): void
|
||||
{
|
||||
static::updating(function (self $measure) {
|
||||
if ($measure->getRawOriginal('status') === 'closed') {
|
||||
throw new \LogicException('A medida encerrada conserva-se no histórico.');
|
||||
}
|
||||
});
|
||||
static::deleting(fn () => throw new \LogicException('Preservar as medidas de melhoria.'));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use App\Models\Concerns\BelongsToTenant;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
/**
|
||||
* @property int $id
|
||||
* @property int $tenant_id
|
||||
* @property int $supplier_evaluation_id
|
||||
* @property int $created_by
|
||||
* @property int $version
|
||||
* @property string $status
|
||||
* @property array<string,mixed> $payload
|
||||
* @property list<int> $contributors
|
||||
* @property array<string,mixed>|null $decision
|
||||
*/
|
||||
class SupplierResponse extends Model
|
||||
{
|
||||
use BelongsToTenant;
|
||||
|
||||
protected $guarded = ['id'];
|
||||
|
||||
protected $attributes = ['status' => 'draft', 'version' => 1];
|
||||
|
||||
protected function casts(): array
|
||||
{
|
||||
return ['payload' => 'array', 'contributors' => 'array', 'decision' => 'array', 'reviewed_at' => 'datetime'];
|
||||
}
|
||||
|
||||
protected static function booted(): void
|
||||
{
|
||||
static::updating(function (self $record) {
|
||||
if ($record->getRawOriginal('status') === 'decided') {
|
||||
throw new \LogicException('A conclusão registada conserva-se no histórico.');
|
||||
}
|
||||
});
|
||||
static::deleting(fn () => throw new \LogicException('Preservar o contraditório do fornecedor.'));
|
||||
}
|
||||
}
|
||||
+13
-1
@@ -3,6 +3,7 @@
|
||||
namespace App\Models;
|
||||
|
||||
use App\Enums\PurchasingRole;
|
||||
use App\Services\OrganizationAccess;
|
||||
use Database\Factories\UserFactory;
|
||||
use Illuminate\Database\Eloquent\Attributes\Fillable;
|
||||
use Illuminate\Database\Eloquent\Attributes\Hidden;
|
||||
@@ -15,7 +16,7 @@ use Illuminate\Support\Carbon;
|
||||
* @property int $id
|
||||
* @property int|null $tenant_id
|
||||
* @property int|null $department_id
|
||||
* @property PurchasingRole $purchasing_role
|
||||
* @property PurchasingRole|null $purchasing_role
|
||||
* @property string $name
|
||||
* @property string $email
|
||||
* @property Carbon|null $email_verified_at
|
||||
@@ -31,6 +32,17 @@ use Illuminate\Support\Carbon;
|
||||
#[Hidden(['password', 'two_factor_secret', 'two_factor_recovery_codes', 'remember_token'])]
|
||||
class User extends Authenticatable
|
||||
{
|
||||
/** @param list<PurchasingRole|string> $functions */
|
||||
public function hasFunctions(array $functions): bool
|
||||
{
|
||||
return app(OrganizationAccess::class)->allows($this, $functions);
|
||||
}
|
||||
|
||||
public function departmentScoped(): bool
|
||||
{
|
||||
return app(OrganizationAccess::class)->departmentScoped($this);
|
||||
}
|
||||
|
||||
/** @use HasFactory<UserFactory> */
|
||||
use HasFactory, Notifiable;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user