Reputation: 115
Currently, I'm working on a WooCommerce (5.2.2) project. My client wants to create a custom input field for Advance payment in the Backend (not for customers) so that when my client received an advance payment from the customer (delivery purpose) they can add manually and order total auto adjust from the backend. So I've wright a code and create a custom field in the post meta table and use that meta table value to calculate the total order, it works but I have to refresh twice to get Order's total new value. here is my code and tell me how to fix it -
add_action( 'manage_shop_order_posts_custom_column' , array(&$this,'add_custom_column_content'), 11, 2 );
add_action( 'woocommerce_admin_order_totals_after_discount', array(&$this, 'vp_add_sub_total'), 10, 1);
add_action( 'woocommerce_process_shop_order_meta', array(&$this, 'save_order_custom_field_meta_data'), 12, 2 );
// Output a custom editable field in backend edit order pages under general section
function editable_order_custom_field( $order ){
// Get "Delivery Type" from meta data (not item meta data)
$updated_advance_payment = $order->get_meta('_advance_payment');
// Replace "Delivery Type" value by the meta data if it exist
$advancePayment = $updated_advance_payment ? $updated_advance_payment : ( isset($item_value) ? $item_value : '');
// Display the custom editable field
woocommerce_wp_text_input(
array(
'id' => 'advance_payment',
'label' => __("Advance Payment:", "woocommerce"),
'value' => $advancePayment,
'wrapper_class' => 'form-field-wide',
)
);
}
// Save the custom editable field value as order meta data and update order item meta data
function save_order_custom_field_meta_data( $post_id, $post ){
if( isset( $_POST[ 'advance_payment' ] )){
update_post_meta( $post_id, '_advance_payment', sanitize_text_field( $_POST[ 'advance_payment' ] ) );
// Update the existing item meta data
if( isset( $_POST[ 'item_id_ref' ] ) ){
wc_update_order_item_meta( $_POST[ 'item_id_ref' ], 'Advance Payment', $_POST[ 'advance_payment' ] );
}
}
}
//Display Advance Payment and calculate
function vp_add_sub_total( $the_order ) {
global $post, $the_order;
if ( empty( $the_order ) || $the_order->get_id() !== $post->ID ) {
$the_order = wc_get_order( $post->ID );
}
?>
<tr>
<td class="label">Advance Payment:</td>
<td width="1%"></td>
<td class="total"><?php echo wc_price(get_post_meta($post->ID, "_advance_payment", true));?></td>
</tr>
<?php
$getTotal = $the_order->get_total();
$updateTotal = $getTotal - get_post_meta($post->ID, "_advance_payment", true);
$the_order->set_total($updateTotal);
$the_order->save();
}
Note : I create a small plugin for this advance payment.
Video link for reference : https://www.awesomescreenshot.com/video/3589010?key=b26b5951753bfdc8a969b53f526a36d1
Upvotes: 3
Views: 2458
Reputation: 88
I was looking for this solution. Unfortunately the solution posted above gave this error "Unsupported operand types: string - string". I used var_dump($getTotal); var_dump( $advanced_payment);
to analyze the data. Since it's adding+ 2 numbers that are in a string add (int)
or (float)
before variable $variable
. float
is used when numbers contain a decimal. Use (int)
for integers that are whole numbers. Example: (int)$variable
, (float)$variable
. Here's an article which helped me. Here's the modified solution which gave no errors and updated the order total.
add_action( 'woocommerce_admin_order_item_headers', 'calculate_advance_payment', 10, 1);
add_action( 'woocommerce_admin_order_totals_after_discount', 'vp_add_sub_total', 10, 1);
add_action( 'woocommerce_process_shop_order_meta', 'save_order_custom_field_meta_data', 12, 2 );
add_action( 'woocommerce_admin_order_data_after_order_details', 'editable_order_custom_field' );
// Output a custom editable field in backend edit order pages under general section
function editable_order_custom_field( $order ){
// Get "Delivery Type" from meta data (not item meta data)
$updated_advance_payment = $order->get_meta('advance_payment');
// Replace "Delivery Type" value by the meta data if it exist
$advanced_payment = $updated_advance_payment ? $updated_advance_payment : ( isset($item_value) ? $item_value : '');
// Display the custom editable field
woocommerce_wp_text_input(
array(
'id' => 'advance_payment',
'label' => __("Advance Payment:", "woocommerce"),
'value' => $advanced_payment,
'wrapper_class' => 'form-field-wide',
)
);
}
// Save the custom editable field value as order meta data and update order item meta data
function save_order_custom_field_meta_data( $post_id, $post ){
//global $order;
if( isset( $_POST[ 'advance_payment' ] )){
update_post_meta( $post_id, 'advance_payment', sanitize_text_field( $_POST[ 'advance_payment' ] ) );
// Update the existing item meta data
if( isset( $_POST[ 'item_id_ref' ] ) ){
wc_update_order_item_meta( $_POST[ 'item_id_ref' ], 'Advance Payment', $_POST[ 'advance_payment' ] );
}
}
}
function calculate_advance_payment( $order ) {
$order_id = $order->get_id();
$getTotal = $order->get_total();
$advanced_payment = get_post_meta($order_id, 'advance_payment', true);
$order_total = (float)$getTotal - (float)$advanced_payment;
$order->set_total( $order_total );
$order->save();
}
function vp_add_sub_total( $order ) {
global $post, $order;
?>
<tr>
<td class="label">Advance Payment:</td>
<td width="1%"></td>
<td class="total"><?php echo wc_price(get_post_meta($post->ID, "advance_payment", true));?></td>
</tr><?php
}
Upvotes: 1
Reputation: 11282
You need to calculate Advance Payment
before display. you can use woocommerce_admin_order_item_headers
action hook.
add_action( 'woocommerce_admin_order_item_headers', 'calculate_advance_payment', 10, 1);
add_action( 'woocommerce_admin_order_totals_after_discount', 'vp_add_sub_total', 10, 1);
add_action( 'woocommerce_process_shop_order_meta', 'save_order_custom_field_meta_data', 12, 2 );
add_action( 'woocommerce_admin_order_data_after_order_details', 'editable_order_custom_field' );
// Output a custom editable field in backend edit order pages under general section
function editable_order_custom_field( $order ){
// Get "Delivery Type" from meta data (not item meta data)
$updated_advance_payment = $order->get_meta('_advance_payment');
// Replace "Delivery Type" value by the meta data if it exist
$advancePayment = $updated_advance_payment ? $updated_advance_payment : ( isset($item_value) ? $item_value : '');
// Display the custom editable field
woocommerce_wp_text_input(
array(
'id' => 'advance_payment',
'label' => __("Advance Payment:", "woocommerce"),
'value' => $advancePayment,
'wrapper_class' => 'form-field-wide',
)
);
}
// Save the custom editable field value as order meta data and update order item meta data
function save_order_custom_field_meta_data( $post_id, $post ){
if( isset( $_POST[ 'advance_payment' ] )){
update_post_meta( $post_id, '_advance_payment', sanitize_text_field( $_POST[ 'advance_payment' ] ) );
// Update the existing item meta data
if( isset( $_POST[ 'item_id_ref' ] ) ){
wc_update_order_item_meta( $_POST[ 'item_id_ref' ], 'Advance Payment', $_POST[ 'advance_payment' ] );
}
}
}
function calculate_advance_payment( $the_order ) {
$getTotal = $the_order->get_total();
$updateTotal = $getTotal - get_post_meta($the_order->get_id(), "_advance_payment", true);
$the_order->set_total($updateTotal);
$the_order->save();
}
function vp_add_sub_total( $the_order ) {
global $post, $the_order; ?>
<tr>
<td class="label">Advance Payment:</td>
<td width="1%"></td>
<td class="total"><?php echo wc_price(get_post_meta($post->ID, "_advance_payment", true));?></td>
</tr><?php
}
Upvotes: 6