Search code examples
phpwoocommercebackendcustom-fieldsorders

Add an editable billing custom field to WooCommerce admin single order


I find a way to manually add a payment date on the order details into the back-office of WooCommerce. I have created a field in the billing address, I find the way to a datepicker. Everything works fine: I am able to edit the billing field and open the date picker.

My custom code:

// Edit Order details to add payment date
add_action( 'woocommerce_admin_order_data_after_billing_address', 'misha_editable_order_meta_billing' );
function misha_editable_order_meta_billing( $order ){
    $billingdate = $order->get_meta( 'billingdate' );
    ?>
        <div class="address">
            <p<?php if( empty( $billingdate ) ) { echo ' class="none_set"'; } ?>>
                <strong>Date deadline:</strong>
                <?php echo ! empty( $billingdate ) ? $billingdate : 'Anytime.' ?>
            </p>
        </div>
        <div class="edit_address">
            <?php
                woocommerce_wp_text_input( array(
                    'id' => 'paymentdate',
                    'label' => 'Date deadline',
                    'wrapper_class' => 'form-field-wide',
                    'class' => 'date-picker',
                    'style' => 'width:100%',
                    'value' => $billingdate,
                    'description' => 'Payment date.'
                ) );
            ?>
        </div>
    <?php
}

add_action( 'woocommerce_process_shop_order_meta', 'misha_save_general_details' );
function misha_save_general_details( $order_id ){
    update_post_meta( $order_id, 'billingdate', wc_clean( $_POST[ 'billingdate' ] ) );
}

I can edit the field, but I cannot save the field value when I click on "Update" button.

Could someone tell me what's wrong? How can I save this field value?


Solution

  • I have revisited your code completely...

    • First, I have renamed your "Billing payment" meta key to WooCommerce billing meta keys conventions.
    • Also, as WooCommerce is migrating progressively to custom tables, I have changed the way that you were trying to save the field.

    The code:

    add_action( 'woocommerce_admin_order_data_after_billing_address', 'add_admin_order_editable_billing_date' );
    function add_admin_order_editable_billing_date( $order ){
        $billing_date    = $order->get_meta( '_billing_date' );
        $billing_date_fr = (new WC_DateTime($billing_date))->date('d/m/Y');
    
        printf('<div class="address"><p%s><strong>%s:</strong> %s</p></div>
            <div class="edit_address">', 
            !$billing_date ? ' class="none_set"' : '',
            __('Date deadline', 'woocommerce'),
            $billing_date ? $billing_date_fr : __('Anytime.', 'woocommerce') 
        );
    
        woocommerce_wp_text_input( array(
            'id'            => '_billing_date',
            'label'         => 'Date deadline (payment date)',
            'wrapper_class' => 'form-field-wide',
            'class'         => 'date-picker',
            'style'         => 'width:100%',
            'value'         => $billing_date,
        ) );
    
        echo '</div>';
    }
    
    add_action( 'woocommerce_process_shop_order_meta', 'save_admin_order_billing_date' );
    function save_admin_order_billing_date( $order_id ){
        if ( isset($_POST[ '_billing_date' ]) ) {
            $order = wc_get_order( $order_id );
            $order->update_meta_data( '_billing_date', wc_clean( wp_unslash( $_POST[ '_billing_date' ] ) ) );
            $order->save();
        }
    }
    

    Code goes in functions.php file of your child theme (or in a plugin). Tested and works.