eZ Publish  [trunk]
ezmultiprice.php
Go to the documentation of this file.
00001 <?php
00002 /**
00003  * File containing the eZMultiPrice 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 eZMultiPrice ezmultiprice.php
00013   \ingroup eZDatatype
00014   \brief Handles prices in different currencies with VAT and discounts.
00015 
00016   The available attributes are:
00017   - vat_type
00018   - current_user
00019   - is_vat_included
00020   - selected_vat_type
00021   - vat_percent
00022   - inc_vat_price
00023   - ex_vat_price
00024   - discount_percent
00025   - discount_price_inc_vat
00026   - discount_price_ex_vat
00027   - has_discount
00028   - price
00029 */
00030 
00031 class eZMultiPrice extends eZSimplePrice
00032 {
00033     const CALCULATION_TYPE_VAT_INCLUDE = 1;
00034     const CALCULATION_TYPE_VAT_EXCLUDE = 2;
00035     const CALCULATION_TYPE_DISCOUNT_INCLUDE = 3;
00036     const CALCULATION_TYPE_DISCOUNT_EXCLUDE = 4;
00037 
00038     /*!
00039      Constructor
00040     */
00041     function eZMultiPrice( $classAttribute, $contentObjectAttribute, $storedPrice = null )
00042     {
00043         eZSimplePrice::eZSimplePrice( $classAttribute, $contentObjectAttribute, $storedPrice );
00044 
00045         $isVatIncluded = ( $classAttribute->attribute( eZMultiPriceType::INCLUDE_VAT_FIELD ) == 1 );
00046         $VATID = $classAttribute->attribute( eZMultiPriceType::VAT_ID_FIELD );
00047 
00048         $this->setVatIncluded( $isVatIncluded );
00049         $this->setVatType( $VATID );
00050 
00051         $this->IsDataDirty = false;
00052         $this->ContentObjectAttribute = $contentObjectAttribute;
00053     }
00054 
00055     /*!
00056      \return An array with attributes that is available.
00057     */
00058     function attributes()
00059     {
00060         return array_unique( array_merge( array( 'currency_list',
00061                                                  'auto_currency_list',
00062                                                  'price_list',
00063                                                  'auto_price_list',
00064                                                  'custom_price_list',
00065                                                  'inc_vat_price_list',
00066                                                  'ex_vat_price_list',
00067                                                  'discount_inc_vat_price_list',
00068                                                  'discount_ex_vat_price_list' ),
00069                                           eZSimplePrice::attributes() ) );
00070     }
00071 
00072     /*!
00073      \return \c true if the attribute named \a $attr exists.
00074     */
00075     function hasAttribute( $attr )
00076     {
00077         return in_array( $attr, $this->attributes() );
00078     }
00079 
00080     /*!
00081       Sets the attribute named \a $attr to value \a $value.
00082     */
00083     function setAttribute( $attr, $value )
00084     {
00085         switch ( $attr )
00086         {
00087             case 'currency_list':
00088             {
00089             } break;
00090 
00091             case 'auto_currency_list':
00092             {
00093             } break;
00094 
00095             case 'price_list':
00096             {
00097             } break;
00098 
00099             case 'auto_price_list':
00100             {
00101             } break;
00102 
00103             case 'custom_price_list':
00104             {
00105             } break;
00106 
00107             default:
00108             {
00109                 eZSimplePrice::setAttribute( $attr, $value );
00110             } break;
00111         }
00112     }
00113 
00114     /*!
00115      \return The value of the attribute named \a $attr or \c null if it doesn't exist.
00116     */
00117     function attribute( $attr )
00118     {
00119         switch ( $attr )
00120         {
00121             case 'currency_list':
00122             {
00123                 return $this->currencyList();
00124             } break;
00125 
00126             case 'auto_currency_list':
00127             {
00128                 return $this->autoCurrencyList();
00129             } break;
00130 
00131             case 'price_list':
00132             {
00133                 return $this->priceList();
00134             } break;
00135 
00136             case 'inc_vat_price_list':
00137             {
00138                 return $this->incVATPriceList();
00139             } break;
00140 
00141             case 'ex_vat_price_list':
00142             {
00143                 return $this->exVATPriceList();
00144             } break;
00145 
00146             case 'discount_inc_vat_price_list':
00147             {
00148                 return $this->discountIncVATPriceList();
00149             } break;
00150 
00151             case 'discount_ex_vat_price_list':
00152             {
00153                 return $this->discountExVATPriceList();
00154             } break;
00155 
00156             case 'auto_price_list':
00157             {
00158                 return $this->autoPriceList();
00159             } break;
00160 
00161             case 'custom_price_list':
00162             {
00163                 return $this->customPriceList();
00164             } break;
00165 
00166             default :
00167             {
00168                 return eZSimplePrice::attribute( $attr );
00169             } break;
00170         }
00171     }
00172 
00173     /*!
00174      functional attribute
00175     */
00176 
00177     function preferredCurrencyCode()
00178     {
00179         return eZShopFunctions::preferredCurrencyCode();
00180     }
00181 
00182     function currencyList()
00183     {
00184         if ( !isset( $this->CurrencyList ) )
00185         {
00186             $this->CurrencyList = eZCurrencyData::fetchList();
00187         }
00188 
00189         return $this->CurrencyList;
00190     }
00191 
00192     /*!
00193      functional attribute
00194     */
00195     function autoCurrencyList()
00196     {
00197         // 'auto currencies' are the currencies used for 'auto' prices.
00198         // 'auto currencies' = 'all currencies' - 'currencies of custom prices'
00199 
00200         $autoCurrecyList = $this->currencyList();
00201         $customPriceList = $this->customPriceList();
00202         foreach ( $customPriceList as $price )
00203         {
00204             if ( $price )
00205             {
00206                 $currencyCode = $price->attribute( 'currency_code' );
00207                 unset( $autoCurrecyList[$currencyCode] );
00208             }
00209         }
00210 
00211         return $autoCurrecyList;
00212     }
00213 
00214     /*!
00215      functional attribute
00216     */
00217     function customPriceList()
00218     {
00219         return $this->priceList( eZMultiPriceData::VALUE_TYPE_CUSTOM );
00220     }
00221 
00222     function autoPriceList()
00223     {
00224         return $this->priceList( eZMultiPriceData::VALUE_TYPE_AUTO );
00225     }
00226 
00227     function priceList( $type = false )
00228     {
00229         if ( !isset( $this->PriceList ) )
00230         {
00231             if ( is_object( $this->ContentObjectAttribute ) )
00232             {
00233                 $this->PriceList = eZMultiPriceData::fetch( $this->ContentObjectAttribute->attribute( 'id' ),
00234                                                             $this->ContentObjectAttribute->attribute( 'version' ) );
00235             }
00236 
00237             if ( !$this->PriceList )
00238             {
00239                 $this->PriceList = array();
00240             }
00241         }
00242 
00243         $priceList = array();
00244         if ( $type !== false )
00245         {
00246             foreach ( $this->priceList() as $currencyCode => $price )
00247             {
00248                 if ( $price->attribute( 'type' ) == $type )
00249                 {
00250                     $priceList[$currencyCode] = $price;
00251                 }
00252             }
00253         }
00254         else
00255         {
00256             $priceList = $this->PriceList;
00257         }
00258 
00259         return $priceList;
00260     }
00261 
00262     function incVATPriceList( $type = false )
00263     {
00264         return $this->calcPriceList( self::CALCULATION_TYPE_VAT_INCLUDE, $type );
00265     }
00266 
00267     function exVATPriceList( $type = false )
00268     {
00269         return $this->calcPriceList( self::CALCULATION_TYPE_VAT_EXCLUDE, $type );
00270     }
00271 
00272     function discountIncVATPriceList( $type = false )
00273     {
00274         return $this->calcPriceList( self::CALCULATION_TYPE_DISCOUNT_INCLUDE, $type );
00275     }
00276 
00277     function discountExVATPriceList( $type = false )
00278     {
00279         return $this->calcPriceList( self::CALCULATION_TYPE_DISCOUNT_EXCLUDE, $type );
00280     }
00281 
00282     function calcPriceList( $calculationType, $priceType )
00283     {
00284         $priceList = $this->priceList( $priceType );
00285 
00286         $calculatedPriceList = array();
00287         foreach ( $priceList as $key => $price )
00288         {
00289             switch ( $calculationType )
00290             {
00291                 case self::CALCULATION_TYPE_VAT_INCLUDE :
00292                 {
00293                     $value = $this->calcIncVATPrice( $price->attribute( 'value' ) );
00294                 } break;
00295 
00296                 case self::CALCULATION_TYPE_VAT_EXCLUDE :
00297                 {
00298                     $value = $this->calcExVATPrice( $price->attribute( 'value' ) );
00299                 } break;
00300 
00301                 case self::CALCULATION_TYPE_DISCOUNT_INCLUDE :
00302                 {
00303                     $value = $this->calcDiscountIncVATPrice( $price->attribute( 'value' ) );
00304                 } break;
00305 
00306                 case self::CALCULATION_TYPE_DISCOUNT_EXCLUDE :
00307                 {
00308                     $value = $this->calcDiscountExVATPrice( $price->attribute( 'value' ) );
00309                 } break;
00310 
00311                 default:
00312                 {
00313                     // do nothing
00314                 } break;
00315             }
00316 
00317             $calculatedPrice = clone $price;
00318             $calculatedPrice->setAttribute( 'value', $value );
00319             $calculatedPriceList[$key] = $calculatedPrice;
00320         }
00321 
00322         return $calculatedPriceList;
00323     }
00324 
00325     static function removeByID( $objectAttributeID, $objectAttributeVersion = null )
00326     {
00327         eZMultiPriceData::removeByOAID( $objectAttributeID, $objectAttributeVersion );
00328     }
00329 
00330     function removePriceByCurrency( $currencyCode )
00331     {
00332         $price = $this->priceByCurrency( $currencyCode );
00333         if ( $price )
00334         {
00335             $price->remove();
00336             $priceList = $this->priceList();
00337             unset( $priceList[$currencyCode] );
00338         }
00339     }
00340 
00341     function setCustomPrice( $currencyCode, $value )
00342     {
00343         $this->setPriceByCurrency( $currencyCode, $value, eZMultiPriceData::VALUE_TYPE_CUSTOM );
00344     }
00345 
00346     function setAutoPrice( $currencyCode, $value )
00347     {
00348         $this->setPriceByCurrency( $currencyCode, $value, eZMultiPriceData::VALUE_TYPE_AUTO );
00349     }
00350 
00351     function setPriceByCurrency( $currencyCode, $value, $type )
00352     {
00353         if ( !$this->updatePrice( $currencyCode, $value, $type ) &&
00354              !$this->addPrice( $currencyCode, $value, $type ) )
00355         {
00356             eZDebug::writeWarning( "Unable to set price in '$currencyCode'", __METHOD__ );
00357             return false;
00358         }
00359 
00360         return true;
00361     }
00362 
00363     function setPrice( $value )
00364     {
00365     }
00366 
00367     function updateAutoPriceList()
00368     {
00369         $converter = eZCurrencyConverter::instance();
00370 
00371         $basePrice = $this->basePrice();
00372         $basePriceValue = $basePrice ? $basePrice->attribute( 'value' ) : 0;
00373         $baseCurrencyCode = $basePrice ? $basePrice->attribute( 'currency_code' ) : false;
00374 
00375         $autoCurrencyList = $this->autoCurrencyList();
00376         foreach( $autoCurrencyList as $currencyCode => $currency )
00377         {
00378             $autoValue = $converter->convert( $baseCurrencyCode, $currencyCode, $basePriceValue );
00379             $this->setAutoPrice( $currencyCode, $autoValue );
00380         }
00381     }
00382 
00383     function createPrice( $currencyCode, $value, $type )
00384     {
00385         if ( is_object( $this->ContentObjectAttribute ) && $this->currencyByCode( $currencyCode ) )
00386         {
00387             return eZMultiPriceData::create( $this->ContentObjectAttribute->attribute( 'id' ),
00388                                              $this->ContentObjectAttribute->attribute( 'version' ),
00389                                              $currencyCode,
00390                                              $value,
00391                                              $type );
00392         }
00393         return false;
00394     }
00395 
00396 
00397     function addPrice( $currencyCode, $value, $type )
00398     {
00399         $price = $this->createPrice( $currencyCode, $value, $type );
00400         if( $price )
00401         {
00402             if ( $value === false )
00403                 $price->setAttribute( 'value', '0.00' );
00404 
00405             $this->PriceList[$price->attribute( 'currency_code' )] = $price;
00406             $this->setHasDirtyData( true );
00407         }
00408 
00409         return $price;
00410     }
00411 
00412     function updatePrice( $currencyCode, $value, $type )
00413     {
00414         $price = $this->priceByCurrency( $currencyCode );
00415         if( $price )
00416         {
00417             if ( $value !== false )
00418             {
00419                 $price->setAttribute( 'value', $value );
00420             }
00421 
00422             if ( $type !== false )
00423             {
00424                 $price->setAttribute( 'type', $type );
00425             }
00426 
00427             $this->setHasDirtyData( true );
00428         }
00429 
00430         return $price;
00431     }
00432 
00433     function customPrice( $currencyCode )
00434     {
00435         return $this->priceByCurrency( $currencyCode, eZMultiPriceData::VALUE_TYPE_CUSTOM );
00436     }
00437 
00438     function autoPrice( $currencyCode )
00439     {
00440         return $this->priceByCurrency( $currencyCode, eZMultiPriceData::VALUE_TYPE_AUTO );
00441     }
00442 
00443     function priceByCurrency( $currencyCode, $type = false )
00444     {
00445         $price = false;
00446         $priceList = $this->priceList();
00447 
00448         if ( isset( $priceList[$currencyCode] ) )
00449         {
00450             if( $type === false || $priceList[$currencyCode]->attribute( 'type' ) == $type )
00451             {
00452                 $price = $priceList[$currencyCode];
00453             }
00454         }
00455 
00456         return $price;
00457     }
00458 
00459     function price()
00460     {
00461         $value = '0.0';
00462         if ( $currencyCode = $this->preferredCurrencyCode() )
00463         {
00464             $price = $this->priceByCurrency( $currencyCode );
00465             if ( $price )
00466             {
00467                 $value = $price->attribute( 'value' );
00468             }
00469         }
00470 
00471         return $value;
00472     }
00473 
00474     function currencyByCode( $currencyCode )
00475     {
00476         $currency = false;
00477         $currencyList = $this->currencyList();
00478         if ( isset( $currencyList[$currencyCode] ) )
00479         {
00480             $currency = $currencyList[$currencyCode];
00481         }
00482 
00483         return $currency;
00484     }
00485 
00486     function store()
00487     {
00488         if ( $this->hasDirtyData() )
00489         {
00490             $this->storePriceList();
00491             $this->setHasDirtyData( false );
00492         }
00493     }
00494 
00495     function storePriceList()
00496     {
00497         if ( isset( $this->PriceList ) && count( $this->PriceList ) > 0 )
00498         {
00499             $priceList = $this->priceList();
00500             foreach ( $priceList as $price )
00501             {
00502                 $price->store();
00503             }
00504         }
00505     }
00506 
00507     function hasDirtyData()
00508     {
00509         return $this->HasDataDirty;
00510     }
00511 
00512     function setHasDirtyData( $hasDirtyData )
00513     {
00514         $this->HasDataDirty = $hasDirtyData;
00515     }
00516 
00517     /*!
00518      Returns a currency code of the first custom price.
00519     */
00520     function baseCurrency()
00521     {
00522         // use value of the first custom price as
00523         // base price and base currency.
00524 
00525         $baseCurrency = false;
00526         $customPriceList = $this->customPriceList();
00527         $currencies = array_keys( $customPriceList );
00528         if ( count( $currencies ) > 0 )
00529         {
00530             $baseCurrency = $currencies[0];
00531         }
00532 
00533         return $baseCurrency;
00534     }
00535 
00536     function basePrice()
00537     {
00538         $baseCurrencyCode = $this->baseCurrency();
00539         return $this->priceByCurrency( $baseCurrencyCode );
00540     }
00541 
00542     function currency()
00543     {
00544         return $this->preferredCurrencyCode();
00545     }
00546 
00547     function DOMDocument()
00548     {
00549         $doc = new DOMDocument( '1.0', 'utf-8' );
00550         $root = $doc->createElement( 'ezmultiprice' );
00551         $doc->appendChild( $root );
00552 
00553         $priceListNode = $doc->createElement( 'price-list' );
00554 
00555         $priceList = $this->attribute( 'price_list' );
00556         foreach ( $priceList as $price )
00557         {
00558             $currencyCode = $price->attribute( 'currency_code' );
00559             $value = $price->attribute( 'value' );
00560             $type = $price->attribute( 'type' );
00561 
00562             $priceNode = $doc->createElement( 'price' );
00563 
00564             $priceNode->setAttribute( 'currency-code', $currencyCode );
00565             $priceNode->setAttribute( 'value', $value );
00566             $priceNode->setAttribute( 'type', $type );
00567 
00568             $priceListNode->appendChild( $priceNode );
00569             unset( $priceNode );
00570         }
00571 
00572         $root->appendChild( $priceListNode );
00573 
00574         return $doc;
00575     }
00576 
00577     function decodeDOMTree( $rootNode )
00578     {
00579         $priceNode = $rootNode->getElementsByTagName( 'price-list' )->item( 0 );
00580         $priceNodes = $priceNode->getElementsByTagName( 'price' );
00581         if ( $priceNodes->length > 0 )
00582         {
00583             foreach ( $priceNodes as $priceNode )
00584             {
00585                 $currencyCode = $priceNode->getAttribute( 'currency-code' );
00586                 $value = $priceNode->getAttribute( 'value' );
00587                 $type = $priceNode->getAttribute( 'type' );
00588 
00589                 $this->setPriceByCurrency( $currencyCode, $value, $type );
00590             }
00591         }
00592     }
00593 
00594     /// \privatesection
00595     public $PriceList;
00596     public $CurrencyList;
00597     public $HasDataDirty;
00598     public $ContentObjectAttribute;
00599 }
00600 
00601 ?>