Delete specific product from cart depend on shipping method - cart

On my woocommerce site, there are 2 shipping methods. Delivery and local pickup.
I use a code to add specific product to cart if the cart subtotal is under a value. If the subtotal is higher than the limit (in the code) the product will be removed.
Here is the code:
add_action( 'woocommerce_before_calculate_totals', 'adding_promotional_product', 10, 1 );
function adding_promotional_product( $cart ) {
if ( is_admin() && ! defined( 'DOING_AJAX' ) )
return;
if ( did_action( 'woocommerce_before_calculate_totals' ) >= 2 )
return;
$promo_id = 18625; // <=== <=== <=== Set HERE the ID of your promotional product
$targeted_cart_subtotal = 100000; // <=== Set HERE the target cart subtotal
$has_promo = false;
$subtotal = 0;
if ( ! $cart->is_empty() ){
// Iterating through each item in cart
foreach ($cart->get_cart() as $item_key => $cart_item ){
$product_id = version_compare( WC_VERSION, '3.0', '<' ) ? $cart_item['data']->id : $cart_item['data']->get_id();
// If Promo product is in cart
if( $product_id == $promo_id ) {
$has_promo = true;
$promo_key= $item_key;
} else {
// Adding subtotal item to global subtotal
$subtotal += $cart_item['line_subtotal'];
}
}
// If Promo product is NOT in cart and target subtotal not reached, we add it.
if( ! $has_promo && $subtotal < $targeted_cart_subtotal ) {
$cart->add_to_cart( $promo_id );
// echo 'add';
// If Promo product is in cart and target subtotal is reached, we remove it.
} elseif( $has_promo && $subtotal > $targeted_cart_subtotal ) {
$cart->remove_cart_item( $promo_key );
}
}
}
The code is working good, but i would like to set this option for only 1 shipping method, which is the delivery. if customer would choose local pickup, it should delete it from the cart
Could someone help me how to resolve this?

Related

Make the cart automatically add quantity to 0 to cart page in WooCommcerce

I need my cart page to automatically add products to it when user visits the cart page with quantity 0, I tried to change it by:
I tried code 1 and code 2 with some variations but when I click on update cart the quantity get again to zero. For that product, although total remains the same.
What it should is the cart items wit zero quantities should not be removed when I update the cart and the quantity of that product which I changes from 0 to 1 should be get to 1.
Code 1
function add_product_to_cart_new() {
if ( ! is_admin() ) {
$product_id = array(2595,2594,1404,2650,1410,2652); //replace with your own product id
$found = false;
//check if product already in cart
if ( sizeof( WC()->cart->get_cart() ) > 0 ) {
foreach ( WC()->cart->get_cart() as $cart_item_key => $values ) {
$_product = $values['data'];
if (in_array($_product->get_id(), $product_id))
//if ( $_product->get_id() == $product_id )
$found = true;
}
//if product not found, add it
if ( ! $found )
foreach($product_id as $ids ){
WC()->cart->add_to_cart( $ids);
}
} else {
//if no products in cart, add it
foreach($product_id as $ids ){
WC()->cart->add_to_cart( $ids);
}
}
}
}
And then below code (input_value) to make it zero on cart page.
Code 2
add_filter( 'woocommerce_quantity_input_args', 'jk_woocommerce_quantity_input_args', 10, 2 ); // Simple products
function jk_woocommerce_quantity_input_args( $args, $product ) {
//if ( is_singular( 'product' ) ) {
if( is_cart() ){
$args['input_value'] = 0; // Starting value (we only want to affect cart page)
}
//}
$args['max_value'] = 80; // Maximum value
$args['min_value'] = 0; // Minimum value
$args['step'] = 1; // Quantity steps
return $args;
}
Expected results like in this:
http://www.ecotechlube.com/cart/
This isn't perfect, but it is the only way I have found to do this.
First of all, you need to add product to cart with a magic small quantity, like this:
WC()->cart->add_to_cart($product_id, 0.00000001);
Then you need to make checks in cart and checkout templates like this:
if($cart_item['quantity'] == 0.00000001) $cart_item['quantity'] = 0;

Get sum of multiplication of two column values from unrelated tables in cart

