73 lines
3.3 KiB
PHP
73 lines
3.3 KiB
PHP
<?php
|
|
|
|
namespace App\Modules\Purchasing;
|
|
|
|
use App\Models\User;
|
|
use App\Modules\Identity\Services\Permissions;
|
|
use App\Shared\Context\CompanyContext;
|
|
use Illuminate\Support\Facades\DB;
|
|
use Tempo\Finance\Payables\Payables;
|
|
|
|
final class SupplierPayables
|
|
{
|
|
public static function guard(): void
|
|
{
|
|
$c = DB::connection();
|
|
abort_unless(app()->environment('payable-testing'), 403, 'Obrigações apenas no ensaio isolado.');
|
|
if ($c->getDriverName() !== 'pgsql' || ! preg_match('/^payable_sgf_[a-f0-9]{12}$/D', $c->getDatabaseName()) || $c->getConfig('host') !== '127.0.0.1' || $c->selectOne('select current_database() as d')->d !== $c->getDatabaseName()) {
|
|
throw new \LogicException('PAYABLE_QA_DATABASE_REFUSED');
|
|
}
|
|
}
|
|
|
|
public function scope(User $u): array
|
|
{
|
|
self::guard();
|
|
$c = app(CompanyContext::class);
|
|
abort_unless(auth()->id() === $u->id && $c->userId() === $u->id && $c->unitId(), 403);
|
|
$ids = $c->identifiers();
|
|
app(Permissions::class)->require($u->id, $ids['tenant_id'], $ids['company_id'], 'supplier_payables.view', $c->unitId());
|
|
|
|
return $c->identifiers() + ['unit_id' => $c->unitId()];
|
|
}
|
|
|
|
public function can(User $u, string $a): bool
|
|
{
|
|
return DB::table('pa_access')->where($this->scope($u))->where(['user_id' => $u->id, 'action' => $a])->exists();
|
|
}
|
|
|
|
public function document(User $u, int $id): array
|
|
{
|
|
$row = DB::table('pa_imported_sources')->where($this->scope($u))->where('id', $id)->first() ?? abort(403, 'Origem não mapeada neste contexto.');
|
|
$s = json_decode($row->payload, true, 64, JSON_THROW_ON_ERROR);
|
|
abort_unless(hash_equals($row->receipt_hash, hash('sha256', Payables::canonical($s))), 409, 'Recibo de origem divergente.');
|
|
$s['local_id'] = $id;
|
|
|
|
return $s;
|
|
}
|
|
|
|
public function engine(User $u): Payables
|
|
{
|
|
$scope = $this->scope($u);
|
|
$person = DB::table('pa_access')->where($scope)->where(['user_id' => $u->id, 'action' => 'view'])->value('person');
|
|
abort_unless($person, 403);
|
|
|
|
return new Payables(DB::connection(), $u->id, $person, $scope, function (string $a) use ($u, $scope, $person) {
|
|
self::guard();
|
|
DB::table('companies')->where('tenant_id', $scope['tenant_id'])->where('id', $scope['company_id'])->lockForUpdate()->firstOrFail();
|
|
DB::table('users')->where('id', $u->id)->lockForUpdate()->firstOrFail();
|
|
abort_unless(DB::table('pa_access')->where($scope)->where(['user_id' => $u->id, 'action' => 'view'])->value('person') === $person, 409, 'Identidade de pessoa alterada; reabra a proposta.');
|
|
abort_unless($this->scope($u) === $scope, 409, 'Contexto mudou.');
|
|
app(CompanyContext::class)->selectFor($u->id, $scope['tenant_id'], $scope['company_id'], $scope['unit_id']);
|
|
abort_unless($this->can($u, 'view') && $this->can($u, $a), 403);
|
|
}, fn (int $id) => $this->document($u, $id));
|
|
}
|
|
|
|
public function listing(User $u): array
|
|
{
|
|
$d = $this->engine($u)->listing(DB::table('pa_imported_sources')->where($this->scope($u))->pluck('id')->all());
|
|
$d['permissions'] = ['prepare' => $this->can($u, 'prepare'), 'validate' => $this->can($u, 'validate')];
|
|
|
|
return $d;
|
|
}
|
|
}
|