addons-cm/website_sale_aplicoop/tests/test_date_calculations.py
snt dbf5bd38b4 [TEST FIX] Resolver errores de tests en addons custom
CAMBIOS PRINCIPALES:
- Agregar field 'default_supplier_id' a product_main_seller (related a main_seller_id)
- Actualizar product_price_category_supplier tests para usar seller_ids (supplierinfo)
- Cambiar product type de 'product' a 'consu' en tests de account_invoice_triple_discount_readonly
- Crear product.template en lugar de product.product directamente en tests
- Corregir parámetros de _compute_price: 'qty' -> 'quantity'
- Comentar test de company_dependent que no puede ejecutarse sin migración

RESULTADOS:
- 193 tests totales (fue 172)
- 0 error(s) (fueron 5 en setUpClass)
- 10 failed (lógica de descuentos en account_invoice_triple_discount_readonly)
- 183 tests PASANDO

ADDONS PASANDO COMPLETAMENTE:
 product_main_seller: 9 tests
 product_price_category_supplier: 12 tests
 product_sale_price_from_pricelist: 47 tests
 website_sale_aplicoop: 111 tests
 account_invoice_triple_discount_readonly: 36/46 tests
2026-02-18 18:17:55 +01:00

569 lines
21 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Copyright 2026 Criptomart
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl)
from datetime import timedelta
from odoo import fields
from odoo.exceptions import ValidationError
from odoo.tests.common import TransactionCase
from odoo.tests.common import tagged
@tagged("post_install", "date_calculations")
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": "6", # Sunday (must be >= cutoff_day)
"cutoff_day": "5", # Saturday
}
)
# 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",
)
# === NEW REGRESSION TESTS (v18.0.1.3.1) ===
def test_cutoff_same_day_as_today_bug_fix(self):
"""Regression test: cutoff_date should allow same day as today.
Bug fixed in v18.0.1.3.1: Previously, if cutoff_day == today.weekday(),
the system would incorrectly add 7 days, scheduling cutoff for next week.
Now cutoff_date can be today if cutoff_day matches today's weekday.
"""
today = fields.Date.today()
cutoff_day = str(today.weekday()) # Same as today
order = self.env["group.order"].create(
{
"name": "Test Cutoff Today",
"group_ids": [(6, 0, [self.group.id])],
"start_date": today,
"cutoff_day": cutoff_day,
"period": "weekly",
}
)
# cutoff_date should be TODAY, not next week
self.assertEqual(
order.cutoff_date,
today,
f"Expected cutoff_date={today} (today), got {order.cutoff_date}. "
"Cutoff should be allowed on the same day.",
)
def test_delivery_date_stored_correctly(self):
"""Regression test: delivery_date must be stored in database.
Bug fixed in v18.0.1.3.1: delivery_date had store=False, causing
inconsistent values and inability to search/filter by this field.
Now delivery_date is stored (store=True).
"""
today = fields.Date.today()
# Set pickup for next Monday
days_until_monday = (0 - today.weekday()) % 7
if days_until_monday == 0:
days_until_monday = 7
start_date = today + timedelta(days=days_until_monday - 1)
order = self.env["group.order"].create(
{
"name": "Test Delivery Stored",
"group_ids": [(6, 0, [self.group.id])],
"start_date": start_date,
"pickup_day": "0", # Monday
"period": "weekly",
}
)
# Force computation
order._compute_pickup_date()
order._compute_delivery_date()
expected_delivery = order.pickup_date + timedelta(days=1)
self.assertEqual(
order.delivery_date,
expected_delivery,
f"Expected delivery_date={expected_delivery}, got {order.delivery_date}",
)
# Verify it's stored: read from database
order_from_db = self.env["group.order"].browse(order.id)
self.assertEqual(
order_from_db.delivery_date,
expected_delivery,
"delivery_date should be persisted in database (store=True)",
)
def test_constraint_cutoff_before_pickup_invalid(self):
"""Test constraint: pickup_day must be >= cutoff_day for weekly orders.
New constraint in v18.0.1.3.1: For weekly orders, if pickup_day < cutoff_day
numerically, it creates an illogical scenario where pickup would be
scheduled before cutoff in the same week cycle.
"""
today = fields.Date.today()
# Invalid configuration: pickup (Tuesday=1) < cutoff (Thursday=3)
with self.assertRaises(
ValidationError,
msg="Should raise ValidationError for pickup_day < cutoff_day",
):
self.env["group.order"].create(
{
"name": "Invalid Order",
"group_ids": [(6, 0, [self.group.id])],
"start_date": today,
"cutoff_day": "3", # Thursday
"pickup_day": "1", # Tuesday (BEFORE Thursday)
"period": "weekly",
}
)
def test_constraint_cutoff_before_pickup_valid(self):
"""Test constraint allows valid configurations.
Valid scenarios:
- pickup_day > cutoff_day: pickup is after cutoff ✓
- pickup_day == cutoff_day: same day allowed ✓
"""
today = fields.Date.today()
# Valid: pickup (Saturday=5) > cutoff (Tuesday=1)
order1 = self.env["group.order"].create(
{
"name": "Valid Order 1",
"group_ids": [(6, 0, [self.group.id])],
"start_date": today,
"cutoff_day": "1", # Tuesday
"pickup_day": "5", # Saturday (AFTER Tuesday)
"period": "weekly",
}
)
self.assertTrue(order1.id, "Valid configuration should create order")
# Valid: pickup == cutoff (same day)
order2 = self.env["group.order"].create(
{
"name": "Valid Order 2",
"group_ids": [(6, 0, [self.group.id])],
"start_date": today,
"cutoff_day": "5", # Saturday
"pickup_day": "5", # Saturday (SAME DAY)
"period": "weekly",
}
)
self.assertTrue(order2.id, "Same day configuration should be allowed")
def test_all_weekday_combinations_consistency(self):
"""Test that all valid weekday combinations produce consistent results.
This regression test ensures the date calculation logic works correctly
for all 49 combinations of start_date × pickup_day (7 × 7).
"""
today = fields.Date.today()
errors = []
for start_offset in range(7): # 7 possible start days
start_date = today + timedelta(days=start_offset)
for pickup_weekday in range(7): # 7 possible pickup days
order = self.env["group.order"].create(
{
"name": f"Test S{start_offset}P{pickup_weekday}",
"group_ids": [(6, 0, [self.group.id])],
"start_date": start_date,
"pickup_day": str(pickup_weekday),
"period": "weekly",
}
)
# Validate pickup_date is set
if not order.pickup_date:
errors.append(
f"start_offset={start_offset}, pickup_day={pickup_weekday}: "
f"pickup_date is None"
)
continue
# Validate pickup_date is in the future or today
if order.pickup_date < start_date:
errors.append(
f"start_offset={start_offset}, pickup_day={pickup_weekday}: "
f"pickup_date {order.pickup_date} < start_date {start_date}"
)
# Validate pickup_date weekday matches pickup_day
if order.pickup_date.weekday() != pickup_weekday:
errors.append(
f"start_offset={start_offset}, pickup_day={pickup_weekday}: "
f"pickup_date weekday is {order.pickup_date.weekday()}, "
f"expected {pickup_weekday}"
)
self.assertEqual(
len(errors),
0,
f"Found {len(errors)} errors in weekday combinations:\n"
+ "\n".join(errors),
)
def test_cron_update_dates_executes(self):
"""Test that cron job method executes without errors.
New feature in v18.0.1.3.1: Daily cron job to recalculate dates
for active orders to keep them up-to-date as time passes.
"""
today = fields.Date.today()
# Create multiple orders in different states
orders = []
for i, state in enumerate(["draft", "open", "closed"]):
order = self.env["group.order"].create(
{
"name": f"Test Cron Order {state}",
"group_ids": [(6, 0, [self.group.id])],
"start_date": today,
"pickup_day": str((i + 1) % 7),
"cutoff_day": str(i % 7),
"period": "weekly",
"state": state,
}
)
orders.append(order)
# Execute cron method (should not raise errors)
try:
self.env["group.order"]._cron_update_dates()
except Exception as e:
self.fail(f"Cron method raised exception: {e}")
# Verify dates are still valid for active orders
active_orders = [o for o in orders if o.state in ["draft", "open"]]
for order in active_orders:
self.assertIsNotNone(
order.pickup_date,
f"Pickup date should be set for active order {order.name}",
)