testERP5Commerce.py 36.4 KB
Newer Older
1
# encoding: utf-8
Ivan Tyagov's avatar
Ivan Tyagov committed
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
##############################################################################
#
# Copyright (c) 2005 Nexedi SARL and Contributors. All Rights Reserved.
#                     Ivan Tyagov <ivan@nexedi.com>
#
# WARNING: This program as such is intended to be used by professional
# programmers who take the whole responsability of assessing all potential
# consequences resulting from its eventual inadequacies and bugs
# End users who are looking for a ready-to-use solution with commercial
# garantees and support are strongly adviced to contract a Free Software
# Service Company
#
# This program is Free Software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
#
##############################################################################

30 31
import os
import string
32
import transaction
33
import urllib
34 35 36

from Products.ERP5Type.tests.ERP5TypeTestCase import ERP5TypeTestCase
from Products.ERP5Type.tests.utils import FileUpload
Ivan Tyagov's avatar
Ivan Tyagov committed
37 38

SESSION_ID = "12345678"
39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60
LANGUAGE_LIST = ('en', 'fr', 'de', 'bg',)
SIMULATE_PAYPAL_SERVER = """
# this script simulate the reponse of paypal
if not 'METHOD' in parameter_dict:
  return {'ACK':'Failure'}

# Step 1 : get a token
if parameter_dict['METHOD'] == 'SetExpressCheckout':
  return {'ACK':'Success',
          'TOKEN':'FOOTOKEN'}

# Step 2 : check if token is good
if parameter_dict['METHOD'] == 'GetExpressCheckoutDetails':
  return {'ACK':'Success',
          'PAYERID':'THEPAYERID'}

# Step 3 : pay
if parameter_dict['METHOD'] == 'DoExpressCheckoutPayment':
  return {'ACK':'Success',
          'PAYERID':'THEPAYERID'}
return {'ACK':'Failure'}
"""
Ivan Tyagov's avatar
Ivan Tyagov committed
61

Lucas Carvalho's avatar
Lucas Carvalho committed
62

Ivan Tyagov's avatar
Ivan Tyagov committed
63
class TestCommerce(ERP5TypeTestCase):
64
  """
Lucas Carvalho's avatar
Lucas Carvalho committed
65 66 67
  Todo:
  > Change name of all script, most of them should not be called on a
    SaleOrder.
68 69 70 71 72 73 74 75 76 77 78 79 80 81
  > Test SaleOrder_getShoppingCartItemList With include_shipping=True
  > implement Person_getApplicableDiscountList (actually just return None)
  > implement Person_getApplicableTaxList (actually always return a tax of 20%)
  > SaleOrder_externalPaymentHandler is totally empty
  > SaleOrder_finalizeShopping doesnt check if the payment is successful or not
  > Fix proxy for SaleOrder_finalizeShopping anonym and normal user cant use it
  > SaleOrder_getAvailableShippingResourceList have hardcoded
  > SaleOrder_isConsistent the usage must be more generic or rename it
  > SaleOrder_isShippingRequired this script just return 1 ...

  Not tested :
  Person_getApplicableDiscountList
  SaleOrder_externalPaymentHandler
  SaleOrder_isShippingRequired
82 83 84 85 86 87 88 89 90 91 92 93
  WebSection_checkPaypalIdentification
  WebSection_checkoutProcedure
  WebSection_doPaypalPayment
  WebSection_viewCurrentPersonAsWeb
  WebSite_doExpressCheckoutPayment
  WebSite_getExpressCheckoutDetails
  WebSite_getNewPaypalToken
  WebSite_getPaypalOrderParameterDict
  WebSite_getPaypalSecurityParameterDict
  WebSite_getPaypalUrl
  WebSite_setupECommerceWebSite
  Product_getRelatedDescription
94
  Person_editPersonalInformation
95
  """
Ivan Tyagov's avatar
Ivan Tyagov committed
96 97 98

  def getTitle(self):
    return "E-Commerce System"
99 100 101 102 103

  def getBusinessTemplateList(self):
    """
      Return the list of required business templates.
    """
Lucas Carvalho's avatar
Lucas Carvalho committed
104 105 106 107
    return ('erp5_base',
            'erp5_web',
            'erp5_trade',
            'erp5_pdm',
108 109
            'erp5_commerce',)

Ivan Tyagov's avatar
Ivan Tyagov committed
110
  def afterSetUp(self):
111 112 113 114 115 116
    uf = self.getPortal().acl_users
    uf._doAddUser('ivan', '', ['Manager'], [])
    uf._doAddUser('customer', '', ['Auditor', 'Author'], [])

    self.login('ivan')

117 118 119
    product_module = self.portal.product_module
    currency_module = self.portal.currency_module
    sale_order_module = self.portal.sale_order_module
Lucas Carvalho's avatar
Lucas Carvalho committed
120
    currency_module.manage_permission('Access contents information',
121
                                     roles=['Anonymous'], acquire=0)
Lucas Carvalho's avatar
Lucas Carvalho committed
122
    product_module.manage_permission('Access contents information',
123
                                     roles=['Anonymous'], acquire=0)
Lucas Carvalho's avatar
Lucas Carvalho committed
124
    sale_order_module.manage_permission('Access contents information',
125 126
                                     roles=['Anonymous'], acquire=0)

Ivan Tyagov's avatar
Ivan Tyagov committed
127
    # create default currency (EUR)
Lucas Carvalho's avatar
Lucas Carvalho committed
128
    currency = currency_module.newContent(portal_type='Currency',
129
                                          id='EUR')
Ivan Tyagov's avatar
Ivan Tyagov committed
130 131
    currency.setTitle('EUR')
    currency.setReference('EUR')
132
    currency.setShortTitle('€')
Ivan Tyagov's avatar
Ivan Tyagov committed
133
    currency.setBaseUnitQuantity(0.01)
134 135
    currency.validate()
    currency.publish()
136

Ivan Tyagov's avatar
Ivan Tyagov committed
137
    # create product, set price & currency
138
    product = product_module.newContent(portal_type='Product', id='1')
Ivan Tyagov's avatar
Ivan Tyagov committed
139 140
    product.setSupplyLinePriceCurrency(currency.getRelativeUrl())
    product.setBasePrice(10.0)
