- Add mypy.ini configuration to exclude migration scripts - Rename migration files to proper snake_case (post-migration.py → post_migration.py) - Add __init__.py to migration directories for proper Python package structure - Add new portal access tests for website_sale_aplicoop - Code formatting improvements (black, isort) - Update copilot instructions and project configuration Related to previous code quality refactoring work.
506 lines
15 KiB
Python
506 lines
15 KiB
Python
# 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)
|