# 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 date from datetime import timedelta from dateutil.relativedelta import relativedelta from odoo.exceptions import ValidationError # noqa: F401 from odoo.tests.common import TransactionCase 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() 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)