141 142
    product.validate()
    product.publish()
143

Ivan Tyagov's avatar
Ivan Tyagov committed
144
    # create second product, set price & currency
145
    product = product_module.newContent(portal_type='Product', id='2')
Ivan Tyagov's avatar
Ivan Tyagov committed
146 147
    product.setSupplyLinePriceCurrency(currency.getRelativeUrl())
    product.setBasePrice(20.0)
148 149 150
    product.validate()
    product.publish()

Ivan Tyagov's avatar
Ivan Tyagov committed
151
    # create shipping which is actually a product
Lucas Carvalho's avatar
Lucas Carvalho committed
152
    shipping = product_module.newContent(portal_type='Product',
153
                                         id='3')
Ivan Tyagov's avatar
Ivan Tyagov committed
154 155 156
    shipping.setSupplyLinePriceCurrency(currency.getRelativeUrl())
    shipping.setBasePrice(10.0)
    shipping.setProductLine('shipping')
157 158
    shipping.validate()
    shipping.publish()
Lucas Carvalho's avatar
Lucas Carvalho committed
159

160
    # validate default order rule
161
    default_order_rule = self.portal.portal_rules.default_order_rule
162
    if default_order_rule.getValidationState() != 'validated':
163
      self.portal.portal_rules.default_order_rule.validate()
164

Lucas Carvalho's avatar
Lucas Carvalho committed
165 166
    self.website = self.setupWebSite()
    self.website.setProperty('ecommerce_base_currency',
167 168
                                            currency.getRelativeUrl())

169
    self.app.REQUEST.set('session_id', SESSION_ID)
170
    self.login('ivan')
171 172 173 174 175 176 177 178 179
    transaction.commit()
    self.tic()

  def clearModule(self, module):
    module.manage_delObjects(list(module.objectIds()))
    transaction.commit()
    self.tic()

  def beforeTearDown(self):
180
    self.clearModule(self.portal.web_site_module)
181 182 183
    self.clearModule(self.portal.product_module)
    self.clearModule(self.portal.sale_order_module)
    self.clearModule(self.portal.currency_module)
184
    self.portal.portal_caches.clearAllCache()
185

186 187 188 189 190 191
  def createDefaultOrganisation(self):
    """
      Create Seller organisation
    """
    self.organisation_module = self.portal.getDefaultModule('Organisation')
    if 'seller' not in self.organisation_module.objectIds():
192 193 194 195
        self.nexedi = self.organisation_module.newContent(title="Seller",
                                                          group='seller',
                                                          role='internal',
                                                          id='seller')
196 197 198 199 200 201 202

  def createTestUser(self, first_name, last_name, reference, group,
                     destination_project=None, id=None):
    """
      Create a user with the given parameters
    """
    self.person_module = self.getPersonModule()
203 204
    if hasattr(self.person_module, id or reference):
      return
205 206 207 208 209 210 211 212 213 214 215
    person = self.person_module.newContent(
      first_name=first_name,
      last_name=last_name,
      reference=reference,
      password='secret',
      career_role='internal',
      id=id or reference,
    )

    # Set the assignment
    assignment = person.newContent(portal_type='Assignment')
Lucas Carvalho's avatar
Lucas Carvalho committed
216 217
    assignment.edit(function='',
                    destination_value=getattr(self, 'seller', None),
218 219 220
                    start_date='1972-01-01', stop_date='2999-12-31',
                    group=group, destination_project=destination_project)
    assignment.open()
221
    transaction.commit()
222 223
    self.tic()

224
    #XXX: Security hack (lucas)
Lucas Carvalho's avatar
Lucas Carvalho committed
225 226
    self.portal.acl_users.zodb_roles.assignRoleToPrincipal('Manager',
                                                           reference)
227 228

  def getDefaultProduct(self, id='1'):
Lucas Carvalho's avatar
Lucas Carvalho committed
229
    """
Ivan Tyagov's avatar
Ivan Tyagov committed
230 231 232
      Get default product.
    """
    return self.getPortal().product_module[id]
233

234
  def initialiseSupplyLine(self):
235
    category_list = []
236
    portal_categories = self.portal.portal_categories
237 238
    if hasattr(portal_categories.product_line, 'ldlc'):
      portal_categories.product_line.manage_delObjects(['ldlc'])
Lucas Carvalho's avatar
Lucas Carvalho committed
239 240
    ldlc = portal_categories.product_line.newContent(portal_type='Category',
                                                     id='ldlc',
241
                                                     title='LDLC')
Lucas Carvalho's avatar
Lucas Carvalho committed
242 243
    laptop = ldlc.newContent(portal_type='Category',
                             id='laptop',
244 245
                             title='Laptop')

Lucas Carvalho's avatar
Lucas Carvalho committed
246 247
    netbook = laptop.newContent(portal_type='Category',
                                id='netbook',
248 249
                                title='Netbook')

Lucas Carvalho's avatar
Lucas Carvalho committed
250 251
    lcd = ldlc.newContent(portal_type='Category',
                          id='lcd',
252
                          title='Lcd Screen')
Lucas Carvalho's avatar
Lucas Carvalho committed
253 254
    mp3_player = ldlc.newContent(portal_type='Category',
                                 id='mp3',
255
                                 title='Mp3 Player')
256 257
    category_list.append(laptop)
    category_list.append(netbook)
258 259
    category_list.append(lcd)
    category_list.append(mp3_player)
260 261 262 263

    product_list = []
    for category in category_list:
      for i in range(3):
264 265
        title = '%s %s' % (category.getTitle(), i)
        reference = '%s_%s' % (category.getId(), i)
266 267 268
        product = self. portal.product_module.newContent(portal_type="Product",
                                                         title=title,
                                                         reference=reference)
269 270
        product_line = category.getRelativeUrl().replace('product_line/', '')
        product.setProductLine(product_line)
271
        product.setQuantityUnit('unit/piece')
272 273
        supply_line = product.newContent(id='default_supply_line',
                                         portal_type='Supply Line')
274 275 276
        supply_line.setBasePrice(10 * (i + 1))
        supply_line.setPricedQuantity(1)
        supply_line.setDefaultResourceValue(product)
