Skip to content

Commit c7368db

Browse files
authored
Create 2. Demonstrate ability to use totals models.md
1 parent a62d358 commit c7368db

File tree

1 file changed

+148
-0
lines changed

1 file changed

+148
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,148 @@
1+
# Demonstrate ability to use totals models
2+
3+
sales.xml
4+
```xml
5+
<section name="quote">
6+
<group name="totals">
7+
<item name="tax" instance="Magento\Tax\Model\Sales\Total\Quote\Tax" sort_order="450">
8+
<renderer name="adminhtml" instance="Magento\Sales\Block\Adminhtml\Order\Create\Totals\Tax"/>
9+
<renderer name="frontend" instance="Magento\Tax\Block\Checkout\Tax"/>
10+
</item>
11+
</group>
12+
</section>
13+
```
14+
15+
Classes:
16+
- Quote\TotalsCollector - does the job, `collect` and `collectAddressTotals`. (collectQuoteTotals not used)
17+
18+
## Quote totals
19+
- quote.collectTotals
20+
- total = totalsCollector.collect - crunch numbers, return data to set on quote
21+
* create *quote total object* quote\address\total. all you set here will be copied to quote
22+
* event `sales_quote_collect_totals_before`
23+
* collect item qtys - quote.itemsCount, quote.itemsQty, quote.virtualItemsQty
24+
* zero total object amounts - subtotal, grand total etc.
25+
* collect each *address totals*:
26+
+ *collect address totals* into new address total object
27+
- address total = quote.*collectAddressTotals* _(see below)_
28+
+ *add* to quote total object: shipping amount, shipping description, subtotal, subtotal with discount, grant total
29+
(+ base versions when applicable)
30+
* validate max grand total amount 99999999
31+
* validate coupon code - check that at least one address has it, otherwise reset to '' - code is invalid
32+
* event `sales_quote_collect_totals_after`
33+
- quote.addData(total.getData)
34+
35+
## Address totals
36+
quote.collectAddressTotals for each address (billing, shipping) - set address fields, return some fields for quote
37+
- new shipping assignment obj:
38+
+ shipping = [method, address]
39+
+ items = address items. empty for normal checkout?
40+
- create new *address total object* quote\address\total. all you set here will be copied to address
41+
- event `sales_quote_address_collect_totals_before`
42+
- get collectors:
43+
+ _initModels -> _initModelInstance -> model.processConfigArray -- tax collector can change its sort programmaticaly
44+
+ sales/totals_sort/* - admin configurable *totals retrievers* ordering - display order
45+
- *every collector[].collect*
46+
+ all data set on address total object will be copied to address. Main amounts will also copy to quote total object.
47+
+ has direct access to quote
48+
+ has access to address via shipping assignment.getShipping.getAddress
49+
- event `sales_quote_address_collect_totals_after`
50+
- address.addData(address total.getData)
51+
52+
## Display totals
53+
Totals rendered in cart in UI-component fashion with JS configuration.
54+
55+
Totals JS models extend `Magento_Checkout/js/view/summary/abstract-total` and implement:
56+
- getPureValue - raw float
57+
- getValue - formatted via `Magento_Catalog/js/price-utils` in format `window.checkoutConfig.priceFormat`.
58+
59+
Models get their values from model quote.getTotals(), e.g. `quote.getTotals()().subtotal`.
60+
Initial totals values are in `window.checkoutConfig.totalsData`, any extended attributes are merged into main totals.
61+
62+
`window.checkoutConfig` values are provided by `\Magento\Checkout\Model\CompositeConfigProvider`.
63+
Default config provider `\Magento\Checkout\Model\DefaultConfigProvider`.
64+
Register your classes via arguments.
65+
66+
Default config provider.getTotalsData and REST API reuse same repository.
67+
\Magento\Quote\Model\Cart\CartTotalRepository::get:
68+
- billing or shipping address.getTotals
69+
* \Magento\Quote\Model\Quote\TotalsReader::fetch
70+
* each collector[].*fetch*(quote, data)
71+
+ can return \Magento\Quote\Model\Quote\Address\Total or array [code, title, value]
72+
+ title can be object with method *render()* - by default this is just __ Phrase translation
73+
+ can return multiple totals as once
74+
+ can overwrite other totals by code
75+
- convert address data to interface Cart\Totals - totals by code + quote visible items
76+
- *totals segments* - totals by code as return from fetch:
77+
* \Magento\Quote\Model\Cart\TotalsConverter::process - convert address totals to total segment
78+
* title = titleRenderer.render
79+
- add other info - coupon code, grand total, items, items qty, currency code
80+
81+
js model quote.getTotals:
82+
```
83+
[
84+
{address data fields = populate \Magento\Quote\Api\Data\TotalsInterface with address.getData},
85+
items = quote visible items,
86+
total_segments = as returned from totals collector.fetch
87+
]
88+
```
89+
90+
## Invoice totals, credit memo totals
91+
```xml
92+
<section name="order_invoice">
93+
<group name="totals">
94+
<item name="subtotal" instance="Magento\Sales\Model\Order\Invoice\Total\Subtotal" sort_order="50"/>
95+
</group>
96+
</section>
97+
<section name="order_creditmemo">
98+
<group name="totals">
99+
<item name="subtotal" instance="Magento\Sales\Model\Order\Creditmemo\Total\Subtotal" sort_order="50"/>
100+
</group>
101+
</section>
102+
```
103+
104+
Invoice totals:
105+
- \Magento\Sales\Model\Order\Invoice::collectTotals
106+
- every total - \Magento\Sales\Model\Order\Invoice\Total\AbstractTotal::collect(invoice)
107+
+ directly update invoice object
108+
109+
Credit memo totals:
110+
- \Magento\Sales\Model\Order\Creditmemo::collectTotals
111+
- every total - \Magento\Sales\Model\Order\Creditmemo\Total\AbstractTotal::collect
112+
+ directly update credit memo object
113+
114+
## Render totals in admin area:
115+
Example - admin invoice totals:
116+
117+
handle `sales_order_invoice_view`:
118+
```xml
119+
<block class="Magento\Sales\Block\Adminhtml\Order\Invoice\Totals" name="invoice_totals" template="Magento_Sales::order/totals.phtml">
120+
```
121+
122+
- block totals.`_beforeToHtml`
123+
- block order totals.`_initTotals` - add hardcoded totals - subtotal, shipping, discount, grand_total, base_grandtotal
124+
- every child block.initTotals
125+
- child blocks call block order totals.addTotal(total, after={'first'|'last'|$code}) or addTotalBefore(total, before)
126+
+ total = DataObject [code, value, base_value, label, optional: {area, block_name, is_formated, strong}]
127+
- block order totals template
128+
+ totals with area = 'footer'
129+
+ totals with empty area
130+
+ if 'block_name', getChildHtml - simply renders child block
131+
+ otherwise print [label, value], value will be price formated unless flag 'is_formated'
132+
133+
134+
## Describe how to modify the price calculation process in the shopping cart.
135+
- when preparing product in product type model, can set `product.custom_price`
136+
- register quote totals collector in sales.xml. Edit given address_total.
137+
Examples:
138+
* `$total->setGrandTotal($total->getGrandTotal() - $pointsCurrencyAmountUsed);`
139+
* call `$total->addTotalAmount(code, value)`. Grand total will then be sum of all total amounts - they can be negative.
140+
141+
## How can you add a custom totals model or modify existing totals models?
142+
- add quote totals collector - declare in sales.xml, implement `collect` and `fetch`
143+
+ in collect can modify address totals object (preferred), or edit directly quote or quote address via shipping assignment
144+
+ fetch can return null, or one or many declarations in array format or ready Address\Total objects
145+
+ fetch can rewrite other totals with same 'code'
146+
+ in cart block JS config, add view model and implement getPureValue, getValue. Can read values from model quote.getTotals().totals_segments
147+
- Render totals in admin:
148+
+ sales_invoice_view, referenceBlock 'invoice_totals', add block with method `initTotals`, call parentBlock.`addTotal`

0 commit comments

Comments
 (0)