Disable COD when exceeded specific amount - wordpress

I need to disable Woocommerce COD option and make it unchecked when total price exceeded certain amount.
I tried this code, but does nothing!
add_filter('woocommerce_available_payment_gateways', 'unsetting_payment_gateway', 10, 1);
function unsetting_payment_gateway( $available_gateways ) {
global $woocommerce;
$shipping_cost = WC()->cart->get_cart_shipping_total();
$amount = $woocommerce->cart->cart_contents_total + $woocommerce->cart->tax_total + $shipping_cost;
$max = 999.9 * WCPBC()->customer->exchange_rate;
if($amount >= $max){ ?>
<script type="text/javascript">
jQuery(document).ready(function ($) {
$("#payment_method_cod").disabled = true;
$("#payment_method_cod").checked = false;
});
</script>
<?php
add_action( 'woocommerce_review_order_before_payment', 'COD_exceed_amount_before_paying_notice' );
}
return $available_gateways;
}
function COD_exceed_amount_before_paying_notice() {
wc_print_notice( __( 'COD amount exceeded!', 'woocommerce' ), 'notice' );
}

add_filter( 'woocommerce_available_payment_gateways' , 'hide_payment_gateway', 20, 1);
/**
* remove cod gateway if cart total > 100
* #param $gateways
* #return mixed
*/
function hide_payment_gateway( $gateways ){
//change whatever amount you want
if( WC()->cart->subtotal < 699 ){
// then unset the 'cod' key (cod is the unique id of COD Gateway)
unset( $gateways['cod'] );
add_action( 'woocommerce_review_order_before_payment', 'COD_exceed_amount_before_paying_notice' );
}
return $gateways;
}
function COD_exceed_amount_before_paying_notice() {
wc_print_notice( __( 'COD option not available on orders below 699.00', 'woocommerce' ), 'notice' );
}

First you need to deregister the woocommerce/assets/js/frontend/checkout.js
Then include checkout.js in your theme assets folder and register it again after theme script files
then your code will work as you expect.
for deregister use below code,
wp_deregister_script( $handle );
again register by,
wp_enqueue_script(parameters);

You should change your jquery code. Can you please try below code and check your code again. Because that is working for me.
<script type="text/javascript">
jQuery( document ).ready(function($) {
$("#payment_method_cod").prop('checked', false);
$("#payment_method_cod").attr('disabled', true);
});
</script>

Related

Validating custom Woo checkout field via regex

I'm trying to validate a custom checkout field against a regex expression so that it is a very specifically formatted date.
Here's my code:
add_action('woocommerce_after_checkout_validation', array($this, 'bkf_dd_checkout_validation'), 10, 2 );
add_action('wp_footer', array($this, 'bkf_dd_checkout_validation_js'));
function bkf_dd_checkout_validation( $fields, $errors ){
if( ! preg_match( '/[a-zA-Z]{6,9}\,\ \d{1,2}\ [a-zA-Z]{3,9}\ \d{4}/', $fields['delivery_date'] ) ){
$errors->add( 'validation', 'Please select a <strong>Delivery Date</strong> via the datepicker.' );
}
}
function bkf_dd_checkout_validation_js(){
if( ! is_checkout() ) {
return;
}
?>
<script>
jQuery(function($){
$( 'body' ).on( 'blur change', '#delivery_date', function(){
const wrapper = $(this).closest( '.form-row' );
if( ! /[a-zA-Z]{6,9}\,\ \d{1,2}\ [a-zA-Z]{3,9}\ \d{4}/.test( $(this).val() ) ) {
wrapper.addClass( 'woocommerce-invalid' );
wrapper.removeClass( 'woocommerce-validated' );
} else {
wrapper.addClass( 'woocommerce-validated' );
}
});
});
</script>
<?php
}
The JS is working, but the error is being set regardless of the value, ie. this displays even if field is valid (and set as green by the JS)
(the date format: Friday, 30 December 2022)
Any ideas?
Solution as provided by Vijay Hardaha
Replace $fields['delivery_date'] with $_POST['delivery_date']

Update order total price by payment method after order was placed

