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 109 110
            'erp5_commerce',
            'erp5_simulation',
            'erp5_simulation_test',)
111

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

    self.login('ivan')

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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


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