/**
  * Validate this form field, make sure the {@link Item} exists, is in the current 
  * {@link Order} and the item is valid for adding to the cart.
  * 
  * @see FormField::validate()
  * @return Boolean
  */
 function validate($validator)
 {
     $valid = true;
     $item = $this->Item();
     $currentOrder = CartControllerExtension::get_current_order();
     $items = $currentOrder->Items();
     //Check that item exists and is in the current order
     if (!$item || !$item->exists() || !$items->find('ID', $item->ID)) {
         $errorMessage = _t('Form.ITEM_IS_NOT_IN_ORDER', 'This product is not in the Order.');
         if ($msg = $this->getCustomValidationMessage()) {
             $errorMessage = $msg;
         }
         $validator->validationError($this->Name(), $errorMessage, "error");
         $valid = false;
     } else {
         if ($item) {
             $validation = $item->validateForCart();
             if (!$validation->valid()) {
                 $errorMessage = $validation->message();
                 if ($msg = $this->getCustomValidationMessage()) {
                     $errorMessage = $msg;
                 }
                 $validator->validationError($this->Name(), $errorMessage, "error");
                 $valid = false;
             }
         }
     }
     return $valid;
 }
 /**
  * Check that current order is valid
  *
  * @param Array $data Submitted data
  * @return Boolean Returns TRUE if the submitted data is valid, otherwise FALSE.
  */
 function php($data)
 {
     //TODO move the form error messages to CheckoutForm::validate()
     $valid = parent::php($data);
     $fields = $this->form->Fields();
     //Check the order is valid
     $currentOrder = CartControllerExtension::get_current_order();
     if (!$currentOrder) {
         $this->form->sessionMessage(_t('Form.ORDER_IS_NOT_VALID', 'Your cart seems to be empty, please add an item from the shop'), 'bad');
         //Have to set an error for Form::validate()
         $this->errors[] = true;
         $valid = false;
     } else {
         $validation = $currentOrder->validateForCart();
         if (!$validation->valid()) {
             $this->form->sessionMessage(_t('Form.ORDER_IS_NOT_VALID', 'There seems to be a problem with your order. ' . $validation->message()), 'bad');
             //Have to set an error for Form::validate()
             $this->errors[] = true;
             $valid = false;
         }
     }
     return $valid;
 }
 /**
  * Try to checkout with valid flat fee shipping option
  */
 function testCheckoutFlatFeeShipping()
 {
     $productA = $this->objFromFixture('Product', 'productA');
     $taxRate = $this->objFromFixture('FlatFeeTaxRate', 'gstNewZealand');
     $countryNZ = $this->objFromFixture('Country_Shipping', 'newZealand');
     $buyer = $this->objFromFixture('Customer', 'buyer');
     $checkoutPage = DataObject::get_one('CheckoutPage');
     $accountPage = DataObject::get_one('AccountPage');
     $this->loginAs('admin');
     $productA->doPublish();
     $checkoutPage->doPublish();
     $accountPage->doPublish();
     $this->logOut();
     $this->assertTrue($productA->isPublished());
     $this->loginAs($buyer);
     $orders = $buyer->Orders();
     $this->assertEquals(1, $orders->Count());
     $this->get(Director::makeRelative($productA->Link()));
     $this->submitForm('AddToCartForm_AddToCartForm', null, array('Quantity' => 1));
     $order = CartControllerExtension::get_current_order();
     $items = $order->Items();
     $this->assertEquals(1, $items->Count());
     $this->assertEquals($productA->ID, $items->First()->Object()->ID);
     $this->get(Director::makeRelative($checkoutPage->Link()));
     //Set a modification for this Order via updateOrderFormCart
     $data = $this->getFormDataNested('CheckoutForm_OrderForm');
     $this->post(Director::makeRelative($checkoutPage->Link() . 'updateOrderFormCart'), $data);
     $this->get(Director::makeRelative($checkoutPage->Link()));
     $this->submitForm('CheckoutForm_OrderForm', null, array('Shipping[Country]' => $countryNZ->ID, 'Modifiers[FlatFeeTax]' => $taxRate->ID));
     $orders = $buyer->Orders();
     $orders->sort('ID', "ASC");
     $this->assertEquals(2, $orders->Count());
     $order = $orders->Last();
     $this->assertEquals(15, $taxRate->Rate);
     $realTotal = $order->SubTotal->getAmount() * 1.15;
     $this->assertEquals($orders->Last()->Total->getAmount(), $realTotal);
 }
 /**
  * Add a product variation to the cart, change the cart so that it is out of date
  * then delete it
  */
 function testRemoveAbandonedCartsWithProductVariationsTask()
 {
     $teeshirtA = $this->objFromFixture('Product', 'teeshirtA');
     $this->logInAs('admin');
     $teeshirtA->doPublish();
     $this->logOut();
     $teeshirtAVariation = $this->objFromFixture('Variation', 'teeshirtExtraLargePurpleCotton');
     $this->assertEquals('Enabled', $teeshirtAVariation->Status);
     $this->assertEquals(5, $teeshirtAVariation->StockLevel()->Level);
     //Add variation to the cart
     $this->get(Director::makeRelative($teeshirtA->Link()));
     $data = array('Quantity' => 1);
     foreach ($teeshirtAVariation->Options() as $option) {
         $data["Options[{$option->AttributeID}]"] = $option->ID;
     }
     $this->submitForm('AddToCartForm_AddToCartForm', null, $data);
     $teeshirtAVariation = $this->objFromFixture('Variation', 'teeshirtExtraLargePurpleCotton');
     $this->assertEquals(4, $teeshirtAVariation->StockLevel()->Level);
     $order = CartControllerExtension::get_current_order();
     $this->logInAs('admin');
     $order->LastActive = '2011-12-22 17:02:49';
     $order->Status = 'Cart';
     $order->write();
     $this->logOut();
     Order::delete_abandoned();
     DataObject::flush_and_destroy_cache();
     $teeshirtAVariation = $this->objFromFixture('Variation', 'teeshirtExtraLargePurpleCotton');
     $this->assertEquals(5, $teeshirtAVariation->StockLevel()->Level);
 }
 /**
  * Update the order form cart, called via AJAX with current order form data.
  * Renders the cart and sends that back for displaying on the order form page.
  * 
  * @param SS_HTTPRequest $data Form data sent via AJAX POST.
  * @return String Rendered cart for the order form, template include 'CheckoutFormOrder'.
  */
 function updateOrderFormCart(SS_HTTPRequest $data)
 {
     if ($data->isPOST()) {
         $fields = array();
         $validator = new OrderFormValidator();
         $member = Customer::currentUser() ? Customer::currentUser() : singleton('Customer');
         $order = CartControllerExtension::get_current_order();
         //Update the Order
         $order->addAddressesAtCheckout($data->postVars());
         $order->addModifiersAtCheckout($data->postVars());
         //TODO update personal details, notes and payment type?
         //Create the part of the form that displays the Order
         $this->addItemFields($fields, $validator, $order);
         $this->addModifierFields($fields, $validator, $order);
         //This is going to go through and add modifiers based on current Form DATA
         //TODO This should be constructed for non-dropdown fields as well
         //Update modifier form fields so that the dropdown values are correct
         $newModifierData = array();
         $subTotalModifiers = isset($fields['SubTotalModifiers']) ? $fields['SubTotalModifiers'] : array();
         $totalModifiers = isset($fields['Modifiers']) ? $fields['Modifiers'] : array();
         $modifierFields = array_merge($subTotalModifiers, $totalModifiers);
         foreach ($modifierFields as $field) {
             if (method_exists($field, 'updateValue')) {
                 $field->updateValue($order);
             }
             $modifierClassName = get_class($field->getModifier());
             $newModifierData['Modifiers'][$modifierClassName] = $field->Value();
         }
         //Add modifiers to the order again so that the new values are used
         $order->addModifiersAtCheckout($newModifierData);
         $actions = new FieldSet(new FormAction('ProcessOrder', _t('CheckoutPage.PROCEED_TO_PAY', "Proceed to pay")));
         $form = new CheckoutForm($this, 'OrderForm', $fields, $actions, $validator, $order);
         $form->disableSecurityToken();
         $form->validate();
         return $form->renderWith('CheckoutFormOrder');
     }
 }
 /**
  * Try checkout with invalid flat fee shipping option
  */
 function testCheckoutInvalidFlatFeeShipping()
 {
     $productA = $this->objFromFixture('Product', 'productA');
     $shippingMainCentreAustralia = $this->objFromFixture('FlatFeeShippingRate', 'MainCentreAustralia');
     $shippingAmount = $shippingMainCentreAustralia->Amount->getAmount();
     $checkoutPage = DataObject::get_one('CheckoutPage');
     $accountPage = DataObject::get_one('AccountPage');
     $this->loginAs('admin');
     $productA->doPublish();
     $checkoutPage->doPublish();
     $accountPage->doPublish();
     $this->logOut();
     $this->assertTrue($productA->isPublished());
     $this->loginAs($this->objFromFixture('Customer', 'buyer'));
     $buyer = $this->objFromFixture('Customer', 'buyer');
     $orders = $buyer->Orders();
     $this->assertEquals(1, $orders->Count());
     $this->get(Director::makeRelative($productA->Link()));
     $this->submitForm('AddToCartForm_AddToCartForm', null, array('Quantity' => 1));
     $order = CartControllerExtension::get_current_order();
     $items = $order->Items();
     $this->assertEquals(1, $items->Count());
     $this->assertEquals($productA->ID, $items->First()->Object()->ID);
     $checkoutPage = DataObject::get_one('CheckoutPage');
     $this->get(Director::makeRelative($checkoutPage->Link()));
     $this->submitForm('CheckoutForm_OrderForm', null, array('Shipping[Country]' => 'NZ', 'Modifiers[FlatFeeShipping]' => $shippingMainCentreAustralia->ID));
     $orders = $buyer->Orders();
     $orders->sort('ID', "ASC");
     $this->assertEquals(1, $orders->Count());
     $realTotal = $productA->Amount->getAmount();
     $this->assertEquals($orders->Last()->Total->getAmount(), $realTotal);
     $this->assertEquals(0, $orders->Last()->Modifications()->Count());
 }
 /**
  * Try checking out an order without specifying a payment gateway
  */
 function testCheckoutWithoutPaymentGateway()
 {
     $productA = $this->objFromFixture('Product', 'productA');
     $this->loginAs('admin');
     $productA->doPublish();
     $this->logOut();
     $buyer = $this->objFromFixture('Customer', 'buyer');
     $this->assertEquals(1, $buyer->Orders()->Count());
     $this->loginAs($this->objFromFixture('Customer', 'buyer'));
     $productALink = $productA->Link();
     $this->get(Director::makeRelative($productALink));
     $this->submitForm('AddToCartForm_AddToCartForm', null, array('Quantity' => 1));
     $order = CartControllerExtension::get_current_order();
     $items = $order->Items();
     $this->assertEquals(1, $items->Count());
     $checkoutPage = DataObject::get_one('CheckoutPage');
     $this->get(Director::makeRelative($checkoutPage->Link()));
     //Submit the form without restrictions on what can be POST'd
     $data = $this->getFormData('CheckoutForm_OrderForm');
     $data['PaymentMethod'] = '';
     $this->post(Director::absoluteURL('/checkout/OrderForm'), $data);
     $this->assertEquals(1, $buyer->Orders()->Count());
 }
 /**
  * Add an item to the current cart ({@link Order}) for a given {@link Product}.
  * 
  * @param Array $data
  * @param Form $form
  */
 function add(array $data, Form $form)
 {
     CartControllerExtension::get_current_order()->addItem($this->getProduct(), $this->getQuantity(), $this->getProductOptions());
     //Show feedback if redirecting back to the Product page
     if (!$this->getRequest()->requestVar('Redirect')) {
         $cartPage = DataObject::get_one('CartPage');
         $message = $cartPage ? 'The product was added to <a href="' . $cartPage->Link() . '">your cart</a>.' : "The product was added to your cart.";
         $form->sessionMessage($message, 'good');
     }
     $this->goToNextPage();
 }
 /**
  * Validate this field, check that the current {@link Item} is in the current 
  * {@Link Order} and is valid for adding to the cart.
  * 
  * @see FormField::validate()
  * @return Boolean
  */
 function validate($validator)
 {
     $valid = true;
     $item = $this->Item();
     $currentOrder = CartControllerExtension::get_current_order();
     $items = $currentOrder->Items();
     $quantity = $this->Value();
     $removingItem = false;
     if ($quantity == 0) {
         $removingItem = true;
     }
     //Check that item exists and is in the current order
     if (!$item || !$item->exists() || !$items->find('ID', $item->ID)) {
         $errorMessage = _t('Form.ITEM_IS_NOT_IN_ORDER', 'This product is not in the Cart.');
         if ($msg = $this->getCustomValidationMessage()) {
             $errorMessage = $msg;
         }
         $validator->validationError($this->Name(), $errorMessage, "error");
         $valid = false;
     } else {
         if ($item && !$removingItem) {
             //If quantity is zero the item is removed already @see CartPage::saveCart()
             if (!$quantity || !is_numeric($quantity) || $quantity <= 0) {
                 $errorMessage = _t('Form.ITEM_QUANTITY_INCORRECT', 'The quantity must be at least one (1).');
                 if ($msg = $this->getCustomValidationMessage()) {
                     $errorMessage = $msg;
                 }
                 $validator->validationError($this->Name(), $errorMessage, "error");
                 $valid = false;
             }
             $validation = $item->validateForCart();
             if (!$validation->valid()) {
                 $errorMessage = $validation->message();
                 if ($msg = $this->getCustomValidationMessage()) {
                     $errorMessage = $msg;
                 }
                 $validator->validationError($this->Name(), $errorMessage, "error");
                 $valid = false;
             }
         }
     }
     //Check that quantity for an item is not being pushed beyond available stock levels for a product
     $quantityChange = $quantity - $item->Quantity;
     if ($item) {
         $variation = $item->Variation();
         $product = $item->Product();
         $stockLevel = 0;
         if ($variation) {
             $stockLevel = $variation->StockLevel()->Level;
         } else {
             $stockLevel = $product->StockLevel()->Level;
         }
         if ($quantityChange > 0 && $quantityChange > $stockLevel && $stockLevel > -1) {
             //If the change in quantity is greater than the remaining stock level then there is a problem
             $errorMessage = _t('Form.ITEM_QUANTITY_INCORRECT', 'Quantity is greater than remaining stock.');
             if ($msg = $this->getCustomValidationMessage()) {
                 $errorMessage = $msg;
             }
             $validator->validationError($this->Name(), $errorMessage, "error");
             $valid = false;
         }
     }
     return $valid;
 }
 /**
  * Save the cart, update the order item quantities and the order total.
  * 
  * @param Array $data Data submitted from the form via POST
  * @param Form $form Form that data was submitted from
  */
 private function saveCart(array $data, Form $form)
 {
     $currentOrder = CartControllerExtension::get_current_order();
     $quantities = isset($data['Quantity']) ? $data['Quantity'] : null;
     if ($quantities) {
         foreach ($quantities as $itemID => $quantity) {
             if ($item = $currentOrder->Items()->find('ID', $itemID)) {
                 if ($quantity == 0) {
                     $item->delete();
                 } else {
                     $item->Quantity = $quantity;
                     $item->write();
                 }
             }
         }
     }
     $currentOrder->updateTotal();
 }