277
        supply_line.setPriceCurrency('currency_module/EUR')
278
        product_list.append(product)
Lucas Carvalho's avatar
Lucas Carvalho committed
279

280 281
    for product in product_list:
      product.validate()
282
      product.publish()
Lucas Carvalho's avatar
Lucas Carvalho committed
283

284
    ups = self.portal.product_module.newContent(portal_type='Product',
285
                                           title='UPS Shipping : 24h')
286 287
    ups.setQuantityUnit('unit/piece')
    supply_line = ups.setProductLine('shipping/UPS24h')
288 289
    supply_line = ups.newContent(id='default_supply_line',
                                 portal_type='Supply Line')
290 291 292
    supply_line.setBasePrice(10)
    supply_line.setPricedQuantity(1)
    supply_line.setDefaultResourceValue(product)
293
    supply_line.setPriceCurrency('currency_module/EUR')
294 295 296 297
    ups.validate()
    ups.publish()
    transaction.commit()
    self.tic()
298 299

  def createUser(self, name, role_list):
300
    user_folder = self.portal.acl_users
301 302
    user_folder._doAddUser(name, 'password', role_list, [])

303 304 305 306 307
  def setupWebSite(self, **kw):
    """
      Setup Web Site
    """
    # add supported languages for Localizer
308
    localizer = self.portal.Localizer
309
    for language in LANGUAGE_LIST:
310
      localizer.manage_addLanguage(language=language)
Lucas Carvalho's avatar
Lucas Carvalho committed
311

312
    # create website
Lucas Carvalho's avatar
Lucas Carvalho committed
313 314 315 316
    website = getattr(self.portal.web_site_module, 'website', None)
    if website is None:
      website = self.portal.web_site_module.newContent(portal_type='Web Site',
                                                        id='website',
317 318 319
                                                        **kw)
      transaction.commit()
      self.tic()
320

Lucas Carvalho's avatar
Lucas Carvalho committed
321
    website.WebSite_setupECommerceWebSite()
322
    self.initialiseSupplyLine()
323 324 325 326 327 328 329 330
    transaction.commit()
    self.tic()

    self.createDefaultOrganisation()
    self.createTestUser(first_name="Web",
                        last_name='master',
                        reference='webmaster',
                        group=None)
331

Lucas Carvalho's avatar
Lucas Carvalho committed
332
    return website
333 334 335 336 337 338 339

  def createShoppingCartWithProductListAndShipping(self):
    """
      This method must create a Shopping Cart and add
      some Products and select one Shipping.
    """
    default_product = self.getDefaultProduct()
Lucas Carvalho's avatar
Lucas Carvalho committed
340
    self.website.Resource_addToShoppingCart(resource=default_product,
341
                                             quantity=1)
Lucas Carvalho's avatar
Lucas Carvalho committed
342

343 344 345 346 347 348 349 350 351 352
    shopping_cart = self.portal.SaleOrder_getShoppingCart()
    shipping_list = self.portal.SaleOrder_getAvailableShippingResourceList()
    order_line = getattr(shopping_cart, 'shipping_method', None)
    if order_line is None:
      order_line = shopping_cart.newContent(id='shipping_method',
                                            portal_type='Sale Order Line')
    order_line.setResource(shipping_list[0].getRelativeUrl())
    order_line.setQuantity(1)
    transaction.commit()
    self.tic()
Lucas Carvalho's avatar
Lucas Carvalho committed
353

354
  def test_01_AddResourceToShoppingCart(self):
Lucas Carvalho's avatar
Lucas Carvalho committed
355
    """
Ivan Tyagov's avatar
Ivan Tyagov committed
356 357 358
       Test adding an arbitrary resources to shopping cart.
    """
    default_product = self.getDefaultProduct()
Lucas Carvalho's avatar
Lucas Carvalho committed
359 360

    # set 'session_id' to simulate browser (cookie) environment
361
    self.app.REQUEST.set('session_id', SESSION_ID)
Lucas Carvalho's avatar
Lucas Carvalho committed
362
    self.assertEquals(SESSION_ID, self.website.SaleOrder_getShoppingCartId())
363 364

    # check if the shopping cart is empty
Lucas Carvalho's avatar
Lucas Carvalho committed
365
    self.assertTrue(self.website.SaleOrder_isShoppingCartEmpty())
Ivan Tyagov's avatar
Ivan Tyagov committed
366 367

    # add product to shopping cart
Lucas Carvalho's avatar
Lucas Carvalho committed
368
    self.website.Resource_addToShoppingCart(default_product, 1)
369

Lucas Carvalho's avatar
Lucas Carvalho committed
370
    shoppping_cart_item_list = self.website.SaleOrder_getShoppingCartItemList()
371 372 373 374
    self.assertEquals(1, len(shoppping_cart_item_list))
    self.assertEquals(1, shoppping_cart_item_list[0].getQuantity())
    self.assertEquals(shoppping_cart_item_list[0].getResource(), \
                                         default_product.getRelativeUrl())
Lucas Carvalho's avatar
Lucas Carvalho committed
375 376
    self.assertFalse(self.website.SaleOrder_isShoppingCartEmpty())

377
  def test_02_AddSameResourceToShoppingCart(self):
Lucas Carvalho's avatar
Lucas Carvalho committed
378
    """
Ivan Tyagov's avatar
Ivan Tyagov committed
379 380 381
       Test adding same resource to shopping cart.
    """
    default_product = self.getDefaultProduct()
382 383

    # add in two steps same product and check that we do not create
Ivan Tyagov's avatar
Ivan Tyagov committed
384
    # new Sale Order Line but just increase quantity on existing one
Lucas Carvalho's avatar
Lucas Carvalho committed
385 386
    self.website.Resource_addToShoppingCart(default_product, 1)
    self.website.Resource_addToShoppingCart(default_product, 1)
387

Lucas Carvalho's avatar
Lucas Carvalho committed
388
    shoppping_cart_item_list = self.website.SaleOrder_getShoppingCartItemList()
389 390 391 392 393 394 395

    self.assertEquals(1, len(shoppping_cart_item_list))
    self.assertEquals(2, shoppping_cart_item_list[0].getQuantity())
    self.assertEquals(shoppping_cart_item_list[0].getResource(), \
                                          default_product.getRelativeUrl())

  def test_03_AddDifferentResourceToShoppingCart(self):
