diff --git a/apps/web/src/routes/(dashboard)/pedidos/[id]/+page.svelte b/apps/web/src/routes/(dashboard)/pedidos/[id]/+page.svelte index 8b17615..325f843 100644 --- a/apps/web/src/routes/(dashboard)/pedidos/[id]/+page.svelte +++ b/apps/web/src/routes/(dashboard)/pedidos/[id]/+page.svelte @@ -385,6 +385,11 @@ let seiValue = $state(''); let updatingSei = $state(false); + // Edit DFD State + let editingDfd = $state(false); + let dfdValue = $state(''); + let updatingDfd = $state(false); + // Item Details Modal State let showDetailsModal = $state(false); let selectedObjeto = $state | null>(null); @@ -820,6 +825,36 @@ seiValue = ''; } + async function handleUpdateDfd() { + if (!dfdValue.trim()) { + toast.error('O número DFD não pode estar vazio.'); + return; + } + updatingDfd = true; + try { + await client.mutation(api.pedidos.updateDfdNumber, { + pedidoId, + numeroDfd: dfdValue + }); + editingDfd = false; + toast.success('Número DFD atualizado com sucesso!'); + } catch (e) { + toast.error('Erro ao atualizar número DFD: ' + (e as Error).message); + } finally { + updatingDfd = false; + } + } + + function startEditingDfd() { + dfdValue = pedido?.numeroDfd || ''; + editingDfd = true; + } + + function cancelEditingDfd() { + editingDfd = false; + dfdValue = ''; + } + function getStatusColor(status: string) { switch (status) { case 'em_rascunho': @@ -853,6 +888,8 @@ return '🔄'; case 'atualizacao_sei': return '📋'; + case 'atualizacao_dfd': + return '📋'; case 'edicao_item': return '✏️'; case 'solicitacao_ajuste': @@ -898,7 +935,9 @@ case 'alteracao_status': return `${entry.usuarioNome} alterou o status para "${formatStatus(detalhes.novoStatus)}"`; case 'atualizacao_sei': - return `${entry.usuarioNome} atualizou o número SEI para "${detalhes.numeroSei}"`; + return `${entry.usuarioNome} atualizou o número SEI para "${detalhes.para}"`; + case 'atualizacao_dfd': + return `${entry.usuarioNome} atualizou o número DFD para "${detalhes.para}"`; case 'edicao_item': { const objeto = objetos.find((o) => o._id === detalhes.objetoId); const nomeObjeto = objeto?.nome || 'Objeto desconhecido'; @@ -1111,53 +1150,102 @@

