testERP5Commerce.py 36.5 KB
Newer Older
1
# -*- coding: 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
37
from Products.ERP5.tests.utils import newSimulationExpectedFailure
Ivan Tyagov's avatar
Ivan Tyagov committed
38 39

SESSION_ID = "12345678"
40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61
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
62

Lucas Carvalho's avatar
Lucas Carvalho committed
63

Ivan Tyagov's avatar
Ivan Tyagov committed
64
class TestCommerce(ERP5TypeTestCase):
65
  """
Lucas Carvalho's avatar
Lucas Carvalho committed
66 67 68
  Todo:
  > Change name of all script, most of them should not be called on a
    SaleOrder.
69 70 71 72 73 74 75 76 77 78 79 80 81 82
  > 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
83 84 85 86 87 88 89 90 91 92 93 94
  WebSection_checkPaypalIdentification
  WebSection_checkoutProcedure
  WebSection_doPaypalPayment
  WebSection_viewCurrentPersonAsWeb
  WebSite_doExpressCheckoutPayment
  WebSite_getExpressCheckoutDetails
  WebSite_getNewPaypalToken
  WebSite_getPaypalOrderParameterDict
  WebSite_getPaypalSecurityParameterDict
  WebSite_getPaypalUrl
  WebSite_setupECommerceWebSite
  Product_getRelatedDescription
95
  Person_editPersonalInformation
96
  """
Ivan Tyagov's avatar
Ivan Tyagov committed
97 98 99

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

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

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

    self.login('ivan')

120 121 122
    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
123
    currency_module.manage_permission('Access contents information',
124
                                     roles=['Anonymous'], acquire=0)
Lucas Carvalho's avatar
Lucas Carvalho committed
125
    product_module.manage_permission('Access contents information',
126
                                     roles=['Anonymous'], acquire=0)
Lucas Carvalho's avatar
Lucas Carvalho committed
127
    sale_order_module.manage_permission('Access contents information',
128 129
                                     roles=['Anonymous'], acquire=0)

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

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

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

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

163
    # validate default order rule
164 165 166
    rule = self.getRule(reference='default_order_rule')
    if rule.getValidationState() != 'validated':
      rule.validate()
167

Lucas Carvalho's avatar
Lucas Carvalho committed
168 169
    self.website = self.setupWebSite()
    self.website.setProperty('ecommerce_base_currency',
170 171
                                            currency.getRelativeUrl())

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

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

  def beforeTearDown(self):
183
    self.clearModule(self.portal.web_site_module)
184 185 186
    self.clearModule(self.portal.product_module)
    self.clearModule(self.portal.sale_order_module)
    self.clearModule(self.portal.currency_module)
187
    self.portal.portal_caches.clearAllCache()
188

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

  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()
206 207
    if hasattr(self.person_module, id or reference):
      return
208 209 210 211 212 213 214 215 216 217 218
    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
219 220
    assignment.edit(function='',
                    destination_value=getattr(self, 'seller', None),
221 222 223
                    start_date='1972-01-01', stop_date='2999-12-31',
                    group=group, destination_project=destination_project)
    assignment.open()
224
    transaction.commit()
225 226
    self.tic()

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

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

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

Lucas Carvalho's avatar
Lucas Carvalho committed
249 250
    netbook = laptop.newContent(portal_type='Category',
                                id='netbook',
251 252
                                title='Netbook')

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

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

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

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

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

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

313
    # create website
Lucas Carvalho's avatar
Lucas Carvalho committed
314 315 316 317
    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',
318 319 320
                                                        **kw)
      transaction.commit()
      self.tic()
321

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

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

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

  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
341
    self.website.Resource_addToShoppingCart(resource=default_product,
342
                                             quantity=1)
Lucas Carvalho's avatar
Lucas Carvalho committed
343

344 345 346 347 348 349 350 351 352 353
    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
354

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

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

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

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

Lucas Carvalho's avatar
Lucas Carvalho committed
371
    shoppping_cart_item_list = self.website.SaleOrder_getShoppingCartItemList()
372 373 374 375
    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
