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.
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.
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