In my laravel ecommerce project
I have 2 tables in the database :
cart [c_id(pk), laundry, l1, dryclean, dc1, dc2, dc3, shop_id]
price [p_id, p_l1, p_dc1, p_dc2, p_dc3, shop_id]
In controller I get prices of logged in shop i.e. single row
$price = DB::table('price')->where('price.shop_id', '=', auth()->id())->get();
also to get a row from cart table I am taking the most recent entry
$cart = DB::table('cart')->latest()->first();
Laundry and dryclean columns from cart table can have two values YES and NO. If laundry is yes then user also enters l1(which is quantity) else null.
similarly, for dryclean column can have two values YES and NO. If YES then user also enters dc1, dc2, dc3(quantities of items).
Now I want to get the Total amount on checkout page from controller including conditions where values of laundry and dryclean are checked.
So far I was calculating total in the view file.
#if ( $cart->dryclean == "no")
#php $c1=0;$c2=0;$c3=0; #endphp
#else
#if (is_null($cart->dc1))
#php $c1=0; #endphp
#else
#php
$a1= $cart->dc1;
$b1 =$price->p_dc1;
$c1= $a1*$b1;
#endphp
#endif
#if (is_null($cart->dc2))
#php $c2=0; #endphp
#else
#php
$a2= $cart->dc2;
$b2 =$price->p_dc2;
$c2= $a2*$b2;
#endphp
#endif
#if (is_null($cart->dc3))
#php $c3=0; #endphp
#else
#php
$a3= $cart->dc3;
$b3 =$price->p_dc3;
$c3= $a3*$b3;
#endphp
#endif
{{ $c1 + $c2 + $c3}} <!-- This is total amount -->
#endif
Please help me writing controller queries to calculate total amount in controller itself and display in the view.
Thanks in advance.
Just remove the blade syntax of everything you did.
if ( $cart->dryclean == "no" ) {
$c1 = 0;
$c2 = 0;
$c3 = 0;
} else {
if ( is_null($cart->dc1) ) {
$c1 = 0;
} else {
$a1 = $cart->dc1;
$b1 = $price->p_dc1;
$c1 = $a1 * $b1;
}
if ( is_null($cart->dc2) ) {
$c2 = 0;
} else {
$a2 = $cart->dc2;
$b2 = $price->p_dc2;
$c2 = $a2 * $b2;
}
if ( is_null($cart->dc3) ) {
$c3 = 0;
} else {
$a3 = $cart->dc3;
$b3 = $price->p_dc3;
$c3 = $a3 * $b3;
}
// total used to be calculated here
}
$total = $c1 + $c2 + $c3;
return view('your.view.here')->with('total', $total);
Some tips, based on what I see:
Use a Boolean value in the $cart->dryclean field. This is easier to store and use than "yes" and "no".
You were calculating the total in blade before you got to the end of your first"if" statement. If the dryclean value was no (or false), no total would have been given.
For your own readability, I recommend using the full name, such as $cost1. I actually can't even tell if that is your intention because it just says 'c1'..
You can bypass many of the calculations by using the null coalesce operator to give a default value if the first one is null.
If you take my tips, you could have your controller be like the example below.
if ( $cart->dryclean ) {
$cost1 = ($cart->dc1 ?? 0) * $price->p_dc1;
$cost2 = ($cart->dc2 ?? 0) * $price->p_dc2;
$cost3 = ($cart->dc3 ?? 0) * $price->p_dc3;
} else {
$cost1 = 0;
$cost2 = 0;
$cost3 = 0;
}
$total = $cost1 + $cost2 + $cost3;
return view('your.view.here')->with('total', $total);
If you wanted to take it a step further, you could do this (using the ternary operator):
// set class properties
$this->cart = $cart;
$this->price = $price;
$total = ( $cart->dryclean )
? $this->costOf('1') + $this->costOf('2') + $this->costOf('3')
: 0;
return view('your.view.here')->with('total', $total);
Of course, this is using another private function outside of the original controller function:
private funtion costOf($number)
{
return ( $this->cart->{'dc'.$number} ?? 0 ) * $this->price->{'p_dc'.$number};
}
This costOf function is using the string version of the number to grab the associated fields on each model type.

how to load customer/group into Mage_Catalog_Model_Product_Type_Price

SOLVED By using Price Rules
i have changed the price scheme based on customer group by percentage. So here I do the trick for the product
if ($group->getCode() == "High ST. Shops") {
$percent = 100 - $_product->getHighstshopPerc();
$percent = "0." . $percent;
$srrp = $_product->getPrice() * $percent;
echo "Your Price £" . number_format($srrp, 2, '.', '');
}
Now I need getPrice() to come from price.php already with my new scheme so it adds to cart correctly. I tried the code below but i cant get getCode() to give me customer group so I can calculate/override getPrice
public function getPrice($product)
{
//$groupId = Mage::getSingleton('customer/session')->getCustomerGroupId();
//$group = Mage::getModel('customer/group')->load($groupId);
//return $product->getData('price');
//return $product->getTradePerc();
//echo $product->getCode(); exit();
if ($product->getCode() == "NOT LOGGED IN")
return 1;
else return 2;
}

Magento partial refund programmatically