376 377
    self.assertFalse(self.website.SaleOrder_isShoppingCartEmpty())

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

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

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

    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
397
    """
Ivan Tyagov's avatar
Ivan Tyagov committed
398 399 400
       Test adding different resource to shopping cart.
    """
    default_product = self.getDefaultProduct()
401
    another_product = self.getDefaultProduct(id='2')
Lucas Carvalho's avatar
Lucas Carvalho committed
402

403
    # add second diff product and check that we create new Sale Order Line
Lucas Carvalho's avatar
Lucas Carvalho committed
404 405 406 407
    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()
408 409 410 411 412 413 414
    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
415

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

513
  def test_07_SessionIDGeneration(self):
514
    """
515
      Test the generation of session id.
516 517 518 519 520 521 522 523
    """
    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
524

525 526 527 528
    # 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))

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

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

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

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

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

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

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

    # 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
581

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

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

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

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

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

610
    sale_order_object_list = self.portal.sale_order_module.contentValues()
611 612
    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
613 614
    self.assertEquals(0, len(self.website.SaleOrder_getShoppingCartItemList()))

615
  def test_12_getAvailableShippingResourceList(self):
616 617 618 619
    """
      Test the SaleOrder_getAvailableShippingResourceList script
    """
    default_product = self.getDefaultProduct()
620 621 622 623 624
    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)
625 626 627
    transaction.commit()
    self.tic()
    self.assertEquals(2,
628
               len(self.portal.SaleOrder_getAvailableShippingResourceList()))
Lucas Carvalho's avatar
Lucas Carvalho committed
629

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

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

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

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

    order_line.setResource(shipping_list[0].getRelativeUrl())
661
    order_line.setQuantity(1)
662 663

    selected_resource = self.portal.SaleOrder_getSelectedShippingResource()
664
    self.assertEquals(shipping_list[0].getRelativeUrl(),
665
                      selected_resource.getRelativeUrl())
666

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

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

681
    self.assertEquals(currency.getShortTitle(),
Lucas Carvalho's avatar
Lucas Carvalho committed
682
                 self.website.WebSite_getShoppingCartDefaultCurrencySymbol())
683

684
  @newSimulationExpectedFailure
685
  def test_16_simulatePaypalPayment(self):
686 687 688
    """
      Test all the scripts related to paypal
    """
689
    # create new python script to replace the external method
690
    custom_skin = self.portal.portal_skins.custom
691
    method_id = 'WebSection_submitPaypalNVPRequest'
692 693 694
    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
695 696
                   .manage_addPythonScript(id=method_id)

697
    script = custom_skin[method_id]
Lucas Carvalho's avatar
Lucas Carvalho committed
698
    script.ZPythonScript_edit('parameter_dict, nvp_url',
699 700
                                                  SIMULATE_PAYPAL_SERVER)

701
    self.portal.changeSkin('View')
Lucas Carvalho's avatar
Lucas Carvalho committed
702

703
    #1 initialise a website
Lucas Carvalho's avatar
Lucas Carvalho committed
704 705 706 707
    self.website.setProperty('ecommerce_paypal_username', 'user')
    self.website.setProperty('ecommerce_paypal_password', 'pass')
    self.website.setProperty('ecommerce_paypal_signature', 'signature')

708
    #2 login and activate a cart
709
    self.login('webmaster')
710 711
    request = self.app.REQUEST
    request.set('session_id', SESSION_ID)
712 713

    #3 add a product in the cart
714
    self.createShoppingCartWithProductListAndShipping()
715

716
    #4 : paypal step 1 : get a new token
717
    token = self.website.cart.WebSection_getNewPaypalToken()
718
    self.assertNotEquals(token, None)
719

720
    #5 : paypal step 2 : go to paypal and confirm this token
Lucas Carvalho's avatar
Lucas Carvalho committed
721
    # PayerID is normaly set in the request when paypal
722
    # redirect to the instance
723
    request.set('PayerID', 'THEPAYERID')
Lucas Carvalho's avatar
Lucas Carvalho committed
724

725
    #6 : paypal step 3 : check if this token is confirmed by paypal
