eZ Publish  [4.0]
ezdefaultvathandler.php
Go to the documentation of this file.
00001 <?php
00002 //
00003 // Definition of eZDefaultVATHandler class
00004 //
00005 // Created on: <15-Dec-2005 15:42:29 vs>
00006 //
00007 // ## BEGIN COPYRIGHT, LICENSE AND WARRANTY NOTICE ##
00008 // SOFTWARE NAME: eZ Publish
00009 // SOFTWARE RELEASE: 4.0.x
00010 // COPYRIGHT NOTICE: Copyright (C) 1999-2008 eZ Systems AS
00011 // SOFTWARE LICENSE: GNU General Public License v2.0
00012 // NOTICE: >
00013 //   This program is free software; you can redistribute it and/or
00014 //   modify it under the terms of version 2.0  of the GNU General
00015 //   Public License as published by the Free Software Foundation.
00016 //
00017 //   This program is distributed in the hope that it will be useful,
00018 //   but WITHOUT ANY WARRANTY; without even the implied warranty of
00019 //   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00020 //   GNU General Public License for more details.
00021 //
00022 //   You should have received a copy of version 2.0 of the GNU General
00023 //   Public License along with this program; if not, write to the Free
00024 //   Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
00025 //   MA 02110-1301, USA.
00026 //
00027 //
00028 // ## END COPYRIGHT, LICENSE AND WARRANTY NOTICE ##
00029 //
00030 
00031 /*! \file ezdefaultvathandler.php
00032 */
00033 
00034 /*!
00035   \class eZDefaultVATHandler ezdefaultvathandler.php
00036   \brief Default VAT handler.
00037 
00038   Provides basic VAT charging rules.
00039   Resulting VAT percentage may depend on product category
00040   and country the user is from.
00041 */
00042 
00043 class eZDefaultVATHandler
00044 {
00045     /**
00046      * \public
00047      * \static
00048      */
00049     function getVatPercent( $object, $country )
00050     {
00051         $productCategory = eZDefaultVATHandler::getProductCategory( $object );
00052 
00053         // If product category is not specified
00054         if ( $productCategory === null )
00055         {
00056             require_once( 'kernel/classes/ezproductcategory.php' );
00057 
00058             // Default to a fake product category (*) that will produce
00059             // weak match on category for any VAT rule.
00060             $productCategory = new eZProductCategory( array( 'id' => -1,
00061                                                              'name' => '*' ) );
00062         }
00063 
00064         // If country is not specified
00065         if ( !$country )
00066         {
00067             // Default to a fake country that will produce
00068             // weak match on country for any VAT rule.
00069             $country = '*';
00070         }
00071 
00072         $vatType = eZDefaultVATHandler::chooseVatType( $productCategory, $country );
00073 
00074         return $vatType->attribute( 'percentage' );
00075     }
00076 
00077     /**
00078      * Determine object's product category.
00079      *
00080      * \private
00081      * \static
00082      */
00083     function getProductCategory( $object )
00084     {
00085         $ini = eZINI::instance( 'shop.ini' );
00086         if ( !$ini->hasVariable( 'VATSettings', 'ProductCategoryAttribute' ) )
00087         {
00088             eZDebug::writeError( "Cannot find product category: please specify its attribute identifier " .
00089                                  "in the following setting: shop.ini.[VATSettings].ProductCategoryAttribute" );
00090             return null;
00091         }
00092 
00093         $categoryAttributeName = $ini->variable( 'VATSettings', 'ProductCategoryAttribute' );
00094 
00095         if ( !$categoryAttributeName )
00096         {
00097             eZDebug::writeError( "Cannot find product category: empty attribute name specified " .
00098                                  "in the following setting: shop.ini.[VATSettings].ProductCategoryAttribute" );
00099 
00100             return null;
00101         }
00102 
00103         $productDataMap = $object->attribute( 'data_map' );
00104 
00105         if ( !isset( $productDataMap[$categoryAttributeName] ) )
00106         {
00107             eZDebug::writeError( "Cannot find product category: there is no attribute '$categoryAttributeName' in object '" .
00108                                   $object->attribute( 'name' ) .
00109                                   "' of class '" .
00110                                   $object->attribute( 'class_name' ) . "'." );
00111             return null;
00112         }
00113 
00114         $categoryAttribute = $productDataMap[$categoryAttributeName];
00115         $productCategory = $categoryAttribute->attribute( 'content' );
00116 
00117         if ( $productCategory === null )
00118         {
00119             eZDebug::writeNotice( "Product category is not specified in object '" .
00120                                    $object->attribute( 'name' ) .
00121                                    "' of class '" .
00122                                    $object->attribute( 'class_name' ) . "'." );
00123             return null;
00124         }
00125 
00126         return $productCategory;
00127     }
00128 
00129     /**
00130      * Choose the best matching VAT type for given product category and country.
00131      *
00132      * We calculate priority for each VAT type and then choose
00133      * the VAT type having the highest priority
00134      * (or first of those having the highest priority).
00135      *
00136      * VAT type priority is calculated from county match and category match as following:
00137      *
00138      * CountryMatch  = 0
00139      * CategoryMatch = 1
00140      *
00141      * if ( <there is exact match on country> )
00142      *     CountryMatch = 2
00143      * elseif ( <there is weak match on country> )
00144      *     CountryMatch = 1
00145      *
00146      * if ( <there is exact match on product category> )
00147      *     CategoryMatch = 2
00148      * elseif ( <there is weak match on product category> )
00149      *     CategoryMatch = 1
00150      *
00151      * if ( <there is match on both country and category )
00152      *     VatTypePriority = CountryMatch * 2 + CategoryMatch - 2
00153      * else
00154      *     VatTypePriority = 0
00155      *
00156      * \private
00157      * \static
00158      */
00159     function chooseVatType( $productCategory, $country )
00160     {
00161         require_once( 'kernel/classes/ezvatrule.php' );
00162 
00163         $vatRules = eZVatRule::fetchList();
00164 
00165         $catID = $productCategory->attribute( 'id' );
00166 
00167         $vatPriorities = array();
00168         foreach ( $vatRules as $rule )
00169         {
00170             $ruleCountry = $rule->attribute( 'country_code' );
00171             $ruleCatIDs  = $rule->attribute( 'product_categories_ids' );
00172             $ruleVatID   = $rule->attribute( 'vat_type' );
00173 
00174             $categoryMatch = 0;
00175             $countryMatch  = 0;
00176 
00177             if ( $ruleCountry == '*' )
00178                 $countryMatch = 1;
00179             elseif ( $ruleCountry == $country )
00180                 $countryMatch = 2;
00181 
00182             if ( !$ruleCatIDs )
00183                 $categoryMatch = 1;
00184             elseif ( in_array( $catID, $ruleCatIDs ) )
00185                 $categoryMatch = 2;
00186 
00187             if ( $countryMatch && $categoryMatch )
00188                 $vatPriority = $countryMatch * 2 + $categoryMatch - 2;
00189             else
00190                 $vatPriority = 0;
00191 
00192             if ( !isset( $vatPriorities[$vatPriority] ) )
00193                 $vatPriorities[$vatPriority] = $ruleVatID;
00194         }
00195 
00196         krsort( $vatPriorities, SORT_NUMERIC );
00197 
00198 
00199         $bestPriority = 0;
00200         if ( $vatPriorities )
00201         {
00202             $tmpKeys = array_keys( $vatPriorities );
00203             $bestPriority = array_shift( $tmpKeys );
00204         }
00205 
00206         if ( $bestPriority == 0 )
00207         {
00208             eZDebug::writeError( "Cannot find a suitable VAT type " .
00209                                  "for country '" . $country . "'" .
00210                                  " and category '" . $productCategory->attribute( 'name' ). "'." );
00211 
00212             return new eZVatType( array( "id" => 0,
00213                                          "name" => ezi18n( 'kernel/shop', 'None' ),
00214                                          "percentage" => 0.0 ) );
00215         }
00216 
00217         $bestVatTypeID = array_shift( $vatPriorities );
00218         $bestVatType = eZVatType::fetch( $bestVatTypeID );
00219 
00220         eZDebug::writeDebug(
00221             sprintf( "Best matching VAT for '%s'/'%s' is '%s' (%d%%)",
00222                      $country,
00223                      $productCategory->attribute( 'name' ),
00224                      $bestVatType->attribute( 'name' ),
00225                      $bestVatType->attribute( 'percentage' ) ) );
00226 
00227         return $bestVatType;
00228     }
00229 }
00230 
00231 ?>