This commit is contained in:
2026-11-02 08:08:05 +02:00
parent 13a6cb9922
commit 504b01b244
246 changed files with 24499 additions and 185 deletions
+4
View File
@@ -6,6 +6,10 @@ use App\Models\Concerns\BelongsToTenant;
use Illuminate\Database\Eloquent\Model;
use LogicException;
/**
* @property array<string,mixed>|null $before
* @property array<string,mixed> $after
*/
class AuditLog extends Model
{
use BelongsToTenant;
+43
View File
@@ -0,0 +1,43 @@
<?php
namespace App\Models\Concerns;
use App\Models\User;
use App\Services\WorkContext;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Validation\ValidationException;
trait HasWorkContext
{
protected static function bootHasWorkContext(): void
{
static::addGlobalScope('work_context', function (Builder $query) {
if (! app()->bound('request') || ! request()->hasSession() || request()->is('candidaturas/*')) {
return;
}
$actor = request()->user('web');
if ($actor instanceof User && app(WorkContext::class)->enforced($actor)) {
$key = app(WorkContext::class)->active(request());
$query->where($query->getModel()->qualifyColumn('work_context_key'), $key ?? '__no_context__');
}
});
static::creating(function (Model $model) {
if (! app()->bound('request') || ! request()->hasSession()) {
return;
}
$actor = request()->user('web');
if ($actor instanceof User && app(WorkContext::class)->enforced($actor)) {
$key = app(WorkContext::class)->active(request());
$area = $model->getTable() === 'people_processes' ? 'people' : 'procurement';
abort_unless($key !== null && WorkContext::OPTIONS[$key]['operational'] && WorkContext::OPTIONS[$key]['area'] === $area, 403);
$model->setAttribute('work_context_key', $key);
}
});
static::updating(function (Model $model) {
if ($model->isDirty('work_context_key')) {
throw ValidationException::withMessages(['context' => 'O contexto de origem do processo não pode ser alterado.']);
}
});
}
}
+1
View File
@@ -6,6 +6,7 @@ use App\Models\Concerns\AppendOnlyInventoryRecord;
use App\Models\Concerns\BelongsToTenant;
use Illuminate\Database\Eloquent\Model;
/** @property array<string,mixed> $snapshot */
class GoodsReceiptItem extends Model
{
use AppendOnlyInventoryRecord, BelongsToTenant;
+22
View File
@@ -0,0 +1,22 @@
<?php
namespace App\Models;
use App\Models\Concerns\BelongsToTenant;
use Illuminate\Database\Eloquent\Model;
/** @property int $lot_id */
class InventoryLotAllocation extends Model
{
use BelongsToTenant;
public $timestamps = false;
protected $guarded = ['id'];
protected static function booted(): void
{
static::updating(fn () => throw new \LogicException('Preservar repartições de lotes.'));
static::deleting(fn () => throw new \LogicException('Preservar repartições de lotes.'));
}
}
+2
View File
@@ -3,6 +3,7 @@
namespace App\Models;
use App\Models\Concerns\BelongsToTenant;
use App\Models\Concerns\HasWorkContext;
use Illuminate\Database\Eloquent\Model;
/**
@@ -22,6 +23,7 @@ use Illuminate\Database\Eloquent\Model;
class PeopleProcess extends Model
{
use BelongsToTenant;
use HasWorkContext;
protected $guarded = ['id'];
+7 -8
View File
@@ -4,6 +4,7 @@ namespace App\Models;
use App\Enums\PurchasingRole;
use App\Models\Concerns\BelongsToTenant;
use App\Models\Concerns\HasWorkContext;
use App\Services\ConflictGuard;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Collection;
@@ -11,6 +12,7 @@ use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Support\Carbon;
use Tempo\Purchasing\Internal\InternalRequisitions;
/**
* @property int $id
@@ -31,6 +33,7 @@ use Illuminate\Support\Carbon;
class Requisition extends Model
{
use BelongsToTenant;
use HasWorkContext;
protected $guarded = ['id'];
@@ -81,18 +84,14 @@ class Requisition extends Model
public function canDecide(User $user): bool
{
if ($this->tenant_id !== $user->tenant_id || $this->status !== 'pending' || $this->requester_id === $user->id) {
if ($this->tenant_id !== $user->tenant_id) {
return false;
}
if ($this->steps->contains('approver_id', $user->id)) {
return false;
}
$next = InternalRequisitions::nextStep(['status' => $this->status, 'requester_id' => $this->requester_id, 'steps' => $this->steps->toArray()], $user->id);
$next = $this->steps->firstWhere('decision', 'pending');
return $next !== null && $user->hasFunctions([$next->role])
&& ($next->role !== 'department_head' || $this->department_id === $user->department_id)
return $next !== null && $user->hasFunctions([$next['role']])
&& ($next['role'] !== 'department_head' || $this->department_id === $user->department_id)
&& ! app(ConflictGuard::class)->participationBlocked($user, $this);
}
}
+7
View File
@@ -4,8 +4,15 @@ namespace App\Models;
use App\Models\Concerns\AppendOnlyInventoryRecord;
use App\Models\Concerns\BelongsToTenant;
use Carbon\CarbonInterface;
use Illuminate\Database\Eloquent\Model;
/**
* @property CarbonInterface $moved_at
* @property int|null $equipment_id
* @property int|null $spare_part_id
* @property array<string,mixed> $snapshot
*/
class StockMovement extends Model
{
use AppendOnlyInventoryRecord, BelongsToTenant;
+2
View File
@@ -4,12 +4,14 @@ namespace App\Models;
use App\Models\Concerns\AppendOnlyInventoryRecord;
use App\Models\Concerns\BelongsToTenant;
use Carbon\CarbonInterface;
use Illuminate\Database\Eloquent\Model;
/**
* @property array<string, mixed> $snapshot
* @property int|null $equipment_id
* @property int|null $spare_part_id
* @property CarbonInterface $recorded_at
*/
class StockOperation extends Model
{
+34
View File
@@ -0,0 +1,34 @@
<?php
namespace App\Models;
use App\Models\Concerns\BelongsToTenant;
use Illuminate\Database\Eloquent\Model;
/**
* @property array<string,mixed> $data
* @property array<string,mixed> $snapshot
* @property int $version
* @property string $record_key
* @property \Illuminate\Support\Carbon $created_at
*/
class SupplyRecord extends Model
{
use BelongsToTenant;
public $timestamps = false;
protected $guarded = ['id'];
/** @return array<string,string> */
protected function casts(): array
{
return ['data' => 'array', 'snapshot' => 'array', 'created_at' => 'datetime'];
}
protected static function booted(): void
{
static::updating(fn () => throw new \LogicException('Criar uma nova versão.'));
static::deleting(fn () => throw new \LogicException('Preservar histórico.'));
}
}
+3 -1
View File
@@ -11,7 +11,9 @@ use Illuminate\Database\Eloquent\Model;
* @property int $second_limit_minor
* @property bool $approval_includes_tax
* @property bool $rules_provisional
* @property string|null $default_tax_rate
* @property array<string,mixed>|null $comparison_policy
* @property array{revision:int,enabled:list<string>}|null $work_context_policy
* @property array{revision:int,configured:bool,procurement_brief:bool,people_brief:bool,ai_plan?:array<string,mixed>}|null $intelligence_policy
*/
class Tenant extends Model
@@ -20,6 +22,6 @@ class Tenant extends Model
protected function casts(): array
{
return ['approval_includes_tax' => 'boolean', 'rules_provisional' => 'boolean', 'default_tax_rate' => 'decimal:2', 'comparison_policy' => 'array', 'intelligence_policy' => 'array'];
return ['work_context_policy' => 'array', 'approval_includes_tax' => 'boolean', 'rules_provisional' => 'boolean', 'default_tax_rate' => 'decimal:2', 'comparison_policy' => 'array', 'intelligence_policy' => 'array'];
}
}
+23
View File
@@ -0,0 +1,23 @@
<?php
namespace App\Models;
use App\Models\Concerns\AppendOnlyInventoryRecord;
use App\Models\Concerns\BelongsToTenant;
use App\Models\Concerns\HasWorkContext;
use Illuminate\Database\Eloquent\Model;
/** @property array<string,mixed> $snapshot */
class WarehouseRequest extends Model
{
use AppendOnlyInventoryRecord, BelongsToTenant, HasWorkContext;
public $timestamps = false;
protected $guarded = ['id'];
protected function casts(): array
{
return ['snapshot' => 'array'];
}
}
+22
View File
@@ -0,0 +1,22 @@
<?php
namespace App\Models;
use App\Models\Concerns\AppendOnlyInventoryRecord;
use App\Models\Concerns\BelongsToTenant;
use Illuminate\Database\Eloquent\Model;
/** @property array<string,mixed> $data */
class WarehouseRequestEvent extends Model
{
use AppendOnlyInventoryRecord, BelongsToTenant;
public $timestamps = false;
protected $guarded = ['id'];
protected function casts(): array
{
return ['data' => 'array'];
}
}