# Dev note

# Dev notes

8/15/24: Latest js code for usps address validation:

Library: app/code/Frans/CheckoutViews/view/frontend/web/js/addrval.js  
Using the above library: app/code/Frans/CheckoutViews/view/frontend/web/js/view/shipping.js

8/14/24:

app/code/Frans/MultiShip/view/adminhtml/web/js/quoteaddress/uspsvalidation.js

8/11/24: Latest js code for uspsvalidation:

Frans/MultiShip/view/adminhtml/web/js/quoteaddress/uspsvalidation.js  
design/frontend/Frans/default/Magento\_Multishipping/web/js/billing-address-validation.js

# Magento dev tricks and tips

##### 1/ To debug email sending code:

  
For example, when placing an order in FrontEnd; the order immediately gets marked as processed; and the quote is cleared. In order to debug sending email:

in file `vendor/magento/module-checkout/Controller/Onepage/Success.php`, disable this code: `$session-&gt;clearQuote();`

##### 2/ Store object in memory per session

There is a deprecated technique still being used in Magento: use registry to store objects in memory.  
Example:

```
$this->registry->unregister('current_creditmemo');<br></br>$this->registry->register('current_creditmemo', $creditmemo);
```

# PHP files and XML files to edit

\- Shipment grid:  
  
code/Frans/CustomOrderGridExport/Rewrite/Framework/View/Element/UiComponent/DataProvider/FilterPool.php  
code/Frans/OrderProcessing/Model/ResourceModel/Shipment/Grid/CollectionShipment.php  
code/Frans/OrderProcessing/view/adminhtml/ui\_component/sales\_order\_shipment\_grid.xml  
Custom columns, such as code/Frans/OrderProcessing/Ui/Component/Listing/Column/Shipment/InvoiceNumber.php

# Coding guidelines

- JavaScript: do NOT translate text!  
    Instead of  
     $.mage.\_\_('Attention')  
      
    just use   
     `Attention`  
      
    Frans is an English-only website for now.
- Don't use `INNER JOIN`  
    Use `JOIN`. Keep it simple. `INNER JOIN` is the same as `JOIN`  
    Don't use `LEFT OUTER JOIN`  
    Just use `LEFT JOIN`. Keep it simple. `LEFT OUTER JOIN` is the same as `LEFT JOIN`
- Table design, ID column:  
    Every table must have int identity unsigned pk column, named `id`  
    ```
    <table name="frans_stripe_reauth_log" resource="default" engine="innodb" comment="Stripe Reauthorization Logs">
        <column xsi:type="int" name="id" padding="10" unsigned="true" nullable="false" identity="true" comment="ID"/>
    ```
    
    Keep column name simple. Instead of log\_id, order\_item\_id, just name the column `id`. The table name already tells if it's a log or an order\_item. No need to repeat that in the column name.
- Table design text column:

Try not to use `**text**` column; because it affects performance. Use **varchar**() with a limit instead. Only use `text` column if it's really necessary, such as storing raw shipping label data, raw image data..

- For SQL statement, when using GROUP\_CONCAT it's highly recommended to use | as separator. Because by default, most database use comma as a separator. When raw data is used for csv output; column cannot contain comma.   
    For example, instead of   
    SELECT GROUP\_CONCAT(order\_id) -- which yield 3,5,7 -&gt; breaks the CSV download  
    we should do  
    SLECT GROUP\_CONCAT(order\_id SEPARATOR '|') -- which yields 3|5|7 -&gt; does not break for the CSV download
- For SQL statements, do NOT put column on its own line like this  
    ```
    SELECT
        qa_id,
        MAX(invoice_item_id) AS example_invoice_item_id,
        MAX(invoice_id) AS invoice_id,
        MAX(si_num) AS si_num,
    ```
    
    because it takes forever to scroll up and down.  
      
    Write columns on the same line like this:  
    ```
    SELECT
        qa_id, MAX(invoice_item_id) AS example_invoice_item_id, MAX(invoice_id) AS invoice_id, MAX(si_num) AS si_num,
    ```
- SQL CASE:

For simple IF/ELSE, do NOT use CASE like this

```
CASE WHEN soi.product_notes IS NULL OR soi.product_notes = '' THEN NULL ELSE soi.product_notes END
```

Instead, is IF (if MSSQL, use IIF):

```
IF(soi.product_notes IS NULL OR soi.product_notes = '',NULL,soi.product_notes)
```

Only use CASE WHEN if there are more than one if/else branches.

