public function createOrder()
 {
     $order = new Order();
     $order->write();
     $item1a = $this->mp3player->createItem(2);
     $item1a->write();
     $order->Items()->add($item1a);
     $item1b = $this->socks->createItem();
     $item1b->write();
     $order->Items()->add($item1b);
     return $order;
 }
Esempio n. 2
0
 public function createValidator()
 {
     $validator = RequiredFields::create();
     $items = $this->order->Items();
     if ($items) {
         foreach ($items as $item) {
             $validator->addRequiredField('Quantity[' . $item->ID . ']');
         }
     }
     $this->extend('updateValidator', $validator);
     $validator->setForm($this);
     return $validator;
 }
 /**
  * Add a XeroTaxModification to the order by applying tax rates to Items and Modifications in the order using 
  * the taxCalculator.
  * 
  * @param Order $order
  * @param Mixed $value Unused
  */
 public function add($order, $value = null)
 {
     // Go through the items and modifications in the order and apply a tax rate to them
     // Calculate tax based on rates for each item and modification
     $items = $order->Items();
     if ($items && $items->exists()) {
         foreach ($items as $item) {
             $this->taxCalculator->applyItemTaxRate($item);
         }
     }
     $mods = $order->Modifications();
     if ($mods && $mods->exists()) {
         foreach ($mods as $mod) {
             $this->taxCalculator->applyModificationTaxRate($mod);
         }
     }
     // Create new modification using rates for each item and modification in the order
     $taxAmount = $this->taxCalculator->calculate($order);
     $mod = new XeroTaxModification();
     $mod->Price = $taxAmount->getAmount();
     $mod->Description = _t('Xero.TAX', 'Tax');
     $mod->OrderID = $order->ID;
     $mod->Value = null;
     $mod->write();
 }
