|
| 1 | +# Demonstrate ability to use quote, quote item, address, and shopping cart rules in checkout |
| 2 | + |
| 3 | +Interesting *quote* fields or methods: |
| 4 | +- `ext_shipping_info` - TEXT 64k, existed in M1, not used. Good place to keep shipping API response? |
| 5 | +- `trigger_recollect` |
| 6 | + * quoteResource.markQuotesRecollectOnCatalogRules - Mark quotes that depend on catalog price rules |
| 7 | + to be recollected on demand. Called on event `catalogrule_before_apply`. Good way to update carts |
| 8 | + after "hacking" prices? |
| 9 | + * quoteResource.markQuotesRecollect - by product IDs. Mark recollect contain product(s) quotes |
| 10 | + + global plugin after product save, _if price or tier price changed_, trigger recollect |
| 11 | + + adminhtml event after product save, _if status disabled_. |
| 12 | +- `is_changed` - not used |
| 13 | + * before quote save - see temporary data-attribute quote.`changed_flag` - not used |
| 14 | +- `orig_order_id` - not used |
| 15 | +- `items_count` - INT "Display number of items in cart" |
| 16 | +- `items_qty` - FLOAT "Display item quantities", e.g. 1.5 kg, 3 same chairs etc. |
| 17 | +- `converted_at` - not used |
| 18 | +- getItemsByProduct - matching product id and custom options. good to use right after add to cart |
| 19 | + + quote.addProduct |
| 20 | + + after withlist aded to cart, finds and changes store id |
| 21 | + + withlist add all to cart, on error find and remove from cart |
| 22 | + |
| 23 | +Quote extends Model\AbstractExtensibleModel - has support of `extension_attributes`. |
| 24 | +Register extensions in `extension_attributes.xml`: |
| 25 | +```xml |
| 26 | +<extension_attributes for="Magento\Quote\Api\Data\CartInterface"> |
| 27 | + <attribute code="shipping_assignments" type="Magento\Quote\Api\Data\ShippingAssignmentInterface[]" /> |
| 28 | +</extension_attributes> |
| 29 | +``` |
| 30 | +Use quote repository plugins afterLoad, beforeSave or whenever needed to populate your values. |
| 31 | +Quote does not utilize `custom_attributes` as it is not EAV by nature. |
| 32 | + |
| 33 | +Quote address custom attributes: |
| 34 | +* community \Magento\Quote\Model\Quote\Address\CustomAttributeList - empty, use plugin to add |
| 35 | +* EE \Magento\CustomerCustomAttributes\Model\Quote\Address\CustomAttributeList::getAttributes |
| 36 | + + customer address attributes + customer attributes |
| 37 | + |
| 38 | +Quote Item shares 2 models, quote item and quote address item. |
| 39 | + |
| 40 | +*Quote item* interesting methods: |
| 41 | +- checkData - called after adding to cart and updating options |
| 42 | + * quote item.setQty - triggers stock validation |
| 43 | + * product type instance.checkProductBuyState |
| 44 | +- `custom_price` |
| 45 | +- getCalculationPrice - `custom_price` or converted price |
| 46 | +- isChildrenCalculated - product.getPriceType = CALCULATE_CHILD |
| 47 | +- isShipSeparately - product.getShipmentType = SHIPMENT_SEPARATELY |
| 48 | +- `additional_data` - TEXT |
| 49 | +- getOptions |
| 50 | +- getQtyOptions: |
| 51 | + * for composite products in cart when sub-products are added, returns array something like |
| 52 | + `[$subProductId = qty (from option `product_qty_{$subProductId}`), otherSubId = qty, ...]` |
| 53 | + + used in \Magento\CatalogInventory\Model\Quote\Item\QuantityValidator::validate |
| 54 | +- compare - \Magento\Quote\Model\Quote\Item\Compare::compare - merge items and add qty instead of new item |
| 55 | + + \Magento\Quote\Model\Quote::updateItem |
| 56 | +- representProduct - compares quote item with some new product, checks product id and custom options |
| 57 | + + quote.getItemsByProduct |
| 58 | +- compareOptions |
| 59 | + + representProduct |
| 60 | + |
| 61 | +## Describe how to modify these models and effectively use them in customizations. |
| 62 | +- All support extension attributes |
| 63 | +- Quote address supports custom_attributes |
| 64 | + |
| 65 | +## Inventory validation |
| 66 | +Qty can be updated from: |
| 67 | +- cart model.updateItems by: |
| 68 | + * checkout/cart/updatePost with update_cart_action='update_qty' |
| 69 | +- quote.updateItem by: |
| 70 | + * admin/sales/order/create |
| 71 | + * advanced checkout |
| 72 | + * checkout/cart/updateItemOptions |
| 73 | + * admin/cart_product_composite_cart/update |
| 74 | + * quote repository.save via Savehandler and CartItemPersister |
| 75 | + |
| 76 | +on qty update: |
| 77 | +- quote item.setQty |
| 78 | +- event `sales_quote_item_qty_set_after` |
| 79 | +- \Magento\CatalogInventory\Observer\QuantityValidatorObserver::execute |
| 80 | +- \Magento\CatalogInventory\Model\Quote\Item\QuantityValidator::validate |
| 81 | + * all validation errors can set quote.addErrorInfo, quote item.addErrorInfo |
| 82 | + * check out of stock, parent out of stock |
| 83 | + * when there's sub products with qty options: |
| 84 | + + check qty increments |
| 85 | + + for each sub product - initializer option.initialize |
| 86 | + \Magento\CatalogInventory\Model\Quote\Item\QuantityValidator\Initializer\Option::initialize |
| 87 | + - multiply parent qty`*`sub qty, check resulting min sale qty, max sale qty, qty increments, in stock, backorders |
| 88 | + \Magento\CatalogInventory\Model\StockState::checkQuoteItemQty, |
| 89 | + \Magento\CatalogInventory\Model\StockStateProvider::checkQuoteItemQty |
| 90 | + * when no sub products qty: |
| 91 | + + initializer stock item.initialize |
| 92 | + \Magento\CatalogInventory\Model\Quote\Item\QuantityValidator\Initializer\StockItem::initialize |
| 93 | + \Magento\CatalogInventory\Model\StockState::checkQuoteItemQty |
| 94 | + \Magento\CatalogInventory\Model\StockStateProvider::checkQuoteItemQty |
| 95 | + |
| 96 | +## Add to cart |
| 97 | +cart model - deprecated. |
| 98 | + |
| 99 | +- checkout/cart/add [product, qty, related_product] |
| 100 | + * cart model.addProduct |
| 101 | + + filter request here, can register own via argument for \Magento\Checkout\Model\Cart\RequestInfoFilter |
| 102 | + + by default filtered out `form_key` and `custom_price` |
| 103 | + * quote.addProduct |
| 104 | + * product type instance.prepareForCartAdvanced |
| 105 | + * get same quote item or create new |
| 106 | + * \Magento\Quote\Model\Quote\Item\Processor::prepare |
| 107 | + + quote item.addQty |
| 108 | + + support request.customPrice -> quote item.customPrice |
| 109 | + * event `checkout_cart_product_add_after` |
| 110 | + * checkout session.setLastAddedProductId |
| 111 | + * cart.save |
| 112 | + + quote collect totals |
| 113 | + + event `checkout_cart_save_after` |
| 114 | + + reinitialize state - remove addresses and payments |
| 115 | + * event `checkout_cart_add_product_complete` |
| 116 | + |
| 117 | +- checkout/cart/updatePost |
| 118 | + * cart.suggestItemsQty => \Magento\CatalogInventory\Model\StockStateProvider::suggestQty - qty increments, min/max qty |
| 119 | + * cart.updateItems |
| 120 | + + events `checkout_cart_update_items_before`, `checkout_cart_update_items_after` |
| 121 | + + quote item.setQty -- triggers stock validation |
| 122 | + * cart.save |
| 123 | + |
| 124 | +## Describe how to customize the process of adding a product to the cart. |
| 125 | +- plugin over product type `prepareForCartAdvanced` |
| 126 | +- event `catalog_product_type_prepare_full_options` - custom options in `_prepareOptions` |
| 127 | +- plugin over \Magento\Quote\Model\Quote\Item\Processor::prepare - qty, custom price |
| 128 | +- event `checkout_cart_product_add_after` |
| 129 | + |
| 130 | +## Which different scenarios should you take into account? |
| 131 | +- add to cart from catalog |
| 132 | +- add to cart from wishlist |
| 133 | +- move all wishlist to cart |
| 134 | +- merge quote when existing customer has quote, then shops as a guest and logs in |
| 135 | +- admin create order |
| 136 | +- admin reorder |
| 137 | +- configure added product - change custom options |
0 commit comments