Lucas Carvalho's avatar
Lucas Carvalho committed
396
    """
Ivan Tyagov's avatar
Ivan Tyagov committed
397 398 399
       Test adding different resource to shopping cart.
    """
    default_product = self.getDefaultProduct()
400
    another_product = self.getDefaultProduct(id='2')
Lucas Carvalho's avatar
Lucas Carvalho committed
401

402
    # add second diff product and check that we create new Sale Order Line
Lucas Carvalho's avatar
Lucas Carvalho committed
403 404 405 406
    self.website.Resource_addToShoppingCart(default_product, 1)
    self.website.Resource_addToShoppingCart(default_product, 1)
    self.website.Resource_addToShoppingCart(another_product, 1)
    shoppping_cart_item_list = self.website.SaleOrder_getShoppingCartItemList()
407 408 409 410 411 412 413
    self.assertEquals(2, len(shoppping_cart_item_list))
    self.assertEquals(2, shoppping_cart_item_list[0].getQuantity())
    self.assertEquals(1, shoppping_cart_item_list[1].getQuantity())
    self.assertEquals(shoppping_cart_item_list[0].getResource(), \
                                          default_product.getRelativeUrl())
    self.assertEquals(shoppping_cart_item_list[1].getResource(), \
                                          another_product.getRelativeUrl())
Lucas Carvalho's avatar
Lucas Carvalho committed
414

415
  def test_04_CalculateTotaShoppingCartPrice(self):
Lucas Carvalho's avatar
Lucas Carvalho committed
416
    """
Ivan Tyagov's avatar
Ivan Tyagov committed
417 418 419
       Test calculation shopping cart's total price.
    """
    default_product = self.getDefaultProduct()
420
    another_product = self.getDefaultProduct(id='2')
Lucas Carvalho's avatar
Lucas Carvalho committed
421 422 423
    self.website.Resource_addToShoppingCart(default_product, 1)
    self.website.Resource_addToShoppingCart(default_product, 1)
    self.website.Resource_addToShoppingCart(another_product, 1)
424

425
    shopping_cart = self.portal.SaleOrder_getShoppingCart()
Ivan Tyagov's avatar
Ivan Tyagov committed
426
    self.assertEquals(40.0, \
Lucas Carvalho's avatar
Lucas Carvalho committed
427
         float(self.website.SaleOrder_getShoppingCartTotalPrice()))
Ivan Tyagov's avatar
Ivan Tyagov committed
428
    # include taxes (by default it's 20%)
Lucas Carvalho's avatar
Lucas Carvalho committed
429 430
    self.assertEquals(40.0 * 1.20, \
         float(self.website.SaleOrder_getShoppingCartTotalPrice(
431 432
                                                        include_shipping=True,
                                                        include_taxes=True)))
Ivan Tyagov's avatar
Ivan Tyagov committed
433 434
    # no shipping selected yet so price should be the same
    self.assertEquals(40.0, \
Lucas Carvalho's avatar
Lucas Carvalho committed
435
         float(self.website.SaleOrder_getShoppingCartTotalPrice(
436
                                         include_shipping=True)))
437

Ivan Tyagov's avatar
Ivan Tyagov committed
438 439
    # add shipping
    shipping = self.getDefaultProduct('3')
440 441
    self.portal.SaleOrder_editShoppingCart(
                        field_my_shipping_method=shipping.getRelativeUrl())
442

Ivan Tyagov's avatar
Ivan Tyagov committed
443 444
    # test price calculation only with shipping
    self.assertEquals(40.0 + 10.0, \
Lucas Carvalho's avatar
Lucas Carvalho committed
445
                float(self.website.SaleOrder_getShoppingCartTotalPrice(
446
                                                      include_shipping=True)))
447

Ivan Tyagov's avatar
Ivan Tyagov committed
448
    # test price calculation shipping and taxes
Lucas Carvalho's avatar
Lucas Carvalho committed
449 450
    self.assertEquals((40.0 + 10.0) * 1.20, \
                float(self.website.SaleOrder_getShoppingCartTotalPrice(
451 452
                                                      include_shipping=True,
                                                      include_taxes=True)))
Lucas Carvalho's avatar
Lucas Carvalho committed
453

454
  def test_05_TestUpdateShoppingCart(self):
Lucas Carvalho's avatar
Lucas Carvalho committed
455
    """
Ivan Tyagov's avatar
Ivan Tyagov committed
456 457 458
       Test update of shopping cart.
    """
    default_product = self.getDefaultProduct()
459
    another_product = self.getDefaultProduct(id='2')
Ivan Tyagov's avatar
Ivan Tyagov committed
460 461
    shipping = self.getDefaultProduct('3')

Lucas Carvalho's avatar
Lucas Carvalho committed
462 463
    self.website.Resource_addToShoppingCart(default_product, quantity=1)
    self.website.Resource_addToShoppingCart(another_product, quantity=1)
464 465

    shopping_cart = self.portal.SaleOrder_getShoppingCart()
466
    shipping_url = shipping.getRelativeUrl()
Lucas Carvalho's avatar
Lucas Carvalho committed
467

468
    # increase shopping item number and set shipping
469
    self.portal.SaleOrder_editShoppingCart(field_my_buy_quantity=(2, 1,),
470
                                      field_my_shipping_method=shipping_url)
Lucas Carvalho's avatar
Lucas Carvalho committed
471

Ivan Tyagov's avatar
Ivan Tyagov committed
472
    # test price calculation without shipping and without taxes
Lucas Carvalho's avatar
Lucas Carvalho committed
473 474
    self.assertEquals((10.0 * 2 + 20.0 * 1) * 1.0, \
       float(self.website.SaleOrder_getShoppingCartTotalPrice(
475 476 477
                                                    include_shipping=False,
                                                    include_taxes=False)))

Ivan Tyagov's avatar
Ivan Tyagov committed
478
    # test price calculation with shipping and without taxes
