Appearance
Menzzo promotions and cart recovery
Checkout and payment · Support and refunds
This page maps the product-page banner coupon, manual cart coupon, chatbot add-to-cart link, and two distinct WhatsApp paths. The technical behavior was reviewed against axelites/menzzo at 6bf5acf477d65bcfd54182549fc9487e110da007. The source confirms implementation paths only; effective store configuration, deployment, scheduled execution, external delivery, and customer use have not been verified.
View diagram source
flowchart TB
subgraph PDP[Product page banner coupon]
A[Resolve first active promo]
B[Show product price projection at quantity 1]
C[Reveal coupon and submit add-to-cart form]
D[Observer validates code, updates quote, recollects totals]
A --> B --> C --> D
end
subgraph Manual[Manual cart coupon]
M[Submit cart coupon form]
N[Custom CouponPost runs eligibility validator]
O[Custom rejection clears quote coupon and recollects totals]
P[Otherwise Magento parent handler applies the code]
M --> N
N -->|custom rejection| O
N -->|no custom rejection| P
end
subgraph Chatbot[Chatbot product link]
Q["/chatbot/cart/add with product_id and optional promotion"]
R[Load enabled and salable product, add quantity 1, save quote]
S[Apply coupon or active banner in a separate step]
T[Redirect to cart; product can remain when coupon fails]
Q --> R --> S --> T
end
Product-page banner and manual coupon
Purchase::getPdpBannerCouponData() asks BannerPromoResolver for the first active banner promo and a discounted product price at quantity one. The product page displays this as a coupon-price projection. It is not a promise of the final quote total, which is recalculated after the coupon is added to the cart.
On reveal, pdp-banner-coupon.js updates the banner display and puts ax_banner_coupon_revealed=1 plus ax_banner_coupon_code into the add-to-cart form. The Axelites_Core add-to-cart observer accepts that banner coupon only when the submitted code still matches the active banner and the resolver returns a discounted price for the product. It then sets the quote coupon, asks Magento to recollect shipping rates and totals, and saves the quote. The observer next validates the quote's current coupon; a custom rejection clears it and recollects totals, with no attempt to restore the earlier code. If the reveal/code checks fail, the banner code is not applied by this observer.
Source: Purchase.php, BannerPromoResolver.php, banner template, banner JavaScript, observer binding, add-to-cart observer.
Manual coupon submission uses the custom preference for Magento's cart CouponPost. Before delegating to Magento's parent handler, CouponEligibilityValidator rejects certain Amasty rules with skip_rule enabled and a configured free-shipping action when the quote contains a discounted product. For a fixed set of daily-coupon rule IDs, it also rejects a coupon not created today when the quote already has items. On either custom rejection, CouponPost clears the quote's current coupon, recollects totals, saves, and returns with an error. Other cases proceed through Magento's parent coupon handler.
Source: Core DI preference, CouponPost.php, CouponEligibilityValidator.php.
Chatbot product and promotion link
The chatbot frontend route maps Controller/Cart/Add to /chatbot/cart/add. It reads product_id, optional coupon_code, and auto_apply_banner. ChatbotCartProductService loads the product in the current store and requires it to be enabled and salable; it builds a quantity-one add request and fills the dispo and éco-participation options when present. The controller adds the product, saves the active cart, dispatches checkout_cart_add_product_complete, and redirects to the cart.
Source: chatbot route, Add.php, ChatbotCartProductService.php.
Promotion application is a second step after a successful product add. An explicit coupon is checked as submitted; auto_apply_banner=1 with no explicit code selects the first active banner promo. The applier validates the coupon and custom eligibility, then sets it on the quote, recollects shipping and totals, and saves. If Magento does not retain the requested coupon after applying it, or an exception occurs after the quote code changed, the applier tries to restore the previous coupon and recollect/save again. A restoration exception is logged. An invalid or ineligible coupon produces a message without undoing the successful product add, so the cart mutation outcome and coupon outcome must be read separately.
Source: ChatbotCartPromotionApplier.php, CouponEligibilityValidator.php.
Two separate WhatsApp journeys
Amasty abandoned-cart history. HistoryEmailSenderPlugin::aroundProcess() runs while Amasty processes an abandoned-cart history row. Depending on channel mode, it sends WhatsApp after Amasty's email succeeds or handles a WhatsApp-only history. ScheduleWhatsapp::execute() checks the Amasty rule quote, whether the Magento quote was converted, store channel settings, usable phone and country, commercial consent, opt-out, content SID, and the configured per-rule-quote send cap. An eligible request uses Amasty's cart-restoration URL and the coupon from that history. A send success records whatsapp_sent=1, clears whatsapp_error, and sets whatsapp_sent_at; failures store whatsapp_sent=0, a reason in whatsapp_error, and a null timestamp. In WhatsApp-only mode, the plugin also sets Amasty history status to sent or failed. WhatsApp errors are kept from failing Amasty's email path when email is enabled. This state belongs to the Amasty history flow.
Source: Amasty history plugin, ScheduleWhatsapp.php, EligibilityInputBuilder.php, EligibilityChecker.php, CartUrlResolver.php.
View diagram source
flowchart TB
subgraph Amasty[Amasty abandoned-cart history]
A[Amasty processes history row]
B[Check quote conversion, contact, consent, opt-out, channel and cap]
C[Send Amasty cart URL with history coupon]
D[Record WhatsApp sent or error fields on history]
A --> B --> C --> D
end
subgraph Priority[Logidav priority cancelled-order WhatsApp]
E[POST /V1/logidav-api/priority-abandoned-cart-whatsapp/send]
F[Resolve order, generate coupon, request WhatsApp send]
G[Return sent result or failure reason]
H[acartwhatsapp/cart/recover replaces active quote with order items]
I[Check cart recovery and coupon application separately]
E --> F --> G
G -->|if sent link is later opened| H --> I
end
Logidav priority recovery. The permissioned POST /V1/logidav-api/priority-abandoned-cart-whatsapp/send route calls PriorityAbandonedCartWhatsappManagement::send(). It resolves the supplied Magento order ID, checks store WhatsApp settings and content SID, validates a supplied or order-address phone, generates a coupon, and asks the sender to send a URL containing order_id and coupon. The JSON result reports sent, status, and either a failure reason or send metadata such as message SID, time, and URLs. Failure reasons include a missing or unknown order, disabled WhatsApp, missing content SID or phone, coupon-generation failure, sender exception, or provider rejection.
The recovery URL opens acartwhatsapp/cart/recover, which calls CancelledOrderCartRecovery::recover(). For an order with visible items, the service truncates the visitor's active quote, re-adds those order items, requests shipping-rate and total recollection, sets the supplied coupon (or clears the quote coupon if none was supplied), and saves. Thus this path can replace the visitor's current cart and coupon. If order lookup fails, there are no visible items, or cart rebuilding fails, recovery returns an error; a rebuilding failure occurs after truncation, and this service has no rollback of the prior quote. When rebuilding succeeds, coupon application is evaluated separately: the controller still reports that the cart was restored and redirects to /checkout/cart, while an unapplied coupon receives its own error message.
Source: Logidav API route, PriorityAbandonedCartWhatsappManagement.php, coupon generator, Recover.php, CancelledOrderCartRecovery.php.
| Journey | The source-level success checkpoint | Separate outcome to verify |
|---|---|---|
| PDP banner | Coupon survives quote validation and totals are recollected | Final cart amount, including other items and shipping |
| Chatbot link | Product is saved to the active quote | Coupon may fail while the product remains |
| Amasty history | History records WhatsApp sent state | Whether a customer opened the cart URL |
| Logidav priority recovery | Cart recovery result is successful | couponApplied is separate; active quote can be replaced |
Evidence boundary
This is a partial, source-reviewed map. Evidence review was an agent-led source review by Codex on 2026-10-07; it does not signal human or owner acceptance. The source DI binding maps SenderInterface to TwilioSender, but the effective Twilio account, credentials, sender number, store values (Config.php), content SID, and external message acceptance are unknown. The priority sender service resolves an order ID but does not itself establish that the order is cancelled; the Logidav caller and its selection rule are also unknown. No live Amasty schedule, deployed revision, runtime quote, WhatsApp delivery, or customer recovery result was checked. Do not treat a send declaration or successful send result as proof that a shopper opened the link or that recovery completed.