eZ Publish  [trunk]
ezdefaultvathandler.php
Go to the documentation of this file.
00001 <?php
00002 /**
00003  * File containing the eZDefaultVATHandler class.
00004  *
00005  * @copyright Copyright (C) 1999-2012 eZ Systems AS. All rights reserved.
00006  * @license http://www.gnu.org/licenses/gpl-2.0.txt GNU General Public License v2
00007  * @version //autogentag//
00008  * @package kernel
00009  */
00010 
00011 /*!
00012   \class eZDefaultVATHandler ezdefaultvathandler.php
00013   \brief Default VAT handler.
00014 
00015   Provides basic VAT charging rules.
00016   Resulting VAT percentage may depend on product category
00017   and country the user is from.
00018 */
00019 
00020 class eZDefaultVATHandler
00021 {
00022     /**
00023      * \public
00024      * \static
00025      */
00026     function getVatPercent( $object, $country )
00027     {
00028         $productCategory = eZDefaultVATHandler::getProductCategory( $object );
00029 
00030         // If product category is not specified
00031         if ( $productCategory === null )
00032         {
00033             // Default to a fake product category (*) that will produce
00034             // weak match on category for any VAT rule.
00035             $productCategory = new eZProductCategory( array( 'id' => -1,
00036                                                              'name' => '*' ) );
00037         }
00038 
00039         // If country is not specified
00040         if ( !$country )
00041         {
00042             // Default to a fake country that will produce
00043             // weak match on country for any VAT rule.
00044             $country = '*';
00045         }
00046 
00047         $vatType = eZDefaultVATHandler::chooseVatType( $productCategory, $country );
00048 
00049         return $vatType->attribute( 'percentage' );
00050     }
00051 
00052     /**
00053      * Determine object's product category.
00054      *
00055      * \private
00056      * \static
00057      */
00058     function getProductCategory( $object )
00059     {
00060         $ini = eZINI::instance( 'shop.ini' );
00061         if ( !$ini->hasVariable( 'VATSettings', 'ProductCategoryAttribute' ) )
00062         {
00063             eZDebug::writeError( "Cannot find product category: please specify its attribute identifier " .
00064                                  "in the following setting: shop.ini.[VATSettings].ProductCategoryAttribute" );
00065             return null;
00066         }
00067 
00068         $categoryAttributeName = $ini->variable( 'VATSettings', 'ProductCategoryAttribute' );
00069 
00070         if ( !$categoryAttributeName )
00071         {
00072             eZDebug::writeError( "Cannot find product category: empty attribute name specified " .
00073                                  "in the following setting: shop.ini.[VATSettings].ProductCategoryAttribute" );
00074 
00075             return null;
00076         }
00077 
00078         $productDataMap = $object->attribute( 'data_map' );
00079 
00080         if ( !isset( $productDataMap[$categoryAttributeName] ) )
00081         {
00082             eZDebug::writeError( "Cannot find product category: there is no attribute '$categoryAttributeName' in object '" .
00083                                   $object->attribute( 'name' ) .
00084                                   "' of class '" .
00085                                   $object->attribute( 'class_name' ) . "'." );
00086             return null;
00087         }
00088 
00089         $categoryAttribute = $productDataMap[$categoryAttributeName];
00090         $productCategory = $categoryAttribute->attribute( 'content' );
00091 
00092         if ( $productCategory === null )
00093         {
00094             eZDebug::writeNotice( "Product category is not specified in object '" .
00095                                    $object->attribute( 'name' ) .
00096                                    "' of class '" .
00097                                    $object->attribute( 'class_name' ) . "'." );
00098             return null;
00099         }
00100 
00101         return $productCategory;
00102     }
00103 
00104     /**
00105      * Choose the best matching VAT type for given product category and country.
00106      *
00107      * We calculate priority for each VAT type and then choose
00108      * the VAT type having the highest priority
00109      * (or first of those having the highest priority).
00110      *
00111      * VAT type priority is calculated from county match and category match as following:
00112      *
00113      * CountryMatch  = 0
00114      * CategoryMatch = 1
00115      *
00116      * if ( there is exact match on country )
00117      *     CountryMatch = 2
00118      * elseif ( there is weak match on country )
00119      *     CountryMatch = 1
00120      *
00121      * if ( there is exact match on product category )
00122      *     CategoryMatch = 2
00123      * elseif ( there is weak match on product category )
00124      *     CategoryMatch = 1
00125      *
00126      * if ( there is match on both country and category )
00127      *     VatTypePriority = CountryMatch * 2 + CategoryMatch - 2
00128      * else
00129      *     VatTypePriority = 0
00130      *
00131      * \private
00132      * \static
00133      */
00134     function chooseVatType( $productCategory, $country )
00135     {
00136         $vatRules = eZVatRule::fetchList();
00137 
00138         $catID = $productCategory->attribute( 'id' );
00139 
00140         $vatPriorities = array();
00141         foreach ( $vatRules as $rule )
00142         {
00143             $ruleCountry = $rule->attribute( 'country_code' );
00144             $ruleCatIDs  = $rule->attribute( 'product_categories_ids' );
00145             $ruleVatID   = $rule->attribute( 'vat_type' );
00146 
00147             $categoryMatch = 0;
00148             $countryMatch  = 0;
00149 
00150             if ( $ruleCountry == '*' )
00151                 $countryMatch = 1;
00152             elseif ( $ruleCountry == $country )
00153                 $countryMatch = 2;
00154 
00155             if ( !$ruleCatIDs )
00156                 $categoryMatch = 1;
00157             elseif ( in_array( $catID, $ruleCatIDs ) )
00158                 $categoryMatch = 2;
00159 
00160             if ( $countryMatch && $categoryMatch )
00161                 $vatPriority = $countryMatch * 2 + $categoryMatch - 2;
00162             else
00163                 $vatPriority = 0;
00164 
00165             if ( !isset( $vatPriorities[$vatPriority] ) )
00166                 $vatPriorities[$vatPriority] = $ruleVatID;
00167         }
00168 
00169         krsort( $vatPriorities, SORT_NUMERIC );
00170 
00171 
00172         $bestPriority = 0;
00173         if ( $vatPriorities )
00174         {
00175             $tmpKeys = array_keys( $vatPriorities );
00176             $bestPriority = array_shift( $tmpKeys );
00177         }
00178 
00179         if ( $bestPriority == 0 )
00180         {
00181             eZDebug::writeError( "Cannot find a suitable VAT type " .
00182                                  "for country '" . $country . "'" .
00183                                  " and category '" . $productCategory->attribute( 'name' ). "'." );
00184 
00185             return new eZVatType( array( "id" => 0,
00186                                          "name" => ezpI18n::tr( 'kernel/shop', 'None' ),
00187                                          "percentage" => 0.0 ) );
00188         }
00189 
00190         $bestVatTypeID = array_shift( $vatPriorities );
00191         $bestVatType = eZVatType::fetch( $bestVatTypeID );
00192 
00193         eZDebug::writeDebug(
00194             sprintf( "Best matching VAT for '%s'/'%s' is '%s' (%d%%)",
00195                      $country,
00196                      $productCategory->attribute( 'name' ),
00197                      $bestVatType->attribute( 'name' ),
00198                      $bestVatType->attribute( 'percentage' ) ) );
00199 
00200         return $bestVatType;
00201     }
00202 }
00203 
00204 ?>