Files
Investidor-V2/app/Services/InvestorPathDefinition.php
T
nala 6ddafc95ba
tests / ci (push) Canceled after 0s
oportunidades 4
2026-10-10 07:03:59 +02:00

77 lines
4.0 KiB
PHP

<?php
namespace App\Services;
final class InvestorPathDefinition
{
public const STATES = ['not_started', 'preparing', 'ready_to_submit', 'submitted', 'reviewing', 'correction_required', 'waiting_external', 'approved', 'rejected', 'dispensed', 'completed', 'expired'];
/** @return array<string,mixed> */
public static function snapshot(): array
{
$titles = ['Sistematizar a ideia', 'Análise preliminar', 'Decisão sobre a viabilidade', 'Estruturar o investimento',
'Constituição e registo', 'Preparar o dossier', 'Submeter quando aplicável', 'Licenciamento prévio',
'Necessidade de terra', 'Regularização da terra', 'Confirmar regularização aplicável',
'Necessidade e estrutura de financiamento', 'Diligência e negociação financeira', 'Decisão do financiador',
'Fecho e desembolso', 'Implementação', 'Inspecções, testes e licença de operação', 'Início de operação', 'Acompanhamento recorrente'];
$steps = [];
foreach ($titles as $index => $title) {
$n = $index + 1;
$steps[] = ['code' => sprintf('S%02d', $n), 'sequence' => $n, 'title' => $title,
'phase' => $n <= 4 ? 1 : ($n <= 7 ? 2 : ($n <= 11 ? 3 : ($n <= 15 ? 4 : 5))),
'source_paragraph' => 21 + $n,
'branch' => $n === 10 ? 'land_needed' : (in_array($n, [13, 14, 15], true) ? 'external_funding' : null),
// Preparation has no dependencies. These only constrain the named consequential action.
'dependencies' => match ($n) {
7 => ['submit' => ['S06']],
15 => ['execute' => ['S14']],
18 => ['operate' => ['S17']],
default => [],
}];
}
return ['kind' => 'investor-path', 'version' => 1,
'source_sha256' => 'aa13c53138ec15cd808de43d9dc2fc6808da86943d09d3352c9dd0944bdae364',
'phases' => [1 => 'Ideia e viabilidade', 2 => 'Formalização e dossier', 3 => 'Licenciamento e terra', 4 => 'Financiamento', 5 => 'Execução e acompanhamento'],
'states' => self::STATES, 'steps' => $steps,
'legacy_roadmaps' => ['virtual-desk:E0-E11', 'investor-guidance:7-phases', 'investment-roadmap:14-activities']];
}
/** @param array<string,mixed> $definition */
public static function validate(array $definition): void
{
$steps = $definition['steps'] ?? [];
$expected = array_map(fn ($n) => sprintf('S%02d', $n), range(1, 19));
if (count($definition['phases'] ?? []) !== 5 || array_column($steps, 'code') !== $expected
|| array_column($steps, 'sequence') !== range(1, 19)) {
throw new \LogicException('The five phases and nineteen source stages must remain traceable.');
}
$edges = [];
foreach ($steps as $step) {
if (! in_array($step['phase'], range(1, 5), true)
|| ! in_array($step['branch'], [null, 'land_needed', 'external_funding'], true)) {
throw new \LogicException('Unknown phase or applicability field.');
}
$edges[$step['code']] = [];
foreach ($step['dependencies'] as $action => $dependencies) {
if (! in_array($action, ['submit', 'execute', 'operate'], true)
|| array_diff($dependencies, $expected)) {
throw new \LogicException('Unknown action/dependency; preparation cannot be blocked.');
}
$edges[$step['code']] = array_merge($edges[$step['code']], $dependencies);
}
}
$visit = function (string $code, array $trail) use (&$visit, $edges): void {
if (in_array($code, $trail, true)) {
throw new \LogicException('Cyclic action dependencies.');
}
foreach ($edges[$code] as $next) {
$visit($next, [...$trail, $code]);
}
};
foreach ($expected as $code) {
$visit($code, []);
}
}
}