Requirements Document
Task: task-194883-cart-api-remove-item.md Contexto: CONTEXT Contexto US: US 194871 — MVP Upsell (Pedido) Pesquisa tecnica: pesquisa-remove-recommended-item.md ADRs: ADR-008
Status: refinado
Sessão de grilling: 2026-05-15, 2026-06-19
Endpoint interno da Cart API para remover um item recomendado de um carrinho existente. O endpoint DELETE api/cart/{cartId}/items/{cartItemId} é chamado exclusivamente pelo checkout service via x-api-key: "internal". A remoção aplica soft-delete no item, desvincula a recomendação associada (CartItemId = null) e recalcula os totais do cart, permitindo que a recomendação fique disponível para re-adição futura.
O endpoint segue semântica idempotente: se o cart ou item não existe (ou já foi removido), retorna 200 silencioso — o estado desejado já foi alcançado.
Glossary
- Cart_API: Serviço responsável por gerenciar carrinhos de compras (coezzion-service-cart)
- Checkout_Service: Serviço consumidor exclusivo deste endpoint (coezzion-service-checkout)
- CartModel: Entidade que representa o carrinho, contendo coleções de
CartItemseCartItemRecommendations - CartItemsModel: Entidade que representa um item do carrinho, com propriedade
FromRecommendationindicando origem - CartItemRecommendationModel: Entidade que representa uma recomendação de item vinculada ao carrinho; campo
CartItemIdnullable indica se a recomendação foi efetivada - RemoveCartItemCommand: Command DTO contendo
CartIdeCartItemId, ambos inteiros vindos da rota - BaseResult: Objeto padrão de resposta de negócio da Cart API; quando válido sem erros produz HTTP 200, quando contém erros produz HTTP 400
- ApiKey_Internal: Chave de autenticação configurada em
appsettings.jsonpara chamadas internas entre serviços - CartService: Serviço de aplicação que orquestra commands via métodos
Handlesobrecarregados - RevertRecommendedItem: Método de domínio em CartModel que executa soft-delete do item, desvincula a recomendação e recalcula totais
- SaleEcommerce: Flag booleana em CartModel que indica se o pedido é do tipo e-commerce (operação não permitida para este endpoint)
Requirements
Requisito 1: Autenticação via ApiKey
User Story: Como checkout service, quero chamar a Cart API sem JWT de usuário, para que eu possa remover itens recomendados do carrinho sem depender de contexto de sessão do cliente.
Critérios de Aceite
- WHEN uma requisição chega com header
x-api-keycontendo o valor correspondente à ApiKey_Internal, THE Cart_API SHALL processar a requisição normalmente - WHEN uma requisição chega sem header
x-api-key, THE Cart_API SHALL retornar HTTP 401 - WHEN uma requisição chega com header
x-api-keycontendo valor diferente da ApiKey_Internal, THE Cart_API SHALL retornar HTTP 401 - WHEN uma requisição contém header
Authorizationcom Bearer token, THE Cart_API SHALL ignorar o token e autenticar exclusivamente pela ApiKey_Internal
Requisito 2: Contrato do Endpoint e Command
User Story: Como checkout service, quero um endpoint DELETE api/cart/{cartId}/items/{cartItemId} sem body, para que eu possa remover um item de um cart existente usando apenas identificadores na rota.
Critérios de Aceite
- WHEN uma requisição
DELETE api/cart/{cartId}/items/{cartItemId}chega com ApiKey_Internal válida, THE Cart_API SHALL aceitar a requisição e iniciar o processamento - WHEN o
cartIdna rota não é um inteiro válido, THE Cart_API SHALL retornar HTTP 400 - WHEN o
cartItemIdna rota não é um inteiro válido, THE Cart_API SHALL retornar HTTP 400 - THE Cart_API SHALL criar o RemoveCartItemCommand com
CartIdeCartItemIdextraídos dos parâmetros da rota, sem desserialização de body
Requisito 3: Busca do Carrinho
User Story: Como Cart API, quero buscar o carrinho com suas recomendações e itens em uma única query com tracking, para que eu possa validar o estado e persistir alterações via EF Core change tracking.
Critérios de Aceite
- WHEN o endpoint é chamado com
cartIdválido, THE Cart_API SHALL buscar o CartModel pelocartIdviaGetByIdWithRecommendationsAsyncincluindo as coleçõesCartItemseCartItemRecommendationscom tracking habilitado - WHEN o CartModel não é encontrado para o
cartIdinformado, THE Cart_API SHALL retornar HTTP 200 sem corpo e sem erros (idempotente) - WHEN o CartModel é encontrado, THE Cart_API SHALL prosseguir com a validação de SaleEcommerce
Requisito 4: Validação de SaleEcommerce
User Story: Como Cart API, quero rejeitar operações em carts do tipo e-commerce, para que este endpoint interno seja utilizado apenas em pedidos do tipo venda assistida.
Critérios de Aceite
- WHEN o CartModel é encontrado e o campo
SaleEcommerceétrue, THE Cart_API SHALL retornar HTTP 400 com mensagem "Operacao nao disponivel para este tipo de pedido" - WHEN o CartModel é encontrado e o campo
SaleEcommerceéfalse, THE Cart_API SHALL prosseguir com a busca do item
Requisito 5: Busca do Item no Carrinho (Idempotente)
User Story: Como Cart API, quero localizar o item na coleção do cart carregado, para que eu possa validar sua origem antes de removê-lo.
Critérios de Aceite
- WHEN o CartModel é validado, THE Cart_API SHALL buscar o CartItemsModel com
Idigual aocartItemIdna coleçãoCartItemsdo CartModel carregado - WHEN o CartItemsModel não é encontrado na coleção (inexistente, já soft-deletado pelo EF global query filter, ou pertencente a outro cart), THE Cart_API SHALL retornar HTTP 200 sem corpo e sem erros (idempotente)
- WHEN o CartItemsModel é encontrado na coleção, THE Cart_API SHALL prosseguir com a validação de FromRecommendation
Requisito 6: Validação de Origem do Item (FromRecommendation)
User Story: Como Cart API, quero garantir que apenas itens originados de recomendações possam ser removidos por este endpoint, para que itens adicionados manualmente pelo vendedor não sejam removidos inadvertidamente.
Critérios de Aceite
- WHEN o CartItemsModel é encontrado e o campo
FromRecommendationéfalse, THE Cart_API SHALL retornar HTTP 400 com mensagem "Item nao originado de recomendacao" - WHEN o CartItemsModel é encontrado e o campo
FromRecommendationétrue, THE Cart_API SHALL prosseguir com a remoção do item
Requisito 7: Reverter Item Recomendado
User Story: Como Cart API, quero aplicar soft-delete no item, desvincular a recomendação e recalcular os totais do cart, para que o estado do carrinho permaneça consistente e a recomendação fique disponível para re-adição futura.
Critérios de Aceite
- WHEN o item é válido com
FromRecommendationigual atrue, THE Cart_API SHALL chamarRevertRecommendedItemno CartModel passando ocartItemId - WHEN RevertRecommendedItem é executado, THE Cart_API SHALL garantir que o CartItemsModel recebe soft-delete via
Delete()(campoDateDeletedpreenchido) - WHEN RevertRecommendedItem é executado, THE Cart_API SHALL garantir que o CartItemRecommendationModel vinculado tem o campo
CartItemIdsetado paranull - WHEN RevertRecommendedItem é executado, THE Cart_API SHALL garantir que os totais do CartModel são recalculados excluindo itens com
DateDeletedpreenchido
Requisito 8: Persistência e Resposta
User Story: Como Cart API, quero persistir o carrinho atualizado de forma atômica e invalidar o cache, para que o estado do banco permaneça consistente e leituras subsequentes reflitam a remoção.
Critérios de Aceite
- WHEN RevertRecommendedItem é concluído, THE Cart_API SHALL chamar
Updateno repositório de cart seguido deSaveAsyncpara persistir as alterações - WHEN
Updateé chamado no repositório, THE Cart_API SHALL invalidar automaticamente o cache do cart (comportamento já implementado no repositório) - WHEN a persistência é bem-sucedida, THE Cart_API SHALL retornar HTTP 200 sem corpo na resposta
- IF ocorre erro inesperado durante a persistência, THEN THE Cart_API SHALL retornar HTTP 400 com mensagem "Erro interno ao processar a requisicao"