Files
SGF/app/Shared/Context/ModuleNavigation.php
T
2026-11-02 20:29:34 +02:00

62 lines
3.6 KiB
PHP

<?php
namespace App\Shared\Context;
use Illuminate\Support\Facades\DB;
final class ModuleNavigation
{
public const LABELS = ['commercial'=>'Comercial', 'purchasing'=>'Compras', 'stock'=>'Stock', 'workshop'=>'Oficinas', 'finance'=>'Financeiro', 'accounting'=>'Contabilidade'];
private const RIGHTS = [
'commercial'=>['clients.', 'services.', 'service_drafts.', 'billing_drafts.', 'issuer_documents.', 'client_documents.', 'draft_documents.', 'service_invoices.'],
'purchasing'=>['purchasing_budget.', 'supplier_payables.'],
'stock'=>['stock.'], 'workshop'=>['workshop.', 'workshop_billing.', 'workshop_corrections.'],
'finance'=>['direct_costs.', 'industrial_costs.', 'industrial_budgets.', 'industrial_budget_comparisons.', 'service_receivables.'],
'accounting'=>['catalogue_accounting.', 'service_fiscal.'],
];
public function available(CompanyContext $context): array
{
$s = $context->identifiers();
$grants = DB::table('permission_grants')->where($s)->where('user_id', $context->userId())
->where(fn($q) => $q->whereNull('unit_id')->orWhere('unit_id', $context->unitId()))->pluck('permission')->all();
$development = app()->environment(['local','testing','browser-testing'])
&& in_array($context->userId().':'.$s['tenant_id'].':'.$s['company_id'], config('modules.development_profiles', []), true);
if ($development) {
// A local environment name alone must never turn client accounts into
// development profiles. Discovery also requires the isolated DB guard.
try { \App\Shared\Testing\TestingDatabaseGuard::assertSafe(); }
catch (\RuntimeException) { $development=false; }
}
$policy = config('modules.companies.'.$s['tenant_id'].':'.$s['company_id'], []);
$contracted = $policy['contracted'] ?? config('modules.contracted', []);
$enabled = $policy['enabled'] ?? $contracted;
$out = [];
foreach (self::LABELS as $id => $label) {
$authorized = false;
foreach ($grants as $permission) {
foreach (self::RIGHTS[$id] as $prefix) {
if (str_starts_with($permission, $prefix) && str_ends_with($permission, '.view')) { $authorized = true; }
}
}
if ($development || ($authorized && in_array($id,$contracted,true) && in_array($id,$enabled,true))) {
$out[] = ['id'=>$id, 'label'=>$label, 'development'=>$development, 'operations_authorized'=>$authorized];
}
}
return $out;
}
// Ownership of existing endpoints, not an attribution of legacy rows to a new module.
// Company, unit and access configuration are explicitly general.
public static function owner(string $path): ?string
{
if (preg_match('~^api/stock-read(/|$)~', $path)) return 'stock';
if (preg_match('~^(supplier-payables|supplier-payments|api/(supplier-payables|supplier-payments|purchasing-budget))(/|$)~', $path)) return 'purchasing';
if (preg_match('~^api/(workshop|workshop-stock|workshop-billing|workshop-corrections)(/|$)~', $path)) return 'workshop';
if (preg_match('~^api/(direct-costs|industrial-costs|industrial-budgets|service-receivables)(/|$)~', $path)) return 'finance';
if (preg_match('~^api/(catalogue-accounting|service-fiscal)(/|$)~', $path)) return 'accounting';
if (preg_match('~^api/(a|b1|service-invoices|service-calculations|document-preview|document-preparation)(/|$)~', $path)) return 'commercial';
return null;
}
}