- {#if editingSei} -
- - - -
- {:else} -
- Pedido {pedido.numeroSei || 'sem número SEI'} - {#if pedido.status === 'em_rascunho' || pedido.status === 'precisa_ajustes'} +
+ {#if editingSei} +
+ - {/if} -
- {/if} + +
+ {:else} +
+ SEI: {pedido.numeroSei || 'sem número SEI'} + {#if pedido.status === 'em_rascunho' || pedido.status === 'precisa_ajustes'} + + {/if} +
+ {/if} + {#if editingDfd} +
+ + + +
+ {:else} +
+ DFD: {pedido.numeroDfd || 'sem número DFD'} + {#if pedido.status === 'em_rascunho' || pedido.status === 'precisa_ajustes'} + + {/if} +
+ {/if} +
{formatStatus(pedido.status)}

{#if !pedido.numeroSei}

- ⚠️ Este pedido não possui número SEI. Adicione um número SEI quando disponível. + ⚠️ Este pedido não possui número SEI. Um número SEI deve ser informado antes de enviar + para aceite. +

+ {/if} + {#if !pedido.numeroDfd} +

+ ⚠️ Este pedido não possui número DFD. Um número DFD deve ser informado antes de enviar + para aceite.

{/if} {#if pedido.status === 'precisa_ajustes' && pedido.descricaoAjuste} @@ -1174,7 +1262,11 @@ {#if permissions?.canSendToAcceptance} diff --git a/packages/backend/convex/pedidos.ts b/packages/backend/convex/pedidos.ts index d678e3d..ce930b9 100644 --- a/packages/backend/convex/pedidos.ts +++ b/packages/backend/convex/pedidos.ts @@ -409,6 +409,7 @@ export const list = query({ _id: v.id('pedidos'), _creationTime: v.number(), numeroSei: v.optional(v.string()), + numeroDfd: v.optional(v.string()), status: pedidoStatusValidator, // acaoId removed from return criadoPor: v.id('usuarios'), @@ -433,6 +434,7 @@ export const list = query({ _id: p._id, _creationTime: p._creationTime, numeroSei: p.numeroSei, + numeroDfd: p.numeroDfd, status: p.status, criadoPor: p.criadoPor, criadoPorNome: creator?.nome || 'Desconhecido', @@ -455,6 +457,7 @@ export const get = query({ _id: v.id('pedidos'), _creationTime: v.number(), numeroSei: v.optional(v.string()), + numeroDfd: v.optional(v.string()), status: pedidoStatusValidator, acaoId: v.optional(v.id('acoes')), criadoPor: v.id('usuarios'), @@ -568,6 +571,7 @@ export const checkExisting = query({ _id: v.id('pedidos'), _creationTime: v.number(), numeroSei: v.optional(v.string()), + numeroDfd: v.optional(v.string()), status: v.union( v.literal('em_rascunho'), v.literal('aguardando_aceite'), @@ -662,6 +666,7 @@ export const checkExisting = query({ _id: pedido._id, _creationTime: pedido._creationTime, numeroSei: pedido.numeroSei, + numeroDfd: pedido.numeroDfd, status: pedido.status, criadoPor: pedido.criadoPor, aceitoPor: pedido.aceitoPor, @@ -684,6 +689,7 @@ export const listForAcceptance = query({ _id: v.id('pedidos'), _creationTime: v.number(), numeroSei: v.optional(v.string()), + numeroDfd: v.optional(v.string()), status: v.string(), criadoPor: v.id('usuarios'), criadoPorNome: v.string(), @@ -722,6 +728,7 @@ export const listForAcceptance = query({ _id: o._id, _creationTime: o._creationTime, numeroSei: o.numeroSei, + numeroDfd: o.numeroDfd, status: o.status, criadoPor: o.criadoPor, criadoPorNome: creator?.nome || 'Desconhecido', @@ -742,6 +749,7 @@ export const listMyAnalysis = query({ _id: v.id('pedidos'), _creationTime: v.number(), numeroSei: v.optional(v.string()), + numeroDfd: v.optional(v.string()), status: v.string(), criadoPor: v.id('usuarios'), criadoPorNome: v.string(), @@ -789,6 +797,7 @@ export const listMyAnalysis = query({ _id: o._id, _creationTime: o._creationTime, numeroSei: o.numeroSei, + numeroDfd: o.numeroDfd, status: o.status, criadoPor: o.criadoPor, criadoPorNome: creator?.nome || 'Desconhecido', @@ -816,6 +825,7 @@ export const listByItemCreator = query({ _id: v.id('pedidos'), _creationTime: v.number(), numeroSei: v.optional(v.string()), + numeroDfd: v.optional(v.string()), status: pedidoStatusValidator, aceitoPor: v.optional(v.id('funcionarios')), criadoPor: v.id('usuarios'), @@ -855,6 +865,7 @@ export const listByItemCreator = query({ _id: o._id, _creationTime: o._creationTime, numeroSei: o.numeroSei, + numeroDfd: o.numeroDfd, status: o.status, criadoPor: o.criadoPor, criadoPorNome: creator?.nome || 'Desconhecido', @@ -901,6 +912,7 @@ export const gerarRelatorio = query({ _id: v.id('pedidos'), _creationTime: v.number(), numeroSei: v.optional(v.string()), + numeroDfd: v.optional(v.string()), status: pedidoStatusValidator, criadoPor: v.id('usuarios'), criadoPorNome: v.string(), @@ -1111,6 +1123,7 @@ export const gerarRelatorio = query({ _id: p._id, _creationTime: p._creationTime, numeroSei: p.numeroSei, + numeroDfd: p.numeroDfd, status: p.status, criadoPor: p.criadoPor, criadoPorNome: creator?.nome || 'Desconhecido', @@ -1228,7 +1241,8 @@ export const acceptOrder = mutation({ export const create = mutation({ args: { - numeroSei: v.optional(v.string()) + numeroSei: v.optional(v.string()), + numeroDfd: v.optional(v.string()) // acaoId removed }, returns: v.id('pedidos'), @@ -1246,6 +1260,7 @@ export const create = mutation({ // 3. Create Order const pedidoId = await ctx.db.insert('pedidos', { numeroSei: args.numeroSei, + numeroDfd: args.numeroDfd, status: 'em_rascunho', criadoPor: user._id, criadoEm: Date.now(), @@ -1305,6 +1320,41 @@ export const updateSeiNumber = mutation({ } }); +export const updateDfdNumber = mutation({ + args: { + pedidoId: v.id('pedidos'), + numeroDfd: v.string() + }, + returns: v.null(), + handler: async (ctx, args) => { + const user = await getUsuarioAutenticado(ctx); + const pedido = await ctx.db.get(args.pedidoId); + if (!pedido) throw new Error('Pedido não encontrado.'); + + // Verificar se o pedido está em um status que permite edição + if (pedido.status !== 'em_rascunho' && pedido.status !== 'precisa_ajustes') { + throw new Error( + 'Apenas pedidos em rascunho ou que precisam de ajustes podem ter o número DFD atualizado.' + ); + } + + const oldDfd = pedido.numeroDfd; + + await ctx.db.patch(args.pedidoId, { + numeroDfd: args.numeroDfd, + atualizadoEm: Date.now() + }); + + await ctx.db.insert('historicoPedidos', { + pedidoId: args.pedidoId, + usuarioId: user._id, + acao: 'atualizacao_dfd', + detalhes: JSON.stringify({ de: oldDfd, para: args.numeroDfd }), + data: Date.now() + }); + } +}); + export const addItem = mutation({ args: { pedidoId: v.id('pedidos'), @@ -1635,7 +1685,8 @@ export const splitPedido = mutation({ args: { pedidoId: v.id('pedidos'), itemIds: v.array(v.id('objetoItems')), - numeroSei: v.optional(v.string()) + numeroSei: v.optional(v.string()), + numeroDfd: v.optional(v.string()) }, returns: v.id('pedidos'), handler: async (ctx, args) => { @@ -1679,6 +1730,7 @@ export const splitPedido = mutation({ const novoPedidoId = await ctx.db.insert('pedidos', { numeroSei: args.numeroSei, + numeroDfd: args.numeroDfd, status: 'em_rascunho', criadoPor: user._id, criadoEm: Date.now(), @@ -1936,6 +1988,14 @@ export const enviarParaAceite = mutation({ ); } + // Validar que numeroSei e numeroDfd estão preenchidos + if (!pedido.numeroSei || !pedido.numeroSei.trim()) { + throw new Error('O número SEI deve ser informado antes de enviar o pedido para aceite.'); + } + if (!pedido.numeroDfd || !pedido.numeroDfd.trim()) { + throw new Error('O número DFD deve ser informado antes de enviar o pedido para aceite.'); + } + const oldStatus = pedido.status; const newStatus = 'aguardando_aceite'; diff --git a/packages/backend/convex/tables/pedidos.ts b/packages/backend/convex/tables/pedidos.ts index 69e9d78..c3f6685 100644 --- a/packages/backend/convex/tables/pedidos.ts +++ b/packages/backend/convex/tables/pedidos.ts @@ -4,6 +4,7 @@ import { v } from 'convex/values'; export const pedidosTables = { pedidos: defineTable({ numeroSei: v.optional(v.string()), + numeroDfd: v.optional(v.string()), status: v.union( v.literal('em_rascunho'), v.literal('aguardando_aceite'), @@ -21,6 +22,7 @@ export const pedidosTables = { atualizadoEm: v.number() }) .index('by_numeroSei', ['numeroSei']) + .index('by_numeroDfd', ['numeroDfd']) .index('by_status', ['status']) .index('by_criadoPor', ['criadoPor']) .index('by_aceitoPor', ['aceitoPor'])