I've created a specific method of payment to manage approval or decline of orders for specific products.
Once order was approved I set order in status "Waiting for payment" and send an email to customer with link to pay.
The problem is that for some payment method I have to apply a discount.
I'm able to apply discount before order was placed ( I use it for order that doesn't require approval), but I don't know how to recalcultate the total in this moment.
For do that I use this code:
add_action( 'woocommerce_cart_calculate_fees','payment_method_discount', 20, 1 );
function payment_method_discount( $cart_object ) {
if ( is_admin() && !defined( 'DOING_AJAX' ) ) return;
foreach($cart_object->cart_contents as $cart_item_id => $cart_item) {
$payment_method_arr = array('ppcp-gateway');
foreach($payment_method_arr as $payment_method) {
$percent = 25;
$chosen_payment_method = WC()->session->get('chosen_payment_method');
if( $payment_method == $chosen_payment_method ) {
WC()->cart->add_fee( 'PayPal fee', 0 - $discount );
}
}
}
}
To trigger the update I used:
add_action( 'woocommerce_review_order_before_payment', 'refresh_payment_methods', 20, 1 );
function refresh_payment_methods() {
?>
<script type="text/javascript">
(function($){
$( 'form.checkout' ).on( 'change', 'input[name^="payment_method"]', function() {
$('body').trigger('update_checkout');
});
})(jQuery);
</script>
<?php
}
I've tried also to add the function refresh_payment_methods to wp_footer hook.

Updating cart totals after ajax request

Here is my custom ajax request callback.
I use some data with wp_remote_post and getting json results about my own woocommerce payment gateway installments.
/**
* Check avaliblity for installments via WordPress Ajax
*
* #return void
*/
function check_installment() {
if ( isset($_REQUEST) ) {
$action = data_get($_REQUEST, 'action');
if($action == 'check_installment')
{
$cart_data = WC()->session->get('cart_totals');
$binNumber = data_get($_REQUEST, 'bin');
if(!$binNumber)
{
return;
}
$_initGateway = new Woo_Ipara_Gateway();
$_initGateway = $_initGateway->checkInstallment($binNumber);
$data = [
'cardFamilyName' => data_get($_initGateway, 'cardFamilyName'),
'supportedInstallments' => data_get($_initGateway, 'supportedInstallments')
];
echo json_encode(getInstallmentComissions(data_get($_initGateway, 'cardFamilyName')));
}
}
die();
}
add_action( 'wp_ajax_check_installment', 'check_installment');
add_action( 'wp_ajax_nopriv_check_installment', 'check_installment');
Right now, payment provider, have different comissions for spesific credit card. So it means, i want to change order total after this request, when user's selected installment value.
I also found some filter, about calculated total woocommerce_calculated_total, but how to trigger this, after ajax request and user, selected installment choice?
add_filter( 'woocommerce_calculated_total', 'custom_calculated_total', 10, 2 );
function custom_calculated_total( $total, $cart ){
// some magic.
}
Any helps ? Thanks.
First of all, filter method was wrong, what i wanted to try woocommerce_calculated_total.
It must be, woocommerce_checkout_order_processed
Other issue is, WC()->cart->add_fee( "text", $fee, false, '' ); not really work correctly.
You should use, new WC_Order_Item_Fee() class in your action directly.
Here is the some part of code in my case ;
add_action('woocommerce_checkout_order_processed', 'addFeesBeforePayment', 10, 3);
function addFeesBeforePayment( $order_id, $posted_data, $order ) {
// some logic about bin verification and remote fetch about installment comissions.
$cartTotal = WC()->cart->cart_contents_total;
$newCartTotal = $cartTotal + ( $cartTotal * $defaultComission / 100 );
$installmentFee = $cartTotal * ($defaultComission / 100 );
$item_fee = new WC_Order_Item_Fee();
$item_fee->set_name( 'Kredi Kartı Komisyonu ('.$defaultInstallment.' Taksit)' ); // Generic fee name
$item_fee->set_amount( $installmentFee ); // Fee amount
$item_fee->set_tax_class( '' ); // default for ''
$item_fee->set_tax_status( 'none' ); // or 'none'
$item_fee->set_total( $installmentFee ); // Fee amount
$order->add_item( $item_fee );
$order->calculate_totals();
$order->add_order_note( 'Bu sipariş için ödeme '. $defaultInstallment . ' taksit seçeneği seçilerek oluşturuldu. Toplam taksit komisyonu, sipariş tutarına ek olarak ' . $installmentFee. ' TL karşılığında eklendi.' );
}
Happy coding.

Add "sub-total" to my-account/orders table

