Add cart send-to-customer endpoint#314
Conversation
Fill the SendCartToCustomerCommand gap: PUT /carts/{cartId}/emails (scope cart_write)
to email the cart to its customer. The test disables real mail sending
(PS_MAIL_METHOD) so Mail::send() succeeds without an SMTP server.
Related to PrestaShop/PrestaShop#39630
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
mattgoud
left a comment
There was a problem hiding this comment.
Thanks for this. The endpoint is correct and functional and follows the module conventions well:
SendCartToCustomerCommand::__construct($cartId)maps cleanly from thecartIdidentifier, noCQRSCommandMappingneeded, and the green integration test confirms the wiring.- The exception mapping is correctly ordered:
CartNotFoundException => 404beforeCartException => 422(required sinceCartNotFoundException extends CartException). read: false+output: false+allowEmptyBody: trueis the right combo for a no-input/no-output action returning204, and disablingPS_MAIL_METHODin the test avoids an SMTP dependency.
A few changes I would like before merging:
- Add
declare(strict_types=1);toCartEmail.php. The test file already has it, and it is the project standard for every PHP file. - Cover the not-found case in the test. A
PUT /carts/{nonExistentId}/emailsasserting404would exercise theCartNotFoundException => 404mapping, which is the most subtle part of the resource and is currently untested. This is the main one for me. - Use a non-empty cart in
createCustomerCart()(add a product) so the test is more representative of a real send-to-customer flow.
Happy to re-review once these are in.
📋 Summary of changesThis PR exposes ⏱️ Estimated review time3–5 minutes — the resource class is very small; the test has a couple of issues worth examining closely. 🎯 Scope
🧱 API Platform / CQRS architecture complianceOperation attribute choice — acceptable but worth a note
URI —
Identifier property — No No No custom normalizer or processor — ✅ No Value Objects in properties — ✅ 💡 Improvement suggestions1. Missing test coverage for non-existent
|
- Add declare(strict_types=1) to CartEmail resource for consistency - Add testSendUnknownCartReturnsNotFound to cover CartNotFoundException => 404 - Populate the cart with a product for a more representative send-to-customer case Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
Thanks for the thorough review @mattgoud! Addressed all three nits in dc08b06:
|
mattgoud
left a comment
There was a problem hiding this comment.
Perfect, all three addressed in dc08b06 and CI is green across the matrix:
declare(strict_types=1);added toCartEmail.php.testSendUnknownCartReturnsNotFoundusesMAX(id_cart)+1for a guaranteed non-existent id and asserts404, so theCartNotFoundException => 404mapping is now exercised end-to-end.createCustomerCart()now adds a simple, active, in-stock product (nicely filtered out of products with combinations), which is more representative of a real send-to-customer flow.
Thanks for the quick turnaround. LGTM 👍
📋 Summary of changesThis PR adds a single ⏱️ Estimated review time10–15 minutes — small diff (2 files, ~170 lines), simple action-only endpoint with no CQRS mapping needed. 🎯 Scope
🧱 API Platform / CQRS architecture complianceURI endpoint name — moderate concernThe established pattern in this module for action sub-resources is a verb or hyphenated action phrase in the URI suffix. For example: This PR uses the noun The word HTTP semantics — minor concern
|
|
Following up on the AI pre-review checklist — not every box is ticked, but they are not all equal, so here is my triage so you know what is worth acting on vs noise: Worth fixing (the one I would actually like addressed):
Design calls, your/maintainers' decision (not blocking):
Bot noise — safe to ignore:
My approval stands; only the DB cleanup is something I would genuinely like in before merge. |
mattgoud
left a comment
There was a problem hiding this comment.
Switching my approval back to request-changes to gate the merge on the one real item from the AI pre-review (my earlier comment stands for the full triage).
Blocking:
- Add
DatabaseDump::restoreTables(['cart', 'cart_product']);in bothsetUpBeforeClassandtearDownAfterClass. The test inserts intocart/cart_productand currently never restores them, leaking rows into other test classes — including any readingMAX(id_cart), whichtestSendUnknownCartReturnsNotFounditself depends on. 29 endpoint tests in the module already follow this pattern.
Everything else (URI naming, PUT vs POST, testInvalid*) is a non-blocking design call, and the bot's "remove createApiClient" suggestion is wrong (it is the dominant convention). Happy to re-approve as soon as the DB cleanup is in.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
Thanks @mattgoud, appreciate the triage.
|
mattgoud
left a comment
There was a problem hiding this comment.
Re-approving. Both points are in and CI is green across the full matrix:
- DB cleanup (was blocking):
DatabaseDump::restoreTables(['cart', 'cart_product'])added tosetUpBeforeClassandtearDownAfterClass(d8e64a8). No more row leakage. - 422 mapping (non-blocking): documented why the
CartException => 422path is not reachable from an integration test (2c71cb9).
Thanks again for the quick turnarounds. LGTM 👍
SendCartToCustomerCommandgap:PUT /carts/{cartId}/emails(scopecart_write) to send the cart to its customer by email.PUT /carts/{id}/emails(client grantedcart_write) emails the cart to the customer. Covered byCartEmailEndpointTest(which disables real mail sending so the assertion does not depend on an SMTP server).