Changeset 3285848
- Timestamp:
- 05/01/2025 08:03:05 PM (11 months ago)
- Location:
- ceretax
- Files:
-
- 25 added
- 6 edited
-
tags/1.4.2 (added)
-
tags/1.4.2/assets (added)
-
tags/1.4.2/assets/css (added)
-
tags/1.4.2/assets/css/admin.css (added)
-
tags/1.4.2/assets/js (added)
-
tags/1.4.2/assets/js/admin.js (added)
-
tags/1.4.2/assets/js/front.js (added)
-
tags/1.4.2/ceretax.php (added)
-
tags/1.4.2/changelog.txt (added)
-
tags/1.4.2/inc (added)
-
tags/1.4.2/inc/admin (added)
-
tags/1.4.2/inc/admin/class-cwafc-admin-action.php (added)
-
tags/1.4.2/inc/admin/class-cwafc-admin-filter.php (added)
-
tags/1.4.2/inc/admin/class-cwafc-admin.php (added)
-
tags/1.4.2/inc/class-cwafc.php (added)
-
tags/1.4.2/inc/front (added)
-
tags/1.4.2/inc/front/class-cwafc-front-action.php (added)
-
tags/1.4.2/inc/front/class-cwafc-front-filter.php (added)
-
tags/1.4.2/inc/front/class-cwafc-front.php (added)
-
tags/1.4.2/languages (added)
-
tags/1.4.2/languages/ceretax.pot (added)
-
tags/1.4.2/readme.txt (added)
-
tags/1.4.2/woocommerce (added)
-
tags/1.4.2/woocommerce/cart (added)
-
tags/1.4.2/woocommerce/cart/shipping-calculator.php (added)
-
trunk/assets/js/front.js (modified) (2 diffs)
-
trunk/ceretax.php (modified) (2 diffs)
-
trunk/changelog.txt (modified) (1 diff)
-
trunk/inc/admin/class-cwafc-admin-action.php (modified) (10 diffs)
-
trunk/inc/class-cwafc.php (modified) (24 diffs)
-
trunk/readme.txt (modified) (3 diffs)
Legend:
- Unmodified
- Added
- Removed
-
ceretax/trunk/assets/js/front.js
r3219747 r3285848 2 2 3 3 // 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 ) { 5 6 6 7 function debounce(func, wait) { … … 193 194 return false; 194 195 } 195 196 196 jQuery.ajax({ 197 197 type: 'POST', -
ceretax/trunk/ceretax.php
r3264502 r3285848 4 4 * Plugin URI: https://wordpress.org/plugins/ceretax/ 5 5 * Description: Simplify sales tax complexity with CereTax for WooCommerce. 6 * Version: 1.4. 16 * Version: 1.4.2 7 7 * Author: CereTax, Inc. 8 8 * Author URI: https://www.ceretax.com/ … … 39 39 // Version of plugin. 40 40 if ( ! defined( 'CWAFC_VERSION' ) ) { 41 define( 'CWAFC_VERSION', '1. 3.0' );41 define( 'CWAFC_VERSION', '1.4.2' ); 42 42 } 43 43 -
ceretax/trunk/changelog.txt
r3264502 r3285848 45 45 2025-03-20 - version 1.4.1 46 46 * add - Fix for tax display at line level for variable product types 47 48 2025-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 434 434 } 435 435 } 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 ) ) ) { ?> 437 437 <style> 438 438 /* Hide the 3rd tr of .wc-order-totals if .wc-used-coupons is found */ … … 458 458 <?php 459 459 } 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 461 484 // Refund order script. 462 485 if ( ! empty( $order_id ) && ! empty( $ceretax_data ) ) { ?> … … 464 487 jQuery(function($) { 465 488 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' ); 467 490 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 ); 472 495 473 496 var unit_line_ceretax_total = accounting.unformat( ceretax_line_total.attr( 'data-line-tax' ), woocommerce_admin.mon_decimal_point ) / qty; … … 487 510 ).trigger( 'change' ); 488 511 489 $( this ).trigger( 'refund_quantity_changed' );512 jQuery( this ).trigger( 'refund_quantity_changed' ); 490 513 491 514 }); 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() { 493 516 494 517 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' ); 496 519 var round_at_subtotal = 'yes' === woocommerce_admin_meta_boxes.round_at_subtotal; 497 520 498 521 // 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; 501 524 502 525 if ( inputValue > maxValue ) { 503 526 alert( 'You cannot refund the line item tax exceeding the allowed limit of ' + maxValue + '.' ); 504 $( this ).val( maxValue );527 jQuery( this ).val( maxValue ); 505 528 } 506 529 507 530 $items.each(function() { 508 var $row = $( this );531 var $row = jQuery( this ); 509 532 var refund_cost_fields = $row.find( '.refund input:not(.refund_order_item_qty)' ); 510 533 511 534 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 ); 513 536 refund_amount += parseFloat( round_at_subtotal ? 514 537 field_amount : … … 517 540 }); 518 541 519 $( '#refund_amount' ).val(542 jQuery( '#refund_amount' ).val( 520 543 accounting.formatNumber( 521 544 refund_amount, … … 526 549 527 550 }); 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 }); 528 572 }); 529 573 </script> 530 574 <?php } 531 532 575 } 533 576 … … 540 583 public function action__cwafc_woocommerce_admin_order_item_headers( $order ) { 541 584 $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 ) ) { 543 588 $cere_tax_line_item_column_name = get_option( CWAFC_PREFIX . '_cere_tax_line_item_column_name', 'Tax Total' ); 544 589 echo '<th class="ceretax_line_heading" width="7%">' . esc_html( $cere_tax_line_item_column_name ) . '</th>'; … … 556 601 public function action__cwafc_woocommerce_admin_order_item_values( $product, $item, $item_id ) { 557 602 603 // phpcs:disable WordPress.Security.NonceVerification.Missing 558 604 $order_id = null; 559 605 if ( isset( $_GET['post'] ) && ! empty( $_GET['post'] ) ) { 560 $order_id = $_GET['post'];606 $order_id = sanitize_text_field( wp_unslash( $_GET['post'] ) ); 561 607 } else if ( isset( $_GET['id'] ) && ! empty( $_GET['id'] ) ) { 562 $order_id = $_GET['id'];608 $order_id = sanitize_text_field( wp_unslash( $_GET['id'] ) ); 563 609 } else { 564 610 $order_id = null; 565 611 } 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 566 616 567 617 $cere_tax_name = get_option( CWAFC_PREFIX . '_cere_tax_name', 'Tax' ); … … 588 638 } 589 639 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 ) { 591 646 return isset( $filtered_item->itemNumber ) && $filtered_item->itemNumber == $product_id; 592 647 }); … … 595 650 return isset( $refunded_item->itemNumber ) && $refunded_item->itemNumber == $product_id; 596 651 }); 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 597 668 $total_line_tax = ! empty( $filtered ) ? reset( $filtered )->totalTaxLine : null; 598 669 $total_line_refunded_tax = ! empty( $refunded_filtered ) ? reset( $refunded_filtered )->totalTaxLine : null; 599 670 $ceretax_refunded_line_item_tax = $item->get_meta( '_ceretax_refunded_line_item_tax' ); 600 671 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() ) ); 602 673 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>'; 604 675 } 605 676 echo '</div>'; 606 677 607 678 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 ) ) ) . '" /> 609 680 </div>'; 610 681 } 611 682 } 612 683 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 ) { 616 685 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>'; 617 731 } else { 618 732 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>';622 733 echo '</td>'; 623 734 } -
ceretax/trunk/inc/class-cwafc.php
r3259100 r3285848 50 50 51 51 /** 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; 59 57 60 58 /** … … 86 84 add_action( 'woocommerce_checkout_update_order_meta', array( $this, 'action__cwafc_checkout_field_update_order_meta' ) ); 87 85 // 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' ) ); 89 88 // Add tax calculation on order place. 90 89 add_action( 'woocommerce_new_order', array( $this, 'action__cwafc_add_tax_calculation_when_order_placed' ), 10, 2 ); … … 96 95 add_action( 'woocommerce_order_refunded', array( $this, 'action__cwafc_add_tax_calculation_when_order_refunded' ), 10, 2 ); 97 96 // 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 ); 99 98 // Hide the tax from cart page. 100 99 add_filter( 'woocommerce_cart_totals_taxes_total_html', '__return_empty_string' ); … … 468 467 * @return mix 469 468 */ 470 public function action__cwafc_apply_custom_tax_rate( ) {469 public function action__cwafc_apply_custom_tax_rate( $cart ) { 471 470 472 471 // Caclulate tax if only CereTax calculation option is not enabled. … … 563 562 if ( ! empty( $custom_tax_rate ) ) { 564 563 $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() ) { 565 611 // 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() ) {568 612 $tax = 0; 569 613 WC()->cart->add_fee( $cere_tax_name, $tax, true, '' ); … … 779 823 $ceretax_items_data = $ceretax_data->invoice->lineItems; 780 824 if ( ! empty( $ceretax_items_data ) ) { 781 $tax_table .= '<tr><td colspan="7"><table class=" woocommerce_order_itemsceratax-tax-table">';825 $tax_table .= '<tr><td colspan="7"><table class="ceratax-tax-table">'; 782 826 foreach ( $ceretax_items_data as $ceretax_item_data_key => $ceretax_item_data ) { 783 827 if ( ! empty( $ceretax_item_data->taxes ) ) { … … 827 871 828 872 /** 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 /** 829 954 * Add tax calulation on order place. 830 955 * … … 986 1111 public function action__cwafc_order_after_calculate_totals( $and_taxes, $order ) { 987 1112 1113 // Check static flag first. 1114 if ( self::$is_calculating ) { 1115 return; 1116 } 1117 self::$is_calculating = true; 1118 988 1119 $cere_tax_post_transactions = get_option( CWAFC_PREFIX . '_cere_tax_post_transactions' ); 989 1120 $cere_tax_name = get_option( CWAFC_PREFIX . '_cere_tax_name', 'Tax' ); … … 1001 1132 return false; 1002 1133 } 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 1007 1139 $shipping_address_1 = $order->get_shipping_address_1(); 1008 1140 if ( ! empty( $shipping_address_1 ) ) { … … 1023 1155 ); 1024 1156 } 1157 // phpcs:enable WordPress.Security.NonceVerification.Missing 1025 1158 $res = ''; 1026 1159 if ( ! empty( $address_data ) && ! empty( $order->get_items() ) ) { … … 1050 1183 } 1051 1184 // Set the transient to prevent recursion. 1052 set_transient( 'prevent_order_calculate_totals', true, 10 );1185 // set_transient( 'prevent_order_calculate_totals', true, 10 ); 1053 1186 1054 1187 // Recalculate order totals. … … 1056 1189 1057 1190 // Remove the transient after recalculation. 1058 delete_transient( 'prevent_order_calculate_totals' );1191 // delete_transient( 'prevent_order_calculate_totals' ); 1059 1192 1060 1193 // Save the order. 1061 1194 $order->save(); 1062 1195 } 1196 self::$is_calculating = false; 1063 1197 } 1064 1198 … … 1077 1211 1078 1212 // Save ceretax line item tax in order line items. 1213 // phpcs:disable WordPress.Security.NonceVerification.Missing 1079 1214 $line_item_result = array(); 1080 1215 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'] ) ) ); 1082 1217 $line_item_data = json_decode( $line_item_json, true ); 1083 1218 $line_item_result = array_map( function( $item ) { … … 1087 1222 return ! empty( $value ); 1088 1223 }); 1224 1225 // For order items. 1089 1226 if ( ! empty( $line_item_result ) && ! empty( $order->get_items() ) ) { 1090 1227 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; 1091 1230 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 ); 1093 1233 $item->save(); 1094 1234 } 1095 1235 } 1096 1236 } 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 1098 1251 1099 1252 $cere_tax_post_transactions = get_option( CWAFC_PREFIX . '_cere_tax_post_transactions' ); … … 1159 1312 1160 1313 /** 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 /** 1161 1330 * On order placed calculate cera tax from API 1162 1331 * … … 1207 1376 1208 1377 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'; 1210 1380 } 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'; 1212 1383 } 1213 1384 … … 1302 1473 $item_count++; 1303 1474 } 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 ); 1304 1478 1305 1479 $request_body = array( … … 1345 1519 $ceretax_stau = get_post_meta( $order->get_id(), 'ceretax_stau_' . $order->get_id(), true ); 1346 1520 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 ) ) { 1348 1523 1349 1524 $response = wp_remote_post( … … 1384 1559 update_post_meta( $order->get_id(), 'ceretax_data', wp_json_encode( $data ) ); 1385 1560 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' ); 1386 1563 return $data['invoice']['totalTaxInvoice']; 1387 1564 } 1388 1565 } 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 ), 1397 1596 ), 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 } 1401 1628 1402 1629 // add api response data in wc logs if log option enabled. … … 1424 1651 update_post_meta( $order->get_id(), 'ceretax_data', wp_json_encode( $data ) ); 1425 1652 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() ) ); 1426 1654 return $data['invoice']['totalTaxInvoice']; 1427 1655 } … … 1630 1858 $data = json_decode( $data, true ); 1631 1859 } 1632 1860 1633 1861 if ( is_wp_error( $response ) ) { 1634 1862 return false; … … 1791 2019 } 1792 2020 } 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 1793 2025 $request_body = array( 1794 2026 'configuration' => array( … … 1851 2083 if ( ! empty( $data['systemTraceAuditNumber'] ) ) { 1852 2084 WC()->session->set( 'ceretax_stau', $data['systemTraceAuditNumber'] ); 2085 update_option( 'ceretax_tmp_data', wp_json_encode( $data ) ); 1853 2086 } else { 1854 2087 WC()->session->set( 'ceretax_stau', 'not_found' ); … … 1888 2121 if ( ! empty( $data['systemTraceAuditNumber'] ) ) { 1889 2122 WC()->session->set( 'ceretax_stau', $data['systemTraceAuditNumber'] ); 2123 update_option( 'ceretax_tmp_data', wp_json_encode( $data ) ); 1890 2124 } else { 1891 2125 WC()->session->set( 'ceretax_stau', 'not_found' ); -
ceretax/trunk/readme.txt
r3264502 r3285848 5 5 Tested up to: 6.6.1 6 6 Requires PHP: 7.4 7 Stable tag: 1.4. 17 Stable tag: 1.4.2 8 8 License: GNU General Public License v3.0 9 9 URI: http://www.gnu.org/licenses/gpl-3.0.html … … 35 35 36 36 == 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 37 44 38 45 = 1.4.1 = … … 83 90 == Upgrade Notice == 84 91 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 85 99 = 1.4.1 = 86 100 * add - Fix for tax display at line level for variable product types
Note: See TracChangeset
for help on using the changeset viewer.