Negócio

Cotacoes (Orders)

Documentacao completa do modulo de cotacoes/licitacoes da plataforma AgrSis.

Cotacoes (Orders)

O que e uma cotacao no AgrSis

Uma cotacao (internamente chamada de Order) e o mecanismo central da plataforma AgrSis. Ela representa uma solicitacao de compra de insumos agricolas criada por um produtor rural, que e publicada para que fornecedores dentro de um raio geografico possam enviar propostas competitivas.

Cada cotacao recebe automaticamente um numero sequencial unico (gerado por OrderNumberGenerator) e um UUID utilizado para identificacao publica nas URLs e na API.


Status da cotacao

A cotacao possui os seguintes status, definidos no enum OrderStatus:

StatusLabel (PT)Descricao
draftRascunhoCotacao em criacao, dados incompletos
pendingPendenteDados completos, pronta para publicacao
publishedPublicadaAtiva e recebendo propostas de fornecedores
in_analysisEm AnalisePrazo de propostas encerrado, produtor analisa as propostas recebidas
awardedAguardando ConfirmacaoProposta vencedora selecionada, aguardando confirmacao do fornecedor
finishedFinalizadaFornecedor confirmou, cotacao encerrada com sucesso
cancelledCanceladaCancelada pelo produtor (pode ser reaberta)
revokedRevogadaRevogada definitivamente (estado final)
expiredExpiradaPrazo de analise expirou sem selecao de vencedor (estado final)
completedFinalizadaDeprecado, mantido para compatibilidade

Fluxo de status (transicoes permitidas)

DRAFT --> PENDING
PENDING --> DRAFT | PUBLISHED
PUBLISHED --> CANCELLED | REVOKED | IN_ANALYSIS
CANCELLED --> PENDING | PUBLISHED
IN_ANALYSIS --> AWARDED | EXPIRED
AWARDED --> IN_ANALYSIS | FINISHED

Detalhamento do fluxo

  1. Criacao (DRAFT): O produtor inicia a cotacao pelo wizard. Os dados podem ser salvos parcialmente.
  2. Revisao (PENDING): Quando todos os campos obrigatorios estao preenchidos, o status muda para PENDING. O produtor pode voltar para DRAFT se precisar editar.
  3. Publicacao (PUBLISHED): O produtor publica a cotacao. Fornecedores dentro do raio sao notificados e podem enviar propostas.
  4. Analise (IN_ANALYSIS): Apos o prazo de propostas (deadline_date) expirar, a cotacao entra em periodo de analise. O prazo de analise e configuravel (padrao: 48h apos o deadline).
  5. Selecao do vencedor (AWARDED): O produtor seleciona uma proposta vencedora. O fornecedor tem um prazo em horas uteis (padrao: 2h uteis) para confirmar.
  6. Finalizacao (FINISHED): O fornecedor confirma a proposta. A cotacao e encerrada e as demais propostas recebem status lost.
  7. Retorno a analise (IN_ANALYSIS): Se o fornecedor recusar ou nao confirmar a tempo, a cotacao volta para IN_ANALYSIS com prazo estendido (padrao: +24h) para que o produtor selecione outro fornecedor.

Estados finais (sem retorno)

  • REVOKED: Revogada definitivamente pelo produtor.
  • EXPIRED: O prazo de analise expirou sem selecao de vencedor.
  • FINISHED: Concluida com sucesso.

Campos da cotacao

Campos obrigatorios para publicacao

CampoTipoDescricao
descriptionstringDescricao/titulo da cotacao
customer_address_idintegerEndereco de entrega (com coordenadas para calculo de raio)
deadline_datedatetimeData limite para recebimento de propostas (deve ser futura)
supply_radiusintegerRaio de fornecimento em km
freight_typestringModalidade de frete: cif (fornecedor entrega) ou fob (produtor retira)
itemsarrayPelo menos 1 item (produto + quantidade + unidade de medida)

Campos opcionais

CampoTipoDescricao
bidding_typestringTipo de licitacao: open ou closed (padrao: closed)
product_type_idsarrayIDs dos tipos de produto (filtro)
deadline_modestringModo do prazo: general ou specific
delivery_deadlinestringPrazo de entrega em dias
delivery_datedateData especifica de entrega
wants_scaled_deliverybooleanSe deseja entrega escalonada
payment_termsstringCondicao de pagamento (ex: avista, 30dias)
estimated_payment_datedateData estimada de pagamento (obrigatoria se payment_terms != avista)

Campos automaticos

CampoDescricao
uuidGerado automaticamente na criacao
numberNumero sequencial gerado por OrderNumberGenerator
analysis_deadlineCalculado a partir de deadline_date + horas de analise, ou definido manualmente quando a cotacao e reaberta
published_atPreenchido ao publicar
awarded_atPreenchido ao selecionar vencedor
finished_atPreenchido ao finalizar
cancelled_atPreenchido ao cancelar
revoked_atPreenchido ao revogar

Prazos

Prazo de propostas (deadline_date)

  • Definido pelo produtor ao criar a cotacao.
  • Enquanto o prazo esta vigente e o status e published, fornecedores podem enviar propostas.
  • Deve ser uma data futura no momento da publicacao.

Prazo de analise (analysis_deadline)

  • Calculado automaticamente: deadline_date + N horas (configuravel via analysis_deadline_hours, padrao: 48h).
  • Pode ser persistido manualmente no campo analysis_deadline quando a cotacao e reaberta apos recusa ou expiracao do vencedor.
  • Durante esse periodo, o produtor analisa e seleciona a proposta vencedora.
  • Se o prazo expirar sem selecao, a cotacao vai para status expired.