Trying to add the order subtotal in woocommerce my-account/orders table but I can't seem to get it to display. Currently it adds the column and the label but its not displaying the orders sub total. I am currently using the code below :
add_filter( 'woocommerce_account_orders_columns',
'add_account_orders_column', 10, 1 );
function add_account_orders_column( $columns ){
$columns['item_subtotal_tax_excl'] = __( 'Sub-total', 'woocommerce' );
return $columns;
}
add_action( 'woocommerce_my_account_my_orders_column_custom-column',
'add_account_orders_column_rows' );
function add_account_orders_column_rows( $order ) {
// Example with a custom field
if ( $value = $order->get_meta( 'item_subtotal_tax_excl' ) ) {
echo esc_html( $value );
}
}
Subtotal like in cart doesn't exist in WooCommerce Orders meta data, so you need to get it and calculate it from order items:
add_filter( 'woocommerce_account_orders_columns', 'add_account_orders_column', 10, 1 );
function add_account_orders_column( $columns ){
$columns['item_subtotal_tax_excl'] = __( 'Sub-total', 'woocommerce' );
return $columns;
}
add_action( 'woocommerce_my_account_my_orders_column_custom-column', 'display_account_orders_column_rows_value' );
function display_account_orders_column_rows_value( $order ) {
$subtotal = 0; // Initializing
// Loop through order items (line items)
foreach ( $order->get_items() as $item ) {
// Sum item subtotal excluding taxes and not discounted
$subtotal += $item->get_subtotal();
}
echo $subtotal;
}
Code goes in functions.php file of your active child theme (or active theme). Tested and works.
Related:
Get Order items and WC_Order_Item_Product in WooCommerce 3
How to get WooCommerce order details
Get the metadata of an order item in woocommerce 3
Edit: the following code worked for me: (answer provided by helgatheviking on woocommerce slack)
//show sub total in order page
add_filter( 'woocommerce_account_orders_columns',
'add_account_orders_column', 10, 1 );
function add_account_orders_column( $columns ){
$columns['item_subtotal_tax_excl'] = __( 'Sub-Total',
'woocommerce' );
return $columns;
}
add_action(
'woocommerce_my_account_my_orders_column_item_subtotal_tax_excl',
'add_account_orders_column_rows' );
function add_account_orders_column_rows( $order ) {
// Example with a custom field
if ( $value = $order->get_subtotal() ) {
echo esc_html( $value );
}
}

Add input field to every item in cart