Lucas Carvalho's avatar
Lucas Carvalho committed
726
    error = self.website.WebSection_checkPaypalIdentification()
727
    self.assertEquals(error, None)
728 729 730

    url_location = request.RESPONSE.getHeader('location')
    self.assertTrue('/SaleOrder_viewAsWeb' in url_location)
Lucas Carvalho's avatar
Lucas Carvalho committed
731

732
    #7 : paypal step 4 : validate the payment
Lucas Carvalho's avatar
Lucas Carvalho committed
733 734
    self.assertEquals(1,
                       len(self.website.SaleOrder_getShoppingCartItemList()))
735
    self.assertEquals(0, len(self.portal.sale_order_module.contentValues()))
Lucas Carvalho's avatar
Lucas Carvalho committed
736 737

    self.website.WebSection_doPaypalPayment(token=token)
738 739
    transaction.commit()
    self.tic()
Lucas Carvalho's avatar
Lucas Carvalho committed
740

741
    #8 check if sale order created
Lucas Carvalho's avatar
Lucas Carvalho committed
742
    self.assertEquals(0, len(self.website.SaleOrder_getShoppingCartItemList()))
743
    self.assertEquals(1, len(self.portal.sale_order_module.contentValues()))
744 745

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

747
  def test_17_getProductListFromWebSection(self):
748 749 750 751 752 753 754 755
    """
      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
756
    self.website.WebSection_generateSectionFromCategory(
757
                                              category='product_line/ldlc',
758
                                              section_id='product_section',
759
                                              depth=2)
760 761 762
    transaction.commit()
    self.tic()

Lucas Carvalho's avatar
Lucas Carvalho committed
763 764 765 766
    self.assertEquals(14,
             len(self.website.product_section.WebSection_getProductList()))
    self.assertEquals(8,
         len(self.website.product_section.laptop.WebSection_getProductList()))
767

Lucas Carvalho's avatar
Lucas Carvalho committed
768
    netbook_section = self.website.product_section.laptop.netbook
769
    self.assertEquals(3, len(netbook_section.WebSection_getProductList()))
770

771
  def test_18_editShoppingCardWithABlankShippingMethod(self):
772 773 774 775 776
    """
      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
777
    self.website.Resource_addToShoppingCart(default_product, 1)
778

Lucas Carvalho's avatar
Lucas Carvalho committed
779
    shopping_cart = self.website.SaleOrder_getShoppingCart()
780 781
    self.assertFalse(hasattr(shopping_cart, 'shipping_method'))

782 783
    self.portal.SaleOrder_editShoppingCart(field_my_shipping_method='')
    self.portal.SaleOrder_editShoppingCart(field_my_shipping_method=None)
784 785 786

    # add shipping
    shipping = self.getDefaultProduct('3')
787 788
    self.portal.SaleOrder_editShoppingCart(
                          field_my_shipping_method=shipping.getRelativeUrl())
789 790 791

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

792
  def test_19_editShoppingCardWithShippingMethodWithoutPrice(self):
793
    """
Lucas Carvalho's avatar
Lucas Carvalho committed
794
      This test must make sure that you can not edit the shopping cart
795 796
      selecting a shipping method without price.
    """
797
    default_product = self.getDefaultProduct(id='1')
Lucas Carvalho's avatar
Lucas Carvalho committed
798 799
    self.website.Resource_addToShoppingCart(default_product, 1)
    shopping_cart = self.website.SaleOrder_getShoppingCart()
800 801 802

    # add shipping
    shipping = self.getDefaultProduct('3')
Lucas Carvalho's avatar
Lucas Carvalho committed
803 804
    shipping.setBasePrice(None)
    self.website.SaleOrder_editShoppingCart(
805
                     field_my_shipping_method=shipping.getRelativeUrl())
806

807
    self.assertEquals(10.0, \
Lucas Carvalho's avatar
Lucas Carvalho committed
808
            float(self.website.SaleOrder_getShoppingCartTotalPrice(
809
                                                    include_shipping=True)))
810