Lucas Carvalho's avatar
Lucas Carvalho committed
479 480
    self.assertEquals((10.0 * 2 + 20.0 * 1 + 10.0) * 1.0, \
         float(self.website.SaleOrder_getShoppingCartTotalPrice(
481 482
                                                    include_shipping=True,
                                                    include_taxes=False)))
Ivan Tyagov's avatar
Ivan Tyagov committed
483
    # test price calculation with shipping and with taxes
Lucas Carvalho's avatar
Lucas Carvalho committed
484 485
    self.assertEquals((10.0 * 2 + 20.0 * 1 + 10.0) * 1.20, \
         float(self.website.SaleOrder_getShoppingCartTotalPrice(
486 487
                                                    include_shipping=True,
                                                    include_taxes=True)))
Lucas Carvalho's avatar
Lucas Carvalho committed
488

Ivan Tyagov's avatar
Ivan Tyagov committed
489
    # delete shopping item
490
    self.portal.SaleOrder_deleteShoppingCartItem('1')
Ivan Tyagov's avatar
Ivan Tyagov committed
491
    self.assertEquals(1, \
Lucas Carvalho's avatar
Lucas Carvalho committed
492 493
                      len(self.website.SaleOrder_getShoppingCartItemList()))

494
    self.portal.SaleOrder_deleteShoppingCartItem('2')
Ivan Tyagov's avatar
Ivan Tyagov committed
495
    self.assertEquals(0, \
Lucas Carvalho's avatar
Lucas Carvalho committed
496
                      len(self.website.SaleOrder_getShoppingCartItemList()))
Ivan Tyagov's avatar
Ivan Tyagov committed
497
    self.assertEquals(0.0, \
Lucas Carvalho's avatar
Lucas Carvalho committed
498
                   float(self.website.SaleOrder_getShoppingCartTotalPrice()))
Ivan Tyagov's avatar
Ivan Tyagov committed
499

500
  def test_06_TestClearShoppingCart(self):
Lucas Carvalho's avatar
Lucas Carvalho committed
501
    """
502
       Test clear of shopping cart.
Ivan Tyagov's avatar
Ivan Tyagov committed
503 504
    """
    default_product = self.getDefaultProduct()
505
    self.createShoppingCartWithProductListAndShipping()
506
    transaction.commit()
507
    self.tic()
508

Lucas Carvalho's avatar
Lucas Carvalho committed
509 510
    shopping_cart = self.website.SaleOrder_getShoppingCart(action='reset')
    self.assertEquals(0, len(self.website.SaleOrder_getShoppingCartItemList()))
511

512
  def test_07_SessionIDGeneration(self):
513
    """
514
      Test the generation of session id.
515 516 517 518 519 520 521 522
    """
    id_string = self.getPortal().Base_generateSessionID()
    self.assertEquals(10, len(id_string))
    for caracter in id_string:
      self.assertTrue(caracter in string.letters)

    id_string = self.getPortal().Base_generateSessionID(max_long=20)
    self.assertEquals(20, len(id_string))
Ivan Tyagov's avatar
Ivan Tyagov committed
523

524 525 526 527
    # XXX : maybe it can be good to forbid this case
    id_string = self.getPortal().Base_generateSessionID(max_long=0)
    self.assertEquals(0, len(id_string))

528
  def test_08_getApplicableTaxList(self):
529 530 531
    """
      Test the Person_getApplicableTaxList script
    """
Lucas Carvalho's avatar
Lucas Carvalho committed
532 533 534 535
    # XXX : actually the script is only in squeleton mode,
    # only return a tax of 20%
    self.assertEquals({'VAT': 20.0},
                          self.getPortal().Person_getApplicableTaxList())
536

537
  def test_09_paymentRedirect(self):
538
    """
539
      Test the SaleOrder_paymentRedirect script
540 541
    """
    default_product = self.getDefaultProduct()
Lucas Carvalho's avatar
Lucas Carvalho committed
542
    self.website.Resource_addToShoppingCart(default_product, quantity=1)
543
    transaction.commit()
544
    self.tic()
545 546 547

    # the confirmation should not be possible if the user is not logged
    self.logout()
Lucas Carvalho's avatar
Lucas Carvalho committed
548
    self.assertEquals(1, len(self.website.SaleOrder_getShoppingCartItemList()))
549
    self.website.SaleOrder_paymentRedirect()
550
    self.assertTrue(urllib.quote("You need to create an account to " \
Lucas Carvalho's avatar
Lucas Carvalho committed
551
                              "continue. If you already have please login.") in
552
                    self.app.REQUEST.RESPONSE.getHeader('location'))
553 554

    # but it should work if the user is authenticated
555
    self.login('customer')
556
    self.portal.SaleOrder_paymentRedirect()
557
    self.assertTrue(urllib.quote("SaleOrder_viewAsWeb") in
558
                    self.app.REQUEST.RESPONSE.getHeader('location'))
559

560
  def test_10_deleteShoppingCartItem(self):
561 562 563 564
    """
      Test the SaleOrder_deleteShoppingCartItem script
    """
    default_product = self.getDefaultProduct()
Lucas Carvalho's avatar
Lucas Carvalho committed
565 566
    self.website.Resource_addToShoppingCart(default_product, quantity=1)
    self.assertEquals(1, len(self.website.SaleOrder_getShoppingCartItemList()))
567

568
    # Trying to remove
569
    self.portal.SaleOrder_deleteShoppingCartItem()
Lucas Carvalho's avatar
Lucas Carvalho committed
570
    self.assertTrue(urllib.quote("Please select an item.") in
571
                               self.app.REQUEST.RESPONSE.getHeader('location'))
572

573
    # Check if the item still into the Shopping Cart
Lucas Carvalho's avatar
Lucas Carvalho committed
574
    self.assertEquals(1, len(self.website.SaleOrder_getShoppingCartItemList()))
575 576 577 578 579

    # Remove the product from the Shopping Cart
    product_id = default_product.getId()
    self.portal.SaleOrder_deleteShoppingCartItem(
                                          field_my_order_line_id=product_id)
Lucas Carvalho's avatar
Lucas Carvalho committed
580

581 582 583 584
    # Check if the Product have been removed sucessfully
    self.assertTrue(
              urllib.quote("Successfully removed from shopping cart.") in
                 self.app.REQUEST.RESPONSE.getHeader('location'))
