testERP5Commerce.py 36.4 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
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',
Aurel's avatar
Aurel committed
108
            'erp5_commerce',
109
            'erp5_accounting', 
Aurel's avatar
Aurel committed
110 111
            'erp5_simulation',
            '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
    default_order_rule = self.portal.portal_rules.default_order_rule
165
    if default_order_rule.getValidationState() != 'validated':
166
      self.portal.portal_rules.default_order_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
  def test_11_finalizeShopping(self):
591 592 593
    """
      Test the SaleOrder_finalizeShopping script
    """
594
    self.login('webmaster')
Lucas Carvalho's avatar
Lucas Carvalho committed
595
    self.website.Resource_addToShoppingCart(self.getDefaultProduct(),
596
                                           quantity=1)
Lucas Carvalho's avatar
Lucas Carvalho committed
597
    self.website.Resource_addToShoppingCart(self.getDefaultProduct('2'),
598
                                           quantity=1)
599
    transaction.commit()
600 601
    self.tic()

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    self.website.WebSection_doPaypalPayment(token=token)
734 735
    transaction.commit()
    self.tic()
Lucas Carvalho's avatar
Lucas Carvalho committed
736

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

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

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

Lucas Carvalho's avatar
Lucas Carvalho committed
759 760 761 762
    self.assertEquals(14,
             len(self.website.product_section.WebSection_getProductList()))
    self.assertEquals(8,
         len(self.website.product_section.laptop.WebSection_getProductList()))
763

Lucas Carvalho's avatar
Lucas Carvalho committed
764
    netbook_section = self.website.product_section.laptop.netbook
765
    self.assertEquals(3, len(netbook_section.WebSection_getProductList()))
766

767
  def test_18_editShoppingCardWithABlankShippingMethod(self):
768 769 770 771 772
    """
      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
773
    self.website.Resource_addToShoppingCart(default_product, 1)
774

Lucas Carvalho's avatar
Lucas Carvalho committed
775
    shopping_cart = self.website.SaleOrder_getShoppingCart()
776 777
    self.assertFalse(hasattr(shopping_cart, 'shipping_method'))

778 779
    self.portal.SaleOrder_editShoppingCart(field_my_shipping_method='')
    self.portal.SaleOrder_editShoppingCart(field_my_shipping_method=None)
780 781 782

    # add shipping
    shipping = self.getDefaultProduct('3')
783 784
    self.portal.SaleOrder_editShoppingCart(
                          field_my_shipping_method=shipping.getRelativeUrl())
785 786 787

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

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

    # add shipping
    shipping = self.getDefaultProduct('3')
Lucas Carvalho's avatar
Lucas Carvalho committed
799 800
    shipping.setBasePrice(None)
    self.website.SaleOrder_editShoppingCart(
801
                     field_my_shipping_method=shipping.getRelativeUrl())
802

803
    self.assertEquals(10.0, \
Lucas Carvalho's avatar
Lucas Carvalho committed
804
            float(self.website.SaleOrder_getShoppingCartTotalPrice(
805
                                                    include_shipping=True)))
806

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

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

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

846
    self.login('toto')
847
    self.portal.SaleOrder_paymentRedirect()
848
    self.assertTrue(urllib.quote("SaleOrder_viewAsWeb") in
849
                    self.app.REQUEST.RESPONSE.getHeader('location'))
850

851 852 853 854 855 856
  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
857
    person_object = self.website.SaleOrder_getShoppingCartCustomer()
858 859
    self.assertEquals(person_object, None)

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

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

    self.assertEquals(currency_object.getReference(),
                   self.website.WebSite_getShoppingCartDefaultCurrencyCode())
906 907

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

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

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

Lucas Carvalho's avatar
Lucas Carvalho committed
929 930
    self.website.SaleOrder_paymentRedirect(field_my_comment=comment)
    self.website.SaleOrder_finalizeShopping()
931 932 933 934 935
    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
936

937
import unittest
Lucas Carvalho's avatar
Lucas Carvalho committed
938 939


940 941 942 943
def test_suite():
  suite = unittest.TestSuite()
  suite.addTest(unittest.makeSuite(TestCommerce))
  return suite