Shipping Rate Per Product using Configurable Products - php

I'm using a Free, open source flat rate shipping per product extension on Magento CE 1.8. Basically it just creates a new shipping method and you control the price of that method at the product level.
My problem is I'm using configurable products with child simple products. I'm trying to set the shipping rate on the child simple product ie. $5 for a specific option, if I add that option to the cart it shows the shipping rate correctly as $5, but if I add a qty of 3, it still shows $5 instead of $15.
Any idea how to calculate the shipCost of the child products correctly in the cart?
It calculates the shipping rate with this expression, where shipCost is the custom attribute on the product where you enter the rate:
$shippingPrice += $item->getQty() * $shipCost;
I'm thinking the issue is here:
if($product->getTypeId()=='configurable' || $product->getTypeId()=='bundle') {
continue;
}
And here is the full code:
class Magebuzz_Flatrateperproduct_Model_Carrier_Flatrateperproduct
extends Mage_Shipping_Model_Carrier_Abstract
implements Mage_Shipping_Model_Carrier_Interface {
protected $_code = 'flatrateperproduct';
public function collectRates(Mage_Shipping_Model_Rate_Request $request)
{
if (!$this->getConfigFlag('active')) {
return false;
}
$shippingPrice =0;
if ($request->getAllItems()) {
foreach ($request->getAllItems() as $item) {
$product = Mage::getModel('catalog/product')->load($item->getProductId());
if($product->getTypeId()=='configurable' || $product->getTypeId()=='bundle') {
continue;
}
$shipCost= $product->getShipCost();
if($shipCost==null || $shipCost==0){
$shippingPrice += $item->getQty() * $this->getConfigData('price');
}
else{
$shippingPrice += $item->getQty() * $shipCost;
}
}
}
$result = Mage::getModel('shipping/rate_result');
if ($shippingPrice !== false) {
$method = Mage::getModel('shipping/rate_result_method');
$method->setCarrier('flatrateperproduct');
$method->setCarrierTitle($this->getConfigData('title'));
$method->setMethod('flatrateperproduct');
$method->setMethodTitle($this->getConfigData('name'));
$method->setPrice($shippingPrice);
$method->setCost($shippingPrice);
$result->append($method);
}
return $result;
}
public function getAllowedMethods()
{
return array('flatrateperproduct'=>$this->getConfigData('name'));
}
}

Please check this you can get configurable product Quantity by this Code :
if($product->getTypeId()=='configurable' || $product->getTypeId()=='bundle')
{
foreach ($item->getChildren() as $child)
{
$quentity = $item->getQty() * $child->getQty();
}
}
else
{
$quentity = $item->getQty();
}

Related

WooCommerce: Old deleted item comes back when trying to change the quantity of other item in cart

I have created a custom popup cart using WooCommerce. It has functionalities like
Decrease a product
Increase a product
Remove a product
When I remove the product from the top it goes away. I am using this logic to do that using AJAX.
public function remove_item($key)
{
$this->refresh();
$remove = $this->woocommerce->cart->remove_cart_item($key);
$this->woocommerce->cart->calculate_totals();
if ($remove) {
$this->refresh();
return true;
} else {
return false;
}
}
Now I decrease the remaining item, from quantity 2 to 1. What I get back is the already deleted comes back with 1 quantity and the present item is set to 1.
public function set_item_quantity($key, $quantity)
{
if (!is_numeric($quantity)) {
return;
}
$job = $this->woocommerce->cart->set_quantity($key, $quantity, true);
$this->woocommerce->cart->calculate_totals();
if ($job) {
$this->refresh();
return true;
} else {
return false;
}
}
This is what refresh method looks like.
public function refresh()
{
$woocommerce = \WC();
$this->cart = $woocommerce->cart;
$this->woocommerce = $woocommerce;
$this->woocommerce->cart->calculate_totals();
}
This isn't a cache issue, as I have removed my cache plugin and it still gives me issues. The same doesn't happen when the cart has just one product.
Any help is appreciated. Thanks!

Wrong discount calculation on Shopware 6 Price Collector/Processor