585

586
    # Check if the Shopping Cart is empty
Lucas Carvalho's avatar
Lucas Carvalho committed
587
    self.assertEquals(0, len(self.website.SaleOrder_getShoppingCartItemList()))
588

589
  def test_11_finalizeShopping(self):
590 591 592
    """
      Test the SaleOrder_finalizeShopping script
    """
593
    self.login('webmaster')
Lucas Carvalho's avatar
Lucas Carvalho committed
594
    self.website.Resource_addToShoppingCart(self.getDefaultProduct(),
595
                                           quantity=1)
Lucas Carvalho's avatar
Lucas Carvalho committed
596
    self.website.Resource_addToShoppingCart(self.getDefaultProduct('2'),
597
                                           quantity=1)
598
    transaction.commit()
599 600
    self.tic()

Lucas Carvalho's avatar
Lucas Carvalho committed
601
    self.assertEquals(2, len(self.website.SaleOrder_getShoppingCartItemList()))
602
    self.assertEquals(0, len(self.portal.sale_order_module.contentValues()))
603

Lucas Carvalho's avatar
Lucas Carvalho committed
604
    self.website.SaleOrder_finalizeShopping()
605 606 607
    transaction.commit()
    self.tic()

608
    sale_order_object_list = self.portal.sale_order_module.contentValues()
609 610
    self.assertEquals(1, len(sale_order_object_list))
    self.assertEquals(2, len(sale_order_object_list[0].contentValues()))
Lucas Carvalho's avatar
Lucas Carvalho committed
611 612
    self.assertEquals(0, len(self.website.SaleOrder_getShoppingCartItemList()))

613
  def test_12_getAvailableShippingResourceList(self):
614 615 616 617
    """
      Test the SaleOrder_getAvailableShippingResourceList script
    """
    default_product = self.getDefaultProduct()
618 619 620 621 622
    product_line = self.portal.portal_categories.product_line
    shipping_url = product_line.shipping.getRelativeUrl()
    self.portal.product_module.newContent(portal_type='Product',
                                          title='shipping',
                                          product_line=shipping_url)
623 624 625
    transaction.commit()
    self.tic()
    self.assertEquals(2,
626
               len(self.portal.SaleOrder_getAvailableShippingResourceList()))
Lucas Carvalho's avatar
Lucas Carvalho committed
627

628
  def test_13_getFormatedData(self):
629 630 631
    """
      Test the datas formating scripts
    """
632 633
    sale_order = self.portal.sale_order_module.newContent(
                                                portal_type="Sale Order")
634 635 636 637
    sale_order_line = sale_order.newContent(portal_type="Sale Order Line",
                                            quantity="2",
                                            price="10")

638
    self.assertEqual(
Lucas Carvalho's avatar
Lucas Carvalho committed
639
          sale_order.getCreationDate().strftime('%a, %d %b %Y %H:%M %p'),
640
                    sale_order.SaleOrder_getFormattedCreationDate())
Lucas Carvalho's avatar
Lucas Carvalho committed
641
    self.assertEqual('%s %s' % ('20.0', sale_order.getPriceCurrencyTitle()),
642
                           sale_order.SaleOrder_getFormattedTotalPrice())
643

644
  def test_14_getSelectedShippingResource(self):
645 646 647 648
    """
      Test the SaleOrder_getSelectedShippingResource script
    """
    default_product = self.getDefaultProduct()
Lucas Carvalho's avatar
Lucas Carvalho committed
649
    self.website.Resource_addToShoppingCart(default_product, 1)
650 651
    shopping_cart = self.portal.SaleOrder_getShoppingCart()
    shipping_list = self.portal.SaleOrder_getAvailableShippingResourceList()
652

653 654
    order_line = getattr(shopping_cart, 'shipping_method', None)
    if order_line is None:
Lucas Carvalho's avatar
Lucas Carvalho committed
655
      order_line = shopping_cart.newContent(id='shipping_method',
656 657 658
                                            portal_type='Sale Order Line')

    order_line.setResource(shipping_list[0].getRelativeUrl())
659
    order_line.setQuantity(1)
660 661
    self.assertEquals(shipping_list[0].getRelativeUrl(),
                      self.portal.SaleOrder_getSelectedShippingResource())
662

663
  def test_15_getShoppingCartDefaultCurrency(self):
664
    """
665
      Testing the scripts:
666 667 668
      - WebSite_getShoppingCartDefaultCurrency
      - WebSite_getShoppingCartDefaultCurrencyCode
      - WebSite_getShoppingCartDefaultCurrencySymbol
669
    """
670
    currency = self.portal.restrictedTraverse('currency_module/EUR')
Lucas Carvalho's avatar
Lucas Carvalho committed
671 672 673 674 675
    self.assertEquals(currency,
                      self.website.WebSite_getShoppingCartDefaultCurrency())

    self.assertEquals(currency.getReference(),
                   self.website.WebSite_getShoppingCartDefaultCurrencyCode())
676

677
    self.assertEquals(currency.getShortTitle(),
Lucas Carvalho's avatar
Lucas Carvalho committed
678
                 self.website.WebSite_getShoppingCartDefaultCurrencySymbol())
679

680
  def test_16_simulatePaypalPayment(self):
681 682 683
    """
      Test all the scripts related to paypal
    """
684
    # create new python script to replace the external method
685
    custom_skin = self.portal.portal_skins.custom
686
    method_id = 'WebSection_submitPaypalNVPRequest'
687 688 689
    if method_id in custom_skin.objectIds():
      custom_skin.manage_delObjects([method_id])
    custom_skin.manage_addProduct['PythonScripts']\
Lucas Carvalho's avatar
Lucas Carvalho committed
690 691
                   .manage_addPythonScript(id=method_id)

692
    script = custom_skin[method_id]
Lucas Carvalho's avatar
Lucas Carvalho committed
693
    script.ZPythonScript_edit('parameter_dict, nvp_url',
694 695
                                                  SIMULATE_PAYPAL_SERVER)

696
    self.portal.changeSkin('View')
Lucas Carvalho's avatar
Lucas Carvalho committed
697

698
    #1 initialise a website
