Andrade Systems
EntregueFiveMCliente: SIDE RP

side_medical

Sistema hospitalar · Lua e React

O saldo do caixa é calculado dentro do próprio INSERT, para que duas movimentações simultâneas não leiam o mesmo saldo anterior.

Tabelas
23

criadas na subida do sistema, sem importar SQL à mão

Endpoints no servidor
63
Capacidades de permissão
19
Lua
4.893 linhas
TypeScript e React
7.068 linhas

Fonte verificada no repositório interno em 08/09/2026

O que faz

Em uso

O sistema cobre o ciclo inteiro de um hospital dentro do jogo: fila e emergências, ficha e prontuário do paciente, evoluções e sinais vitais, solicitação e laudo de exames, estoque e receituário da farmácia, escala de consultas e plantões, chamados de campo e frota de ambulâncias, quadro de pessoal com turno, promoção e advertência, mural, caixa, estatísticas e administração.

A organização vem do grupo do jogador no framework e o cargo vem da hierarquia dele, lida em tempo real. A matriz de permissões vive no banco e a tela de administração serve para revogar, não para conceder: o topo da hierarquia tem tudo e não é editável.

A interface esconde aba e botão que a capacidade não permite. Quem decide, porém, é o servidor: todo endpoint passa por uma checagem de capacidade antes de qualquer efeito.

Evidência

Como o sistema aparece

Capturas da interface real, renderizada com payload de demonstração derivado dos contratos do resource — organizações, cargos, pessoas e identificadores são sintéticos. Onde não existe interface, entra visualização técnica, rotulada como tal.

Explore a interface

Uma ação. Sete responsabilidades.

Inicie uma triagem e acompanhe o caminho até a atualização da tela. Tente antecipar o resultado: o sistema precisa recusar antes de concluir as etapas.

Simulação interativa · Hospital Demo, Paciente Exemplo e estado local. As capturas abaixo mostram a interface real com dados sintéticos.

Simulação isolada, sem conexão com o jogo. Nenhum dado é enviado ou persistido fora desta página.

  • Interface do sistema

    Painel: fila de espera, emergências em campo, ocupação e caixa numa tela só.

  • Interface do sistema

    Pacientes: ficha, prontuário, evoluções e sinais vitais.

  • Interface do sistema

    Exames: solicitação, análise e laudo com resultados.

  • Interface do sistema

    Farmácia: estoque e movimentações. A saída valida a quantidade na própria cláusula do UPDATE.

  • Interface do sistema

    Administração: a matriz de 19 capacidades por nível de hierarquia. A tela serve para revogar — nível 1 tem tudo e não é editável.

Por dentro da engenharia

Decisões de implementação

Um bloco por decisão de implementação. Abra o que interessa.

O saldo é calculado dentro do próprio INSERT

Problema

O caminho natural é ler o saldo, somar e gravar de volta. Com duas movimentações simultâneas, as duas leem o mesmo saldo anterior e uma delas some — sem erro, sem log, sem sintoma até alguém conferir o extrato.

Solução

O novo saldo é computado por uma subconsulta dentro da própria inserção, junto com a linha. Leitura e escrita viram um comando só.

Por que foi feito assim

Correção de dinheiro não pode depender do intervalo entre duas idas ao banco. Se depende, o bug aparece exatamente quando o hospital está movimentado.

A validação de estoque mora na cláusula WHERE

Problema

Conferir a quantidade e depois subtrair permite que dois cliques simultâneos passem os dois pela conferência e deixem o estoque negativo.

Solução

A saída é uma atualização que subtrai a quantidade e ao mesmo tempo exige que ela exista, na própria condição do comando. Se nenhuma linha foi afetada, não havia estoque, e a movimentação não é registrada.

Por que foi feito assim

O banco é a única parte do sistema que enxerga as duas operações. A conferência precisa acontecer onde a decisão acontece.

Código de exibição derivado da chave

Problema

Um código legível como o do atendimento parece pedir uma coluna própria. Coluna própria pede uma sequência, e sequência entre duas inserções simultâneas pede uma corrida.

Solução

O código é derivado da chave primária no momento da leitura. Não existe coluna, não existe sequência, não existe corrida.

Por que foi feito assim

O identificador já é único e já é atômico. Duplicar essa garantia em outro lugar só cria um segundo lugar onde ela pode divergir.

Decisões

Decisões e trade-offs

Cada decisão registra a justificativa e o trade-off aceito.

  1. Nível sem registro na matriz de permissões é liberado por padrão; a tela serve para revogar.

    Cargo novo criado durante o plantão não pode travar o hospital esperando que alguém lembre de cadastrar permissão.

    Custo aceito · Um cargo recém-criado nasce com acesso amplo até que alguém restrinja. A escolha favorece a operação continuar, e está documentada para quem administra.

  2. Horas trabalhadas são aproximadas, e isso está escrito.

    O turno abre quando a pessoa abre o sistema em serviço e fecha na desconexão. É suficiente para o uso real do indicador.

    Custo aceito · Precisão de verdade exigiria amarrar o turno aos eventos de serviço do framework. A aproximação foi aceita conscientemente e registrada, em vez de o número parecer exato.

Stack

O que foi usado

  • Servidor

    • Lua
    • FiveM
    • vRP
  • Dados

    • MySQL
    • Migrations na subida do sistema
    • Cache em memória com expiração
  • Interface

    • React 19
    • Vite
    • Tailwind CSS 4
    • TypeScript
  • Permissões

    • 19 capacidades por nível de hierarquia
    • Checagem no servidor em todo endpoint
    • Registro de toda ação de escrita