I implemented a price collector / processor exactly as described in the docs (https://developer.shopware.com/docs/guides/plugins/plugins/checkout/cart/change-price-of-item).
For testing purposes every line item product in the cart has a price of 100€.
When applying a discount (10%) that I have created in the admin, the discount is applied on the original price of the product but not on the actual new cart price.
What am I missing here? My OverwritePriceCollector.php looks as following:
<?php declare(strict_types=1);
namespace Test\TestPlugin\Core\Checkout\Cart;
use Shopware\Core\Checkout\Cart\Cart;
use Shopware\Core\Checkout\Cart\CartBehavior;
use Shopware\Core\Checkout\Cart\CartDataCollectorInterface;
use Shopware\Core\Checkout\Cart\CartProcessorInterface;
use Shopware\Core\Checkout\Cart\LineItem\CartDataCollection;
use Shopware\Core\Checkout\Cart\LineItem\LineItem;
use Shopware\Core\Checkout\Cart\Price\AbsolutePriceCalculator;
use Shopware\Core\Checkout\Cart\Price\PercentagePriceCalculator;
use Shopware\Core\Checkout\Cart\Price\QuantityPriceCalculator;
use Shopware\Core\Checkout\Cart\Price\Struct\AbsolutePriceDefinition;
use Shopware\Core\Checkout\Cart\Price\Struct\PercentagePriceDefinition;
use Shopware\Core\Checkout\Cart\Price\Struct\QuantityPriceDefinition;
use Shopware\Core\System\SalesChannel\SalesChannelContext;
class OverwritePriceCollector implements CartDataCollectorInterface, CartProcessorInterface
{
/**
* #var QuantityPriceCalculator
*/
private $calculator;
public function __construct(QuantityPriceCalculator $calculator) {
$this->calculator = $calculator;
}
public function collect(CartDataCollection $data, Cart $original, SalesChannelContext $context, CartBehavior $behavior): void
{
// get all product ids of current cart
$productIds = $original->getLineItems()->filterType(LineItem::PRODUCT_LINE_ITEM_TYPE)->getReferenceIds();
// remove all product ids which are already fetched from the database
$filtered = $this->filterAlreadyFetchedPrices($productIds, $data);
// Skip execution if there are no prices to be saved
if (empty($filtered)) {
return;
}
foreach ($filtered as $id) {
$key = $this->buildKey($id);
// Needs implementation, just an example
$newPrice = 100;
// we have to set a value for each product id to prevent duplicate queries in next calculation
$data->set($key, $newPrice);
}
}
public function process(CartDataCollection $data, Cart $original, Cart $toCalculate, SalesChannelContext $context, CartBehavior $behavior): void
{
// get all product line items
$products = $toCalculate->getLineItems()->filterType(LineItem::PRODUCT_LINE_ITEM_TYPE);
foreach ($products as $product) {
$key = $this->buildKey($product->getReferencedId());
// no overwritten price? continue with next product
if (!$data->has($key) || $data->get($key) === null) {
continue;
}
$newPrice = $data->get($key);
// build new price definition
$definition = new QuantityPriceDefinition(
$newPrice,
$product->getPrice()->getTaxRules(),
$product->getPrice()->getQuantity()
);
// build CalculatedPrice over calculator class for overwritten price
$calculated = $this->calculator->calculate($definition, $context);
// set new price into line item
$product->setPrice($calculated);
$product->setPriceDefinition($definition);
}
}
private function filterAlreadyFetchedPrices(array $productIds, CartDataCollection $data): array
{
$filtered = [];
foreach ($productIds as $id) {
$key = $this->buildKey($id);
// already fetched from database?
if ($data->has($key)) {
continue;
}
$filtered[] = $id;
}
return $filtered;
}
private function buildKey(string $id): string
{
return 'price-overwrite-'.$id;
}
}
I think your problem is that you registered your Collector with the same priority as in documentation (4500).
Shopware PromotionProcessor is registered with priority 4900, so your code is called after PromotionProcessor.
So what do you need is to register your OverwritePriceCollector with higher priority e.g. 5000.

Magento 1.9 remove tax on checkout when user enter VAT

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;
}
}

Magento hide a shipping method or change it's price through a Observer

