Skip to content

Commit 6475620

Browse files
authored
Create 3. Demonstrate ability to customize the shopping cart.md
1 parent ad489bc commit 6475620

File tree

1 file changed

+268
-0
lines changed

1 file changed

+268
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,268 @@
1+
# Demonstrate ability to customize the shopping cart
2+
3+
## Describe how to implement shopping cart rules.
4+
DB tables:
5+
- `salesrule`
6+
* name, description, is_active, is_rss
7+
* from_date, to_date, conditions_serialized, is_advanced, sort_order, product_ids
8+
* actions_serialized, simple_action, discount_amount, discount_qty, discount_step, apply_to_shipping
9+
* stop_rules_processing, uses_per_customer, times_used
10+
* coupon_type, use_auto_generation
11+
- `salesrule_label` - label translation
12+
* rule_id, store_id, label
13+
- `salesrule_product_attribute`
14+
* rule_id, website_id, customer_group_id, attribute_id
15+
16+
Multiple selection:
17+
- `salesrule_website`
18+
- `salesrule_customer_group`
19+
20+
- `salesrule_coupon`
21+
* rule_id, code, usage_limit, usage_per_customer, times_used, expiration_date, is_primary, created_at, type
22+
23+
Usage tracking:
24+
- `salesrule_coupon_usage`
25+
* coupon_id, customer_id, times_used
26+
- `salesrule_customer`
27+
* rule_id, customer_id, times_used
28+
- `salesrule_coupon_aggregated`, `salesrule_coupon_aggregated_updated`, `salesrule_coupon_aggregated_order` - reporting stuff
29+
30+
- ui component `sales_rule_form`
31+
- conditions - html content block - *generic form* Edit\Tab\Conditions
32+
- conditions fieldset renderer \Magento\Rule\Block\Conditions.render
33+
- `$element->getRule()->getConditions()->asHtmlRecursive();`
34+
- Magento\SalesRule\Model\Rule extends Magento\Rule\Model\AbstractModel
35+
+ store labels
36+
+ coupon generation
37+
- Conditions model instance - \Magento\SalesRule\Model\Rule\Condition\Combine, extends getNewChildSelectOptions:
38+
+ \Magento\SalesRule\Model\Rule\Condition\Product\Found - Product attribute combination
39+
+ \Magento\SalesRule\Model\Rule\Condition\Product\Subselect - Products subselection
40+
+ Conditions combination - self, recursion
41+
+ \Magento\SalesRule\Model\Rule\Condition\Address - Cart Attribute:
42+
base_subtotal, total_qty, weight, shipping_method, postcode, region, region_id, country_id
43+
44+
what is:
45+
- `is_advanced` column - not used
46+
- `product_ids` column - not used
47+
- `salesrule_product_attribute` table - attributes currently used in conditions and actions of rule.
48+
49+
Used in plugin to \Magento\Quote\Model\Quote\Config::`getProductAttributes` to ensure all needed
50+
attributes are loaded with quote.
51+
* quote.load()
52+
* quoteResource.`_assignProducts`
53+
* product collection `->addAttributeToSelect($this->_quoteConfig->getProductAttributes())`.
54+
55+
56+
## What is the difference between sales rules and catalog rules?
57+
- Catalog rules update product final price, they are visible in all catalog - category listing, product page.
58+
- Sales rule is visible only in checkout and can require a coupon.
59+
- Sales rules can affect shipping price
60+
- Sales rules can trigger on products combination
61+
62+
63+
## How do sales rules affect performance?
64+
Performance is not affected, all calculation happens in totals collectors.
65+
66+
## What are the limitations of the native sales rules engine?
67+
Only one coupon can be applied.
68+
69+
70+
Implementing rules:
71+
- Rule model
72+
* getConditionsInstance - will be used in form as `$model->getConditions()->asHtmlRecursive()`.
73+
Usually starting conditions are composite - selector [all/any] and sub-conditions selection.
74+
- Composite conditions model
75+
* getNewChildSelectOptions - used by Consition\Combine.getNewChildElement
76+
77+
78+
## Describe add-to-cart logic in different scenarios.
79+
80+
### Add to cart
81+
cart model - used only on frontend, marked deprecated.
82+
83+
- checkout/cart/add [product, qty, related_product]
84+
* cart model.addProduct
85+
+ filter request here, can register own via argument for \Magento\Checkout\Model\Cart\RequestInfoFilter
86+
+ by default filtered out `form_key` and `custom_price`
87+
* quote.addProduct
88+
* product type instance.`prepareForCartAdvanced`
89+
* get same quote item or create new
90+
* \Magento\Quote\Model\Quote\Item\Processor::prepare
91+
+ quote item.addQty
92+
+ support request.customPrice -> quote item.customPrice
93+
* event `checkout_cart_product_add_after`
94+
* checkout session.setLastAddedProductId
95+
* cart.save
96+
+ quote collect totals
97+
+ event `checkout_cart_save_after`
98+
+ reinitialize state - remove addresses and payments
99+
* event `checkout_cart_add_product_complete`
100+
101+
- checkout/cart/updatePost
102+
* cart.suggestItemsQty => \Magento\CatalogInventory\Model\StockStateProvider::suggestQty - qty increments, min/max qty
103+
* cart.updateItems
104+
+ events `checkout_cart_update_items_before`, `checkout_cart_update_items_after`
105+
+ quote item.setQty -- triggers stock validation
106+
* cart.save
107+
108+
### *controller checkout/cart/add*:
109+
- cart.addProduct:
110+
* quote.addProduct: type.`prepareForCartAdvanced`, event `sales_quote_product_add_after`
111+
* event `checkout_cart_product_add_after`
112+
- event `checkout_cart_add_product_complete` -- this event only when normal add to cart
113+
* withlist observer, marked to be deleted
114+
115+
116+
### *add to withlist* `wishlist/index/add`:
117+
- same buy request
118+
- cart candidates = type instance.processConfiguration -> `_prepareProduct`. Same as with add to cart.
119+
- create/update qty withlist item, just like quote item
120+
- event `wishlist_product_add_after`
121+
- event `wishlist_add_product`
122+
123+
### *add to cart from wishlist* `withlist/index/cart`:
124+
125+
Can override original buyRequest when adding to cart.
126+
NO event _checkout_cart_add_product_complete_.
127+
128+
- load withlist item and options
129+
- merge buy request - saved and current.
130+
- wishlist item.addToCart
131+
- `cart.addProduct` with merged buyRequest:
132+
* events `sales_quote_product_add_after`, `checkout_cart_product_add_after`
133+
- cart.save
134+
* event `checkout_cart_save_before`
135+
* event `checkout_cart_save_after`
136+
- quote.collectTotals
137+
- \Magento\Wishlist\Helper\Data::calculate
138+
* write to customer session
139+
* event `wishlist_items_renewed`
140+
141+
### *merge quotes* controller `customer/account/loginPost`:
142+
143+
Cart model is not used at all.
144+
145+
- \Magento\Customer\Model\Session::setCustomerDataAsLoggedIn
146+
- event `customer_login`
147+
- \Magento\Checkout\Observer\LoadCustomerQuoteObserver
148+
- checkout session.`loadCustomerQuote`:
149+
* event `load_customer_quote_before`
150+
* finds existing customer quote
151+
* detects that guest quote <> customer quote
152+
* customer quote.`merge`(guest quote):
153+
+ event `sales_quote_merge_before`
154+
+ for each quote item.`compare` - product id, options same
155+
+ if items same, qty++
156+
+ if guest item is new, clone quote item, quote.addItem, event `sales_quote_add_item`
157+
+ event `sales_quote_merge_after`
158+
* *delete guest quote*
159+
160+
### *reorder* controller `sales/order/reorder`:
161+
162+
Like normal add to cart, but NO event _checkout_cart_add_product_complete_.
163+
164+
- load order, ensure can view
165+
- for each order item, `cart.addOrderItem` - converts order item to quote item:
166+
* load product
167+
* get item option buyRequest
168+
* `cart.addProduct` with old buy request
169+
+ events `sales_quote_product_add_after`, `checkout_cart_product_add_after`
170+
171+
172+
## Describe how to customize the process of adding a product to the cart.
173+
- plugin over product type `prepareForCartAdvanced`
174+
- event `catalog_product_type_prepare_full_options` - custom options in `_prepareOptions`
175+
- plugin over \Magento\Quote\Model\Quote\Item\Processor::prepare - qty, custom price
176+
- event `checkout_cart_product_add_after`
177+
178+
## Which different scenarios should you take into account?
179+
- add to cart from catalog
180+
- add to cart from wishlist
181+
- move all wishlist to cart
182+
- merge quote when existing customer has quote, then shops as a guest and logs in
183+
- admin create order
184+
- admin reorder
185+
- configure added product - change custom options
186+
187+
188+
## Render product types
189+
checkout cart index:
190+
- `<update handle="checkout_cart_item_renderers"/>`
191+
- `<update handle="checkout_item_price_renderers"/>`
192+
193+
- block \Magento\Checkout\Block\Cart\AbstractCart::getItems - quote visible items
194+
* can limit with *pagination*
195+
* *custom_items* can override
196+
- abstract cart.`getItemHtml`(quote item)
197+
- render via abstract cart.`getItemRenderer` by product type
198+
* renderer child block `renderer.list` \Magento\Framework\View\Element\RendererList
199+
* renderer list block.getRenderer(type, template)
200+
* finds child block by alias = product type
201+
* \Magento\Checkout\Block\Cart\Item\Renderer
202+
*
203+
204+
Customizations:
205+
- provide cart block data arguments `<referenceBlock name="checkout.cart.form">`:
206+
* `renderer_list_name` - use custom renderer list
207+
* `overriden_templates` - array by product type
208+
* `renderer_template` - regardless of product type
209+
- in `checkout_cart_item_renderers`, `<referenceBlock name='renderer.list'>`, add child blocks by alias = product type. E.g.
210+
211+
```xml
212+
<referenceBlock name="checkout.cart.item.renderers">
213+
<block class="Magento\Checkout\Block\Cart\Item\Renderer" name="checkout.cart.item.renderers.default" as="default" template="Magento_Checkout::cart/item/default.phtml">
214+
<block class="Magento\Checkout\Block\Cart\Item\Renderer\Actions" name="checkout.cart.item.renderers.default.actions" as="actions">
215+
<block class="Magento\Checkout\Block\Cart\Item\Renderer\Actions\Edit" name="checkout.cart.item.renderers.default.actions.edit" template="Magento_Checkout::cart/item/renderer/actions/edit.phtml"/>
216+
<block class="Magento\Checkout\Block\Cart\Item\Renderer\Actions\Remove" name="checkout.cart.item.renderers.default.actions.remove" template="Magento_Checkout::cart/item/renderer/actions/remove.phtml"/>
217+
</block>
218+
</block>
219+
</referenceBlock>
220+
```
221+
222+
## Describe the available shopping cart operations.
223+
224+
### Configure product in cart - controller `checkout/cart/configure`
225+
Product view and product configure are rendered via same helper
226+
\Magento\Catalog\Helper\Product\View.prepareAndRender.
227+
228+
The only difference is params:
229+
- category_id - can be `false`
230+
- configure_mode - optional
231+
- buy_request - optional
232+
- specify_options - error message if missing options
233+
234+
*Normal product view*:
235+
- params[category_id] = current
236+
- params[specify_options] - from product type
237+
- helper product view.prepareAndRender
238+
* \Magento\Catalog\Helper\Product::initProduct - load product, check visible/enabled
239+
+ event `catalog_controller_product_init_before`
240+
+ event `catalog_controller_product_init_after`
241+
* event `catalog_controller_product_view`
242+
243+
*Configure product*:
244+
- params[`buyRequest`] = quote item.buyRequest
245+
- helper product view.prepareAndRender
246+
* product helper.initProduct
247+
* product helper.`prepareProductOptions` - set default selections from buy request, e.g. selected size=XXL
248+
+ product.processBuyRequest, `product type.processBuyRequest`, `product type.checkProductConfiguration`
249+
+ product.`setPreconfiguredValues`
250+
* product.setConfigureMode -- used to show all hidden customization options instantly in edit mode
251+
* event `catalog_controller_product_view`
252+
253+
product.getPreconfiguredValues is later used:
254+
- default product qty = product.preconfigured values.qty
255+
- custom option values = product.preconfigured values.option_{$id}
256+
257+
### How do you add a field to the shipping address?
258+
259+
Quote address extends AbstractExtensibleModel, and so should implement `getCustomAttributesCodes()`
260+
to add custom attributes. Custom attributes should load and save automatically, assuming you added
261+
a column in migration and registered custom attribute in plugin (see below).
262+
263+
Quote address custom attributes:
264+
* community \Magento\Quote\Model\Quote\Address\CustomAttributeList - empty, use plugin to add
265+
* EE \Magento\CustomerCustomAttributes\Model\Quote\Address\CustomAttributeList::getAttributes
266+
+ customer address attributes + customer attributes
267+
268+
Alternatively, you can always register extension attribute and load/save it manually.

0 commit comments

Comments
 (0)