feat(orders): send the confirmation email the order flow never dispatched - #1703
Open
MOHITKOURAV01 wants to merge 1 commit into
Open
Conversation
…ched emailService, the HTML template, the admin log viewer, the robots.txt entry and the vercel.json header rule all shipped together. The caller did not. Every reference to sendOrderEmail in the repo was its definition, its export and one unit test that called it directly, so no shopper has ever received a confirmation. Add orderNotificationService as the seam between the two. createOrderService returns a result shaped for the HTTP response and sendOrderEmail reads a shape built for the template, so something has to translate; doing it inline at both call sites is how the two drift. It also makes the dispatch contract -- never blocking, never throwing -- a property a test can point at. Both call sites dispatch after connection.commit(), and neither awaits it. An email cannot be un-sent, so telling a customer about an order that then rolls back is strictly worse than a missing email, and a checkout that has committed must not turn into a 500 because an SMTP handshake timed out. The money comes from the pricing breakdown rather than the convenience copies of it, so the confirmation cannot quote a different total from the invoice. Also link admin-email-logs.html from the admin sidebar and give it a way back. The page was excluded from the sitemap and disallowed in robots.txt but linked from nowhere, so reaching it meant knowing the filename.
🔍 Quality Gate Report✅ All quality gates passed!
|
|
Someone is attempting to deploy a commit to the Bhuvansh's projects Team on Vercel. A member of the Team first needs to authorize it. |
🤖 AI Code Review🔴 Score: 50/100 | AI review unavailable at this time. Automated AI review — a human maintainer will also review. |
|
💡 Suggested reviewers based on relevant file history: @Aditya8369, @Pcmhacker-hero |
🟡 PR Health Score: 55/100This PR's health score is below the 75/100 threshold for a healthy label.
Improving these signals will help reviewers engage faster and raise your score. 💪 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #1698
What was wrong
The order-confirmation feature shipped a service, an HTML template, an admin log viewer, a
robots.txtentry and avercel.jsonheader rule. It did not ship a caller.A definition, an export, and one unit test calling it directly.
createOrderServicebuilds the order, records promo usage, converts the cart and returns a summary, and never touches the mailer. No shopper has received a confirmation since it landed.Separately,
frontend/admin-email-logs.htmlwas linked from nowhere — reaching it meant knowing the filename.What this does
backend/services/orderNotificationService.js— the seam between the order flow and the transport. It exists rather than the controller callingsendOrderEmaildirectly for two reasons:createOrderServicereturns a result shaped for the HTTP response (orderId,breakdown,items);sendOrderEmailreads a shape built for the template (orderNumber,subtotal,shippingAddress). Something has to translate, and doing it inline at two call sites is how the two drift.The money comes from
result.breakdown— what the pricing engine actually charged — rather than the convenience copies at the top level, so the confirmation cannot quote a different total from the invoice. Lines come fromvalidatedItems, priced as the order was written, not as the cart submitted.Both call sites in
orderController.js—createOrderandcreateOrderWithPayment— dispatch afterconnection.commit(), alongsidemarkAddressUsed, and neither awaits it:smtp.example.comtimed out.frontend/admin.htmlgets an Email Logs entry in the sidebar, and the log page gets a link back. The entry deliberately does not carry.admin-tab— that is the classadmin.jsswitches panels on, and it would swallow the navigation.Guard
backend/tests/orderConfirmationEmail.test.js, 21 cases.The first block is the one that would have caught the original bug. A unit test of a service passes perfectly well with no caller at all — that is exactly the shape of test that shipped with #1668 — so the wiring is asserted against the controller source: the require is present, every
createOrderServicecall site has a matching dispatch, each dispatch sits after itsconnection.commit()and after itscreateOrderService, and none is awaited.The rest cover payload assembly (breakdown wins over the convenience fields when they disagree; a zero-priced line is kept; an empty result does not throw), the dispatch contract (skips without a recipient, resolves rather than rejects when the transport throws or the payload cannot be built, passes the outcome back), that every
{{placeholder}}in the template is onesendOrderEmailsubstitutes — an unfilled one renders as the raw{{token}}in the customer's inbox — and that the admin log page is now reachable in both directions.Verification
CI note — merge #1701 first
The Syntax check job fails on this branch, and it is not this change:
frontend/scripts/shop.jsis unparsable onmain— the responsive refactor duplicated and interleaved its initialization block. Every open PR against this repository inherits it, and becausecheck:syntaxis the first CI job and the other two are gated on it, Backend tests and Server boots are skipped rather than run. That is why this PR shows no test result.#1701 fixes it. Once that merges, this branch picks the fix up from
mainwith no rebase needed — the two touch no file in common. All gates pass locally on this branch's changes:and I verified the whole set merges cleanly by merging all five of these branches together locally: no conflicts,
check:syntaxgreen at 659 files, and the full Jest suite at 2976 passing.The
Vercelcheck fails on every PR in this repository with "Authorization required to deploy" against thebhuvanshs-projectsteam, unrelated to any change.