Skip to main content

Task #194883 — Cart API: Endpoint para Remover Item de Cart Existente

Task pai: #194883 — [Back] 05 - Cart API: Remove Item de cart existente Contexto: US 194871 — MVP Upsell (Pedido)

Status do refinamento: concluido Requisitos EARS: task-194883-cart-api-remove-item-requisitos.md Pesquisa tecnica: pesquisa-remove-recommended-item.md ADRs: ADR-008


Contexto

O endpoint DELETE api/payment/v2/{id}/remove-recommended-item do checkout service precisa chamar a Cart API para remover um item do cart. A Cart API nao possui hoje um endpoint de remocao de item individual — a unica remocao existente e o DELETE api/cart que deleta o cart inteiro.

Esta task cria o endpoint interno que sera chamado exclusivamente pelo checkout service via ApiKey "internal".


Endpoint

DELETE api/cart/{cartId}/items/{cartItemId}
x-api-key: {internal api key}

Sem body.

Autenticacao

[AllowAnonymous] + [UseApiKey("internal")] + [AddSchema] — mesmo padrao do POST api/cart/{cartId}/items. Sem JWT. A chamada vem exclusivamente do checkout service.


Fluxo do Handler

1. Buscar cart via GetByIdWithRecommendationsAsync(cartId)
2. Cart null? → 200 silencioso (idempotente)
3. SaleEcommerce == true? → 400 "Operacao nao disponivel para este tipo de pedido"
4. Buscar item em cart.CartItems por Id == cartItemId
5. Item null? → 200 silencioso (idempotente)
6. FromRecommendation == false? → 400 "Item nao originado de recomendacao"
7. cart.RevertRecommendedItem(cartItemId) [soft-delete + desvincula recomendação + recalcula total]
8. _cartRepository.Update(cart) + SaveAsync()
9. Erro persistência? → 500 "Erro interno ao processar a requisicao"
10. Sucesso → 200 sem body

Responsabilidades da Cart API

  1. Buscar o cart pelo cartId via GetByIdWithRecommendationsAsync (tracking)
    • Retornar 200 silencioso se nao encontrado (idempotente)
  2. Validar SaleEcommerce == false
    • Retornar 400 se e-commerce
  3. Buscar o CartItem pelo cartItemId dentro da colecao do cart (EF global query filter exclui soft-deletados automaticamente)
    • Retornar 200 silencioso se nao encontrado (idempotente)
  4. Validar que item.FromRecommendation == true
    • Retornar 400 se o item nao e originado de recomendacao
  5. Chamar cart.RevertRecommendedItem(cartItemId) que executa:
    • item.Delete() (soft-delete via BaseEntity.Delete())
    • Desvincula a CartItemRecommendationModel (CartItemId = null) para liberar re-adição
    • CalculateTotal() (já filtra DateDeleted == null)
  6. Persistir via Update(cart) + SaveAsync() e retornar 200

A validacao de PaymentStatus (cart nao pago) nao e responsabilidade da Cart API — e feita pelo checkout service antes de chamar este endpoint. A remocao e idempotente: se o item ja foi removido ou nao existe, retorna 200 silencioso.


Saida

CódigoSituação
200Item removido com sucesso
200Cart não encontrado (idempotente)
200Item não encontrado — inexistente, já soft-deletado ou outro cart (idempotente)
400SaleEcommerce == true"Operacao nao disponivel para este tipo de pedido"
400FromRecommendation == false"Item nao originado de recomendacao"
401ApiKey ausente ou inválida
500Erro inesperado na persistência — "Erro interno ao processar a requisicao"

Artefatos

Escopo: coezzion-service-cart

ArtefatoTipo
Cart.Domain/Commands/RemoveCartItemCommand.csNovo
Cart.Domain/Services/ICartService.csModificar
Cart.API/Application/CartService.csModificar
Cart.API/Controllers/CartController.csModificar
Cart.UnitTests/Application/Commands/RemoveCartItemHandlerTests.csNovo

Já implementado: coezzion-db-core (nao mexer)

ArtefatoStatus
CartModel.RevertRecommendedItem(int cartItemId)✅ Implementado
CartModel.CalculateTotal() — filtra DateDeleted == null✅ Implementado
CartItemsModel.FromRecommendation (bool)✅ Existe e mapeado

Arquivos desta pasta

ArquivoDescricao
task-194883-cart-api-remove-item.mdEste arquivo — sumario, indice da task e fluxo do endpoint
task-194883-cart-api-remove-item-requisitos.mdDocumento de requisitos EARS (pt-BR): REQs, respostas HTTP, fluxo do handler, questoes fechadas