# Magento Frequently Asked Questions [TOC] ## Development ### Load-order-by-increment-id-using-Object-Method-in-magento2 Sometime you need to load order record in phtml file. Not recommended method to use in magento2 but so magento use it so here it is just for knowledge. ```php $orderIncrementId=10000003; $objectManager = \Magento\Framework\App\ObjectManager::getInstance(); $orderInfo = $objectManager->create('Magento\Sales\Model\Order')->loadByIncrementId($orderIncrementId); ``` 1. Factory Method: Best practice method always use this method ```php namespace QaisarSatti\Module\Block; class Product extends \Magento\Framework\View\Element\Template { protected $orderFactory; public function __construct( \Magento\Sales\Model\OrderFactory $orderFactory, ) { $this->orderFactory = $orderFactory; } public function getOrderByIncrementId(){ $orderIncrementId = 10000003; $order = $this->orderFactory->create()->loadByIncrementId($orderIncrementId); } } ``` 2. Api Repository: This was introduce in Magento 2.1 by magento. ```php namespace QaisarSatti\Module\Block; use Magento\Catalog\Api\ProductRepositoryInterface; class Product extends \Magento\Framework\View\Element\Template { protected $order; public function __construct( \Magento\Sales\Api\Data\OrderInterface $order, ) { $this->order = $order; } public function getOrderByIncrementId(){ $orderIncrementId = 10000003; $order = $this->order->loadByIncrementId($orderIncrementId); } } ``` ### Magento:Quote-vs-Cart The cart model is an abstraction for the quote (or better: for the items in the cart) and you should use it wherever possible. Working with the quote object directly when it comes to adding, removing and changing items is complicated and almost never necessary. From: [Magento: Quote vs Cart](https://magento.stackexchange.com/questions/107593/magento-quote-vs-cart) ### Get-current-order-ID-magento-2 ```php protected $_checkoutSession; public function __construct( ..... \Magento\Checkout\Model\Session $checkoutSession, ..... ) { $this->_checkoutSession = $checkoutSession; } ..... $order = $this->_checkoutSession->getLastRealOrder(); $orderId=$order->getIncrementId(); //$this->_checkoutSession->getLastRealOrderId() $order->getEntityId(); ``` #### Entity_Id-vs-Increment-Id Entity Id (entity_id column name in table) is the primary key which is used for the table to keep unique id per row and its auto-increment so when a new row is generated/inserted automatically generate latest id. Increment id (increment_id column name in table) is for Order purpose. It's used for order fetching/display information of a specific order based on the increment id. Increment ID is also used for third party API to connect order related stuff to another platform. You can also change the default behavior of Increment id as per your requirement. Like 000000001 to T000000001. >`getLastRealOrderId` => the increment ID (the order # shown to a customer after checkout. >`getLastOrderId` => the entity ID of the order in the database. Background The method getLastRealOrderId are magic methods, meaning they're getters for the properties last_real_order_id and last_order_id. They are set on the checkout session during a successful order placement by Mage_Checkout_Model_Onepage::saveOrder. The two data properties are set in tandem once the order is successful. - getLastRealOrderId was introduced in Magento 1.8 CE on the checkout session along with the previously available getLastOrderId because it would require another model load (e.g. another database query) get get the increment id, which is usually what you want, if you wanted access to that information to display on the site or use in code. By setting it on the checkout session directly, when it's available, after a successful order they prevent a developer from writing code which may adversely affect performance. ### Get-order-details-from-order-object ```php $orderId = 1222; $order = $this->getOrderById($orderId); /*get customer details*/ $custLastName= $order->getCustomerLastname(); $custFirsrName= $order->getCustomerFirstname(); $ipaddress=$order->getRemoteIp(); $customer_email=$order->getCustomerEmail(); $customerid=$order->getCustomerId(); /* get Billing details */ $billingaddress=$order->getBillingAddress(); $billingcity=$billingaddress->getCity(); $billingstreet=$billingaddress->getStreet(); $billingpostcode=$billingaddress->getPostcode(); $billingtelephone=$billingaddress->getTelephone(); $billingstate_code=$billingaddress->getRegionCode(); /* get shipping details */ $shippingaddress=$order->getShippingAddress(); $shippingcity=$shippingaddress->getCity(); $shippingstreet=$shippingaddress->getStreet(); $shippingpostcode=$shippingaddress->getPostcode(); $shippingtelephone=$shippingaddress->getTelephone(); $shippingstate_code=$shippingaddress->getRegionCode(); /* get total */ $tax_amount=$order->getTaxAmount(); $total=$order->getGrandTotal(); /* get order status*/ $status=$order->getStatus(); ``` ### Magento-2-Events Read [Magento-2-Events](https://www.mageplaza.com/magento-2-module-development/magento-2-events.html#event-area) and [An Introduction To Magento 2 Events and Observers](https://www.cloudways.com/blog/magento-2-events-observers/) ### Magento2-Correct-Way-to-get-Order-items This is how the different methods to get items from an order work: getItems(): returns array of items from loaded order item collection getAllItems(): returns array of all items that are not marked as deleted getAllVisibleItems(): returns array of all items that are not marked as deleted and do not have a parent item So to get only the configurable product and not its associated product, getAllVisibleItems() is the correct method: the single simple item does not have a parent => visible the configurable item does not have a parent => visible the associated simple item has a parent => not visible Note that unfortunately, as of magento-2.0 only getItems() is part of the service contract in Magento\Sales\Api\Data\OrderInterface Read [Magento2 Correct Way to get Order items](https://magento.stackexchange.com/questions/111112/magento2-correct-way-to-get-order-items) ### Update Order status programmatically ```php use Magento\Sales\Model\Order; $orderId = 1; $objectManager = \Magento\Framework\App\ObjectManager::getInstance(); $order = $objectManager->create('\Magento\Sales\Model\Order') ->load($orderId); $orderState = Order::STATE_PROCESSING; $order->setState($orderState)->setStatus(Order::STATE_PROCESSING); $order->save(); ``` Reference: [Magento 2: How to update order status programmatically in custom module?](https://magento.stackexchange.com/questions/164600/magento-2-how-to-update-order-status-programmatically-in-custom-module) ### How to programmatically create transaction in Magento2 ```php public function createTransaction($order = null, $paymentData = array()) { try { //get payment object from order object $payment = $order->getPayment(); $payment->setLastTransId($paymentData['id']); $payment->setTransactionId($paymentData['id']); $payment->setAdditionalInformation( [\Magento\Sales\Model\Order\Payment\Transaction::RAW_DETAILS => (array) $paymentData] ); $formatedPrice = $order->getBaseCurrency()->formatTxt( $order->getGrandTotal() ); $message = __('The authorized amount is %1.', $formatedPrice); //get the object of builder class $trans = $this->_transactionBuilder; $transaction = $trans->setPayment($payment) ->setOrder($order) ->setTransactionId($paymentData['id']) ->setAdditionalInformation( [\Magento\Sales\Model\Order\Payment\Transaction::RAW_DETAILS => (array) $paymentData] ) ->setFailSafe(true) //build method creates the transaction and returns the object ->build(\Magento\Sales\Model\Order\Payment\Transaction::TYPE_CAPTURE); $payment->addTransactionCommentsToOrder( $transaction, $message ); $payment->setParentTransactionId(null); $payment->save(); $order->save(); return $transaction->save()->getTransactionId(); } catch (Exception $e) { //log errors here } } ``` `paymentData` must be an `array of string`, e.g. `["abc" => "cde", ...]` Reference: [How to programmatically create transaction in Magento2](https://webkul.com/blog/create-payment-transaction-in-magento2/) ### How to get all the items using the order id in magento2 ```php public function getAllItems() { $objectManager = \Magento\Framework\App\ObjectManager::getInstance(); $order = $objectManager->create('Magento\Sales\Model\Order')->loadByIncrementId(000000014); $orderItems = $order->getAllItems(); $itemQty = array(); foreach ($orderItems as $item) { $itemQty[]=array('quantity'=>$item->getQtyOrdered(),'description'=>$item->getDescription(),'name'=>$item->getName(),'price'=>$item->getPrice()); } return $itemQty; } ``` Referenec: [How to get all the items using the order id in magento2](https://magento.stackexchange.com/questions/201651/how-to-get-all-the-items-using-the-order-id-in-magento2) ### How to programmatically create invoice in magento2 >Create invoice for a new order ```php <?php /** * Webkul Software. * * @category Webkul * @package Webkul_Grid * @author Webkul * @copyright Copyright (c) 2010-2016 Webkul Software Private Limited (https://webkul.com) * @license https://store.webkul.com/license.html */ namespace Webkul\Grid\Controller; class CreateInvoice extends Magento\Framework\App\Action\Action { /** * @var \Magento\Sales\Api\OrderRepositoryInterface */ protected $_orderRepository; /** * @var \Magento\Sales\Model\Service\InvoiceService */ protected $_invoiceService; /** * @var \Magento\Framework\DB\Transaction */ protected $_transaction; public function __construct( \Magento\Framework\App\Action\Context $context, \Magento\Sales\Api\OrderRepositoryInterface $orderRepository, \Magento\Sales\Model\Service\InvoiceService $invoiceService, \Magento\Framework\DB\Transaction $transaction ) { $this->_orderRepository = $orderRepository; $this->_invoiceService = $invoiceService; $this->_transaction = $transaction; parent::__construct($context); } /** * Marketplace order invoice controller. * * @return \Magento\Framework\View\Result\Page */ public function execute() { $orderId = 1; //order id for which want to create invoice $order = $this->_orderRepository->get($orderId); if($order->canInvoice()) { $invoice = $this->_invoiceService->prepareInvoice($order); $invoice->register(); $invoice->save(); $transactionSave = $this->_transaction->addObject( $invoice )->addObject( $invoice->getOrder() ); $transactionSave->save(); $this->invoiceSender->send($invoice); //send notification code $order->addStatusHistoryComment( __('Notified customer about invoice #%1.', $invoice->getId()) ) ->setIsCustomerNotified(true) ->save(); } } } ``` > Create invoice for a part of order ```php <?php /** * Webkul Software. * * @category Webkul * @package Webkul_Grid * @author Webkul * @copyright Copyright (c) 2010-2016 Webkul Software Private Limited (https://webkul.com) * @license https://store.webkul.com/license.html */ namespace Webkul\Grid\Controller; class CreateInvoice extends Magento\Framework\App\Action\Action { /** * @var \Magento\Sales\Api\OrderRepositoryInterface */ protected $_orderRepository; /** * @var \Magento\Sales\Model\Service\InvoiceService */ protected $_invoiceService; /** * @var \Magento\Framework\DB\Transaction */ protected $_transaction; public function __construct( \Magento\Framework\App\Action\Context $context, \Magento\Sales\Api\OrderRepositoryInterface $orderRepository, \Magento\Sales\Model\Service\InvoiceService $invoiceService, \Magento\Framework\DB\Transaction $transaction ) { $this->_orderRepository = $orderRepository; $this->_invoiceService = $invoiceService; $this->_transaction = $transaction; parent::__construct($context); } /** * Marketplace order invoice controller. * * @return \Magento\Framework\View\Result\Page */ public function execute() { $orderId = 1; //order id for which want to create invoice $order = $this->_orderRepository->get($orderId); if($order->canInvoice()) { $itemsArray = ['80'=>2]; //here 80 is order item id and 2 is it's quantity to be invoice $shippingAmount = '10.00'; $subTotal = '110.00'; $baseSubtotal = '110.00'; $grandTotal = '110.00'; $baseGrandTotal = '110.00'; $invoice = $this->_invoiceService->prepareInvoice($order, $itemsArray); $invoice->setShippingAmount($shippingAmount); $invoice->setSubtotal($subTotal); $invoice->setBaseSubtotal($baseSubtotal); $invoice->setGrandTotal($grandTotal); $invoice->setBaseGrandTotal($baseGrandTotal); $invoice->register(); $transactionSave = $this->_transaction->addObject( $invoice )->addObject( $invoice->getOrder() ); $transactionSave->save(); $this->invoiceSender->send($invoice); //send notification code $order->addStatusHistoryComment( __('Notified customer about invoice #%1.', $invoice->getId()) ) ->setIsCustomerNotified(true) ->save(); } } } ``` Reference: [How to programmatically create invoice in magento2](https://webkul.com/blog/how-to-programmatically-create-invoice-in-magento2/) ### Overriding Block, Model Create di.xml file in `app/code/[Name_Space]/[Your_Module]/etc` For example: ```xml <?xml version="1.0"?> <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd"> <preference for="Magento\Catalog\Block\Product\ListProduct" type="[Name_Space]\[Your_Module]\Block\Rewrite\Product\ListProduct" /> </config> ``` then create block file: ```php <?php namespace [Name_Space]\[Your_Module]\Block\Rewrite\Product; class ListProduct extends \Magento\Catalog\Block\Product\ListProduct { public function _getProductCollection() { } } ``` Reference: [Overriding Block, Model In Magento 2 – Magento 2.3](https://www.magestore.com/magento-2-tutorial/overriding-block-model-in-magento2/) ### Payment workflow Reference: [How to post data to a payment provider when placing an order in Magento 2](https://magento.stackexchange.com/questions/208834/how-to-post-data-to-a-payment-provider-when-placing-an-order-in-magento-2 ### Magento 2 get Parameters in URL ```php <?php ... protected $request; public function __construct( \Magento\Framework\App\Request\Http $request, ....//rest of parameters here ) { $this->request = $request; ...//rest of constructor here } public function getIddata() { // use $this->request->getParams(); // all params return $this->request->getParam('id'); } ``` ```php <?php namespace Namespace\Module\Something; class ClassName { protected $request; public function __construct( \Magento\Framework\App\RequestInterface $request ....//rest of parameters here ) { $this->request = $request; ...//rest of constructor here } public function getPost() { return $this->request->getPostValue();//in Magento 2.* } } ``` ## Sales ### Order_Workflow **Order Workflow** When a customer places an order, a sales order is created as a temporary record of the transaction. In the Orders grid, sales orders initially have a status of “Pending,” and can be canceled at any time until the payment is processed. After payment is confirmed, the order can be invoiced and shipped. **Step 1: Place Order** The checkout process begins when the shopper clicks the Go to Checkout button on the shopping cart page or reorders directly from their customer account. **Step 2: Order Pending** In the Orders grid, the status of the sales order is initially Pending. Payment has not been processed, and the order can still be edited or canceled. **Step 3: Receive Payment** The status of the order changes to Processing when payment is received or authorized. Depending on the payment method, you might receive notification when the transaction is authorized or processed. **Step 4: Invoice Order** An order is typically invoiced after payment is received. Some payment methods generate an invoice automatically when payment is authorized and captured. The payment method determines which invoicing options are needed for the order. After the invoice is generated and submitted, a copy is sent to the customer. **Step 5: Book a Single Shipment** When the shipment detail is complete, the shipment is booked, and the packing slip and shipping label are printed. The customer receives notification, and the package is shipped. If tracking numbers are used, the shipment can be tracked from the customer’s account. Book a Batch of Shipments (Magento Shipping only) Enter and process the shipment information for multiple orders as a batch. **Step 6: Create a Dispatch** (Magento Shipping only) Create a dispatch that lists the packages that are ready for pickup and print the manifest. Reference: [Order Workflow](https://docs.magento.com/m2/ce/user_guide/sales/order-workflow.html [Manage Magento 2 Order Status - Magento 2.3](https://www.magestore.com/magento-2-tutorial/manage-order-status-in-magento-2/) [Magento 2 New Order Status remains “Processing” instead of “Pending” in custom payment method](https://magento.stackexchange.com/questions/150058/magento-2-new-order-status-remains-processing-instead-of-pending-in-custom-p) ## Server-settings ### Change-Servername 1. `sudo nano /etc/apache2/apache2.conf` 2. Add this line `ServerName <server_IP Or domain name>` at the end of the file, then save and exit 3. `sudo apache2ctl configtest` for checking the syntax 4. `sudo a2enmod rewrite` for enable rewrite module 5. `sudo systemctl restart apache2` for restart apache2 6. Update magento base url if you have domain name 1. Go to the Magento’s root directory, then type within the console: `php bin/magento setup:store-config:set --base-url="<new base-url>"` 2. Also you may change for https: `php bin/magento setup:store-config:set --base-url-secure="<new base-url-secure>"` 3. Clear the cache:`php bin/magento cache:flush` ### Magento-2-admin-page-has-a-redirect-loop-after-changing-the-domain-name Run `bin/magento config:set web/secure/use_in_adminhtml 1` and `bin/magento config:set web/secure/use_in_frontend 1` in directory root ## Useful Resource 1. [magento/magento2-samples/sample-module-payment-gateway](https://github.com/magento/magento2-samples/tree/master/sample-module-payment-gateway) 2. [Payments Integrations](https://devdocs.magento.com/guides/v2.3/payments-integrations/bk-payments-integrations.html)