Arquitetura e Engenharia - LucasXRosas/utfprarena GitHub Wiki

Esta página detalha as decisões arquiteturais, o ecossistema técnico e os exemplos práticos de implementação em PHP para o sistema de gerenciamento de arena.


Padrão Arquitetural

O back-end é desenvolvido utilizando a versão estável do PHP 8.x, seguindo o paradigma de Programação Orientada a Objetos (POO) e a arquitetura em camadas estruturadas em:

  • Controllers: Responsáveis por receber as requisições HTTP, validar os dados de entrada e retornar respostas JSON.
  • Services/Business Logic: Onde residem as regras de negócio puras (cálculo de mensalidades e checagem de bloqueios).
  • Repositories/Models: Camada encarregada da persistência e comunicação com o banco de dados via PDO (PHP Data Objects) de forma segura contra SQL Injection.

Ecossistema e Dependências

O gerenciamento de pacotes do projeto é feito através do Composer. O arquivo composer.json inclui:

  • Autoload (PSR-4): Para carregamento automático e organizado das classes.
  • firebase/php-jwt: Biblioteca para geração e validação de tokens JWT no login tradicional.
  • vlucas/phpdotenv: Para gerenciar variáveis de ambiente de forma segura (credenciais de banco de dados).

Implementação das Regras de Negócio em PHP

1. Rotina de Verificação e Bloqueio (Script para CLI/Cron Job)

Este script PHP deve ser configurado no servidor (Crontab do Linux) para rodar todas as madrugadas de forma automatizada (ex: 0 2 * * * php /caminho/projeto/cron/verificar_bloqueios.php). Ele busca no banco de dados todos os usuários que violam a regra de inadimplência e aplica o bloqueio de acesso.

<?php

declare(strict_types=1);

require_once __DIR__ . '/../vendor/autoload.php';

use App\Services\BloqueioUsuarioService;
use App\Database\Connection;

try {
    echo "[" . date('Y-m-d H:i:s') . "] Iniciando rotina de verificação de inadimplência...\n";

    $pdo = Connection::getInstance();
    $bloqueioService = new BloqueioUsuarioService($pdo);

    $totalBloqueados =$bloqueioService->processarUsuariosInadimplentes();

    echo "[" . date('Y-m-d H:i:s') . "] Processo concluído com sucesso. Total de alunos bloqueados: {$totalBloqueados}\n";
    exit(0);
} catch (\Throwable $e) {
    fwrite(STDERR, "[" . date('Y-m-d H:i:s') . "] ERRO: " . $e->getMessage() . "\n");
    exit(1);
}

2. Gatilho de Desbloqueio Automático (Service PHP)

Método responsável por dar baixa no pagamento em PHP e verificar instantaneamente se o número de faturas pendentes caiu abaixo do limite permitido (ex: menos de 2 faturas abertas) para reativar o aluno de forma automatizada.

<?php

declare(strict_types=1);

namespace App\Services;

use PDO;

class DesbloqueioUsuarioService
{
    private PDO $db;

    public function __construct(PDO $db)
    {
        $this->db =$db;
    }

    /**
     * Registra o pagamento de uma fatura e reativa o usuário caso a inadimplência seja quitada.
     */
    public function registrarPagamento(int $faturaId, int$usuarioId): bool
    {
        $this->db->beginTransaction();

        try {
            // 1. Marcar fatura como paga
            $stmt =$this->db->prepare("
                UPDATE faturas 
                SET status = 'PAGA', data_pagamento = NOW() 
                WHERE id = :fatura_id AND usuario_id = :usuario_id
            ");
            $stmt->execute([':fatura_id' => $faturaId, ':usuario_id' =>$usuarioId]);

            // 2. Verificar quantidade de faturas ainda pendentes/vencidas
            $stmtCount =$this->db->prepare("
                SELECT COUNT(*) 
                FROM faturas 
                WHERE usuario_id = :usuario_id AND status = 'PENDENTE' AND data_vencimento < CURRENT_DATE()
            ");
            $stmtCount->execute([':usuario_id' =>$usuarioId]);
            $faturasPendentes = (int)$stmtCount->fetchColumn();

            // 3. Se houver menos de 2 faturas pendentes, reativa o usuário
            if ($faturasPendentes < 2) {
                $stmtReativar =$this->db->prepare("
                    UPDATE usuarios 
                    SET status = 'ATIVO', motivo_bloqueio = NULL 
                    WHERE id = :usuario_id
                ");
                $stmtReativar->execute([':usuario_id' =>$usuarioId]);
            }

            $this->db->commit();
            return true;
        } catch (\Throwable $e) {$this->db->rollBack();
            throw $e;
        }
    }
}