Jump to content
  • Checkout
  • Login
  • Get in touch

osCommerce

The e-commerce.

Tax Information


Recommended Posts

Hello,
 
Trying to apply best practice guidelines to a modular rewritten add-on, I found the following issue:
 
the add-on will show tax information below all shown product prices. So I use a header tag module which include the language definitions, configuration entries and defines a constant which is used to apply the addition only on selected pages. All worked fine except for the column boxes.
I discovered that there exists a configuration entrance "TEMPLATE_BLOCK_GROUPS" which is used in includes/classes/osc_templates.php for to load the modules and is defined by the OsC installation database script like: 'boxes;header_tags'.
This is the reason why the boxes are loading before the header tags and the constants and variables defined in a header tag module are not available for the boxes.
 
In order to fix it I inluded the following script in the header tag module which is executed during installation. It moves the header tags to first place:

      if ( defined('TEMPLATE_BLOCK_GROUPS') && tep_not_null(TEMPLATE_BLOCK_GROUPS) ) {
        $tbgroups_array = explode(';', TEMPLATE_BLOCK_GROUPS);
	$key = array_search('header_tags', $tbgroups_array);
	if (false !== $key) {
	  unset($tbgroups_array[$key]);
	  $tbgroups_array = array_merge(array('0' => 'header_tags'), $tbgroups_array );
	  tep_db_query("update configuration SET configuration_value = '" . implode(';', $tbgroups_array) . "' WHERE configuration_key LIKE 'TEMPLATE_BLOCK_GROUPS'");
        }						
      }

Is this solution ok and save??

And shouldn't the OsC Installation Script be changed to load first the header tag modules or the coding in osc_templates class be modified to ensure the header tags load first??

 

regards

Rainer

Link to comment
Share on other sites

Hello,

 

Trying to apply best practice guidelines to a modular rewritten add-on, I found the following issue:

 

the add-on will show tax information below all shown product prices. So I use a header tag module which include the language definitions, configuration entries and defines a constant which is used to apply the addition only on selected pages. All worked fine except for the column boxes.

I discovered that there exists a configuration entrance "TEMPLATE_BLOCK_GROUPS" which is used in includes/classes/osc_templates.php for to load the modules and is defined by the OsC installation database script like: 'boxes;header_tags'.

This is the reason why the boxes are loading before the header tags and the constants and variables defined in a header tag module are not available for the boxes.

 

In order to fix it I inluded the following script in the header tag module which is executed during installation. It moves the header tags to first place:

      if ( defined('TEMPLATE_BLOCK_GROUPS') && tep_not_null(TEMPLATE_BLOCK_GROUPS) ) {
        $tbgroups_array = explode(';', TEMPLATE_BLOCK_GROUPS);
	$key = array_search('header_tags', $tbgroups_array);
	if (false !== $key) {
	  unset($tbgroups_array[$key]);
	  $tbgroups_array = array_merge(array('0' => 'header_tags'), $tbgroups_array );
	  tep_db_query("update configuration SET configuration_value = '" . implode(';', $tbgroups_array) . "' WHERE configuration_key LIKE 'TEMPLATE_BLOCK_GROUPS'");
        }						
      }

Is this solution ok and save??

And shouldn't the OsC Installation Script be changed to load first the header tag modules or the coding in osc_templates class be modified to ensure the header tags load first??

 

regards

Rainer

Hi Rainer,

 

Simple alternate overtake module solution is found here without core rule attacks.

:blink:
osCommerce based shop owner with minimal design and focused on background works. When the less is more.
Email managment with tracking pixel, package managment for shipping, stock management, warehouse managment with bar code reader, parcel shops management on 3000 pickup points without local store.

Link to comment
Share on other sites

@@raiwa but the hooks do it much better.

:blink:
osCommerce based shop owner with minimal design and focused on background works. When the less is more.
Email managment with tracking pixel, package managment for shipping, stock management, warehouse managment with bar code reader, parcel shops management on 3000 pickup points without local store.

Link to comment
Share on other sites

@@Gergely,

 

Thank You!!

 

I could do the bootstrap module idea you posted first:

