I sell two services in my Magento store. I've disabled cart and multi-page checkout. I want to sell only one service at a time. Means I want to accomplish, if customer tries to add both services to cart so the previous service should be removed.
How can I accomplish this? I've been searching this from last 5 hours.
in the file
app/code/core/Mage/Sales/Model/Quote.php
there is a method public function addProduct($product, $request = null);
you should only add $this->removeAllItems(); to be the first line in the method, like:
public function addProduct(Mage_Catalog_Model_Product $product, $request = null)
{
$this->removeAllItems(); // new code
....
}
of course, it's better idea to be overridden in the local pool.
Related
Given that I have multiple websites in my Magento instance, how do I identify the website where a particular event happened? For example, observing the checkout_cart_add_product_complete event lets me catch all Add to Cart events. Let's say I wanted to get the website Id of the website where this Add to Cart event happened, how do you I do that?
public function addToCart(Varien_Event_Observer $observer) {
$product = $observer->getEvent()->getProduct();
$websiteId = $observer->getEvent()->get ??? ();
}
I know that I can get the websiteIds of the product that was added to the cart, by doing the following
$websiteIds = $observer->getEvent()->getProduct()->getWebsiteIds();
But that is not what I want, because if the product belongs to more than one website, it will give me all the websites and not the one where the Add to Cart event happened.
Thanks
Have you tried:
Mage::app()->getStore()->getId()
within your observer? That should give you the current store id..
You can directly get the StoreId from Mage, not from the observer object.
StoreId:
Mage::app()->getStore()->getStoreId();
WebsiteId:
Mage::app()->getStore()->getWebsiteId();
Laravel Cashier makes it pretty simple to swap plans:
$user->subscription('premium')
->swapAndInvoice();
This feature is also great because it invoices the user right away, HOWEVER, it also forces the user to pay right away rather than waiting an hour like it normally would. This seems to get in the way of my invoice.created webhook because once swapAndInvoice happens, I don't seem to be able to make further changes to the invoice.
If I just use ->swap(), it doesn't appear to create an invoice at all, but rather it just creates line items waiting to be added to the next invoice. Thoughts are appreciated.
Since posting this question, I have actually submitted a pull request to the Laravel Cashier repository to add a method within the StripeGateway.php file that can perform such functionality.
/**
* Invoice the billable entity outside of regular billing cycle without charging the user immediately.
*
* #return bool
*/
public function invoiceWithoutImmediateCharge()
{
try
{
$customer = $this->getStripeCustomer();
// Removed this because it immediately charges the user which doesn't allow the invoice to be modified by webhooks
//Stripe_Invoice::create(['customer' => $customer->id], $this->getStripeKey())->pay();
Stripe_Invoice::create(['customer' => $customer->id], $this->getStripeKey());
return true;
}
catch (\Stripe_InvalidRequestError $e)
{
return false;
}
}
I have a magento site for ecommerce. When an order is placed, I need to call another function I've created in a new php file and pass the order skus, quantities and shipping address to. I'm extremely comfortable with php, but Magento is an entirely new beast for me.
Does anyone know how to call a function when an order is placed? Even just the name of the event would be helpful.
I haven't used it personally, but sales_order_place_after sounds like it might be what you're looking for. It's used in this way in this Inchoo article, which also involves doing some things as soon as an order is placed.
Here's a page on the Magento wiki about setting up an event observer, which really is just a little XML to tell Magento to run some code when that event is dispatched, and the code you want to run.
you can try sales_order_place_before and sales_order_place_after
if you are interested in the events fired, a common approach is to temporary add
Mage::log($name); in the Mage.php (app/Mage.php) like this
public static function dispatchEvent($name, array $data = array())
{
Mage::log($name);
Varien_Profiler::start('DISPATCH EVENT:'.$name);
$result = self::app()->dispatchEvent($name, $data);
Varien_Profiler::stop('DISPATCH EVENT:'.$name);
return $result;
}
this will log any event fired during a page view or action to the var/log/system.log, if you enabled logging in the backend System->Configuration>Developer->Log Settings
PROBLEM:
While in backend o cron task (ex. in a custom product feed generator running on user request or on a cron event), and generally out of frontend, the Mage_Catalog_Model_Product's method getFinalPrice() returns product's base price, not taking in account, for example, Magento Catalog Price Rules applicable to that product.
This means that prices exported in the generated feed are not the same as show in Magento frontend, which can easily become a problem.
So, how to obtain product's final price as show in frontend?
The SOLUTION stated by the person who asked the question only works on Admin site if you add this line towards the top:
Mage::app()->loadAreaPart(Mage_Core_Model_App_Area::AREA_FRONTEND,Mage_Core_Model_App_Area::PART_EVENTS);
This loads the Frontend Event which takes in account of the Catalog Price Rules defined on Admin site.
Hope it helps someone in the future.
SOLUTION
Use a helper class, with the following method defined:
class My_Package_Helper_Price extends Mage_Core_Helper_Abstract {
private $_init_rule = false;
private function initRuleData($product) {
if ($this->_init_rule || empty($product)) return $this;
$productStore = Mage::getModel('core/store')->load($product->getStoreId());
if (!empty($productStore)) {
Mage::register('rule_data', new Varien_Object(array(
'store_id' => $product->getStoreId(),
'website_id' => $productStore->getWebsiteId(),
'customer_group_id' => 0, // NOT_LOGGED_IN
)));
$this->_init_rule = true;
}
return $this;
}
public function getProductFinalPrice($product) {
$this->initRuleData($product);
return $product->getFinalPrice();
}
}
Then, you can use:
Mage::helper('my_package/price')->getProductFinalPrice($product);
where $product is a loaded instance of Mage_Catalog_Model_Product class.
I'd like to implement a global order limit on certain products. The point of this is that I want to enable backorders on certain products and define several date periods where there are limits to how many of these individual products that may be ordered.
Currently my custom model is loaded with the relevant information for the chosen date period and attached to the product models when they are loaded as $product->setMyModel(...) on these events:
catalog_product_load_after
catalog_product_collection_load_after
sales_quote_item_collection_products_after_load
Accessing my model with data for a specific product is as simple as calling $product->getMyModel(), which I hence will refer to as simply my model.
This is what I want to do:
1. Whenever a product is added to a cart/quote, or placed in an order, I want to do something like this (pseudocode):
// Somehow get $product and $requestedQty (most likely from an event)
$myModel = $product->getMyModel();
if($myModel->applyOrderLimit()) {
// ($orderedQty + $requestedQty) <= $orderLimit
if($myModel->isRequestedQtyAvailable($requestedQty)) {
// Issue an error and prevent the item from being ordered
return;
}
// $orderedQty += $requestedQty
$myModel->addToQtyOrdered($requestedQty);
}
// Continue Magentos default behaviour
1.1. I suspect that Mage_CatalogInventory_Item::checkQuoteItemQty() should be overriden to capture the $requestedQty here.
2. Update $myModel::ordered_qty whenever an order is cancelled, refunded or such.
I guess the real question is where do I run this code, and is there anything more to implementing such an order limit and keeping track of the qty's than I have realized?
To me, this seem like quite a complex task. Which is why I need assistance from more experienced Magento developers!
Note: I couldnt figure out how to mix numbered lists and code blocks, but I hope its readable enough
You don't have to resort to rewriting the Mage_CatalogInventory_Model_Stock_Item:.checkQty() method in order to achieve your goal.
If you add an event observer to the event sales_quote_item_qty_set_after, your observer will be triggered in addition to the cataloginventory check.
public function salesQuoteItemQtySetAfter(Varien_Event_Observer $observer)
{
$quoteItem = $observer->getItem();
$qty = $quoteItem->getQty();
$myModel = $quoteItem->getProduct()->getMyModel()
// Your Logic
// If not salable set error for the quote item
$quoteItem->addErrorInfo(
'mymodule', // origin code
'currently_not_salable', // error code
'The Error Message'
);
}
The sales_quote_item_qty_set_after event is also used by the cataloginventory module to call checkQty(), so you can also examine Mage_CatalogInventory_Model_Observer::checkQuoteItemQty() for additional possibilities on what functionality is available.