|
eZ Publish
[trunk]
|
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 ?>