811
  def test_20_getProductListFromWebSite(self):
812 813 814
    """
      Test the  WebSite_getProductList script.
    """
Lucas Carvalho's avatar
Lucas Carvalho committed
815 816 817
    self.assertEquals(5, len(self.website.WebSite_getProductList()))
    self.assertEquals(16,
               len(self.website.WebSite_getProductList(limit=1000)))
818

819
  def test_21_AddResourceToShoppingCartWithAnonymousUser(self):
820 821 822 823 824 825
    """
      Test adding an arbitrary resources to shopping cart with Anonymous user.
    """
    # anonymous user
    self.logout()
    self.createShoppingCartWithProductListAndShipping()
Lucas Carvalho's avatar
Lucas Carvalho committed
826
    shoppping_cart_item_list = self.website.SaleOrder_getShoppingCartItemList()
827 828
    self.assertEquals(1, len(shoppping_cart_item_list))

829
  def test_22_createShoppingCartWithAnonymousAndLogin(self):
830 831 832 833 834 835 836 837 838 839 840 841 842 843 844
    """
      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
845 846
      self.app.REQUEST.set('field_your_%s' % key, item)
    self.website.WebSite_createWebSiteAccount('WebSite_viewRegistrationDialog')
847 848
    transaction.commit()
    self.tic()
Lucas Carvalho's avatar
Lucas Carvalho committed
849

850
    self.login('toto')
851
    self.portal.SaleOrder_paymentRedirect()
852
    self.assertTrue(urllib.quote("SaleOrder_viewAsWeb") in
853
                    self.app.REQUEST.RESPONSE.getHeader('location'))
854

855 856 857 858 859 860
  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
861
    person_object = self.website.SaleOrder_getShoppingCartCustomer()
862 863
    self.assertEquals(person_object, None)

864
    self.login('webmaster')
Lucas Carvalho's avatar
Lucas Carvalho committed
865
    person_object = self.website.SaleOrder_getShoppingCartCustomer()
866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881
    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
882
    self.assertTrue(product.getDefaultImageValue().getData()
883 884 885 886 887
                                                 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
888
      information.
889 890
    """
    self.logout()
Lucas Carvalho's avatar
Lucas Carvalho committed
891 892
    self.assertNotEquals(self.website.sale_order_module.absolute_url(), None)

893 894 895 896 897 898 899 900 901 902
  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
903
    currency_url = self.website.getLayoutProperty('ecommerce_base_currency')
904
    currency_object = self.portal.restrictedTraverse(currency_url)
Lucas Carvalho's avatar
Lucas Carvalho committed
905 906 907 908 909
    self.assertEquals(currency_object,
                      self.website.WebSite_getShoppingCartDefaultCurrency())

    self.assertEquals(currency_object.getReference(),
                   self.website.WebSite_getShoppingCartDefaultCurrencyCode())
910 911

    self.assertEquals(currency_object.getShortTitle(),
Lucas Carvalho's avatar
Lucas Carvalho committed
912
                 self.website.WebSite_getShoppingCartDefaultCurrencySymbol())
913 914 915 916 917 918 919 920 921 922

  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'))

923
  @newSimulationExpectedFailure
924 925 926 927 928
  def test_28_finalizeShoppingWithComment(self):
    """
      Testing if the comment added during the checkout will be set on the sale
      order object generated.
    """
929
    self.login('webmaster')
930
    comment = 'TESTING COMMENT'
Lucas Carvalho's avatar
Lucas Carvalho committed
931
    self.website.Resource_addToShoppingCart(self.getDefaultProduct(),
932 933
                                           quantity=1)

Lucas Carvalho's avatar
Lucas Carvalho committed
934 935
    self.website.SaleOrder_paymentRedirect(field_my_comment=comment)
    self.website.SaleOrder_finalizeShopping()
936 937 938 939 940
    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
941

942
import unittest
Lucas Carvalho's avatar
Lucas Carvalho committed
943 944


945 946 947 948
def test_suite():
  suite = unittest.TestSuite()
  suite.addTest(unittest.makeSuite(TestCommerce))
  return suite