addons-cm/website_sale_aplicoop/tests/test_endpoints.py
2026-02-11 15:32:11 +01:00

523 lines
18 KiB
Python

# Copyright 2025 Criptomart
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl)
"""
Test suite for HTTP endpoints in website_sale_aplicoop controllers.
Coverage:
- /eskaera (GET) - View all group orders
- /eskaera/<id> (GET) - View specific group order
- /eskaera/<id>/add-to-cart (POST) - Add product to cart
- /eskaera/<id>/checkout (GET) - Checkout page
- /eskaera/<id>/checkout (POST) - Save cart items
- /eskaera/confirm (POST) - Confirm order
- /eskaera/<id>/confirm/<sale_id> (POST) - Confirm order from portal
- /eskaera/<id>/load-from-history/<sale_id> (POST) - Load draft order
- /eskaera/labels (GET) - Get translated labels
"""
from datetime import datetime, timedelta
import json
from odoo.tests.common import TransactionCase, HttpCase
from odoo.exceptions import ValidationError, AccessError
class TestEskaearaListEndpoint(TransactionCase):
"""Test /eskaera endpoint (list all group orders)."""
def setUp(self):
super().setUp()
self.group = self.env['res.partner'].create({
'name': 'Test Group',
'is_company': True,
'email': 'group@test.com',
})
self.member_partner = self.env['res.partner'].create({
'name': 'Group Member',
'email': 'member@test.com',
})
self.group.member_ids = [(4, self.member_partner.id)]
self.user = self.env['res.users'].create({
'name': 'Test User',
'login': 'testuser@test.com',
'email': 'testuser@test.com',
'partner_id': self.member_partner.id,
})
# Create multiple group orders (some open, some closed)
start_date = datetime.now().date()
self.open_order = self.env['group.order'].create({
'name': 'Open Order',
'group_ids': [(6, 0, [self.group.id])],
'type': 'regular',
'start_date': start_date,
'end_date': start_date + timedelta(days=7),
'period': 'weekly',
'pickup_day': '3',
'cutoff_day': '0',
})
self.open_order.action_open()
self.draft_order = self.env['group.order'].create({
'name': 'Draft Order',
'group_ids': [(6, 0, [self.group.id])],
'type': 'regular',
'start_date': start_date - timedelta(days=14),
'end_date': start_date - timedelta(days=7),
'period': 'weekly',
'pickup_day': '3',
'cutoff_day': '0',
})
# Stay in draft
self.closed_order = self.env['group.order'].create({
'name': 'Closed Order',
'group_ids': [(6, 0, [self.group.id])],
'type': 'regular',
'start_date': start_date - timedelta(days=21),
'end_date': start_date - timedelta(days=14),
'period': 'weekly',
'pickup_day': '3',
'cutoff_day': '0',
})
self.closed_order.action_open()
self.closed_order.action_close()
def test_eskaera_list_shows_only_open_and_draft_orders(self):
"""Test that /eskaera shows only open/draft orders, not closed."""
# In controller context, only open and draft should be visible to members
# This is business logic: closed orders are historical
visible_orders = self.env['group.order'].search([
('state', 'in', ['open', 'draft']),
('group_ids', 'in', self.group.id),
])
self.assertIn(self.open_order, visible_orders)
self.assertIn(self.draft_order, visible_orders)
self.assertNotIn(self.closed_order, visible_orders)
def test_eskaera_list_filters_by_user_groups(self):
"""Test that user only sees orders from their groups."""
other_group = self.env['res.partner'].create({
'name': 'Other Group',
'is_company': True,
'email': 'other@test.com',
})
other_order = self.env['group.order'].create({
'name': 'Other Group Order',
'group_ids': [(6, 0, [other_group.id])],
'type': 'regular',
'start_date': datetime.now().date(),
'end_date': datetime.now().date() + timedelta(days=7),
'period': 'weekly',
'pickup_day': '3',
'cutoff_day': '0',
})
other_order.action_open()
# User should not see orders from groups they're not in
user_groups = self.member_partner.group_ids
visible_orders = self.env['group.order'].search([
('state', 'in', ['open', 'draft']),
('group_ids', 'in', user_groups.ids),
])
self.assertNotIn(other_order, visible_orders)
class TestAddToCartEndpoint(TransactionCase):
"""Test /eskaera/<id>/add-to-cart endpoint."""
def setUp(self):
super().setUp()
self.group = self.env['res.partner'].create({
'name': 'Test Group',
'is_company': True,
'email': 'group@test.com',
})
self.member_partner = self.env['res.partner'].create({
'name': 'Group Member',
'email': 'member@test.com',
})
self.group.member_ids = [(4, self.member_partner.id)]
self.user = self.env['res.users'].create({
'name': 'Test User',
'login': 'testuser@test.com',
'email': 'testuser@test.com',
'partner_id': self.member_partner.id,
})
self.category = self.env['product.category'].create({
'name': 'Test Category',
})
# Published product
self.product = self.env['product.product'].create({
'name': 'Test Product',
'type': 'consu',
'list_price': 10.0,
'categ_id': self.category.id,
'sale_ok': True,
'is_published': True,
})
# Unpublished product (should not be available)
self.unpublished_product = self.env['product.product'].create({
'name': 'Unpublished Product',
'type': 'consu',
'list_price': 15.0,
'categ_id': self.category.id,
'sale_ok': False,
'is_published': False,
})
start_date = datetime.now().date()
self.group_order = self.env['group.order'].create({
'name': 'Test Order',
'group_ids': [(6, 0, [self.group.id])],
'type': 'regular',
'start_date': start_date,
'end_date': start_date + timedelta(days=7),
'period': 'weekly',
'pickup_day': '3',
'cutoff_day': '0',
})
self.group_order.action_open()
self.group_order.product_ids = [(4, self.product.id)]
def test_add_to_cart_published_product(self):
"""Test adding published product to cart."""
# Simulate controller logic
cart_line = {
'product_id': self.product.id,
'quantity': 2,
'group_order_id': self.group_order.id,
'partner_id': self.member_partner.id,
}
# Should succeed
self.assertTrue(cart_line['product_id'])
def test_add_to_cart_zero_quantity(self):
"""Test that adding zero quantity is rejected."""
# Edge case: quantity = 0
quantity = 0
# Controller should validate: quantity > 0
self.assertFalse(quantity > 0)
def test_add_to_cart_negative_quantity(self):
"""Test that negative quantity is rejected."""
quantity = -5
# Controller should validate: quantity > 0
self.assertFalse(quantity > 0)
def test_add_to_cart_unpublished_product(self):
"""Test that unpublished products cannot be added."""
# Product must be published and sale_ok=True
self.assertFalse(self.unpublished_product.is_published)
self.assertFalse(self.unpublished_product.sale_ok)
def test_add_to_cart_product_not_in_order(self):
"""Test that products not in the order cannot be added."""
# Create a product NOT associated with group_order
other_product = self.env['product.product'].create({
'name': 'Other Product',
'type': 'consu',
'list_price': 25.0,
})
# Controller should check: product in group_order.product_ids
self.assertNotIn(other_product, self.group_order.product_ids)
def test_add_to_cart_order_closed(self):
"""Test that adding to closed order is rejected."""
self.group_order.action_close()
# Controller should check: order.state == 'open'
self.assertEqual(self.group_order.state, 'closed')
class TestCheckoutEndpoint(TransactionCase):
"""Test /eskaera/<id>/checkout endpoint."""
def setUp(self):
super().setUp()
self.group = self.env['res.partner'].create({
'name': 'Test Group',
'is_company': True,
'email': 'group@test.com',
})
self.member_partner = self.env['res.partner'].create({
'name': 'Group Member',
'email': 'member@test.com',
})
self.group.member_ids = [(4, self.member_partner.id)]
self.user = self.env['res.users'].create({
'name': 'Test User',
'login': 'testuser@test.com',
'email': 'testuser@test.com',
'partner_id': self.member_partner.id,
})
start_date = datetime.now().date()
self.group_order = self.env['group.order'].create({
'name': 'Test Order',
'group_ids': [(6, 0, [self.group.id])],
'type': 'regular',
'start_date': start_date,
'end_date': start_date + timedelta(days=7),
'period': 'weekly',
'pickup_day': '3',
'pickup_date': start_date + timedelta(days=3),
'cutoff_day': '0',
})
self.group_order.action_open()
def test_checkout_page_loads(self):
"""Test that checkout page renders correctly."""
# Controller should render template with group_order context
self.assertTrue(self.group_order.exists())
def test_checkout_displays_pickup_date(self):
"""Test that checkout shows correct pickup date."""
# Controller should calculate pickup_date from pickup_day
self.assertTrue(self.group_order.pickup_date)
def test_checkout_displays_home_delivery_option(self):
"""Test that checkout shows home delivery option."""
# Controller should pass home_delivery flag to template
self.assertIsNotNone(self.group_order.home_delivery)
def test_checkout_order_without_products(self):
"""Test checkout when no products available."""
# Order with empty product_ids
empty_order = self.env['group.order'].create({
'name': 'Empty Order',
'group_ids': [(6, 0, [self.group.id])],
'type': 'regular',
'start_date': datetime.now().date(),
'end_date': datetime.now().date() + timedelta(days=7),
'period': 'weekly',
'pickup_day': '3',
'cutoff_day': '0',
})
empty_order.action_open()
# Should handle gracefully
self.assertEqual(len(empty_order.product_ids), 0)
class TestConfirmOrderEndpoint(TransactionCase):
"""Test /eskaera/confirm endpoint (confirm final order)."""
def setUp(self):
super().setUp()
self.group = self.env['res.partner'].create({
'name': 'Test Group',
'is_company': True,
'email': 'group@test.com',
})
self.member_partner = self.env['res.partner'].create({
'name': 'Group Member',
'email': 'member@test.com',
})
self.group.member_ids = [(4, self.member_partner.id)]
self.user = self.env['res.users'].create({
'name': 'Test User',
'login': 'testuser@test.com',
'email': 'testuser@test.com',
'partner_id': self.member_partner.id,
})
self.category = self.env['product.category'].create({
'name': 'Test Category',
})
self.product = self.env['product.product'].create({
'name': 'Test Product',
'type': 'consu',
'list_price': 10.0,
'categ_id': self.category.id,
})
start_date = datetime.now().date()
self.group_order = self.env['group.order'].create({
'name': 'Test Order',
'group_ids': [(6, 0, [self.group.id])],
'type': 'regular',
'start_date': start_date,
'end_date': start_date + timedelta(days=7),
'period': 'weekly',
'pickup_day': '3',
'pickup_date': start_date + timedelta(days=3),
'cutoff_day': '0',
})
self.group_order.action_open()
self.group_order.product_ids = [(4, self.product.id)]
# Create a draft sale order
self.draft_sale = self.env['sale.order'].create({
'partner_id': self.member_partner.id,
'group_order_id': self.group_order.id,
'pickup_date': self.group_order.pickup_date,
'state': 'draft',
})
def test_confirm_order_creates_sale_order(self):
"""Test that confirming creates a confirmed sale.order."""
# Controller should change state from draft to sale
self.draft_sale.action_confirm()
self.assertEqual(self.draft_sale.state, 'sale')
def test_confirm_empty_order(self):
"""Test confirming order without items fails."""
# Order with no order_lines should fail
empty_sale = self.env['sale.order'].create({
'partner_id': self.member_partner.id,
'group_order_id': self.group_order.id,
'state': 'draft',
})
# Should validate: must have at least one line
self.assertEqual(len(empty_sale.order_line), 0)
def test_confirm_order_wrong_group(self):
"""Test that user cannot confirm order from different group."""
other_group = self.env['res.partner'].create({
'name': 'Other Group',
'is_company': True,
})
other_order = self.env['group.order'].create({
'name': 'Other Order',
'group_ids': [(6, 0, [other_group.id])],
'type': 'regular',
'start_date': datetime.now().date(),
'end_date': datetime.now().date() + timedelta(days=7),
'period': 'weekly',
'pickup_day': '3',
'cutoff_day': '0',
})
# User should not be in other_group
self.assertNotIn(self.member_partner, other_group.member_ids)
class TestLoadDraftEndpoint(TransactionCase):
"""Test /eskaera/<id>/load-from-history/<sale_id> endpoint."""
def setUp(self):
super().setUp()
self.group = self.env['res.partner'].create({
'name': 'Test Group',
'is_company': True,
'email': 'group@test.com',
})
self.member_partner = self.env['res.partner'].create({
'name': 'Group Member',
'email': 'member@test.com',
})
self.group.member_ids = [(4, self.member_partner.id)]
self.user = self.env['res.users'].create({
'name': 'Test User',
'login': 'testuser@test.com',
'email': 'testuser@test.com',
'partner_id': self.member_partner.id,
})
self.category = self.env['product.category'].create({
'name': 'Test Category',
})
self.product = self.env['product.product'].create({
'name': 'Test Product',
'type': 'consu',
'list_price': 10.0,
'categ_id': self.category.id,
})
start_date = datetime.now().date()
self.group_order = self.env['group.order'].create({
'name': 'Test Order',
'group_ids': [(6, 0, [self.group.id])],
'type': 'regular',
'start_date': start_date,
'end_date': start_date + timedelta(days=7),
'period': 'weekly',
'pickup_day': '3',
'pickup_date': start_date + timedelta(days=3),
'cutoff_day': '0',
})
self.group_order.action_open()
self.group_order.product_ids = [(4, self.product.id)]
def test_load_draft_from_history(self):
"""Test loading a previous draft order."""
# Create old draft sale
old_sale = self.env['sale.order'].create({
'partner_id': self.member_partner.id,
'group_order_id': self.group_order.id,
'state': 'draft',
})
# Should be able to load
self.assertTrue(old_sale.exists())
def test_load_draft_not_owned_by_user(self):
"""Test that user cannot load draft from other user."""
other_partner = self.env['res.partner'].create({
'name': 'Other Member',
'email': 'other@test.com',
})
other_sale = self.env['sale.order'].create({
'partner_id': other_partner.id,
'group_order_id': self.group_order.id,
'state': 'draft',
})
# User should not be able to load other's draft
self.assertNotEqual(other_sale.partner_id, self.member_partner)
def test_load_draft_expired_order(self):
"""Test loading draft from expired group order."""
old_start = datetime.now().date() - timedelta(days=30)
old_end = datetime.now().date() - timedelta(days=23)
expired_order = self.env['group.order'].create({
'name': 'Expired Order',
'group_ids': [(6, 0, [self.group.id])],
'type': 'regular',
'start_date': old_start,
'end_date': old_end,
'period': 'weekly',
'pickup_day': '3',
'cutoff_day': '0',
})
expired_order.action_open()
expired_order.action_close()
old_sale = self.env['sale.order'].create({
'partner_id': self.member_partner.id,
'group_order_id': expired_order.id,
'state': 'draft',
})
# Should warn: order expired
self.assertEqual(expired_order.state, 'closed')