alguma coisa ai
This commit is contained in:
parent
c08b38f91b
commit
5d5f224dff
@ -550,7 +550,7 @@ Substituiu o antigo par de botões "Exportar regra"/"Importar regra" (baixava/li
|
||||
- **Campos**: `nome` (obrigatório), `operadora` (opcional — a `key` de `planos_saude.pipeline.OPERADORAS`, não o label; só usada pra pré-selecionar o `<select>` de operadora ao aplicar a regra, nunca bloqueia aplicar uma regra com uma operadora diferente da atual), `tipos_lancamento`/`custeio_por_tipo` (exatamente o mesmo formato dos campos homônimos de `ImportacaoPlanoSaude`, ver acima) e `observacoes` (texto livre).
|
||||
- **Validação reaproveitada, não duplicada**: `RegraCusteioPlanoSaudeSerializer.validate()` e `ImportacaoPlanoSaudeCreateSerializer.validate()` chamam a mesma função módulo-level `_monta_regra_custeio()` (`serializers.py`) pra validar/parsear cada combinação tipo×pessoa — sem isso, a regra de negócio de custeio (parsing BR, faixa 0–100 do percentual, "ao menos um de limite/percentual") viveria duplicada em dois serializers e podia divergir com o tempo. A única diferença entre os dois pontos de entrada é o formato de payload: `ImportacaoPlanoSaudeCreateSerializer` recebe campos multipart achatados (`custeio_mensalidade_titular`, `limite_valor_mensalidade_titular`...), `RegraCusteioPlanoSaudeSerializer` recebe o `custeio_por_tipo` já aninhado como JSON puro.
|
||||
- **`limite_valor`/`percentual` sempre em texto BR na entrada, float|None persistido**: igual ao resto do módulo, esses dois campos chegam como string BR (`"150,00"`) tanto no create de uma importação quanto no banco de regras — mas uma regra salva, uma vez lida de volta pelo `GET`, já vem com esses valores como `float` (formato final persistido). Pra `RegraCusteioPlanoSaudeSerializer` aceitar os dois formatos sem corromper o valor (`"150.0"` seria lido errado como 15000 por `parse_valor_br`, que só entende separador de milhar `.`/decimal `,`), `_valor_custeio_para_texto_br()` normaliza um float de volta pra texto BR (`formata_valor_br`) antes de repassar pro parser — isso é o que permite reenviar uma regra sem edição (ex.: só mudando o nome) sem precisar reformatar nada no frontend.
|
||||
- **Frontend** (`importacao-plano-saude.js`, seção "Regra de custeio salva" — **primeiro** campo do formulário de Nova Importação, antes até de "Operadora": decisão explícita do usuário, já que aplicar uma regra já preenche a operadora junto, então escolher a regra é o primeiro passo natural do fluxo, não um apêndice no final): um combobox pesquisável (`#ips-regra-combo` — `<input>` `#ips-regra-search` + lista flutuante `#ips-regra-combo-list`, filtra por nome a cada tecla; era um `<select>` simples, trocado quando o banco de regras cresceu o bastante pra não caber numa lista sem busca) + "Aplicar" preenche o formulário inteiro (tipos de lançamento + custeio de cada combinação + operadora, se ainda existir na lista) a partir de uma regra salva — os campos continuam 100% editáveis depois, é só um preenchimento em massa (`aplicarCusteio()`/`aplicarRegraNoFormulario()`), mesmo espírito do antigo "Importar regra". `regraSelecionadaId` (JS) rastreia o que está de fato escolhido no combobox — digitar de novo no campo invalida a seleção anterior até o usuário clicar numa regra da lista, pra "Aplicar" nunca usar uma regra desatualizada em relação ao texto exibido. "Salvar regra atual..." (`#ips-regra-salvar-btn`) abre um modal (`#ips-regra-save-modal`) pra nomear/descrever a configuração atualmente preenchida (validada antes com a mesma `mensagemErroCusteio()` usada pelo botão "Processar", reaproveitada pelas duas ações) — **editar uma regra existente é literalmente aplicá-la, ajustar o que quiser no formulário, e salvar de novo**: o modal nasce em modo "atualizar a regra selecionada" sempre que a regra atualmente refletida no formulário (`regraAplicadaId`) ainda existir, com uma checkbox pra optar por "criar uma nova regra" em vez de sobrescrever. "Ver regras salvas" (`#ips-regras-modal`) lista todas as regras (nome, operadora, tipos, observações) com ações de Aplicar/Excluir — não duplica a grade de custeio num modal separado, de propósito, pra não manter dois lugares editáveis da mesma coisa.
|
||||
- **Frontend** (`importacao-plano-saude.js`, seção "Regra de custeio salva" — **primeiro** campo do formulário de Nova Importação, antes até de "Operadora": decisão explícita do usuário, já que aplicar uma regra já preenche a operadora junto, então escolher a regra é o primeiro passo natural do fluxo, não um apêndice no final): um combobox pesquisável (`#ips-regra-combo` — `<input>` `#ips-regra-search` + lista flutuante `#ips-regra-combo-list`, filtra por nome a cada tecla; era um `<select>` simples, trocado quando o banco de regras cresceu o bastante pra não caber numa lista sem busca) + "Aplicar" preenche o formulário inteiro (tipos de lançamento + custeio de cada combinação + operadora, se ainda existir na lista) a partir de uma regra salva — os campos continuam 100% editáveis depois, é só um preenchimento em massa (`aplicarCusteio()`/`aplicarRegraNoFormulario()`), mesmo espírito do antigo "Importar regra". `regraSelecionadaId` (JS) rastreia o que está de fato escolhido no combobox — digitar de novo no campo invalida a seleção anterior até o usuário clicar numa regra da lista, pra "Aplicar" nunca usar uma regra desatualizada em relação ao texto exibido. **"Limpar seleção"** (`#ips-regra-limpar-btn`, ao lado de "Aplicar" — adicionado pro caso de aplicar a regra errada por engano) chama `limparRegraSelecionada()` (zera o rastreamento — combobox, `regraSelecionadaId`/`regraAplicadaId`, observações) **e** `limparCusteioForm()` (desfaz o que a regra preencheu: desmarca tipos de lançamento, radios de custeio e campos de limite/percentual de cada combinação tipo×pessoa) — as duas funções foram extraídas de dentro de `resetForm()` justamente pra serem reaproveitadas aqui; não mexe em Operadora nem nos arquivos já anexados, só no que uma regra aplicada de fato preenche em massa. **"Ver regras salvas"** (`#ips-regras-modal`) continua no topo, junto de Aplicar/Limpar; **"Salvar regra atual..."** (`#ips-regra-salvar-btn`) foi movido pro **final do formulário** (depois de "Tipo de importação", antes do botão "Processar" — `.ips-regra-salvar-field` em `importacao-plano-saude.css`), decisão explícita do usuário: salvar só faz sentido depois de parametrizar o custeio, é o último passo do fluxo de criar/editar uma regra, não algo que deveria ficar ao lado de Aplicar/Ver regras salvas no topo. Continua abrindo o mesmo modal (`#ips-regra-save-modal`) pra nomear/descrever a configuração atualmente preenchida (validada antes com a mesma `mensagemErroCusteio()` usada pelo botão "Processar", reaproveitada pelas duas ações) — **editar uma regra existente é literalmente aplicá-la, ajustar o que quiser no formulário, e salvar de novo**: o modal nasce em modo "atualizar a regra selecionada" sempre que a regra atualmente refletida no formulário (`regraAplicadaId`) ainda existir, com uma checkbox pra optar por "criar uma nova regra" em vez de sobrescrever. "Ver regras salvas" lista todas as regras (nome, operadora, tipos, observações) com ações de Aplicar/Excluir — não duplica a grade de custeio num modal separado, de propósito, pra não manter dois lugares editáveis da mesma coisa.
|
||||
|
||||
## CSS — organização entre arquivos
|
||||
|
||||
|
||||
Binary file not shown.
@ -0,0 +1,25 @@
|
||||
CODIGOEMPRESA;NOMEFUNC;CPFFUNC;CODIGOOUTEMP;DATAINICIAL;NOMEDEPENDENTE;CPFDEPENDENTE;VALOREMPRESA;VALOR;DESCRICAO
|
||||
221;DIEGO RODRIGO DA FONSECA;007.377.729-30;3755;01/12/2023;;;0;0;
|
||||
221;ZAIRA DAVID BARBOSA;007.396.889-79;3755;01/12/2023;;;0;0;
|
||||
221;ADRIANA OLIVEIRA DOS SANTOS CODO;022.366.869-94;3755;01/12/2023;;;0;0;
|
||||
221;ADRIANA OLIVEIRA DOS SANTOS CODO;022.366.869-94;3755;01/12/2023;RAFHAEL HENRIQUE CODO;133.710.699-23;0;0;
|
||||
221;LEANDRA SPEROTTO;022.795.359-20;3755;01/12/2023;LUCAS SPEROTTO SCHIRMANN;125.709.619-22;0;0;
|
||||
221;LEANDRA SPEROTTO;022.795.359-20;3755;01/12/2023;;;0;0;
|
||||
221;JANE MARILIA BEKER;025.273.319-39;3755;01/12/2023;;;0;0;
|
||||
221;ANELISA CLAUDIA TOLEDO;028.627.449-30;3755;01/12/2023;;;0;0;
|
||||
221;ANELISA CLAUDIA TOLEDO;028.627.449-30;3755;01/12/2023;MURILO AUGUSTO TOLEDO SILVA;140.796.419-40;0;0;
|
||||
221;VANESSA JUIF TRINDADE;032.476.309-37;3755;01/12/2023;;;0;0;
|
||||
221;FERNANDO BERLATTO;040.875.749-38;3755;01/12/2023;;;0;0;
|
||||
221;JOAO VICTOR DE OLIVEIRA EGIDIO;051.271.009-08;3755;01/12/2023;;;0;0;
|
||||
221;MARCOS PAULO GOBBO;057.539.659-89;3755;01/12/2023;;;0;0;
|
||||
221;ELIANA KARPSAK LOPES;064.896.469-86;3755;01/12/2023;;;0;0;
|
||||
221;ELIANA KARPSAK LOPES;064.896.469-86;3755;01/12/2023;LUCAS ANTONIO DE OLIVEIRA;066.200.469-83;0;0;
|
||||
221;PAULA MICHELLI DA SILVA;073.516.259-05;3755;01/12/2023;;;0;0;
|
||||
221;PAULA MICHELLI DA SILVA;073.516.259-05;3755;01/12/2023;EMANUELLY FERREIRA DA SILVA;152.794.939-70;0;0;
|
||||
221;CAROLINE DAYANE DE ALMEIDA;091.247.879-90;3755;01/12/2023;;;0;0;
|
||||
221;JESSICA DE FATIMA CATTANI DE PAULA;092.879.749-00;3755;01/12/2023;;;0;0;
|
||||
221;LUCAS DE SOUZA;093.861.469-08;3755;01/12/2023;;;0;0;
|
||||
221;APARECIDA DOBNER;389.259.312-49;3755;01/12/2023;ANNA CAROLINA DOBNER WILLMBRINK;097.280.639-38;0;0;
|
||||
221;APARECIDA DOBNER;389.259.312-49;3755;01/12/2023;;;0;0;
|
||||
221;MARIZA KARPSAK LOPES;726.088.899-72;3755;01/12/2023;EDUARDO KARPSAK LOPES;096.771.579-22;0;0;
|
||||
221;MARIZA KARPSAK LOPES;726.088.899-72;3755;01/12/2023;;;0;0;
|
||||
|
6
plano.md
6
plano.md
@ -834,6 +834,12 @@ Adicionada mais uma opção de tema de cor (`--accent`) ao seletor de swatches d
|
||||
|
||||
Como `--danger` (usado em feriados/selos de ausente etc.) já era um tom de vermelho (`#e5484d`) escolhido antes de "vermelho" existir como cor de tema selecionável, agora há uma sobreposição visual esperada quando o usuário escolhe o tema "Vermelho": elementos que usam `--accent` (ex.: pill "somente_eu" do Calendário Individual) ficam bem parecidos com elementos de erro/alerta que usam `--danger`. Diferente de `--gold`/`--teal`/`--slate`/`--coral` (rodada 35, escolhidos deliberadamente fora das cores de tema pra nunca colidir com `--accent`), `--danger` não foi criado pensando nisso — é uma coincidência aceita ao adicionar "Vermelho" à lista, não um bug. Se isso incomodar na prática, ajustar `--danger` para um tom fora da família "vermelho" é a correção futura, não mudar a cor do tema.
|
||||
|
||||
### 55. Regra de custeio salva: "Salvar regra atual..." movido pro final do formulário + botão "Limpar seleção"
|
||||
|
||||
Ajuste de usabilidade pedido pelo usuário na seção "Regra de custeio salva" do formulário de Nova Importação: "Salvar regra atual..." saiu de junto de Aplicar/Ver regras salvas (topo do formulário) e passou pro **final** (depois de "Tipo de importação", antes do botão "Processar") — salvar só faz sentido depois de parametrizar o custeio, é o último passo do fluxo, não um botão que deveria ficar ao lado de Aplicar. Aplicar/Limpar seleção/Ver regras salvas continuam no topo, já que aplicar uma regra continua sendo o primeiro passo natural (preenche operadora + custeio de uma vez).
|
||||
|
||||
Novo botão "Limpar seleção" (`#ips-regra-limpar-btn`, ao lado de Aplicar) resolve o caso de aplicar a regra errada por engano: desfaz tanto o rastreamento (`regraSelecionadaId`/`regraAplicadaId`, texto do combobox, observações) quanto o próprio custeio que a regra preencheu (tipos de lançamento, radios de custeio, limite/percentual de cada combinação tipo×pessoa) — as duas partes de `resetForm()` que faziam isso foram extraídas em `limparCusteioForm()`/`limparRegraSelecionada()` pra serem reaproveitadas aqui. De propósito não mexe em Operadora nem nos arquivos já anexados — só desfaz o que uma regra aplicada de fato preenche em massa.
|
||||
|
||||
## Roadmap / próximos passos
|
||||
|
||||
Nenhuma pendência explícita em aberto no momento, exceto a limitação conhecida
|
||||
|
||||
@ -292,6 +292,16 @@
|
||||
white-space: pre-wrap;
|
||||
}
|
||||
|
||||
/* "Salvar regra atual..." fica no final do formulário (não mais junto de
|
||||
Aplicar/Limpar/Ver regras salvas no topo) — salvar só faz sentido depois
|
||||
de parametrizar o custeio abaixo, é o último passo do fluxo de
|
||||
parametrização de uma regra nova. */
|
||||
.ips-regra-salvar-field {
|
||||
margin-top: var(--space-5);
|
||||
padding-top: var(--space-5);
|
||||
border-top: 1px solid var(--border-subtle);
|
||||
}
|
||||
|
||||
/* Lista de regras salvas (#ips-regras-modal) — reaproveita .checklist-box
|
||||
como moldura rolável, mas cada linha tem seus próprios botões de ação em
|
||||
vez do checkbox usado pelos outros consumidores de .checklist-box. */
|
||||
|
||||
@ -202,6 +202,7 @@ document.addEventListener("DOMContentLoaded", async () => {
|
||||
const ipsRegraSearch = document.getElementById("ips-regra-search");
|
||||
const ipsRegraComboList = document.getElementById("ips-regra-combo-list");
|
||||
const ipsRegraAplicarBtn = document.getElementById("ips-regra-aplicar-btn");
|
||||
const ipsRegraLimparBtn = document.getElementById("ips-regra-limpar-btn");
|
||||
const ipsRegraSalvarBtn = document.getElementById("ips-regra-salvar-btn");
|
||||
const ipsRegraObservacoes = document.getElementById("ips-regra-observacoes");
|
||||
const regrasGerenciarBtn = document.getElementById("ips-regras-gerenciar-btn");
|
||||
@ -504,9 +505,11 @@ document.addEventListener("DOMContentLoaded", async () => {
|
||||
renderList();
|
||||
}
|
||||
|
||||
function resetForm() {
|
||||
validadorPlanilha.limpar();
|
||||
validadorArquivo.limpar();
|
||||
// Zera só a parte de tipo/custeio do formulário (tipos_lancamento + modo de
|
||||
// custeio/limite/percentual de cada combinação tipo×pessoa) — extraído de
|
||||
// resetForm() pra ser reaproveitado por "Limpar seleção" (desfaz o que uma
|
||||
// regra aplicada por engano preencheu, sem mexer nos arquivos já anexados).
|
||||
function limparCusteioForm() {
|
||||
formTipoMensalidade.checked = false;
|
||||
formTipoCoparticipacao.checked = false;
|
||||
custeioMensalidade.hidden = true;
|
||||
@ -524,11 +527,24 @@ document.addEventListener("DOMContentLoaded", async () => {
|
||||
if (percentualInput) percentualInput.value = "";
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// Limpa só o rastreamento de "regra selecionada/aplicada" (combobox +
|
||||
// observações), sem mexer no custeio do formulário — usado por resetForm()
|
||||
// e sozinho pelo botão "Limpar seleção" (junto com limparCusteioForm()).
|
||||
function limparRegraSelecionada() {
|
||||
regraAplicadaId = null;
|
||||
regraSelecionadaId = null;
|
||||
if (ipsRegraSearch) ipsRegraSearch.value = "";
|
||||
fecharRegraComboList();
|
||||
mostrarObservacoesRegra(null);
|
||||
}
|
||||
|
||||
function resetForm() {
|
||||
validadorPlanilha.limpar();
|
||||
validadorArquivo.limpar();
|
||||
limparCusteioForm();
|
||||
limparRegraSelecionada();
|
||||
formError.textContent = "";
|
||||
}
|
||||
|
||||
@ -1129,6 +1145,14 @@ document.addEventListener("DOMContentLoaded", async () => {
|
||||
});
|
||||
}
|
||||
|
||||
if (ipsRegraLimparBtn) {
|
||||
ipsRegraLimparBtn.addEventListener("click", () => {
|
||||
limparRegraSelecionada();
|
||||
limparCusteioForm();
|
||||
formError.textContent = "";
|
||||
});
|
||||
}
|
||||
|
||||
if (ipsRegraSalvarBtn) {
|
||||
ipsRegraSalvarBtn.addEventListener("click", () => {
|
||||
const { tipos_lancamento } = coletarCusteioAtual();
|
||||
|
||||
@ -313,17 +313,14 @@
|
||||
<div class="ips-form">
|
||||
<div class="modal-field ips-regra-field">
|
||||
<label>Regra de custeio salva</label>
|
||||
<p class="ips-regra-actions__hint">Aplique uma regra salva pra preencher a operadora e o custeio abaixo automaticamente, ou salve a configuração atual como uma regra nova pra reaproveitar em importações futuras — os campos continuam editáveis normalmente depois.</p>
|
||||
<p class="ips-regra-actions__hint">Aplique uma regra salva pra preencher a operadora e o custeio abaixo automaticamente — os campos continuam editáveis normalmente depois. Selecionou a regra errada? Use "Limpar seleção" pra desfazer.</p>
|
||||
<div class="ips-regra-actions">
|
||||
<div class="ips-regra-combo" id="ips-regra-combo">
|
||||
<input type="text" id="ips-regra-search" class="ips-regra-combo__input" placeholder="Selecionar regra salva..." autocomplete="off" />
|
||||
<div class="ips-regra-combo__list" id="ips-regra-combo-list" hidden></div>
|
||||
</div>
|
||||
<button type="button" class="btn-outline" id="ips-regra-aplicar-btn">Aplicar</button>
|
||||
<button type="button" class="btn-outline" id="ips-regra-salvar-btn">
|
||||
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M19 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h11l5 5v11a2 2 0 0 1-2 2Z" stroke-linejoin="round"/><path d="M17 21v-8H7v8M7 3v5h5" stroke-linejoin="round"/></svg>
|
||||
Salvar regra atual...
|
||||
</button>
|
||||
<button type="button" class="btn-outline" id="ips-regra-limpar-btn">Limpar seleção</button>
|
||||
<button type="button" class="btn-outline" id="ips-regras-gerenciar-btn">Ver regras salvas</button>
|
||||
</div>
|
||||
<p class="ips-regra-observacoes" id="ips-regra-observacoes" hidden></p>
|
||||
@ -457,6 +454,15 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="modal-field ips-regra-salvar-field">
|
||||
<label>Salvar como regra de custeio</label>
|
||||
<p class="ips-regra-actions__hint">Depois de parametrizar o custeio acima, salve como uma regra nova (ou atualize a regra aplicada) pra reaproveitar em importações futuras.</p>
|
||||
<button type="button" class="btn-outline" id="ips-regra-salvar-btn">
|
||||
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M19 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h11l5 5v11a2 2 0 0 1-2 2Z" stroke-linejoin="round"/><path d="M17 21v-8H7v8M7 3v5h5" stroke-linejoin="round"/></svg>
|
||||
Salvar regra atual...
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<p class="modal-error" id="ips-form-error"></p>
|
||||
<div class="modal-actions">
|
||||
<button type="button" class="btn-outline" id="ips-form-cancel-btn">Cancelar</button>
|
||||
|
||||
Loading…
Reference in New Issue
Block a user