Lucas Carvalho's avatar
Lucas Carvalho committed
699 700 701 702
    self.website.setProperty('ecommerce_paypal_username', 'user')
    self.website.setProperty('ecommerce_paypal_password', 'pass')
    self.website.setProperty('ecommerce_paypal_signature', 'signature')

703
    #2 login and activate a cart
704
    self.login('webmaster')
705 706
    request = self.app.REQUEST
    request.set('session_id', SESSION_ID)
707 708

    #3 add a product in the cart
709
    self.createShoppingCartWithProductListAndShipping()
710

711
    #4 : paypal step 1 : get a new token
712
    token = self.website.cart.WebSection_getNewPaypalToken()
713
    self.assertNotEquals(token, None)
714

715
    #5 : paypal step 2 : go to paypal and confirm this token
Lucas Carvalho's avatar
Lucas Carvalho committed
716
    # PayerID is normaly set in the request when paypal
717
    # redirect to the instance
718
    request.set('PayerID', 'THEPAYERID')
Lucas Carvalho's avatar
Lucas Carvalho committed
719

720
    #6 : paypal step 3 : check if this token is confirmed by paypal
Lucas Carvalho's avatar
Lucas Carvalho committed
721
    error = self.website.WebSection_checkPaypalIdentification()
722
    self.assertEquals(error, None)
723
    self.assertTrue('/cart' in request.RESPONSE.getHeader('location'))
Lucas Carvalho's avatar
Lucas Carvalho committed
724

725
    #7 : paypal step 4 : validate the payment
Lucas Carvalho's avatar
Lucas Carvalho committed
726 727
    self.assertEquals(1,
                       len(self.website.SaleOrder_getShoppingCartItemList()))
728
    self.assertEquals(0, len(self.portal.sale_order_module.contentValues()))
Lucas Carvalho's avatar
Lucas Carvalho committed
729 730

    self.website.WebSection_doPaypalPayment(token=token)
731 732
    transaction.commit()
    self.tic()
Lucas Carvalho's avatar
Lucas Carvalho committed
733

734
    #8 check if sale order created
Lucas Carvalho's avatar
Lucas Carvalho committed
735
    self.assertEquals(0, len(self.website.SaleOrder_getShoppingCartItemList()))
736
    self.assertEquals(1, len(self.portal.sale_order_module.contentValues()))
737 738

    custom_skin.manage_delObjects([method_id])
Lucas Carvalho's avatar
Lucas Carvalho committed
739

740
  def test_17_getProductListFromWebSection(self):
741 742 743 744 745 746 747 748
    """
      Test the  WebSection_getProductList script.
    """
    laptop_product = self.getDefaultProduct(id='1')
    laptop_product.setProductLine('ldlc/laptop')
    netbook_product = self.getDefaultProduct(id='2')
    netbook_product.setProductLine('ldlc/laptop')

Lucas Carvalho's avatar
Lucas Carvalho committed
749
    self.website.WebSection_generateSectionFromCategory(
750
                                              category='product_line/ldlc',
751
                                              section_id='product_section',
752
                                              depth=2)
753 754 755
    transaction.commit()
    self.tic()

Lucas Carvalho's avatar
Lucas Carvalho committed
756 757 758 759
    self.assertEquals(14,
             len(self.website.product_section.WebSection_getProductList()))
    self.assertEquals(8,
         len(self.website.product_section.laptop.WebSection_getProductList()))
760

Lucas Carvalho's avatar
Lucas Carvalho committed
761
    netbook_section = self.website.product_section.laptop.netbook
762
    self.assertEquals(3, len(netbook_section.WebSection_getProductList()))
763

764
  def test_18_editShoppingCardWithABlankShippingMethod(self):
765 766 767 768 769
    """
      This test must make sure that you can edit the shopping cart selecting a
      blank shipping method and it will not break.
    """
    default_product = self.getDefaultProduct()
Lucas Carvalho's avatar
Lucas Carvalho committed
770
    self.website.Resource_addToShoppingCart(default_product, 1)
771

Lucas Carvalho's avatar
Lucas Carvalho committed
772
    shopping_cart = self.website.SaleOrder_getShoppingCart()
773 774
    self.assertFalse(hasattr(shopping_cart, 'shipping_method'))

775 776
    self.portal.SaleOrder_editShoppingCart(field_my_shipping_method='')
    self.portal.SaleOrder_editShoppingCart(field_my_shipping_method=None)
777 778 779

    # add shipping
    shipping = self.getDefaultProduct('3')
780 781
    self.portal.SaleOrder_editShoppingCart(
                          field_my_shipping_method=shipping.getRelativeUrl())
782 783 784

    self.assertTrue(hasattr(shopping_cart, 'shipping_method'))

785
  def test_19_editShoppingCardWithShippingMethodWithoutPrice(self):
786
    """
Lucas Carvalho's avatar
Lucas Carvalho committed
787
      This test must make sure that you can not edit the shopping cart
788 789
      selecting a shipping method without price.
    """
790
    default_product = self.getDefaultProduct(id='1')
Lucas Carvalho's avatar
Lucas Carvalho committed
791 792
    self.website.Resource_addToShoppingCart(default_product, 1)
    shopping_cart = self.website.SaleOrder_getShoppingCart()
793 794 795

    # add shipping
    shipping = self.getDefaultProduct('3')
Lucas Carvalho's avatar
Lucas Carvalho committed
796 797
    shipping.setBasePrice(None)
    self.website.SaleOrder_editShoppingCart(
798
                     field_my_shipping_method=shipping.getRelativeUrl())
799

800
    self.assertEquals(10.0, \
Lucas Carvalho's avatar
Lucas Carvalho committed
801
            float(self.website.SaleOrder_getShoppingCartTotalPrice(
802
                                                    include_shipping=True)))
803

804
  def test_20_getProductListFromWebSite(self):
805 806 807
    """
      Test the  WebSite_getProductList script.
    """
Lucas Carvalho's avatar
Lucas Carvalho committed
808 809 810
    self.assertEquals(5, len(self.website.WebSite_getProductList()))
    self.assertEquals(16,
               len(self.website.WebSite_getProductList(limit=1000)))
811

812
  def test_21_AddResourceToShoppingCartWithAnonymousUser(self):
