add website_membership_associate

This commit is contained in:
Luis 2026-07-28 09:29:14 +02:00
parent 40d7cc8772
commit 31d53c428c
12 changed files with 837 additions and 0 deletions

View file

@ -0,0 +1,3 @@
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
from . import test_website_membership_associate

View file

@ -0,0 +1,277 @@
# Copyright 2026 Criptomart
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
from odoo import fields
from odoo.tests import HttpCase, tagged
from odoo.addons.membership.tests.common import TestMembershipCommon
@tagged("post_install", "-at_install")
class TestWebsiteMembershipAssociate(HttpCase, TestMembershipCommon):
@classmethod
def setUpClass(cls):
super().setUpClass()
cls.website = cls.env.ref("website.default_website")
cls.country_us = cls.env.ref("base.us")
cls.country_be = cls.env.ref("base.be")
cls.membership_1.write({"website_published": True})
cls.partner_1.write(
{
"website_published": True,
"is_company": True,
"country_id": cls.country_us.id,
}
)
invoice = cls.partner_1.create_membership_invoice(cls.membership_1, 75.0)
invoice.action_post()
cls.env["account.payment.register"].with_context(
active_model="account.move", active_ids=invoice.ids
).create(
{
"amount": 86.25,
"payment_method_line_id": cls.inbound_payment_method_line.id,
}
)._create_payments()
cls.partner_1._compute_membership_state()
cls.associate = cls.env["res.partner"].create(
{
"name": "Associate Paid",
"associate_member": cls.partner_1.id,
"website_published": True,
"is_company": True,
"country_id": cls.country_be.id,
"website_description": "Sustainable farming",
}
)
cls.partner_2.write(
{
"website_published": True,
"is_company": True,
"country_id": cls.country_us.id,
}
)
cls.associate_free = cls.env["res.partner"].create(
{
"name": "Associate Free",
"associate_member": cls.partner_2.id,
"website_published": True,
"is_company": True,
"country_id": cls.country_us.id,
}
)
def test_host_membership_state_is_paid(self):
self.assertEqual(self.partner_1.membership_state, "paid")
def test_members_page_lists_host_and_associate(self):
response = self.url_open("/members")
self.assertEqual(response.status_code, 200)
self.assertIn(self.partner_1.name, response.text)
self.assertIn(self.associate.name, response.text)
def test_membership_filter_includes_associate(self):
response = self.url_open("/members/association/%d" % self.membership_1.id)
self.assertEqual(response.status_code, 200)
self.assertIn(self.partner_1.name, response.text)
self.assertIn(self.associate.name, response.text)
def test_free_membership_filter_includes_associate(self):
response = self.url_open("/members/association/free")
self.assertEqual(response.status_code, 200)
self.assertIn(self.partner_2.name, response.text)
self.assertIn(self.associate_free.name, response.text)
def test_country_filter_counts_associate(self):
response = self.url_open("/members/country/%d" % self.country_be.id)
self.assertEqual(response.status_code, 200)
self.assertIn(self.associate.name, response.text)
self.assertNotIn(self.partner_1.name, response.text)
self.assertNotIn(self.partner_2.name, response.text)
self.assertNotIn(self.associate_free.name, response.text)
def test_search_finds_associate(self):
response = self.url_open("/members?search=Sustainable+farming")
self.assertEqual(response.status_code, 200)
self.assertIn(self.associate.name, response.text)
self.assertNotIn(self.partner_1.name, response.text)
def test_published_companies_map_includes_associate(self):
host_line = self.partner_1.member_lines[0]
companies = host_line._get_published_companies(limit=2000)
self.assertIn(self.partner_1.id, companies)
self.assertIn(self.associate.id, companies)
@tagged("post_install", "-at_install")
class TestWebsiteMembershipAssociatePagination(HttpCase, TestMembershipCommon):
@classmethod
def setUpClass(cls):
super().setUpClass()
cls.website = cls.env.ref("website.default_website")
cls.country_es = cls.env.ref("base.es")
cls.membership_1.write({"website_published": True})
host_vals = [
{
"name": "Host Page %d" % i,
"website_published": True,
"is_company": True,
"country_id": cls.country_es.id,
}
for i in range(20)
]
cls.paginated_hosts = cls.env["res.partner"].create(host_vals)
invoices = cls.paginated_hosts.create_membership_invoice(
cls.membership_1, 75.0
)
invoices.action_post()
cls.env["account.payment.register"].with_context(
active_model="account.move", active_ids=invoices.ids
).create(
{
"amount": sum(invoices.mapped("amount_total")),
"payment_method_line_id": cls.inbound_payment_method_line.id,
}
)._create_payments()
cls.paginated_hosts._compute_membership_state()
associate_vals = [
{
"name": "Associate Page %d" % i,
"associate_member": cls.paginated_hosts[i].id,
"website_published": True,
"is_company": True,
"country_id": cls.country_es.id,
}
for i in range(20)
]
cls.paginated_associates = cls.env["res.partner"].create(associate_vals)
def test_pagination_hosts_plus_associates(self):
response = self.url_open("/members/association/%d" % self.membership_1.id)
self.assertEqual(response.status_code, 200)
# Page 1 contains all 20 hosts plus their 20 associates.
self.assertIn("Host Page 0", response.text)
self.assertIn("Host Page 19", response.text)
self.assertIn("Associate Page 0", response.text)
self.assertIn("Associate Page 19", response.text)
# No pagination placeholder from a second page is expected.
self.assertNotIn("Host Page 20", response.text)
self.assertNotIn("Associate Page 20", response.text)
@tagged("post_install", "-at_install")
class TestMembershipLineAssociate(TestMembershipCommon):
@classmethod
def setUpClass(cls):
super().setUpClass()
cls.country_us = cls.env.ref("base.us")
cls.country_be = cls.env.ref("base.be")
cls.membership_1.write({"website_published": True})
cls.partner_1.write(
{
"website_published": True,
"is_company": True,
"country_id": cls.country_us.id,
"website_description": "Host description",
}
)
invoice = cls.partner_1.create_membership_invoice(cls.membership_1, 75.0)
invoice.action_post()
cls.env["account.payment.register"].with_context(
active_model="account.move", active_ids=invoice.ids
).create(
{
"amount": invoice.amount_total,
"payment_method_line_id": cls.inbound_payment_method_line.id,
}
)._create_payments()
cls.partner_1._compute_membership_state()
cls.associate = cls.env["res.partner"].create(
{
"name": "Associate Paid",
"associate_member": cls.partner_1.id,
"website_published": True,
"is_company": True,
"country_id": cls.country_be.id,
"website_description": "Sustainable farming",
}
)
def _base_domain(self):
today = fields.Date.today()
return [
("partner.website_published", "=", True),
("state", "=", "paid"),
("date_to", ">=", today),
("date_from", "<=", today),
("membership_id", "in", self.membership_1.ids),
]
def test_search_excludes_host_when_only_associate_matches_without_context(self):
domain = self._base_domain()
domain += [
"|",
("partner.name", "ilike", "Sustainable farming"),
("partner.website_description", "ilike", "Sustainable farming"),
]
lines = self.env["membership.membership_line"].search(domain)
self.assertNotIn(self.partner_1.id, lines.partner.ids)
def test_search_includes_host_when_associate_name_matches(self):
domain = self._base_domain()
domain += [
"|",
("partner.name", "ilike", "Sustainable farming"),
("partner.website_description", "ilike", "Sustainable farming"),
]
lines = (
self.env["membership.membership_line"]
.with_context(include_associate_members=True)
.search(domain)
)
self.assertIn(self.partner_1.id, lines.partner.ids)
def test_search_includes_host_when_associate_country_matches(self):
domain = self._base_domain()
domain.append(("partner.country_id", "=", self.country_be.id))
lines = (
self.env["membership.membership_line"]
.with_context(include_associate_members=True)
.search(domain)
)
self.assertIn(self.partner_1.id, lines.partner.ids)
def test_get_associate_partners_filters_by_country(self):
MembershipLine = self.env["membership.membership_line"]
match = MembershipLine._get_associate_partners(
(self.partner_1.id,), country_id=self.country_be.id
)
self.assertEqual(match, self.associate)
no_match = MembershipLine._get_associate_partners(
(self.partner_1.id,), country_id=self.country_us.id
)
self.assertFalse(no_match)
def test_get_associate_partners_filters_by_search(self):
MembershipLine = self.env["membership.membership_line"]
match = MembershipLine._get_associate_partners(
(self.partner_1.id,), post_name="Sustainable"
)
self.assertEqual(match, self.associate)
no_match = MembershipLine._get_associate_partners(
(self.partner_1.id,), post_name="Nonexistent"
)
self.assertFalse(no_match)
def test_published_companies_includes_associate(self):
host_line = self.partner_1.member_lines[0]
companies = host_line._get_published_companies(limit=2000)
self.assertIn(self.partner_1.id, companies)
self.assertIn(self.associate.id, companies)