Esempio n. 4
0
 /**
  * Iterate over the order items and calculate the gst
  * for each depending on StreakGSTModule.config.currency_percentages()
  *
  * @param Order     $order
  * @param null $value
  * @throws ValidationException
  * @throws null
  */
 public function add($order, $value = null)
 {
     $gst = new Price();
     $gst->setCurrency(ShopConfig::current_shop_config()->BaseCurrency);
     $descriptions = array();
     /** @var Price|null $calculated */
     $calculated = null;
     /** @var Item $item */
     foreach ($order->Items() as $item) {
         if ($price = $item->Price()) {
             $currency = $price->getCurrency();
             if ($rate = self::rate_for_currency($currency)) {
                 if (!$calculated) {
                     $calculated = new Price();
                 }
                 $percentage = Zend_Locale_Math::Div($rate, 100.0, 10);
                 $taxed = Zend_Locale_Math::Mul($price, $percentage, 10);
                 $temp = Zend_Locale_Math::Add($calculated, $taxed, 10);
                 $calculated->setAmount($temp);
                 $descriptions[$currency] = static::description($currency);
             }
         }
     }
     if ($calculated) {
         $mod = new StreakGST_Modification();
         $mod->OrderID = $order->ID;
         $mod->Price = 0;
         $mod->Description = implode("<br/>\n", $descriptions);
         $mod->GST = $calculated->getAmount();
         $mod->Value = $calculated->getAmount();
         $mod->write();
     }
 }
 /**
  * Test {@link Order::process()}
  */
 function testProcess()
 {
     $var1 = $this->objFromFixture('ProductVariation', 'variation1');
     $var2 = $this->objFromFixture('ProductVariation', 'variation2');
     $member = $this->objFromFixture('Member', 'member1');
     $this->get("cart/add/{$var1->ID}/{$var1->class}?quantity=3");
     $this->get("cart/add/{$var2->ID}/{$var2->class}");
     $order = new Order();
     $this->assertType('DataObjectSet', $order->Items(), 'Items are in the cart, returned as a DataObjectSet');
     $this->assertType('DataObjectSet', $order->Modifiers(), 'Modifiers are in the cart, returned as a DataObjectSet');
     $order->process($member->ID);
     $this->assertType('ComponentSet', $order->Items(), 'Items are now a component set because they are in the DB');
     $this->assertType('ComponentSet', $order->Modifiers(), 'Modifiers are now a component set because they are in the DB');
     $this->assertEquals(104, $order->Subtotal());
     $this->assertEquals(104, $order->Total());
     $this->assertFalse($order->process($member->ID), 'The order in the DB cannot be processed again');
 }
 public function doProcess($data, $form, $request)
 {
     $order = new Order();
     $items = $order->Items();
     $member = Member::currentUserID() ? Member::currentUser() : new Member();
     $paymentClass = isset($data['PaymentMethod']) ? $data['PaymentMethod'] : null;
     $payment = class_exists($paymentClass) ? new $paymentClass() : null;
     $requirePayment = $order->Subtotal() > 0 ? true : false;
     if (!($items && $items->Count() > 0)) {
         $form->sessionMessage(_t('OrderForm.NOITEMS', 'Error placing order: You have no items in your cart.'), 'bad');
         return Director::redirectBack();
     }
     if ($requirePayment) {
         if (!($payment && $payment instanceof Payment)) {
             user_error("OrderForm::doProcess(): '{$paymentClass}' is not a valid payment class!", E_USER_ERROR);
         }
     }
     // Ensure existing members don't get their record hijacked (IMPORTANT!)
     if (!$member->checkUniqueFieldValue($data)) {
         $uniqueField = Member::get_unique_identifier_field();
         $uniqueValue = $data[$uniqueField];
         $uniqueError = "Error placing order: The %s \"%d\" is\n\t\t\t\talready taken by another member. If this belongs to you, please\n\t\t\t\tlog in first before placing your order.";
         $form->sessionMessage(_t('EcommerceMemberExtension.ALREADYEXISTS', printf($uniqueError, strtolower($uniqueField), $uniqueValue), PR_MEDIUM, 'Let the user know that member already exists (e.g. %s could be "Email", %d could be "joe@somewhere.com)'), 'bad');
         return Director::redirectBack();
     }
     $form->saveInto($member);
     if (!$member->Password) {
         $member->setField('Password', Member::create_new_password());
     }
     $member->write();
     $form->saveInto($order);
     try {
         $result = $order->process($member->ID);
     } catch (Exception $e) {
         $form->sessionMessage(_t('OrderForm.PROCESSERROR', "An error occurred while placing your order: {$e->getMessage()}.<br>\n\t\t\t\t\tPlease contact the website administrator."), 'bad');
         // Send an email to site admin with $e->getMessage() error
         return Director::redirectBack();
     }
     if ($requirePayment) {
         $form->saveInto($payment);
         $payment->write();
         $result = $payment->processPayment($data, $form);
         if ($result->isSuccess()) {
             $order->sendReceipt();
         }
         // Long payment process. e.g. user goes to external site to pay (PayPal, WorldPay)
         if ($result->isProcessing()) {
             return $result->getValue();
         }
     }
     Director::redirect($order->Link());
 }
 /**
  * Add the member to the order, in case the member is not an admin.
  * @param Order $order
  * @return Boolean
  **/
 public function doStep(Order $order)
 {
     $logClassName = $this->getRelevantLogEntryClassName();
     $obj = $logClassName::get()->filter(array("OrderID" => $order->ID))->first();
     if (!$obj) {
         $files = new ArrayList();
         $items = $order->Items();
         if ($items && $items->count()) {
             foreach ($items as $item) {
                 $buyable = $item->Buyable();
                 if ($buyable) {
                     $method = $this->Config()->get("download_method_in_byable");
                     if ($buyable->hasMethod($method)) {
                         $itemDownloadFiles = $buyable->{$method}();
                         if ($itemDownloadFiles) {
                             if ($itemDownloadFiles instanceof DataList) {
                                 if ($itemDownloadFiles->count()) {
                                     foreach ($itemDownloadFiles as $itemDownloadFile) {
                                         $files->push($itemDownloadFile);
                                     }
                                 }
                             } else {
                                 user_error("{$method} should return a Datalist. Specifically watch for has_one methods as they return a DataObject.", E_USER_NOTICE);
                             }
                         }
                     }
                 }
             }
         }
         if ($files->count()) {
             //additional files ar only added to orders
             //with downloads
             $additionalFiles = $this->AdditionalFiles();
             foreach ($additionalFiles as $additionalFile) {
                 $files->push($additionalFile);
             }
             //create log with information...
             $obj = $logClassName::create();
             $obj->OrderID = $order->ID;
             $obj->AuthorID = $order->MemberID;
             $obj->NumberOfHoursBeforeDownloadGetsDeleted = $this->NumberOfHoursBeforeDownloadGetsDeleted;
             $obj->write();
             $obj->AddFiles($files);
         } else {
             //do nothingh....
         }
     }
     return true;
 }
 /**
  * Calculate the tax component based on tax rates for the items and modifications in the order
  * 
  * @param  Order  $order
  * @return Price  The tax amount for the order
  */
 public function calculate(Order $order)
 {
     $taxAmount = 0;
     $shopConfig = ShopConfig::current_shop_config();
     $items = $order->Items();
     if ($items && $items->exists()) {
         foreach ($items as $item) {
             $taxAmount += $item->Total()->getAmount() * ($item->XeroTaxRate / 100);
         }
     }
     $mods = $order->Modifications();
     if ($mods && $mods->exists()) {
         foreach ($mods as $mod) {
             $taxAmount += $mod->Amount()->getAmount() * ($mod->XeroTaxRate / 100);
         }
     }
     $amount = new Price();
     $amount->setAmount($taxAmount);
     $amount->setCurrency($shopConfig->BaseCurrency);
     $amount->setSymbol($shopConfig->BaseCurrencySymbol);
     return $amount;
 }
 /**
  * @param Order     $order
  * @param null $value
  * @throws ValidationException
  * @throws null
  */
 public function add($order, $value = null)
 {
     if ($order->ShippingRegionCode) {
         if ($orderRegion = Region_Shipping::get()->filter('Code', $order->ShippingRegionCode)->first()) {
             $shippingCost = 0.0;
             /** @var Item $item */
             foreach ($order->Items() as $item) {
                 $productRegion = $item->Product()->Shippables()->filter('RegionID', $orderRegion->ID)->first();
                 if ($productRegion) {
                     $shippingCost = Zend_Locale_Math::Add($shippingCost, Zend_Locale_Math::Mul($productRegion->Price, $item->Quantity));
                 }
             }
             //Generate the Modification now that we have picked the correct rate
             $mod = new StreakRegionalShipping_Modification();
             $mod->OrderID = $order->ID;
             $mod->RegionID = $orderRegion->ID;
             $mod->Price = $shippingCost;
             $mod->Description = "Shipping to {$orderRegion->Title}";
             $mod->Value = $shippingCost;
             $mod->write();
         }
     }
 }
 /**
  * Takes an order from being a cart to awaiting payment.
  *
  * @param Member $member - assign a member to the order
  *
  * @return boolean - success/failure
  */
 public function placeOrder()
 {
     if (!$this->order) {
         $this->error(_t("OrderProcessor.NoOrderStarted", "A new order has not yet been started."));
         return false;
     }
     if (!$this->canPlace($this->order)) {
         //final cart validation
         return false;
     }
     if ($this->order->Locale) {
         ShopTools::install_locale($this->order->Locale);
     }
     // recalculate order to be sure we have the correct total
     $this->order->calculate();
     if (ShopTools::DBConn()->supportsTransactions()) {
         ShopTools::DBConn()->transactionStart();
     }
     //update status
     if ($this->order->TotalOutstanding(false)) {
         $this->order->Status = 'Unpaid';
     } else {
         $this->order->Status = 'Paid';
     }
     if (!$this->order->Placed) {
         $this->order->Placed = SS_Datetime::now()->Rfc2822();
         //record placed order datetime
         if ($request = Controller::curr()->getRequest()) {
             $this->order->IPAddress = $request->getIP();
             //record client IP
         }
     }
     // Add an error handler that throws an exception upon error, so that we can catch errors as exceptions
     // in the following block.
     set_error_handler(function ($severity, $message, $file, $line) {
         throw new ErrorException($message, 0, $severity, $file, $line);
     }, E_ALL & ~(E_STRICT | E_NOTICE));
     try {
         //re-write all attributes and modifiers to make sure they are up-to-date before they can't be changed again
         $items = $this->order->Items();
         if ($items->exists()) {
             foreach ($items as $item) {
                 $item->onPlacement();
                 $item->write();
             }
         }
         $modifiers = $this->order->Modifiers();
         if ($modifiers->exists()) {
             foreach ($modifiers as $modifier) {
                 $modifier->write();
             }
         }
         //add member to order & customers group
         if ($member = Member::currentUser()) {
             if (!$this->order->MemberID) {
                 $this->order->MemberID = $member->ID;
             }
             $cgroup = ShopConfig::current()->CustomerGroup();
             if ($cgroup->exists()) {
                 $member->Groups()->add($cgroup);
             }
         }
         //allow decorators to do stuff when order is saved.
         $this->order->extend('onPlaceOrder');
         $this->order->write();
     } catch (Exception $ex) {
         // Rollback the transaction if an error occurred
         if (ShopTools::DBConn()->supportsTransactions()) {
             ShopTools::DBConn()->transactionRollback();
         }
         $this->error($ex->getMessage());
         return false;
     } finally {
         // restore the error handler, no matter what
         restore_error_handler();
     }
     // Everything went through fine, complete the transaction
     if (ShopTools::DBConn()->supportsTransactions()) {
         ShopTools::DBConn()->transactionEnd();
     }
     //remove from session
     $cart = ShoppingCart::curr();
     if ($cart && $cart->ID == $this->order->ID) {
         // clear the cart, but don't write the order in the process (order is finalized and should NOT be overwritten)
         ShoppingCart::singleton()->clear(false);
     }
     //send confirmation if configured and receipt hasn't been sent
     if (self::config()->send_confirmation && !$this->order->ReceiptSent) {
         $this->notifier->sendConfirmation();
     }
     //notify admin, if configured
     if (self::config()->send_admin_notification) {
         $this->notifier->sendAdminNotification();
     }
     // Save order reference to session
     OrderManipulation::add_session_order($this->order);
     return true;
     //report success
 }
 /**
  * Takes an order from being a cart to awaiting payment.
  *
  * @param Member $member - assign a member to the order
  *
  * @return boolean - success/failure
  */
 public function placeOrder()
 {
     if (!$this->order) {
         $this->error(_t("OrderProcessor.NULL", "A new order has not yet been started."));
         return false;
     }
     if (!$this->canPlace($this->order)) {
         //final cart validation
         return false;
     }
     if ($this->order->Locale) {
         ShopTools::install_locale($this->order->Locale);
     }
     //remove from session
     $cart = ShoppingCart::curr();
     if ($cart && $cart->ID == $this->order->ID) {
         ShoppingCart::singleton()->clear();
     }
     //update status
     if ($this->order->TotalOutstanding()) {
         $this->order->Status = 'Unpaid';
     } else {
         $this->order->Status = 'Paid';
     }
     if (!$this->order->Placed) {
         $this->order->Placed = SS_Datetime::now()->Rfc2822();
         //record placed order datetime
         if ($request = Controller::curr()->getRequest()) {
             $this->order->IPAddress = $request->getIP();
             //record client IP
         }
     }
     //re-write all attributes and modifiers to make sure they are up-to-date before they can't be changed again
     $items = $this->order->Items();
     if ($items->exists()) {
         foreach ($items as $item) {
             $item->onPlacement();
             $item->write();
         }
     }
     $modifiers = $this->order->Modifiers();
     if ($modifiers->exists()) {
         foreach ($modifiers as $modifier) {
             $modifier->write();
         }
     }
     //add member to order & customers group
     if ($member = Member::currentUser()) {
         if (!$this->order->MemberID) {
             $this->order->MemberID = $member->ID;
         }
         $cgroup = ShopConfig::current()->CustomerGroup();
         if ($cgroup->exists()) {
             $member->Groups()->add($cgroup);
         }
     }
     //allow decorators to do stuff when order is saved.
     $this->order->extend('onPlaceOrder');
     $this->order->write();
     //send confirmation if configured and receipt hasn't been sent
     if (self::config()->send_confirmation && !$this->order->ReceiptSent) {
         $this->notifier->sendConfirmation();
     }
     //notify admin, if configured
     if (self::config()->send_admin_notification) {
         $this->notifier->sendAdminNotification();
     }
     // Save order reference to session
     OrderManipulation::add_session_order($this->order);
     return true;
     //report success
 }
 /**
  * Action that gets called before we interface with our payment
  * method.
  *
  * This action is responsible for setting up an order and
  * saving it into the database (as well as a session) and also then
  * generating an order summary before the user performs any final
  * actions needed.
  *
  * This action is then mapped directly to the index action of the
  * Handler for the payment method that was selected by the user
  * in the "Postage and Payment" form.
  *
  */
 public function index()
 {
     $cart = ShoppingCart::get();
     // If shopping cart doesn't exist, redirect to base
     if (!$cart->getItems()->exists() || $this->getPaymentHandler() === null) {
         return $this->redirect(Director::BaseURL());
     }
     // Get billing and delivery details and merge into an array
     $billing_data = Session::get("Commerce.BillingDetailsForm.data");
     $delivery_data = Session::get("Commerce.DeliveryDetailsForm.data");
     $postage = PostageArea::get()->byID(Session::get('Commerce.PostageID'));
     if (!$postage || !$billing_data || !$delivery_data) {
         return $this->redirect(Checkout_Controller::create()->Link());
     }
     // Work out if an order prefix string has been set in siteconfig
     $config = SiteConfig::current_site_config();
     $order_prefix = $config->OrderPrefix ? $config->OrderPrefix . '-' : '';
     // Merge billand and delivery data into an array
     $data = array_merge((array) $billing_data, (array) $delivery_data);
     // Set discount info
     $data['DiscountAmount'] = $cart->DiscountAmount();
     // Get postage data
     $data['PostageType'] = $postage->Title;
     $data['PostageCost'] = $postage->Cost;
     $data['PostageTax'] = $config->TaxRate > 0 && $postage->Cost > 0 ? (double) $postage->Cost / 100 * $config->TaxRate : 0;
     // Set status
     $data['Status'] = 'incomplete';
     // Setup an order based on the data from the shopping cart and load data
     $order = new Order();
     $order->update($data);
     // If user logged in, track it against an order
     if (Member::currentUserID()) {
         $order->CustomerID = Member::currentUserID();
     }
     // Write so we can setup our foreign keys
     $order->write();
     // Loop through each session cart item and add that item to the order
     foreach ($cart->getItems() as $cart_item) {
         $order_item = new OrderItem();
         $order_item->Title = $cart_item->Title;
         $order_item->SKU = $cart_item->SKU;
         $order_item->Price = $cart_item->Price;
         $order_item->Tax = $cart_item->Tax;
         $order_item->Customisation = serialize($cart_item->Customised);
         $order_item->Quantity = $cart_item->Quantity;
         $order_item->write();
         $order->Items()->add($order_item);
     }
     $order->write();
     // Add order to session so our payment handler can process it
     Session::set("Commerce.Order", $order);
     $this->payment_handler->setOrder($order);
     // Get gateway data
     $return = $this->payment_handler->index();
     return $this->customise($return)->renderWith(array("Payment", "Commerce", "Page"));
 }
 /**
  * Add item fields for each item in the current order.
  * 
  * @param Array $fields Array of fields
  * @param OrderFormValidator $validator Checkout form validator
  * @param Order $order The current order
  */
 private function addItemFields(&$fields, &$validator, $order)
 {
     $items = $order->Items();
     if ($items) {
         foreach ($items as $item) {
             $fields['Items'][] = new OrderItemField($item);
         }
     }
 }
