feat: enhance ata management by adding dataProrrogacao field and updating related logic for effective date handling, improving data integrity and user experience in pedidos
This commit is contained in:
@@ -24,6 +24,7 @@
|
||||
import { resolve } from '$app/paths';
|
||||
import { page } from '$app/state';
|
||||
import { maskCurrencyBRL } from '$lib/utils/masks';
|
||||
import { formatarDataBR } from '$lib/utils/datas';
|
||||
|
||||
const pedidoId = $derived(page.params.id as Id<'pedidos'>);
|
||||
const client = useConvexClient();
|
||||
@@ -84,7 +85,7 @@
|
||||
|
||||
// Atas por objeto (carregadas sob demanda)
|
||||
type AtasComLimite = FunctionReturnType<typeof api.objetos.getAtasComLimite>;
|
||||
let atasPorObjeto = $state<Record<string, AtasComLimite>>({});
|
||||
let atasPorObjetoExtra = $state<Record<string, AtasComLimite>>({});
|
||||
|
||||
let editingItems = $state<Record<string, EditingItem>>({});
|
||||
|
||||
@@ -110,14 +111,39 @@
|
||||
let selectedCount = $derived(selectedItemIds.size);
|
||||
let hasSelection = $derived(selectedCount > 0);
|
||||
|
||||
// Garante que, para todos os itens existentes, as atas do respectivo objeto
|
||||
// sejam carregadas independentemente do formulário de criação.
|
||||
$effect(() => {
|
||||
for (const item of items as unknown as PedidoItemForEdit[]) {
|
||||
if (!atasPorObjeto[item.objetoId]) {
|
||||
void loadAtasForObjeto(item.objetoId);
|
||||
// Pela regra do backend, um pedido só pode ter uma ata (quando houver).
|
||||
// Usamos isso para “forçar incluir” a ata atual do pedido na listagem do objeto,
|
||||
// mesmo que esteja fora da janela (ex.: vencida há mais de 3 meses).
|
||||
let pedidoAtaId = $derived.by(() => {
|
||||
const withAta = (items as unknown as PedidoItemForEdit[]).find((i) => i.ataId);
|
||||
return (withAta?.ataId ?? null) as Id<'atas'> | null;
|
||||
});
|
||||
|
||||
// Carrega atas (para itens existentes) via query batch, evitando efeitos que mutam estado.
|
||||
const atasBatchQuery = $derived.by(() =>
|
||||
useQuery(api.objetos.getAtasComLimiteBatch, () => {
|
||||
const ids: Id<'objetos'>[] = [];
|
||||
const seen: Record<string, true> = {};
|
||||
for (const item of items as unknown as PedidoItemForEdit[]) {
|
||||
const key = String(item.objetoId);
|
||||
if (seen[key]) continue;
|
||||
seen[key] = true;
|
||||
ids.push(item.objetoId);
|
||||
}
|
||||
return {
|
||||
objetoIds: ids,
|
||||
includeAtaIds: pedidoAtaId ? [pedidoAtaId] : undefined
|
||||
};
|
||||
})
|
||||
);
|
||||
|
||||
let atasPorObjetoFromBatch = $derived.by(() => {
|
||||
const map: Record<string, AtasComLimite> = {};
|
||||
const data = atasBatchQuery.data || [];
|
||||
for (const row of data) {
|
||||
map[String(row.objetoId)] = row.atas;
|
||||
}
|
||||
return map;
|
||||
});
|
||||
|
||||
// Group items by user
|
||||
@@ -663,19 +689,20 @@
|
||||
}
|
||||
|
||||
async function loadAtasForObjeto(objetoId: string) {
|
||||
if (atasPorObjeto[objetoId]) return;
|
||||
if (atasPorObjetoExtra[objetoId]) return;
|
||||
try {
|
||||
const linkedAtas = await client.query(api.objetos.getAtasComLimite, {
|
||||
objetoId: objetoId as Id<'objetos'>
|
||||
objetoId: objetoId as Id<'objetos'>,
|
||||
includeAtaIds: pedidoAtaId ? [pedidoAtaId] : undefined
|
||||
});
|
||||
atasPorObjeto[objetoId] = linkedAtas;
|
||||
atasPorObjetoExtra[objetoId] = linkedAtas;
|
||||
} catch (e) {
|
||||
console.error('Erro ao carregar atas para objeto', objetoId, e);
|
||||
}
|
||||
}
|
||||
|
||||
function getAtasForObjeto(objetoId: string): AtasComLimite {
|
||||
return atasPorObjeto[objetoId] || [];
|
||||
return atasPorObjetoExtra[objetoId] || atasPorObjetoFromBatch[objetoId] || [];
|
||||
}
|
||||
|
||||
function handleObjetoChange(id: string) {
|
||||
@@ -1664,11 +1691,18 @@
|
||||
<option value="">Nenhuma</option>
|
||||
{#each getAtasForObjeto(newItem.objetoId) as ata (ata._id)}
|
||||
{@const isSelectedAta = String(ata._id) === newItem.ataId}
|
||||
{@const reason = !ata.quantidadeTotal
|
||||
? 'não configurada'
|
||||
: ata.quantidadeUsada >= ata.limitePermitido
|
||||
? 'limite atingido'
|
||||
: null}
|
||||
{@const reason =
|
||||
ata.lockReason === 'nao_configurada'
|
||||
? 'não configurada'
|
||||
: ata.lockReason === 'limite_atingido'
|
||||
? 'limite atingido'
|
||||
: ata.lockReason === 'vigencia_expirada'
|
||||
? `vigência encerrada em ${
|
||||
ata.dataFimEfetiva || ata.dataFim
|
||||
? formatarDataBR((ata.dataFimEfetiva || ata.dataFim) as string)
|
||||
: '-'
|
||||
}`
|
||||
: null}
|
||||
<option value={ata._id} disabled={ata.isLocked && !isSelectedAta}>
|
||||
Ata {ata.numero} (SEI: {ata.numeroSei}){reason ? ` (${reason})` : ''}
|
||||
</option>
|
||||
@@ -1920,11 +1954,20 @@
|
||||
{#each getAtasForObjeto(item.objetoId) as ata (ata._id)}
|
||||
{@const currentAtaId = ensureEditingItem(item).ataId}
|
||||
{@const isSelectedAta = String(ata._id) === currentAtaId}
|
||||
{@const reason = !ata.quantidadeTotal
|
||||
? 'não configurada'
|
||||
: ata.quantidadeUsada >= ata.limitePermitido
|
||||
? 'limite atingido'
|
||||
: null}
|
||||
{@const reason =
|
||||
ata.lockReason === 'nao_configurada'
|
||||
? 'não configurada'
|
||||
: ata.lockReason === 'limite_atingido'
|
||||
? 'limite atingido'
|
||||
: ata.lockReason === 'vigencia_expirada'
|
||||
? `vigência encerrada em ${
|
||||
ata.dataFimEfetiva || ata.dataFim
|
||||
? formatarDataBR(
|
||||
(ata.dataFimEfetiva || ata.dataFim) as string
|
||||
)
|
||||
: '-'
|
||||
}`
|
||||
: null}
|
||||
<option value={ata._id} disabled={ata.isLocked && !isSelectedAta}>
|
||||
Ata {ata.numero} (SEI: {ata.numeroSei}){reason ? ` (${reason})` : ''}
|
||||
</option>
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
import { Plus, Trash2, X, Info } from 'lucide-svelte';
|
||||
import { goto } from '$app/navigation';
|
||||
import { resolve } from '$app/paths';
|
||||
import { formatarDataBR } from '$lib/utils/datas';
|
||||
|
||||
const client = useConvexClient();
|
||||
|
||||
@@ -635,11 +636,18 @@
|
||||
>
|
||||
<option value="">Nenhuma</option>
|
||||
{#each availableAtas as ata (ata._id)}
|
||||
{@const reason = !ata.quantidadeTotal
|
||||
? 'não configurada'
|
||||
: ata.quantidadeUsada >= ata.limitePermitido
|
||||
? 'limite atingido'
|
||||
: null}
|
||||
{@const reason =
|
||||
ata.lockReason === 'nao_configurada'
|
||||
? 'não configurada'
|
||||
: ata.lockReason === 'limite_atingido'
|
||||
? 'limite atingido'
|
||||
: ata.lockReason === 'vigencia_expirada'
|
||||
? `vigência encerrada em ${
|
||||
ata.dataFimEfetiva || ata.dataFim
|
||||
? formatarDataBR((ata.dataFimEfetiva || ata.dataFim) as string)
|
||||
: '-'
|
||||
}`
|
||||
: null}
|
||||
<option value={ata._id} disabled={ata.isLocked}>
|
||||
Ata {ata.numero} (SEI: {ata.numeroSei}){reason ? ` (${reason})` : ''}
|
||||
</option>
|
||||
@@ -735,7 +743,12 @@
|
||||
{#if detailsItem.ata.dataInicio}
|
||||
<p class="text-green-800">
|
||||
<strong>Vigência:</strong>
|
||||
{detailsItem.ata.dataInicio} até {detailsItem.ata.dataFim || 'Indefinido'}
|
||||
{formatarDataBR(detailsItem.ata.dataInicio)} até {detailsItem.ata
|
||||
.dataFimEfetiva || detailsItem.ata.dataFim
|
||||
? formatarDataBR(
|
||||
(detailsItem.ata.dataFimEfetiva || detailsItem.ata.dataFim) as string
|
||||
)
|
||||
: 'Indefinido'}
|
||||
</p>
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user