Cancelling order in magento 2 programatically:
I implemented the module in magento 1 in which I will cancel the pending order from customer my account page.
Please refer to the code below which I implemented in the magento 1:
$order = Mage::getModel('sales/order')->load($orderId);
$order_status=$order->setState(Mage_Sales_Model_Order::STATE_CANCELED, true)->save();
I want to implement the same functionality in magento 2. Does anyone know how to implement it?
I loaded the order with order id in magento 2, but am unable to cancel the order.
You should use API (more about magento2 API concepts) for that, example how to use it in your class:
<?php
use Magento\Sales\Api\OrderManagementInterface;
class A
{
/**
* #var OrderManagementInterface
*/
private $orderManagement;
/**
* #param OrderManagementInterface $orderManagement
*/
public function __construct(OrderManagementInterface $orderManagement)
{
$this->orderManagement = $orderManagement;
}
public function cancelOrderOne()
{
$orderId = 1;
$isCanceled = $this->orderManagement->cancel($orderId);
}
}
Please look at the code below, it will also validate the user associations for the order also
<?php
Nmaespace\Modulename\Controller\Action;
class Cancelorder extends \Magento\Framework\App\Action\Action
{
protected $orderManagement;
public function __construct(
\Magento\Framework\App\Action\Context $context,
\Magento\Sales\Api\OrderManagementInterface $orderManagement
) {
$this->orderManagement = $orderManagement;
parent::__construct($context);
}
public function execute()
{
$objectManager = \Magento\Framework\App\ObjectManager::getInstance();
$customerSession = $objectManager->get('Magento\Customer\Model\Session');
if(!$customerSession->isLoggedIn()) {
$this->_redirect('/');
die;
}
/*get request params */
$get_customer_id = $customerSession->getCustomer()->getId();
$get_order_id = $this->getRequest()->getParam('order_id');
/*get request params */
//die;
$order = $objectManager->create('Magento\Sales\Model\Order')->load($get_order_id);
$getcustomerid = $get_customer_id;
$orderdata = $order->getData();
$order_status = $orderdata["status"];
//print_r($orderdata);
$cus_id = $orderdata["customer_id"];
if($getcustomerid != $cus_id){
echo "We cant Cancel this order at this time" ;
//die("go back");
}
if($order_status == "pending"){
$this->orderManagement->cancel($get_order_id);
echo "Order Cancelled successfully" ;
}
else{
echo "We cant Cancel this order at this time" ;
}
}
}
Related
I am creating a script to add orders programmatically in Magento. I need help to change the date of the entries in the Comments History (quote, invoice, shipping, etc.). I can manipulate the date of the order itself (setCreatedAt) and some of the comments related to the creation of the order are correct (e.g. "Sep 29, 2008 8:59:25 AM|Pending Customer Notification Not Applicable"), but I cannot change the date of the comment when I use addStatusHistoryComment...
Here's a snippet of my code:
try {
if(!$order->canInvoice()) {
Mage::throwException(Mage::helper('core')->__('Cannot create an invoice.'));
}
$invoice = Mage::getModel('sales/service_order', $order)->prepareInvoice();
if (!$invoice->getTotalQty()) {
Mage::throwException(Mage::helper('core')->__('Cannot create an invoice without products.'));
}
$invoice->setRequestedCaptureCase(Mage_Sales_Model_Order_Invoice::CAPTURE_OFFLINE);
$invoice->setCreatedAt('2008-09-23 13:05:20');
$invoice->register();
$invoice->getOrder()->setCustomerNoteNotify(true);
$invoice->getOrder()->setIsInProcess(true);
$transactionSave = Mage::getModel('core/resource_transaction')
->addObject($invoice)
- >addObject($invoice->getOrder());
$transactionSave->save();
//END Handle Invoice
//START Handle Shipment
$shipment = $order->prepareShipment();
$shipment->setCreatedAt('2008-09-23 14:20:10');
$shipment->register();
$order->setIsInProcess(true);
$order->addStatusHistoryComment('Shipping message goes here...', true);
$shipment->setEmailSent(true);
$transactionSave = Mage::getModel('core/resource_transaction')
->addObject($shipment)
->addObject($shipment->getOrder())
->save();
$track = Mage::getModel('sales/order_shipment_track')
->setShipment($shipment)
->setData('title', 'Some tracking no.')
->setData('number', '111222333444')
->setData('carrier_code', 'fedex') //custom, fedex, ups, usps, dhl
->setData('order_id', $shipment->getData('order_id'))
->save();
//END Handle Shipment
}
catch (Mage_Core_Exception $ex) {
echo "Problem creating order invoice and/or shipment: ".$ex."\n";
}
Thanks in advance.
If I understand your question correctly, you just need to do this:
$comments = $order->getStatusHistoryCollection(true);
$comments now contains a collection of all the status history comments, and you can loop over them with whatever sort of criteria you like.
foreach ($comments as $c) {
if ( /* some stuff */ ) {
$c->setData('created_at',$new_date)->save();
}
}
So this is untested, but should work:
You need to create a new method based off addStatusHistoryComment:
/app/code/core/Mage/Sales/Model/Order.php
/*
* Add a comment to order
* Different or default status may be specified
*
* #param string $comment
* #param string $status
* #return Mage_Sales_Model_Order_Status_History
*/
public function addStatusHistoryComment($comment, $status = false)
{
if (false === $status) {
$status = $this->getStatus();
} elseif (true === $status) {
$status = $this->getConfig()->getStateDefaultStatus($this->getState());
} else {
$this->setStatus($status);
}
$history = Mage::getModel('sales/order_status_history')
->setStatus($status)
->setComment($comment)
->setEntityName($this->_historyEntityName);
->setCreatedAt('2008-09-23 14:20:10'); //I added this line
$this->addStatusHistory($history);
return $history;
}
Obviously you either need to rewrite this method, or refactor the code to do the same.
I am new to Magento Extension Development and wondering which is the best way to create categories and sub-categories from within an extension. The Extension I am working on is synchronizing product-data from an ERP-System. The extension is operating with a System->Configuration Dialog which holds the data for the connection to the server (user/pwd/etc.) Now I am wondering, if it is better to connect via Ajax request or use a Soap call. Ajax seems very slow in this case for about 700 Products. So what do you suggest?
Furthermore, I am a little stuck by creating categories and sub-categories. Is there simple way to do that. I found some stuff on creating a category and then use the ->move() function. Moreover I am wondering if the 'path' of the category is essential on creating sub-categories.
You should use magento models:
Create category with subcategory:
/**
* After installation system has two categories: root one with ID:1 and Default category with ID:2
*/
/** #var $category1 Mage_Catalog_Model_Category */
$category1 = Mage::getModel('catalog/category');
$category1->setName('Category 1')
->setParentId(2)
->setLevel(2)
->setAvailableSortBy('name')
->setDefaultSortBy('name')
->setIsActive(true)
->setPosition(1)
->save();
/** #var $category2 Mage_Catalog_Model_Category */
$category2 = Mage::getModel('catalog/category');
$category2->setName('Category 1.1')
->setParentId($category1->getId()) // set parent category which was created above
->setLevel(3)
->setAvailableSortBy('name')
->setDefaultSortBy('name')
->setIsActive(true)
->setIsAnchor(true)
->setPosition(1)
->save();
public static function addCatalogCategory($item, $id, $storeId = 0) {
/*
* resource for checking category exists
* http://fishpig.co.uk/blog/load-a-category-or-product-by-an-attribute.html
*/
$categories = Mage::getResourceModel('catalog/category_collection');
// Select which fields to load into the category
// * will load all fields but it is possible to pass an array of
// select fields to load
$categories->addAttributeToSelect('*');
// Ensure the category is active
$categories->addAttributeToFilter('is_active', 1);
// Add Name filter
$categories->addAttributeToFilter('name', $item->GROUP_NAME);
// Limit the collection to 1 result
$categories->setCurPage(1)->setPageSize(1);
// Load the collection
$categories->load();
if ($categories->getFirstItem()->getId()) {
$category = $categories->getFirstItem();
return $category->getId();
}
/* get category object model */
$category = Mage::getModel('catalog/category');
$category->setStoreId($storeId);
$data = array();
/* if the node is root */
if (Heliumv_Synchronization_Helper_Data::xml_attribute($item, 'type') == 'root') {
$data['category']['parent'] = 2; // 2 top level id
} else {
/* is node/leaf */
$data['category']['parent'] = $id;
}
$data['general']['path'] = $item->PARENT_ID;
$data['general']['name'] = $item->GROUP_NAME;
$data['general']['meta_title'] = "";
$data['general']['meta_description'] = "";
$data['general']['is_active'] = "1";
$data['general']['url_key'] = "";
$data['general']['display_mode'] = "PRODUCTS";
$data['general']['is_anchor'] = 0;
/* add data to category model */
$category->addData($data['general']);
if (!$category->getId()) {
$parentId = $data['category']['parent'];
if (!$parentId) {
if ($storeId) {
$parentId = Mage::app()->getStore($storeId)->getRootCategoryId();
} else {
$parentId = Mage_Catalog_Model_Category::TREE_ROOT_ID;
}
}
$parentCategory = Mage::getModel('catalog/category')->load($parentId);
$category->setPath($parentCategory->getPath());
}
$category->setAttributeSetId($category->getDefaultAttributeSetId());
try {
$category->save();
return $category->getId();
} catch (Exception $e) {
echo Mage::log($e->getMessage());
}
}
I hope this helps someone. cheers
I'm using the Cart class in Codeigniter. What I want to do should (hopefully!) be simple... but i'm struggling.
On the product page, I have a button to 'add to cart'. What I want to happen is that when the item is already in the cart, the button changes to 'remove from cart'.
<? //if(**not in cart**) { ?>
Add to cart
<? } else { ?>
Remove from cart
<? } ?>
How can I query the cart to see if that item is in there or not and get the 'rowid' so I can use that for a remove function?
Many thanks!
I had a similar problem - I got round it by extending the CI_Cart library with 2 new functions - in_cart() and all_item_count().
<?php
class MY_Cart extends CI_Cart {
function __construct()
{
parent::__construct();
$this->product_name_rules = '\d\D';
}
/*
* Returns data for products in cart
*
* #param integer $product_id used to fetch only the quantity of a specific product
* #return array|integer $in_cart an array in the form (id => quantity, ....) OR quantity if $product_id is set
*/
public function in_cart($product_id = null) {
if ($this->total_items() > 0)
{
$in_cart = array();
// Fetch data for all products in cart
foreach ($this->contents() AS $item)
{
$in_cart[$item['id']] = $item['qty'];
}
if ($product_id)
{
if (array_key_exists($product_id, $in_cart))
{
return $in_cart[$product_id];
}
return null;
}
else
{
return $in_cart;
}
}
return null;
}
public function all_item_count()
{
$total = 0;
if ($this->total_items() > 0)
{
foreach ($this->contents() AS $item)
{
$total = $item['qty'] + $total;
}
}
return $total;
}
}
/* End of file: MY_Cart.php */
/* Location: ./application/libraries/MY_Cart.php */
You could check in your model if the job name or whatever you would like to check already exists. If it exists display delete button else show add.
The paypal module tries to map the billing information that is returned (usually nothing) from Paypal over the billing information entered by the user during the checkout process. I've fond the code that does this in NVP.php model.
/**
* Create billing and shipping addresses basing on response data
* #param array $data
*/
protected function _exportAddressses($data)
{
$address = new Varien_Object();
Varien_Object_Mapper::accumulateByMap($data, $address, $this->_billingAddressMap);
$address->setExportedKeys(array_values($this->_billingAddressMap));
$this->_applyStreetAndRegionWorkarounds($address);
$this->setExportedBillingAddress($address);
// assume there is shipping address if there is at least one field specific to shipping
if (isset($data['SHIPTONAME'])) {
$shippingAddress = clone $address;
Varien_Object_Mapper::accumulateByMap($data, $shippingAddress, $this->_shippingAddressMap);
$this->_applyStreetAndRegionWorkarounds($shippingAddress);
// PayPal doesn't provide detailed shipping name fields, so the name will be overwritten
$shippingAddress->addData(array(
'prefix' => null,
'firstname' => $data['SHIPTONAME'],
'middlename' => null,
'lastname' => null,
'suffix' => null,
));
$this->setExportedShippingAddress($shippingAddress);
}
}
/**
* Adopt specified address object to be compatible with Magento
*
* #param Varien_Object $address
*/
protected function _applyStreetAndRegionWorkarounds(Varien_Object $address)
{
// merge street addresses into 1
if ($address->hasStreet2()) {
$address->setStreet(implode("\n", array($address->getStreet(), $address->getStreet2())));
$address->unsStreet2();
}
// attempt to fetch region_id from directory
if ($address->getCountryId() && $address->getRegion()) {
$regions = Mage::getModel('directory/country')->loadByCode($address->getCountryId())->getRegionCollection()
->addRegionCodeFilter($address->getRegion())
->setPageSize(1)
;
foreach ($regions as $region) {
$address->setRegionId($region->getId());
$address->setExportedKeys(array_merge($address->getExportedKeys(), array('region_id')));
break;
}
}
}
Has anyone had any success modifying this process to get back fuller billing information. We need to be able to send "Paid" invoices to customers who pay with Paypal, so we need to capture this information.
i have hacked a workaround for that problem. It is not the cleanest way but i can save the billing address data in the order after paying with PayPal. I spent 2 days working on it and at the end i coded only a few lines. I marked my workaround with the comment #103.
Override method of class Mage_Paypal_Model_Api_Nvp:
protected function _importAddresses(array $to)
{
// Original Code
//$billingAddress = ($this->getBillingAddress()) ? $this->getBillingAddress() : $this->getAddress();
// Workaround #103
if ($this->getBillingAddress())
{
$billingAddress = $this->getBillingAddress();
}
else
{
$chkout = Mage::getSingleton('checkout/session');
$quote = $chkout->getQuote();
$billingAddress = $quote->getBillingAddress();
$billingAddress->setData($billingAddress->getOrigData());
$session = Mage::getSingleton("core/session", array("name"=>"frontend"));
$session->setData("syn_paypal_original_billing_address", serialize($billingAddress->getOrigData()));
}
$shippingAddress = $this->getAddress();
$to = Varien_Object_Mapper::accumulateByMap($billingAddress, $to, array_flip($this->_billingAddressMap));
if ($regionCode = $this->_lookupRegionCodeFromAddress($billingAddress)) {
$to['STATE'] = $regionCode;
}
if (!$this->getSuppressShipping()) {
$to = Varien_Object_Mapper::accumulateByMap($shippingAddress, $to, array_flip($this->_shippingAddressMap));
if ($regionCode = $this->_lookupRegionCodeFromAddress($shippingAddress)) {
$to['SHIPTOSTATE'] = $regionCode;
}
$this->_importStreetFromAddress($shippingAddress, $to, 'SHIPTOSTREET', 'SHIPTOSTREET2');
$this->_importStreetFromAddress($billingAddress, $to, 'STREET', 'STREET2');
$to['SHIPTONAME'] = $shippingAddress->getName();
}
$this->_applyCountryWorkarounds($to);
return $to;
}
And override method in Mage_Paypal_Model_Express_Checkout:
public function returnFromPaypal($token)
{
$this->_getApi();
$this->_api->setToken($token)
->callGetExpressCheckoutDetails();
// import billing address
$billingAddress = $this->_quote->getBillingAddress();
$exportedBillingAddress = $this->_api->getExportedBillingAddress();
// Workaround #103
$session = Mage::getSingleton("core/session", array("name"=>"frontend"));
$dataOrg = unserialize($session->getData("syn_paypal_original_billing_address"));
if (true === is_object($billingAddress))
{
foreach ($exportedBillingAddress->getExportedKeys() as $key) {
if (array_key_exists($key, $dataOrg))
{
$billingAddress->setData($key, $dataOrg[$key]);
}
}
$this->_quote->setBillingAddress($billingAddress);
}
// import shipping address
$exportedShippingAddress = $this->_api->getExportedShippingAddress();
if (!$this->_quote->getIsVirtual()) {
$shippingAddress = $this->_quote->getShippingAddress();
if ($shippingAddress) {
if ($exportedShippingAddress) {
foreach ($exportedShippingAddress->getExportedKeys() as $key) {
$shippingAddress->setDataUsingMethod($key, $exportedShippingAddress->getData($key));
}
$shippingAddress->setCollectShippingRates(true);
}
// import shipping method
$code = '';
if ($this->_api->getShippingRateCode()) {
if ($code = $this->_matchShippingMethodCode($shippingAddress, $this->_api->getShippingRateCode())) {
// possible bug of double collecting rates :-/
$shippingAddress->setShippingMethod($code)->setCollectShippingRates(true);
}
}
$this->_quote->getPayment()->setAdditionalInformation(self::PAYMENT_INFO_TRANSPORT_SHIPPING_METHOD, $code);
}
}
$this->_ignoreAddressValidation();
// import payment info
$payment = $this->_quote->getPayment();
$payment->setMethod($this->_methodType);
Mage::getSingleton('paypal/info')->importToPayment($this->_api, $payment);
$payment->setAdditionalInformation(self::PAYMENT_INFO_TRANSPORT_PAYER_ID, $this->_api->getPayerId())
->setAdditionalInformation(self::PAYMENT_INFO_TRANSPORT_TOKEN, $token)
;
$this->_quote->collectTotals()->save();
}
I'm working on a Magento theme, and I need to build a function that can check to see whether or not a product has been added to the user's wishlist.
Magento has a "Mage_Wishlist_Helper_Data" helper class, but I have no idea how to build a check-if-already-in-wishlist function. Basically I need to use Magento's wishlist feature to build a favorites list. I want to add a special class to the "add to wishlist" link if the particular product was already added to the user's favorites.
<?php $wishlist = Mage::getModel('wishlist/item')->load($_product->getId(),'product_id');
if($wishlist->getId())
//product is added
echo "Added! - Product is in the wishlist!";
else
//add product to wishlist
echo "<a href='".$this->helper('wishlist')->getAddUrl($_product) ."'>Add This?</a>";
;?>
Since collections are lazy loaded, I am assuming you can do something such as:
$_product = ...; // some product object you already have
$_productCollection = Mage::helper('wishlist')->getProductCollection()
->addFieldToFilter('sku', $_product->getSku());
if($_productCollection->count() > 0) {
// User already has item in wishlist.
}
You can do similar filtering on other fields, but SKU should be sufficient in this case.
I'm only getting back to this project now, but I took Daniel Sloof's suggestion, and it worked perfectly using the function below:
public function isInWishlist($item)
{
$_productCollection = Mage::helper('wishlist')->getProductCollection()
->addFieldToFilter('sku', $item->getSku());
if($_productCollection->count()) {
return true;
}
return false;
}
This checks to see whether or not a product has been added into the current user's Wishlist. I called it my template file like this:
if ($this->helper('wishlist')->isInWishlist($_product)) :
I found this solution after checked select query of Mage::helper('wishlist')->getWishlistItemCollection(). I hope this solution help to someone.
/**
* Check customers wishlist on identity product.
* #param Mage_Catalog_Model_Product $_product
* #return bool
*/
private function _isInWishlist($_product)
{
$_productCollection = Mage::helper('wishlist')->getWishlistItemCollection()
->addFieldToFilter('product_id', $_product->getId());
if ($_productCollection->count()) {
return true;
}
return false;
}
I solved this by the below function. I Hope this may help some one.
function checkInWishilist($_product){
Mage::getSingleton('customer/session')->isLoggedIn();
$session = Mage::getSingleton('customer/session');
$cidData = $session->isLoggedIn();
$customer_id = $session->getId();
if($customer_id){
$wishlist = Mage::getModel('wishlist/item')->getCollection();
$wishlist->getSelect()
->join(array('t2' => 'wishlist'),
'main_table.wishlist_id = t2.wishlist_id',
array('wishlist_id','customer_id'))
->where('main_table.product_id = '.$_product->getId().' AND t2.customer_id='.$customer_id);
$count = $wishlist->count();
$wishlist = Mage::getModel('wishlist/item')->getCollection();
}
else {
$count="0";
}
if ($count) :
return true;
else:
return false;
endif;
}
Since #alexadr.parhomenk s' solution causes undesired results, here's a smaller method that does the trick:
/**
* Check customers wishlist on identity product.
* #param int $productId
* #return bool
*/
public function isInWishlist($productId)
{
$ids = Mage::registry('wishlist_ids');
if (!$ids) {
$productCollection = Mage::helper('wishlist')->getWishlistItemCollection();
$ids = $productCollection->getColumnValues('product_id');
Mage::register('wishlist_ids', $ids);
}
return in_array($productId, $ids);
}