|
|
- <?php
- require(__DATAGEN_CLASSES__ . '/ShoppingCartGen.class.php');
-
- /**
- * The ShoppingCart class defined here represents the "shopping_cart" table
- * in the database, and extends from the code generated abstract ShoppingCartGen
- * class, which contains all the basic CRUD-type functionality as well as
- * basic methods to handle relationships and index-based loading.
- *
- * This class also provides a factory method to generate an Order object from the
- * current contents of the cart - see CreateNewOrder below.
- *
- * @package Quasi
- * @subpackage ORM
- *
- */
- class ShoppingCart extends ShoppingCartGen
- {
- /**
- *@var Order objOrder - a new Order object for the contents of this cart
- */
- protected $objOrder;
-
- /**
- *@var Account objAccount - a new Account object for the contents of this cart
- */
- protected $objAccount;
-
- /**
- *@var boolean blnUsePreviousAddresses - if true, attempt to use address from last order for new order.
- */
- protected $blnUsePreviousAddresses;
-
- /**
- * Default "to string" handler
- * Allows pages to _p()/echo()/print() this object, and to define the default
- * way this object would be outputted.
- *
- * Can also be called directly via $objShoppingCart->__toString().
- *
- * @return string a nicely formatted string representation of this object
- */
- public function __toString() {
- return sprintf('Cart for %s', $this->Account);
- }
-
- public static function LoadByAccountId($intAccountId)
- {
- return ShoppingCart::QuerySingle(QQ::Equal(QQN::ShoppingCart()->AccountId, $intAccountId) );
- }
-
- public function AddItem($intProductId)
- {
- $objSCItem = ShoppingCartItem::LoadByProductIdShoppingCartId($intProductId, $this->Id);
- if(!$objSCItem)
- {
- $objSCItem = new ShoppingCartItem();
- $objSCItem->ProductId = $intProductId;
- $objSCItem->ShoppingCartId = $this->Id;
- }//Note: quantity defaults to 1 on creation ..
- else
- $objSCItem->Quantity += 1;
-
- $objSCItem->Save();
- $this->RefreshCartModule();
-
- }
- public function RemoveItem($intProductId)
- {
- $objSCItem = ShoppingCartItem::LoadByProductIdShoppingCartId($intProductId, $this->Id);
- if($objSCItem)
- {
- $objSCItem->Delete();
- $this->RefreshCartModule();
- }
- }
- public function RefreshCartModule()
- {
- ///@todo - kludge to refresh the module, do this without reloading the page ..
-
- QApplication::Redirect(Quasi::$RequestUri );
-
- /* $objShoppingCartModule = IndexPage::$MainWindow->GetActiveModule('ShoppingCartModule');
- if($objShoppingCartModule instanceof ShoppingCartModule)
- $objShoppingCartModule->RefreshCart();*/
- }
- /**
- * This function creates a new Order object initilized with the current contents of the cart.
- * Note: the order is returned unsaved, both the order and order items are virtual and not
- * inserted to the database until Save() is called on the order object.
- *
- * The Order is returned unsaved with status set to "Shopping". The array of NewOrderItems in the
- * new order is loaded with OrderItems created from the ShoppingCart Items.
- * If possible we set the Shipping cost based on the default configured shipping method
- *
- *
- * This function uses several subfunctions to:
- * - transfer order items from the shopping cart items
- * - calculate estimated shipping
- * - calculate taxes
- * - set the address fields based on the Account addresses
- * - set the price totals
- * @todo - be able to save order/address state if they go back from checkout
- * really the cart box could be merged into the Checkout module
- * if($this->objOrder instanceof Order)
- * return $this->objOrder;
- *@param boolean blnUsePreviousAddresses - if true, use the Addresses from the previous order
- * @return Order - an initialized order object
- */
- public function CreateNewOrder($blnUsePreviousAddresses=false)
- {
- $this->blnUsePreviousAddresses = $blnUsePreviousAddresses;
-
- if(! $this->AccountId)
- throw new QCallerException('CreateOrder called on a ShoppingCart that has no Account Id!');
-
- $this->objOrder = new Order();
- $this->objAccount = Account::LoadById($this->AccountId);
- $this->initOrderAddresses();
-
- if( $this->objOrder->ShippingCountryId != CountryType::GetId(STORE_COUNTRY) )
- $this->objOrder->IsInternational = true;
- else
- $this->objOrder->IsInternational = false;
-
- $this->objOrder->AccountId = $this->AccountId;
- $this->objOrder->StatusId = OrderStatusType::Shopping;
-
- // create the order items from shopping cart ..
- $this->initOrderItems();
-
- //try to set a default shipping charge estimate ..
- $this->initOrderShippingCharge();
-
- ///@todo this should be more configurable ..
- $this->objOrder->HandlingCharged = DEFAULT_HANDLING_CHARGE;
-
- $this->objOrder->InitTax();
- return $this->objOrder;
-
- }
- /**
- * This function initializes the array of OrderItems and also various product totals in the Order.
- * The order items are obtained from the ShoppingCartItems, a Product is instatiated for each
- * to obtain values added to Order totals.
- */
- private function initOrderItems()
- {
- $fltProductTotalCharged = 0.0;
- $fltProductTotalCost = 0.0;
- $fltMaxX = 0.0;
- $fltMaxY = 0.0;
- $fltMaxZ = 0.0;
-
- foreach ( $this->GetShoppingCartItemArray() as $objShoppingCartItem )
- {
- $objItem = new OrderItem();
- $objItem->ProductId = $objShoppingCartItem->ProductId;
- $objItem->Quantity = $objShoppingCartItem->Quantity;
- $this->objOrder->AddNewOrderItem($objItem);
-
- //now, increment order values for each product ..
- $objProduct = Product::Load($objItem->ProductId);
- //increment total price
- $fltProductTotalCharged += $objProduct->RetailPrice * $objItem->Quantity;
- $fltProductTotalCost += $objProduct->Cost * $objItem->Quantity;
- //increment total weight
- $this->objOrder->TotalOunces += $objProduct->Weight;
- //increment total max sizes
- if($objProduct->Width > $fltMaxX)
- $fltMaxX = $objProduct->Width;
- if($objProduct->Height > $fltMaxY)
- $fltMaxY = $objProduct->Height;
-
- //BUG alert: add thickness, tranlates to "height" in shipping, sorry ..
- // this might need fixing, we are assuming things are stacked up and
- // that they are thin (like PCB boards ..)
- $fltMaxZ += $objProduct->Depth;
-
- }
-
- $this->objOrder->ProductTotalCharged = $fltProductTotalCharged;
- $this->objOrder->ProductTotalCost = $fltProductTotalCost;
-
- if($this->objOrder->TotalOunces >= 16)
- {
- $this->objOrder->TotalPounds = (int) floor( $this->objOrder->TotalOunces / 16 );
- $this->objOrder->TotalOunces = ( $this->objOrder->TotalOunces % 16);
- }
-
- $this->objOrder->XAxisSize = $fltMaxX;
- $this->objOrder->YAxisSize = $fltMaxY;
- $this->objOrder->ZAxisSize = $fltMaxZ;
- }
- /**
- * This function determines the default addresses for the Account and place them in Order fields
- * for shipping and billing address. These may be modified by the user in the CheckOutEditModule
- * The default addresses are those for the Person associated with the Account - note that these
- * may be changed by the user, here we are just setting the defaults for initial display.
- *
- * Note: if CreateNewOrder(true) was called, UsePreviousAddresses will be set true and will trigger
- * an attempt to initilize the order using the last used address - if no previous order exists the
- * usual default assignment occurs.
- */
- private function initOrderAddresses()
- {
- if($this->blnUsePreviousAddresses)
- {
- $aryClauses = array();
- array_push($aryClauses, QQ::OrderBy(QQN::Order()->CreationDate, false) );
-
- $objPreviousOrder = Order::QuerySingle(
- QQ::Equal(QQN::Order()->AccountId, $this->AccountId),
- $aryClauses
- );
- //if possible, just copy addresses from previous order ..
- if($objPreviousOrder instanceof Order)
- {
- $this->objOrder = $objPreviousOrder;
- $this->objOrder->Id = null;
- $this->objOrder->Restored = false;
- $this->objOrder->HandlingCharged = null;
- $this->objOrder->ProductTotalCharged = null;
- $this->objOrder->ShippingCharged = null;
- $this->objOrder->ProductTotalCost = null;
- $this->objOrder->ShippingCost = null;
- $this->objOrder->Tax = null;
- $this->objOrder->CreationDate = null;
- $this->objOrder->LastModificationDate = null;
- $this->objOrder->CompletionDate = null;
- $this->objOrder->Notes = null;
- $this->objOrder->ShippingMethodId = null;
- $this->objOrder->PaymentMethodId = null;
-
- /* Bug alert - these may need to be reset .. however, they are all private
- so we would need to override in Order. Leave unless problematic.
- $this->objOrder->_objOrderChange = null;
- $this->objOrder->_objOrderChangeArray = array();
- $this->objOrder->_objOrderItem = null;
- $this->objOrder->_objOrderItemArray = array();
- $this->objOrder->_objOrderStatusHistory = null;
- $this->objOrder->_objOrderStatusHistoryArray = array();
- $this->objOrder->_objPaypalTransaction = null;
- $this->objOrder->_objPaypalTransactionArray = array();
- $this->objOrder->_objTrackingNumber = null;
- $this->objOrder->_objTrackingNumberArray = array();
- $this->objOrder->__strVirtualAttributeArray = array();
- */
- //now, attempt to set address ids used ..
- $this->objOrder->SetShippingAddress($objPreviousOrder->GetShippingAddress());
- $this->objOrder->SetBillingAddress($objPreviousOrder->GetBillingAddress());
-
- return;
- }
- }
- //Otherwise, try to get a shipping address or default to primary ..
- $objShippingAddress = Address::QuerySingle( QQ::AndCondition (
- QQ::Equal(QQN::Address()->PersonId, $this->objAccount->PersonId ),
- QQ::Equal(QQN::Address()->TypeId, AddressType::Shipping)
- ) );
- if( null === $objShippingAddress )
- $objShippingAddress = Address::QuerySingle( QQ::AndCondition (
- QQ::Equal(QQN::Address()->PersonId, $this->objAccount->PersonId ),
- QQ::Equal(QQN::Address()->TypeId, AddressType::Primary)
- ) );
- //could be that they entered something different in their account so check for associated persons/addresses ..
- if( null === $objShippingAddress )
- {
- $aryPersonIds = array();
- $aryPersons = Person::QueryArray(QQ::Equal(QQN::Person()->OwnerPersonId, $this->objAccount->PersonId));
- if(!empty($aryPersons) )
- foreach($aryPersons as $objPerson )
- $aryPersonIds[] = $objPerson->Id;
- else
- throw new QCallerException('ShoppingCart: No shipping address found for ' . $this->objAccount);
-
- $objShippingAddress = Address::QuerySingle( QQ::AndCondition (
- QQ::In(QQN::Address()->PersonId, $aryPersonIds ),
- QQ::In(QQN::Address()->TypeId, array(AddressType::Primary, AddressType::Shipping, AddressType::Billing))
- ) );
- }
- //set the order's fields for shipping
- if(null != $objShippingAddress)
- $this->objOrder->SetShippingAddress($objShippingAddress);
- else
- throw new QCallerException('ShoppingCart: No shipping address found for ' . $this->objAccount);
-
- //now try to get a billing address or default to primary ..
- $objBillingAddress = Address::QuerySingle( QQ::AndCondition (
- QQ::Equal(QQN::Address()->PersonId, $this->objAccount->PersonId ),
- QQ::Equal(QQN::Address()->TypeId, AddressType::Billing)
- ) );
- if( null === $objBillingAddress )
- $objBillingAddress = Address::QuerySingle( QQ::AndCondition (
- QQ::Equal(QQN::Address()->PersonId, $this->objAccount->PersonId ),
- QQ::Equal(QQN::Address()->TypeId, AddressType::Primary)
- ) );
- if( null === $objBillingAddress )
- $objBillingAddress = $objShippingAddress;
-
-
- //set the order's fields for billing, use shipping as a default if none was found above
- if(null != $objBillingAddress)
- $this->objOrder->SetBillingAddress($objBillingAddress);
- elseif(null != $objShippingAddress)
- $this->objOrder->SetBillingAddress($objShippingAddress);
-
- }
-
- /**
- * This function attempts to set the shipping charge based on the default address
- * and the configured default provider
- */
- private function initOrderShippingCharge()
- {
- $objShippingMethod = ShippingMethod::QuerySingle( QQ::AndCondition(
- QQ::Equal(QQN::ShippingMethod()->Active, true),
- QQ::Equal( QQN::ShippingMethod()->Carrier, DEFAULT_SHIPPING_CARRIER ),
- QQ::Equal( QQN::ShippingMethod()->ServiceType, DEFAULT_SHIPPING_SERVICE )
- ));
-
- //possible that default method is inactive ..
- if( $objShippingMethod instanceof ShippingMethod )
- {
- $this->objOrder->ShippingMethodId = $objShippingMethod->Id;
- $objShippingMethod->Init($this->objOrder);
- $this->objOrder->ShippingCharged = $objShippingMethod->GetRate();
- if(! $this->objOrder->ShippingCharged )
- {//errors .. fallback to default.
- $this->objOrder->ShippingCharged = DEFAULT_SHIPPING_RATE;
- $this->objOrder->ShippingMethodId = 1;
- }
- } else {
- $this->objOrder->ShippingCharged = DEFAULT_SHIPPING_RATE;
- $this->objOrder->ShippingMethodId = 1;
- }
- }
-
- // Override or Create New Properties and Variables
- // For performance reasons, these variables and __set and __get override methods
- // are commented out. But if you wish to implement or override any
- // of the data generated properties, please feel free to uncomment them.
- /*
- protected $strSomeNewProperty;
-
- public function __get($strName) {
- switch ($strName) {
- case 'SomeNewProperty': return $this->strSomeNewProperty;
-
- default:
- try {
- return parent::__get($strName);
- } catch (QCallerException $objExc) {
- $objExc->IncrementOffset();
- throw $objExc;
- }
- }
- }
-
- public function __set($strName, $mixValue) {
- switch ($strName) {
- case 'SomeNewProperty':
- try {
- return ($this->strSomeNewProperty = QType::Cast($mixValue, QType::String));
- } catch (QInvalidCastException $objExc) {
- $objExc->IncrementOffset();
- throw $objExc;
- }
-
- default:
- try {
- return (parent::__set($strName, $mixValue));
- } catch (QCallerException $objExc) {
- $objExc->IncrementOffset();
- throw $objExc;
- }
- }
- }
- */
- }
- ?>
|