from __future__ import annotations import re from .models import Curso, Pessoa, Vinculo SEMESTRE_RE = re.compile(r"^(01|02)(19|20)\d{2}$") def validate_curso(curso: Curso) -> list[str]: issues = [] if not curso.codigo_mec: issues.append("Curso: codigo MEC obrigatorio.") if not curso.descricao: issues.append("Curso: descricao obrigatoria.") if not curso.situacao_funcionamento_curso: issues.append("Curso: situacao de funcionamento obrigatoria.") if curso.carga_horaria_total <= 0: issues.append("Curso: carga horaria total deve ser maior que zero.") if curso.ead and curso.polo_id is None: issues.append("Curso: curso EaD deve ter polo vinculado.") return issues def validate_pessoa(pessoa: Pessoa) -> list[str]: issues = [] if not pessoa.nome: issues.append("Pessoa: nome obrigatorio.") if not pessoa.cpf or len(pessoa.cpf) != 11 or not pessoa.cpf.isdigit(): issues.append("Pessoa: CPF deve ter 11 digitos.") if not pessoa.data_nascimento: issues.append("Pessoa: data de nascimento obrigatoria.") if pessoa.cor_raca is None: issues.append("Pessoa: cor/raca obrigatoria.") if pessoa.nacionalidade is None: issues.append("Pessoa: nacionalidade obrigatoria.") if pessoa.pais_origem_id is None: issues.append("Pessoa: pais de origem obrigatorio.") if pessoa.aluno_com_deficiencia is None: issues.append("Pessoa: indicador de deficiencia obrigatorio.") if pessoa.tipo_escola_ensino_medio is None: issues.append("Pessoa: tipo de escola do ensino medio obrigatorio.") if pessoa.nacionalidade == Pessoa.Nacionalidade.BRASILEIRA_NATA: if pessoa.pais_origem_id != "BRA": issues.append("Pessoa: brasileira nata deve ter pais de origem BRA.") if pessoa.uf_nascimento_id is None: issues.append("Pessoa: brasileira nata deve ter UF de nascimento.") elif pessoa.nacionalidade in { Pessoa.Nacionalidade.BRASILEIRA_NATURALIZADA, Pessoa.Nacionalidade.ESTRANGEIRA, }: if pessoa.pais_origem_id == "BRA": issues.append("Pessoa: pais BRA e exclusivo de brasileira nata.") if pessoa.uf_nascimento_id is not None or pessoa.municipio_nascimento_id is not None: issues.append("Pessoa: UF/municipio de nascimento sao exclusivos de brasileira nata.") if pessoa.municipio_nascimento_id and pessoa.uf_nascimento_id is None: issues.append("Pessoa: municipio de nascimento exige UF de nascimento.") if ( pessoa.municipio_nascimento_id and pessoa.uf_nascimento_id and pessoa.municipio_nascimento.uf_id != pessoa.uf_nascimento_id ): issues.append("Pessoa: municipio de nascimento nao pertence a UF informada.") disability_flags = [ pessoa.deficiencia_cegueira, pessoa.deficiencia_baixa_visao, pessoa.deficiencia_visao_monocular, pessoa.deficiencia_surdez, pessoa.deficiencia_auditiva, pessoa.deficiencia_fisica, pessoa.deficiencia_surdocegueira, pessoa.deficiencia_intelectual, pessoa.deficiencia_tea, pessoa.deficiencia_altas_habilidades, ] has_disability_flag = any(flag is True for flag in disability_flags) has_blank_disability_flag = any(flag is None for flag in disability_flags) if pessoa.aluno_com_deficiencia == Pessoa.SimNaoNaoDispoe.SIM: if has_blank_disability_flag: issues.append("Pessoa: todos os tipos de deficiencia devem ser informados.") if not has_disability_flag: issues.append("Pessoa: ao menos um tipo de deficiencia deve ser marcado.") elif has_disability_flag: issues.append("Pessoa: tipos de deficiencia so podem ser marcados quando indicador for Sim.") return issues def validate_vinculo(vinculo: Vinculo) -> list[str]: issues = [] curso = vinculo.curso pessoa = vinculo.pessoa issues.extend(validate_curso(curso)) issues.extend(validate_pessoa(pessoa)) if not vinculo.ano_censo: issues.append("Vinculo: ano do censo obrigatorio.") if vinculo.situacao == Vinculo.Situacao.NAO_INFORMADA: issues.append("Vinculo: situacao de vinculo obrigatoria.") if not vinculo.semestre_ingresso or not SEMESTRE_RE.match(vinculo.semestre_ingresso): issues.append("Vinculo: semestre de ingresso deve estar no formato 01AAAA ou 02AAAA.") if curso.ead: if vinculo.polo_id is None and curso.polo_id is None: issues.append("Vinculo: curso EaD exige polo.") elif vinculo.turno is None: issues.append("Vinculo: curso presencial exige turno do aluno.") if curso.licenciatura: if vinculo.aluno_parfor is None: issues.append("Vinculo: licenciatura exige informacao de Aluno PARFOR.") if vinculo.segunda_licenciatura_formacao_pedagogica is None: issues.append("Vinculo: licenciatura exige segunda licenciatura/formacao pedagogica.") if ( vinculo.segunda_licenciatura_formacao_pedagogica is True and vinculo.tipo_segunda_licenciatura_formacao_pedagogica is None ): issues.append("Vinculo: segunda licenciatura/formacao pedagogica exige tipo.") if vinculo.carga_horaria_total_aluno != curso.carga_horaria_total: issues.append("Vinculo: carga horaria total deve vir do curso.") if vinculo.carga_horaria_total_aluno <= 0: issues.append("Vinculo: carga horaria total obrigatoria.") if vinculo.carga_horaria_integralizada < 0: issues.append("Vinculo: carga horaria integralizada invalida.") if vinculo.carga_horaria_integralizada > 15000: issues.append("Vinculo: carga horaria integralizada deve ser menor que 15000.") if ( vinculo.situacao == Vinculo.Situacao.FORMADO and vinculo.carga_horaria_integralizada < vinculo.carga_horaria_total_aluno ): issues.append("Vinculo: formado exige carga integralizada maior ou igual a total.") if vinculo.financiamento_estudantil is True: financing_flags = [ vinculo.financiamento_fies, vinculo.financiamento_governo_estadual, vinculo.financiamento_governo_municipal, vinculo.financiamento_ies, vinculo.financiamento_entidades_externas, vinculo.financiamento_prouni_integral, vinculo.financiamento_prouni_parcial, vinculo.financiamento_nao_reembolsavel_entidades_externas, vinculo.financiamento_nao_reembolsavel_governo_estadual, vinculo.financiamento_nao_reembolsavel_ies, vinculo.financiamento_nao_reembolsavel_governo_municipal, ] if any(flag is None for flag in financing_flags): issues.append("Vinculo: financiamento exige preenchimento dos tipos.") if not any(flag is True for flag in financing_flags): issues.append("Vinculo: financiamento exige ao menos um tipo marcado.") social_flags = [ vinculo.apoio_alimentacao, vinculo.apoio_moradia, vinculo.apoio_transporte, vinculo.apoio_material_didatico, vinculo.apoio_bolsa_trabalho, vinculo.apoio_bolsa_permanencia, ] if vinculo.apoio_social and (any(flag is None for flag in social_flags) or not any(social_flags)): issues.append("Vinculo: apoio social exige tipos preenchidos e ao menos um marcado.") if not vinculo.apoio_social and any(flag is True for flag in social_flags): issues.append("Vinculo: tipos de apoio social exigem Apoio Social igual a Sim.") activity_flags = [ vinculo.atividade_pesquisa, vinculo.atividade_extensao, vinculo.atividade_monitoria, vinculo.atividade_estagio_nao_obrigatorio, ] if vinculo.atividade_extracurricular and ( any(flag is None for flag in activity_flags) or not any(activity_flags) ): issues.append("Vinculo: atividade extracurricular exige tipos preenchidos e ao menos um marcado.") if not vinculo.atividade_extracurricular and any(flag is True for flag in activity_flags): issues.append("Vinculo: tipos de atividade exigem Atividade extracurricular igual a Sim.") if vinculo.ingressou_acao_afirmativa: if vinculo.tipo_politica_acao_afirmativa is None: issues.append("Vinculo: acao afirmativa exige tipo de politica.") reserve_flags = [ vinculo.reserva_ppi, vinculo.reserva_renda, vinculo.reserva_pessoa_com_deficiencia, vinculo.reserva_escola_publica, vinculo.reserva_quilombola, vinculo.reserva_transgenero_travesti, vinculo.reserva_estudante_internacional, vinculo.reserva_refugiado_apatrida_visto_humanitario, vinculo.reserva_idoso, vinculo.reserva_povos_comunidades_tradicionais, vinculo.reserva_olimpiadas_conhecimento, vinculo.reserva_outros, ] if not any(flag is True for flag in reserve_flags) and vinculo.tipo_acao_afirmativa_lei_cotas is None: issues.append("Vinculo: acao afirmativa exige ao menos um tipo.") return issues