# Copyright 2025 Criptomart # License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl) """ Test suite for edge cases involving dates, times, and calendar calculations. Coverage: - Leap year (Feb 29) handling - Long-duration orders (entire year) - Pickup day boundary conditions - Orders with future start dates - Orders without end dates - Extreme dates (year 1900, year 2099) """ from datetime import datetime, timedelta, date from dateutil.relativedelta import relativedelta from odoo.tests.common import TransactionCase from odoo.exceptions import ValidationError class TestLeapYearHandling(TransactionCase): """Test date calculations with leap year (Feb 29).""" def setUp(self): super().setUp() self.group = self.env['res.partner'].create({ 'name': 'Test Group', 'is_company': True, }) def test_order_spans_leap_day(self): """Test order that includes Feb 29 (leap year).""" # 2024 is a leap year start = date(2024, 2, 25) end = date(2024, 3, 3) # Spans Feb 29 order = self.env['group.order'].create({ 'name': 'Leap Year Order', 'group_ids': [(6, 0, [self.group.id])], 'type': 'regular', 'start_date': start, 'end_date': end, 'period': 'weekly', 'pickup_day': '2', # Wednesday (Feb 28 or 29 depending on week) 'cutoff_day': '0', }) self.assertTrue(order.exists()) # Should correctly calculate pickup date self.assertTrue(order.pickup_date) def test_pickup_day_on_feb_29(self): """Test setting pickup_day to land on Feb 29.""" # 2024 Feb 29 is a Thursday (day 3) start = date(2024, 2, 26) # Monday end = date(2024, 3, 3) order = self.env['group.order'].create({ 'name': 'Feb 29 Pickup', 'group_ids': [(6, 0, [self.group.id])], 'type': 'regular', 'start_date': start, 'end_date': end, 'period': 'weekly', 'pickup_day': '3', # Thursday = Feb 29 'cutoff_day': '0', }) self.assertEqual(order.pickup_date, date(2024, 2, 29)) def test_order_before_leap_day(self): """Test order in non-leap year (no Feb 29).""" # 2023 is NOT a leap year start = date(2023, 2, 25) end = date(2023, 3, 3) order = self.env['group.order'].create({ 'name': 'Non-Leap Year Order', 'group_ids': [(6, 0, [self.group.id])], 'type': 'regular', 'start_date': start, 'end_date': end, 'period': 'weekly', 'pickup_day': '2', 'cutoff_day': '0', }) self.assertTrue(order.exists()) # Pickup should be Feb 28 (last day of Feb) self.assertIn(order.pickup_date.month, [2, 3]) class TestLongDurationOrders(TransactionCase): """Test orders spanning very long periods.""" def setUp(self): super().setUp() self.group = self.env['res.partner'].create({ 'name': 'Test Group', 'is_company': True, }) def test_order_spans_entire_year(self): """Test order running for 365 days.""" start = date(2024, 1, 1) end = date(2024, 12, 31) order = self.env['group.order'].create({ 'name': 'Year-Long Order', 'group_ids': [(6, 0, [self.group.id])], 'type': 'regular', 'start_date': start, 'end_date': end, 'period': 'weekly', 'pickup_day': '3', # Same day each week 'cutoff_day': '0', }) self.assertTrue(order.exists()) # Should handle 52+ weeks correctly days_diff = (end - start).days self.assertEqual(days_diff, 365) def test_order_multiple_years(self): """Test order spanning multiple years (2+ years).""" start = date(2024, 1, 1) end = date(2026, 12, 31) # 3 years order = self.env['group.order'].create({ 'name': 'Multi-Year Order', 'group_ids': [(6, 0, [self.group.id])], 'type': 'regular', 'start_date': start, 'end_date': end, 'period': 'monthly', 'pickup_day': '15', 'cutoff_day': '10', }) self.assertTrue(order.exists()) days_diff = (end - start).days self.assertGreater(days_diff, 700) # More than 2 years def test_order_one_day_duration(self): """Test order with start_date == end_date (single day).""" same_day = date(2024, 2, 15) order = self.env['group.order'].create({ 'name': 'One-Day Order', 'group_ids': [(6, 0, [self.group.id])], 'type': 'once', 'start_date': same_day, 'end_date': same_day, 'period': 'once', 'pickup_day': '0', 'cutoff_day': '0', }) self.assertTrue(order.exists()) class TestPickupDayBoundary(TransactionCase): """Test pickup_day calculations at boundaries.""" def setUp(self): super().setUp() self.group = self.env['res.partner'].create({ 'name': 'Test Group', 'is_company': True, }) def test_pickup_day_same_as_start_date(self): """Test when pickup_day equals start date (today).""" today = date.today() start = today end = today + timedelta(days=7) order = self.env['group.order'].create({ 'name': 'Today Pickup', 'group_ids': [(6, 0, [self.group.id])], 'type': 'regular', 'start_date': start, 'end_date': end, 'period': 'weekly', 'pickup_day': str(start.weekday()), # Same as start 'cutoff_day': '0', }) self.assertTrue(order.exists()) # Pickup should be today self.assertEqual(order.pickup_date, start) def test_pickup_day_last_day_of_month(self): """Test pickup day on last day of month (Jan 31, Feb 28/29, etc).""" # Start on Jan 24, pickup on Jan 31 start = date(2024, 1, 24) end = date(2024, 2, 1) order = self.env['group.order'].create({ 'name': 'Month-End Pickup', 'group_ids': [(6, 0, [self.group.id])], 'type': 'regular', 'start_date': start, 'end_date': end, 'period': 'once', 'pickup_day': '2', # Wednesday = Jan 31 'cutoff_day': '0', }) self.assertTrue(order.exists()) def test_pickup_day_month_boundary(self): """Test when pickup crosses month boundary.""" # Start Jan 28, pickup might be in February start = date(2024, 1, 28) end = date(2024, 2, 5) order = self.env['group.order'].create({ 'name': 'Month Boundary Pickup', 'group_ids': [(6, 0, [self.group.id])], 'type': 'regular', 'start_date': start, 'end_date': end, 'period': 'weekly', 'pickup_day': '4', # Friday (Feb 2) 'cutoff_day': '0', }) self.assertTrue(order.exists()) # Pickup should be in Feb self.assertEqual(order.pickup_date.month, 2) def test_all_seven_days_as_pickup(self): """Test each day of week (0-6) as valid pickup_day.""" start = date(2024, 1, 1) # Monday end = date(2024, 1, 8) for day_num in range(7): order = self.env['group.order'].create({ 'name': f'Pickup Day {day_num}', 'group_ids': [(6, 0, [self.group.id])], 'type': 'regular', 'start_date': start, 'end_date': end, 'period': 'weekly', 'pickup_day': str(day_num), 'cutoff_day': '0', }) self.assertTrue(order.exists()) # Each should have valid pickup_date self.assertTrue(order.pickup_date) class TestFutureStartDateOrders(TransactionCase): """Test orders that start in the future.""" def setUp(self): super().setUp() self.group = self.env['res.partner'].create({ 'name': 'Test Group', 'is_company': True, }) def test_order_starts_tomorrow(self): """Test order starting tomorrow.""" today = date.today() start = today + timedelta(days=1) end = start + timedelta(days=7) order = self.env['group.order'].create({ 'name': 'Future Order', 'group_ids': [(6, 0, [self.group.id])], 'type': 'regular', 'start_date': start, 'end_date': end, 'period': 'weekly', 'pickup_day': '3', 'cutoff_day': '0', }) self.assertTrue(order.exists()) self.assertGreater(order.start_date, today) def test_order_starts_6_months_future(self): """Test order starting 6 months from now.""" today = date.today() start = today + relativedelta(months=6) end = start + timedelta(days=30) order = self.env['group.order'].create({ 'name': 'Far Future Order', 'group_ids': [(6, 0, [self.group.id])], 'type': 'regular', 'start_date': start, 'end_date': end, 'period': 'monthly', 'pickup_day': '15', 'cutoff_day': '10', }) self.assertTrue(order.exists()) class TestExtremeDate(TransactionCase): """Test edge cases with very old or very new dates.""" def setUp(self): super().setUp() self.group = self.env['res.partner'].create({ 'name': 'Test Group', 'is_company': True, }) def test_order_year_2000(self): """Test order in year 2000 (Y2K edge case).""" start = date(2000, 1, 1) end = date(2000, 12, 31) order = self.env['group.order'].create({ 'name': 'Y2K Order', 'group_ids': [(6, 0, [self.group.id])], 'type': 'regular', 'start_date': start, 'end_date': end, 'period': 'weekly', 'pickup_day': '3', 'cutoff_day': '0', }) self.assertTrue(order.exists()) def test_order_far_future_2099(self): """Test order in far future (year 2099).""" start = date(2099, 1, 1) end = date(2099, 12, 31) order = self.env['group.order'].create({ 'name': 'Far Future Order', 'group_ids': [(6, 0, [self.group.id])], 'type': 'regular', 'start_date': start, 'end_date': end, 'period': 'weekly', 'pickup_day': '3', 'cutoff_day': '0', }) self.assertTrue(order.exists()) def test_order_crossing_century(self): """Test order spanning century boundary (Dec 1999 to Jan 2000).""" start = date(1999, 12, 26) end = date(2000, 1, 2) order = self.env['group.order'].create({ 'name': 'Century Order', 'group_ids': [(6, 0, [self.group.id])], 'type': 'regular', 'start_date': start, 'end_date': end, 'period': 'weekly', 'pickup_day': '6', # Saturday 'cutoff_day': '0', }) self.assertTrue(order.exists()) # Should handle date arithmetic correctly across years self.assertEqual(order.start_date.year, 1999) self.assertEqual(order.end_date.year, 2000) class TestOrderWithoutEndDate(TransactionCase): """Test orders without explicit end_date (permanent/ongoing).""" def setUp(self): super().setUp() self.group = self.env['res.partner'].create({ 'name': 'Test Group', 'is_company': True, }) def test_permanent_order_with_null_end_date(self): """Test order with end_date = NULL (ongoing order).""" start = date.today() order = self.env['group.order'].create({ 'name': 'Permanent Order', 'group_ids': [(6, 0, [self.group.id])], 'type': 'regular', 'start_date': start, 'end_date': False, # No end date 'period': 'weekly', 'pickup_day': '3', 'cutoff_day': '0', }) # If supported, should handle gracefully # Otherwise, may be optional validation class TestPickupCalculationAccuracy(TransactionCase): """Test accuracy of pickup_date calculations.""" def setUp(self): super().setUp() self.group = self.env['res.partner'].create({ 'name': 'Test Group', 'is_company': True, }) def test_pickup_date_calculation_multiple_weeks(self): """Test pickup_date calculation over multiple weeks.""" # Week 1: Jan 1-7 (Mon-Sun), pickup Thursday = Jan 4 start = date(2024, 1, 1) end = date(2024, 1, 22) order = self.env['group.order'].create({ 'name': 'Multi-Week Pickup', 'group_ids': [(6, 0, [self.group.id])], 'type': 'regular', 'start_date': start, 'end_date': end, 'period': 'weekly', 'pickup_day': '3', # Thursday 'cutoff_day': '0', }) self.assertTrue(order.exists()) # First pickup should be first Thursday on or after start self.assertEqual(order.pickup_date.weekday(), 3) def test_monthly_order_pickup_date(self): """Test pickup_date for monthly orders.""" # Order runs Feb 1 - Mar 31, pickup on 15th start = date(2024, 2, 1) end = date(2024, 3, 31) order = self.env['group.order'].create({ 'name': 'Monthly Order', 'group_ids': [(6, 0, [self.group.id])], 'type': 'regular', 'start_date': start, 'end_date': end, 'period': 'monthly', 'pickup_day': '15', 'cutoff_day': '10', }) self.assertTrue(order.exists()) # First pickup should be Feb 15 self.assertGreaterEqual(order.pickup_date.day, 15)