<?php
/*
  $Id: tax_below_price.php
  $Loc: catalog/includes/modules/bootstrap/

  osCommerce, Open Source E-Commerce Solutions
  http://www.oscommerce.com

  2015 show tax below price 3.0 BS by @raiwa [email protected]
  based on 2.3 by @raiwa
  Original version:
  By www.tim-international.net

  Copyright (c) 2015 osCommerce

  Released under the GNU General Public License
*/

  class bt_tax_below_price {
    var $code = 'bt_tax_below_price';
    var $group = 'bootstrap';
    var $title;
    var $description;
    var $sort_order;
    var $enabled = false;

    function bt_tax_below_price() {
      $this->title = MODULE_BOOTSTRAP_TAX_BELOW_PRICE_TITLE;
      $this->description = MODULE_BOOTSTRAP_TAX_BELOW_PRICE_DESCRIPTION;

      if ( defined('MODULE_BOOTSTRAP_TAX_BELOW_PRICE_STATUS') ) {
        $this->sort_order = MODULE_BOOTSTRAP_TAX_BELOW_PRICE_SORT_ORDER;
        $this->enabled = (MODULE_BOOTSTRAP_TAX_BELOW_PRICE_STATUS == 'True');
      }
    }

    function execute() {
      global $oscTemplate, $PHP_SELF, $currencies;

      if (tep_not_null(MODULE_BOOTSTRAP_TAX_BELOW_PRICE_PAGES)) {
        $pages_array = array();

        foreach (explode(';', MODULE_BOOTSTRAP_TAX_BELOW_PRICE_PAGES) as $page) {
          $page = trim($page);

          if (!empty($page)) {
            $pages_array[] = $page;
          }
        }
        
        if (in_array(basename($PHP_SELF), $pages_array)) { // register only if page is selected
        	
        	define('MODULE_BOOTSTRAP_TAX_BELOW_PRICE_SHOW', 'True');

          $oscTemplate->addBlock('<style type="text/css"> .taxinfo { text-align: center; } td .taxinfo { text-align: right; } del .taxinfo { display: none; } .caption .taxinfo { margin-top: -10px; } .btn .taxinfo { margin-top: 0px; }</style>' . "\n", 'header_tags');
          
          $currencies = new currencies_mod();

	      } // end if page is in array
      } // end if page array is not empty
    }

    function isEnabled() {
      return $this->enabled;
    }

    function check() {
      return defined('MODULE_BOOTSTRAP_TAX_BELOW_PRICE_STATUS');
    }

    function install() {
      tep_db_query("insert into configuration (configuration_title, configuration_key, configuration_value, configuration_description, configuration_group_id, sort_order, set_function, date_added) values ('Enable Tax Below Price Module', 'MODULE_BOOTSTRAP_TAX_BELOW_PRICE_STATUS', 'True', 'Do you want to enable the Tax Below Price module?', '6', '1', 'tep_cfg_select_option(array(\'True\', \'False\'), ', now())");
      tep_db_query("insert into configuration (configuration_title, configuration_key, configuration_value, configuration_description, configuration_group_id, sort_order, set_function, date_added) values ('Display tax amount', 'MODULE_BOOTSTRAP_TAX_BELOW_PRICE_DISPLAY_TAX_VALUE', 'True', 'Do you wants to include the tax amount?', '6', '2', 'tep_cfg_select_option(array(\'True\', \'False\'), ', now())");
      tep_db_query("insert into configuration (configuration_title, configuration_key, configuration_value, configuration_description, configuration_group_id, sort_order, use_function, set_function, date_added) values ('Pages', 'MODULE_BOOTSTRAP_TAX_BELOW_PRICE_PAGES', '" . implode(';', $this->get_default_pages()) . "', 'The pages to show Tax below Price.', '6', '3', 'bt_tax_below_price_show_pages', 'bt_tax_below_price_edit_pages(', now())");
      tep_db_query("insert into configuration (configuration_title, configuration_key, configuration_value, configuration_description, configuration_group_id, sort_order, date_added) values ('Sort Order', 'MODULE_BOOTSTRAP_TAX_BELOW_PRICE_SORT_ORDER', '1000', 'Sort order of display. No effect for this module.', '6', '4', now())");
    }

    function remove() {
      tep_db_query("delete from " . TABLE_CONFIGURATION . " where configuration_key in ('" . implode("', '", $this->keys()) . "')");
    }

    function keys() {
      return array('MODULE_BOOTSTRAP_TAX_BELOW_PRICE_STATUS', 'MODULE_BOOTSTRAP_TAX_BELOW_PRICE_DISPLAY_TAX_VALUE', 'MODULE_BOOTSTRAP_TAX_BELOW_PRICE_PAGES', 'MODULE_BOOTSTRAP_TAX_BELOW_PRICE_SORT_ORDER');
    }

    function get_default_pages() {
    	global $PHP_SELF;
    	$exclude_array = array('checkout_process.php',
                   					 'download.php',
                   					 'redirect.php',
                   					 'ssl_check.php');
    	$file_extension = substr($PHP_SELF, strrpos($PHP_SELF, '.'));
    	$files_array = array();
    	if ($dir = @[member='dir'](DIR_FS_CATALOG)) {
    		while ($file = $dir->read()) {
    			if ( !is_dir(DIR_FS_CATALOG . $file) && !in_array($file, $exclude_array) ) {
    				if (substr($file, strrpos($file, '.')) == $file_extension) {
    					$files_array[] = $file;
    				}
    			}
    		}
    		sort($files_array);
    		$dir->close();
    		return $files_array;
    	}
    }
  }

  function bt_tax_below_price_show_pages($text) {
    return nl2br(implode("\n", explode(';', $text)));
  }

  function bt_tax_below_price_edit_pages($values, $key) {
    global $PHP_SELF;

    $file_extension = substr($PHP_SELF, strrpos($PHP_SELF, '.'));
    $files_array = array();
	  if ($dir = @[member='dir'](DIR_FS_CATALOG)) {
	    while ($file = $dir->read()) {
	      if (!is_dir(DIR_FS_CATALOG . $file)) {
	        if (substr($file, strrpos($file, '.')) == $file_extension) {
            $files_array[] = $file;
          }
        }
      }
      sort($files_array);
      $dir->close();
    }

    $values_array = explode(';', $values);

    $output = '';
    foreach ($files_array as $file) {
      $output .= tep_draw_checkbox_field('bt_tax_below_price_file[]', $file, in_array($file, $values_array), null, True) . ' ' . tep_output_string($file) . '<br />';
    }

    if (!empty($output)) {
      $output = '<br />' . substr($output, 0, -6);
    }

    $output .= tep_draw_hidden_field('configuration[' . $key . ']', '', 'id="htrn_files"');

    $output .= '<script>
                function htrn_update_cfg_value() {
                  var htrn_selected_files = \'\';

                  if ($(\'input[name="bt_tax_below_price_file[]"]\').length > 0) {
                    $(\'input[name="bt_tax_below_price_file[]"]:checked\').each(function() {
                      htrn_selected_files += $(this).attr(\'value\') + \';\';
                    });

                    if (htrn_selected_files.length > 0) {
                      htrn_selected_files = htrn_selected_files.substring(0, htrn_selected_files.length - 1);
                    }
                  }

                  $(\'#htrn_files\').val(htrn_selected_files);
                }

                $(function() {
                  htrn_update_cfg_value();

                  if ($(\'input[name="bt_tax_below_price_file[]"]\').length > 0) {
                    $(\'input[name="bt_tax_below_price_file[]"]\').change(function() {
                      htrn_update_cfg_value();
                    });
                  }
                });
                </script>';

    return $output;
  }

  if (class_exists('currencies')) {
    class currencies_mod extends currencies {
    	// add tax below price mod
    	public function format($number, $calculate_currency_value = true, $currency_type = '', $currency_value = '', $products_tax = '') {
    		global $currency;

    		if (empty($currency_type)) $currency_type = $currency;

    		if ($calculate_currency_value == true) {
    			$rate = (tep_not_null($currency_value)) ? $currency_value : $this->currencies[$currency_type]['value'];
    			$format_string = $this->currencies[$currency_type]['symbol_left'] . number_format(tep_round($number * $rate, $this->currencies[$currency_type]['decimal_places']), $this->currencies[$currency_type]['decimal_places'], $this->currencies[$currency_type]['decimal_point'], $this->currencies[$currency_type]['thousands_point']) . $this->currencies[$currency_type]['symbol_right'];
    		} else {
    			$format_string = $this->currencies[$currency_type]['symbol_left'] . number_format(tep_round($number, $this->currencies[$currency_type]['decimal_places']), $this->currencies[$currency_type]['decimal_places'], $this->currencies[$currency_type]['decimal_point'], $this->currencies[$currency_type]['thousands_point']) . $this->currencies[$currency_type]['symbol_right'];
    		}

    		if ( MODULE_BOOTSTRAP_TAX_BELOW_PRICE_STATUS == 'True' && MODULE_BOOTSTRAP_TAX_BELOW_PRICE_SHOW == 'True' && $number > 0 && $products_tax !== '' ) {
    			$format_string .= '<div class="taxinfo"><small>';
    			if ( $products_tax == '0' || DISPLAY_PRICE_WITH_TAX == 'false' ) {
    				$format_string .= MODULE_BOOTSTRAP_TAX_BELOW_PRICE_EXCLUDING_TAX;
    			} else {
    				if ( MODULE_BOOTSTRAP_TAX_BELOW_PRICE_DISPLAY_TAX_VALUE == 'True' ) {
    					$format_string .= sprintf(MODULE_BOOTSTRAP_TAX_BELOW_PRICE_INCLUDING_TAX_AMOUNT, $products_tax, null);
    				} else {
    					$format_string .= MODULE_BOOTSTRAP_TAX_BELOW_PRICE_INCLUDING_TAX_TEXTONLY;
    				}
    			}
    			$format_string.= '</small></div>';
    		}
    		return $format_string;
    	}
    	
    	// add tax below price mod
      public function display_price($products_price, $products_tax, $quantity = 1) {
      	return $this->format($this->calculate_price($products_price, $products_tax, $quantity), null, null, null, $products_tax);
      }

    // legacy format
    function format_legacy($number, $calculate_currency_value = true, $currency_type = '', $currency_value = '') {
      global $currency;

      if (empty($currency_type)) $currency_type = $currency;

      if ($calculate_currency_value == true) {
        $rate = (tep_not_null($currency_value)) ? $currency_value : $this->currencies[$currency_type]['value'];
        $format_string = $this->currencies[$currency_type]['symbol_left'] . number_format(tep_round($number * $rate, $this->currencies[$currency_type]['decimal_places']), $this->currencies[$currency_type]['decimal_places'], $this->currencies[$currency_type]['decimal_point'], $this->currencies[$currency_type]['thousands_point']) . $this->currencies[$currency_type]['symbol_right'];
      } else {
        $format_string = $this->currencies[$currency_type]['symbol_left'] . number_format(tep_round($number, $this->currencies[$currency_type]['decimal_places']), $this->currencies[$currency_type]['decimal_places'], $this->currencies[$currency_type]['decimal_point'], $this->currencies[$currency_type]['thousands_point']) . $this->currencies[$currency_type]['symbol_right'];
      }

      return $format_string;
    }
      
    // legacy display price
    public function display_price_legacy($products_price, $products_tax, $quantity = 1) {
      return $this->format_legacy($this->calculate_price($products_price, $products_tax, $quantity));
    }

    }
  }
?>

It works great and there is no core change needed any more except one small issue:

In product info for the case an option has a different price, the html tags appear:

For now my fix would be to use the display_price_legacy function to show only the price without tax info:

            $products_options_array[sizeof($products_options_array)-1]['text'] .= ' (' . $products_options['price_prefix'] . $currencies->display_price_legacy($products_options['options_values_price'], tep_get_tax_rate($product_info['products_tax_class_id'])) .') ';

Do you have any idea how to fix this without modifying product_info.php or html_output.php??

 

Another issue:

If any other later added add-on, adds another group and module, it may be possible that the bootstrap group doesn't load first any more and the content may not be available for the new group modules. Same problem like explained for the header tags and boxes.

So maybe keeping this as a header tag module which includes this check for installation:

      if ( defined('TEMPLATE_BLOCK_GROUPS') ) {
      	// If header_tags is not the first item on the list
        if( substr( TEMPLATE_BLOCK_GROUPS, 0, 11 ) != 'header_tags' ) {
        	// Remove header_tags from wherever it is in the list
        	$template_block_groups = str_replace( ';header_tags', '', TEMPLATE_BLOCK_GROUPS );
        	// And add header_tags back onto the front of the list
        	$template_block_groups = 'header_tags;' . $template_block_groups;
        	$sql_data_array = array( 'configuration_value' => $template_block_groups );
        	// Update the database with the fixed string
        	tep_db_perform( TABLE_CONFIGURATION, $sql_data_array, 'update', "configuration_key = 'TEMPLATE_BLOCK_GROUPS'" );
        } // if( substr
      } // end if defined TEMPLATE_BLOCK_GROUPS

would keep the installation easier (no admin mods). Or is there any other reason to use a new bootstrap group??

 

 

Now the last question:

I would like to try this as a hook, but I have not any experience with hooks. Any help for a starting point to do it with hook please??

 

Thanks again and kind regards

Rainer

Link to comment
Share on other sites

@@raiwa

 

here is a solution for display problem.

BTW My opinion is that the hooks class extends is a best way for modify class functions. If modules and not hooks extend classes we can not see the extended facts.

 

here is the core hooks admin: https://github.com/haraldpdl/oscommerce2/commit/e4344f7d93b2ed07e36e26ac20a7555ef2f1d23d

At this moment the main latest github oscommerce repo is uninstallable. So its very hard to start as new project.

Use the paypal App discover hooks on v234.

:blink:
osCommerce based shop owner with minimal design and focused on background works. When the less is more.
Email managment with tracking pixel, package managment for shipping, stock management, warehouse managment with bar code reader, parcel shops management on 3000 pickup points without local store.

Link to comment
Share on other sites

@@Gergely, @@wHiTeHaT,

 

The new tax info add on finally uploaded here:

http://addons.oscommerce.com/info/9365

 

New store module, includes currency class extension, no core file changes at all!!

 

Thank you very much for your help and support!!

 

regards

Rainer

Link to comment
Share on other sites

Archived

This topic is now archived and is closed to further replies.

×
×
  • Create New...