813 814 815 816 817 818
    """
      Test adding an arbitrary resources to shopping cart with Anonymous user.
    """
    # anonymous user
    self.logout()
    self.createShoppingCartWithProductListAndShipping()
Lucas Carvalho's avatar
Lucas Carvalho committed
819
    shoppping_cart_item_list = self.website.SaleOrder_getShoppingCartItemList()
820 821
    self.assertEquals(1, len(shoppping_cart_item_list))

822
  def test_22_createShoppingCartWithAnonymousAndLogin(self):
823 824 825 826 827 828 829 830 831 832 833 834 835 836 837
    """
      Test adding an arbitrary resources to shopping cart with Anonymous user
      then create a new user, login and check if the Shopping Cart still the
      same.
    """
    # anonymous user
    self.logout()
    self.createShoppingCartWithProductListAndShipping()
    kw = dict(reference='toto',
              first_name='Toto',
              last_name='Test',
              default_email_text='test@test.com',
              password='secret',
              password_confirm='secret')
    for key, item in kw.items():
Lucas Carvalho's avatar
Lucas Carvalho committed
838 839
      self.app.REQUEST.set('field_your_%s' % key, item)
    self.website.WebSite_createWebSiteAccount('WebSite_viewRegistrationDialog')
840 841
    transaction.commit()
    self.tic()
Lucas Carvalho's avatar
Lucas Carvalho committed
842

843
    self.login('toto')
844
    self.portal.SaleOrder_paymentRedirect()
845
    self.assertTrue(urllib.quote("SaleOrder_viewAsWeb") in
846
                    self.app.REQUEST.RESPONSE.getHeader('location'))
847

848 849 850 851 852 853
  def test_23_getShoppingCartCustomer(self):
    """
      It must test SaleOrder_getShoppingCartCustomer script
      for a given Authenticated Member it should return the person value.
    """
    self.logout()
Lucas Carvalho's avatar
Lucas Carvalho committed
854
    person_object = self.website.SaleOrder_getShoppingCartCustomer()
855 856
    self.assertEquals(person_object, None)

857
    self.login('webmaster')
Lucas Carvalho's avatar
Lucas Carvalho committed
858
    person_object = self.website.SaleOrder_getShoppingCartCustomer()
859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874
    self.assertNotEquals(person_object, None)
    self.assertEquals(person_object.getReference(), 'webmaster')

  def test_24_getImageDataWithAnonymousUser(self):
    """
      Anonymous user must be able to get product image.
    """
    product = self.getDefaultProduct()
    file_upload = FileUpload(os.path.join(os.path.dirname(__file__),
                          'test_data', 'images', 'erp5_logo_small.png'), 'rb')
    product.edit(default_image_file=file_upload)
    transaction.get()
    self.tic()

    self.logout()
    product = self.getDefaultProduct()
Lucas Carvalho's avatar
Lucas Carvalho committed
875
    self.assertTrue(product.getDefaultImageValue().getData()
876 877 878 879 880
                                                 not in ('', None))

  def test_25_getSaleOrderModuleAbsoluteUrlWithAnonymousUser(self):
    """
      Anonymous User must have permission access Sale Order Module contents
Lucas Carvalho's avatar
Lucas Carvalho committed
881
      information.
882 883
    """
    self.logout()
Lucas Carvalho's avatar
Lucas Carvalho committed
884 885
    self.assertNotEquals(self.website.sale_order_module.absolute_url(), None)

886 887 888 889 890 891 892 893 894 895
  def test_26_getShoppingCartDefaultCurrencyWithAnonymousUser(self):
    """
      Anonymous User must have persmission to access Currency Module contents
      information and Published Currency objects.
      Testing the scripts:
      - WebSite_getShoppingCartDefaultCurrency
      - WebSite_getShoppingCartDefaultCurrencyCode
      - WebSite_getShoppingCartDefaultCurrencySymbol
    """
    self.logout()
Lucas Carvalho's avatar
Lucas Carvalho committed
896
    currency_url = self.website.getLayoutProperty('ecommerce_base_currency')
897
    currency_object = self.portal.restrictedTraverse(currency_url)
Lucas Carvalho's avatar
Lucas Carvalho committed
898 899 900 901 902
    self.assertEquals(currency_object,
                      self.website.WebSite_getShoppingCartDefaultCurrency())

    self.assertEquals(currency_object.getReference(),
                   self.website.WebSite_getShoppingCartDefaultCurrencyCode())
903 904

    self.assertEquals(currency_object.getShortTitle(),
Lucas Carvalho's avatar
Lucas Carvalho committed
905
                 self.website.WebSite_getShoppingCartDefaultCurrencySymbol())
906 907 908 909 910 911 912 913 914 915

  def test_27_ResourceGetShopUrl(self):
    """
      For a given Resource the Python Script (Resource_getShopUrl)
      should return the Shopping Url.
    """
    product = self.getDefaultProduct()
    self.assertEquals(product.Resource_getShopUrl(),
                 '%s/%s' % (product.getRelativeUrl(), 'Resource_viewAsShop'))

916 917 918 919 920
  def test_28_finalizeShoppingWithComment(self):
    """
      Testing if the comment added during the checkout will be set on the sale
      order object generated.
    """
921
    self.login('webmaster')
922
    comment = 'TESTING COMMENT'
Lucas Carvalho's avatar
Lucas Carvalho committed
923
    self.website.Resource_addToShoppingCart(self.getDefaultProduct(),
924 925
                                           quantity=1)

Lucas Carvalho's avatar
Lucas Carvalho committed
926 927
    self.website.SaleOrder_paymentRedirect(field_my_comment=comment)
    self.website.SaleOrder_finalizeShopping()
928 929 930 931 932
    transaction.commit()
    self.tic()

    sale_order_object_list = self.portal.sale_order_module.contentValues()
    self.assertEquals(comment, sale_order_object_list[0].getComment())
Lucas Carvalho's avatar
Lucas Carvalho committed
933

934
import unittest
Lucas Carvalho's avatar
Lucas Carvalho committed
935 936


937 938 939 940
def test_suite():
  suite = unittest.TestSuite()
  suite.addTest(unittest.makeSuite(TestCommerce))
  return suite