Propostas (Proposals)
Propostas (Proposals)
O que e uma proposta
Uma proposta (internamente Proposal) e a resposta de um fornecedor a uma cotacao publicada por um produtor. O fornecedor monta sua proposta item a item, podendo ajustar precos, quantidades e oferecer produtos similares quando o produtor permite.
Cada proposta recebe automaticamente um UUID e esta vinculada a uma unica cotacao (order_id) e um unico fornecedor (supplier_id).
Status da proposta
| Status | Label (Fornecedor) | Label (Produtor) | Descricao |
|---|---|---|---|
draft | Rascunho | Rascunho | Proposta em montagem, nao visivel para o produtor |
submitted | Enviada | Recebida | Proposta enviada, visivel para o produtor |
awarded_pending_confirmation | Aguardando sua confirmacao | Vencedora aguardando confirmacao | Produtor selecionou esta proposta como vencedora |
accepted | Vencedora | Aceita | Fornecedor confirmou a proposta vencedora |
declined_after_award | Recusada por voce | Recusada pelo vencedor | Fornecedor recusou a proposta apos ser selecionado |
expired_after_award | Prazo de confirmacao expirado | Confirmacao expirada | Fornecedor nao confirmou dentro do prazo |
rejected | Rejeitada | Rejeitada | Produtor rejeitou a proposta |
cancelled | Cancelada | Cancelada | Fornecedor cancelou a proposta enviada |
lost | Perdida | Perdida | Outra proposta foi aceita nesta cotacao |
expired | Expirada | Expirada | Prazo da cotacao expirou sem acao |
Fluxo de status
Fluxo principal (caminho feliz)
draft --> submitted --> awarded_pending_confirmation --> accepted
- Rascunho (draft): Fornecedor cria a proposta, adicionando precos por item.
- Enviada (submitted): Fornecedor submete a proposta. Produtor e notificado.
- Vencedora pendente (awarded_pending_confirmation): Produtor seleciona esta proposta. Fornecedor tem prazo para confirmar.
- Aceita (accepted): Fornecedor confirma. Cotacao finalizada. Demais propostas recebem status
lost.
Fluxos alternativos
submitted --> rejected (produtor rejeita)
submitted --> cancelled (fornecedor cancela)
submitted --> lost (outra proposta foi aceita)
submitted --> expired (prazo da cotacao expirou)
draft --> expired (prazo da cotacao expirou antes do envio)
awarded_pending_confirmation --> declined_after_award (fornecedor recusa)
awarded_pending_confirmation --> expired_after_award (fornecedor nao respondeu a tempo)
Quando o vencedor recusa ou expira:
- A cotacao volta para
in_analysiscom prazo de analise estendido. - As demais propostas
submittedcontinuam ativas para nova selecao.
Campos da proposta
Campos principais
| Campo | Tipo | Descricao |
|---|---|---|
uuid | string | Identificador unico (gerado automaticamente) |
order_id | integer | Cotacao associada |
supplier_id | integer | Fornecedor que enviou |
total_amount | decimal(2) | Valor total calculado (subtotal - desconto + frete) |
notes | string | Observacoes gerais do fornecedor |
validity_date | date | Data de validade da proposta |
Desconto
O fornecedor pode aplicar desconto de duas formas (mutuamente exclusivas):
| Campo | Tipo | Descricao |
|---|---|---|
discount_percent | decimal(2) | Desconto percentual (0-100%) |
discount_value | decimal(2) | Desconto em valor absoluto (R$) |
Regras:
- Se
discount_valuefor informado e maior que zero, ele tem prioridade. O percentual e calculado automaticamente (discount_value / subtotal * 100). - O valor de desconto nao pode exceder o subtotal da proposta.
Frete
| Campo | Tipo | Descricao |
|---|---|---|
freight_value | decimal(2) | Valor do frete (quando a cotacao e CIF) |
freight_included | boolean | Se o frete esta incluso no preco |
Regras:
- Se a cotacao tem
freight_type = cif(fornecedor entrega), o fornecedor deve informar o valor do frete ou indicar frete gratis. - Se a cotacao tem
freight_type = fob(produtor retira), o frete e zerado automaticamente. - Quando
is_free_shipping = true, ofreight_valuee definido como 0.
Calculo do total
subtotal = soma(item.unit_price * item.quantity) para cada item
desconto = discount_value OU (subtotal * discount_percent / 100)
total_amount = max(subtotal - desconto + freight_value, 0)
Itens da proposta (ProposalItem)
Cada proposta possui itens correspondentes aos itens da cotacao:
| Campo | Tipo | Descricao |
|---|---|---|
order_item_id | integer | Item da cotacao correspondente |
product_id | integer | Produto ofertado |
unit_price | decimal | Preco unitario |
quantity | decimal(2) | Quantidade ofertada |
total_price | decimal | Preco total do item (unit_price * quantity) |
offers_similar | boolean | Se oferece produto similar |
similar_product_name | string | Nome do produto similar |
similar_product_description | string | Descricao do produto similar |
justification | string | Justificativa (quando nao oferta o produto original) |
justification_type | enum | Tipo: unavailable, out_of_stock, logistics, other |
Regras de quantidade:
- A quantidade ofertada nao pode ultrapassar 5x a quantidade solicitada no item da cotacao.
- Se o fornecedor nao informar quantidade, assume a mesma quantidade solicitada pelo produtor.
- Todos os itens precisam ter quantidade valida maior que zero para envio.
Produto similar:
- Somente permitido se o item da cotacao tem
accepts_similar = true. - Quando
offers_similar = false, o sistema forca oproduct_iddo item original da cotacao, ignorando qualquer produto diferente informado.
Confirmacao da proposta vencedora
Quando o produtor seleciona uma proposta como vencedora, o fluxo de confirmacao e acionado via AwardWorkflowService.
Etapas da confirmacao
- Selecao pelo produtor: Somente durante o periodo de analise (
in_analysis). Nao pode haver outro vencedor ativo. - Prazo de confirmacao: Calculado em horas uteis (padrao: 2h uteis) via
BusinessHoursService.- Horas uteis: 8h as 18h (configuravel).
- Dias uteis: segunda a sexta (configuravel).
- Exemplo: se a selecao ocorrer as 17h30 de sexta-feira, o prazo considera as proximas horas uteis (segunda-feira).
- Fornecedor confirma: A proposta vai para
accepted, a cotacao parafinished, e as demais propostassubmittedrecebemlost. - Fornecedor recusa: Deve informar motivo (minimo 10 caracteres). A proposta vai para
declined_after_award. - Prazo expira: A proposta vai para
expired_after_award.
O que acontece quando o fornecedor confirma
- Proposta: status muda para
acceptedcomconfirmed_atpreenchido. - Cotacao: status muda para
finishedcomfinished_atpreenchido. - Demais propostas com status
submittedrecebemlostelost_at. - Notificacoes enviadas para produtor, fornecedor vencedor e demais participantes.
- Dados de contato ficam disponiveis para ambas as partes.
O que acontece quando o fornecedor recusa
- Proposta: status muda para
declined_after_awardcomdeclined_after_award_ateaward_decline_reasonpreenchidos. - Cotacao: volta para
in_analysis. - Prazo de analise: estendido em N horas (padrao: 24h, configuravel via
analysis_extension_hours). - Notificacao enviada ao produtor informando a recusa e o novo prazo.
- Demais fornecedores participantes sao notificados de que a cotacao reabriu para analise.
- O fornecedor que recusou nao pode participar novamente desta cotacao.
O que acontece quando o prazo expira
- Comportamento identico a recusa, exceto que o motivo e automatico (timeout).
- Proposta: status muda para
expired_after_awardcomaward_confirmation_expired_atpreenchido. - Cotacao: volta para
in_analysiscom prazo estendido. - Notificacoes enviadas a todos os envolvidos.
Extensao do prazo de analise
Sempre que um vencedor recusa ou nao confirma:
- A cotacao volta para
in_analysis. - O campo
analysis_deadlinee atualizado paranow() + analysis_extension_hours(padrao: 24h). - O produtor pode selecionar outro fornecedor durante o novo prazo.
- Os demais fornecedores participantes recebem notificacao de "Nova oportunidade".
Este ciclo pode se repetir ate que um fornecedor confirme ou o prazo de analise expire sem selecao.
Cancelamento de proposta pelo fornecedor
O fornecedor pode cancelar uma proposta ja enviada (submitted), sujeito as seguintes regras:
- Limite de cancelamentos: Maximo 1 cancelamento por proposta (
cancellation_count < 1). - Limite total por cotacao: Maximo 2 propostas canceladas por fornecedor na mesma cotacao.
- Deve informar justificativa (minimo 10, maximo 1000 caracteres).
- Apos cancelar, o produtor e notificado.
Cancelar e duplicar
O fornecedor pode usar o recurso de "cancelar e duplicar" para corrigir uma proposta:
- A proposta atual e cancelada.
- Uma nova proposta e criada em
draftcom os mesmos itens e valores. - O fornecedor pode editar e reenviar.
- Se ja existir um rascunho, o sistema pergunta se deseja substituir.
- Esse recurso so pode ser usado 1 vez por cotacao (alem do cancelamento direto).
Favoritos
O produtor pode marcar propostas como favoritas para facilitar a analise:
- Somente propostas com status
submittedpodem ser favoritadas. - Campos:
favorited_atefavorited_by. - Toggle: favoritar/desfavoritar.
Visualizacao
O produtor pode marcar propostas como visualizadas:
- Campo
viewed_ate preenchido na primeira visualizacao. - O sistema rastreia contagem de propostas nao visualizadas (
countUnviewed).
Permissoes por acao
| Acao | Quem pode executar | Restricoes |
|---|---|---|
| Criar proposta (draft) | Fornecedor | Cotacao publicada e dentro do prazo; sem outra proposta ativa |
| Editar proposta | Fornecedor dono | Somente em draft e dentro do prazo da cotacao |
| Enviar proposta (submit) | Fornecedor dono | Somente draft com itens; cotacao deve aceitar propostas; max 2 cancelamentos anteriores |
| Cancelar proposta | Fornecedor dono | Somente submitted; max 1 cancelamento; requer justificativa |
| Cancelar e duplicar | Fornecedor dono | submitted ou cancelled; max 1 uso por cotacao |
| Excluir proposta | Fornecedor dono | Somente draft |
| Selecionar vencedora (accept) | Produtor dono da cotacao | Cotacao em in_analysis; proposta submitted; sem outro vencedor ativo |
| Confirmar proposta | Fornecedor vencedor | Status awarded_pending_confirmation; dentro do prazo |
| Recusar proposta | Fornecedor vencedor | Status awarded_pending_confirmation; requer motivo |
| Rejeitar proposta | Produtor dono da cotacao | Proposta submitted; motivo opcional |
| Favoritar proposta | Produtor dono da cotacao | Proposta submitted |
Notificacoes
| Evento | Destinatario | Tipo |
|---|---|---|
| Proposta enviada | Produtor | PROPOSAL_RECEIVED |
| Proposta cancelada | Produtor | PROPOSAL_CANCELLED |
| Proposta selecionada como vencedora | Fornecedor vencedor + produtor + demais | AWARD_PENDING_CONFIRMATION |
| Fornecedor confirma | Produtor + fornecedor + demais | AWARD_CONFIRMED |
| Fornecedor recusa | Produtor + fornecedor + demais | AWARD_DECLINED |
| Prazo de confirmacao expirou | Produtor + fornecedor + demais | AWARD_CONFIRMATION_EXPIRED |
| Prazo de analise estendido | Demais fornecedores | ANALYSIS_DEADLINE_EXTENDED |
| Proposta aceita (pelo produtor) | Fornecedor vencedor | YOUR_PROPOSAL_ACCEPTED |
| Proposta perdida | Fornecedores nao selecionados | YOUR_PROPOSAL_LOST |
| Proposta rejeitada | Fornecedor | YOUR_PROPOSAL_REJECTED |
Endpoints da API
| Metodo | Rota | Acao |
|---|---|---|
GET | /api/proposals | Listar propostas do fornecedor |
GET | /api/orders/{uuid}/proposals | Propostas do fornecedor para uma cotacao |
GET | /api/orders/{uuid}/proposals/received | Propostas recebidas pelo produtor |
POST | /api/orders/{uuid}/proposals | Criar/atualizar rascunho de proposta |
GET | /api/proposals/{uuid} | Detalhes da proposta |
DELETE | /api/proposals/{uuid} | Excluir rascunho |
POST | /api/proposals/{uuid}/submit | Enviar proposta |
POST | /api/proposals/{uuid}/cancel | Cancelar proposta |
POST | /api/proposals/{uuid}/cancel-duplicate | Cancelar e duplicar |
POST | /api/proposals/{uuid}/accept | Selecionar como vencedora (produtor) |
POST | /api/proposals/{uuid}/confirm-award | Confirmar proposta vencedora (fornecedor) |
POST | /api/proposals/{uuid}/decline-award | Recusar proposta vencedora (fornecedor) |
POST | /api/proposals/{uuid}/reject | Rejeitar proposta (produtor) |
POST | /api/proposals/{uuid}/favorite | Favoritar/desfavoritar (produtor) |
POST | /api/proposals/{uuid}/viewed | Marcar como visualizada (produtor) |
GET | /api/proposals/{uuid}/items | Itens detalhados da proposta |
GET | /api/proposals/unviewed/count | Contagem de propostas nao visualizadas |
GET | /api/proposals/unviewed | Listar propostas nao visualizadas |