Plugin Directory

Changeset 3285848


Ignore:
Timestamp:
05/01/2025 08:03:05 PM (11 months ago)
Author:
ceretax
Message:

Woo Commerce V1.4.2

Location:
ceretax
Files:
25 added
6 edited

Legend:

Unmodified
Added
Removed
  • ceretax/trunk/assets/js/front.js

    r3219747 r3285848  
    22
    33    // Caclulate tax if option enabled
    4     if ( cwa_front_ajax_object && cwa_front_ajax_object.is_ceretax_enable && cwa_front_ajax_object.enable_address_change == 1 ) {
     4    // if ( cwa_front_ajax_object && cwa_front_ajax_object.is_ceretax_enable == 1 && cwa_front_ajax_object.enable_address_change == 1 ) {
     5    if ( cwa_front_ajax_object && cwa_front_ajax_object.is_ceretax_enable == 1 ) {
    56       
    67        function debounce(func, wait) {
     
    193194        return false;
    194195    }
    195 
    196196    jQuery.ajax({
    197197        type: 'POST',
  • ceretax/trunk/ceretax.php

    r3264502 r3285848  
    44 * Plugin URI: https://wordpress.org/plugins/ceretax/
    55 * Description: Simplify sales tax complexity with CereTax for WooCommerce.
    6  * Version: 1.4.1
     6 * Version: 1.4.2
    77 * Author: CereTax, Inc.
    88 * Author URI: https://www.ceretax.com/
     
    3939// Version of plugin.
    4040if ( ! defined( 'CWAFC_VERSION' ) ) {
    41     define( 'CWAFC_VERSION', '1.3.0' );
     41    define( 'CWAFC_VERSION', '1.4.2' );
    4242}
    4343
  • ceretax/trunk/changelog.txt

    r3264502 r3285848  
    45452025-03-20 - version 1.4.1
    4646* add - Fix for tax display at line level for variable product types
     47
     482025-04-28 - version 1.4.2
     49* fix - Tax box now hidden in refunds to avoid confusion, as it no longer reflects accurate post-refund data
     50* fix - Updated tax calculation summary table with an accordion-style UI for better readability and user experience
     51* add - Shipping tax amount now displayed separately in the tax breakdown for clarity
     52* fix - System now supports multiple partial refunds on a single order, providing greater flexibility in transaction management
     53* fix - Corrected recurring subscription product tax display issue on the checkout page to show accurate tax amounts
  • ceretax/trunk/inc/admin/class-cwafc-admin-action.php

    r3264502 r3285848  
    434434                }
    435435            }
    436             if ( ! empty( $order_id ) && ! empty( $ceretax_data ) && $fee_amount > 0 ) { ?>
     436            if ( ( ! empty( $order_id ) && ! empty( $ceretax_data ) && $fee_amount > 0 ) || ( 'shop_order' === get_post_type( $order_id ) && empty( $ceretax_data ) ) ) { ?>
    437437                <style>
    438438                    /* Hide the 3rd tr of .wc-order-totals if .wc-used-coupons is found */
     
    458458            <?php
    459459            }
    460 
     460            ?>
     461            <style>
     462                /* Ceretax table stysle */
     463                #cwafc_ceretax_metabox .inside {
     464                    margin: 0px;
     465                    padding: 0px;
     466                    overflow: auto !important;
     467                }
     468                table.ceratax-tax-table {
     469                    width: 100% !important;
     470                    font-size: 14px !important;
     471                }
     472                .ceratax-tax-table thead {
     473                    background:#ededed !important;
     474                }
     475                .ceratax-tax-table tr th {
     476                    padding: 8px 10px !important;
     477                }
     478                .ceratax-tax-table tr td {
     479                    padding: 8px 10px !important;
     480                    border-bottom: 1px solid #ededed !important;
     481                }
     482            </style>
     483            <?php
    461484            // Refund order script.
    462485            if ( ! empty( $order_id ) && ! empty( $ceretax_data ) ) { ?>
     
    464487                jQuery(function($) {
    465488                    jQuery( '#woocommerce-order-items' ).on( 'change', 'input.refund_order_item_qty', function() {
    466                         var $row               = $( this ).closest( 'tr.item' );
     489                        var $row               = jQuery( this ).closest( 'tr.item' );
    467490                        var qty                = $row.find( 'input.quantity' ).val();
    468                         var refund_qty         = $( this ).val();
    469                         var ceretax_line_total = $( 'input.ceretax_line_total', $row );
    470                         var line_total         = $( 'input.line_total', $row );
    471                         var refund_line_total  = $( 'input.refund_line_total', $row );
     491                        var refund_qty         = jQuery( this ).val();
     492                        var ceretax_line_total = jQuery( 'input.ceretax_line_total', $row );
     493                        var line_total         = jQuery( 'input.line_total', $row );
     494                        var refund_line_total  = jQuery( 'input.refund_line_total', $row );
    472495
    473496                        var unit_line_ceretax_total = accounting.unformat( ceretax_line_total.attr( 'data-line-tax' ), woocommerce_admin.mon_decimal_point ) / qty;
     
    487510                        ).trigger( 'change' );
    488511
    489                         $( this ).trigger( 'refund_quantity_changed' );
     512                        jQuery( this ).trigger( 'refund_quantity_changed' );
    490513
    491514                    });
    492                     $( '#woocommerce-order-items' ).on( 'change', '.refund input.ceretax_line_total', function() {
     515                    jQuery( '#woocommerce-order-items' ).on( 'change', '.refund input.ceretax_line_total', function() {
    493516
    494517                        var refund_amount     = 0;
    495                         var $items            = $( '.woocommerce_order_items' ).find( 'tr.item, tr.fee, tr.shipping' );
     518                        var $items            = jQuery( '.woocommerce_order_items' ).find( 'tr.item, tr.fee, tr.shipping' );
    496519                        var round_at_subtotal = 'yes' === woocommerce_admin_meta_boxes.round_at_subtotal;
    497520
    498521                        // Restrict value based on data-line-tax
    499                         var maxValue   = parseFloat( $( this ).data('line-tax') ) || 0;
    500                         var inputValue = parseFloat( $( this ).val() ) || 0;
     522                        var maxValue   = parseFloat( jQuery( this ).data('line-tax') ) || 0;
     523                        var inputValue = parseFloat( jQuery( this ).val() ) || 0;
    501524
    502525                        if ( inputValue > maxValue ) {
    503526                            alert( 'You cannot refund the line item tax exceeding the allowed limit of ' + maxValue + '.' );
    504                             $( this ).val( maxValue );
     527                            jQuery( this ).val( maxValue );
    505528                        }
    506529
    507530                        $items.each(function() {
    508                             var $row               = $( this );
     531                            var $row               = jQuery( this );
    509532                            var refund_cost_fields = $row.find( '.refund input:not(.refund_order_item_qty)' );
    510533
    511534                            refund_cost_fields.each(function( index, el ) {
    512                                 var field_amount = accounting.unformat( $( el ).val() || 0, woocommerce_admin.mon_decimal_point );
     535                                var field_amount = accounting.unformat( jQuery( el ).val() || 0, woocommerce_admin.mon_decimal_point );
    513536                                refund_amount += parseFloat( round_at_subtotal ?
    514537                                    field_amount :
     
    517540                        });
    518541
    519                         $( '#refund_amount' ).val(
     542                        jQuery( '#refund_amount' ).val(
    520543                            accounting.formatNumber(
    521544                                refund_amount,
     
    526549
    527550                    });
     551                    jQuery( '#woocommerce-order-items' ).on( 'change', '.refund input.ceretax_shipping_line_total', function() {
     552
     553                        // Restrict value based on data-line-tax
     554                        var maxValue   = parseFloat( jQuery( this ).data('shipping-tax') ) || 0;
     555                        var inputValue = parseFloat( jQuery( this ).val() ) || 0;
     556
     557                        if ( inputValue > maxValue ) {
     558                            alert( 'You cannot refund the line item tax exceeding the allowed limit of ' + maxValue + '.' );
     559                            jQuery( this ).val( maxValue );
     560                        }
     561
     562                    });
     563
     564                    // Hide the Tax( Custom fee ) refund text input.
     565                    jQuery( '.woocommerce_order_items #order_fee_line_items tr' ).each( function() {
     566                        var feeName = jQuery( this ).find('.name .view').text().trim();
     567                        var taxName = '<?php echo get_option( CWAFC_PREFIX . '_cere_tax_name', 'Tax' ); ?>';
     568                        if ( feeName === taxName ) {
     569                            jQuery( this ).find( '.refund input' ).hide();
     570                        }
     571                    });
    528572                });
    529573            </script>
    530574            <?php }
    531 
    532575        }
    533576
     
    540583        public function action__cwafc_woocommerce_admin_order_item_headers( $order ) {
    541584            $ceretax_data_lineitem = get_post_meta( $order->get_id(), 'ceretax_data_lineitem', true );
    542             if ( ! empty( $ceretax_data_lineitem ) ) {
     585            $ceretax_data          = get_post_meta( $order->get_id(), 'ceretax_data', true );
     586            // if ( ! empty( $ceretax_data_lineitem ) ) {
     587            if ( ! empty( $ceretax_data_lineitem ) && ! empty( $ceretax_data ) && ! empty( $order ) ) {
    543588                $cere_tax_line_item_column_name = get_option( CWAFC_PREFIX . '_cere_tax_line_item_column_name', 'Tax Total' );
    544589                echo '<th class="ceretax_line_heading" width="7%">' . esc_html( $cere_tax_line_item_column_name ) . '</th>';
     
    556601        public function action__cwafc_woocommerce_admin_order_item_values( $product, $item, $item_id ) {
    557602
     603            // phpcs:disable WordPress.Security.NonceVerification.Missing
    558604            $order_id = null;
    559605            if ( isset( $_GET['post'] ) && ! empty( $_GET['post'] ) ) {
    560                 $order_id = $_GET['post'];
     606                $order_id = sanitize_text_field( wp_unslash( $_GET['post'] ) );
    561607            } else if ( isset( $_GET['id'] ) && ! empty( $_GET['id'] ) ) {
    562                 $order_id = $_GET['id'];
     608                $order_id = sanitize_text_field( wp_unslash( $_GET['id'] ) );
    563609            } else {
    564610                $order_id = null;
    565611            }
     612            if ( empty( $order_id ) && isset( $_POST['order_id'] ) ) {
     613                $order_id = sanitize_text_field( wp_unslash( $_POST['order_id'] ) );
     614            }
     615            // phpcs:enable WordPress.Security.NonceVerification.Missing
    566616
    567617            $cere_tax_name         = get_option( CWAFC_PREFIX . '_cere_tax_name', 'Tax' );
     
    588638                            }
    589639
    590                             $filtered   = array_filter( $ceretax_items_data, function ( $filtered_item ) use ( $product_id ) {
     640                            $line_item_total_tax_amount = 0;
     641                            $line_item_calc_base_amount = 0;
     642                            $line_item_revenue_amount   = 0;
     643                            $line_item_total_tax        = 0;
     644
     645                            $filtered = array_filter( $ceretax_items_data, function ( $filtered_item ) use ( $product_id ) {
    591646                                return isset( $filtered_item->itemNumber ) && $filtered_item->itemNumber == $product_id;
    592647                            });
     
    595650                                return isset( $refunded_item->itemNumber ) && $refunded_item->itemNumber == $product_id;
    596651                            });
     652
     653                            $line_item_revenue_amount = ! empty( $filtered ) ? reset( $filtered )->revenue : 0;
     654                            $line_item_taxe_breaks    = ! empty( $filtered ) ? reset( $filtered )->taxes : array();
     655
     656                            if ( ! empty( $line_item_taxe_breaks ) && is_array( $line_item_taxe_breaks ) ) {
     657                                foreach ( $line_item_taxe_breaks as $key => $val ) {
     658                                    if ( ! empty( $val->calculationBaseAmt ) && ( $val->calculationBaseAmt >= $line_item_revenue_amount ) ) {
     659                                        $line_item_calc_base_amount  = $val->calculationBaseAmt;
     660                                        $line_item_total_tax_amount += $val->totalTax;
     661                                    }
     662                                }
     663                            }
     664                            if ( ! empty( $line_item_calc_base_amount ) ) {
     665                                $line_item_total_tax = ( $line_item_revenue_amount / $line_item_calc_base_amount ) * $line_item_total_tax_amount;
     666                            }
     667
    597668                            $total_line_tax          = ! empty( $filtered ) ? reset( $filtered )->totalTaxLine : null;
    598669                            $total_line_refunded_tax = ! empty( $refunded_filtered ) ? reset( $refunded_filtered )->totalTaxLine : null;
    599670                            $ceretax_refunded_line_item_tax = $item->get_meta( '_ceretax_refunded_line_item_tax' );
    600671                            echo '<div class="view">';
    601                                 echo wc_price( $total_line_tax, array( 'currency' => $order->get_currency() ) );
     672                                echo wc_price( $line_item_total_tax, array( 'currency' => $order->get_currency() ) );
    602673                                if ( is_array( $order->get_refunds() ) && count( $order->get_refunds() ) > 0 && ! empty( $ceretax_refunded_line_item_tax ) ) {
    603                                     echo '<small class="refunded">' . wc_price( $ceretax_refunded_line_item_tax, array( 'currency' => $order->get_currency() ) ) . '</small>';
     674                                    echo '<small class="refunded">' . wc_price( -1 * $ceretax_refunded_line_item_tax, array( 'currency' => $order->get_currency() ) ) . '</small>';
    604675                                }
    605676                            echo '</div>';
    606677
    607678                            echo '<div class="refund" style="display: none;">
    608                                 <input type="text" name="ceretax_line_total[' . absint( $item_id ) . ']" placeholder="' . esc_attr( wc_format_localized_price( 0 ) ) . '" class="refund_line_tax ceretax_line_total wc_input_price" size="4" data-line-tax="' . esc_attr( wc_format_localized_price( $total_line_tax ) ) . '" />
     679                                <input type="text" name="ceretax_line_total[' . absint( $item_id ) . ']" placeholder="' . esc_attr( wc_format_localized_price( 0 ) ) . '" class="refund_line_tax ceretax_line_total wc_input_price" size="4" data-line-tax="' . esc_attr( wc_format_localized_price( round( $line_item_total_tax, 2 ) ) ) . '" />
    609680                            </div>';
    610681                        }
    611682                    }
    612683                    echo '</td>';
    613                
    614                 } elseif ( $item instanceof WC_Order_Item_Fee && $item->get_name() === $cere_tax_name ) {
    615                 // } elseif ( isset( $item['name'] ) && $item['name'] === $cere_tax_name ) {
     684                } elseif ( $item instanceof WC_Order_Item_Fee && $item->get_name() === $cere_tax_name ) {
    616685                    echo '<td class="ceretax_line_value" width="7%"></td>';
     686                } elseif ( $item instanceof WC_Order_Item_Shipping ) {
     687
     688                    echo '<td class="ceretax_line_value" width="7%">';
     689
     690                    $shipping_tax_amount = 0;
     691                    $shipping_line_total = $item['total'];
     692                    $ceretax_refunded_line_item_tax = $item->get_meta( '_ceretax_refunded_line_item_tax' );
     693                    if ( ! empty( $item['total'] ) && is_object( $ceretax_data_lineitem ) ) {
     694                        $ceretax_items_data = $ceretax_data_lineitem->invoice->lineItems;
     695                        if ( ! empty( $ceretax_items_data ) ) {
     696                            $tt = 0;
     697                            $ceretax_items_count = 0;
     698                            foreach ( $ceretax_items_data as $item_data ) {
     699                                $line_item_tax_breaks = $item_data->taxes;
     700                                $transaction_charges_tax      = 0;
     701                                $tras_charge_calc_base_amount = 0;
     702                                if ( ! empty( $line_item_tax_breaks ) ) {
     703                                    foreach ( $line_item_tax_breaks as $key => $val ) {
     704                                        if ( ! empty( $val->transactionChargesCalculationBaseAmt ) ) {
     705                                            $tras_charge_calc_base_amount = $val->transactionChargesCalculationBaseAmt;
     706                                            $transaction_charges_tax      = $transaction_charges_tax + $val->transactionChargesTax;
     707                                        }
     708                                    }
     709                                }
     710                                if ( ! empty( $tras_charge_calc_base_amount ) ) {
     711                                    $ceretax_items_count++;
     712                                    $shipping_tax_amount = $shipping_tax_amount + ( $transaction_charges_tax ) * ( $shipping_line_total / $tras_charge_calc_base_amount );
     713                                }
     714                            }
     715                        }
     716                    }
     717                    if ( ! empty( $ceretax_items_count ) ) {
     718                        $shipping_tax_amount = ( $shipping_tax_amount / $ceretax_items_count );
     719                    }
     720                    echo '<div class="view">';
     721                        echo wc_price( $shipping_tax_amount, array( 'currency' => $order->get_currency() ) );
     722                        if ( is_array( $order->get_refunds() ) && count( $order->get_refunds() ) > 0 && ! empty( $ceretax_refunded_line_item_tax ) ) {
     723                            echo '<small class="refunded">' . wc_price( -1 * $ceretax_refunded_line_item_tax, array( 'currency' => $order->get_currency() ) ) . '</small>';
     724                        }
     725                    echo '</div>';
     726
     727                    echo '<div class="refund" style="display: none;">
     728                        <input type="text" name="ceretax_shipping_line_total[' . absint( $item_id ) . ']" placeholder="' . esc_attr( wc_format_localized_price( 0 ) ) . '" class="refund_line_tax ceretax_shipping_line_total wc_input_price" size="4" data-shipping-tax="' . esc_attr( wc_format_localized_price( round( $shipping_tax_amount, 2 ) ) ) . '" />
     729                    </div>';
     730                    echo '</td>';
    617731                } else {
    618732                    echo '<td class="ceretax_line_value" width="7%">';
    619                         // echo '<div class="refund" style="display: none;">
    620                         //  <input type="text" name="ceretax_line_total[' . absint( $item_id ) . ']" placeholder="' . esc_attr( wc_format_localized_price( 0 ) ) . '" class="refund_line_tax ceretax_line_total wc_input_price" size="4" />
    621                         // </div>';
    622733                    echo '</td>';
    623734                }
  • ceretax/trunk/inc/class-cwafc.php

    r3259100 r3285848  
    5050
    5151        /**
    52          * Create array for static data
    53          *
    54          * @var array  static data => value
    55          */
    56         protected $static_data = array(
    57             'id' => 123,
    58         );
     52         * Add static flag to class.
     53         *
     54         * @var boolean false
     55         */
     56        private static $is_calculating = false;
    5957
    6058        /**
     
    8684            add_action( 'woocommerce_checkout_update_order_meta', array( $this, 'action__cwafc_checkout_field_update_order_meta' ) );
    8785            // Add tax calculation table on admin order edit page.
    88             add_action( 'woocommerce_admin_order_items_after_shipping', array( $this, 'action__cwafc_add_tax_calculation_table_after_shipping' ), 99 );
     86            // add_action( 'woocommerce_admin_order_items_after_shipping', array( $this, 'action__cwafc_add_tax_calculation_table_after_shipping' ), 99 );
     87            add_action( 'add_meta_boxes', array( $this, 'action__cwafc_add_tax_calculation_table' ) );
    8988            // Add tax calculation on order place.
    9089            add_action( 'woocommerce_new_order', array( $this, 'action__cwafc_add_tax_calculation_when_order_placed' ), 10, 2 );
     
    9695            add_action( 'woocommerce_order_refunded', array( $this, 'action__cwafc_add_tax_calculation_when_order_refunded' ), 10, 2 );
    9796            // Allow woocommerce subscriptions to add recurring fee.
    98             add_filter( 'woocommerce_subscriptions_is_recurring_fee', '__return_true' );
     97            add_filter( 'woocommerce_subscriptions_is_recurring_fee', array( $this, 'filter__cwafc_woocommerce_subscriptions_is_recurring_fee' ), 10, 2 );
    9998            // Hide the tax from cart page.
    10099            add_filter( 'woocommerce_cart_totals_taxes_total_html', '__return_empty_string' );
     
    468467         * @return mix
    469468         */
    470         public function action__cwafc_apply_custom_tax_rate() {
     469        public function action__cwafc_apply_custom_tax_rate( $cart ) {
    471470
    472471            // Caclulate tax if only CereTax calculation option is not enabled.
     
    563562            if ( ! empty( $custom_tax_rate ) ) {
    564563                $tax = $custom_tax_rate;
     564
     565                // Add recurring fee for subscription product.
     566                if ( ! empty( $cart->recurring_cart_key ) ) {
     567                    // Add fee only for recurring carts.
     568                    $ceretax_tmp_data            = get_option( 'ceretax_tmp_data' );
     569                    $ceretax_tmp_data            = json_decode( $ceretax_tmp_data );
     570                    $ceretax_tmp_items_data      = $ceretax_tmp_data->invoice->lineItems;
     571                    $total_line_tran_charges_tax = 0;
     572                    if ( ! WC()->cart->is_empty() && ! empty( $ceretax_tmp_items_data ) && is_array( $ceretax_tmp_items_data ) ) {
     573                        $item_count          = 0;
     574                        $total_recurring_fee = 0;
     575                        foreach ( $cart->get_cart() as $cart_item_id => $cart_item ) {
     576                            $line_item_recurring_tax_amount = 0;
     577                            $line_item_calc_base_amount     = 0;
     578                            $line_item_revenue_amount       = 0;
     579                            $line_item_total_tax            = 0;
     580                            $product_id                     = $cart_item['product_id'];
     581
     582                            if ( class_exists( 'WC_Subscriptions_Product' ) && WC_Subscriptions_Product::is_subscription( $product_id ) ) {
     583                                $filtered = array_filter( $ceretax_tmp_items_data, function ( $filtered_item ) use ( $product_id ) {
     584                                    return isset( $filtered_item->itemNumber ) && $filtered_item->itemNumber == $product_id;
     585                                });
     586                                $line_item_revenue_amount = ! empty( $filtered ) ? reset( $filtered )->revenue : 0;
     587                                $line_item_taxe_breaks    = ! empty( $filtered ) ? reset( $filtered )->taxes : array();
     588
     589                                if ( ! empty( $line_item_taxe_breaks ) && is_array( $line_item_taxe_breaks ) ) {
     590                                    foreach ( $line_item_taxe_breaks as $key => $val ) {
     591                                        if ( ! empty( $val->calculationBaseAmt ) && ( $val->calculationBaseAmt >= $line_item_revenue_amount ) ) {
     592                                            $line_item_calc_base_amount      = $val->calculationBaseAmt;
     593                                            $line_item_recurring_tax_amount += $val->totalTax;
     594                                        }
     595                                    }
     596                                }
     597                                if ( ! empty( $line_item_calc_base_amount ) ) {
     598                                    $line_item_total_tax = ( $line_item_revenue_amount / $line_item_calc_base_amount ) * $line_item_recurring_tax_amount;
     599                                    $total_recurring_fee = $total_recurring_fee + $line_item_total_tax;
     600                                    continue;
     601                                }
     602                            }
     603                        }
     604                        $cart->add_fee( $cere_tax_name, $total_recurring_fee, false );
     605                    }
     606                } else {
     607                    $cart->add_fee( $cere_tax_name, $tax, true, '' );
     608                }
     609                // WC()->cart->add_fee( $cere_tax_name, $tax, true, '' );
     610            } elseif ( is_checkout() ) {
    565611                // Ensure the fee is added even if the tax is 0.00.
    566                 WC()->cart->add_fee( $cere_tax_name, $tax, true, '' );
    567             } elseif ( is_checkout() ) {
    568612                $tax = 0;
    569613                WC()->cart->add_fee( $cere_tax_name, $tax, true, '' );
     
    779823                $ceretax_items_data = $ceretax_data->invoice->lineItems;
    780824                if ( ! empty( $ceretax_items_data ) ) {
    781                     $tax_table .= '<tr><td colspan="7"><table class="woocommerce_order_items ceratax-tax-table">';
     825                    $tax_table .= '<tr><td colspan="7"><table class="ceratax-tax-table">';
    782826                    foreach ( $ceretax_items_data as $ceretax_item_data_key => $ceretax_item_data ) {
    783827                        if ( ! empty( $ceretax_item_data->taxes ) ) {
     
    827871
    828872        /**
     873         * Add tax calculation table metaxbox.
     874         *
     875         * @return void
     876         */
     877        public function action__cwafc_add_tax_calculation_table() {
     878            global $post;
     879            $ceretax_data = json_decode( get_post_meta( $post->ID, 'ceretax_data', true ) );
     880            if ( ! empty( $ceretax_data ) ) {
     881                add_meta_box(
     882                    'cwafc_ceretax_metabox',
     883                    __( 'Ceretax Data', 'ceretax' ),
     884                    array( $this, 'cwafc_ceretax_metabox_callback' ),
     885                    array( 'shop_order', 'shop_subscription' ),
     886                    'normal',
     887                    'default'
     888                );
     889            }
     890        }
     891
     892        /**
     893         * Add tax calculation table in the metaxbox.
     894         *
     895         * @param object $post Post Object.
     896         * @return void
     897         */
     898        public function cwafc_ceretax_metabox_callback( $post ) {
     899
     900            $order_id     = $post->ID;
     901            $ceretax_data = json_decode( get_post_meta( $order_id, 'ceretax_data', true ) );
     902            $tax_table    = '';
     903            if ( is_object( $ceretax_data ) ) {
     904                $ceretax_items_data = $ceretax_data->invoice->lineItems;
     905                if ( ! empty( $ceretax_items_data ) ) {
     906                    $tax_table .= '<table class="woocommerce_order_items ceratax-tax-table">';
     907                    foreach ( $ceretax_items_data as $ceretax_item_data_key => $ceretax_item_data ) {
     908                        if ( ! empty( $ceretax_item_data->taxes ) ) {
     909                            $tax_table .= '<thead>
     910                                <tr>
     911                                    <th>' . __( 'Authority', 'ceretax' ) . '</th>
     912                                    <th>' . __( 'Description', 'ceretax' ) . '</th>
     913                                    <th>' . __( 'Tax Type', 'ceretax' ) . '</th>
     914                                    <th>' . __( 'Tax Type Class', 'ceretax' ) . '</th>
     915                                    <th>' . __( 'Tax Type Ref', 'ceretax' ) . '</th>
     916                                    <th>' . __( 'Taxable', 'ceretax' ) . '</th>
     917                                    <th>' . __( 'Calc Base', 'ceretax' ) . '</th>
     918                                    <th>' . __( 'NonTaxable', 'ceretax' ) . '</th>
     919                                    <th>' . __( 'Exempt', 'ceretax' ) . '</th>
     920                                    <th>' . __( '% Taxable', 'ceretax' ) . '</th>
     921                                    <th>' . __( 'Tax rate', 'ceretax' ) . '</th>
     922                                    <th>' . __( 'Total Tax', 'ceretax' ) . '</th>
     923                                </tr>
     924                            <thead>';
     925                            $tax_table .= '<tbody>';
     926                            foreach ( $ceretax_item_data->taxes as $ceretax_item ) {
     927                                // phpcs:disable
     928                                $tax_table .= '<tr>
     929                                    <td>' . $ceretax_item->taxAuthorityName . '</td>
     930                                    <td>' . $ceretax_item->description . '</td>
     931                                    <td>' . $ceretax_item->taxTypeDesc . '</td>
     932                                    <td>' . $ceretax_item->taxTypeClassDesc . '</td>
     933                                    <td>' . $ceretax_item->taxTypeRefDesc . '</td>
     934                                    <td>' . $ceretax_item->taxable . '</td>
     935                                    <td>' . $ceretax_item->calculationBaseAmt . '</td>
     936                                    <td>' . $ceretax_item->nonTaxableAmount . '</td>
     937                                    <td>' . $ceretax_item->exemptAmount . '</td>
     938                                    <td>' . $ceretax_item->percentTaxable . '</td>
     939                                    <td>' . $ceretax_item->rate . '</td>
     940                                    <td>' . $ceretax_item->totalTax . '</td>
     941                                </tr>';
     942                                // phpcs:enable
     943                            }
     944                            $tax_table .= '</tbody>';
     945                        }
     946                    }
     947                    $tax_table .= '</table>';
     948                }
     949            }
     950            echo wp_kses_post( $tax_table );
     951        }
     952
     953        /**
    829954         * Add tax calulation on order place.
    830955         *
     
    9861111        public function action__cwafc_order_after_calculate_totals( $and_taxes, $order ) {
    9871112
     1113            // Check static flag first.
     1114            if ( self::$is_calculating ) {
     1115                return;
     1116            }
     1117            self::$is_calculating = true;
     1118
    9881119            $cere_tax_post_transactions = get_option( CWAFC_PREFIX . '_cere_tax_post_transactions' );
    9891120            $cere_tax_name              = get_option( CWAFC_PREFIX . '_cere_tax_name', 'Tax' );
     
    10011132                return false;
    10021133            }
    1003             // Prevent infinite loop using a transient or custom flag.
    1004             if ( get_transient( 'prevent_order_calculate_totals' ) ) {
    1005                 return;
    1006             }
     1134            // Check for paid order.
     1135            if ( $order && $order->is_paid() ) {
     1136                return false;
     1137            }
     1138            // phpcs:disable WordPress.Security.NonceVerification.Missing
    10071139            $shipping_address_1 = $order->get_shipping_address_1();
    10081140            if ( ! empty( $shipping_address_1 ) ) {
     
    10231155                );
    10241156            }
     1157            // phpcs:enable WordPress.Security.NonceVerification.Missing
    10251158            $res = '';
    10261159            if ( ! empty( $address_data ) && ! empty( $order->get_items() ) ) {
     
    10501183                }
    10511184                // Set the transient to prevent recursion.
    1052                 set_transient( 'prevent_order_calculate_totals', true, 10 );
     1185                // set_transient( 'prevent_order_calculate_totals', true, 10 );
    10531186
    10541187                // Recalculate order totals.
     
    10561189
    10571190                // Remove the transient after recalculation.
    1058                 delete_transient( 'prevent_order_calculate_totals' );
     1191                // delete_transient( 'prevent_order_calculate_totals' );
    10591192
    10601193                // Save the order.
    10611194                $order->save();
    10621195            }
     1196            self::$is_calculating = false;
    10631197        }
    10641198
     
    10771211
    10781212            // Save ceretax line item tax in order line items.
     1213            // phpcs:disable WordPress.Security.NonceVerification.Missing
    10791214            $line_item_result = array();
    10801215            if ( isset( $_POST['line_item_tax_totals'] ) && ! empty( $_POST['line_item_tax_totals'] ) ) {
    1081                 $line_item_json   = stripslashes( $_POST['line_item_tax_totals'] );
     1216                $line_item_json   = stripslashes( sanitize_text_field( wp_unslash( $_POST['line_item_tax_totals'] ) ) );
    10821217                $line_item_data   = json_decode( $line_item_json, true );
    10831218                $line_item_result = array_map( function( $item ) {
     
    10871222                    return ! empty( $value );
    10881223                });
     1224
     1225                // For order items.
    10891226                if ( ! empty( $line_item_result ) && ! empty( $order->get_items() ) ) {
    10901227                    foreach ( $order->get_items() as $item_id => $item ) {
     1228                        $refunded_line_item_tax = $item->get_meta( '_ceretax_refunded_line_item_tax' );
     1229                        $refunded_line_item_tax = ! empty( $refunded_line_item_tax ) ? $refunded_line_item_tax : 0;
    10911230                        if ( array_key_exists( $item_id, $line_item_result ) ) {
    1092                             $item->add_meta_data( '_ceretax_refunded_line_item_tax', $line_item_result[$item_id], true );
     1231                            $refunded_line_item_tax_total = $refunded_line_item_tax + $line_item_result[ $item_id ];
     1232                            $item->update_meta_data( '_ceretax_refunded_line_item_tax', $refunded_line_item_tax_total, true );
    10931233                            $item->save();
    10941234                        }
    10951235                    }
    10961236                }
    1097             }
     1237                // For shipping items.
     1238                if ( ! empty( $line_item_result ) && ! empty( $order->get_items( 'shipping' ) ) ) {
     1239                    foreach ( $order->get_items( 'shipping' ) as $item_id => $item ) {
     1240                        $refunded_line_item_tax = $item->get_meta( '_ceretax_refunded_line_item_tax' );
     1241                        $refunded_line_item_tax = ! empty( $refunded_line_item_tax ) ? $refunded_line_item_tax : 0;
     1242                        if ( array_key_exists( $item_id, $line_item_result ) ) {
     1243                            $refunded_line_item_tax_total = $refunded_line_item_tax + $line_item_result[ $item_id ];
     1244                            $item->update_meta_data( '_ceretax_refunded_line_item_tax', $refunded_line_item_tax_total, true );
     1245                            $item->save();
     1246                        }
     1247                    }
     1248                }
     1249            }
     1250            // phpcs:enable WordPress.Security.NonceVerification.Missing
    10981251
    10991252            $cere_tax_post_transactions = get_option( CWAFC_PREFIX . '_cere_tax_post_transactions' );
     
    11591312
    11601313        /**
     1314         * Subscription conditional recurring fee.
     1315         *
     1316         * @param boolean $is_recurring is fee recurring.
     1317         * @param object  $fee          Fee object.
     1318         * @return $is_recurring
     1319         */
     1320        public function filter__cwafc_woocommerce_subscriptions_is_recurring_fee( $is_recurring, $fee ) {
     1321
     1322            $cere_tax_name = get_option( CWAFC_PREFIX . '_cere_tax_name', 'Tax' );
     1323            if ( $cere_tax_name === $fee->id ) {
     1324                $is_recurring = true;
     1325            }
     1326            return $is_recurring;
     1327        }
     1328
     1329        /**
    11611330         * On order placed calculate cera tax from API
    11621331         *
     
    12071376
    12081377            if ( 'production' === $cere_tax_tax_env ) {
    1209                 $api_url = 'https://calc.prod.ceretax.net/sale';
     1378                $api_url         = 'https://calc.prod.ceretax.net/sale';
     1379                $reverse_api_url = 'https://calc.prod.ceretax.net/reverse';
    12101380            } else {
    1211                 $api_url = 'https://calc.cert.ceretax.net/sale';
     1381                $api_url         = 'https://calc.cert.ceretax.net/sale';
     1382                $reverse_api_url = 'https://calc.cert.ceretax.net/reverse';
    12121383            }
    12131384
     
    13021473                $item_count++;
    13031474            }
     1475
     1476            // Ceretax API request lineitem filter.
     1477            $line_items = apply_filters( 'ceretax_line_items_before_calculate_tax', $line_items, $order, $address_data, $tax_status );
    13041478
    13051479            $request_body = array(
     
    13451519            $ceretax_stau = get_post_meta( $order->get_id(), 'ceretax_stau_' . $order->get_id(), true );
    13461520
    1347             if ( ( empty( $ceretax_stau ) || 'not_found' === $ceretax_stau ) && ! empty( $body ) && ! empty( $cere_tax_api_key ) ) {
     1521            // if ( ( empty( $ceretax_stau ) || 'not_found' === $ceretax_stau ) && ! empty( $body ) && ! empty( $cere_tax_api_key ) ) {
     1522            if ( empty( $ceretax_stau ) && ! empty( $body ) && ! empty( $cere_tax_api_key ) ) {
    13481523
    13491524                $response = wp_remote_post(
     
    13841559                    update_post_meta( $order->get_id(), 'ceretax_data', wp_json_encode( $data ) );
    13851560                    update_post_meta( $order->get_id(), 'ceretax_data_lineitem', wp_json_encode( $data ) );
     1561                    update_post_meta( $order->get_id(), 'ceretax_order_line_item_count', count( $order->get_items() ) );
     1562                    update_post_meta( $order->get_id(), 'wps_separate_upsell_order', 'false' );
    13861563                    return $data['invoice']['totalTaxInvoice'];
    13871564                }
    13881565            } else {
    1389                 $response = wp_remote_post(
    1390                     $api_url . '?systemTraceAuditNumber=' . $ceretax_stau,
    1391                     array(
    1392                         'method'  => 'PUT',
    1393                         'body'    => $body,
    1394                         'headers' => array(
    1395                             'x-api-key'    => $cere_tax_api_key,
    1396                             'Content-Type' => 'application/json',
     1566
     1567                // Check upsell order.
     1568                $wps_upsell_order_started  = get_post_meta( $order->get_id(), 'wps_upsell_order_started', true );
     1569                $wps_separate_upsell_order = get_post_meta( $order->get_id(), 'wps_separate_upsell_order', true );
     1570                $order_line_item_count     = get_post_meta( $order->get_id(), 'ceretax_order_line_item_count', true );
     1571
     1572                if ( 'true' === $wps_upsell_order_started && 'true' !== $wps_separate_upsell_order && $order_line_item_count != count( $order->get_items() ) ) {
     1573
     1574                    update_post_meta( $order->get_id(), 'wps_separate_upsell_order', 'true' );
     1575
     1576                    $response = wp_remote_post(
     1577                        $api_url,
     1578                        array(
     1579                            'method'  => 'POST',
     1580                            'body'    => $body,
     1581                            'headers' => array(
     1582                                'x-api-key'    => $cere_tax_api_key,
     1583                                'Content-Type' => 'application/json',
     1584                            ),
     1585                            'timeout' => 60,
     1586                        )
     1587                    );
     1588
     1589                    // Update main order status in ceretax.
     1590                    $reverse_request_body = array(
     1591                        'transactions' => array(
     1592                            array(
     1593                                'reversalType'           => 'unpost',
     1594                                'systemTraceAuditNumber' => $ceretax_stau,
     1595                            ),
    13971596                        ),
    1398                         'timeout' => 60,
    1399                     )
    1400                 );
     1597                    );
     1598                    $reverse_body         = wp_json_encode( $reverse_request_body );
     1599                    $reverse_response     = wp_remote_post(
     1600                        $reverse_api_url,
     1601                        array(
     1602                            'method'  => 'POST',
     1603                            'body'    => $reverse_body,
     1604                            'headers' => array(
     1605                                'x-api-key'    => $cere_tax_api_key,
     1606                                'Content-Type' => 'application/json',
     1607                            ),
     1608                            'timeout' => 60,
     1609                        )
     1610                    );
     1611
     1612                } else {
     1613                   
     1614                    $response = wp_remote_post(
     1615                        $api_url . '?systemTraceAuditNumber=' . $ceretax_stau,
     1616                        array(
     1617                            'method'  => 'PUT',
     1618                            'body'    => $body,
     1619                            'headers' => array(
     1620                                'x-api-key'    => $cere_tax_api_key,
     1621                                'Content-Type' => 'application/json',
     1622                            ),
     1623                            'timeout' => 60,
     1624                        )
     1625                    );
     1626
     1627                }
    14011628
    14021629                // add api response data in wc logs if log option enabled.
     
    14241651                    update_post_meta( $order->get_id(), 'ceretax_data', wp_json_encode( $data ) );
    14251652                    update_post_meta( $order->get_id(), 'ceretax_data_lineitem', wp_json_encode( $data ) );
     1653                    update_post_meta( $order->get_id(), 'ceretax_order_line_item_count', count( $order->get_items() ) );
    14261654                    return $data['invoice']['totalTaxInvoice'];
    14271655                }
     
    16301858                $data = json_decode( $data, true );
    16311859            }
    1632            
     1860
    16331861            if ( is_wp_error( $response ) ) {
    16341862                return false;
     
    17912019                }
    17922020            }
     2021
     2022            // Ceretax API request lineitem filter.
     2023            $cart_items = apply_filters( 'ceretax_get_tax_rate_from_api', $cart_items, WC()->cart, $checkout_data );
     2024
    17932025            $request_body = array(
    17942026                'configuration' => array(
     
    18512083                    if ( ! empty( $data['systemTraceAuditNumber'] ) ) {
    18522084                        WC()->session->set( 'ceretax_stau', $data['systemTraceAuditNumber'] );
     2085                        update_option( 'ceretax_tmp_data', wp_json_encode( $data ) );
    18532086                    } else {
    18542087                        WC()->session->set( 'ceretax_stau', 'not_found' );
     
    18882121                    if ( ! empty( $data['systemTraceAuditNumber'] ) ) {
    18892122                        WC()->session->set( 'ceretax_stau', $data['systemTraceAuditNumber'] );
     2123                        update_option( 'ceretax_tmp_data', wp_json_encode( $data ) );
    18902124                    } else {
    18912125                        WC()->session->set( 'ceretax_stau', 'not_found' );
  • ceretax/trunk/readme.txt

    r3264502 r3285848  
    55Tested up to: 6.6.1
    66Requires PHP: 7.4
    7 Stable tag: 1.4.1
     7Stable tag: 1.4.2
    88License: GNU General Public License v3.0
    99URI: http://www.gnu.org/licenses/gpl-3.0.html
     
    3535
    3636== Changelog ==
     37
     38= 1.4.2 =
     39* fix - Tax box now hidden in refunds to avoid confusion, as it no longer reflects accurate post-refund data
     40* fix - Updated tax calculation summary table with an accordion-style UI for better readability and user experience
     41* add - Shipping tax amount now displayed separately in the tax breakdown for clarity
     42* fix - System now supports multiple partial refunds on a single order, providing greater flexibility in transaction management
     43* fix - Corrected recurring subscription product tax display issue on the checkout page to show accurate tax amounts
    3744
    3845= 1.4.1 =
     
    8390== Upgrade Notice ==
    8491
     92= 1.4.2 =
     93* fix - Tax box now hidden in refunds to avoid confusion, as it no longer reflects accurate post-refund data
     94* fix - Updated tax calculation summary table with an accordion-style UI for better readability and user experience
     95* add - Shipping tax amount now displayed separately in the tax breakdown for clarity
     96* fix - System now supports multiple partial refunds on a single order, providing greater flexibility in transaction management
     97* fix - Corrected recurring subscription product tax display issue on the checkout page to show accurate tax amounts
     98
    8599= 1.4.1 =
    86100* add - Fix for tax display at line level for variable product types
Note: See TracChangeset for help on using the changeset viewer.