- To check if a value exists, use if ($value !== null)  
    Do not use if ($value)  
    because when $value is zero, if ($value) does not pass.  
    Example code:  
      
     if($quote-&gt;getIsMultiShipping() &amp;&amp; **$quoteItem-&gt;getCustomPrice()**) {  
     $item-&gt;setPrice($quoteItem-&gt;getCustomPrice())-&gt;setBaseOriginalPrice($quoteItem-&gt;getCustomPrice());  
      
    This code is wrong. When customPrice is zero (no-charge), this if statement does not pass.  
      
    Rewrite it to this:  
      
     if($quote-&gt;getIsMultiShipping() &amp;&amp; (**$quoteItem-&gt;getCustomPrice() !== null**)) {  
     $item-&gt;setPrice($quoteItem-&gt;getCustomPrice())-&gt;setBaseOriginalPrice($quoteItem-&gt;getCustomPrice());  
      
    now, if customPrice is zero, this if statement passes
- Class overriding/extending  
    When overriding or extending a class; make sure to document at the top of the PHP/Javascript file. For example:

`<?php/** * Frans overrides Techgroup\UspsValidation\Controller\Index\Address */`  
  
\- Javascript  
  
Each function must have documentation explaining its purpose, and one or a few usage example(s)

`/** * Frans Address Validation module for BE * 2024/09/02 Brian created * Usage: define('addrval', addrVal) *  addrVal.validateAddress */define([    'jquery',    'ko',    'Magento_Ui/js/form/form',    'Magento_Ui/js/modal/modal',    'Frans_Framework/frans/framework/axios.min',], function ($, ko, Component, modal, axios) {    'use strict';`

\- <span style="text-decoration: underline;">**Branching rules:**</span>  
When you work on a task, such as S1234, create a branch with the same name, such as branch s1234  
For example, task [https://plan.socalappsolutions.com/view.php?id=S1904p4](https://plan.socalappsolutions.com/view.php?id=S1904p4) --&gt; branch name = s1904p4  
Notice that git does not work well if we name the branch with numbers only; so do NOT name it with numbers only, such as `1904`. Sometimes it works, sometimes git will throw an error because it thinks 1904 is a commit sha, not a branch name.

Make sure branches are lowercase, not uppercase. For example, branch name = s1904, not **S**1904

\- PHP code to get table name: no need to call functions to get table name, just use string literal. Instead of

```
resourceConnection->getTableName('frans_order');
```

Just type ‘frans\_order’

# Dev bulletin 11/15

Currently there's a difference between FE and BE MS orders:

- for FE MS orders, the sales-ship-item stores product id of configurable-product; and store the SKU of the simple-product.
- for BE MS orders, the sales-ship-item stores product id of simple-product; and store SKU of the simple-product  
      
    Example: right is front-end, left is back-end. Same product orders; but data stored differently in database

[![image.png](https://frdocs.socalappsolutions.com/uploads/images/gallery/2025-11/scaled-1680-/image.png)](https://frdocs.socalappsolutions.com/uploads/images/gallery/2025-11/image.png)

To address this difference; in reports; we currently need to UNION two queries. For example, ItemsOnOrderByItem: app/code/Frans/AdminReport/Controller/Adminhtml/Action/ItemsOrdByItemCsv.php

Query:

> \# First set, pull from configurable prod. Because FE MS orders has sales\_shipment\_item storing prod-id of CONFIGURABLE PROD, we need to union this set. In the  
> \# future we might want to rewrite either FE or BE to make sure they are consistent  
> SELECT  
> \# ,ss.entity\_id,o.updated\_at, o.entity\_id,ssi.product\_id  
> max(ssi.parent\_id) example\_shipment\_id,max(ssi.product\_id) example\_product\_id  
> ,ssi.sku as prod\_sku,max(ce\_vc.value) as product\_name # 9/27  
>  ,max(aovcolor.value) color\_title  
>  ,sum(ssi.qty) quantity #9/27 pull qty from configurable prod
> 
> FROM sales\_shipment\_item ssi  
> JOIN catalog\_product\_entity pconf ON pconf.entity\_id=ssi.product\_id AND pconf.type\_id ='configurable'
> 
> UNION  
> \## Second set, pull from simple prod  
> SELECT  
> \# ,ss.entity\_id,o.updated\_at, o.entity\_id,ssi.product\_id  
> max(ssi.parent\_id) example\_shipment\_id,max(ssi.product\_id) example\_product\_id  
> ,ssi.sku as prod\_sku,max(ce\_vc.value) as product\_name # 9/27  
>  ,max(aovcolor.value) color\_title  
>  ,sum(COALESCE(ssi\_conf.qty,ssi.qty)) quantity #9/27 pull qty from configurable prod, if any
> 
> FROM sales\_shipment\_item ssi  
> JOIN catalog\_product\_entity psimp ON psimp.entity\_id=ssi.product\_id AND psimp.type\_id ='simple'

Because FE MS orders has sales\_shipment\_item storing prod-id of CONFIGURABLE PROD, we need to union. In the future we might want to rewrite either FE or BE to make sure they are consistent.

# Coding Suggestions

Here are suggestions when coding. These are less strict than [coding-guidelines](https://frdocs.socalappsolutions.com/books/dev-note/page/coding-guidelines).

1/ SQL select performance:

- If possible, always specify the list of columns you want to select. For example:

```mysql
$this->connection->select()
    ->from($mainTable, ['id'])
    ->where('ent_type = ?', 'shipment')
    ->columns('id')    // ONLY id is needed
    ->order('id DESC')
    ->limit(1)
```

In the above example; since we only care about the count of rows; we only need to specify columns('id')   
There is a big difference from querying 10 columns versus querying 2 columns.

# Frans Extensions

- AddressValidation: app/code/Frans/AddressValidation

Config values:

[![image.png](https://frdocs.socalappsolutions.com/uploads/images/gallery/2026-05/scaled-1680-/image.png)](https://frdocs.socalappsolutions.com/uploads/images/gallery/2026-05/image.png)