def test_pricelist_combination(self): product = self.env['product.product'].create({ 'name': 'Super Product', 'list_price': 100, 'taxes_id': False, }) current_website = self.env['website'].get_current_website() website_pricelist = current_website.get_current_pricelist() website_pricelist.write({ 'discount_policy': 'with_discount', 'item_ids': [(5, 0, 0), (0, 0, { 'applied_on': '1_product', 'product_tmpl_id': product.product_tmpl_id.id, 'min_quantity': 500, 'compute_price': 'percentage', 'percent_price': 63, })] }) promo_pricelist = self.env['product.pricelist'].create({ 'name': 'Super Pricelist', 'discount_policy': 'without_discount', 'item_ids': [(0, 0, { 'applied_on': '1_product', 'product_tmpl_id': product.product_tmpl_id.id, 'base': 'pricelist', 'base_pricelist_id': website_pricelist.id, 'compute_price': 'formula', 'price_discount': 25 })] }) so = self.env['sale.order'].create({ 'partner_id': self.env.user.partner_id.id, 'order_line': [(0, 0, { 'name': product.name, 'product_id': product.id, 'product_uom_qty': 1, 'product_uom': product.uom_id.id, 'price_unit': product.list_price, 'tax_id': False, })] }) sol = so.order_line self.assertEqual(sol.price_total, 100.0) so.pricelist_id = promo_pricelist with MockRequest(self.env, website=current_website, sale_order_id=so.id): so._cart_update(product_id=product.id, line_id=sol.id, set_qty=500) self.assertEqual(sol.price_unit, 37.0, 'Both reductions should be applied') self.assertEqual(sol.price_reduce, 27.75, 'Both reductions should be applied') self.assertEqual(sol.price_total, 13875)
def test_01_create_shipping_address_specific_user_account(self): ''' Ensure `website_id` is correctly set (specific_user_account) ''' p = self.env.user.partner_id so = self._create_so(p.id) with MockRequest(self.env, website=self.website, sale_order_id=so.id): self.WebsiteSaleController.address(**self.default_address_values) self.assertFalse( self._get_last_address(p).website_id, "New shipping address should not have a website set on it (no specific_user_account)." ) self.website.specific_user_account = True self.WebsiteSaleController.address(**self.default_address_values) self.assertEqual( self._get_last_address(p).website_id, self.website, "New shipping address should have a website set on it (specific_user_account)." )
def test_04_apply_empty_pl(self): ''' Ensure empty pl code reset the applied pl ''' so = self._create_so(self.env.user.partner_id.id) eur_pl = self.env['product.pricelist'].create({ 'name': 'EUR_test', 'website_id': self.website.id, 'code': 'EUR_test', }) with MockRequest(self.env, website=self.website, sale_order_id=so.id): self.WebsiteSaleController.pricelist('EUR_test') self.assertEqual(so.pricelist_id, eur_pl, "Ensure EUR_test is applied") self.WebsiteSaleController.pricelist('') self.assertNotEqual( so.pricelist_id, eur_pl, "Pricelist should be removed when sending an empty pl code")
def test_process_attendees_form(self): event = self.env['event.event'].create({ 'name': 'Event Update Type', 'event_type_id': self.event_type_complex.with_user(self.env.user).id, 'date_begin': FieldsDatetime.to_string(datetime.today() + timedelta(days=1)), 'date_end': FieldsDatetime.to_string(datetime.today() + timedelta(days=15)), }) form_details = { '1-name': 'Pixis', '1-email': '*****@*****.**', '1-phone': '+32444444444', '1-event_ticket_id': '2', '2-name': 'Geluchat', '2-email': '*****@*****.**', '2-phone': '+32777777777', '2-event_ticket_id': '3', 'question_answer-1-%s' % self.event_question_1.id: '5', 'question_answer-2-%s' % self.event_question_1.id: '9', 'question_answer-0-%s' % self.event_question_2.id: '7', 'question_answer-0-%s' % self.event_question_3.id: 'Free Text', } with MockRequest(self.env): registrations = WebsiteEvent()._process_attendees_form(event, form_details) self.assertEqual(registrations, [ {'name': 'Pixis', 'email': '*****@*****.**', 'phone': '+32444444444', 'event_ticket_id': 2, 'registration_answer_ids': [ (0, 0, {'question_id': self.event_question_1.id, 'value_answer_id': 5}), (0, 0, {'question_id': self.event_question_2.id, 'value_answer_id': 7}), (0, 0, {'question_id': self.event_question_3.id, 'value_text_box': 'Free Text'})]}, {'name': 'Geluchat', 'email': '*****@*****.**', 'phone': '+32777777777', 'event_ticket_id': 3, 'registration_answer_ids': [ (0, 0, {'question_id': self.event_question_1.id, 'value_answer_id': 9}), (0, 0, {'question_id': self.event_question_2.id, 'value_answer_id': 7}), (0, 0, {'question_id': self.event_question_3.id, 'value_text_box': 'Free Text'})]} ])
def test_pricelist_with_no_list_price(self): product = self.env['product.product'].create({ 'name': 'Super Product', 'list_price': 0, 'taxes_id': False, }) current_website = self.env['website'].get_current_website() website_pricelist = current_website.get_current_pricelist() website_pricelist.write({ 'discount_policy': 'without_discount', 'item_ids': [(5, 0, 0), (0, 0, { 'applied_on': '1_product', 'product_tmpl_id': product.product_tmpl_id.id, 'min_quantity': 0, 'compute_price': 'fixed', 'fixed_price': 10, })] }) so = self.env['sale.order'].create({ 'partner_id': self.env.user.partner_id.id, 'order_line': [(0, 0, { 'name': product.name, 'product_id': product.id, 'product_uom_qty': 5, 'product_uom': product.uom_id.id, 'price_unit': product.list_price, 'tax_id': False, })] }) sol = so.order_line self.assertEqual(sol.price_total, 0) so.pricelist_id = website_pricelist with MockRequest(self.env, website=current_website, sale_order_id=so.id): so._cart_update(product_id=product.id, line_id=sol.id, set_qty=5) self.assertEqual(sol.price_unit, 10.0, 'Pricelist price should be applied') self.assertEqual(sol.price_reduce, 10.0, 'Pricelist price should be applied') self.assertEqual(sol.price_total, 50.0)
def test_cart_update_with_fpos(self): # We will test that the mapping of an 10% included tax by a 0% by a fiscal position is taken into account when updating the cart self.env.user.partner_id.country_id = False current_website = self.env['website'].get_current_website() pricelist = current_website.get_current_pricelist() (self.env['product.pricelist'].search([]) - pricelist).write( {'active': False}) # Add 10% tax on product tax10 = self.env['account.tax'].create({ 'name': "Test tax 10", 'amount': 10, 'price_include': True, 'amount_type': 'percent' }) tax0 = self.env['account.tax'].create({ 'name': "Test tax 0", 'amount': 0, 'price_include': True, 'amount_type': 'percent' }) test_product = self.env['product.template'].create({ 'name': 'Test Product', 'price': 110, 'taxes_id': [(6, 0, [tax10.id])], }).with_context(website_id=current_website.id) # Add discout of 50% for pricelist pricelist.item_ids = self.env['product.pricelist.item'].create({ 'applied_on': "1_product", 'base': "list_price", 'compute_price': "percentage", 'percent_price': 50, 'product_tmpl_id': test_product.id, }) pricelist.discount_policy = 'without_discount' # Create fiscal position mapping taxes 10% -> 0% fpos = self.env['account.fiscal.position'].create({ 'name': 'test', }) self.env['account.fiscal.position.tax'].create({ 'position_id': fpos.id, 'tax_src_id': tax10.id, 'tax_dest_id': tax0.id, }) so = self.env['sale.order'].create({ 'partner_id': self.env.user.partner_id.id, }) sol = self.env['sale.order.line'].create({ 'name': test_product.name, 'product_id': test_product.product_variant_id.id, 'product_uom_qty': 1, 'product_uom': test_product.uom_id.id, 'price_unit': test_product.list_price, 'order_id': so.id, 'tax_id': [(6, 0, [tax10.id])], }) self.assertEqual(round(sol.price_total), 110.0, "110$ with 10% included tax") so.pricelist_id = pricelist so.fiscal_position_id = fpos sol.product_id_change() with MockRequest(self.env, website=current_website, sale_order_id=so.id): so._cart_update(product_id=test_product.product_variant_id.id, line_id=sol.id, set_qty=1) self.assertEqual( round(sol.price_total), 50, "100$ with 50% discount + 0% tax (mapped from fp 10% -> 0%)")
def test_process_att_no_request_lang(self): with MockRequest(self.env, website=self.website): self._test_att('/', {'href': '/'}) self._test_att('/en/', {'href': '/'}) self._test_att('/fr/', {'href': '/fr/'})
def test_visitor_creation_on_tracked_page(self): """ Test various flows involving visitor creation and update. """ existing_visitors = self.env['website.visitor'].search([]) existing_tracks = self.env['website.track'].search([]) self.url_open(self.untracked_page.url) self.url_open(self.tracked_page.url) self.url_open(self.tracked_page.url) new_visitor = self.env['website.visitor'].search([ ('id', 'not in', existing_visitors.ids) ]) new_track = self.env['website.track'].search([('id', 'not in', existing_tracks.ids)]) self.assertEqual(len(new_visitor), 1, "1 visitor should be created") self.assertEqual(len(new_track), 1, "There should be 1 tracked page") self.assertEqual(new_visitor.visit_count, 1) self.assertEqual(new_visitor.website_track_ids, new_track) self.assertVisitorTracking(new_visitor, self.tracked_page) # ------------------------------------------------------------ # Admin connects # ------------------------------------------------------------ self.cookies = {'visitor_uuid': new_visitor.access_token} with MockRequest(self.env, website=self.website, cookies=self.cookies): self.authenticate(self.user_admin.login, 'admin') visitor_admin = new_visitor # visit a page self.url_open(self.tracked_page_2.url) # check tracking and visitor / user sync self.assertVisitorTracking(visitor_admin, self.tracked_page | self.tracked_page_2) self.assertEqual(visitor_admin.partner_id, self.partner_admin) self.assertEqual(visitor_admin.name, self.partner_admin.name) # ------------------------------------------------------------ # Portal connects # ------------------------------------------------------------ with MockRequest(self.env, website=self.website, cookies=self.cookies): self.authenticate(self.user_portal.login, 'portal') self.assertFalse( self.env['website.visitor'].search([ ('id', 'not in', (existing_visitors | visitor_admin).ids) ]), "No extra visitor should be created") # visit a page self.url_open(self.tracked_page.url) self.url_open(self.untracked_page.url) self.url_open(self.tracked_page_2.url) self.url_open(self.tracked_page_2.url ) # 2 time to be sure it does not record twice # new visitor is created new_visitors = self.env['website.visitor'].search([ ('id', 'not in', existing_visitors.ids) ]) self.assertEqual(len(new_visitors), 2, "One extra visitor should be created") visitor_portal = new_visitors[0] self.assertEqual(visitor_portal.partner_id, self.partner_portal) self.assertEqual(visitor_portal.name, self.partner_portal.name) self.assertVisitorTracking(visitor_portal, self.tracked_page | self.tracked_page_2) # ------------------------------------------------------------ # Back to anonymous # ------------------------------------------------------------ # portal user disconnects self.logout() # visit some pages self.url_open(self.tracked_page.url) self.url_open(self.untracked_page.url) self.url_open(self.tracked_page_2.url) self.url_open(self.tracked_page_2.url ) # 2 time to be sure it does not record twice # new visitor is created new_visitors = self.env['website.visitor'].search([ ('id', 'not in', existing_visitors.ids) ]) self.assertEqual(len(new_visitors), 3, "One extra visitor should be created") visitor_anonymous = new_visitors[0] self.cookies['visitor_uuid'] = visitor_anonymous.access_token self.assertFalse(visitor_anonymous.name) self.assertFalse(visitor_anonymous.partner_id) self.assertVisitorTracking(visitor_anonymous, self.tracked_page | self.tracked_page_2) visitor_anonymous_tracks = visitor_anonymous.website_track_ids # ------------------------------------------------------------ # Admin connects again # ------------------------------------------------------------ with MockRequest(self.env, website=self.website, cookies=self.cookies): self.authenticate(self.user_admin.login, 'admin') # one visitor is deleted visitor_anonymous = self.env['website.visitor'].with_context( active_test=False).search([('id', '=', visitor_anonymous.id)]) self.assertVisitorDeactivated(visitor_anonymous, visitor_admin) new_visitors = self.env['website.visitor'].search([ ('id', 'not in', existing_visitors.ids) ]) self.assertEqual(new_visitors, visitor_admin | visitor_portal) visitor_admin = self.env['website.visitor'].search([ ('partner_id', '=', self.partner_admin.id) ]) # tracks are linked self.assertTrue( visitor_anonymous_tracks < visitor_admin.website_track_ids) self.assertEqual(len(visitor_admin.website_track_ids), 4, "There should be 4 tracked page for the admin") # ------------------------------------------------------------ # Back to anonymous # ------------------------------------------------------------ # admin disconnects self.logout() # visit some pages self.url_open(self.tracked_page.url) self.url_open(self.untracked_page.url) self.url_open(self.tracked_page_2.url) self.url_open(self.tracked_page_2.url ) # 2 time to be sure it does not record twice # new visitor created new_visitors = self.env['website.visitor'].search([ ('id', 'not in', existing_visitors.ids) ]) self.assertEqual(len(new_visitors), 3, "One extra visitor should be created") visitor_anonymous_2 = new_visitors[0] self.cookies['visitor_uuid'] = visitor_anonymous_2.access_token self.assertFalse(visitor_anonymous_2.name) self.assertFalse(visitor_anonymous_2.partner_id) self.assertVisitorTracking(visitor_anonymous_2, self.tracked_page | self.tracked_page_2) visitor_anonymous_2_tracks = visitor_anonymous_2.website_track_ids # ------------------------------------------------------------ # Portal connects again # ------------------------------------------------------------ with MockRequest(self.env, website=self.website, cookies=self.cookies): self.authenticate(self.user_portal.login, 'portal') # one visitor is deleted new_visitors = self.env['website.visitor'].search([ ('id', 'not in', existing_visitors.ids) ]) self.assertEqual(new_visitors, visitor_admin | visitor_portal) # tracks are linked self.assertTrue( visitor_anonymous_2_tracks < visitor_portal.website_track_ids) self.assertEqual(len(visitor_portal.website_track_ids), 4, "There should be 4 tracked page for the portal user") # simulate the portal user comes back 30min later for track in visitor_portal.website_track_ids: track.write({ 'visit_datetime': track.visit_datetime - timedelta(minutes=30) }) # visit a page self.url_open(self.tracked_page.url) visitor_portal.invalidate_cache(fnames=['website_track_ids']) # tracks are created self.assertEqual(len(visitor_portal.website_track_ids), 5, "There should be 5 tracked page for the portal user") # simulate the portal user comes back 8hours later visitor_portal.write({ 'last_connection_datetime': visitor_portal.last_connection_datetime - timedelta(hours=8) }) self.url_open(self.tracked_page.url) visitor_portal.invalidate_cache(fnames=['visit_count']) # check number of visits self.assertEqual(visitor_portal.visit_count, 2, "There should be 2 visits for the portal user")
def test_01_url_lang(self): with MockRequest(self.env, website=self.website): self.assertEqual( url_lang('', '[lang]'), '/[lang]/hello/', "`[lang]` is used to be replaced in the url_return after installing a language, it should not be replaced or removed." )
def test_02_copy_ids_views_unlink_on_module_update(env): """ Ensure copy_ids views are correctly removed during module update. - Having an ir.ui.view A in the codebase, eg `website.layout` - Having a theme.ir.ui.view B in a theme, inheriting ir.ui.view A - Removing the theme.ir.ui.view B from the XML file and then updating the theme for a particular website should: 1. Remove the theme.ir.ui.view record, which is the record pointed by the ir.model.data -> This is done through the regular Flectra behavior related to the ir.model.data and XML file check on upgrade. 2. Remove the theme.ir.ui.view's copy_ids (sort of the COW views) -> Not working for now 3. (not impact other website using this theme, see below) -> This is done through flectra/flectra@96ef4885a79 but did not come with tests Point 2. was not working, this test aims to ensure it will now. Note: This can't be done through a `ondelete=cascade` as this would impact other websites when modifying a specific website. This would be against the multi-website rule: "What is done on a website should not alter other websites." Regarding the flow described above, if a theme module was updated through the command line (or via the UI, but this is not possible in standard as theme modules are hidden from the Apps), it should update every website using this theme. """ View = env['ir.ui.view'] ThemeView = env['theme.ir.ui.view'] Imd = env['ir.model.data'] website_1 = env['website'].browse(1) website_2 = env['website'].browse(2) theme_default = env.ref('base.module_theme_default') # Install theme_default on website 1 and website 2 (website_1 + website_2).theme_id = theme_default env['ir.module.module'].with_context( load_all_views=True)._theme_load(website_1) env['ir.module.module'].with_context( load_all_views=True)._theme_load(website_2) key = 'theme_default.theme_child_view' domain = [ ('type', '=', 'qweb'), ('key', '=', key), ] def _simulate_xml_view(): # Simulate a theme.ir.ui.view inside theme_default XML files base_view = env.ref('test_website.update_module_base_view') theme_child_view = ThemeView.create({ 'name': 'Theme Child View', 'mode': 'extension', 'inherit_id': f'{base_view._name},{base_view.id}', 'arch': ''' <div position="inside"> <p>, and I am inherited by a theme.ir.ui.view</p> </div> ''', 'key': key, }) # Create IMD so when updating the module the views will be removed (not found in file) Imd.create({ 'module': 'theme_default', 'name': 'theme_child_view', 'model': 'theme.ir.ui.view', 'res_id': theme_child_view.id, }) # Simulate the theme.ir.ui.view being installed on website 1 and 2 View.create([ theme_child_view._convert_to_base_model(website_1), theme_child_view._convert_to_base_model(website_2), ]) # Ensure views are correctly setup: the theme.ir.ui.view should have been # copied to an ir.ui.view for website 1 view_website_1, view_website_2 = View.search(domain + [ ('theme_template_id', '=', theme_child_view.id), ('website_id', 'in', (website_1 + website_2).ids), ]) assert (set((view_website_1 + view_website_2)).issubset( theme_child_view.copy_ids) and view_website_1.website_id == website_1 and view_website_2.website_id == website_2 ), "Theme View should have been copied to the website." return view_website_1, view_website_2, theme_child_view ########################################## # CASE 1: generic update (-u, migration) # ########################################## view_website_1, view_website_2, theme_child_view = _simulate_xml_view() # Upgrade the module theme_default.button_immediate_upgrade() env.reset() # clear the set of environments env = env() # get an environment that refers to the new registry # Ensure the theme.ir.ui.view got removed (since there is an IMD but not # present in XML files) view = env.ref('theme_default.theme_child_view', False) assert not view, "Theme view should have been removed during module update." assert not theme_child_view.exists(),\ "Theme view should have been removed during module update. (2)" # Ensure copy_ids view got removed (and is not a leftover orphan) assert not View.search(domain), "copy_ids views did not get removed!" assert not (view_website_1.exists() or view_website_2.exists()),\ "copy_ids views did not get removed! (2)" ##################################################### # CASE 2: specific update (website theme selection) # ##################################################### view_website_1, view_website_2, theme_child_view = _simulate_xml_view() # Upgrade the module with MockRequest(env, website=website_1): theme_default.button_immediate_upgrade() env.reset() # clear the set of environments env = env() # get an environment that refers to the new registry # Ensure the theme.ir.ui.view got removed (since there is an IMD but not # present in XML files) view = env.ref('theme_default.theme_child_view', False) assert not view, "Theme view should have been removed during module update." assert not theme_child_view.exists(),\ "Theme view should have been removed during module update. (2)" # Ensure only website_1 copy_ids got removed, website_2 should be untouched assert not view_website_1.exists() and view_website_2.exists(),\ "Only website_1 copy should be removed (2)"
def test_01_multiwebsite_checks(self): """ Ensure the multi website compliance of programs and coupons, both in backend and frontend. """ order = self.empty_order self.env['sale.order.line'].create({ 'product_id': self.largeCabinet.id, 'name': 'Large Cabinet', 'product_uom_qty': 2.0, 'order_id': order.id, }) def _remove_reward(): order.order_line.filtered('is_reward_line').unlink() self.assertEqual(len(order.order_line.ids), 1, "Program should have been removed") def _apply_code(code, backend=True): if backend: self.env['sale.coupon.apply.code'].with_context( active_id=order.id).create({ 'coupon_code': code }).process_coupon() else: self.env['sale.coupon.apply.code'].sudo().apply_coupon( order, code) # ========================================== # ========== Programs (with code) ========== # ========================================== # 1. Backend - Generic _apply_code(self.p1.promo_code) self.assertEqual( len(order.order_line.ids), 2, "Should get the discount line as it is a generic promo program") _remove_reward() # 2. Frontend - Generic with MockRequest(self.env, website=self.website): _apply_code(self.p1.promo_code, False) self.assertEqual( len(order.order_line.ids), 2, "Should get the discount line as it is a generic promo program (2)" ) _remove_reward() # make program specific self.p1.website_id = self.website.id # 3. Backend - Specific with self.assertRaises(UserError): _apply_code( self.p1.promo_code ) # the order has no website_id so not possible to use a website specific code # 4. Frontend - Specific - Correct website order.website_id = self.website.id with MockRequest(self.env, website=self.website): _apply_code(self.p1.promo_code, False) self.assertEqual( len(order.order_line.ids), 2, "Should get the discount line as it is a specific promo program for the correct website" ) _remove_reward() # 5. Frontend - Specific - Wrong website self.p1.website_id = self.website2.id with MockRequest(self.env, website=self.website): _apply_code(self.p1.promo_code, False) self.assertEqual(len(order.order_line.ids), 1, "Should not get the reward as wrong website") # ============================== # =========== Coupons ========== # ============================== order.website_id = False self.env['coupon.generate.wizard'].with_context( active_id=self.discount_coupon_program.id).create({ 'nbr_coupons': 4, }).generate_coupon() coupons = self.discount_coupon_program.coupon_ids # 1. Backend - Generic _apply_code(coupons[0].code) self.assertEqual( len(order.order_line.ids), 2, "Should get the discount line as it is a generic coupon program") _remove_reward() # 2. Frontend - Generic with MockRequest(self.env, website=self.website): _apply_code(coupons[1].code, False) self.assertEqual( len(order.order_line.ids), 2, "Should get the discount line as it is a generic coupon program (2)" ) _remove_reward() # make program specific self.discount_coupon_program.website_id = self.website.id # 3. Backend - Specific with self.assertRaises(UserError): _apply_code( coupons[2].code ) # the order has no website_id so not possible to use a website specific code # 4. Frontend - Specific - Correct website order.website_id = self.website.id with MockRequest(self.env, website=self.website): _apply_code(coupons[2].code, False) self.assertEqual( len(order.order_line.ids), 2, "Should get the discount line as it is a specific coupon program for the correct website" ) _remove_reward() # 5. Frontend - Specific - Wrong website self.discount_coupon_program.website_id = self.website2.id with MockRequest(self.env, website=self.website): _apply_code(coupons[3].code, False) self.assertEqual(len(order.order_line.ids), 1, "Should not get the reward as wrong website") # ======================================== # ========== Programs (no code) ========== # ======================================== order.website_id = False self.p1.website_id = False self.p1.promo_code = False self.p1.promo_code_usage = 'no_code_needed' # 1. Backend - Generic order.recompute_coupon_lines() self.assertEqual( len(order.order_line.ids), 2, "Should get the discount line as it is a generic promo program") # 2. Frontend - Generic with MockRequest(self.env, website=self.website): order.recompute_coupon_lines() self.assertEqual( len(order.order_line.ids), 2, "Should get the discount line as it is a generic promo program (2)" ) # make program specific self.p1.website_id = self.website.id # 3. Backend - Specific order.recompute_coupon_lines() self.assertEqual( len(order.order_line.ids), 1, "The order has no website_id so not possible to use a website specific code" ) # 4. Frontend - Specific - Correct website order.website_id = self.website.id with MockRequest(self.env, website=self.website): order.recompute_coupon_lines() self.assertEqual( len(order.order_line.ids), 2, "Should get the discount line as it is a specific promo program for the correct website" ) # 5. Frontend - Specific - Wrong website self.p1.website_id = self.website2.id with MockRequest(self.env, website=self.website): order.recompute_coupon_lines() self.assertEqual(len(order.order_line.ids), 1, "Should not get the reward as wrong website")