# Copyright 2026 Criptomart # License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl) from datetime import datetime, timedelta from odoo.tests.common import TransactionCase from odoo import fields class TestDateCalculations(TransactionCase): '''Test suite for date calculation methods in group.order model.''' def setUp(self): super().setUp() # Create a test group self.group = self.env['res.partner'].create({ 'name': 'Test Group', 'is_company': True, 'email': 'group@test.com', }) def test_compute_pickup_date_basic(self): '''Test pickup_date calculation returns next occurrence of pickup day.''' # Use today as reference and calculate next Tuesday today = fields.Date.today() # Find next Sunday (weekday 6) from today days_until_sunday = (6 - today.weekday()) % 7 if days_until_sunday == 0: # If today is Sunday start_date = today else: start_date = today + timedelta(days=days_until_sunday) # Create order with pickup_day = Tuesday (1), starting on Sunday # NO cutoff_day to avoid dependency on cutoff_date order = self.env['group.order'].create({ 'name': 'Test Order', 'group_ids': [(6, 0, [self.group.id])], 'start_date': start_date, # Sunday 'pickup_day': '1', # Tuesday 'cutoff_day': False, # Disable to avoid cutoff_date interference }) # Force computation order._compute_pickup_date() # Expected: Next Tuesday after Sunday (2 days later) expected_date = start_date + timedelta(days=2) self.assertEqual( order.pickup_date, expected_date, f"Expected {expected_date}, got {order.pickup_date}" ) def test_compute_pickup_date_same_day(self): '''Test pickup_date when start_date is same weekday as pickup_day.''' # Find next Tuesday from today today = fields.Date.today() days_until_tuesday = (1 - today.weekday()) % 7 if days_until_tuesday == 0: # If today is Tuesday start_date = today else: start_date = today + timedelta(days=days_until_tuesday) # Start on Tuesday, pickup also Tuesday - should return next week's Tuesday order = self.env['group.order'].create({ 'name': 'Test Order Same Day', 'group_ids': [(6, 0, [self.group.id])], 'start_date': start_date, # Tuesday 'pickup_day': '1', # Tuesday }) order._compute_pickup_date() # Should get next Tuesday (7 days later) expected_date = start_date + timedelta(days=7) self.assertEqual(order.pickup_date, expected_date) def test_compute_pickup_date_no_start_date(self): '''Test pickup_date calculation when no start_date is set.''' order = self.env['group.order'].create({ 'name': 'Test Order No Start', 'group_ids': [(6, 0, [self.group.id])], 'start_date': False, 'pickup_day': '1', # Tuesday }) order._compute_pickup_date() # Should calculate from today self.assertIsNotNone(order.pickup_date) # Verify it's a future date and falls on Tuesday self.assertGreaterEqual(order.pickup_date, fields.Date.today()) self.assertEqual(order.pickup_date.weekday(), 1) # 1 = Tuesday def test_compute_pickup_date_without_pickup_day(self): '''Test pickup_date is None when pickup_day is not set.''' order = self.env['group.order'].create({ 'name': 'Test Order No Pickup Day', 'group_ids': [(6, 0, [self.group.id])], 'start_date': fields.Date.today(), 'pickup_day': False, }) order._compute_pickup_date() # In Odoo, computed Date fields return False (not None) when no value self.assertFalse(order.pickup_date) def test_compute_pickup_date_all_weekdays(self): '''Test pickup_date calculation for each day of the week.''' base_date = fields.Date.from_string('2026-02-02') # Monday for day_num in range(7): day_name = ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sunday'][day_num] order = self.env['group.order'].create({ 'name': f'Test Order {day_name}', 'group_ids': [(6, 0, [self.group.id])], 'start_date': base_date, 'pickup_day': str(day_num), }) order._compute_pickup_date() # Verify the weekday matches self.assertEqual( order.pickup_date.weekday(), day_num, f"Pickup date weekday should be {day_num} ({day_name})" ) # Verify it's after start_date self.assertGreater(order.pickup_date, base_date) def test_compute_delivery_date_basic(self): '''Test delivery_date is pickup_date + 1 day.''' # Find next Sunday from today today = fields.Date.today() days_until_sunday = (6 - today.weekday()) % 7 if days_until_sunday == 0: # If today is Sunday start_date = today else: start_date = today + timedelta(days=days_until_sunday) order = self.env['group.order'].create({ 'name': 'Test Delivery Date', 'group_ids': [(6, 0, [self.group.id])], 'start_date': start_date, # Sunday 'pickup_day': '1', # Tuesday = start_date + 2 days }) order._compute_pickup_date() order._compute_delivery_date() # Pickup is Tuesday (2 days after Sunday start_date) expected_pickup = start_date + timedelta(days=2) # Delivery should be Wednesday (Tuesday + 1) expected_delivery = expected_pickup + timedelta(days=1) self.assertEqual(order.delivery_date, expected_delivery) def test_compute_delivery_date_without_pickup(self): '''Test delivery_date is None when pickup_date is not set.''' order = self.env['group.order'].create({ 'name': 'Test No Delivery', 'group_ids': [(6, 0, [self.group.id])], 'start_date': fields.Date.today(), 'pickup_day': False, # No pickup day = no pickup_date }) order._compute_pickup_date() order._compute_delivery_date() # In Odoo, computed Date fields return False (not None) when no value self.assertFalse(order.delivery_date) def test_compute_cutoff_date_basic(self): '''Test cutoff_date calculation returns next occurrence of cutoff day.''' # Create order with cutoff_day = Sunday (6) # If today is Sunday, cutoff should be today (days_ahead = 0 is allowed) order = self.env['group.order'].create({ 'name': 'Test Cutoff Date', 'group_ids': [(6, 0, [self.group.id])], 'start_date': fields.Date.from_string('2026-02-01'), # Sunday 'cutoff_day': '6', # Sunday }) order._compute_cutoff_date() # When today (in code) matches cutoff_day, days_ahead=0, so cutoff is today # The function uses datetime.now().date(), so we can't predict exact date # Instead verify: cutoff_date is set and falls on correct weekday self.assertIsNotNone(order.cutoff_date) self.assertEqual(order.cutoff_date.weekday(), 6) # Sunday def test_compute_cutoff_date_without_cutoff_day(self): '''Test cutoff_date is None when cutoff_day is not set.''' order = self.env['group.order'].create({ 'name': 'Test No Cutoff', 'group_ids': [(6, 0, [self.group.id])], 'start_date': fields.Date.today(), 'cutoff_day': False, }) order._compute_cutoff_date() # In Odoo, computed Date fields return False (not None) when no value self.assertFalse(order.cutoff_date) def test_date_dependency_chain(self): '''Test that changing start_date triggers recomputation of date fields.''' # Find next Sunday from today today = fields.Date.today() days_until_sunday = (6 - today.weekday()) % 7 if days_until_sunday == 0: # If today is Sunday start_date = today else: start_date = today + timedelta(days=days_until_sunday) order = self.env['group.order'].create({ 'name': 'Test Date Chain', 'group_ids': [(6, 0, [self.group.id])], 'start_date': start_date, # Dynamic Sunday 'pickup_day': '1', # Tuesday 'cutoff_day': '6', # Sunday }) # Get initial dates initial_pickup = order.pickup_date initial_delivery = order.delivery_date # Note: cutoff_date uses datetime.now() not start_date, so won't change # Change start_date to a week later new_start_date = start_date + timedelta(days=7) order.write({'start_date': new_start_date}) # Verify pickup and delivery dates changed self.assertNotEqual(order.pickup_date, initial_pickup) self.assertNotEqual(order.delivery_date, initial_delivery) # Verify dates are still consistent if order.pickup_date and order.delivery_date: delta = order.delivery_date - order.pickup_date self.assertEqual(delta.days, 1) def test_pickup_date_no_extra_week_bug(self): '''Regression test: ensure pickup_date doesn't add extra week incorrectly. Bug context: Previously when cutoff_day >= pickup_day numerically, logic incorrectly added 7 extra days even when pickup was already ahead in the calendar. ''' # Scenario: Pickup Tuesday (1) # Start: Sunday (dynamic) # Expected pickup: Tuesday (2 days later, NOT +9 days) # NOTE: NO cutoff_day to avoid cutoff_date dependency # Find next Sunday from today today = fields.Date.today() days_until_sunday = (6 - today.weekday()) % 7 if days_until_sunday == 0: # If today is Sunday start_date = today else: start_date = today + timedelta(days=days_until_sunday) order = self.env['group.order'].create({ 'name': 'Regression Test Extra Week', 'group_ids': [(6, 0, [self.group.id])], 'start_date': start_date, # Sunday (dynamic) 'pickup_day': '1', # Tuesday (numerically < 6) 'cutoff_day': False, # Disable to test pure start_date logic }) order._compute_pickup_date() # Must be 2 days after start_date (Tuesday) expected = start_date + timedelta(days=2) self.assertEqual( order.pickup_date, expected, f"Bug detected: pickup_date should be {expected} not {order.pickup_date}" ) # Verify it's exactly 2 days after start_date delta = order.pickup_date - order.start_date self.assertEqual( delta.days, 2, "Pickup should be 2 days after Sunday start_date" ) def test_multiple_orders_same_pickup_day(self): '''Test multiple orders with same pickup day get consistent dates.''' start = fields.Date.from_string('2026-02-01') pickup_day = '1' # Tuesday orders = [] for i in range(3): order = self.env['group.order'].create({ 'name': f'Test Order {i}', 'group_ids': [(6, 0, [self.group.id])], 'start_date': start, 'pickup_day': pickup_day, }) orders.append(order) # All should have same pickup_date pickup_dates = [o.pickup_date for o in orders] self.assertEqual( len(set(pickup_dates)), 1, "All orders with same start_date and pickup_day should have same pickup_date" )