예제 #11
0
 /**
  * Add addresses to this Order at the checkout.
  * 
  * @param Array $data
  */
 function addAddressesAtCheckout(array $data)
 {
     $member = Customer::currentUser() ? Customer::currentUser() : singleton('Customer');
     $order = CartControllerExtension::get_current_order();
     $billingCountries = Country::billing_countries();
     $shippingCountries = Country::shipping_countries();
     $shippingRegions = Region::shipping_regions();
     //If there is a current billing and shipping address, update them, otherwise create new ones
     $existingBillingAddress = $this->BillingAddress();
     $existingShippingAddress = $this->ShippingAddress();
     if ($existingBillingAddress && $existingBillingAddress->exists()) {
         $newData = array();
         if (isset($data['Billing']) && is_array($data['Billing'])) {
             foreach ($data['Billing'] as $fieldName => $value) {
                 $newData[$fieldName] = $value;
             }
         }
         $newData['CountryID'] = $data['Billing']['Country'];
         $newData['CountryName'] = in_array($newData['CountryID'], array_keys($billingCountries)) ? $billingCountries[$newData['CountryID']] : null;
         if ($member->ID) {
             $newData['MemberID'] = $member->ID;
         }
         $existingBillingAddress->update($newData);
         $existingBillingAddress->write();
     } else {
         $billingAddress = new Address();
         $billingAddress->OrderID = $order->ID;
         if ($member->ID) {
             $billingAddress->MemberID = $member->ID;
         }
         $billingAddress->FirstName = $data['Billing']['FirstName'];
         $billingAddress->Surname = $data['Billing']['Surname'];
         $billingAddress->Company = $data['Billing']['Company'];
         $billingAddress->Address = $data['Billing']['Address'];
         $billingAddress->AddressLine2 = $data['Billing']['AddressLine2'];
         $billingAddress->City = $data['Billing']['City'];
         $billingAddress->PostalCode = $data['Billing']['PostalCode'];
         $billingAddress->State = $data['Billing']['State'];
         $billingAddress->CountryID = $data['Billing']['Country'];
         $billingAddress->CountryName = in_array($data['Billing']['Country'], array_keys($billingCountries)) ? $billingCountries[$data['Billing']['Country']] : null;
         $billingAddress->Type = 'Billing';
         $billingAddress->write();
     }
     if ($existingShippingAddress && $existingShippingAddress->exists()) {
         $newData = array();
         if (isset($data['Shipping']) && is_array($data['Shipping'])) {
             foreach ($data['Shipping'] as $fieldName => $value) {
                 $newData[$fieldName] = $value;
             }
         }
         $newData['CountryID'] = $data['Shipping']['Country'];
         $newData['CountryName'] = in_array($newData['CountryID'], array_keys($shippingCountries)) ? $shippingCountries[$newData['CountryID']] : null;
         if (isset($newData['Region']) && isset($shippingRegions[$newData['Country']])) {
             if (in_array($newData['Region'], array_keys($shippingRegions[$newData['Country']]))) {
                 $newData['RegionName'] = $shippingRegions[$newData['Country']][$newData['Region']];
             }
         } else {
             $newData['RegionName'] = null;
         }
         if ($member->ID) {
             $newData['MemberID'] = $member->ID;
         }
         $existingShippingAddress->update($newData);
         $existingShippingAddress->write();
     } else {
         $shippingAddress = new Address();
         $shippingAddress->OrderID = $order->ID;
         if ($member->ID) {
             $shippingAddress->MemberID = $member->ID;
         }
         $shippingAddress->FirstName = $data['Shipping']['FirstName'];
         $shippingAddress->Surname = $data['Shipping']['Surname'];
         $shippingAddress->Company = $data['Shipping']['Company'];
         $shippingAddress->Address = $data['Shipping']['Address'];
         $shippingAddress->AddressLine2 = $data['Shipping']['AddressLine2'];
         $shippingAddress->City = $data['Shipping']['City'];
         $shippingAddress->PostalCode = $data['Shipping']['PostalCode'];
         $shippingAddress->State = $data['Shipping']['State'];
         $shippingAddress->CountryID = $data['Shipping']['Country'];
         $shippingAddress->Region = isset($data['Shipping']['Region']) ? $data['Shipping']['Region'] : null;
         $shippingAddress->CountryName = in_array($data['Shipping']['Country'], array_keys($shippingCountries)) ? $shippingCountries[$data['Shipping']['Country']] : null;
         $shippingAddress->RegionName = isset($data['Shipping']['Region']) && isset($shippingRegions[$data['Shipping']['Country']]) && in_array($data['Shipping']['Region'], array_keys($shippingRegions[$data['Shipping']['Country']])) ? $shippingRegions[$data['Shipping']['Country']][$data['Shipping']['Region']] : null;
         $shippingAddress->Type = 'Shipping';
         $shippingAddress->write();
     }
 }
 /**
  * Adding non published product to a cart should fail
  */
 function testAddNonPublishedProductToCart()
 {
     $productA = $this->objFromFixture('Product', 'productA');
     $this->assertEquals(false, $productA->isPublished());
     $productALink = $productA->Link();
     $this->get(Director::makeRelative($productALink));
     $message = null;
     try {
         $this->submitForm('AddToCartForm_AddToCartForm', null, array('Quantity' => 1));
     } catch (Exception $e) {
         $message = $e->getMessage();
     }
     $this->assertStringEndsWith('Object not written.', $message);
     $order = CartControllerExtension::get_current_order();
     $items = $order->Items();
     $this->assertEquals(0, $items->Count());
 }