i-educar - 1º seminário php no serpro
Post on 15-Apr-2017
498 Views
Preview:
TRANSCRIPT
Líder em soluções de TI para governo
Sistema de Gestão Escolar
Carlos M. dos SantosCoordenação Estratégica de Ações Governamentais - CEAGO
1º Seminário de PHP da SERPRO9 de novembro de 2015
Introdução
● Software de gestão escolar
● Desenvolvido inicialmente pela Prefeitura de Itajaí, SC
● Software Livre
● Desenvolvimento ativo
Software livre
● Portal do Software Público Brasileiro (SPB)
● Disponível sob licença GPL
● http://softwarepublico.gov.br
Histórico
● 2006/2007
● Criação do SoftwareCTIMA – Prefeitura Municipal de Itajaí
● 2008
● Portal do Software Público Brasileiro
● Parceria com Cobra Tecnologia
● 2010/2011
● Comunidade ativa
● Portabilis Tecnologia
● 2014/2015
● Parceria – SERPRO, Ieducativa Soluções e Portabilis Tecnologia
● Trabalho unificado no novo Portal do SPB
Evolução
● CTIMA/Prefeitura de Itajaí
● Desenvolvimento do software
● Cobra Tecnologia
● Refatoração e criação de arquitetura em framework
● Portabilis Tecnologia
● Novas funcionalidades, modelo Software as a Service (SaaS)
● SERPRO
● Migração para PostgreSQL 9.X
● Produção a ser feita em modelo Infrastructure as a Service (IaaS)
● Importação Educacenso
Quem usa?
●Araranguá/SC●Arapiraca/AL●Balneário Arroio do Silva/SC●Balneário Gaivota/SC●Balneário Rincão/SC●Benevides/PA●Bonito/MS●Botucatu/SP●Cocal do Sul/SC●Colégio Tiradentes da Brigada Militar Passo Fundo/RS●Dom Eliseu/PA●Esplanada/BA●Estado de Alagoas●Florianópolis/SC●Grão Pará/SC●Içara/SC●Irecê/BA●Instituto Mãos de Arte Paranoá/DF●Itajaí/SC●Jacinto Machado/SC●Jaguaruna/SC●Lagoa Grande/PE●Laguna/SC●Maracajá/SC●Meleiro/SC
● Montes Claros/MG● Natuba/PB● Nova Veneza/SC● Pacajá/PA● Pescaria Brava/SC● Praia Grande/SC● Polícia Militar da Paraíba● Sangão/SC● Santa Rosa do Sul/SC● São Francisco do
Conde/BA● Sombrio/SC● Timbé do Sul/SC● Sombrio/SC● Valparaíso de Goiás/GO
Programa Cidades Digitais
● Ministério das ComunicaçõesSecretaria de Inclusão Digital
● 362 municípios contemplados
● Infraestrutura de acesso
● Softwares de Gestão Pública
Quem o SERPRO atende?
Valparaíso de GoiásAcordo de Cooperação
Viçosa do CearáPrograma Cidades Digitais
Módulos principais
● Escola
● Cadastros: Controle de alunos, turmas, matrículas, ...
● Movimentações: Controle de notas, frequência, ...
● Documentos: Emissão de boletins, atestados, certificados, …
● Biblioteca
● Controle de empréstimos
● Inventário do acervo
● Transporte escolar
● Cadastro de prestadores e veículos
● Controle de rotas oferecidas
● Agenda
● Gestão de Pessoas
Funcionalidades
● Documentos
● Emissão de boletins, relatórios gerenciais e atestados de vaga e matrícula, ...
Benefícios
● Menor despesa com sistemas de informação
● Automação dos procedimentos de gestão escolar
● Redução do uso de papel
● Centralização dos cadastros
● Gestão unificada da rede de ensino
● Frequente evolução do software na comunidade
Três gerações de código
● 1ª – Gerador de código (ewwww...)
● 2ª – Framework próprio
● 3ª – Migração para API
Exploração arqueológica do código
● Aplicação da intranet da Prefeitura de Itajaí
● Stack em Linux, PostgreSQL (8.2!), PHP e Apache HTTPD
● Diversos sistemas de controle integrados
● Charset ISO-8859-1
Código antigo – DAOs primitivos
<?php
class clsPessoaFisica extends clsPessoaFj { var $idpes; var $data_nasc; var $sexo; var $data_obito; var $nacionalidade; var $idmun_nascimento;
function clsPessoaFisica($int_idpes = FALSE, $numeric_cpf = FALSE, $date_data_nasc = FALSE, $str_sexo = FALSE, …);
function lista($str_nome = FALSE, $numeric_cpf = FALSE, $inicio_limite = FALSE, $qtd_registros = FALSE, $str_orderBy = FALSE, …);
function detalhe();
function excluir();
}
?>
Código antigo – Templates simples
<table summary="" class='tabelanum2' border='0' cellspacing='0' cellpadding='0'>
<tr><td class="r3c1" width='170'><!-- #&MENU&# --></td><td valign=top>
<table summary="" class='tabelanum2' border='0' cellspacing='0' cellpadding='0'>
<tr><td height="0" id="menu_suspenso">
<input type="hidden" value="" id="posx"><input type="hidden" value="" id="posy">
</td></tr><tr>
<td height="100%" valign="top" id="corpo"><!-- #&PROG_ALERT&# --><!-- #&NOTIFICACOES&# --><!-- #&CORPO&# --></td>
</tr></table>
</td></tr>
</table>
Código antigo – Um arquivo .php por página
<?php
class clsIndex extends clsBase {function Formular() {
$this->SetTitulo( "Pessoas Físicas" );$this->processoAp = 43;
$this->addEstilo( "localizacaoSistema" );}
}
class indice extends clsListagem {function Gerar() { /* retorna um monte de HTML em texto */ }
}
$pagina = new clsIndex();
$miolo = new indice();$pagina->addForm( $miolo );
$pagina->MakeAll();
?>
Código antigo – Banco de dados
CREATE TABLE endereco_externo ( idpes numeric(8,0) NOT NULL, tipo numeric(1,0) NOT NULL, idtlog character varying(5) NOT NULL, logradouro character varying(150) NOT NULL, numero numeric(6,0), letra character(1), complemento character varying(20), bairro character varying(40), cep numeric(8,0), cidade character varying(60) NOT NULL, sigla_uf character(2) NOT NULL, reside_desde date, idpes_rev numeric, data_rev timestamp without time zone, origem_gravacao character(1) NOT NULL, idpes_cad numeric, data_cad timestamp without time zone NOT NULL, operacao character(1) NOT NULL, bloco character varying(20), andar numeric(2,0), apartamento numeric(6,0), idsis_rev integer, idsis_cad integer NOT NULL, zona_localizacao integer DEFAULT 1, CONSTRAINT ck_endereco_externo_operacao CHECK ((((operacao = 'I'::bpchar) OR (operacao = 'A'::bpchar)) OR (operacao = 'E'::bpchar))), CONSTRAINT ck_endereco_externo_origem_gravacao CHECK (((((origem_gravacao = 'M'::bpchar) OR (origem_gravacao = 'U'::bpchar)) OR (origem_gravacao = 'C'::bpchar)) OR (origem_gravacao = 'O'::bpchar))), CONSTRAINT ck_endereco_externo_tipo CHECK (((tipo >= (1)::numeric) AND (tipo <= (3)::numeric))));
CREATE TABLE endereco_pessoa ( idpes numeric(8,0) NOT NULL, tipo numeric(1,0) NOT NULL, cep numeric(8,0) NOT NULL, idlog numeric(6,0) NOT NULL, numero numeric(6,0), letra character(1), complemento character varying(20), reside_desde date, idbai numeric(6,0) NOT NULL, idpes_rev numeric, data_rev timestamp without time zone, origem_gravacao character(1) NOT NULL, idpes_cad numeric, data_cad timestamp without time zone NOT NULL, operacao character(1) NOT NULL, bloco character varying(20), andar numeric(2,0), apartamento numeric(6,0), idsis_rev integer, idsis_cad integer NOT NULL, CONSTRAINT ck_endereco_pessoa_operacao CHECK ((((operacao = 'I'::bpchar) OR (operacao = 'A'::bpchar)) OR (operacao = 'E'::bpchar))), CONSTRAINT ck_endereco_pessoa_origem_gravacao CHECK (((((origem_gravacao = 'M'::bpchar) OR (origem_gravacao = 'U'::bpchar)) OR (origem_gravacao = 'C'::bpchar)) OR (origem_gravacao = 'O'::bpchar))), CONSTRAINT ck_endereco_pessoa_tipo CHECK (((tipo >= (1)::numeric) AND (tipo <= (3)::numeric))));
Código antigo – Triggers aleatórias
CREATE FUNCTION fcn_aft_ins_endereco_pessoa() RETURNS trigger LANGUAGE plpgsql AS $$DECLARE v_idpes numeric; v_tipo_endereco text; BEGIN v_idpes := NEW.idpes; v_tipo_endereco := NEW.tipo; EXECUTE 'DELETE FROM cadastro.endereco_externo WHERE idpes='||quote_literal(v_idpes)||' AND tipo='||v_tipo_endereco||';'; RETURN NEW;END; $$;
Código moderno – Framework próprio
~/i/d/i/i/l/CoreExt ls -l master❯❯❯ ⏎
total 140drwxr-xr-x 2 wolverine xmen 4096 Set 25 17:44 Configdrwxr-xr-x 5 wolverine xmen 4096 Ago 6 10:30 Controllerdrwxr-xr-x 2 wolverine xmen 4096 Ago 6 10:30 DataMapperdrwxr-xr-x 2 wolverine xmen 4096 Ago 6 10:30 Entitydrwxr-xr-x 2 wolverine xmen 4096 Ago 6 10:30 Exceptiondrwxr-xr-x 2 wolverine xmen 4096 Ago 6 10:30 Servicedrwxr-xr-x 3 wolverine xmen 4096 Ago 6 10:30 Sessiondrwxr-xr-x 2 wolverine xmen 4096 Ago 6 10:30 Validatedrwxr-xr-x 3 wolverine xmen 4096 Ago 6 10:30 View-rw-r--r-- 1 wolverine xmen 7312 Ago 6 10:30 Config.class.php-rw-r--r-- 1 wolverine xmen 2849 Ago 6 10:30 Configurable.php-rw-r--r-- 1 wolverine xmen 22526 Ago 6 10:30 DataMapper.php-rw-r--r-- 1 wolverine xmen 33495 Ago 6 10:30 Entity.php-rw-r--r-- 1 wolverine xmen 4801 Ago 6 10:30 Enum.php-rw-r--r-- 1 wolverine xmen 1451 Ago 6 10:30 Exception.php-rw-r--r-- 1 wolverine xmen 5437 Ago 6 10:30 Locale.php-rw-r--r-- 1 wolverine xmen 1504 Ago 6 10:30 Session.php-rw-r--r-- 1 wolverine xmen 3205 Ago 6 10:30 Singleton.php-rw-r--r-- 1 wolverine xmen 1486 Ago 6 10:30 View.php
Código moderno – Arquivo de coniguração
[production]app.database.dbname = ieducarapp.database.username = ieducarapp.database.hostname = 10.100.148.56app.database.password = ieducarapp.database.port = 5432
app.aws.bucketname = fotos_alunosapp.aws.awsacesskey = 114aa9bac59642fa951a0fed8359930fc602679dapp.aws.awssecretkey = de53907ec5f10615d1c093bd7eb3d11249381f4f
app.template.vars.instituicao = Secretaria de Educação de Campos Novosapp.template.pdf.titulo = Relatório i-Educarapp.template.pdf.logo = campos_novos.png
app.template.loginpage = templates/template_cidades_digitais.tpl
[gothamcity.ieducar.com.br : production]app.database.dbname = Gothamapp.locale.province = SPapp.entity.name = Prefeitura de Gotham cityreport.logo_file_name = batman.pngapp.routes.redirect_to = /intranet/coringa.php
Código moderno – Bootstrapping
global $coreExt;$coreExt = array();
// Localização para pt_BR$locale = CoreExt_Locale::getInstance();$locale->setCulture('pt_BR')->setLocale();
// Instancia objeto CoreExt_Configuration$coreExt['Config'] = new CoreExt_Config_Ini($configFile, CORE_EXT_CONFIGURATION_ENV);$coreExt['Locale'] = $locale;
// Timezonedate_default_timezone_set($coreExt['Config']->app->locale->timezone);
$tenantEnv = $_SERVER['HTTP_HOST'];
// tenta carregar as configurações da seção especifica do tenant,// ex: ao acessar http://tenant.ieducar.com.br será carregado a seção tenant.ieducar.com.br caso existaif ($coreExt['Config']->hasEnviromentSection($tenantEnv)) $coreExt['Config']->changeEnviroment($tenantEnv);
...
Código moderno – API
class PessoaController extends ApiCoreController { protected function validatesResourceId(); protected function loadPessoa($id = null); protected function loadPessoaByCpf($cpf = null); protected function searchOptions(); protected function get() { $pessoa = array(); if ($this->canGet()) { if ($this->getRequest()->id) $pessoa = $this->loadPessoa($this->getRequest()->id); else $pessoa = $this->loadPessoaByCpf($this->getRequest()->cpf); $attrs = array('id', 'nome'); $pessoa = Portabilis_Array_Utils::filter($pessoa, $attrs); $details = $this->loadDetails($this->getRequest()->id); } return $pessoa; } public function Gerar() { if ($this->isRequestFor('get', 'pessoa-search')) $this->appendResponse($this->search()); elseif ($this->isRequestFor('get', 'pessoa')) $this->appendResponse($this->get()); else $this->notImplementedOperationError(); }}
Código moderno – MVC - View
class ViewController extends Core_Controller_Page_ViewController { protected $_dataMapper = 'Docente_Model_LicenciaturaDataMapper'; protected $_titulo = 'Detalhes da licenciatura'; protected $_processoAp = 635; protected $_tableMap = array( 'Licenciatura' => 'licenciatura', 'Curso' => 'curso', 'Ano de conclusão' => 'anoConclusao', 'IES' => 'ies' ); public function setUrlEditar(CoreExt_Entity $entry) { $this->url_editar = CoreExt_View_Helper_UrlHelper::url( 'edit', array('query' => array( 'id' => $entry->id, 'servidor' => $entry->servidor, 'instituicao' => $this->getRequest()->instituicao )) ); } public function setUrlCancelar(CoreExt_Entity $entry) { $this->url_cancelar = CoreExt_View_Helper_UrlHelper::url( 'index', array('query' => array( 'id' => $entry->id, 'servidor' => $entry->servidor, 'instituicao' => $this->getRequest()->instituicao )) ); }}
Código moderno – MVC - Model
class Docente_Model_Licenciatura extends CoreExt_Entity { protected $_data = array( 'servidor' => NULL, 'licenciatura' => NULL, 'curso' => NULL, 'anoConclusao' => NULL, 'ies' => NULL, 'user' => NULL, 'created_at' => NULL, 'updated_at' => NULL ); protected $_references = array( 'licenciatura' => array( 'value' => NULL, 'class' => 'App_Model_SimNao', 'file' => 'App/Model/SimNao.php' ), 'ies' => array( 'value' => NULL, 'class' => 'Educacenso_Model_IesDataMapper', 'file' => 'Educacenso/Model/IesDataMapper.php' ), 'curso' => array( 'value' => NULL, 'class' => 'Educacenso_Model_CursoSuperiorDataMapper', 'file' => 'Educacenso/Model/CursoSuperiorDataMapper.php' ) );}
Código moderno – Relatórios – Formulários
class BoletimController extends Portabilis_Controller_ReportCoreController { protected $_titulo = 'Boletim Escolar';
function form() { $this->inputsHelper()->dynamic(array('ano', 'instituicao', 'escola', 'curso', 'serie', 'turma')); $this->inputsHelper()->dynamic('matricula', array('required' => false)); $this->inputsHelper()->checkbox('manual', array('label' => 'Preenchimento manual?')); $this->loadResourceAssets($this->getDispatcher()); } function report() {
return new BoletimReport();}
function beforeValidation() { $this->report->addArg('ano', (int)$this->getRequest()->ano); $this->report->addArg('instituicao', (int)$this->getRequest()->ref_cod_instituicao); $this->report->addArg('escola', (int)$this->getRequest()->ref_cod_escola); $this->report->addArg('curso', (int)$this->getRequest()->ref_cod_curso); $this->report->addArg('serie', (int)$this->getRequest()->ref_cod_serie); $this->report->addArg('turma', (int)$this->getRequest()->ref_cod_turma); if (is_null($this->getRequest()->ref_cod_matricula)) $this->report->addArg('matricula',0); else $this->report->addArg('matricula', (int)$this->getRequest()->ref_cod_matricula); $this->report->addArg('manual', $this->getRequest()->manual ? 1 : 0);}}
Código moderno – Relatórios – Mapeamento
class BoletimReport extends Portabilis_Report_ReportCore { function templateName() { $flagTipoBoletimTurma = App_Model_IedFinder::getTurma($codTurma = $this->args['turma']); $flagTipoBoletimTurma = $flagTipoBoletimTurma['tipo_boletim']; if (empty($flagTipoBoletimTurma)) { throw new Exception( Portabilis_String_Utils::toLatin1("Não foi definido o tipo de boletim no cadastro de turmas.") ); } $tiposBoletim = Portabilis_Model_Report_TipoBoletim; $templates = array($tiposBoletim::BIMESTRAL => 'portabilis_boletim', $tiposBoletim::TRIMESTRAL => 'portabilis_boletim_trimestral'); $template = is_null($flagTipoBoletimTurma) ? '' : $templates[$flagTipoBoletimTurma];
function requiredArgs() {$this->addRequiredArg('ano');$this->addRequiredArg('instituicao');$this->addRequiredArg('escola');$this->addRequiredArg('curso');$this->addRequiredArg('serie');$this->addRequiredArg('turma');
}}
Código moderno – Relatórios – .jrxml
<?xml version="1.0" encoding="UTF-8"?><jasperReport xmlns="http://jasperreports.sourceforge.net/jasperreports" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://jasperreports.sourceforge.net/jasperreports http://jasperreports.sourceforge.net/xsd/jasperreport.xsd" name="portabilis_boletim" language="groovy" pageWidth="595" pageHeight="842" columnWidth="555" leftMargin="20" rightMargin="20" topMargin="20" bottomMargin="20" uuid="4f9ea369-c6c3-48c5-ae82-2872022857d3">
<parameter name="ano" class="java.lang.Integer"><defaultValueExpression><![CDATA[new
java.lang.Integer(0)]]></defaultValueExpression></parameter><parameter name="instituicao" class="java.lang.Integer">
<defaultValueExpression><![CDATA[new java.lang.Integer(0)]]></defaultValueExpression>
</parameter><parameter name="escola" class="java.lang.Integer">
<defaultValueExpression><![CDATA[new java.lang.Integer(0)]]></defaultValueExpression>
</parameter><parameter name="curso" class="java.lang.Integer">
<defaultValueExpression><![CDATA[new java.lang.Integer(0)]]></defaultValueExpression>
</parameter><parameter name="serie" class="java.lang.Integer">
<defaultValueExpression><![CDATA[new java.lang.Integer(0)]]></defaultValueExpression>
</parameter>
Futuro para o código
● Premissa: Aprender com o passado
● Merging nos repositórios do SPB
● Migrations: Phinx
● Concluir implementação da API
● Padronizar uma API
● Criar novos clientes – Professor, Gestão, Pais
● Refatorar o backend
Novos documentos e relatórios
Diário de classe
Certificado de conclusão
Atestado de reserva de vaga
...
Administração no atendimento multi-tenant
Múltiplos clientes por
instância de aplicação
Facilidade de administração
Melhorias no acesso ao PostgreSQL
Migração da versão 8.2 para 9.x
Visualização dos dados do coletor de estatísticas
Automação de testes com Behat + Mink
BDD: Behavior-Driven Development
Próximo passo: Integração contínua
Integração com Educacenso
Importação dos dados do Censo Escolar/INEP
Migração completa em desenvolvimento na comunidade
Próximos passos
Conclusão dos rollouts atuais
- Cidades Digitais
- Valparaíso de Goiás
Entrega do modelo de negócio/serviço
Novas funcionalidades e melhoria contínua
"Fazer do SERPRO uma empresa atuante,
parceira e inovadora em soluções de
gestão educacional, escolar e acadêmica
para uma Pátria, de fato, Educadora."
"O SERPRO, em atendimento ao Programa Cidades Digitais,
internalizou o i-Educar e agora implanta uma nova linha de
atuação para atendimento educacional, com
desenvolvimento colaborativo em comunidade."
Carlos M. dos Santos
Desenvolvedor de Software
SERPRO Florianópolis
carlos-morais.santos@serpro.gov.br
+55 48 3231 8970
top related