I'm creating a product on prestashop, I enter the amount with this function:
echo "1";
StockAvailable::setQuantity($id_prod, 0, $quantity,1);
echo "2";
the result is:
1fatal error
going on the backend, the product is and the amount set correctly.
How can I avoid the "fatal error"?
Report me error here: classes/Product.php in line 2582: if (!$id_cart && !isset($context->employee)) die(Tools::displayError());
This code is in the function "getPriceStatic". It is normal that it is pulled to perform "StockAvailable::setQuantity"?
I have not changed classes and I do not override
Usually I use this snippet (adapt it to your needs):
$shop_is_feature_active = Shop::isFeatureActive();
$shops = Shop::getContextListShopID();
if ($shop_is_feature_active) {
foreach ($shops as $shop) {
StockAvailable::setQuantity((int)$product->id, 0, (int)$product->quantity, (int)$shop);
}
} else {
StockAvailable::setQuantity((int)$product->id, 0, (int)$product->quantity, (int)$this->context->shop->id);
}
However, I always suggest to check if the product is in that shop.
It is important to check if
Context::getContext()->employee
is not empty, otherwise enter:
$psContext = Context::getContext();
if (!$psContext->employee) {
$psContext->employee = new Employee(PS_DEFAULT_EMPLOYEE);
}
Related
I'm trying to make magento modification when user enter vat number on checkout remove tax from order.
I found a code on stackoverflow which support on magento older version but it not work with new version 1.9,
I made few modifications for work the condition and return 0,even it return 0 checkout still shows tax.
here is my code which is on file
/app/code/core/Mage/Tax/Model/Calculation.php line number 268
public function getRate($request)
{
if (!$request->getCountryId() || !$request->getCustomerClassId() || !$request->getProductClassId()) {
return 0;
}
//my code
$ctax= Mage::getSingleton('checkout/session')->getQuote()->getCustomerTaxvat();
if ($this->getCustomer() && $ctax !='') {
//echo 'test';
return 0;
}
//end my code
$cacheKey = $this->_getRequestCacheKey($request);
if (!isset($this->_rateCache[$cacheKey])) {
$this->unsRateValue();
$this->unsCalculationProcess();
$this->unsEventModuleId();
Mage::dispatchEvent('tax_rate_data_fetch', array(
'request' => $request));
if (!$this->hasRateValue()) {
$rateInfo = $this->_getResource()->getRateInfo($request);
$this->setCalculationProcess($rateInfo['process']);
$this->setRateValue($rateInfo['value']);
} else {
$this->setCalculationProcess($this->_formCalculationProcess());
}
$this->_rateCache[$cacheKey] = $this->getRateValue();
$this->_rateCalculationProcess[$cacheKey] = $this->getCalculationProcess();
}
return $this->_rateCache[$cacheKey];
}
Anyone can help me to make tax 0 when user enters vat number on checkout, Thanks a lot
I've managed to solve my problem by following this thread : Modify tax rate on cart quote items and recalculate
I have added an Observer to the event sales_quote_collect_totals_before.
And here is the content of my observer, very simple :
public function removetax($observer)
{
$customer_id = Mage::getSingleton('customer/session')->getId();
$customer = Mage::getModel("customer/customer")->load($customer_id);
if($customer->getIsTaxExempt() == 1)
{
$items = $observer->getEvent()->getQuote()->getAllVisibleItems();
foreach($items as $item)
$item->getProduct()->setTaxClassId(0);
}
}
If customer is tax exempt, I grab the current cart content and for each item, I set the product tax class to 0. It is mandatory to not save the product or the item. The aim here is to set a value for the following calculation, not to save it in the database. Tax classes need to stay to the initial value in the db.
You can use sales_quote_collect_totals_before event.
then you have to define logic for remove tax on checkout page.
This link you can refer.
Go to Calculation.php and find the calcTaxAmount() and add billing condditions
public function calcTaxAmount($price, $taxRate, $priceIncludeTax = false, $round = true)
{
$billing = Mage::getModel('checkout/session')->getQuote()->getCustomerTaxvat();
if($billing !="")
{
return 0;
}
}
How to avoid decreasing of a product quantity when it's still in the "Process" and update when the order was shipped or delivered?
I've edited this part of code in orderdetail.php and add this $id_order_state != Configuration::get('PS_OS_PREPARATION') in the if statement. Yes, the quantity doesn't decrease when it's processed but when shipped it also doesn't decrease. please help I'm stuck in here.
protected function checkProductStock($product, $id_order_state)
{
if ($id_order_state != Configuration::get('PS_OS_CANCELED') && $id_order_state != Configuration::get('PS_OS_ERROR') && $id_order_state != Configuration::get('PS_OS_PREPARATION')) {
$update_quantity = true;
if (!StockAvailable::dependsOnStock($product['id_product'])) {
$update_quantity = StockAvailable::updateQuantity($product['id_product'], $product['id_product_attribute'], -(int)$product['cart_quantity']);
}
if ($update_quantity) {
$product['stock_quantity'] -= $product['cart_quantity'];
}
if ($product['stock_quantity'] < 0 && Configuration::get('PS_STOCK_MANAGEMENT')) {
$this->outOfStock = true;
}
Product::updateDefaultAttribute($product['id_product']);
}
}
An OrderDetail object is only created once for each Order and will not be updated after that even when you change the Order State. So when your OrderDetail object is created, with your modification it will not update the stock because it doesn't have the right state. And when you later change the Order State the method checkProductStock will never be called again.
You can create a custom module hooked on actionOrderStatusPostUpdate (witch is triggered inside changeIdOrderState() method of class OrderHistory(). In your module you will copy the checkProductStock() method and call it from the hook if the state is "shipped".
EDIT
If you want to add it directly in core:
Edit classes/order/OrderHistory.php
In method changeIdOrderState() change the last lines:
// executes hook
Hook::exec('actionOrderStatusPostUpdate', array('newOrderStatus' => $new_os, 'id_order' => (int)$order->id, ), null, false, true, false, $order->id_shop);
// Here change 4 to the desired id_order_state
if ($new_order_state == 4)
{
$virtual_products = $order->getVirtualProducts();
foreach ($virtual_products as $virtual_product)
{
$this->checkProductStock($virtual_product['product_id'], $new_order_state);
}
}
ShopUrl::resetMainDomainCache();
}
After that add a new method in this class:
protected function checkProductStock($product, $id_order_state)
{
$update_quantity = true;
if (!StockAvailable::dependsOnStock($product['product_id']))
{
StockAvailable::updateQuantity($product['product_id'], $product['product_attribute_id'], -(int)$product['product_quantity']);
}
Product::updateDefaultAttribute($product['product_id']);
}
This code has not been tested.
I advise you to do it in an override:
Create a new file in /overrides/classes/order/OrderHistory.php witch contains those two methods and change the class definition to class OrderHistory extends OrderHistoryCore {, you will have to delete /cache/class_index.php after adding this file.
I'm trying to make an interface where I can edit some of the metadata attached to a lineitem. I've tried using update_post_meta() on the line item itself, however that returns bool(false). How can I update the line item meta data manually?
Thanks!
so I managed to figure it out. I wrote a small function that's below. So, all you need to do is load up the order using the API, parse through each line item and you can call wc_update_order_item_meta. The only thing is, you need to know the variation ID of the item being sold if you only want to update a specific item.
function update_order_item_meta($orderID, $variationID, $metaID, $metaValue) {
$order = returnWC_API()->get_order($orderID)->{'order'};
if(!$order) {
return false;
}
if($variationID == "all") {
foreach ($order->{'line_items'} as $line_item) {
if(!wc_update_order_item_meta($line_item->{'id'}, $metaID, $metaValue)) {
return false;
}
}
return true;
}
foreach ($order->{'line_items'} as $line_item) {
if($line_item->{'product_id'} == $variationID) {
return wc_update_order_item_meta($line_item->{'id'}, $metaID, $metaValue);
}
}
}
I am trying to get the subtotal amount on checkout success page. It works good for registred users:
$_order = Mage::getModel('sales/order')->loadByIncrementId($this->getOrderId());
$amount = $_order->getData('subtotal');
$total = number_format($amount, 2);
But when the order is processed by a guest, $total is empty.
What can be done?
P.S.: I am using Magento 1.6.1 CE
Taken from Magento's app/code/core/Mage/Checkout/Block/Onepage.php:
if (!$this->isCustomerLoggedIn()) {
return $this->getQuote()->getShippingAddress();
} else {
return Mage::getModel('sales/quote_address');
}
I am 99% sure you can do exactly the same with getOrder() and with Mage_Checkout_Block_Success =)
Note: the isCustomerLoggedIn() method is defined at Mage_Checkout_Block_Onepage_Abstract which is not inherited by Mage_Checkout_Block_Success. So, you could simply use its implementation:
public function isCustomerLoggedIn()
{
return Mage::getSingleton('customer/session')->isLoggedIn();
}
E.g. your code now shall look like this:
if (!Mage::getSingleton('customer/session')->isLoggedIn()) {
$order = Mage::getSingleton('checkout/session')->getOrder();
} else {
$order = Mage::getModel('sales/order')->loadByIncrementId($this->getOrderId());
}
Sorry for saying non-sense things before...
I'm trying to write some custom logic for browsing and searching in a Magento store.
So I figured I'd overwrite getProductCollection for both Mage_Catalog_Model_Layer and Mage_CatalogSearch_Model_Layer.
I'm trying to make decisions based on what the value of certain Attributes are for some of the products in the collection, but I can't seem to get the text value of all attributes.
The function as I've overwritten is:
public function getProductCollection()
{
if (isset($this->_productCollections[$this->getCurrentCategory()->getId()])) {
$collection = $this->_productCollections[$this->getCurrentCategory()->getId()];
} else {
$collection = $this->getCurrentCategory()->getProductCollection();
$this->prepareProductCollection($collection);
$this->_productCollections[$this->getCurrentCategory()->getId()] = $collection;
}
//ben
$collection->addAttributeToSelect('parent_sku');
$collection->addAttributeToSelect('door_color');
foreach($collection as $product) {
echo "\nSKU: ".$product->getSku()."\n";
$product_data = $product->getData();
if(isset($product_data['parent_sku']) && ($product_data['parent_sku'] != '')) {
echo "GETDATA PARENT: ".$product_data['parent_sku']."\n";
}
if($product->getAttributeText('parent_sku') != '') {
echo "ATTR TEXT PARENT: ".$product->getAttributeText('parent_sku')."\n";
}
if($product->getAttributeText('door_color') != '') {
echo "ATTR TEXT COLOR: ".$product->getAttributeText('door_color')."\n";
}
}
//end ben
return $collection;
}
This produces output like:
SKU: TEST_SKU_1
GETDATA PARENT: TEST_SKU_2
ATTR TEXT COLOR: Black
Notice:
I add both 'parent_sku' and 'door_color' as attributes to select.
I can access door_color using $product->getAttributeText()
I cannot access parent_sku using $product->getAttributeText()
I can access parent_sku through $product->getData()
Any time I call $product->getAttributeText('parent_sku') it returns false.
I assumed that this was a caching problem, but I flushed the cache and that didn't seem to help.
Does anyone have a clue why I can't access the value of 'parent_sku' through getAttributeText()?
Is parent_sku implemented as a dropdown box? My understanding is that getAttributeText loaded dropdown options and mapped them from and ID to text for you.