Esempio n. 14
0
 function old_testProductOrderItems()
 {
     $product1a = $this->objFromFixture('Product', 'p1a');
     $product1b = $this->objFromFixture('Product', 'p1b');
     $order = new Order();
     $order->Currency = 'USD';
     $order->write();
     $item1a = new ProductOrderItem(null, null, $product1a, 2);
     $item1a->write();
     $order->Items()->add($item1a);
     $item1b = new ProductOrderItem(null, null, $product1b, 1);
     $item1b->write();
     $order->Items()->add($item1b);
     $item1c = new ProductOrderItem(null, null, $product1a, 1);
     $item1c->write();
     $order->Items()->add($item1c);
     $items = $order->ProductOrderItems();
     $testString = 'ProductList: ';
     foreach ($items as $item) {
         $testString .= $item->Product()->Title . ";";
     }
     $this->assertEquals($testString, "ProductList: Product 1a;Product 1b;Product 1a;");
 }
 /**
  * Create a RepeatOrder from a regular Order and its Order Items
  * @param Order $Order
  * @return RepeatOrder
  */
 public static function create_repeat_order_from_order(Order $Order)
 {
     $repeatOrder = new RepeatOrder();
     $repeatOrder->Status = 'Pending';
     $repeatOrder->MemberID = $Order->MemberID;
     $repeatOrder->write();
     $orderItems = $Order->Items();
     if ($orderItems) {
         foreach ($orderItems as $orderItem) {
             $buyable = $orderItem->Buyable();
             if ($buyable && $buyable instanceof Product) {
                 $repeatOrder_orderItem = new RepeatOrder_OrderItem();
                 $repeatOrder_orderItem->OrderID = $repeatOrder->ID;
                 $repeatOrder_orderItem->ProductID = $orderItem->BuyableID;
                 $repeatOrder_orderItem->Quantity = $orderItem->Quantity;
                 $repeatOrder_orderItem->write();
             }
         }
     }
     $repeatOrder->write();
     return $repeatOrder;
 }