Back end - letronghieu4897/magento GitHub Wiki
- 1. Install Database or Schema
- 2. Cron Job
-
3. Collection
- 3.1 Create Collection
- 3.2 Using Factory
-
4. Get Data
- 4.1 From Admin Field
- 5. Extension template path hints
-
6. Controller
- 6.1 Redirect to other page
- 7. Get data response and request
- 8. Session
- 9. Payment Redirect to Third Party Page
- 10. Upgrade Schema to insert new column into existing table
- 11. Flow change status Order Magento 2
- 12. Create Constructor when Extend Class
- 13. Show Refund in Invoice
- 14. Working with Order and Payment
- 15. Travelling to find Controller XML
- 16. Plugin Preference to rewrite Block Model Controller Helper
- 17. PHP function
- 18. Get data of Order use Qoute on JS
- 19. Di.xml dependency injection
- 20. Add Payment information into admin order
- 21. Clear all discount price
- 22. Add new products using tools
- 23. Install VIPPS
- 24. Export Data
- 25. getInstance
- 26. get values of product attributes
- 27. Write javascript in phtml and using php variable
- 28. Get data from table with multiple select on admin by ConfigProvider
- 29. Get value product attribute select box of current product
- app/code/[Vendor]/[Extention]/Setup
- Create file : InstallData.php
- Create Schema or Insert New Column : InstallSchema.php
<?php
namespace Netpower\Ghn\Setup;
use \Magento\Framework\Setup\InstallSchemaInterface;
use \Magento\Framework\Setup\SchemaSetupInterface;
use \Magento\Framework\Setup\ModuleContextInterface;
use \Magento\Framework\DB\Ddl\Table;
class InstallSchema implements InstallSchemaInterface
{
public function install(SchemaSetupInterface $setup,ModuleContextInterface $context)
{
$installer = $setup;
$installer->startSetup();
if (!$installer->tableExists('[table_name]')) {
$table = $installer->getConnection()->newTable(
$installer->getTable('[table_name]')
)
->addColumn(
'district_id',
Table::TYPE_INTEGER,
null,
[
'identity' => true,
'nullable' => false,
'primary' => true,
'unsigned' => true,
],
'District ID'
)->addColumn(
'name',
Table::TYPE_TEXT,
null,
['nullable' => false],
'District Name'
)->addColumn(
'region_id',
Table::TYPE_INTEGER,
null,
['nullable' => false,
'unsigned' => true,
],
'Region ID'
)->addColumn(
'province_id',
Table::TYPE_INTEGER,
null,
['nullable' => false],
'Province ID'
)->addColumn(
'district_number',
Table::TYPE_INTEGER,
null,
['nullable' => false],
'District Number'
)->addForeignKey(
$installer->getFkName('[table_name]', 'region_id', '[table_name (foreign key) ]', 'region_id'),
'region_id',
$installer->getTable('directory_country_region'),
'region_id',
Table::ACTION_CASCADE
);
$installer->getConnection()->createTable($table);
}
}
}
- Go into Database. Search setup_module then DROP it.
- [YOU SHOULD Delete only Module you want to upgrade or install in setup_module table]
- [DELETE FROM setup_module WHERE module="<Name_Module>"]
- Go to Server : php bin/magento setup:upgrade
$ CRON JOB
. _______________________________________________________________________
├── etc
│ └── crontab.xml
├── Cron
│ └── FileName.php
. ________________________________________________________________________
<?xml version="1.0" ?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Cron:etc/crontab.xsd">
<group id="default">
<job instance="[Vendor]\[Extention]\Cron\FileName" method="execute" name="netpower_ghn_cron">
<schedule>* * * * *</schedule>
</job>
</group>
</config>
* * * * * *
| | | | | |
| | | | | +-- Year (range: 1900-3000)
| | | | +---- Day of the Week (range: 1-7, 1 standing for Monday)
| | | +------ Month of the Year (range: 1-12)
| | +-------- Day of the Month (range: 1-31)
| +---------- Hour (range: 0-23)
+------------ Minute (range: 0-59)
* * * * * * Each minute
59 23 31 12 5 * One minute before the end of year if the last day of the year is Friday
59 23 31 DEC Fri * Same as above (different notation)
45 17 7 6 * * Every year, on June 7th at 17:45
45 17 7 6 * 2001,2002 Once a year, on June 7th at 17:45, if the year is 2001 or 2002
0,15,30,45 0,6,12,18 1,15,31 * 1-5 * At 00:00, 00:15, 00:30, 00:45, 06:00, 06:15, 06:30,
06:45, 12:00, 12:15, 12:30, 12:45, 18:00, 18:15,
18:30, 18:45, on 1st, 15th or 31st of each month, but not on weekends
*/15 */6 1,15,31 * 1-5 * Same as above (different notation)
0 12 * * 1-5 * (0 12 * * Mon-Fri *) At midday on weekdays
* * * 1,3,5,7,9,11 * * Each minute in January, March, May, July, September, and November
1,2,3,5,20-25,30-35,59 23 31 12 * * On the last day of year, at 23:01, 23:02, 23:03, 23:05,
23:20, 23:21, 23:22, 23:23, 23:24, 23:25, 23:30,
23:31, 23:32, 23:33, 23:34, 23:35, 23:59
0 9 1-7 * 1 * First Monday of each month, at 9 a.m.
0 0 1 * * * At midnight, on the first day of each month
* 0-11 * * * Each minute before midday
* * * 1,2,3 * * Each minute in January, February or March
* * * Jan,Feb,Mar * * Same as above (different notation)
0 0 * * * * Daily at midnight
0 0 * * 3 * Each Wednesday at midnight
<?php
namespace [Vendor]\[Extention]\Cron;
class Test
{
public function __construct()
{}
public function execute()
{
//CODE HERE
}
}
$ crontab -e
#~ MAGENTO START
* * * * * /usr/bin/php /var/www/html/[Source Magento]/bin/magento cron:run | grep -v Ran jobs by schedule >> /var/www/html/[Source Magento]/var/log/magento.cron.log
* * * * * /usr/bin/php /var/www/html/[Source Magento]/update/cron.php >> /var/www/html/[Source Magento]/var/log/update.cron.log
* * * * * /usr/bin/php /var/www/html/[Source Magento]/bin/magento setup:cron:run >> /var/www/html/[Source Magento]/var/log/setup.cron.log
#~ MAGENTO END:
$ php bin/magento cache:flush
$ php bin/magento cron:run --group="default"
//"default" is group declared in crontab.xml
$ crontab -e
$ php bin/magento cache:flush
$ php bin/magento cron:run --group="default"
mysql> SELECT * FROM cron_schedule WHERE status = 'running';
$ COLLECTION
. _______________________________________________________________________
├── Model
| ├── GhnOrder.php [1]
| └── ResourceModel
| ├── GhnOrder.php [2]
| └── GhnOrder
| └── Collection.php [3]
|
. ________________________________________________________________________
- [1] \app\code[Vendor][Extention]\Model\GhnOrder.php
<?php
namespace [Vendor]\[Extention]\Model;
use Magento\Framework\Model\AbstractModel;
/**
* Collection to get data from directory_country_region
*/
class GhnOrder extends AbstractModel
{
protected function _construct()
{
$this->_init('[Vendor]\[Extention]\Model\ResourceModel\GhnOrder');
}
}
- [2] \app\code[Vendor][Extention]\Model\ResourceModel\GhnOrder.php
<?php
namespace [Vendor]\[Extention]\Model\ResourceModel;
class GhnOrder extends \Magento\Framework\Model\ResourceModel\Db\AbstractDb
{
/**
* Define main table
*/
protected function _construct()
{
$this->_init('sale_ghn_order', 'entity_id');
//here "sale_ghn_order" is table name and "entity_id" is the key
}
}
- [3] \app\code[Vendor][Extention]\Model\ResourceModel\GhnOrder\Collection.php
<?php
/**
* Ecommerce Resource Collection
*/
namespace [Vendor]\[Extention]\Model\ResourceModel\GhnOrder;
class Collection extends \Magento\Framework\Model\ResourceModel\Db\Collection\AbstractCollection{
/**
* Resource initialization
*
* @return void
*/
protected function _construct(){
$this->_init('[Vendor]\[Extention]\Model\GhnOrder', '[Vendor]\[Extention]\Model\ResourceModel\GhnOrder');
}
}
- Example
<?php
namespace Netpower\Ghn\Controller\Adminhtml\System;
use \Magento\Catalog\Model\Product\Visibility;
use Netpower\Ghn\Helper\GhnApi;
use Netpower\Ghn\Model\GetRegionIdFactory;
use Netpower\Ghn\Services\Transport;
use Netpower\Ghn\Services\Config;
class Button extends \Magento\Backend\App\Action
{
protected $_ghnApi;
protected $_getRegionId;
protected $_log;
public function __construct(
\Magento\Backend\App\Action\Context $context,
GhnApi $ghnApi,
GetRegionIdFactory $getRegionId,
Transport $log
) {
$this->_ghnApi = $ghnApi;
$this->_getRegionId = $getRegionId;
$this->_log = $log;
parent::__construct($context);
}
public function execute(){
$token = Config::TOKEN_STAGING;
$requestToken = array(
'token' => $token
);
$requestTokens = json_encode($requestToken);
$listDistrictProvinceArray = $this->_ghnApi->getDistrictProvince($requestTokens);
/**********************************************************************
* HERE IS FACTORY
**********************************************************************/
$districts = $this->_getRegionId->create()->getCollection()->getData();
$this->_log->log($districts);
}
}
- Get Data
$getData = $this->_getRegionId->create()->getCollection()->getData();
- Set Data
$setData = $this->_getRegionId->create();
$setData->setData([name_of_column], $data);
$setData->save()
- Load Data
$loadData = $this->_ghnOrder->create()->load(['name_of_column']);
- Update Data
//Combine Set and Load Data
$loadData = $this->_ghnOrder->create()->load(['id_of_table']);
$loadData->setData([name_of_column], $data);
$loadData->save()
<?php
namespace Netpower\Ghn\Model;
use \Magento\Store\Model\ScopeInterface;
class Carrier extends AbstractCarrier implements CarrierInterface
{
/**
* @var string
*/
/**
* @param \Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig
* @param \Magento\Quote\Model\Quote\Address\RateResult\ErrorFactory $rateErrorFactory
* @param \Psr\Log\LoggerInterface $logger
* @param \Magento\Shipping\Model\Rate\ResultFactory $rateResultFactory
* @param \Magento\Quote\Model\Quote\Address\RateResult\MethodFactory $rateMethodFactory
* @param \Netpower\Ghn\Controller\Getdata\Getdata $fee
* @param array $data
*/
public function __construct(
ScopeConfigInterface $scopeConfig,
array $data = []
)
{
parent::__construct($scopeConfig, $rateErrorFactory, $logger, $data);
}
/**
* @return array
*/
public function getAllowedMethods()
{
/*0*/
return ['giaohangnhanh' => $this->getConfigData('name') ];
}
/**
* Processing additional validation to check is carrier applicable.
*
* @param \Magento\Framework\DataObject $request
* @return $this|bool|\Magento\Framework\DataObject
* @SuppressWarnings(PHPMD.UnusedFormalParameter)
*/
public function processAdditionalValidation(DataObject $request)
{
/*1*/
return $this;
}
/**
* @param RateRequest $request
* @return bool|Result
*/
public function collectRates(RateRequest $request)
{
$adminField = $this->_scopeConfig->getValue('[id of section]/[id of group]/[id of field]', ScopeInterface::SCOPE_STORE);
}
- Copy Netpower Base
- Copy Netpower Backend
- Copy MagePsycho/Easypathhints
1. Create routes.xml : etc/routes.xml
2. Create <controller>.php : Controller/<Folder_Action>/<controller>.php
EXAMPLE : Controller/Testcontroller/Controllertest.php
<?xml version="1.0" ?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:App/etc/routes.xsd">
<router id="standard">
<route frontName="netpowermomo" id="netpowermomo">
<module name="Netpower_Momo"/>
</route>
</router>
</config>
<?php
namespace Netpower\Momo\Controller\Testcontroller;
use \Magento\Framework\App\Action\Context;
class Controllertest extends \Magento\Framework\App\Action\Action
{
public function __construct(
Context $context
)
{
return parent::__construct($context);
}
public function execute()
{
echo "TEST";
}
}
- <caomoi.local>/netpowermomo/testcontroller/controllertest
...
..
.
public function execute() {
$resultRedirect = $this->resultRedirectFactory->create();
$resultRedirect->setPath(<path_frontname>_<controller>_<action>); Example momo/index/success;
return $resultRedirect;
}
.
..
...
$valueResponse = $this->getRequest()->getParams();
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Controller extend \Magento\Framework\App\Action\Action
So, we don't have to declare
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
\Magento\Checkout\Model\Session $_session;
$_session->setCaomoi("MOI");
YOU WANT TO GET IT : [$_session->getCaomoi() = "MOI"]
WE HAVE SOME KIND OF SESSION SUCH AS
\Magento\Backend\Model\Session
\Magento\Catalog\Model\Session
\Magento\Checkout\Model\Session
\Magento\Customer\Model\Session
\Magento\Newsletter\Model\Session
app/code/Test/Testpayment/view/frontend/web/js/view/payment/method-renderer/testpayment.js
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
/*browser:true*/
/*global define*/
define(
[
'ko',
'jquery',
'Magento_Checkout/js/view/payment/default',
'Test_Testpayment/js/action/set-payment-method-action'
],
function (ko, $, Component, setPaymentMethodAction) {
'use strict';
return Component.extend({
defaults: {
redirectAfterPlaceOrder: false,
template: 'Test_Testpayment/payment/testpayment'
},
afterPlaceOrder: function () {
setPaymentMethodAction(this.messageContainer);
return false;
}
});
}
);
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
app/code/Test/Testpayment/frontend/web/js/action/set-payment-method-action.js
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
/*jshint jquery:true*/
define(
[
'jquery',
'Magento_Checkout/js/model/quote',
'Magento_Checkout/js/model/url-builder',
'mage/storage',
'Magento_Checkout/js/model/error-processor',
'Magento_Customer/js/model/customer',
'Magento_Checkout/js/model/full-screen-loader'
],
function ($, quote, urlBuilder, storage, errorProcessor, customer, fullScreenLoader) {
'use strict';
return function (messageContainer) {
$.mage.redirect(url); //url is your url
};
}
);
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1. Check version module (/etc/module.xml)
2. Go to database -> table setup-module -> delete old version
Setup > UpgradeSchema
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
<?php
namespace Netpower\Momo\Setup;
use \Magento\Framework\Setup\UpgradeSchemaInterface;
use \Magento\Framework\Setup\ModuleContextInterface;
use \Magento\Framework\Setup\SchemaSetupInterface;
use \Magento\Framework\DB\Ddl\Table;
class UpgradeSchema implements UpgradeSchemaInterface
{
public function upgrade(SchemaSetupInterface $setup, ModuleContextInterface $context)
{
if (version_compare($context->getVersion(), '<version_module> example 2.0.1>') < 0) {
$setup->startSetup();
$setup->getConnection()->addColumn(
$setup->getTable('<table_name>'),
'<column_name>',
[
'type' => Table::TYPE_INTEGER,
'length' => '20',
'unique' => true,
'comment' => 'pla pla pla'
]);
$setup->endSetup();
}
}
}
PARENT CLASS
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
public function __construct(
\Magento\Framework\Model\Context $context,
\Magento\Framework\Registry $registry,
\Magento\Framework\Api\ExtensionAttributesFactory $extensionFactory,
\Magento\Framework\Api\AttributeValueFactory $customAttributeFactory,
\Magento\Payment\Helper\Data $paymentData,
\Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig,
\Magento\Payment\Model\Method\Logger $logger,
\Magento\Framework\Model\ResourceModel\AbstractResource $resource = null, // OPTIONAL
\Magento\Framework\Data\Collection\AbstractDb $resourceCollection = null, // OPTIONAL
array $data = [], // OPTIONAL
DirectoryHelper $directory = null // OPTIONAL
) {
parent::__construct(
$context,
$registry,
$extensionFactory,
$customAttributeFactory,
$resource,
$resourceCollection,
$data
);
$this->_paymentData = $paymentData;
$this->_scopeConfig = $scopeConfig;
$this->logger = $logger;
$this->directory = $directory ?: ObjectManager::getInstance()->get(DirectoryHelper::class);
$this->initializeData($data);
}
EXTEND CLASS (Child)
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
public function __construct(
\Magento\Framework\Model\Context $context,
\Magento\Framework\Registry $registry,
\Magento\Framework\Api\ExtensionAttributesFactory $extensionFactory,
\Magento\Framework\Api\AttributeValueFactory $customAttributeFactory,
\Magento\Payment\Helper\Data $paymentData,
\Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig,
\Magento\Payment\Model\Method\Logger $logger,
\Magento\Directory\Helper\Data $directory,
RefundOrder $refund,
Transport $transport,
MomoOrderFactory $momoOrderFactory,
Config $config,
\Magento\Framework\Model\ResourceModel\AbstractResource $resource = null, // OPTIONAL
\Magento\Framework\Data\Collection\AbstractDb $resourceCollection = null, // OPTIONAL
array $data = [] // OPTIONAL
) {
parent::__construct(
$context,
$registry,
$extensionFactory,
$customAttributeFactory,
$paymentData,
$scopeConfig,
$logger,
$resource,
$resourceCollection,
$data,
$directory
);
$this->_refund = $refund;
$this->_transport = $transport;
$this->_momoOrderFactory = $momoOrderFactory;
$this->_config = $config;
}
WHEN ORDER SUCCESS, WE MUST SAVE TRANSACTION.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
$payment = $order->getPayment();
$payment->setTransactionId(<transactionId>)
->setCurrencyCode($order->getBaseCurrencyCode())
->registerCaptureNotification(<amount>);
OR OR OR OR OR SURE WAY
$orderIncrementId = $this->_checkoutSession->getLastRealOrderId();
$order = $this->_orderFactory->create();
$order->loadByIncrementId($orderIncrementId);
$payment = $order->getPayment();
$payment->setTransactionId($dataResponse['out_trade_no'])
->setCurrencyCode($order->getBaseCurrencyCode())
->registerCaptureNotification($dataResponse['total_fee']);
if (!empty($dataResponse)) {
$payment->setAdditionalData(serialize($dataResponse));
}
$payment->save();
$order->save();
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
ADD BELOW CODE INTO CLASS PAYMENT
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
protected $_canAuthorize = false;
protected $_canCapture = false;
protected $_canCapturePartial = false;
protected $_canCaptureOnce = false;
protected $_canRefund = true;
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
$payment = $order->getPayment();
$order = $payment->get0rder();
\Magento\Sales\Model\OrderFactory $orderFactory;
$order = $orderFactory->create->load(<entity_id>);
$payment = $order->getPayment();
$payment->setTransactionId(<transaction Id>)
->setCurrencyCode($order->getBaseCurrencyCode())
->registerCaptureNotification(<amount>);
$order->getPayment()->cancel();
$order->addStatusHistoryComment(<MOMO Queue changes from pending to canceled>);
$order->registerCancellation(<Cancel from MOMO with Error Code {$error}>);
$order->save();
$model = <modelFactory>->create();
$model->load(<id>);
$model->delete();
$model = <modelFactory>->create();
$model->setData(<array>);
$model->save();
$order->setState("processing");
FLOW
1. Use template pathhint find Block
2. In Block find Module
3. In Module find Controller base on URL /frontname/controller/action
- Special case : /frontname = /frontname/index/index
EXAMPLE caomoi.local/checkout/
4. XML : checkout_index_index.xml
1. declare(strict_types = 1)
=> Example function Float(1, '2') return Sum two params
=> When we use STRICT. inside function Float.
1 int -> 1.0 float
'2' string -> 2.0 float
=> result is 3.0.
- - - - - - - - - - - - - - - - - - - - - - - - - - - -
view/frontend/web/js/view/payment/method-renderer.js |
- - - - - - - - - - - - - - - - - - - - - - - - - - - -
define(
[
'uiComponent',
'Magento_Checkout/js/model/payment/renderer-list',
'Magento_Checkout/js/model/quote', <=========[[
],
function (
Component,
rendererList,
quote, <=========[[
) {
'use strict';
const min = 10000;
const max = 20000000;
var amount = quote.totals().grand_total; <=========[[
if(amount == null) {
}
else if(amount < min || amount > max) {
}
else {
rendererList.push(
{
type: 'netpowermomo',
component: 'Netpower_Momo/js/view/payment/method-renderer/netpowermomo'
}
);
}
return Component.extend({});
}
);
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
<preference for="<path_Interface>" type="<path_Class>" />
</config>
1. On payment model : add [ protected $_infoBlockType = \Netpower\Momo\Block\Payment\Info::class; ]
2. Create Block file.
<?php
namespace Netpower\Momo\Block\Payment;
use Netpower\Momo\Model\MomoOrderFactory;
class Info extends \Magento\Payment\Block\Info
{
/**
* @var Netpower\Momo\Model\MomoOrderFactory
*/
protected $_momoInfor;
public function __construct(
\Magento\Backend\Block\Template\Context $context,
MomoOrderFactory $momoInfor,
array $data = []
)
{
parent::__construct($context, $data);
$this->_momoInfor = $momoInfor;
}
/**
* Prepare Momo-specific payment information
*
* @param \Magento\Framework\DataObject|array|null $transport
* @return \Magento\Framework\DataObject
*/
protected function _prepareSpecificInformation($transport = null) <=========[[ Will render infor in admin order detail and checkout on storefront
{
if (null !== $this->_paymentSpecificInformation) {
return $this->_paymentSpecificInformation;
}
$transport = parent::_prepareSpecificInformation($transport);
$data = [];
$payment = $this->getInfo(); <========[[
if($payment == null) {
} else {
$order = $payment->getOrder(); <===========[[
$grandTotal = $order->getData('grand_total');
$currency = $order->getData('store_currency_code');
$orderId = $order->getData('entity_id');
$orderMoMos = $this->_momoInfor->create()->getCollection()->getData();
$orderMomoss = [];
foreach($orderMoMos as $orderMoMo) {
if($orderMoMo['order_id'] == $orderId) {
$orderMomoss = $orderMoMo;
break;
}
}
$momoId = $payType = $tranId = null;
if($orderMomoss == []) {
} else {
$momoId = $orderMomoss['momo_id']; // $momoId = $requestId = $orderId
$payType = $orderMomoss['pay_type'];
$tranId = $orderMomoss['transaction_id'];
$data[(string)__('Total')] = (int)$grandTotal . ' ' .$currency;
$data[(string)__('Request Momo Id')] = $momoId;
$data[(string)__('Transaction Id')] = $tranId;
$data[(string)__('Pay type')] = $payType . ' ' .'<p> pla pla </p>' ;
$data[(string)__('Order Momo Id')] = $momoId;
}
}
$transport = $transport->setData(array_merge($data, $transport->getData()));
return $transport;
}
}
- Check table eav-attribute
*** NOTE : Backup database before doing task
|--- [1] Finding 'special-price' on attribute_code column to find attribute_id
|--- [2] Go to catalog_product_entity_decimal find attribute_id on step [1] to finding entity_id
|--- [3] Check it on frontend, admin and compare with database
NOTE : Using entity_id go to catalog_product_entity finding SKU. Using SKU to finding Product on frontend and admin.
|--- [4] Delete all special-price in catalog_product_entity_decimal with attribute_id in step [2]
- As step to find special price. Finding from date and end date of special price attribute_id to delete all.
*EXAMPLE IN TOTO
DELETE FROM `catalog_product_entity_decimal` WHERE `attribute_id` = 76;
DELETE FROM `catalog_product_entity_datetime` WHERE `attribute_id` = 77;
DELETE FROM `catalog_product_entity_datetime` WHERE `attribute_id` = 78;
- Format file csv from xsls file.
|--- [1] Create excel file online on google drive
|--- [2] Using =ArrayFormula(""""&'Sheet name'!range&"""")
Example : =ArrayFormula(""""&'New Product VN'!A1:E7&"""")
|--- [3] Download file formatted and open with Editor to fix """ => "
|--- [4] Go to Admin -> System -> Import/Export -> Dataflow - Profiles -> Import All Products -> Upload File -> Save.
To upload file for the tool
|--- [5] On production ToTo has a tool is Magmi. With path [https://vn.toto.com/tools/massimport888/web/magmi.php]
Tools using add
--- Default : Product details, Promotion...
--- Categories : Add Raw Categories
--- Images : Add Image for products
How to use :
--- Choose Type of Profile (Default, Categories or Images)
--- Select file uploaded
--- Save Profile and Run
TO IMPORT ATTACHMENT (File pdf, dwg ...) : USING EXTENSION NETPOWER.
--- Catalog -> Manage Attachments -> import Csv
NOTE : Upload file with format csv : "sku","file"
and format name of file is file.csv
*NOTE :
-Remember upload Attachments and Images before import csv
- Import Product : Run Dataflow - Profile
- Import Categories, Images : Using Magmi Tools
- Import Attachments : Using Admin import
*************** USE Window SCP to upload file
--------------------- Attachments : /data/www/html/media/custom/uploaded/file
--------------------- Image products : /data/www/html/media/import
LINK INSTRUCTION DETAIL : Googe Drive
FILE EXCEL EXAMPLE : Google drive
-
php72 composer.phar require vipps/module-payment LINK INSTRUCTION
-
Config VIPPS WIKI
NOTE : Commit : composer.json and composer.lock
System > Import/Export > Dataflow Profiles > Create New Profile [1]. Name of Data flow [2]. Types Import | Export ; Store [3]. File name export and Path where place file [4]. Export All fields or Only Mapping fields
Use tools of TOTO [/tools/...]
<?php
define('MAGENTO', realpath(dirname(__FILE__)));
ini_set('memory_limit', '2048M');
set_time_limit (0);
require_once MAGENTO . '/../app/Mage.php';
Mage::app();
$_productCollection = Mage::getModel('catalog/product')
->getCollection()
->addAttributeToSort('created_at', 'DESC')
->addAttributeToSelect('*')
->load();
$output = Mage::getBaseDir('media') . DS . 'sample-data' . DS . 'categories.csv';
$fp = fopen($output, 'w+');
$csvHeader = array('sku','categories');
fputcsv( $fp, $csvHeader,",");
echo "<b><h1><a href='". Mage::getBaseUrl('media')."/sample-data/categories.csv'>Download Me</a></h1></b><br/>";
echo "<table style='border-collapse:collapse;width: 1702px;table-layout: fixed;'>
<tr><td>sku</td>
<td>categories</td>
</tr>";
foreach ($_productCollection as $_product){
$collection1 = $_product->getCategoryCollection()
->addAttributeToSelect('path')
->addAttributeToSelect('is_active');
foreach($collection1 as $cat1){
$pathIds = explode('/', $cat1->getPath());
$collection = Mage::getModel('catalog/category')->getCollection()
->setStoreId(Mage::app()->getStore()->getId())
->addAttributeToSelect('name')
->addAttributeToSelect('is_active')
->addFieldToFilter('entity_id', array('in' => $pathIds));
$pahtByName = '';
foreach($collection as $cat){
if ($cat->getId() == 1 || $cat->getId() == 2) {
# code...
continue;
}
$pahtByName .= '/' . $cat->getName();
}
$pathName = substr($pahtByName, 1);
fputcsv($fp, array($_product->getSku(),$pathName), ",");
echo "<tr style='border-bottom:1px solid silver;'>
<td>{$_product->getSku()}</td>
<td>{$pathName}</td>
</tr>";
}
}
echo "</table>";
fclose($fp);
Use tools of TOTO [/tools/...]
<?php
define('MAGENTO', realpath(dirname(__FILE__)));
ini_set('memory_limit', '2048M');
set_time_limit (0);
require_once MAGENTO . '/../app/Mage.php';
Mage::app();
class Show{
static $_categories;
function getCsvData($file){
$csv = new Varien_File_Csv();
$csvData = $csv->getData($file);
$columns = array_shift($csvData);
foreach ($csvData as $k => $v) {
$csvData[$k] = array_combine($columns, array_values($v));
}
return $csvData;
}
function getCategoryNames($ids){
$names = array();
foreach($ids as $id){
$category = $this->getCategoryById($id);
$names[]= $category->getName();
}
return $names;
}
function getCategoryById($id){
if(!isset(self::$_categories)){
self::$_categories = array();
}
if(!isset(self::$_categories[$id])){
self::$_categories[$id] = Mage::getModel('catalog/category')->load($id);
}
return self::$_categories[$id];
}
function writeCsv($file , $data ){
$csv = new Varien_File_Csv();
$csv->saveData($file,$data);
}
public function getFileExtension($filename, $pos = 0) {
return strtolower(substr($filename, strrpos($filename, '.') + $pos));
}
public function run(){
$output = Mage::getBaseDir('media') . DS . 'sample-data' . DS . 'attachment.csv';
$newData = [];
$newData[]= ['product_ids', 'uploaded_file','status','exist','rule'];
echo "<b><a href='". Mage::getBaseUrl('media')."/sample-data/attachment.csv'>Download Me</a></b><br/>";
echo "Start<br/>";
echo "<table style='border-collapse:collapse;width: 1702px;table-layout: fixed;'>
<tr><td>#</td>
<td>product_ids</td>
<td>exist</td>
<td>uploaded_file</td>
<td>rule</td>
</tr>";
$data = Mage::getModel('fileuploader/fileuploader')->getCollection();
$data->addFieldToSelect('*');
$data->getSelect()->joinLeft(
array('product' => 'catalog_product_entity'), 'main_table.product_ids=product.entity_id',
array('sku' => 'sku')
);
$count =0;
foreach($data as $row){
$product_ids = $row->getProductIds();
$sku = $row->getSku();
$uploaded_file = $row->getUploadedFile();
$status = $row->getFileStatus();
$exist = file_exists('..'.$uploaded_file);
$ext = $this->getFileExtension($uploaded_file, 1);
$title = 'Unknown';
$filename = explode('/',$uploaded_file);
if(is_array($filename)){
$filename = $filename[count($filename)-1];
$filename_val = strtolower(str_replace(array('_','-'),array(''),$filename));
}
// echo "<h1>{$filename_val}</h1>";
// echo "<h2>{$ext}</h2>";
if(($ext=='dwg' || $ext=='dxf') && !strstr($filename_val,'3d')){
$title = 'CAD';
}else if($ext=='dxf' && strstr($filename_val,'3d')){
$title = '3D DXF';
}else if($ext=='pdf'){
if(strstr($filename_val,'tskt')) {
$title = 'TSKT';
}
else if(strstr($filename_val,'hdsd')) {
$title = 'HDSD';
}
else if(strstr($filename_val,'hdld')) {
$title = 'HDLD';
}
}else if($ext=='dwg' && strstr($filename_val,'3d')){
$title = '3D DWG';
}else if(in_array($ext,array('bmp','gif','jpg','jpeg','png'))){
$title = "IMAGE";
}else{
$title = "FILES OTHER";
}
$newData[] = [
'sku' => $sku,
'uploaded_file' => $uploaded_file,
'status' => $status,
'exist' => $exist ? "TRUE":"FALSE",
'rule' => $title
];
$color = "green";
echo "<tr style='border-bottom:1px solid silver;'>
<td>{$count}</td>
<td width='50px' style='color:".($exist? 'green' : 'red')."'>{$sku}</td>
<td width='50px' style='color:".($exist? 'green' : 'red')."'>".($exist ? 'TRUE' : 'FALSE')."</td>
<td width='300px'>{$uploaded_file}</td>
<td width='300px'>{$title}</td>
</tr>";
$count ++;
}
echo "</table>";
echo "End<br/>";
$this->writeCsv($output,$newData);
}
}
$show = new Show();
$show->run();
class::getInstance();
Using for singleton pattern. Declare new one object if it not existed before. And Using the Object is existing. (Only one object of getInstance exist and using).
EXAMPLE FOR GET ALL VALUES OF MANUFACTURER
<?php
namespace Netpower\Lenspower\Block\Attributes\Manufacturer;
use Magento\Framework\View\Element\Template\Context;
class Brands extends \Magento\Framework\View\Element\Template {
public function __construct(
Context $context,
array $data = []
) {
parent::__construct($context, $data);
}
public function getAllValue() {
$products = \Magento\Framework\App\ObjectManager::getInstance();
$manufacturers = $products->get('\Magento\Catalog\Model\Product\Attribute\Repository')->get('manufacturer')->getOptions();
$values = [];
foreach ($manufacturers as $manufacturersOption) {
if ($manufacturersOption->getValue() != '') {
$values[$manufacturersOption->getValue()] = $manufacturersOption->getLabel();
}
}
return $values;
}
}
<?php
/**
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
// @codingStandardsIgnoreFile
?>
<?php
$productId = $block->getSaleableItem()->getId();
/** @var \Magento\ConfigurableProduct\Pricing\Render\FinalPriceBox$block */
/** @var \Magento\Framework\Pricing\Price\PriceInterface $priceModel */
$priceModel = $block->getPriceType('regular_price');
/** @var \Magento\Framework\Pricing\Price\PriceInterface $finalPriceModel */
$finalPriceModel = $block->getPriceType('final_price');
$idSuffix = $block->getIdSuffix() ? $block->getIdSuffix() : '';
$schema = ($block->getZone() == 'item_view') ? true : false;
?>
<span class="normal-price">
<?php
$arguments = [
'display_label' => __('As low as'),
'price_id' => $block->getPriceId('product-price-' . $idSuffix),
'price_type' => 'finalPrice',
'include_container' => true,
'schema' => $schema,
];
/* @noEscape */ echo $block->renderAmount($finalPriceModel->getAmount(), $arguments);
?>
</span>
<?php if ($block->hasSpecialPrice()): ?>
<?php
$finalPriceSales = $finalPriceModel->getAmount()->getValue();
$originalPriceSales = $priceModel->getAmount()->getValue();
$salePricesRule = (100 - round(($finalPriceSales/$originalPriceSales)*100));
echo $product_labels = '<div class="product-labels configurable price-rule js-configurable-price-rule-label-'.$productId.'" ><div class="product-label sale-label">'.'-'.$salePricesRule.'%'.'</div></div>';
?>
<span class="old-price sly-old-price no-display">
<?php /* @escapeNotVerified */ echo $block->renderAmount($priceModel->getAmount(), [
'display_label' => __('Regular Price'),
'price_id' => $block->getPriceId('old-price-' . $idSuffix),
'price_type' => 'oldPrice',
'include_container' => true,
'skip_adjustments' => true
]); ?>
</span>
<?php endif; ?>
<?php if ($block->showMinimalPrice()): ?>
<?php if ($block->getUseLinkForAsLowAs()):?>
<a href="<?= /* @escapeNotVerified */ $block->getSaleableItem()->getProductUrl() ?>" class="minimal-price-link">
<?= /* @escapeNotVerified */ $block->renderAmountMinimal() ?>
</a>
<?php else:?>
<span class="minimal-price-link">
<?= /* @escapeNotVerified */ $block->renderAmountMinimal() ?>
</span>
<?php endif?>
<?php endif; ?>
=========================================================================================
<script type="text/javascript">
require(['jquery'],
function($) {
console.log("<?php echo $productId ?>");
})
</script>
=========================================================================================
EXAMPLE BLF with preference to Front-end 29. Add table field with add more field and multiple select on admin
app/code/Netpower/OnePageCheckout/Helper/Data.php
<?php
/**
* Copyright 2019 Netpower. All rights reserved.
*/
namespace Netpower\OnePageCheckout\Helper;
use Magento\Framework\App\Helper\Context;
use Magento\Store\Model\ScopeInterface;
use Magento\Checkout\Model\Session;
/**
* Class Data
* @package Netpower\Lenspower\Helper
*/
class Data extends \Magento\Framework\App\Helper\AbstractHelper
{
CONST XML_SHIPPING_CUSTOM_DESCRIPTION_PATH = 'onepage_checkout/shipping/shipping_methods_custom_text';
protected $shippingMethodsCustomDescription = [];
/**
* @param null $storeId
* @return array
*/
public function getShippingMethodsCustomDescriptionValues($storeId = null)
{
if (!$this->shippingMethodsCustomDescription) {
$configs = $this->scopeConfig->getValue(
self::XML_SHIPPING_CUSTOM_DESCRIPTION_PATH,
ScopeInterface::SCOPE_STORE,
$storeId
);
if (!$configs) {
return $this->shippingMethodsCustomDescription;
}
$configs = json_decode($configs, true);
$args = [];
foreach ($configs as $field) {
$args[] = [
'shipping_id' => $field['shipping_id'],
'custom_description' => $field['custom_description'],
];
}
$this->shippingMethodsCustomDescription = $args;
}
return $this->shippingMethodsCustomDescription;
}
}
app/code/Netpower/OnePageCheckout/Model/Checkout/OnepageConfigProvider.php
<?php
/**
* Copyright 2019 Netpower. All rights reserved.
*/
namespace Netpower\OnePageCheckout\Model\Checkout;
use Magento\Checkout\Model\ConfigProviderInterface;
use Netpower\OnePageCheckout\Helper\Data;
use Magento\Framework\UrlInterface;
/**
* Class OnepageConfigProvider
* @package Netpower\OnePageCheckout\Model\Checkout
*/
class OnepageConfigProvider implements ConfigProviderInterface
{
/**
* Url Builder
*
* @var UrlInterface
*/
protected $urlBuilder;
/**
* @var Data
*/
protected $dataHelper;
/**
* KcoConfigProvider constructor.
* @param UrlInterface $urlBuilder
*/
public function __construct(
UrlInterface $urlBuilder,
Data $dataHelper
)
{
$this->urlBuilder = $urlBuilder;
$this->dataHelper = $dataHelper;
}
/**
* Get JS config
*
* @return array
* @throws \Klarna\KcoCore\Exception
* @throws \Magento\Framework\Exception\NoSuchEntityException
*/
public function getConfig()
{
return [
'onepage' => [
'methodUrl' => $this->getUrl('checkout/onepage/saveShippingMethod')
],
'shipping' => [
'shippingMethodsCustomDescription' => $this->dataHelper->getShippingMethodsCustomDescriptionValues()
]
];
}
/**
* Generate url by route and parameters
*
* @param string $route
* @param array $params
* @return string
*/
private function getUrl($route = '', array $params = [])
{
return $this->urlBuilder->getUrl($route, $params);
}
}
window.checkoutConfig : on console to test
<?php
$objectManager = \Magento\Framework\App\ObjectManager::getInstance();
$product = $objectManager->get('Magento\Framework\Registry')->registry('current_product');
$attributeCode = "delivery_time";
$value = $product->getResource()->getAttribute($attributeCode)->getFrontend()->getValue($product);
?>
<div class="delivery-time-wrapper">
<p class="delivery-time"><?= __($value); ?></p>
</div>