QualDoc / app.py
gbope's picture
Update app.py
434bab0 verified
import gradio as gr
import re
def obter_documentos_padrao_2010_mais():
return [
"Certidão de Nascimento (Não pode ser só o RG)",
"Documento com Foto (RG/CNH/OUTROS - se houver)",
"CPF (se não tiver em outro documento)",
"Foto Corporal Completa para Verificação de Saúde",
"Email e celular do responsável"
]
def obter_documentos_padrao_2009_menos():
return [
"Documento com Foto (RG/CNH/OUTROS)",
"CPF (se não tiver no documento com foto)",
"Foto com Documento ao lado do rosto",
"Email e celular"
]
def obter_documentos_carencia():
return [
"3 últimos boletos pagos e seus comprovantes",
"Carteirinha",
"Carta de permanência"
]
def obter_documentos_titular(categoria, modalidade, documentos_padrao):
documentos = documentos_padrao.copy()
documentos.append("Comprovante de Residência: (no nome do titular ou dos pais; Se for no nome de outros, me fale)")
if categoria == "CNPJ":
documentos.append("DA EMPRESA:")
if modalidade == "MEI":
documentos.extend(["CNPJ", "CCMEI"])
elif modalidade == "OUTROS":
documentos.extend(["CNPJ", "Contrato Social e suas alterações"])
elif categoria == "ADESAO":
documentos_map = {
"ENTIDADE ABERTA": None,
"ESTUDANTE": "Declaração Escolar",
"TRABALHADOR": "Contracheque",
"PROFISSIONAL LIBERAL": "Documento de Registro no Conselho na validade + Diploma",
"APOSENTADO": "Comprovante de Pensão"
}
doc_extra = documentos_map.get(modalidade)
if doc_extra:
documentos.append(doc_extra)
return documentos
def simplificar_dependente(nome):
simplificacoes = {
"Cônjuge ou companheiro(a)": "Cônjuge",
"Filhos(as) solteiros naturais, tutelados, enteados e adotivos": "Filhos",
"Filhos(as) inválidos declarados no imposto de renda do titular": "Filho inválido",
"Pai e mãe": "Pais",
"Padrasto e madrasta": "Padrastos",
"Irmãos(ãs) consanguíneos ou adotivos": "Irmãos",
"Netos": "Netos",
"Sobrinhos": "Sobrinhos",
"Primos": "Primos",
"Tios": "Tios",
"Cunhados(as)": "Cunhados",
"Sogro(a)": "Sogro(a)",
"Genros e noras": "Genros/Noras",
"Avô e avó": "Avós"
}
return simplificacoes.get(nome, nome)
def formatar_documentos_para_whatsapp(nome, documentos):
resultado = f"Documentos necessários para {nome}:\n"
for doc in documentos:
if doc == "DA EMPRESA:":
resultado += f"\nDA EMPRESA:\n"
else:
resultado += f"- {doc}\n"
resultado += "\n"
return resultado
def obter_documentos_dependente(dependente, nascido_2010):
documentos = obter_documentos_padrao_2010_mais() if nascido_2010 else obter_documentos_padrao_2009_menos()
if dependente == "Cônjuge ou companheiro(a)":
documentos.append("Certidão de casamento ou declaração de união estável (lavrada em cartório).")
elif "inválido" in dependente:
documentos.append("Declaração de imposto de renda do titular comprovando a condição.")
elif dependente in ["Netos", "Sobrinhos", "Primos", "Tios"]:
documentos.append("Documento com foto (RG/CNH/outros) do pai/mãe.")
elif dependente in ["Cunhados(as)", "Genros e noras"]:
documentos.append("Certidão de casamento.")
elif dependente == "Sogro(a)":
documentos.append("Certidão de casamento do titular")
return documentos
def processar_documentos_para_whatsapp(titular_nascido_2010, categoria, modalidade, titular_carencia, dependentes_info):
texto_final = ""
lista_completa = []
docs_carencia = obter_documentos_carencia()
documentos_padrao_titular = obter_documentos_padrao_2010_mais() if titular_nascido_2010 else obter_documentos_padrao_2009_menos()
documentos_titular = obter_documentos_titular(categoria, modalidade, documentos_padrao_titular)
# --- CORREÇÃO AQUI: Adicionar documentos de carência APENAS se não for categoria CNPJ ---
if titular_carencia and categoria != "CNPJ":
documentos_titular.extend(docs_carencia)
lista_completa.append(("TITULAR", documentos_titular))
if dependentes_info:
for dep_info in dependentes_info:
dep_nascido_2010, dep_tipo, dep_carencia = dep_info
nome_simples = simplificar_dependente(dep_tipo)
docs_dep = obter_documentos_dependente(dep_tipo, dep_nascido_2010)
# Documentos de carência para dependentes sempre são adicionados
if dep_carencia:
docs_dep.extend(docs_carencia)
lista_completa.append((f"Dependente: {nome_simples}", docs_dep))
for nome, documentos in lista_completa:
texto_final += formatar_documentos_para_whatsapp(nome, documentos)
return texto_final.strip(), gr.update(visible=True), gr.update(visible=True)
def atualizar_lista_inclusos(titular_nascido_2010, categoria, modalidade, titular_carencia, dependentes_info):
lista_inclusos = []
tipo_titular = "Titular (2010+)" if titular_nascido_2010 else "Titular (2009-)"
# --- CORREÇÃO AQUI: A frase " + carência" na lista de inclusos só aparece se não for CNPJ ---
if titular_carencia and categoria != "CNPJ":
tipo_titular += " + carência"
lista_inclusos.append([tipo_titular, categoria, modalidade if modalidade else "PF"])
if dependentes_info:
for dep_info in dependentes_info:
dep_nascido_2010, dep_tipo, dep_carencia = dep_info
tipo_dep = f"Dep. {simplificar_dependente(dep_tipo)} (2010+)" if dep_nascido_2010 else f"Dep. {simplificar_dependente(dep_tipo)} (2009-)"
if dep_carencia:
tipo_dep += " + carência"
lista_inclusos.append([tipo_dep, "Dependente", dep_tipo])
return lista_inclusos
def limpar_tudo():
return (
gr.update(value="PF", interactive=True), # categoria
gr.update(choices=[], interactive=False, value=None), # modalidade (reinicia para vazio e desativado)
gr.update(value=False, interactive=True), # titular_nascido_2010
gr.update(value=False, interactive=True), # titular_carencia
gr.Accordion(open=True), # accordion_titular (volta a ser visível e aberto)
gr.update(visible=True), # btn_confirmar_titular (torna o botão de confirmar visível)
gr.update(value=None), # dep_tipo
gr.update(value=False), # dep_nascido_2010
gr.update(value=False), # dep_carencia
gr.update(value=[["Titular (2009-)", "PF", ""]]), # lista_inclusos (volta ao estado inicial)
[], # dependentes_info (limpa a lista de dependentes do estado)
"", # output_textbox (limpa o texto de saída)
gr.update(visible=False), # btn_copiar (oculta o botão de cópia)
gr.update(visible=False, value="") # status_copia (oculta e limpa o status da cópia)
)
def confirmar_titular():
# Isso torna os componentes do titular não interativos e esconde o botão de confirmar.
# O accordion "Adicionar Dependentes" pode ser aberto automaticamente aqui.
return (
gr.update(interactive=False), # categoria
gr.update(interactive=False), # modalidade
gr.update(interactive=False), # titular_nascido_2010
gr.update(interactive=False), # titular_carencia
gr.update(visible=False), # btn_confirmar_titular (esconde o próprio botão)
gr.Accordion(open=True) # Abre o accordion de dependentes
)
def criar_interface():
with gr.Blocks(title="Documentos para Plano de Saúde", theme=gr.themes.Soft()) as app:
gr.Markdown("# 📋 Documentos Necessários para Plano de Saúde")
gr.Markdown("Preencha os dados abaixo para obter a lista de documentos necessários.")
with gr.Row():
with gr.Column():
with gr.Accordion("Dados do Titular", open=True) as accordion_titular:
with gr.Group():
categoria = gr.Radio(
choices=["PF", "CNPJ", "ADESAO"],
label="Categoria do Titular",
value="PF"
)
modalidade = gr.Dropdown(
choices=[],
label="Modalidade (se aplicável)",
interactive=False
)
with gr.Row():
titular_nascido_2010 = gr.Checkbox(label="Nasceu em 2010 ou depois?")
titular_carencia = gr.Checkbox(label="Fará compra de carência?")
btn_confirmar_titular = gr.Button("✅ Confirmar Dados do Titular", variant="primary")
with gr.Accordion("Adicionar Dependentes", open=False) as accordion_deps:
with gr.Group():
gr.Markdown("### Novo Dependente")
dep_tipo = gr.Dropdown(
choices=[
"Cônjuge ou companheiro(a)",
"Filhos(as) solteiros naturais, tutelados, enteados e adotivos",
"Filhos(as) inválidos declarados no imposto de renda do titular",
"Pai e mãe",
"Padrasto e madrasta",
"Irmãos(ãs) consanguíneos ou adotivos",
"Netos",
"Sobrinhos",
"Primos",
"Tios",
"Cunhados(as)",
"Sogro(a)",
"Genros e noras",
"Avô e avó"
],
label="Tipo de Dependente"
)
with gr.Row():
dep_nascido_2010 = gr.Checkbox(label="Nasceu em 2010 ou depois?")
dep_carencia = gr.Checkbox(label="Fará compra de carência?")
btn_adicionar_dep = gr.Button("➕ Adicionar Dependente", variant="primary")
lista_inclusos = gr.Dataframe(
headers=["Inclusos nessa cotação", "Tipo", "Detalhes"],
datatype=["str", "str", "str"],
interactive=False,
label="Inclusos nessa cotação",
value=[["Titular (2009-)", "PF", ""]]
)
dependentes_info = gr.State([])
with gr.Row():
btn_submit = gr.Button("🔍 Gerar Lista de Documentos", variant="primary")
btn_limpar = gr.Button("🧹 Limpar Tudo", variant="secondary")
with gr.Column():
output_textbox = gr.Textbox(
label="Documentos Necessários (Pronto para copiar e colar no WhatsApp!)",
interactive=False,
lines=20,
elem_id="documentos-output-textbox"
)
btn_copiar = gr.Button("📋 Copiar Lista", visible=False)
status_copia = gr.Textbox(label="Status da Cópia", interactive=False, visible=False)
def atualizar_modalidades(categoria):
if categoria == "CNPJ":
return gr.Dropdown(choices=["MEI", "OUTROS"], label="Modalidade CNPJ", interactive=True, value=None)
elif categoria == "ADESAO":
return gr.Dropdown(
choices=["ENTIDADE ABERTA", "ESTUDANTE", "TRABALHADOR", "PROFISSIONAL LIBERAL", "APOSENTADO"],
label="Modalidade Adesão",
interactive=True, value=None
)
else:
return gr.Dropdown(choices=[], label="Modalidade (não aplicável)", interactive=False, value=None)
categoria.change(
atualizar_modalidades,
inputs=categoria,
outputs=modalidade
)
inputs_lista = [titular_nascido_2010, categoria, modalidade, titular_carencia, dependentes_info]
for input_component in inputs_lista:
input_component.change(
atualizar_lista_inclusos,
inputs=inputs_lista,
outputs=lista_inclusos
)
btn_adicionar_dep.click(
lambda dep_info, dep_nasc, dep_tipo, dep_carencia: (dep_info + [(dep_nasc, dep_tipo, dep_carencia)]),
inputs=[dependentes_info, dep_nascido_2010, dep_tipo, dep_carencia],
outputs=dependentes_info
).then(
atualizar_lista_inclusos,
inputs=inputs_lista,
outputs=lista_inclusos
)
btn_submit.click(
processar_documentos_para_whatsapp,
inputs=[
titular_nascido_2010,
categoria,
modalidade,
titular_carencia,
dependentes_info
],
outputs=[output_textbox, btn_copiar, status_copia]
)
btn_copiar.click(
None,
None,
status_copia,
js="""
async () => {
const texto = document.getElementById("documentos-output-textbox").querySelector("textarea").value;
try {
await navigator.clipboard.writeText(texto);
return "✅ Copiado para área de transferência!";
} catch (err) {
const textarea = document.createElement('textarea');
textarea.value = texto;
document.body.appendChild(textarea);
textarea.select();
document.execCommand('copy');
document.body.removeChild(textarea);
return "✅ Copiado (use Ctrl+C se não colar automaticamente)";
}
}
"""
).then(
lambda: gr.update(visible=True),
None,
status_copia
)
btn_limpar.click(
limpar_tudo,
inputs=None,
outputs=[
categoria,
modalidade,
titular_nascido_2010,
titular_carencia,
accordion_titular, # Resetar o accordion do titular (visibilidade)
btn_confirmar_titular, # Torna o botão de confirmar visível novamente
dep_tipo,
dep_nascido_2010,
dep_carencia,
lista_inclusos,
dependentes_info,
output_textbox,
btn_copiar,
status_copia
]
)
btn_confirmar_titular.click(
confirmar_titular,
inputs=None,
outputs=[
categoria,
modalidade,
titular_nascido_2010,
titular_carencia,
btn_confirmar_titular,
accordion_deps
]
)
return app
# Criação e lançamento da interface
app = criar_interface()
app.launch()