š” API PROPOSALS - DOCUMENTAĆĆO COMPLETA
š” API PROPOSALS - DOCUMENTAĆĆO COMPLETA
Base URL
http://localhost:8000/api/v1
Autenticação
Todos os endpoints requerem autenticação via Laravel Sanctum:
Authorization: Bearer {token}
š Endpoints
1. Listar Propostas do Fornecedor para uma Licitação
GET /orders/{order}/proposals
Lista todas as propostas que o fornecedor autenticado criou para uma licitação especĆfica.
Parâmetros:
{order}(path) - UUID ou ID da licitação
Resposta 200:
[
{
"id": 1,
"uuid": "550e8400-e29b-41d4-a716-446655440000",
"order_id": 1,
"supplier_id": 1,
"total_amount": 1500.00,
"notes": "Proposta com desconto especial",
"validity_date": "2026-02-01",
"status": "draft",
"submitted_at": null,
"accepted_at": null,
"rejected_at": null,
"cancelled_at": null,
"rejection_reason": null,
"created_at": "2026-01-11 10:00:00",
"updated_at": "2026-01-11 10:05:00",
"can_edit": true,
"can_submit": true,
"can_cancel": false,
"is_draft": true,
"is_submitted": false,
"is_accepted": false,
"is_rejected": false,
"items": [
{
"id": 1,
"proposal_id": 1,
"order_item_id": 1,
"product_id": 1,
"unit_price": 10.50,
"quantity": 100,
"total_price": 1050.00,
"offers_similar": false,
"similar_product_name": null,
"similar_product_description": null,
"justification": null,
"justification_type": null,
"justification_label": null,
"notes": null,
"has_price": true,
"has_justification": false,
"is_valid": true,
"created_at": "2026-01-11 10:00:00",
"updated_at": "2026-01-11 10:00:00",
"order_item": { ... },
"product": { ... }
}
]
}
]
2. Criar ou Atualizar Proposta Draft
POST /orders/{order}/proposals
Cria uma nova proposta draft ou atualiza uma existente para o fornecedor autenticado.
Parâmetros:
{order}(path) - UUID ou ID da licitação
Body:
{
"order_id": 1,
"items": [
{
"order_item_id": 1,
"product_id": 1,
"unit_price": 10.50,
"quantity": 100,
"offers_similar": false,
"similar_product_name": null,
"similar_product_description": null,
"justification": null,
"justification_type": null,
"notes": null
}
],
"notes": "ObservaƧƵes gerais da proposta",
"validity_date": "2026-02-01"
}
ValidaƧƵes:
items(required, array) - Array de itemsitems.*.order_item_id(required, exists:order_items,id)items.*.product_id(required, exists:products,id)items.*.unit_price(nullable, numeric, min:0)items.*.quantity(required, numeric, min:0)items.*.offers_similar(boolean)items.*.similar_product_name(nullable, string)items.*.similar_product_description(nullable, string)items.*.justification(nullable, string)items.*.justification_type(nullable, in:unavailable,out_of_stock,logistics,other)notes(nullable, string)validity_date(nullable, date)
Resposta 200:
{
"id": 1,
"uuid": "550e8400-e29b-41d4-a716-446655440000",
...
}
Comportamento:
- Se jÔ existe proposta draft do fornecedor para essa licitação, atualiza
- Se não existe, cria nova
- Limpa items existentes e recria com os novos dados
- Calcula automaticamente total_price de cada item
- Calcula automaticamente total_amount da proposta
3. Visualizar Proposta EspecĆfica
GET /proposals/{proposal}
Visualiza detalhes de uma proposta especĆfica.
Parâmetros:
{proposal}(path) - UUID da proposta
Resposta 200:
{
"id": 1,
"uuid": "550e8400-e29b-41d4-a716-446655440000",
"order_id": 1,
"supplier_id": 1,
"total_amount": 1500.00,
...
"items": [ ... ],
"order": { ... },
"supplier": { ... }
}
4. Submeter Proposta
POST /proposals/{proposal}/submit
Submete uma proposta draft, mudando seu status para "submitted".
Parâmetros:
{proposal}(path) - UUID da proposta
ValidaƧƵes:
- Proposta deve estar em status "draft"
- Deve ter pelo menos 1 item
- Todos os items devem ser vƔlidos (ter preƧo OU justificativa)
Resposta 200:
{
"id": 1,
"uuid": "550e8400-e29b-41d4-a716-446655440000",
"status": "submitted",
"submitted_at": "2026-01-11 10:30:00",
"can_edit": false,
"can_submit": false,
...
}
Erro 422:
{
"error": "Proposta não pode ser enviada"
}
5. Deletar Proposta Draft
DELETE /proposals/{proposal}
Deleta uma proposta draft.
Parâmetros:
{proposal}(path) - UUID da proposta
ValidaƧƵes:
- Apenas propostas em status "draft" podem ser deletadas
Resposta 200:
{
"message": "Proposta excluĆda com sucesso"
}
Erro 422:
{
"error": "Apenas rascunhos podem ser excluĆdos"
}
6. Listar Propostas Recebidas (Produtor)
GET /orders/{order}/proposals/received
Lista todas as propostas recebidas (nĆ£o-draft) para uma licitação especĆfica.
Parâmetros:
{order}(path) - UUID ou ID da licitação
Resposta 200:
[
{
"id": 1,
"uuid": "550e8400-e29b-41d4-a716-446655440000",
"order_id": 1,
"supplier_id": 1,
"total_amount": 1500.00,
"status": "submitted",
"submitted_at": "2026-01-11 10:30:00",
...
"supplier": {
"id": 1,
"name": "Fornecedor ABC",
"email": "fornecedor@example.com",
...
},
"items": [ ... ]
}
]
7. Aceitar Proposta (Produtor)
POST /proposals/{proposal}/accept
Aceita uma proposta submetida.
Parâmetros:
{proposal}(path) - UUID da proposta
ValidaƧƵes:
- Proposta deve estar em status "submitted"
Resposta 200:
{
"id": 1,
"uuid": "550e8400-e29b-41d4-a716-446655440000",
"status": "accepted",
"accepted_at": "2026-01-11 11:00:00",
"is_accepted": true,
...
}
Erro 500:
{
"error": "Erro ao aceitar proposta"
}
8. Rejeitar Proposta (Produtor)
POST /proposals/{proposal}/reject
Rejeita uma proposta submetida.
Parâmetros:
{proposal}(path) - UUID da proposta
Body:
{
"reason": "PreƧos acima do orƧamento"
}
ValidaƧƵes:
reason(nullable, string)- Proposta deve estar em status "submitted"
Resposta 200:
{
"id": 1,
"uuid": "550e8400-e29b-41d4-a716-446655440000",
"status": "rejected",
"rejected_at": "2026-01-11 11:00:00",
"rejection_reason": "PreƧos acima do orƧamento",
"is_rejected": true,
...
}
š Fluxo de Estados
draft ā submitted ā accepted
ā rejected
ā cancelled
Status DisponĆveis:
- draft: Rascunho (pode editar)
- submitted: Enviada (aguardando avaliação)
- accepted: Aceita pelo produtor
- rejected: Rejeitada pelo produtor
- cancelled: Cancelada pelo fornecedor
š Códigos de Resposta
- 200 - Sucesso
- 401 - NĆ£o autenticado
- 403 - NĆ£o autorizado
- 404 - NĆ£o encontrado
- 422 - Validação falhou
- 500 - Erro interno
š” Dicas de Uso
Auto-save no Frontend
// Usar composable useProposals
const proposals = useProposals()
// Carregar draft
await proposals.loadOrCreateDraftProposal(orderId)
// Salvar (auto-save)
await proposals.saveDraft(orderId, items, notes)
// Submeter
await proposals.submitProposal(proposalUuid)
Validação de Items
Um item Ʃ vƔlido se:
unit_price > 0(tem preço) OUjustificationnão vazio (tem justificativa)
Licitação Aberta vs Fechada
- Fechada: Todos os items devem ter preƧo
- Aberta: Items podem ter justificativa em vez de preƧo
š§Ŗ Exemplos de Testes
cURL: Criar Draft
curl -X POST http://localhost:8000/api/v1/orders/1/proposals \
-H "Authorization: Bearer {token}" \
-H "Content-Type: application/json" \
-d '{
"order_id": 1,
"items": [
{
"order_item_id": 1,
"product_id": 1,
"unit_price": 10.50,
"quantity": 100
}
],
"notes": "Teste"
}'
cURL: Submeter
curl -X POST http://localhost:8000/api/v1/proposals/{uuid}/submit \
-H "Authorization: Bearer {token}"
cURL: Listar Recebidas
curl -X GET http://localhost:8000/api/v1/orders/1/proposals/received \
-H "Authorization: Bearer {token}"
Versão: 1.0
Data: 2026-01-11