How can i create partial create memo? i.e. if total order value is £50 and I want to create a credit memo of £10. I am using the below code to create credit memo:
function createCreditMemo($orderId) {
$order = Mage::getModel('sales/order')->load($orderId, 'increment_id');
if (!$order->getId()) {
print_r('order_not_exists');
}
if (!$order->canCreditmemo()) {
Mage::log('cannot_create_creditmemo', null, 'product.txt');
print_r('cannot_create_creditmemo');
}
$data = array();
$refundToStoreCreditAmount = '10.22';
$service = Mage::getModel('sales/service_order', $order);
$creditmemo = $service->prepareCreditmemo($data);
// refund to Store Credit
if ($refundToStoreCreditAmount) {
// check if refund to Store Credit is available
if ($order->getCustomerIsGuest()) {
print_r('cannot_refund_to_storecredit');
}
$refundToStoreCreditAmount = max(
0,
min($creditmemo->getBaseCustomerBalanceReturnMax(), $refundToStoreCreditAmount)
);
if ($refundToStoreCreditAmount) {
$refundToStoreCreditAmount = $creditmemo->getStore()->roundPrice($refundToStoreCreditAmount);
$creditmemo->setBaseCustomerBalanceTotalRefunded($refundToStoreCreditAmount);
$refundToStoreCreditAmount = $creditmemo->getStore()->roundPrice(
$refundToStoreCreditAmount*$order->getStoreToOrderRate()
);
// this field can be used by customer balance observer
$creditmemo->setBsCustomerBalTotalRefunded($refundToStoreCreditAmount);
// setting flag to make actual refund to customer balance after credit memo save
$creditmemo->setCustomerBalanceRefundFlag(true);
print_r($refundToStoreCreditAmount.'<br/>');
//die('2');
}
}
//Mage::log($creditmemo, null, 'product.txt');
$creditmemo->setPaymentRefundDisallowed(true);
$creditmemo->register();
$orderCreditMemoStatusCode = Mage_Sales_Model_Order::STATE_CLOSED;
$orderCreditMemoStatusComment = 'Order Refunded.';
$saveTransaction = Mage::getModel('core/resource_transaction')->addObject ($creditmemo )->addObject ( $order )->save ();
$order->addStatusToHistory ( $orderCreditMemoStatusCode, $orderCreditMemoStatusComment, true );
$notifyCustomer = true;
$comment = 'testing refund';
$includeComment = true;
$creditmemo->setEmailSent(true);
// add comment to creditmemo
if (!empty($comment)) {
$creditmemo->addComment($comment, $notifyCustomer);
}
try {
Mage::getModel('core/resource_transaction')
->addObject($creditmemo)
->addObject($order)
->save();
// send email notification
$creditmemo->sendEmail($notifyCustomer, ($includeComment ? $comment : ''));
} catch (Mage_Core_Exception $e) {
print_r('data_invalid', $e->getMessage());
}
echo $creditmemo->getIncrementId();
}
In the below code, even if I set the $refundToStoreCreditAmount = 10; it still refunds the full amount. Any idea how to refund partially?

Pass fees from one shipping method to another

I have a tricky shipping issue that I'm trying to work out. I have a custom extension that calculates the table rates for all of the domestic shipping. But for international, one type of product(category A) is a flat $35/product shipping fee and the rest of the products (categories B and C) are calculated by UPS and USPS. The only way I've been able to figure out how to properly calculate shipping if a customer purchases both types of products is to create a table rate for Category A, then pass it along to UPS/USPS as a handling fee. Is there a variable/method I can use for this process? I haven't yet found one.
As requested, here's my function:
public function collectRates(Mage_Shipping_Model_Rate_Request $request)
{
// Cut out code where it adds up the categories and the number of items in each category
$rates = $this->getRates($request, $_categories);
if (!empty($rates))
{
$rateTypes = array();
foreach($rates as $rate)
{
$rateTypes[] = $rate['method_name'];
}
$rateTypes = array_unique($rateTypes);
$i=0;
// Create array to pass along to UPS/USPS, if needed
$tempCategories = $_categories;
foreach($rateTypes as $rateType)
{
$groupPrice = 0;
foreach($_categories as $category=>$catQty)
{
$rateExists = false;
$standardRate = 0;
foreach($rates as $rate)
{
$rateCats = explode(',',$rate['category_list']);
if(in_array($category,$rateCats) && $rate['method_name'] == $rateType )
{
$rateExists = true;
if($rate['condition_type'] == 'I'){
$ratePrice = $rate['price'] * $catQty;
}
else if ($rate['condition_type'] == 'O') {
$ratePrice = $rate['price'];
}
unset($tempCategories[$category]);
}
else if(in_array($category,$rateCats) && $rate['method_name'] == "Standard" && $rateType != "Standard")
{
if($rate['condition_type'] == 'I'){
$standardRate += $rate['price'] * $catQty;
}
else if ($rate['condition_type'] == 'O') {
$standardRate += $rate['price'];
}
unset($tempCategories[$category]);
}
}
if($rateExists == false)
{
$groupPrice += $standardRate;
}
else
$groupPrice += $ratePrice;
}
if(count($tempCategories) > 0)
{
// Figure out how to pass the $groupPrice to other shipping methods here
}
else {
$method = Mage::getModel('shipping/rate_result_method');
$method->setCarrier('shippingcodes');
$method->setCarrierTitle($this->getConfigData('title'));
$method->setMethod('shippingcodes_'.$rateType);
$method->setMethodTitle($rateType);
$method->setPrice($groupPrice);
$result->append($method);
}
}
}
else
return false;
return $result;
}

Resources