# Copyright 2025 Criptomart # License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl) """ Test suite for cart/draft persistence in website_sale_aplicoop. Coverage: - Save draft order (empty, with items) - Load draft order - Draft consistency (prices don't change unexpectedly) - Product archived in draft (handling) - Merge inconsistent drafts - Draft timeline (very old draft, recent draft) """ from datetime import datetime, timedelta from odoo.tests.common import TransactionCase class TestSaveDraftOrder(TransactionCase): """Test saving draft orders.""" def setUp(self): super().setUp() self.group = self.env['res.partner'].create({ 'name': 'Test Group', 'is_company': True, }) self.member_partner = self.env['res.partner'].create({ 'name': 'Group Member', 'email': 'member@test.com', }) self.group.member_ids = [(4, self.member_partner.id)] self.user = self.env['res.users'].create({ 'name': 'Test User', 'login': 'testuser@test.com', 'email': 'testuser@test.com', 'partner_id': self.member_partner.id, }) self.category = self.env['product.category'].create({ 'name': 'Test Category', }) self.product1 = self.env['product.product'].create({ 'name': 'Product 1', 'type': 'consu', 'list_price': 10.0, 'categ_id': self.category.id, }) self.product2 = self.env['product.product'].create({ 'name': 'Product 2', 'type': 'consu', 'list_price': 20.0, 'categ_id': self.category.id, }) start_date = datetime.now().date() self.group_order = self.env['group.order'].create({ 'name': 'Test Order', 'group_ids': [(6, 0, [self.group.id])], 'type': 'regular', 'start_date': start_date, 'end_date': start_date + timedelta(days=7), 'period': 'weekly', 'pickup_day': '3', 'pickup_date': start_date + timedelta(days=3), 'cutoff_day': '0', }) self.group_order.action_open() self.group_order.product_ids = [(4, self.product1.id), (4, self.product2.id)] def test_save_draft_with_items(self): """Test saving draft order with products.""" draft_order = self.env['sale.order'].create({ 'partner_id': self.member_partner.id, 'group_order_id': self.group_order.id, 'state': 'draft', 'order_line': [ (0, 0, { 'product_id': self.product1.id, 'product_qty': 2, 'price_unit': self.product1.list_price, }), (0, 0, { 'product_id': self.product2.id, 'product_qty': 1, 'price_unit': self.product2.list_price, }), ], }) self.assertTrue(draft_order.exists()) self.assertEqual(draft_order.state, 'draft') self.assertEqual(len(draft_order.order_line), 2) def test_save_draft_empty_order(self): """Test saving draft order without items.""" # Edge case: empty draft empty_draft = self.env['sale.order'].create({ 'partner_id': self.member_partner.id, 'group_order_id': self.group_order.id, 'state': 'draft', 'order_line': [], }) # Should be valid (user hasn't added products yet) self.assertTrue(empty_draft.exists()) self.assertEqual(len(empty_draft.order_line), 0) def test_save_draft_updates_existing(self): """Test that saving draft updates existing draft, not creates new.""" # Create initial draft draft = self.env['sale.order'].create({ 'partner_id': self.member_partner.id, 'group_order_id': self.group_order.id, 'state': 'draft', 'order_line': [(0, 0, { 'product_id': self.product1.id, 'product_qty': 1, })], }) draft_id = draft.id # Simulate "save" with different quantity draft.order_line[0].product_qty = 5 # Should be same draft, not new one updated_draft = self.env['sale.order'].browse(draft_id) self.assertTrue(updated_draft.exists()) self.assertEqual(updated_draft.order_line[0].product_qty, 5) def test_save_draft_preserves_group_order_reference(self): """Test that group_order_id is preserved when saving.""" draft = self.env['sale.order'].create({ 'partner_id': self.member_partner.id, 'group_order_id': self.group_order.id, 'state': 'draft', }) # Link must be preserved self.assertEqual(draft.group_order_id, self.group_order) def test_save_draft_preserves_pickup_date(self): """Test that pickup_date is preserved in draft.""" draft = self.env['sale.order'].create({ 'partner_id': self.member_partner.id, 'group_order_id': self.group_order.id, 'pickup_date': self.group_order.pickup_date, 'state': 'draft', }) self.assertEqual(draft.pickup_date, self.group_order.pickup_date) class TestLoadDraftOrder(TransactionCase): """Test loading (retrieving) draft orders.""" def setUp(self): super().setUp() self.group = self.env['res.partner'].create({ 'name': 'Test Group', 'is_company': True, }) self.member_partner = self.env['res.partner'].create({ 'name': 'Group Member', 'email': 'member@test.com', }) self.group.member_ids = [(4, self.member_partner.id)] self.user = self.env['res.users'].create({ 'name': 'Test User', 'login': 'testuser@test.com', 'email': 'testuser@test.com', 'partner_id': self.member_partner.id, }) self.product = self.env['product.product'].create({ 'name': 'Test Product', 'type': 'consu', 'list_price': 10.0, }) start_date = datetime.now().date() self.group_order = self.env['group.order'].create({ 'name': 'Test Order', 'group_ids': [(6, 0, [self.group.id])], 'type': 'regular', 'start_date': start_date, 'end_date': start_date + timedelta(days=7), 'period': 'weekly', 'pickup_day': '3', 'cutoff_day': '0', }) self.group_order.action_open() def test_load_existing_draft(self): """Test loading an existing draft order.""" # Create draft draft = self.env['sale.order'].create({ 'partner_id': self.member_partner.id, 'group_order_id': self.group_order.id, 'state': 'draft', 'order_line': [(0, 0, { 'product_id': self.product.id, 'product_qty': 3, })], }) # Load it loaded = self.env['sale.order'].search([ ('id', '=', draft.id), ('partner_id', '=', self.member_partner.id), ('state', '=', 'draft'), ]) self.assertEqual(len(loaded), 1) self.assertEqual(loaded[0].order_line[0].product_qty, 3) def test_load_draft_not_visible_to_other_user(self): """Test that draft from one user not accessible to another.""" # Create draft for member_partner draft = self.env['sale.order'].create({ 'partner_id': self.member_partner.id, 'group_order_id': self.group_order.id, 'state': 'draft', }) # Create another user/partner other_partner = self.env['res.partner'].create({ 'name': 'Other Member', 'email': 'other@test.com', }) other_user = self.env['res.users'].create({ 'name': 'Other User', 'login': 'other@test.com', 'partner_id': other_partner.id, }) # Other user should not see original draft other_drafts = self.env['sale.order'].search([ ('id', '=', draft.id), ('partner_id', '=', other_partner.id), ]) self.assertEqual(len(other_drafts), 0) def test_load_draft_from_expired_order(self): """Test loading draft from closed/expired group order.""" # Close the group order self.group_order.action_close() # Create draft before closure (simulated) draft = self.env['sale.order'].create({ 'partner_id': self.member_partner.id, 'group_order_id': self.group_order.id, 'state': 'draft', }) # Draft should still be loadable (but should warn) loaded = self.env['sale.order'].browse(draft.id) self.assertTrue(loaded.exists()) # Controller should check: group_order.state and warn if closed class TestDraftConsistency(TransactionCase): """Test that draft prices remain consistent across saves.""" def setUp(self): super().setUp() self.group = self.env['res.partner'].create({ 'name': 'Test Group', 'is_company': True, }) self.member_partner = self.env['res.partner'].create({ 'name': 'Group Member', 'email': 'member@test.com', }) self.group.member_ids = [(4, self.member_partner.id)] self.user = self.env['res.users'].create({ 'name': 'Test User', 'login': 'testuser@test.com', 'partner_id': self.member_partner.id, }) self.product = self.env['product.product'].create({ 'name': 'Test Product', 'type': 'consu', 'list_price': 100.0, }) start_date = datetime.now().date() self.group_order = self.env['group.order'].create({ 'name': 'Test Order', 'group_ids': [(6, 0, [self.group.id])], 'type': 'regular', 'start_date': start_date, 'end_date': start_date + timedelta(days=7), 'period': 'weekly', 'pickup_day': '3', 'cutoff_day': '0', }) self.group_order.action_open() def test_draft_price_snapshot(self): """Test that draft captures price at time of save.""" original_price = self.product.list_price # Save draft with current price draft = self.env['sale.order'].create({ 'partner_id': self.member_partner.id, 'group_order_id': self.group_order.id, 'state': 'draft', 'order_line': [(0, 0, { 'product_id': self.product.id, 'product_qty': 1, 'price_unit': original_price, })], }) saved_price = draft.order_line[0].price_unit # Change product price self.product.list_price = 150.0 # Draft should still have original price self.assertEqual(draft.order_line[0].price_unit, saved_price) self.assertNotEqual(draft.order_line[0].price_unit, self.product.list_price) def test_draft_quantity_consistency(self): """Test that quantities are preserved across saves.""" # Save draft draft = self.env['sale.order'].create({ 'partner_id': self.member_partner.id, 'group_order_id': self.group_order.id, 'state': 'draft', 'order_line': [(0, 0, { 'product_id': self.product.id, 'product_qty': 5, })], }) # Re-load draft reloaded = self.env['sale.order'].browse(draft.id) self.assertEqual(reloaded.order_line[0].product_qty, 5) class TestProductArchivedInDraft(TransactionCase): """Test handling when product in draft gets archived.""" def setUp(self): super().setUp() self.group = self.env['res.partner'].create({ 'name': 'Test Group', 'is_company': True, }) self.member_partner = self.env['res.partner'].create({ 'name': 'Group Member', 'email': 'member@test.com', }) self.group.member_ids = [(4, self.member_partner.id)] self.user = self.env['res.users'].create({ 'name': 'Test User', 'login': 'testuser@test.com', 'partner_id': self.member_partner.id, }) self.product = self.env['product.product'].create({ 'name': 'Test Product', 'type': 'consu', 'list_price': 10.0, 'active': True, }) start_date = datetime.now().date() self.group_order = self.env['group.order'].create({ 'name': 'Test Order', 'group_ids': [(6, 0, [self.group.id])], 'type': 'regular', 'start_date': start_date, 'end_date': start_date + timedelta(days=7), 'period': 'weekly', 'pickup_day': '3', 'cutoff_day': '0', }) self.group_order.action_open() def test_load_draft_with_archived_product(self): """Test loading draft when product has been archived.""" # Create draft with active product draft = self.env['sale.order'].create({ 'partner_id': self.member_partner.id, 'group_order_id': self.group_order.id, 'state': 'draft', 'order_line': [(0, 0, { 'product_id': self.product.id, 'product_qty': 2, })], }) # Archive the product self.product.active = False # Load draft - should still work (historical data) loaded = self.env['sale.order'].browse(draft.id) self.assertTrue(loaded.exists()) # But product may not be editable/accessible class TestDraftTimeline(TransactionCase): """Test very old vs recent drafts.""" def setUp(self): super().setUp() self.group = self.env['res.partner'].create({ 'name': 'Test Group', 'is_company': True, }) self.member_partner = self.env['res.partner'].create({ 'name': 'Group Member', 'email': 'member@test.com', }) self.group.member_ids = [(4, self.member_partner.id)] self.product = self.env['product.product'].create({ 'name': 'Test Product', 'type': 'consu', 'list_price': 10.0, }) def test_draft_from_current_week(self): """Test draft from current/open group order.""" start_date = datetime.now().date() current_order = self.env['group.order'].create({ 'name': 'Current Order', 'group_ids': [(6, 0, [self.group.id])], 'type': 'regular', 'start_date': start_date, 'end_date': start_date + timedelta(days=7), 'period': 'weekly', 'pickup_day': '3', 'cutoff_day': '0', }) current_order.action_open() draft = self.env['sale.order'].create({ 'partner_id': self.member_partner.id, 'group_order_id': current_order.id, 'state': 'draft', }) # Should be accessible and valid self.assertTrue(draft.exists()) self.assertEqual(draft.group_order_id.state, 'open') def test_draft_from_old_order_6_months_ago(self): """Test draft from order that was 6 months ago.""" old_start = datetime.now().date() - timedelta(days=180) old_end = old_start + timedelta(days=7) old_order = self.env['group.order'].create({ 'name': 'Old Order', 'group_ids': [(6, 0, [self.group.id])], 'type': 'regular', 'start_date': old_start, 'end_date': old_end, 'period': 'weekly', 'pickup_day': '3', 'cutoff_day': '0', }) old_order.action_open() old_order.action_close() old_draft = self.env['sale.order'].create({ 'partner_id': self.member_partner.id, 'group_order_id': old_order.id, 'state': 'draft', }) # Should still exist but be inaccessible (order closed) self.assertTrue(old_draft.exists()) self.assertEqual(old_order.state, 'closed') def test_draft_order_count_for_user(self): """Test counting total drafts for a user.""" # Create multiple orders and drafts orders = [] for i in range(3): start = datetime.now().date() + timedelta(days=i*7) order = self.env['group.order'].create({ 'name': f'Order {i}', 'group_ids': [(6, 0, [self.group.id])], 'type': 'regular', 'start_date': start, 'end_date': start + timedelta(days=7), 'period': 'weekly', 'pickup_day': '3', 'cutoff_day': '0', }) order.action_open() orders.append(order) # Create draft for each for order in orders: self.env['sale.order'].create({ 'partner_id': self.member_partner.id, 'group_order_id': order.id, 'state': 'draft', }) # Count drafts for user user_drafts = self.env['sale.order'].search([ ('partner_id', '=', self.member_partner.id), ('state', '=', 'draft'), ]) self.assertEqual(len(user_drafts), 3)