I have created a Magento module with an Observer that should hide a certain shipping method, but I can't get it to work.
class Company_Modulename_Model_Observer
{
public function hideShippingMethods(Varien_Event_Observer $observer)
{
if (Mage::getDesign()->getArea() === Mage_Core_Model_App_Area::AREA_FRONTEND) {
$quote = $observer->getEvent()->getQuote();
$store = Mage::app()->getStore($quote->getStoreId());
$carriers = Mage::getStoreConfig('carriers', $store);
$newPrice = 10;
foreach ($carriers as $carrierCode => $carrierConfig) {
if ($carrierCode == 'flatrate') {
$store->setConfig('carriers/flatrate/price', $newPrice);
$store->setConfig('carriers/flatrate/showmethod', '0');
$store->setConfig('carriers/flatrate/active', '0');
$store->setConfig('carriers/flatrate/title', 'Test title');
}
}
}
}
}
Of all the setConfig settings only the $store->setConfig('carriers/flatrate/title', 'Test title'); works.
So the title of the delivery method gets changed in the checkout, but the price doesn't change and it is still shown.
How can I hide or change the price of a certain shippig method?

Magento PHP Fatal error: Call to a member function setName() on a non-object

I have a problem within the magento checkout. With integrating Billsafe Payment plugin I get the following error in checkout process:
HTTP-Error 500 (Internal Server Error):
The error log says:
mod_fcgid: stderr: PHP Fatal error: Call to a member function setName() on a non-object in /var/www/vhosts/domain.com/httpdocs/app/code/community/AwHh/PaymentFee/Helper/Data.php
Any Ideas?
The code of Data.php:
/**
* Check if the extension is active
*
* #return boolean
*/
public function isEnabled()
{
return (bool)Mage::getStoreConfig('payment_services/paymentfee/active');
}
/**
* Check if minimum fee amount, maximum fee amount or percentage rate is given
* #return boolean
*/
public function hasFeeValues()
{
$min = (bool)max(0, Mage::getStoreConfig('payment_services/paymentfee/min_fee_amount'));
$max = (bool)Mage::getStoreConfig('payment_services/paymentfee/max_fee_amount');
$rate = (bool)Mage::getStoreConfig('payment_services/paymentfee/relative_fee');
return ($min || $max || $rate);
}
public function getFeeProductSku()
{
return Mage::getStoreConfig('payment_services/paymentfee/sku');
}
/**
* if item represents fee product
*
* #param Mage_Catalog_Model_Product|Mage_Sales_Model_Item $product
* #return boolean
*/
public function isFeeProduct($product)
{
return ($product->getSku() == $this->getFeeProductSku());
}
public function setFeeProduct($feeProduct)
{
$this->feeProduct = $feeProduct;
}
public function getFeeProduct()
{
if (is_null($this->feeProduct)) {
$this->feeProduct = Mage::getModel('catalog/product')->loadByAttribute('sku', $this->getFeeProductSku());
}
return $this->feeProduct;
}
public function hasFeeProduct()
{
$feeProduct = $this->getFeeProduct();
return ($feeProduct && 0 < $feeProduct->getId());
}
/**
* Obtain the fee that is set for the current payment method
* #return float
*/
public function getPaymentFee()
{
if (!$this->isEnabled()) {
return 0;
}
if (!Mage::getModel('checkout/cart')->getQuote()->getPayment()->hasMethodInstance()) {
return 0;
}
// get the currently set payment method
$payment_model = Mage::getModel('checkout/cart')->getQuote()->getPayment()->getMethodInstance();
// check which methods are enabled for payment fee via backend
$enabled_methods = explode(',', Mage::getStoreConfig('payment_services/paymentfee/payment_methods'));
if (!$payment_model || !in_array($payment_model->getCode(), $enabled_methods)) {
return 0;
}
// return fee if
// (1) a payment method has been selected by the customer
// (2) the selected payment method is enabled for payment fee via backend
// (3) the payment method has a fee
return (float)$payment_model->getFee();
}
/**
* get quote item representing fee
*
* #return Mage_Sales_Model_Quote_Item
*/
protected function getFeeQuoteItem()
{
foreach (Mage::getSingleton('checkout/session')->getQuote()->getItemsCollection() as $item) {
if ($this->isFeeProduct($item->getProduct())) {
return $item;
}
}
}
/**
* Computed amount of payment fee based on backend configuration
* and grand total and attach it to fee product.
*/
public function getUpdatedFeeProduct($product=null, $grandTotal=null)
{
if (!$product) {
$product = $this->getFeeProduct();
}
$product->setName($product->getResource()->getAttributeRawValue($product->getId(), 'name', Mage::app()->getStore()->getId()));
if (!$grandTotal) {
$quote = Mage::getSingleton('checkout/session')->getQuote();
$grandTotal = $quote->getGrandTotal();
$feeAmount = 0;
foreach ($quote->getItemsCollection() as $quoteItem) {
if ($this->isFeeProduct($quoteItem->getProduct())) {
$feeAmount = $quoteItem->getBaseRowTotalInclTax();
continue;
}
}
$grandTotal -= $feeAmount;
}
$min = max(0, Mage::getStoreConfig('payment_services/paymentfee/min_fee_amount'));
$max = Mage::getStoreConfig('payment_services/paymentfee/max_fee_amount');
$rate = Mage::getStoreConfig('payment_services/paymentfee/relative_fee');
//$product->setName($this->__('Payment fee'));
if ($this->getFeeQuoteItem()) {
$product->setTaxPercent($this->getFeeQuoteItem()->getTaxPercent());
}
// first, set payment fee to the price configured in backend
$price = $max;
// If set to zero, do not limit the final fee
if (!$max) {
$max = INF;
}
$product->setCheckoutDescription($this->formatPrice($price))
->setExceedsMaxAmount(false)
->setExceedsMinAmount(false);
// calculate relative fee if given in backend
if ($rate) {
$price = $grandTotal * $rate / 100;
if ($max < $price) {
// calculated relative fee exceeds maximum charge
// -> use maximum charge
$product->setCheckoutDescription($this->formatPrice($max));
$product->setExceedsMaxAmount(true);
$price = $max;
} elseif ($price < $min) {
// calculated relative fee is below minimum charge
// -> use minimum charge
$product->setCheckoutDescription($this->formatPrice($min));
$product->setExceedsMinAmount(true);
$price = $min;
} else {
// calculated relative fee is between minimum and maximum charge
// -> use calculated relative fee
$msg = '%s (%s%% of Total %s)';
$product->setCheckoutDescription($this->__(
$msg,
$this->formatPrice($price),
$rate,
$this->formatPrice($grandTotal)
));
$msg = '%s %s (%s%% of Total %s)';
$product->setName($this->__(
$msg,
$product->getName(),
strip_tags($this->formatPrice($price)),
$rate,
strip_tags($this->formatPrice($grandTotal))
));
}
}
$product->setPriceInclTax($price)
->setPrice($price)
->setFinalPrice($price);
// Make sure fee product is "in stock"
$stockItem = Mage::getModel('cataloginventory/stock_item');
$stockItem->assignProduct($product);
$stockItem->setIsInStock(1);
$stockItem->setManageStock(1);
$stockItem->setQty(10000);
$stockItem->save();
return $product;
}
public function removeFeeFromQuote(Mage_Sales_Model_Quote $quote)
{
foreach ($quote->getItemsCollection() as $quoteItem) {
if ($this->isFeeProduct($quoteItem->getProduct())) {
$quote->removeItem($quoteItem->getId());
}
}
}
}
I had the same problem.
Solution:
You propably didnt add the virtual article.
Go to your Adminarea, choose catalog -> manage article
add a new one and choose virtual article
give some name for it and make sure its activce and NOT visible
set the SKU to something and copy it. you need it later!
set price zero and stock at least 1
you can choose if you give it a higher stock or just one and turn of the stock management.
after saving go to system->configuration->paymenttypes and there you have to
paste the SKU you just copied into the field where it says some with SKU.
after all you have to clear your cache's and there you go :)
A helper class extends extends Mage_Core_Helper_Abstract..
class Mage_Catalog_Helper_Data does not extend varien_object so getName() function will genertae this error.
instead of call getname from helper class object.
use
$model = getmodel('whatever') and then call
$model->getName() from there.
Alternatively you can disable Billsafe under Configuration (System->Configuration->payment) (set Active: no )

Categories