addons-cm/website_sale_aplicoop/tests/test_phase3_confirm_eskaera.py
snt ce393b6034 [FIX] TestConfirmEskaera_Integration: limpieza de decoradores @patch y corrección de bugs
- Convertir 4 tests de decorador @patch a context manager 'with patch(...)' para evitar RuntimeError en LocalProxy de Werkzeug
- Corregir patrón env(user=..., context=dict(...)) en Odoo 18 (sin .with_context())
- Agregar website real al mock para integración con helpers de pricing (_get_pricing_info)
- Añadir pickup_date en fixture de existing_order para que _find_recent_draft_order localice correctamente
- BUGFIX: Agregar (5,) a order_line para limpiar líneas previas al actualizar pedido existente

Resultado: 0 failed, 0 errors de 4 tests en Docker para TestConfirmEskaera_Integration

BREAKING: _create_or_update_sale_order ahora limpia las líneas anteriores con (5,) antes de asignar las nuevas cuando se actualiza un pedido existente. Comportamiento previo (duplicación de líneas) era un bug.
2026-04-08 17:26:57 +02:00

977 lines
34 KiB
Python

# Copyright 2026 - Today Criptomart
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
"""
Test suite for Phase 3 refactoring of confirm_eskaera().
Tests the 3 helper methods created in Phase 3:
- _validate_confirm_json(): Validates JSON request data
- _process_cart_items(): Processes cart items into sale.order lines
- _build_confirmation_message(): Builds localized confirmation messages
Includes tests for:
- Request validation with various error conditions
- Cart item processing with product context
- Multi-language message building (ES, EU, CA, GL, PT, FR, IT)
- Pickup vs delivery date handling
- Edge cases and error handling
"""
import json
from datetime import date
from datetime import timedelta
from types import SimpleNamespace
from unittest.mock import patch
from odoo.tests.common import TransactionCase
from odoo.addons.website_sale_aplicoop.controllers.website_sale import (
AplicoopWebsiteSale,
)
REQUEST_PATCH_TARGET = (
"odoo.addons.website_sale_aplicoop.controllers.website_sale.request"
)
def _make_json_response(data, headers=None, status=200):
"""Build a lightweight HTTP-like response object for controller tests."""
raw = data.encode("utf-8") if isinstance(data, str) else data
return SimpleNamespace(data=raw, status=status, headers=headers or [])
def _build_request_mock(env, payload=None, website=None):
"""Build a request mock compatible with the controller helpers/routes.
Args:
env: Odoo Environment to use as request.env.
payload: dict that will be JSON-encoded as request.httprequest.data.
website: Optional real website record. When not provided a minimal
SimpleNamespace stub is used (sufficient for tests that do not
call pricing helpers).
"""
if website is None:
website = SimpleNamespace(
_get_current_pricelist=lambda: False,
show_line_subtotals_tax_selection="tax_excluded",
fiscal_position_id=False,
company_id=False,
)
request_mock = SimpleNamespace(
env=env,
make_response=_make_json_response,
website=website,
)
if payload is not None:
request_mock.httprequest = SimpleNamespace(
data=json.dumps(payload).encode("utf-8")
)
return request_mock
class TestValidateConfirmJson(TransactionCase):
"""Test _validate_confirm_json() helper method."""
def setUp(self):
super().setUp()
self.controller = AplicoopWebsiteSale()
self.group_1 = self.env["res.partner"].create(
{
"name": "Consumer Group 1",
"is_company": True,
"is_group": True,
}
)
self.group_2 = self.env["res.partner"].create(
{
"name": "Consumer Group 2",
"is_company": True,
"is_group": True,
}
)
self.partner = self.env["res.partner"].create(
{
"name": "Phase 3 Member",
"email": "phase3-member@test.com",
}
)
self.group_2.member_ids = [(4, self.partner.id)]
self.user = self.env["res.users"].create(
{
"name": "Phase 3 User",
"login": "phase3-user@test.com",
"email": "phase3-user@test.com",
"partner_id": self.partner.id,
}
)
# Create test group order
self.group_order = self.env["group.order"].create(
{
"name": "Test Order Phase 3",
"state": "open",
"group_ids": [(6, 0, [self.group_1.id, self.group_2.id])],
"start_date": date.today(),
"end_date": date.today() + timedelta(days=7),
"cutoff_day": "3", # Thursday
"pickup_day": "5", # Saturday
}
)
def test_validate_confirm_json_success(self):
"""Test successful validation of confirm JSON data."""
request_mock = _build_request_mock(self.env(user=self.user))
data = {
"order_id": self.group_order.id,
"items": [{"product_id": 1, "quantity": 2, "product_price": 10.0}],
"is_delivery": False,
}
with patch(REQUEST_PATCH_TARGET, request_mock):
order_id, group_order, current_user, items, is_delivery = (
self.controller._validate_confirm_json(data)
)
self.assertEqual(order_id, self.group_order.id)
self.assertEqual(group_order.id, self.group_order.id)
self.assertEqual(current_user.id, self.user.id)
self.assertEqual(len(items), 1)
self.assertFalse(is_delivery)
def test_validate_confirm_json_missing_order_id(self):
"""Test validation fails without order_id."""
request_mock = _build_request_mock(self.env(user=self.user))
data = {"items": [{"product_id": 1, "quantity": 2}]}
with patch(REQUEST_PATCH_TARGET, request_mock):
with self.assertRaises(ValueError) as context:
self.controller._validate_confirm_json(data)
self.assertIn("order_id is required", str(context.exception))
def test_validate_confirm_json_order_not_exists(self):
"""Test validation fails with non-existent order."""
request_mock = _build_request_mock(self.env(user=self.user))
data = {
"order_id": 99999, # Non-existent ID
"items": [{"product_id": 1, "quantity": 2}],
}
with patch(REQUEST_PATCH_TARGET, request_mock):
with self.assertRaises(ValueError) as context:
self.controller._validate_confirm_json(data)
self.assertIn("Order", str(context.exception))
def test_validate_confirm_json_no_items(self):
"""Test validation fails without items in cart."""
request_mock = _build_request_mock(self.env(user=self.user))
data = {
"order_id": self.group_order.id,
"items": [],
}
with patch(REQUEST_PATCH_TARGET, request_mock):
with self.assertRaises(ValueError) as context:
self.controller._validate_confirm_json(data)
self.assertIn("No items in cart", str(context.exception))
def test_validate_confirm_json_with_delivery_flag(self):
"""Test validation correctly handles is_delivery flag."""
request_mock = _build_request_mock(self.env(user=self.user))
data = {
"order_id": self.group_order.id,
"items": [{"product_id": 1, "quantity": 1}],
"is_delivery": True,
}
with patch(REQUEST_PATCH_TARGET, request_mock):
_, _, _, _, is_delivery = self.controller._validate_confirm_json(data)
self.assertTrue(is_delivery)
def test_validate_confirm_json_user_without_matching_group(self):
"""Validation must fail if user is not in any allowed consumer group."""
other_partner = self.env["res.partner"].create(
{
"name": "Partner without matching group",
"email": "nogroup@test.com",
}
)
other_user = self.env["res.users"].create(
{
"name": "User without matching group",
"login": "nogroup-user@test.com",
"email": "nogroup-user@test.com",
"partner_id": other_partner.id,
}
)
request_mock = _build_request_mock(self.env(user=other_user))
data = {
"order_id": self.group_order.id,
"items": [{"product_id": 1, "quantity": 1}],
}
with patch(REQUEST_PATCH_TARGET, request_mock):
with self.assertRaises(ValueError) as context:
self.controller._validate_confirm_json(data)
self.assertIn(
"User is not a member of any consumer group in this order",
str(context.exception),
)
class TestConsumerGroupResolution(TransactionCase):
"""Tests for consumer group selection in multi-group orders."""
def setUp(self):
super().setUp()
self.controller = AplicoopWebsiteSale()
self.group_1 = self.env["res.partner"].create(
{
"name": "Group A",
"is_company": True,
"is_group": True,
}
)
self.group_2 = self.env["res.partner"].create(
{
"name": "Group B",
"is_company": True,
"is_group": True,
}
)
self.group_3 = self.env["res.partner"].create(
{
"name": "Group C",
"is_company": True,
"is_group": True,
}
)
self.partner = self.env["res.partner"].create(
{
"name": "Member B",
"email": "memberb@test.com",
}
)
self.group_2.member_ids = [(4, self.partner.id)]
self.user = self.env["res.users"].create(
{
"name": "Member B User",
"login": "memberb-user@test.com",
"email": "memberb-user@test.com",
"partner_id": self.partner.id,
}
)
self.product = self.env["product.product"].create(
{
"name": "Group Resolution Product",
"type": "consu",
"list_price": 10.0,
}
)
self.group_order = self.env["group.order"].create(
{
"name": "Multi-group order",
"state": "open",
"group_ids": [(6, 0, [self.group_1.id, self.group_2.id])],
"start_date": date.today(),
"end_date": date.today() + timedelta(days=7),
"cutoff_day": "1",
"pickup_day": "2",
}
)
self.sale_order_lines = [
(
0,
0,
{
"product_id": self.product.id,
"name": "Test line",
"product_uom_qty": 1,
"price_unit": 10.0,
},
)
]
def test_get_consumer_group_for_user_returns_matching_group(self):
"""Should resolve the user's own consumer group, not the first order group."""
consumer_group_id = self.controller._get_consumer_group_for_user(
self.group_order, self.user
)
self.assertEqual(consumer_group_id, self.group_2.id)
def test_get_consumer_group_for_user_uses_first_matching_order_group(self):
"""If user belongs to multiple valid groups, use the first in group_order."""
self.group_1.member_ids = [(4, self.partner.id)]
group_order = self.env["group.order"].create(
{
"name": "Multi-match order",
"state": "open",
"group_ids": [
(6, 0, [self.group_1.id, self.group_2.id, self.group_3.id])
],
}
)
consumer_group_id = self.controller._get_consumer_group_for_user(
group_order, self.user
)
self.assertEqual(consumer_group_id, self.group_1.id)
def test_create_or_update_sale_order_assigns_user_consumer_group(self):
"""Created sale.order must use the consumer group that matches the user."""
request_mock = _build_request_mock(self.env(user=self.user))
with patch(REQUEST_PATCH_TARGET, request_mock):
sale_order = self.controller._create_or_update_sale_order(
self.group_order,
self.user,
self.sale_order_lines,
is_delivery=False,
)
self.assertEqual(sale_order.consumer_group_id.id, self.group_2.id)
class TestProcessCartItems(TransactionCase):
"""Test _process_cart_items() helper method."""
def setUp(self):
super().setUp()
self.controller = AplicoopWebsiteSale()
# Create test products
self.product1 = self.env["product.product"].create(
{
"name": "Test Product 1",
"list_price": 15.0,
"type": "consu",
}
)
self.product2 = self.env["product.product"].create(
{
"name": "Test Product 2",
"list_price": 25.0,
"type": "consu",
}
)
self.group = self.env["res.partner"].create(
{
"name": "Cart Test Group",
"is_company": True,
"is_group": True,
}
)
# Create test group order
self.group_order = self.env["group.order"].create(
{
"name": "Test Order for Cart",
"state": "open",
"group_ids": [(6, 0, [self.group.id])],
"start_date": date.today(),
"end_date": date.today() + timedelta(days=7),
}
)
def test_process_cart_items_success(self):
"""Test successful cart item processing."""
request_mock = _build_request_mock(self.env.with_context(lang="es_ES"))
items = [
{
"product_id": self.product1.id,
"quantity": 2,
"product_price": 15.0,
},
{
"product_id": self.product2.id,
"quantity": 1,
"product_price": 25.0,
},
]
with patch(REQUEST_PATCH_TARGET, request_mock):
result = self.controller._process_cart_items(items, self.group_order)
self.assertEqual(len(result), 2)
self.assertEqual(result[0][0], 0) # Command (0, 0, vals)
self.assertEqual(result[0][1], 0)
self.assertIn("product_id", result[0][2])
self.assertEqual(result[0][2]["product_uom_qty"], 2)
self.assertEqual(result[0][2]["price_unit"], 15.0)
def test_process_cart_items_uses_list_price_fallback(self):
"""Test cart processing uses list_price when product_price is 0."""
request_mock = _build_request_mock(self.env.with_context(lang="es_ES"))
items = [
{
"product_id": self.product1.id,
"quantity": 1,
"product_price": 0, # Should fallback to list_price
}
]
with patch(REQUEST_PATCH_TARGET, request_mock):
result = self.controller._process_cart_items(items, self.group_order)
self.assertEqual(len(result), 1)
# Should use product.list_price as fallback
self.assertEqual(result[0][2]["price_unit"], self.product1.list_price)
def test_process_cart_items_skips_invalid_product(self):
"""Test cart processing skips non-existent products."""
request_mock = _build_request_mock(self.env.with_context(lang="es_ES"))
items = [
{
"product_id": 99999, # Non-existent
"quantity": 1,
"product_price": 10.0,
},
{
"product_id": self.product1.id,
"quantity": 2,
"product_price": 15.0,
},
]
with patch(REQUEST_PATCH_TARGET, request_mock):
result = self.controller._process_cart_items(items, self.group_order)
# Should only process the valid product
self.assertEqual(len(result), 1)
self.assertEqual(result[0][2]["product_id"], self.product1.id)
def test_process_cart_items_empty_after_filtering(self):
"""Test cart processing raises error when no valid items remain."""
request_mock = _build_request_mock(self.env.with_context(lang="es_ES"))
items = [{"product_id": 99999, "quantity": 1, "product_price": 10.0}]
with patch(REQUEST_PATCH_TARGET, request_mock):
with self.assertRaises(ValueError) as context:
self.controller._process_cart_items(items, self.group_order)
self.assertIn("No valid items", str(context.exception))
def test_process_cart_items_translates_product_name(self):
"""Test cart processing uses translated product names."""
request_mock = _build_request_mock(self.env.with_context(lang="eu_ES"))
# Add translation for product name
self.env["ir.translation"].create(
{
"type": "model",
"name": "product.product,name",
"module": "website_sale_aplicoop",
"lang": "eu_ES",
"res_id": self.product1.id,
"src": "Test Product 1",
"value": "Proba Produktua 1",
"state": "translated",
}
)
items = [
{
"product_id": self.product1.id,
"quantity": 1,
"product_price": 15.0,
}
]
with patch(REQUEST_PATCH_TARGET, request_mock):
result = self.controller._process_cart_items(items, self.group_order)
# Product name should be in Basque context
product_name = result[0][2]["name"]
self.assertIsNotNone(product_name)
# In real test, would be "Proba Produktua 1" but translation may not work in test
class TestBuildConfirmationMessage(TransactionCase):
"""Test _build_confirmation_message() helper method."""
def setUp(self):
super().setUp()
self.controller = AplicoopWebsiteSale()
self.user = self.env.ref("base.user_admin")
self.partner = self.env.ref("base.partner_admin")
self.group = self.env["res.partner"].create(
{
"name": "Message Test Group",
"is_company": True,
"is_group": True,
}
)
# Create test group order with dates
self.group_order = self.env["group.order"].create(
{
"name": "Test Order Messages",
"state": "open",
"group_ids": [(6, 0, [self.group.id])],
"start_date": date.today(),
"end_date": date.today() + timedelta(days=7),
"cutoff_day": "3",
"pickup_day": "5", # Saturday (0=Monday)
}
)
# Create test sale order
self.sale_order = self.env["sale.order"].create(
{
"partner_id": self.partner.id,
"group_order_id": self.group_order.id,
}
)
@patch(REQUEST_PATCH_TARGET)
def test_build_confirmation_message_pickup(self, mock_request):
"""Test confirmation message for pickup (not delivery)."""
mock_request.env = self.env.with_context(lang="es_ES")
result = self.controller._build_confirmation_message(
self.sale_order, self.group_order, is_delivery=False
)
self.assertIn("message", result)
self.assertIn("pickup_day", result)
self.assertIn("pickup_date", result)
self.assertIn("pickup_day_index", result)
# Should contain "Thank you" text (or translation)
self.assertIn("Thank you", result["message"])
# Should contain order reference
self.assertIn(self.sale_order.name, result["message"])
# Should have pickup day index
self.assertEqual(result["pickup_day_index"], 5)
@patch(REQUEST_PATCH_TARGET)
def test_build_confirmation_message_delivery(self, mock_request):
"""Test confirmation message for home delivery."""
mock_request.env = self.env.with_context(lang="es_ES")
result = self.controller._build_confirmation_message(
self.sale_order, self.group_order, is_delivery=True
)
self.assertIn("message", result)
# Should contain "Delivery date" label (or translation)
# and should use delivery_date, not pickup_date
message = result["message"]
self.assertIsNotNone(message)
# Delivery day should be next day after pickup (Saturday -> Sunday)
# pickup_day_index=5 (Saturday), delivery should be 6 (Sunday)
# Note: _get_day_names would need to be mocked for exact day name
@patch(REQUEST_PATCH_TARGET)
def test_build_confirmation_message_no_dates(self, mock_request):
"""Test confirmation message when no pickup date is set."""
mock_request.env = self.env.with_context(lang="es_ES")
# Create order without dates
group_order_no_dates = self.env["group.order"].create(
{
"name": "Order No Dates",
"state": "open",
"group_ids": [(6, 0, [self.group.id])],
}
)
sale_order_no_dates = self.env["sale.order"].create(
{
"partner_id": self.partner.id,
"group_order_id": group_order_no_dates.id,
}
)
result = self.controller._build_confirmation_message(
sale_order_no_dates, group_order_no_dates, is_delivery=False
)
# Should still build message without dates
self.assertIn("message", result)
self.assertIn("Thank you", result["message"])
# Date fields should be empty
self.assertEqual(result["pickup_date"], "")
@patch(REQUEST_PATCH_TARGET)
def test_build_confirmation_message_formats_date(self, mock_request):
"""Test confirmation message formats dates correctly (DD/MM/YYYY)."""
mock_request.env = self.env.with_context(lang="es_ES")
result = self.controller._build_confirmation_message(
self.sale_order, self.group_order, is_delivery=False
)
# Should have date in DD/MM/YYYY format
pickup_date_str = result["pickup_date"]
self.assertIsNotNone(pickup_date_str)
# Verify format with regex
date_pattern = r"\d{2}/\d{2}/\d{4}"
self.assertRegex(pickup_date_str, date_pattern)
@patch(REQUEST_PATCH_TARGET)
def test_build_confirmation_message_multilang_es(self, mock_request):
"""Test confirmation message in Spanish (es_ES)."""
mock_request.env = self.env.with_context(lang="es_ES")
result = self.controller._build_confirmation_message(
self.sale_order, self.group_order, is_delivery=False
)
message = result["message"]
# Should contain translated strings (if translations loaded)
self.assertIsNotNone(message)
# In real scenario, would check for "¡Gracias!" or similar
@patch(REQUEST_PATCH_TARGET)
def test_build_confirmation_message_multilang_eu(self, mock_request):
"""Test confirmation message in Basque (eu_ES)."""
mock_request.env = self.env.with_context(lang="eu_ES")
result = self.controller._build_confirmation_message(
self.sale_order, self.group_order, is_delivery=False
)
message = result["message"]
self.assertIsNotNone(message)
# In real scenario, would check for "Eskerrik asko!" or similar
@patch(REQUEST_PATCH_TARGET)
def test_build_confirmation_message_multilang_ca(self, mock_request):
"""Test confirmation message in Catalan (ca_ES)."""
mock_request.env = self.env.with_context(lang="ca_ES")
result = self.controller._build_confirmation_message(
self.sale_order, self.group_order, is_delivery=False
)
message = result["message"]
self.assertIsNotNone(message)
# In real scenario, would check for "Gràcies!" or similar
@patch(REQUEST_PATCH_TARGET)
def test_build_confirmation_message_multilang_gl(self, mock_request):
"""Test confirmation message in Galician (gl_ES)."""
mock_request.env = self.env.with_context(lang="gl_ES")
result = self.controller._build_confirmation_message(
self.sale_order, self.group_order, is_delivery=False
)
message = result["message"]
self.assertIsNotNone(message)
# In real scenario, would check for "Grazas!" or similar
@patch(REQUEST_PATCH_TARGET)
def test_build_confirmation_message_multilang_pt(self, mock_request):
"""Test confirmation message in Portuguese (pt_PT)."""
mock_request.env = self.env.with_context(lang="pt_PT")
result = self.controller._build_confirmation_message(
self.sale_order, self.group_order, is_delivery=False
)
message = result["message"]
self.assertIsNotNone(message)
# In real scenario, would check for "Obrigado!" or similar
@patch(REQUEST_PATCH_TARGET)
def test_build_confirmation_message_multilang_fr(self, mock_request):
"""Test confirmation message in French (fr_FR)."""
mock_request.env = self.env.with_context(lang="fr_FR")
result = self.controller._build_confirmation_message(
self.sale_order, self.group_order, is_delivery=False
)
message = result["message"]
self.assertIsNotNone(message)
# In real scenario, would check for "Merci!" or similar
@patch(REQUEST_PATCH_TARGET)
def test_build_confirmation_message_multilang_it(self, mock_request):
"""Test confirmation message in Italian (it_IT)."""
mock_request.env = self.env.with_context(lang="it_IT")
result = self.controller._build_confirmation_message(
self.sale_order, self.group_order, is_delivery=False
)
message = result["message"]
self.assertIsNotNone(message)
# In real scenario, would check for "Grazie!" or similar
class TestConfirmEskaera_Integration(TransactionCase):
"""Integration tests for confirm_eskaera() with all 3 helpers."""
def setUp(self):
super().setUp()
self.controller = AplicoopWebsiteSale()
self.consumer_group = self.env["res.partner"].create(
{
"name": "Integration Consumer Group",
"is_company": True,
"is_group": True,
}
)
self.partner = self.env["res.partner"].create(
{
"name": "Integration Member",
"email": "integration-member@test.com",
}
)
self.consumer_group.member_ids = [(4, self.partner.id)]
self.user = self.env["res.users"].create(
{
"name": "Integration User",
"login": "integration-user@test.com",
"email": "integration-user@test.com",
"partner_id": self.partner.id,
}
)
# Create test product
self.product = self.env["product.product"].create(
{
"name": "Integration Test Product",
"list_price": 20.0,
"type": "consu",
}
)
# Create test group order
self.group_order = self.env["group.order"].create(
{
"name": "Integration Test Order",
"state": "open",
"group_ids": [(6, 0, [self.consumer_group.id])],
"start_date": date.today(),
"end_date": date.today() + timedelta(days=7),
"cutoff_day": "3",
"pickup_day": "5",
"home_delivery": True,
}
)
# Use the real website so pricing helpers can resolve company/fiscal pos
self.website = self.env["website"].search([], limit=1)
def test_confirm_eskaera_full_flow_pickup(self):
"""Test full confirm_eskaera flow for pickup order."""
data = {
"order_id": self.group_order.id,
"items": [
{
"product_id": self.product.id,
"quantity": 3,
"product_price": 20.0,
}
],
"is_delivery": False,
}
mock_request = _build_request_mock(
self.env(user=self.user, context=dict(self.env.context, lang="es_ES")),
data,
website=self.website,
)
with patch(REQUEST_PATCH_TARGET, mock_request):
response = self.controller.confirm_eskaera.__wrapped__(self.controller)
# Verify response
self.assertIsNotNone(response)
response_data = json.loads(response.data.decode("utf-8"))
self.assertTrue(response_data.get("success"))
self.assertIn("message", response_data)
self.assertIn("sale_order_id", response_data)
# Verify sale.order was created
sale_order_id = response_data["sale_order_id"]
sale_order = self.env["sale.order"].browse(sale_order_id)
self.assertTrue(sale_order.exists())
self.assertEqual(sale_order.partner_id.id, self.partner.id)
self.assertEqual(sale_order.group_order_id.id, self.group_order.id)
self.assertEqual(len(sale_order.order_line), 1)
self.assertEqual(sale_order.order_line[0].product_uom_qty, 3)
self.assertFalse(sale_order.home_delivery)
self.assertEqual(
sale_order.commitment_date.date(),
self.group_order.pickup_date,
)
def test_confirm_eskaera_full_flow_delivery(self):
"""Test full confirm_eskaera flow for delivery order."""
# Add delivery_date to group order
self.group_order.delivery_date = self.group_order.pickup_date + timedelta(
days=1
)
data = {
"order_id": self.group_order.id,
"items": [
{
"product_id": self.product.id,
"quantity": 2,
"product_price": 20.0,
}
],
"is_delivery": True,
}
mock_request = _build_request_mock(
self.env(user=self.user, context=dict(self.env.context, lang="es_ES")),
data,
website=self.website,
)
with patch(REQUEST_PATCH_TARGET, mock_request):
response = self.controller.confirm_eskaera.__wrapped__(self.controller)
# Verify response
response_data = json.loads(response.data.decode("utf-8"))
self.assertTrue(response_data.get("success"))
# Verify sale.order has delivery flag
sale_order_id = response_data["sale_order_id"]
sale_order = self.env["sale.order"].browse(sale_order_id)
self.assertTrue(sale_order.home_delivery)
# commitment_date should be delivery_date
self.assertEqual(
sale_order.commitment_date.date(), self.group_order.delivery_date
)
def test_confirm_eskaera_updates_existing_draft(self):
"""Test confirm_eskaera updates existing draft order instead of creating new."""
# Create existing draft order
existing_order = self.env["sale.order"].create(
{
"partner_id": self.partner.id,
"group_order_id": self.group_order.id,
"state": "draft",
# pickup_date must match group_order.pickup_date so
# _find_recent_draft_order can locate this draft
"pickup_date": self.group_order.pickup_date,
"order_line": [
(
0,
0,
{
"product_id": self.product.id,
"product_uom_qty": 1,
"price_unit": 20.0,
},
)
],
}
)
existing_order_id = existing_order.id
data = {
"order_id": self.group_order.id,
"items": [
{
"product_id": self.product.id,
"quantity": 5, # Different quantity
"product_price": 20.0,
}
],
"is_delivery": False,
}
mock_request = _build_request_mock(
self.env(user=self.user, context=dict(self.env.context, lang="es_ES")),
data,
website=self.website,
)
with patch(REQUEST_PATCH_TARGET, mock_request):
response = self.controller.confirm_eskaera.__wrapped__(self.controller)
response_data = json.loads(response.data.decode("utf-8"))
# Should update existing order, not create new
self.assertEqual(response_data["sale_order_id"], existing_order_id)
# Verify order was updated
existing_order.invalidate_recordset()
self.assertEqual(len(existing_order.order_line), 1)
self.assertEqual(existing_order.order_line[0].product_uom_qty, 5)
def test_confirm_eskaera_ignores_old_period_draft(self):
"""Old draft from previous pickup_date must not be reused."""
old_draft = self.env["sale.order"].create(
{
"partner_id": self.partner.id,
"group_order_id": self.group_order.id,
"state": "draft",
"pickup_date": date.today() - timedelta(days=7),
"order_line": [
(
0,
0,
{
"product_id": self.product.id,
"product_uom_qty": 1,
"price_unit": 20.0,
},
)
],
}
)
data = {
"order_id": self.group_order.id,
"items": [
{
"product_id": self.product.id,
"quantity": 4,
"product_price": 20.0,
}
],
"is_delivery": False,
}
mock_request = _build_request_mock(
self.env(user=self.user, context=dict(self.env.context, lang="es_ES")),
data,
website=self.website,
)
with patch(REQUEST_PATCH_TARGET, mock_request):
response = self.controller.confirm_eskaera.__wrapped__(self.controller)
response_data = json.loads(response.data.decode("utf-8"))
self.assertTrue(response_data.get("success"))
self.assertNotEqual(response_data["sale_order_id"], old_draft.id)
old_draft.invalidate_recordset()
self.assertEqual(old_draft.state, "draft")
self.assertEqual(old_draft.order_line[0].product_uom_qty, 1)