addons-cm/website_sale_aplicoop/tests/test_date_calculations.py
2026-02-11 15:32:11 +01:00

311 lines
12 KiB
Python

# 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"
)