311 lines
12 KiB
Python
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"
|
|
)
|