File manager - Edit - /var/www/html/portalHomolog/database/seeders/ProjetosProgramasMigrationSeeder.php
Back
<?php namespace Database\Seeders; use Illuminate\Database\Seeder; use App\Models\ProjetosProgramas\{Tipo, Classificacao, Etapa, Prazo, Fonte, Eixo, Area, Ods, ProjetoPrograma}; use App\Models\Structure; use Illuminate\Support\Facades\DB; use Illuminate\Support\Str; use Carbon\Carbon; /** * Esta seeder unifica a migração de dados básicos e projetos. * * IMPORTANTE: Esta seeder é INTERATIVA. Se encontrar um órgão no CSV que * não existe no sistema, ela perguntará qual órgão atual deve ser usado. * No final, ela oferece a opção de salvar esse mapeamento no arquivo de config. * * Execute: php artisan db:seed --class=ProjetosProgramasMigrationSeeder */ class ProjetosProgramasMigrationSeeder extends Seeder { private array $orgaoMap = []; private array $novosMapeamentos = []; private array $legacyOrgaosData = []; private array $stats = [ 'total' => 0, 'migrated' => 0, 'skipped' => 0, 'errors' => 0, ]; public function run(): void { $this->command->info('==========================================='); $this->command->info('Iniciando migração completa de Projetos e Programas'); $this->command->info('==========================================='); // Etapa 1: Criar dados básicos (tipos, classificações, etapas, etc.) $this->seedDadosBasicos(); // Etapa 2: Carregar nomes dos órgãos legados (apenas para exibição no prompt) $this->loadLegacyOrgaosData(); // Etapa 3: Carregar mapeamentos existentes do config $this->orgaoMap = config('legacy_orgaos_mapping.orgao_mapping', []); // Etapa 4: Migrar projetos do CSV legado $this->migrateProjects(); // Etapa 5: Salvar novos mapeamentos (interativo) $this->salvarNovosMapeamentos(); // Etapa 6: Mostrar estatísticas $this->showStatistics(); } /** * Etapa 1: Cria os dados básicos do módulo (tipos, classificações, etapas, etc.) */ private function seedDadosBasicos(): void { $this->command->info(''); $this->command->info('Criando dados básicos do módulo...'); // Tipos foreach (['Projeto', 'Programa', 'Projeto Estruturante', 'Ação/Iniciativa/Atividade'] as $v) { Tipo::firstOrCreate(['nome' => $v]); } // Classificações foreach (['Estratégico/Prioritário', 'Estruturante', 'Modernização/Inovação', 'Setoriais'] as $v) { Classificacao::firstOrCreate(['nome' => $v]); } // Etapas foreach (Etapa::NOMES_ORDENADOS as $v) { Etapa::firstOrCreate(['nome' => $v]); } // Prazos foreach (['100 dias', '1 ano', '4 anos'] as $v) { Prazo::firstOrCreate(['nome' => $v]); } // Fontes foreach ([ 'Recurso Próprio', 'Convênio', 'Parceria Público Privada', 'Emenda Parlamentar', 'Fundo', 'Transferência Voluntária', 'Banco de Projetos', 'Outro' ] as $v) { Fonte::firstOrCreate(['nome' => $v]); } // Eixos e Áreas $eixos = [ 1 => 'Gestão pública eficiente', 2 => 'Angra, cidade com desenvolvimento e oportunidade', 3 => 'Angra, cidade acolhedora e saudável', 4 => 'Angra, cidade moderna e do conhecimento', 5 => 'Angra, cidade sustentável', 6 => 'Angra, cidade pacífica e segura', ]; $areas = [ 1 => ['Gestão pública', 'Infraestrutura e parcerias de investimento'], 2 => ['Desenvolvimento econômico e geração de emprego', 'Cultura', 'Turismo e eventos'], 3 => ['Saúde', 'Esporte e lazer', 'Desenvolvimento social e promoção da cidadania', 'Juventude e terceira idade'], 4 => ['Educação', 'Modernização e inovação'], 5 => ['Planejamento urbano, habitação e defesa civil', 'Mobilidade urbana e acessibilidade', 'Meio ambiente', 'Saneamento básico e ambiental'], 6 => ['Segurança pública'], ]; $mapEixos = []; foreach ($eixos as $code => $nome) { $eixo = Eixo::firstOrCreate(['nome' => $nome]); $mapEixos[$code] = $eixo->id; } foreach ($areas as $eixoCode => $lista) { foreach ($lista as $nomeArea) { Area::firstOrCreate([ 'eixo_id' => $mapEixos[$eixoCode], 'nome' => $nomeArea ]); } } // ODS (1 a 17) foreach (range(1, 17) as $i) { Ods::firstOrCreate(['codigo' => str_pad($i, 2, '0', STR_PAD_LEFT)]); } $this->command->info('✓ Dados básicos criados com sucesso'); } /** * Carrega os nomes dos órgãos do CSV legado para memória */ private function loadLegacyOrgaosData(): void { $csvPath = base_path('Orgaos.csv'); if (!file_exists($csvPath)) return; $handle = fopen($csvPath, 'r'); if (!$handle) return; $header = fgetcsv($handle); if ($header) { $header[0] = preg_replace('/^\x{FEFF}/u', '', $header[0]); while (($row = fgetcsv($handle)) !== false) { if (count($row) >= count($header)) { $data = array_combine($header, $row); $id = trim($data['id_org'] ?? ''); if ($id) { $this->legacyOrgaosData[$id] = [ 'nome' => trim($data['org_nome'] ?? 'Sem nome'), 'sigla' => trim($data['org_sigla'] ?? ''), ]; } } } } fclose($handle); } /** * Etapa 2: Migra órgãos do CSV legado * * ATENÇÃO: Esta seeder CRIA novos órgãos automaticamente quando não encontra * órgãos existentes. Para uma migração sem criação de órgãos, use a seeder * interativa: ProjetosProgramasMigrationInteractiveSeeder */ private function migrateOrgaos(): void { $this->command->info(''); $this->command->info('Migrando órgãos do CSV legado...'); $this->command->warn('⚠ ATENÇÃO: Novos órgãos serão criados automaticamente se não existirem!'); $csvPath = base_path('Orgaos.csv'); if (!file_exists($csvPath)) { $this->command->warn("Arquivo de órgãos não encontrado: {$csvPath}"); $this->command->warn("Continuando sem migração de órgãos..."); return; } $handle = fopen($csvPath, 'r'); if (!$handle) { $this->command->error("Não foi possível abrir o arquivo: {$csvPath}"); return; } // Read header $header = fgetcsv($handle); if (!$header) { $this->command->error("Arquivo CSV vazio ou inválido"); fclose($handle); return; } // Remove BOM if present $header[0] = preg_replace('/^\x{FEFF}/u', '', $header[0]); $this->command->info("Colunas encontradas: " . implode(', ', $header)); $created = 0; $updated = 0; $skipped = 0; while (($row = fgetcsv($handle)) !== false) { if (count($row) < count($header)) { continue; } $data = array_combine($header, $row); $idOrg = trim($data['id_org'] ?? ''); $sigla = trim($data['org_sigla'] ?? ''); $nome = trim($data['org_nome'] ?? ''); if (empty($idOrg) || empty($sigla) || empty($nome)) { $skipped++; continue; } // Try to find existing structure by abbreviation $structure = Structure::where('abbreviation', $sigla)->first(); if (!$structure) { // Create new structure $structure = Structure::create([ 'id' => Str::uuid(), 'structure_id' => null, 'type' => 'SECRETARIA', 'name' => $nome, 'abbreviation' => $sigla, 'slug' => Str::slug($sigla), 'address' => '', 'phoneNumber' => '', 'email1' => 'contato@angra.rj.gov.br', 'manager' => '', 'status' => 'ATIVADO', 'order' => (int) ($data['org_numero'] ?? 0), ]); $created++; $this->command->info("Criado: {$sigla} - {$nome}"); } else { $updated++; } // Store mapping $this->orgaoMap[$idOrg] = $structure->id; } fclose($handle); // Store mapping in cache for use by other seeders cache()->put('legacy_orgao_map', $this->orgaoMap, now()->addHours(24)); $this->command->info("✓ Migração de órgãos concluída!"); $this->command->info(" Criados: {$created}"); $this->command->info(" Existentes: {$updated}"); $this->command->info(" Ignorados: {$skipped}"); } /** * Limpa dados existentes de projetos (use com cuidado!) */ private function cleanExistingData(): void { $this->command->info(''); $this->command->info('Limpando dados de teste existentes...'); DB::beginTransaction(); try { // Delete relationships first DB::table('project_program_ods')->delete(); DB::table('project_program_orgaos')->delete(); // Delete attachments $attachmentCount = DB::table('project_program_attachments')->count(); DB::table('project_program_attachments')->delete(); // Delete projects $projectCount = DB::table('projects_programs')->count(); DB::table('projects_programs')->delete(); DB::commit(); $this->command->info("✓ Removidos {$projectCount} projetos"); $this->command->info("✓ Removidos {$attachmentCount} anexos"); $this->command->info("✓ Relacionamentos limpos"); } catch (\Exception $e) { DB::rollBack(); $this->command->error("Erro ao limpar dados: " . $e->getMessage()); throw $e; } } /** * Etapa 4: Migra projetos do CSV legado */ private function migrateProjects(): void { $this->command->info(''); $this->command->info('Migrando projetos do CSV...'); $csvPath = base_path('Projetos.csv'); if (!file_exists($csvPath)) { $this->command->warn("Arquivo de projetos não encontrado: {$csvPath}"); $this->command->warn("Pule esta etapa se não houver dados legados para migrar."); return; } $handle = fopen($csvPath, 'r'); if (!$handle) { $this->command->error("Não foi possível abrir o arquivo: {$csvPath}"); return; } // Read header $header = fgetcsv($handle); if (!$header) { $this->command->error("Arquivo CSV vazio ou inválido"); fclose($handle); return; } // Remove BOM if present $header[0] = preg_replace('/^\x{FEFF}/u', '', $header[0]); $lineNumber = 1; $progressBar = $this->command->getOutput()->createProgressBar(); $progressBar->start(); while (($row = fgetcsv($handle)) !== false) { $lineNumber++; $this->stats['total']++; if (count($row) < count($header)) { $this->stats['skipped']++; $progressBar->advance(); continue; } $data = array_combine($header, $row); try { $this->migrateProject($data); $this->stats['migrated']++; } catch (\Exception $e) { $this->stats['errors']++; $this->command->error("\nErro na linha {$lineNumber}: " . $e->getMessage()); } $progressBar->advance(); } $progressBar->finish(); $this->command->info(''); fclose($handle); } /** * Migra um projeto individual */ private function migrateProject(array $data): void { DB::beginTransaction(); try { // Map gestor (órgão) $gestorId = null; $idOrgLegado = $data['pro_dimen_orgao'] ?? null; if (!empty($idOrgLegado)) { $gestorId = $this->orgaoMap[$idOrgLegado] ?? null; // Se não mapeado ainda, perguntar interativamente if (!$gestorId) { $this->command->warn("\nProjeto: " . ($data['pro_dimen_denominacao'] ?? 'Sem nome')); $legacyData = $this->legacyOrgaosData[$idOrgLegado] ?? ['nome' => 'Não encontrado no CSV', 'sigla' => '']; $nomeOrg = $legacyData['nome']; $siglaOrg = $legacyData['sigla']; $gestorId = $this->perguntarOrgao($idOrgLegado, $siglaOrg, $nomeOrg); if ($gestorId) { $this->orgaoMap[$idOrgLegado] = $gestorId; $this->novosMapeamentos[$idOrgLegado] = $gestorId; } } } // Fallback para PMAR se o usuário pulou ou não encontrou if (!$gestorId) { $pmar = Structure::where('abbreviation', 'PMAR')->first(); $gestorId = $pmar?->id ?? config('legacy_orgaos_mapping.default_orgao_id'); } // Parse dates $dataInicio = $this->parseDate($data['pro_crono_inicio']); if (!$dataInicio) { $dataInicio = '2022-01-01'; // Default date } $dataTermino = $this->parseDate($data['pro_crono_fim']); // Build observacoes with extra fields $observacoes = $this->cleanText($data['pro_dados_obs'] ?? ''); $extraInfo = []; if (!empty($data['pro_dados_status_outro'])) { $extraInfo[] = "Status: " . $data['pro_dados_status_outro']; } if (!empty($data['pro_dados_dificuldades_outro'])) { $extraInfo[] = "Dificuldades: " . $data['pro_dados_dificuldades_outro']; } if (!empty($extraInfo)) { $observacoes = trim(($observacoes ? $observacoes . "\n\n" : '') . implode("\n", $extraInfo)); } // Build relacao_ppa with extra fields $relacaoPpa = $this->cleanText($data['pro_dimen_acao'] ?? ''); if (!empty($data['pro_inves_horizonte'])) { $relacaoPpa = trim(($relacaoPpa ? $relacaoPpa . "\n" : '') . "Horizonte: " . $data['pro_inves_horizonte']); } if (!empty($data['pro_inves_relacao'])) { $relacaoPpa = trim(($relacaoPpa ? $relacaoPpa . "\n" : '') . "Relação: " . $data['pro_inves_relacao']); } // Create or update project $project = ProjetoPrograma::updateOrCreate([ 'denominacao' => $this->cleanText($data['pro_dimen_denominacao']) ?? 'Sem denominação', 'codigo' => $this->cleanText($data['pro_dimen_codigo']), ], [ 'num_processo_adm' => $this->cleanText($data['pro_dimen_numprocessoadm']), 'gestor_structure_id' => $gestorId, 'tipo_id' => $this->mapTipo($data['pro_dimen_tipo']), 'programa_ppa' => $this->cleanText($data['pro_dimen_programa']), 'endereco' => $this->cleanText($data['pro_dimen_endereco']), 'bairro' => $this->cleanText($data['pro_dimen_bairro']), 'data_inicio' => $dataInicio, 'data_termino' => $dataTermino, 'prazo_id' => $this->mapPrazo($data['pro_crono_prazo_entrega']), 'acompanhamento_governo' => $this->parseBoolean($data['pro_dimen_acompanhamento'] ?? 0), 'classificacao_id' => $this->mapClassificacao($data['pro_dimen_classificacao']), 'etapa_id' => $this->mapEtapa($data['pro_dimen_etapa']), 'relacao_ppa' => $relacaoPpa, 'eixo_id' => $this->mapEixo($data['pro_eixo'] ?? ''), 'area_id' => $this->mapArea($data['pro_area'] ?? ''), 'contato_nome' => $this->cleanText($data['pro_contato_nome']), 'contato_matricula' => $this->cleanText($data['pro_contato_matricula']), 'contato_ramal' => $this->cleanText($data['pro_contato_ramal']), 'contato_telefone' => $this->cleanText($data['pro_contato_telefone']), 'contato_email' => $this->cleanText($data['pro_contato_email']), 'descricao_objeto' => $this->cleanText($data['pro_dados_objeto']), 'justificativa' => $this->cleanText($data['pro_dados_justificativa']), 'descricao_responsabilidades' => $this->cleanText($data['pro_dados_responsabilidades']), 'status_id' => $this->mapStatus($data['pro_dados_status']), 'dificuldade_id' => $this->mapDificuldade($data['pro_dados_dificuldades']), 'gargalos' => $this->cleanText($data['pro_dados_gargalos']), 'observacoes' => $observacoes, 'fonte_id' => $this->mapFonte($data['pro_inves_fonte']), 'fonte_outro' => $this->cleanText($data['pro_inves_fonte_outro']), 'custo_total' => $this->parseDecimal($data['pro_inves_custototal']) ?? 0, 'custeio_anual' => $this->parseDecimal($data['pro_inves_custoanual']) ?? 0, 'ppa_2022' => $this->parseDecimal($data['pro_inves_previsto1']) ?? 0, 'ppa_2023' => $this->parseDecimal($data['pro_inves_previsto2']) ?? 0, 'ppa_2024' => $this->parseDecimal($data['pro_inves_previsto3']) ?? 0, 'ppa_2025' => $this->parseDecimal($data['pro_inves_previsto4']) ?? 0, 'loa_2022' => $this->parseDecimal($data['pro_inves_loa1']) ?? 0, 'loa_2023' => $this->parseDecimal($data['pro_inves_loa2']) ?? 0, 'loa_2024' => $this->parseDecimal($data['pro_inves_loa3']) ?? 0, 'loa_2025' => $this->parseDecimal($data['pro_inves_loa4']) ?? 0, 'manutencao_2022' => $this->parseDecimal($data['pro_inves_manutencao1']) ?? 0, 'manutencao_2023' => $this->parseDecimal($data['pro_inves_manutencao2']) ?? 0, 'manutencao_2024' => $this->parseDecimal($data['pro_inves_manutencao3']) ?? 0, 'manutencao_2025' => $this->parseDecimal($data['pro_inves_manutencao4']) ?? 0, 'conve_orgao' => $this->cleanText($data['pro_conve_orgao']), 'conve_orgao_outro' => $this->cleanText($data['pro_conve_orgao_outro']), 'conve_proposta' => $this->cleanText($data['pro_conve_proposta']), 'conve_convenio' => $this->cleanText($data['pro_conve_convenio']), 'status_registro' => 'COMPLETO', 'identificacao_done' => true, 'cronograma_done' => true, 'areas_done' => true, 'contato_done' => true, 'dados_done' => true, 'investimento_done' => true, ]); // Attach ODS $odsIds = $this->parseOdsColumns($data); if (!empty($odsIds)) { $odsRecords = Ods::whereIn('codigo', array_map(function ($id) { return str_pad($id, 2, '0', STR_PAD_LEFT); }, $odsIds))->pluck('id')->toArray(); if (!empty($odsRecords)) { $project->ods()->sync($odsRecords); } } // Attach orgaos envolvidos $orgaosEnvolvidosIds = $this->parseCommaSeparatedIds($data['pro_dados_orgaos_envolvidos'] ?? ''); $structureIds = []; foreach ($orgaosEnvolvidosIds as $orgaoId) { if (isset($this->orgaoMap[$orgaoId])) { $structureIds[] = $this->orgaoMap[$orgaoId]; } } if (!empty($structureIds)) { $project->orgaosEnvolvidos()->sync($structureIds); } DB::commit(); } catch (\Exception $e) { DB::rollBack(); throw $e; } } /** * Mostra estatísticas da migração */ private function showStatistics(): void { $this->command->info(''); $this->command->info('==========================================='); $this->command->info('Estatísticas da Migração'); $this->command->info('==========================================='); $this->command->info("Total de linhas processadas: {$this->stats['total']}"); $this->command->info("Projetos migrados: {$this->stats['migrated']}"); $this->command->info("Linhas ignoradas: {$this->stats['skipped']}"); $this->command->info("Erros: {$this->stats['errors']}"); $this->command->info('==========================================='); } /** * Pergunta ao usuário qual structure atribuir a um órgão legado */ private function perguntarOrgao(string $idOrg, string $sigla, string $nome): ?string { $this->command->warn("═══════════════════════════════════════════════════════"); $this->command->warn("MAPEAMENTO DE ÓRGÃO NECESSÁRIO"); $this->command->warn("═══════════════════════════════════════════════════════"); $this->command->info("ID Legado: {$idOrg} " . ($sigla ? "({$sigla})" : "")); if ($nome) $this->command->info("Nome original: {$nome}"); $this->command->info(''); // Buscar structures disponíveis $structures = Structure::where('status', 'ATIVADO') ->orderBy('name', 'asc') ->get(); if ($structures->isEmpty()) { $this->command->error("Nenhuma structure ativa encontrada no sistema!"); return null; } // Mostrar opções $this->command->info("Deseja mapear para uma das estruturas abaixo?"); $options = []; $index = 1; // Sugerir algumas estruturas principais primeiro $highlights = Structure::whereIn('abbreviation', ['SAG', 'SFI', 'CGM', 'SEJIN', 'SSA', 'PGM', 'SMAA', 'SEGOV']) ->where('status', 'ATIVADO')->get(); foreach ($highlights as $structure) { $options[$index] = $structure->id; $this->command->info(" [{$index}] {$structure->name} ({$structure->abbreviation})"); $index++; } $this->command->info(''); $this->command->info(" [0] Pular este mapeamento (usar padrão PMAR)"); $this->command->info(" [s] PESQUISAR outra secretaria por nome/sigla..."); $resposta = $this->command->ask("Escolha o índice ou 's'"); if (strtolower($resposta) === 's') { $termo = $this->command->ask("Digite parte do nome ou sigla"); $encontradas = Structure::where('status', 'ATIVADO') ->where(function ($query) use ($termo) { $query->where('abbreviation', 'like', "%{$termo}%") ->orWhere('name', 'like', "%{$termo}%"); })->get(); if ($encontradas->isEmpty()) { $this->command->warn("Nada encontrado. Tente novamente."); return $this->perguntarOrgao($idOrg, $sigla, $nome); } $searchOptions = []; $sIdx = 1; foreach ($encontradas as $struct) { $searchOptions[$sIdx] = $struct->id; $this->command->info(" [{$sIdx}] {$struct->abbreviation} - {$struct->name}"); $sIdx++; } $escolha = $this->command->ask("Escolha o índice da lista acima (ou 'o' para listar tudo)"); if ($escolha === 'o') return $this->perguntarOrgao($idOrg, $sigla, $nome); return $searchOptions[(int) $escolha] ?? null; } if ($resposta === '0' || empty($resposta)) return null; return $options[(int) $resposta] ?? null; } /** * Salva novos mapeamentos no arquivo de config */ private function salvarNovosMapeamentos(): void { if (empty($this->novosMapeamentos)) { return; } $this->command->info(''); $this->command->info('Mapeamentos realizados nesta sessão:'); foreach ($this->novosMapeamentos as $idOrg => $structureId) { $struct = Structure::find($structureId); $nome = $struct ? ($struct->abbreviation ?? $struct->name) : 'Desconhecido'; $this->command->info(" ID Legado {$idOrg} -> {$nome} ({$structureId})"); } if ($this->command->confirm('Deseja salvar estes mapeamentos permanentemente no arquivo de config?', true)) { $configPath = config_path('legacy_orgaos_mapping.php'); $content = file_get_contents($configPath); $mappingLines = ""; foreach ($this->novosMapeamentos as $idOrg => $structureId) { $struct = Structure::find($structureId); $nome = $struct ? ($struct->abbreviation ?? $struct->name) : 'Manual'; $mappingLines .= " '{$idOrg}' => '{$structureId}', // {$nome} (Atualizado em " . now()->format('d/m/Y') . ")\n"; } // Inserir antes do fechamento do array $content = preg_replace('/(\s+\];)/', "\n" . $mappingLines . "$1", $content); file_put_contents($configPath, $content); $this->command->info("✓ Arquivo config/legacy_orgaos_mapping.php atualizado com sucesso!"); } } // ============================================ // Métodos auxiliares de mapeamento de dados // ============================================ private function cleanText(?string $text): ?string { if (empty($text)) { return null; } return trim($text); } private function parseDate(?string $date): ?string { if (empty($date)) { return null; } try { // Try multiple date formats $formats = ['Y-m-d', 'd/m/Y', 'd-m-Y', 'Y/m/d']; foreach ($formats as $format) { $parsed = Carbon::createFromFormat($format, trim($date)); if ($parsed) { return $parsed->format('Y-m-d'); } } // Try Carbon parse $parsed = Carbon::parse(trim($date)); return $parsed->format('Y-m-d'); } catch (\Exception $e) { return null; } } private function parseDecimal(?string $value): ?float { if (empty($value) || $value === null) { return null; } // Remove currency symbols and spaces $cleaned = str_replace(['R$', '$', ' ', '€'], '', (string) $value); // Handle Brazilian format (1.234,56) if (strpos($cleaned, ',') !== false) { $cleaned = str_replace('.', '', $cleaned); $cleaned = str_replace(',', '.', $cleaned); } $float = filter_var($cleaned, FILTER_VALIDATE_FLOAT); return $float !== false ? (float) $float : null; } private function parseBoolean($value): bool { if (is_bool($value)) { return $value; } if (is_numeric($value)) { return (bool) (int) $value; } if (is_string($value)) { $lower = strtolower(trim($value)); return in_array($lower, ['1', 'true', 'sim', 'yes', 's']); } return false; } private function mapTipo(?string $tipo): ?int { if (empty($tipo)) { return null; } $map = [ 'Projeto' => 1, 'Programa' => 2, 'Projeto Estruturante' => 3, 'Ação/Iniciativa/Atividade' => 4, ]; $tipo = trim($tipo); foreach ($map as $nome => $id) { if (stripos($tipo, $nome) !== false || stripos($nome, $tipo) !== false) { $tipoModel = Tipo::where('nome', $nome)->first(); return $tipoModel?->id; } } return null; } private function mapPrazo(?string $prazo): ?int { if (empty($prazo)) { return null; } $prazo = trim($prazo); $prazoModel = Prazo::where('nome', 'like', "%{$prazo}%")->first(); return $prazoModel?->id; } private function mapClassificacao(?string $classificacao): ?int { if (empty($classificacao)) { return null; } $classificacao = trim($classificacao); $classificacaoModel = Classificacao::where('nome', 'like', "%{$classificacao}%")->first(); return $classificacaoModel?->id; } private function mapEtapa(?string $etapa): ?int { if (empty($etapa)) { return null; } $etapa = trim($etapa); $etapaModel = Etapa::where('nome', 'like', "%{$etapa}%")->first(); return $etapaModel?->id; } private function mapStatus(?string $status): ?int { if (empty($status)) { return null; } $map = [ 'Sem proposta' => 1, 'Projeto Básico' => 2, 'Projeto Executivo' => 3, 'Licitando' => 4, 'Tramitando para Licitar' => 5, 'Outro' => 6, ]; $status = trim($status); foreach ($map as $nome => $id) { if (stripos($status, $nome) !== false || stripos($nome, $status) !== false) { return $id; } } return null; } private function mapDificuldade(?string $dificuldade): ?int { if (empty($dificuldade)) { return null; } $map = [ 'Elaboração da Proposta' => 1, 'Execução' => 2, 'Obter fonte de recursos' => 3, 'Tramitação interna PMAR' => 4, 'Elaboração de Material Técnico para Licitação' => 5, 'Outro' => 6, ]; $dificuldade = trim($dificuldade); foreach ($map as $nome => $id) { if (stripos($dificuldade, $nome) !== false || stripos($nome, $dificuldade) !== false) { return $id; } } return null; } private function mapFonte(?string $fonte): ?int { if (empty($fonte)) { return null; } $fonte = trim($fonte); $fonteModel = Fonte::where('nome', 'like', "%{$fonte}%")->first(); return $fonteModel?->id; } private function mapEixo(?string $eixoName): ?int { if (empty($eixoName)) { return null; } $eixos = [ 'Gestão pública eficiente' => 1, 'Angra, cidade com desenvolvimento e oportunidade' => 2, 'Angra, cidade acolhedora e saudável' => 3, 'Angra, cidade moderna e do conhecimento' => 4, 'Angra, cidade sustentável' => 5, 'Angra, cidade pacífica e segura' => 6, ]; // Try exact match if (isset($eixos[$eixoName])) { $eixoModel = Eixo::where('nome', $eixoName)->first(); return $eixoModel?->id; } // Try to find by number if (is_numeric($eixoName)) { $num = (int) $eixoName; if ($num >= 1 && $num <= 6) { $eixoModel = Eixo::find($num); return $eixoModel?->id; } } // Try partial match $eixoModel = Eixo::where('nome', 'like', "%{$eixoName}%")->first(); return $eixoModel?->id; } private function mapArea(?string $areaName): ?int { if (empty($areaName)) { return null; } $areaName = trim($areaName); $areas = DB::table('project_program_areas')->get(); foreach ($areas as $area) { if (stripos($area->nome, $areaName) !== false || stripos($areaName, $area->nome) !== false) { return $area->id; } } return null; } private function parseOdsColumns(array $data): array { $odsIds = []; // Look for columns like pro_ods_01, pro_ods_02, etc. for ($i = 1; $i <= 17; $i++) { $columnName = 'pro_ods_' . str_pad($i, 2, '0', STR_PAD_LEFT); if (!empty($data[$columnName]) && $this->parseBoolean($data[$columnName])) { $odsIds[] = $i; } } return $odsIds; } private function parseCommaSeparatedIds(?string $ids): array { if (empty($ids)) { return []; } $ids = trim($ids); $idsArray = explode(',', $ids); return array_filter(array_map(function ($id) { $id = trim($id); return !empty($id) && is_numeric($id) ? (int) $id : null; }, $idsArray)); } }
| ver. 1.4 |
Github
|
.
| PHP 8.3.28 | Generation time: 0.02 |
proxy
|
phpinfo
|
Settings