Prazo de confirmacao do vencedor

  • Calculado em horas uteis (padrao: 2h uteis) via BusinessHoursService.
  • Horas uteis consideram horario comercial (padrao: 8h-18h) e dias uteis (segunda a sexta).
  • Se o fornecedor nao confirmar dentro do prazo, a proposta expira e a cotacao volta para in_analysis com prazo estendido.

Extensao do prazo de analise

  • Quando o fornecedor vencedor recusa ou nao confirma, o prazo de analise e estendido em N horas (configuravel via analysis_extension_hours, padrao: 24h).
  • Isso permite ao produtor selecionar outro fornecedor.

Raio de fornecimento

O campo supply_radius define o raio em km a partir do endereco de entrega da cotacao. Apenas fornecedores que possuam endereco ativo com coordenadas dentro desse raio serao notificados sobre a nova cotacao.

O calculo e feito via formula de Haversine no banco de dados (PostgreSQL), comparando as coordenadas (latitude, longitude) do endereco de entrega com as coordenadas dos enderecos dos fornecedores.

Limites configurados via SettingsService:

  • Minimo: 10 km (search_radius_min_km)
  • Maximo: 500 km (search_radius_max_km)

Notificacoes automaticas

O sistema dispara notificacoes em cada etapa relevante do ciclo de vida da cotacao. As notificacoes sao enviadas por ate 3 canais: in-app, email e WhatsApp, conforme configuracao global (NotificationChannelConfig) e preferencias do usuario (NotificationSetting).

Eventos que geram notificacao

EventoDestinatariosTipo
Cotacao publicadaFornecedores dentro do raioNEW_ORDER_AVAILABLE
Proposta recebidaProdutor dono da cotacaoPROPOSAL_RECEIVED
Proposta cancelada pelo fornecedorProdutor dono da cotacaoPROPOSAL_CANCELLED
Proposta vencedora selecionadaFornecedor vencedor + produtor + demais participantesAWARD_PENDING_CONFIRMATION
Fornecedor confirma propostaProdutor + fornecedor vencedor + demais participantesAWARD_CONFIRMED
Fornecedor recusa propostaProdutor + fornecedor + demais participantesAWARD_DECLINED
Prazo de confirmacao expirouProdutor + fornecedor + demais participantesAWARD_CONFIRMATION_EXPIRED
Prazo de analise estendidoDemais fornecedores participantesANALYSIS_DEADLINE_EXTENDED
Cotacao cancelada/revogadaFornecedores que enviaram propostasORDER_UPDATED

Permissoes por acao

AcaoQuem pode executarRestricoes
Criar cotacaoProdutor com assinatura ativa-
Editar cotacaoProdutor donoSomente em status draft, pending ou cancelled
Publicar cotacaoProdutor donoStatus pending ou cancelled; campos obrigatorios preenchidos; deadline futuro
Publicar direto do draftProdutor donoValida campos obrigatorios, promove DRAFT->PENDING->PUBLISHED
Cancelar cotacaoProdutor donoSomente em status published; requer motivo (CancellationReason)
Revogar cotacaoProdutor donoSomente em status published; requer motivo; estado final
Excluir cotacao (soft delete)Produtor donoSomente em status draft ou pending
Duplicar cotacaoProdutor donoCria nova cotacao em draft com os mesmos itens
Reabrir cotacaoProdutor donoSomente published sem propostas recebidas; volta para draft
Selecionar vencedorProdutor donoSomente em in_analysis (dentro do prazo de analise)

Motivos de cancelamento/revogacao (CancellationReason)

ValorLabel
erro_especificacaoErro na especificacao do produto
mudanca_necessidadeMudanca de necessidade
orcamento_insuficienteOrcamento insuficiente
decisao_superiorDecisao superior
propostas_inadequadasTodas propostas inadequadas
problema_prazoProblema com prazo de entrega
problema_fornecedorProblema com fornecedores
outroOutro motivo

Itens da cotacao (OrderItem)

Cada cotacao deve conter pelo menos 1 item. Cada item possui:

CampoDescricao
product_idProduto solicitado (do catalogo)
quantityQuantidade desejada
measurement_unit_idUnidade de medida
accepts_similarSe aceita produto similar (boolean)

O sistema valida limites de quantidade por unidade de medida (ex: maximo 100.000 toneladas, 10.000.000 kg, etc.) para evitar erros de digitacao.


Endpoints da API

MetodoRotaAcao
GET/api/ordersListar cotacoes do produtor
POST/api/ordersCriar cotacao (publicada diretamente)
POST/api/orders/draftSalvar rascunho
GET/api/orders/{uuid}Detalhes da cotacao
PUT/api/orders/{uuid}Atualizar cotacao
DELETE/api/orders/{uuid}Excluir cotacao (soft delete)
POST/api/orders/{uuid}/publishPublicar cotacao
POST/api/orders/{uuid}/cancelCancelar cotacao
POST/api/orders/{uuid}/revokeRevogar cotacao
POST/api/orders/{uuid}/reopenReabrir para edicao
POST/api/orders/{uuid}/duplicateDuplicar cotacao
GET/api/orders/{uuid}/itemsListar itens
GET/api/orders/{uuid}/historyHistorico/timeline
PATCH/api/orders/{uuid}/statusAtualizar status
Copyright © 2026