I am trying to add a new field on my cart.php file.
I actually want to insert a URL field, so user can set a URL for each order item.
I tried to use a code from another post here but I can't get it to work.
The first and the second functions are working but when it comes to the third one, 'woocommerce_get_item_data' the $cart_item['url'] doesn't contain anything even if I add something in the field and I press Update Cart.
$cart_totals[ $cart_item_key ]['url'] from the first function is outputting the right value when the page load.
I don't know what to do now, thanks for any help.
Here is the code
Add the field
cart/cart.php
<td class="product-url">
<?php
$html = sprintf( '<div class="url"><input type="text" name="cart[%s][url]" value="%s" size="4" title="Url" class="input-text url text" /></div>', $cart_item_key, esc_attr( $values['url'] ) );
echo $html;
?>
</td>
functions.php
// get from session your URL variable and add it to item
add_filter('woocommerce_get_cart_item_from_session', 'cart_item_from_session', 99, 3);
function cart_item_from_session( $data, $values, $key ) {
$data['url'] = isset( $values['url'] ) ? $values['url'] : '';
return $data;
}
// this one does the same as woocommerce_update_cart_action() in plugins\woocommerce\woocommerce-functions.php
// but with your URL variable
// this might not be the best way but it works
add_action( 'init', 'update_cart_action', 9);
function update_cart_action() {
global $woocommerce;
if ( ( ! empty( $_POST['update_cart'] ) || ! empty( $_POST['proceed'] ) ) ) {
$cart_totals = isset( $_POST['cart'] ) ? $_POST['cart'] : '';
if ( sizeof( $woocommerce->cart->get_cart() ) > 0 ) {
foreach ( $woocommerce->cart->get_cart() as $cart_item_key => $values ) {
if ( isset( $cart_totals[ $cart_item_key ]['url'] ) ) {
$woocommerce->cart->cart_contents[ $cart_item_key ]['url'] = $cart_totals[ $cart_item_key ]['url'];
}
}
}
}
}
// this is in Order summary. It show Url variable under product name. Same place where Variations are shown.
add_filter( 'woocommerce_get_item_data', 'item_data', 10, 2 );
function item_data( $data, $cart_item ) {
if ( isset( $cart_item['url'] ) ) {
$data['url'] = array('name' => 'Url', 'value' => $cart_item['url']);
}
return $data;
}
// this adds Url as meta in Order for item
add_action ('woocommerce_add_order_item_meta', 'add_item_meta', 10, 2);
function add_item_meta( $item_id, $values ) {
woocommerce_add_order_item_meta( $item_id, 'Url', $values['url'] );
}
Add a textarea field to a WooCommerce cart item
First, we just need to add the textarea field. We use the woocommerce_after_cart_item_name hook so our textarea will appear after the product name.
<?php
/**
* Add a text field to each cart item
*/
function prefix_after_cart_item_name( $cart_item, $cart_item_key ) {
$notes = isset( $cart_item['notes'] ) ? $cart_item['notes'] : '';
printf(
'<div><textarea class="%s" id="cart_notes_%s" data-cart-id="%s">%s</textarea></div>',
'prefix-cart-notes',
$cart_item_key,
$cart_item_key,
$notes
);
}
add_action( 'woocommerce_after_cart_item_name', 'prefix_after_cart_item_name', 10, 2 );
/**
* Enqueue our JS file
*/
function prefix_enqueue_scripts() {
wp_register_script( 'prefix-script', trailingslashit( plugin_dir_url( __FILE__ ) ) . 'update-cart-item-ajax.js', array( 'jquery-blockui' ), time(), true );
wp_localize_script(
'prefix-script',
'prefix_vars',
array(
'ajaxurl' => admin_url( 'admin-ajax.php' )
)
);
wp_enqueue_script( 'prefix-script' );
}
add_action( 'wp_enqueue_scripts', 'prefix_enqueue_scripts' );
´´´
At the moment, the user will be able to enter text into the field but the text won’t save. We are going to use some AJAX to save the text.
The code above not only adds the textarea to the cart item, it also enqueues a JavaScript file ready for our AJAX.
It’s assumed that you’re using the code on this page to create a new plugin. If so, you should create a new JS file with the code below and place the file in the root directory of your plugin.
However, if you’ve added the PHP above to your theme functions.php or as a snippet on your site, you’ll need to change the location of the JS file by updating line 21 of the snippet above to identify the location of the JS file.
´´´
(function($){
$(document).ready(function(){
$('.prefix-cart-notes').on('change keyup paste',function(){
$('.cart_totals').block({
message: null,
overlayCSS: {
background: '#fff',
opacity: 0.6
}
});
var cart_id = $(this).data('cart-id');
$.ajax(
{
type: 'POST',
url: prefix_vars.ajaxurl,
data: {
action: 'prefix_update_cart_notes',
security: $('#woocommerce-cart-nonce').val(),
notes: $('#cart_notes_' + cart_id).val(),
cart_id: cart_id
},
success: function( response ) {
$('.cart_totals').unblock();
}
}
)
});
});
})(jQuery);
´´´
Now, when the user types anything, the contents of the text field get sent back to the server ready to be saved as meta data to the cart item.
´´´
<?php
/**
* Update cart item notes
*/
function prefix_update_cart_notes() {
// Do a nonce check
if( ! isset( $_POST['security'] ) || ! wp_verify_nonce( $_POST['security'], 'woocommerce-cart' ) ) {
wp_send_json( array( 'nonce_fail' => 1 ) );
exit;
}
// Save the notes to the cart meta
$cart = WC()->cart->cart_contents;
$cart_id = $_POST['cart_id'];
$notes = $_POST['notes'];
$cart_item = $cart[$cart_id];
$cart_item['notes'] = $notes;
WC()->cart->cart_contents[$cart_id] = $cart_item;
WC()->cart->set_session();
wp_send_json( array( 'success' => 1 ) );
exit;
}
add_action( 'wp_ajax_prefix_update_cart_notes', 'prefix_update_cart_notes' );
function prefix_checkout_create_order_line_item( $item, $cart_item_key, $values, $order ) {
foreach( $item as $cart_item_key=>$cart_item ) {
if( isset( $cart_item['notes'] ) ) {
$item->add_meta_data( 'notes', $cart_item['notes'], true );
}
}
}
add_action( 'woocommerce_checkout_create_order_line_item', 'prefix_checkout_create_order_line_item', 10, 4 );
´´´
The prefix_update_cart_notes function does a security check using the WooCommerce cart nonce then saves the content of the textarea as meta data in the cart item. You can check out this article for more information about updating cart meta for items that have already been added to the cart.
Add the custom text to the order meta
Finally, we want to pass our meta data to the order so that we can use it after the customer has checked out. The prefix_checkout_create_order_line_item function takes care of that, iterating through each item and saving notes when it finds them.
https://pluginrepublic.com/how-to-add-an-input-field-to-woocommerce-cart-items/

Resources