diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index acbd50efb8..302133ae61 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -2,9 +2,13 @@ name: tests on: push: - branches: 2.* + branches: + - 2.* + - master pull_request: - branches: 2.* + branches: + - 2.* + - master jobs: default: diff --git a/app/Http/Controllers/Api/StudentController.php b/app/Http/Controllers/Api/StudentController.php new file mode 100644 index 0000000000..220fa462a9 --- /dev/null +++ b/app/Http/Controllers/Api/StudentController.php @@ -0,0 +1,31 @@ +state_registration_id = $request->getStateRegistration(); + $student->saveOrFail(); + + return [ + 'id' => $student->getKey(), + 'state_registration_id' => $student->state_registration_id, + ]; + } +} diff --git a/app/Http/Kernel.php b/app/Http/Kernel.php index bc93747b93..db3c90345f 100644 --- a/app/Http/Kernel.php +++ b/app/Http/Kernel.php @@ -46,6 +46,11 @@ class Kernel extends HttpKernel 'api' => [ 'bindings', ], + + 'api:rest' => [ + 'bindings', + \App\Http\Middleware\CheckToken::class, + ], ]; /** diff --git a/app/Http/Middleware/CheckToken.php b/app/Http/Middleware/CheckToken.php new file mode 100644 index 0000000000..e06f6bd259 --- /dev/null +++ b/app/Http/Middleware/CheckToken.php @@ -0,0 +1,29 @@ +bearerToken(); + + if ($token && config('legacy.apis.access_key') === $token) { + return $next($request); + } + + throw new UnauthorizedException(); + } +} diff --git a/app/Http/Requests/Api/UpdateStateRegistrationRequest.php b/app/Http/Requests/Api/UpdateStateRegistrationRequest.php new file mode 100644 index 0000000000..7985bd4149 --- /dev/null +++ b/app/Http/Requests/Api/UpdateStateRegistrationRequest.php @@ -0,0 +1,43 @@ + [ + new StateRegistrationFormatRule(), + new StateRegistrationUniqueRule($this->student), + ], + ]; + } + + /** + * @return string + */ + public function getStateRegistration() + { + return $this->input('state_registration_id'); + } +} diff --git a/app/Models/LegacyStudent.php b/app/Models/LegacyStudent.php index 4f3dbf186e..e3726930af 100644 --- a/app/Models/LegacyStudent.php +++ b/app/Models/LegacyStudent.php @@ -83,6 +83,16 @@ public function getInepNumberAttribute() return $this->inep ? $this->inep->number : null; } + public function getStateRegistrationIdAttribute() + { + return $this->aluno_estado_id; + } + + public function setStateRegistrationIdAttribute($value) + { + $this->aluno_estado_id = $value; + } + public function inep() { return $this->hasOne(StudentInep::class, 'cod_aluno', 'cod_aluno'); diff --git a/app/Rules/StateRegistrationFormatRule.php b/app/Rules/StateRegistrationFormatRule.php new file mode 100644 index 0000000000..3f9dd18c18 --- /dev/null +++ b/app/Rules/StateRegistrationFormatRule.php @@ -0,0 +1,31 @@ +studentToIgnore = $studentToIgnore; + } + + /** + * Determine if the validation rule passes. + * + * @param string $attribute + * @param mixed $value + * @return bool + */ + public function passes($attribute, $value) + { + return LegacyStudent::query() + ->where('aluno_estado_id', $value) + ->when($this->studentToIgnore, function ($query) use ($value) { + $query->where('cod_aluno', '<>', $this->studentToIgnore->getKey()); + }) + ->doesntExist(); + } + + /** + * Get the validation error message. + * + * @return string + */ + public function message() + { + return 'Já existe uma aluno com este número de inscrição.'; + } +} diff --git a/app/Services/CyclicRegimeService.php b/app/Services/CyclicRegimeService.php index b4a2d70279..a0bfabd076 100644 --- a/app/Services/CyclicRegimeService.php +++ b/app/Services/CyclicRegimeService.php @@ -26,6 +26,7 @@ public function getAllRegistrationsOfCycle($registration) foreach ($grades as $grade) { $result = LegacyRegistration::where('ref_ref_cod_serie', $grade->getKey()) ->where('ref_cod_aluno', $registration->ref_cod_aluno) + ->where('ano', $registration->ano) ->active() ->get() ->first(); diff --git a/composer.lock b/composer.lock index c51d23ac70..93be467b5a 100644 --- a/composer.lock +++ b/composer.lock @@ -64,16 +64,16 @@ }, { "name": "aws/aws-sdk-php", - "version": "3.171.21", + "version": "3.172.0", "source": { "type": "git", "url": "https://github.com/aws/aws-sdk-php.git", - "reference": "0455d92bb12d44f80db96a4e70861d186063e9e5" + "reference": "5a5e66c4d54c392042820703eeb8a6bd3d222924" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/0455d92bb12d44f80db96a4e70861d186063e9e5", - "reference": "0455d92bb12d44f80db96a4e70861d186063e9e5", + "url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/5a5e66c4d54c392042820703eeb8a6bd3d222924", + "reference": "5a5e66c4d54c392042820703eeb8a6bd3d222924", "shasum": "" }, "require": { @@ -148,9 +148,9 @@ "support": { "forum": "https://forums.aws.amazon.com/forum.jspa?forumID=80", "issues": "https://github.com/aws/aws-sdk-php/issues", - "source": "https://github.com/aws/aws-sdk-php/tree/3.171.21" + "source": "https://github.com/aws/aws-sdk-php/tree/3.172.0" }, - "time": "2021-01-21T19:15:43+00:00" + "time": "2021-01-22T19:21:38+00:00" }, { "name": "aws/aws-sdk-php-laravel", @@ -8116,16 +8116,16 @@ }, { "name": "filp/whoops", - "version": "2.9.1", + "version": "2.9.2", "source": { "type": "git", "url": "https://github.com/filp/whoops.git", - "reference": "307fb34a5ab697461ec4c9db865b20ff2fd40771" + "reference": "df7933820090489623ce0be5e85c7e693638e536" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/filp/whoops/zipball/307fb34a5ab697461ec4c9db865b20ff2fd40771", - "reference": "307fb34a5ab697461ec4c9db865b20ff2fd40771", + "url": "https://api.github.com/repos/filp/whoops/zipball/df7933820090489623ce0be5e85c7e693638e536", + "reference": "df7933820090489623ce0be5e85c7e693638e536", "shasum": "" }, "require": { @@ -8175,9 +8175,15 @@ ], "support": { "issues": "https://github.com/filp/whoops/issues", - "source": "https://github.com/filp/whoops/tree/2.9.1" + "source": "https://github.com/filp/whoops/tree/2.9.2" }, - "time": "2020-11-01T12:00:00+00:00" + "funding": [ + { + "url": "https://github.com/denis-sokolov", + "type": "github" + } + ], + "time": "2021-01-24T12:00:00+00:00" }, { "name": "friendsofphp/php-cs-fixer", diff --git a/database/sqls/views/public.info_enrollment.sql b/database/sqls/views/public.info_enrollment.sql index 7a9a2a829d..4f79e01635 100644 --- a/database/sqls/views/public.info_enrollment.sql +++ b/database/sqls/views/public.info_enrollment.sql @@ -43,4 +43,5 @@ from pmieducar.matricula_turma enturmacao inner join pmieducar.matricula matricula on true and matricula.cod_matricula = enturmacao.ref_cod_matricula inner join pmieducar.turma turma on true -and turma.cod_turma = enturmacao.ref_cod_turma; +and turma.cod_turma = enturmacao.ref_cod_turma +and turma.ativo = 1; diff --git a/ieducar/intranet/educar_matricula_det.php b/ieducar/intranet/educar_matricula_det.php index acb1c82622..62b6c98626 100644 --- a/ieducar/intranet/educar_matricula_det.php +++ b/ieducar/intranet/educar_matricula_det.php @@ -219,7 +219,7 @@ public function Gerar() $situacao = App_Model_MatriculaSituacao::getSituacao($registro['aprovado']); $this->addDetalhe(['Situação', $situacao]); - if ($registro['aprovado'] == 4) { + if ($registro['aprovado'] == App_Model_MatriculaSituacao::TRANSFERIDO) { $obj_transferencia = new clsPmieducarTransferenciaSolicitacao(); $lst_transferencia = $obj_transferencia->lista(null, null, null, null, null, $registro['cod_matricula'], null, null, null, null, null, 1, null, null, $registro['ref_cod_aluno'], false); @@ -236,23 +236,24 @@ public function Gerar() $this->addDetalhe(['Estado escola destino', $det_transferencia['estado_escola_destino_externa']]); $this->addDetalhe(['Município escola destino', $det_transferencia['municipio_escola_destino_externa']]); } + $this->addDetalhe(['Observação', $det_transferencia['observacao']]); } if ($registro['aprovado'] == App_Model_MatriculaSituacao::FALECIDO) { - $this->addDetalhe(['Observação', Portabilis_String_Utils::toLatin1($registro['observacao'])]); + $this->addDetalhe(['Observação', $registro['observacao']]); } if ($existeSaidaEscola) { $this->addDetalhe(['Saída da escola', 'Sim']); $this->addDetalhe(['Data de saída da escola', Portabilis_Date_Utils::pgSQLToBr($registro['data_saida_escola'])]); - $this->addDetalhe(['Observação', Portabilis_String_Utils::toLatin1($registro['observacao'])]); + $this->addDetalhe(['Observação', $registro['observacao']]); } if ($registro['aprovado'] == App_Model_MatriculaSituacao::ABANDONO) { $tipoAbandono = new clsPmieducarAbandonoTipo($registro['ref_cod_abandono_tipo']); $tipoAbandono = $tipoAbandono->detalhe(); - $observacaoAbandono = Portabilis_String_Utils::toLatin1($registro['observacao']); + $observacaoAbandono = $registro['observacao']; $this->addDetalhe(['Motivo do Abandono', $tipoAbandono['nome']]); $this->addDetalhe(['Observação', $observacaoAbandono]); diff --git a/ieducar/intranet/educar_serie_cad.php b/ieducar/intranet/educar_serie_cad.php index 7107daf4ff..3cbf7823a5 100644 --- a/ieducar/intranet/educar_serie_cad.php +++ b/ieducar/intranet/educar_serie_cad.php @@ -111,7 +111,7 @@ public function Inicializar() ],[ 'serie' => $this->cod_serie ], - [], + ['ano_letivo' => 'DESC'], false ); } diff --git a/ieducar/intranet/educar_transferencia_solicitacao_cad.php b/ieducar/intranet/educar_transferencia_solicitacao_cad.php index 47000526ab..42df793f66 100644 --- a/ieducar/intranet/educar_transferencia_solicitacao_cad.php +++ b/ieducar/intranet/educar_transferencia_solicitacao_cad.php @@ -163,7 +163,7 @@ public function Gerar() $ref_cod_instituicao = $det_matricula['ref_cod_instituicao']; $this->inputsHelper()->dynamic(['instituicao'], ['required' => false]); - $this->inputsHelper()->dynamic(['escola'], ['label_hint' => 'Destino do aluno', 'required' => false]); + $this->inputsHelper()->dynamic(['escolaSemFiltroPorUsuario'], ['label_hint' => 'Destino do aluno', 'required' => false]); $this->inputsHelper()->checkbox('escola_em_outro_municipio', ['label' => 'Escola em outro municipio?', ]); $this->campoTexto('escola_destino_externa', 'Nome da escola ', '', 30, 255, false, false, false, ''); $this->campoTexto('estado_escola_destino_externa', 'Estado da escola ', '', 20, 50, false, false, false, ''); diff --git a/ieducar/lib/Portabilis/View/Helper/DynamicInput/EscolaSemFiltroPorUsuario.php b/ieducar/lib/Portabilis/View/Helper/DynamicInput/EscolaSemFiltroPorUsuario.php new file mode 100644 index 0000000000..b81e571fcb --- /dev/null +++ b/ieducar/lib/Portabilis/View/Helper/DynamicInput/EscolaSemFiltroPorUsuario.php @@ -0,0 +1,33 @@ +getEscolaId($value); + } + + protected function inputName() + { + return 'ref_cod_escola'; + } + + protected function inputOptions($options) + { + $instituicaoId = $this->getInstituicaoId($options['instituicaoId'] ?? null); + $resources = App_Model_IedFinder::getEscolas($instituicaoId); + + return $this->insertOption(null, 'Selecione uma escola', $resources); + } + + public function escolaSemFiltroPorUsuario($options = []) + { + $this->select($options); + Portabilis_View_Helper_Application::loadChosenLib($this->viewInstance); + Portabilis_View_Helper_Application::loadJavascript($this->viewInstance, '/modules/DynamicInput/Assets/Javascripts/Escola.js'); + } +} diff --git a/readme.md b/readme.md index 4b1849888c..c7eeb002a9 100644 --- a/readme.md +++ b/readme.md @@ -67,7 +67,7 @@ ajudar a alcançar nossos objetivos. - [Instalação do pacote de relatórios](#instalação-do-pacote-de-relatórios) - [Upgrade](#upgrade) -### Depêndencias +### Dependência Para executar o projeto é necessário a utilização de alguns softwares para facilitar o desenvolvimento. @@ -81,8 +81,9 @@ facilitar o desenvolvimento. #### Servidor - [PHP](http://php.net/) versão 7.4 -- [Postgres](https://www.postgresql.org/) versão 9.5 (exata) +- [Postgres](https://www.postgresql.org/) versão 9.5 - [Nginx](https://www.nginx.com/) +- [Redis](https://redis.io/) As seguintes extensões do PHP são necessárias: diff --git a/routes/api.php b/routes/api.php index e2df7b9e2b..04465ffc18 100644 --- a/routes/api.php +++ b/routes/api.php @@ -18,6 +18,11 @@ Route::get('/postal-code/{postalCode}', 'Api\PostalCodeController@search'); Route::post('/students/{student}/rotate-picture', 'Api\StudentRotatePictureController@rotate'); +Route::group([ + 'middleware' => 'api:rest', +], function () { + Route::put('/students/{student}/update-state-registration', 'Api\StudentController@updateStateRegistration'); +}); Route::get('/school-class/calendars', 'Api\SchoolClassController@getCalendars'); Route::get('/school-class/stages/{schoolClass}', 'Api\SchoolClassController@getStages'); diff --git a/tests/Feature/Api/StudentControllerTest.php b/tests/Feature/Api/StudentControllerTest.php new file mode 100644 index 0000000000..1812ebab1c --- /dev/null +++ b/tests/Feature/Api/StudentControllerTest.php @@ -0,0 +1,95 @@ +create(); + + $stateRegistration = '000.000.000'; + + $response = $this->put("/api/students/{$student->getKey()}/update-state-registration", [ + 'state_registration_id' => $stateRegistration, + ], $this->getAuthorizationHeader()); + + $response->assertSuccessful(); + $response->assertJson([ + 'id' => $student->getKey(), + 'state_registration_id' => $stateRegistration, + ]); + + $this->assertDatabaseHas($student->getTable(), [ + 'cod_aluno' => $student->getKey(), + 'aluno_estado_id' => $stateRegistration, + ]); + } + + public function testUpdateStateRegistrationWithDigit() + { + /** @var LegacyStudent $student */ + $student = factory(LegacyStudent::class)->create(); + + $stateRegistration = '000.000.000-1'; + + $response = $this->put("/api/students/{$student->getKey()}/update-state-registration", [ + 'state_registration_id' => $stateRegistration, + ], $this->getAuthorizationHeader()); + + $response->assertSuccessful(); + $response->assertJson([ + 'id' => $student->getKey(), + 'state_registration_id' => $stateRegistration, + ]); + + $this->assertDatabaseHas($student->getTable(), [ + 'cod_aluno' => $student->getKey(), + 'aluno_estado_id' => $stateRegistration, + ]); + } + + public function testUpdateStateRegistrationDuplicated() + { + $this->expectException(ValidationException::class); + + $stateRegistration = '000.000.000'; + + /** @var LegacyStudent $student */ + $student = factory(LegacyStudent::class)->create(); + + factory(LegacyStudent::class)->create([ + 'aluno_estado_id' => $stateRegistration, + ]); + + $response = $this->put("/api/students/{$student->getKey()}/update-state-registration", [ + 'state_registration_id' => $stateRegistration, + ], $this->getAuthorizationHeader()); + + $response->assertJson([]); + } + + public function testUpdateStateRegistrationInvalid() + { + $this->expectException(ValidationException::class); + + /** @var LegacyStudent $student */ + $student = factory(LegacyStudent::class)->create(); + + $stateRegistration = 1234; + + $response = $this->put("/api/students/{$student->getKey()}/update-state-registration", [ + 'state_registration_id' => $stateRegistration, + ], $this->getAuthorizationHeader()); + + $response->assertJson([]); + } +} diff --git a/tests/TestCase.php b/tests/TestCase.php index dcaa47bc67..0d280c6898 100644 --- a/tests/TestCase.php +++ b/tests/TestCase.php @@ -37,6 +37,18 @@ protected function enableForeignKeys() DB::statement('SET session_replication_role = DEFAULT;'); } + /** + * Retorna o header de autorização da API. + * + * @return string[] + */ + protected function getAuthorizationHeader() + { + return [ + 'Authorization' => 'Bearer ' . env('API_ACCESS_KEY') + ]; + } + /** * Método necessário para executar testes legados. *