Spaces:
Running
Running
| # -*- coding: utf-8 -*- | |
| from sqlalchemy import ( | |
| Column, | |
| Integer, | |
| String, | |
| Date, | |
| DateTime, | |
| Boolean, | |
| ForeignKey, | |
| Text | |
| ) | |
| from sqlalchemy.orm import relationship | |
| # If you face cyclic import issues, place Base here via declarative_base: | |
| # from sqlalchemy.orm import declarative_base | |
| # Base = declarative_base() | |
| from datetime import datetime | |
| from banco import Base | |
| from sqlalchemy.sql import func # server_default em AvisoGlobal | |
| # ===================================================== | |
| # TABELA EQUIPAMENTOS | |
| # ===================================================== | |
| class Equipamento(Base): | |
| __tablename__ = "equipamentos" | |
| id = Column(Integer, primary_key=True, index=True) | |
| # Identificação | |
| fpso1 = Column(String, index=True, nullable=False) | |
| fpso = Column(String, index=True, nullable=False) | |
| data_coleta = Column(String, index=True, nullable=False) # sugestão futura: Date | |
| # Responsáveis | |
| especialista = Column(String, nullable=False) | |
| conferente = Column(String, nullable=False) | |
| osm = Column(String, nullable=False) | |
| # Operacional | |
| modal = Column(String, index=True, nullable=False) | |
| quant_equip = Column(Integer, default=0) | |
| mrob = Column(String, nullable=False) | |
| # Métricas | |
| linhas_osm = Column(Integer, default=0) | |
| linhas_mrob = Column(Integer, default=0) | |
| linhas_erros = Column(Integer, default=0) | |
| # Erros | |
| erro_storekeeper = Column(String) | |
| erro_operacao = Column(String) | |
| erro_especialista = Column(String) | |
| erro_outros = Column(String) | |
| # Dados complementares | |
| inclusao_exclusao = Column(String) | |
| po = Column(String) | |
| part_number = Column(String) | |
| material = Column(String) | |
| solicitante = Column(String, nullable=False) | |
| motivo = Column(String) | |
| requisitante = Column(String, nullable=False) | |
| nota_fiscal = Column(String, nullable=False) | |
| impacto = Column(String, nullable=False) | |
| dimensao = Column(String, nullable=False) | |
| observacoes = Column(String) | |
| # Dia de inclusão | |
| dia_inclusao = Column(String, nullable=True, index=True) | |
| # Auditoria | |
| data_hora_input = Column(DateTime, default=datetime.utcnow, index=True) | |
| # ===================================================== | |
| # TABELA FPSOS | |
| # ===================================================== | |
| class FPSO(Base): | |
| __tablename__ = "fpsos" | |
| id = Column(Integer, primary_key=True) | |
| nome = Column(String, unique=True, nullable=False, index=True) | |
| ativo = Column(Boolean, default=True) | |
| data_cadastro = Column(DateTime, default=datetime.utcnow) | |
| # ===================================================== | |
| # LOG DE AUDITORIA (OFICIAL) | |
| # ===================================================== | |
| class LogAcesso(Base): | |
| __tablename__ = "log_acesso" | |
| id = Column(Integer, primary_key=True) | |
| usuario = Column(String, nullable=False, index=True) | |
| acao = Column(String, nullable=False) | |
| tabela = Column(String, nullable=True) | |
| registro_id = Column(Integer, nullable=True) | |
| data_hora = Column(DateTime, default=datetime.utcnow, index=True) | |
| # ===================================================== | |
| # USUÁRIOS | |
| # ===================================================== | |
| class Usuario(Base): | |
| __tablename__ = "usuarios" | |
| id = Column(Integer, primary_key=True) | |
| # login & segurança | |
| usuario = Column(String, unique=True, nullable=False, index=True) | |
| senha = Column(String, nullable=False) | |
| # perfil & status | |
| perfil = Column(String, nullable=False) # admin | usuario | consulta | |
| ativo = Column(Boolean, default=True) | |
| # auditoria | |
| data_criacao = Column(DateTime, default=datetime.utcnow) | |
| # UI/contato | |
| nome = Column(String, nullable=True, index=True) | |
| email = Column(String, unique=True, index=True, nullable=True) | |
| # aniversário | |
| data_aniversario = Column(Date, nullable=True) | |
| # ===================================================== | |
| # QUIZ - PERGUNTAS | |
| # ===================================================== | |
| class QuizPergunta(Base): | |
| __tablename__ = "quiz_perguntas" | |
| id = Column(Integer, primary_key=True) | |
| pergunta = Column(String, nullable=False) | |
| ativo = Column(Boolean, default=True) | |
| data_criacao = Column(DateTime, default=datetime.utcnow) | |
| respostas = relationship( | |
| "QuizResposta", | |
| back_populates="pergunta", | |
| cascade="all, delete-orphan" | |
| ) | |
| # ===================================================== | |
| # QUIZ - RESPOSTAS | |
| # ===================================================== | |
| class QuizResposta(Base): | |
| __tablename__ = "quiz_respostas" | |
| id = Column(Integer, primary_key=True) | |
| pergunta_id = Column(Integer, ForeignKey("quiz_perguntas.id"), nullable=False) | |
| texto = Column(String, nullable=False) | |
| correta = Column(Boolean, default=False) | |
| pergunta = relationship("QuizPergunta", back_populates="respostas") | |
| # ===================================================== | |
| # QUIZ - PONTUAÇÃO / RANKING | |
| # ===================================================== | |
| class QuizPontuacao(Base): | |
| __tablename__ = "quiz_pontuacoes" | |
| id = Column(Integer, primary_key=True) | |
| usuario = Column(String, nullable=False, index=True) | |
| pontos = Column(Integer, nullable=False, default=0) | |
| data = Column(DateTime, default=datetime.utcnow, index=True) | |
| # ===================================================== | |
| # VÍDEOS - CATEGORIAS | |
| # ===================================================== | |
| class VideoCategoria(Base): | |
| __tablename__ = "video_categorias" | |
| id = Column(Integer, primary_key=True) | |
| nome = Column(String, nullable=False, unique=True) | |
| ativo = Column(Boolean, default=True) | |
| data_criacao = Column(DateTime, default=datetime.utcnow) | |
| # ===================================================== | |
| # VÍDEOS | |
| # ===================================================== | |
| class Video(Base): | |
| __tablename__ = "videos" | |
| id = Column(Integer, primary_key=True) | |
| titulo = Column(String, nullable=False) | |
| descricao = Column(String) | |
| url = Column(String, nullable=False) | |
| categoria_id = Column(Integer, ForeignKey("video_categorias.id")) | |
| categoria = relationship("VideoCategoria") | |
| ativo = Column(Boolean, default=True) | |
| data_criacao = Column(DateTime, default=datetime.utcnow) | |
| # ===================================================== | |
| # CALENDÁRIO - EVENTOS / LEMBRETES | |
| # ===================================================== | |
| class EventoCalendario(Base): | |
| __tablename__ = "eventos_calendario" | |
| id = Column(Integer, primary_key=True) | |
| titulo = Column(String, nullable=False) | |
| descricao = Column(String) | |
| data_evento = Column(Date, nullable=False) | |
| data_lembrete = Column(Date) | |
| ativo = Column(Boolean, default=True) | |
| usuario_criacao = Column(String, nullable=False) | |
| data_criacao = Column(DateTime, default=datetime.utcnow) | |
| # ===================================================== | |
| # IOI-RUN - SUGESTÕES DO SISTEMA | |
| # ===================================================== | |
| class IOIRunSugestao(Base): | |
| __tablename__ = "ioirun_sugestao" | |
| id = Column(Integer, primary_key=True, index=True) | |
| # Identificação do autor | |
| usuario = Column(String, nullable=False, index=True) | |
| # Conteúdo | |
| area = Column(String, nullable=True, index=True) | |
| mensagem = Column(Text, nullable=False) | |
| # Resposta do time (admin) | |
| resposta = Column(Text, nullable=True) | |
| status = Column(String, default="pendente", nullable=False, index=True) # pendente | respondida | |
| responsavel = Column(String, nullable=True) | |
| # Auditoria | |
| data_envio = Column(DateTime, default=datetime.utcnow, nullable=False, index=True) | |
| data_resposta = Column(DateTime, nullable=True) | |
| # ===================================================== | |
| # RNC - REGISTRO DE NÃO CONFORMIDADES (FOR-SGQ-08) | |
| # ===================================================== | |
| class RNC(Base): | |
| __tablename__ = "rnc" | |
| id = Column(Integer, primary_key=True, index=True) | |
| # Identificação | |
| codigo = Column(String(20), unique=True, index=True) # ex.: RNC-2026-0001 | |
| titulo = Column(String(200), nullable=False) | |
| descricao = Column(Text, nullable=False) | |
| # Cabeçalho do formulário | |
| data_form = Column(Date, nullable=True, index=True) # Data do formulário | |
| emitente = Column(String(120), nullable=True, index=True) | |
| rnc_cliente_numero = Column(String(50), nullable=True) | |
| cliente_emitente = Column(String(120), nullable=True) | |
| area_solicitante = Column(String(120), nullable=True, index=True) | |
| area_notificada = Column(String(120), nullable=True, index=True) | |
| origem = Column(String(50), nullable=True, index=True) # Auditoria Interna/Externa/Outras | |
| # Envolvidos | |
| envolvido1_nome = Column(String(120), nullable=True) | |
| envolvido1_matricula = Column(String(50), nullable=True) | |
| envolvido1_funcao = Column(String(120), nullable=True) | |
| envolvido2_nome = Column(String(120), nullable=True) | |
| envolvido2_matricula = Column(String(50), nullable=True) | |
| envolvido2_funcao = Column(String(120), nullable=True) | |
| # Classificação | |
| tipo = Column(String(50), nullable=True) | |
| severidade = Column(String(20), nullable=True) | |
| prioridade = Column(String(20), nullable=True) | |
| # Status e prazos | |
| status = Column(String(30), default="Aberta", nullable=False, index=True) | |
| data_abertura = Column(DateTime, default=datetime.utcnow, index=True) | |
| prazo = Column(DateTime, nullable=True, index=True) | |
| encerrada_em = Column(DateTime, nullable=True, index=True) | |
| # Responsáveis | |
| responsavel = Column(String(120), nullable=True, index=True) | |
| criado_por = Column(String(120), nullable=False, index=True) | |
| # Complementares | |
| cliente = Column(String(120), nullable=True) | |
| local = Column(String(120), nullable=True) | |
| # Análise das causas | |
| metodologia = Column(String(120), nullable=True) # ex.: Ishikawa, 5 Porquês | |
| causa_raiz = Column(Text, nullable=True) # descrição da causa raiz | |
| ishikawa_json = Column(Text, nullable=True) # opcional: armazenar estrutura Ishikawa em JSON | |
| # Auditoria | |
| data_hora_input = Column(DateTime, default=datetime.utcnow, index=True) | |
| # Relacionamentos | |
| comentarios = relationship("RNCComentario", back_populates="rnc", cascade="all, delete-orphan") | |
| acoes = relationship("RNCAcaoCorretiva", back_populates="rnc", cascade="all, delete-orphan") | |
| anexos = relationship("RNCAnexo", back_populates="rnc", cascade="all, delete-orphan") | |
| # ===================================================== | |
| # RNC - COMENTÁRIOS / TIMELINE | |
| # ===================================================== | |
| class RNCComentario(Base): | |
| __tablename__ = "rnc_comentario" | |
| id = Column(Integer, primary_key=True, index=True) | |
| rnc_id = Column(Integer, ForeignKey("rnc.id"), nullable=False, index=True) | |
| data = Column(DateTime, default=datetime.utcnow, index=True) | |
| autor = Column(String(120), nullable=False, index=True) | |
| mensagem = Column(Text, nullable=False) | |
| status_novo = Column(String(30), nullable=True, index=True) | |
| prazo_novo = Column(DateTime, nullable=True, index=True) | |
| responsavel_novo = Column(String(120), nullable=True, index=True) | |
| rnc = relationship("RNC", back_populates="comentarios") | |
| # ===================================================== | |
| # RNC - AÇÕES CORRETIVAS / PREVENTIVAS | |
| # ===================================================== | |
| class RNCAcaoCorretiva(Base): | |
| __tablename__ = "rnc_acao" | |
| id = Column(Integer, primary_key=True, index=True) | |
| rnc_id = Column(Integer, ForeignKey("rnc.id"), nullable=False, index=True) | |
| descricao = Column(Text, nullable=False) | |
| responsavel = Column(String(120), nullable=True, index=True) | |
| prazo = Column(DateTime, nullable=True, index=True) | |
| status = Column(String(30), default="Planejada", nullable=False, index=True) | |
| eficacia = Column(String(30), nullable=True, index=True) | |
| conclusao_em = Column(DateTime, nullable=True, index=True) | |
| rnc = relationship("RNC", back_populates="acoes") | |
| # ===================================================== | |
| # RNC - ANEXOS | |
| # ===================================================== | |
| class RNCAnexo(Base): | |
| __tablename__ = "rnc_anexo" | |
| id = Column(Integer, primary_key=True, index=True) | |
| rnc_id = Column(Integer, ForeignKey("rnc.id"), nullable=False, index=True) | |
| nome_arquivo = Column(String(255), nullable=False) | |
| caminho = Column(String(500), nullable=False) | |
| conteudo_tipo = Column(String(120), nullable=True) | |
| enviado_por = Column(String(120), nullable=True, index=True) | |
| enviado_em = Column(DateTime, default=datetime.utcnow, index=True) | |
| rnc = relationship("RNC", back_populates="anexos") | |
| # ===================================================== | |
| # AVISO GLOBAL (banner superior) | |
| # ===================================================== | |
| class AvisoGlobal(Base): | |
| __tablename__ = "aviso_global" | |
| id = Column(Integer, primary_key=True, index=True) | |
| mensagem = Column(Text, nullable=False) | |
| # Estilo/visual | |
| bg_color = Column(String(32), default="#FFF3CD") | |
| text_color = Column(String(32), default="#664D03") | |
| largura = Column(String(16), default="100%") | |
| efeito = Column(String(16), default="marquee") | |
| velocidade = Column(Integer, default=20) | |
| font_size = Column(Integer, default=14) | |
| # Controle/estado | |
| ativo = Column(Boolean, default=True, index=True) | |
| # Auditoria | |
| created_at = Column(DateTime(timezone=True), server_default=func.now()) | |
| updated_at = Column(DateTime(timezone=True), server_default=func.now(), onupdate=func.now()) | |
| # ===================================================== | |
| # RECEBIMENTO — PLANILHA OFICIAL (UM REGISTRO POR LINHA) | |
| # Alinhado ao layout oficial de 37 colunas | |
| # ===================================================== | |
| class RecebimentoRegistro(Base): | |
| __tablename__ = "recebimento_registros" | |
| # PK interno + ID da planilha | |
| id = Column(Integer, primary_key=True, autoincrement=True, index=True) | |
| id_planilha = Column(Integer, nullable=True, index=True, unique=True) # ID da planilha, se houver | |
| # Datas | |
| data = Column(Date, nullable=True) | |
| data_emissao = Column(Date, nullable=True) | |
| # Horas (texto HH:MM:SS para compatibilidade) | |
| hora_chegada_portaria = Column(String(8), nullable=True) | |
| hora_chegada_ifs = Column(String(8), nullable=True) | |
| hora_saida_ifs_wms = Column(String(8), nullable=True) | |
| hora_liberacao_operacao = Column(String(8), nullable=True) | |
| hora_chegada_operacao = Column(String(8), nullable=True) | |
| hora_saida_operacao = Column(String(8), nullable=True) | |
| hora_retorno_operacao = Column(String(8), nullable=True) | |
| hora_liberacao_motorista = Column(String(8), nullable=True) | |
| # Dados principais | |
| placa_veiculo = Column(String(50), nullable=True) | |
| transportadora = Column(String(255), nullable=True) | |
| po = Column(String(60), nullable=True) | |
| incoterms = Column(String(30), nullable=True) | |
| qtd_sku = Column(Integer, nullable=True) | |
| nota_fiscal = Column(String(80), nullable=True) | |
| fornecedor = Column(String(255), nullable=True) | |
| # Bools (SIM/NÃO/N/A) | |
| quimicos = Column(Boolean, nullable=True) | |
| fds = Column(Boolean, nullable=True) | |
| repetro = Column(Boolean, nullable=True) | |
| aprovado = Column(Boolean, nullable=True) | |
| # Status/Texto | |
| natureza_operacao = Column(String(120), nullable=True) | |
| tipo_operacao = Column(String(120), nullable=True) | |
| barco = Column(String(80), nullable=True) | |
| # Campo alinhado com a coluna "DIVERGENCIA" do layout oficial | |
| divergencia = Column(String(200), nullable=True) | |
| ifs = Column(String(120), nullable=True) | |
| wms = Column(String(120), nullable=True) | |
| fotografia = Column(String(255), nullable=True) | |
| entrega = Column(String(120), nullable=True) | |
| projeto = Column(String(120), nullable=True) | |
| good_receipt = Column(String(120), nullable=True) | |
| divergencia_recebimento = Column(String(255), nullable=True) | |
| qualidade = Column(String(120), nullable=True) | |
| divergencia_qualidade = Column(String(255), nullable=True) | |
| observacao = Column(Text, nullable=True) | |
| agendamento = Column(String(120), nullable=True) | |
| responsavel = Column(String(120), nullable=True) | |
| # Novos campos (opcionais) para colunas adicionais do layout | |
| po_alt = Column(String(60), nullable=True) # mapeia "P.O" (alternativo) | |
| pn = Column(String(120), nullable=True) # mapeia "PN" | |
| lot_batch = Column(String(120), nullable=True) # mapeia "LOT BATCH" | |
| # Auditoria mínima | |
| created_by = Column(String(150), nullable=True) | |
| updated_by = Column(String(150), nullable=True) | |
| created_at = Column(DateTime, default=datetime.utcnow) | |
| updated_at = Column(DateTime, default=datetime.utcnow, onupdate=datetime.utcnow) | |