When creating an invoice with SugarCRM, I would like to add a line to the invoice header section displaying details of the total amount of the invoice (VAT included and VAT excluded) total amount. The two values can be calculated using the price keyed in in the invoice detail section.
I am told to implement this functionality using the logic hook function of SugarCRM. Since I am new to SugarCRM, could you please advise ?
This is what I have done so far :
<?php
class AddLines {
function update_amount(&$bean, $event, $arguments)
{
//Query c_inv_fee_distribution table for detail_amount value of parent
$bean->client_po = 'working';
}
}
class PriceCalc {
function taxdetail(&$bean, $event, $arguments)
{
$total_amt_excl = 0;
$total_amt_incl = 0;
$line_price = $number_units * $unit_price;
$invoicelength = count($bean->invoice);
for ($line_number=0; $line_number < $invoicelength); $line_number++)
{
if $VAT = true {
$total_amt_excl += $line_price[line_number];
$total_amt_incl += $line_price[line_number] * 1.14;
}else {
$total_amt_excl += $line_price[line_number];
$total_amt_incl += $line_price[line_number];
}
}
}
?>
Related
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.
I just started studying OpenCart, downloaded latest version of opencart and reading the documentation about where to find the function definition of tax calculate function.
In the non admin side, opening any Products shows data with tax calculation. Here is code it uses it.
$this->tax->calculate($product_info['price'], $product_info['tax_class_id'], $this->config->get('config_tax'))
Is there any link to check the location of tax class for checking the calculate function definition?
Not quite sure what exactly do you want to achieve. But the calculate function you can find in system/library/cart/tax.php.
public function calculate($value, $tax_class_id, $calculate = true) {
if ($tax_class_id && $calculate) {
$amount = 0;
$tax_rates = $this->getRates($value, $tax_class_id);
foreach ($tax_rates as $tax_rate) {
if ($calculate != 'P' && $calculate != 'F') {
$amount += $tax_rate['amount'];
} elseif ($tax_rate['type'] == $calculate) {
$amount += $tax_rate['amount'];
}
}
return $value + $amount;
} else {
return $value;
}
}
Although in this file you will find a lot of interesting connected with tax processing in OpenCart.
If this information not enough - please, describe the desired result with more details and I will try to help.
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;
}
}
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 )
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...