293 lines
10 KiB
Python
293 lines
10 KiB
Python
# Copyright 2026 Criptomart
|
|
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
|
|
|
|
from odoo import fields, http
|
|
from odoo.http import request
|
|
from odoo.tools.translate import _
|
|
|
|
from odoo.addons.website_membership.controllers.main import (
|
|
WebsiteMembership as BaseWebsiteMembership,
|
|
)
|
|
|
|
|
|
class WebsiteMembership(BaseWebsiteMembership):
|
|
@http.route()
|
|
def members(
|
|
self, membership_id=None, country_name=None, country_id=0, page=1, **post
|
|
):
|
|
request.env = request.env(
|
|
context=dict(request.env.context, include_associate_members=True)
|
|
)
|
|
response = super().members(
|
|
membership_id=membership_id,
|
|
country_name=country_name,
|
|
country_id=country_id,
|
|
page=page,
|
|
**post,
|
|
)
|
|
self._add_associate_members(response, membership_id, country_id, page, post)
|
|
return response
|
|
|
|
def _add_associate_members(
|
|
self, response, membership_id, country_id, page, post
|
|
):
|
|
values = response.qcontext
|
|
memberships_partner_ids = values.get("memberships_partner_ids", {})
|
|
if not memberships_partner_ids:
|
|
return
|
|
|
|
post_name = post.get("search") or post.get("name", "")
|
|
host_keys = {}
|
|
for key, ids in memberships_partner_ids.items():
|
|
for partner_id in ids:
|
|
host_keys.setdefault(partner_id, []).append(key)
|
|
host_ids = set(host_keys.keys())
|
|
hosts = {
|
|
pid: partner
|
|
for pid, partner in values.get("partners", {}).items()
|
|
if pid in host_ids
|
|
}
|
|
|
|
associates = (
|
|
request.env["membership.membership_line"]
|
|
.sudo()
|
|
._get_associate_partners(
|
|
tuple(host_ids), country_id=country_id, post_name=post_name
|
|
)
|
|
)
|
|
|
|
new_memberships_partner_ids = self._filter_displayed_hosts(
|
|
memberships_partner_ids, hosts, country_id, post_name
|
|
)
|
|
for associate in associates:
|
|
keys = host_keys.get(associate.associate_member.id)
|
|
if not keys:
|
|
continue
|
|
for key in keys:
|
|
if associate.id not in new_memberships_partner_ids[key]:
|
|
new_memberships_partner_ids[key].append(associate.id)
|
|
values["memberships_partner_ids"] = {
|
|
key: ids
|
|
for key, ids in new_memberships_partner_ids.items()
|
|
if ids
|
|
}
|
|
|
|
displayed_ids = set(
|
|
pid
|
|
for ids in values["memberships_partner_ids"].values()
|
|
for pid in ids
|
|
)
|
|
values["partners"] = {
|
|
p.id: p
|
|
for p in request.env["res.partner"]
|
|
.sudo()
|
|
.browse(list(displayed_ids))
|
|
}
|
|
|
|
all_host_ids, all_free_host_ids, all_associates = (
|
|
self._get_all_visible_ids(membership_id, country_id, post_name)
|
|
)
|
|
self._recompute_countries(
|
|
values, all_host_ids, all_free_host_ids, all_associates, country_id
|
|
)
|
|
self._update_google_map(values, country_id, post_name)
|
|
self._update_pager(
|
|
values,
|
|
membership_id,
|
|
country_id,
|
|
page,
|
|
post,
|
|
all_host_ids,
|
|
all_free_host_ids,
|
|
)
|
|
|
|
def _filter_displayed_hosts(
|
|
self, memberships_partner_ids, hosts, country_id, post_name
|
|
):
|
|
return {
|
|
key: [
|
|
pid
|
|
for pid in ids
|
|
if pid not in hosts
|
|
or self._partner_matches_filters(hosts[pid], country_id, post_name)
|
|
]
|
|
for key, ids in memberships_partner_ids.items()
|
|
}
|
|
|
|
def _partner_matches_filters(self, partner, country_id, post_name):
|
|
if country_id and partner.country_id.id != country_id:
|
|
return False
|
|
if post_name and not self._partner_matches_search(partner, post_name):
|
|
return False
|
|
return True
|
|
|
|
def _partner_matches_search(self, partner, post_name):
|
|
term = post_name.lower()
|
|
if term in (partner.name or "").lower():
|
|
return True
|
|
if term in (partner.website_description or "").lower():
|
|
return True
|
|
return False
|
|
|
|
def _get_all_visible_ids(self, membership_id, country_id, post_name):
|
|
free_selected = membership_id in (None, "free")
|
|
if membership_id == "free":
|
|
all_host_ids = set()
|
|
else:
|
|
all_host_ids = self._get_all_host_ids(
|
|
membership_id, country_id, post_name
|
|
)
|
|
all_free_host_ids = (
|
|
self._get_all_free_host_ids(country_id, post_name)
|
|
if free_selected
|
|
else set()
|
|
)
|
|
all_associates = (
|
|
request.env["membership.membership_line"]
|
|
.sudo()
|
|
._get_associate_partners(
|
|
tuple(all_host_ids | all_free_host_ids),
|
|
country_id=country_id,
|
|
post_name=post_name,
|
|
)
|
|
)
|
|
return all_host_ids, all_free_host_ids, all_associates
|
|
|
|
def _get_all_host_ids(self, membership_id, country_id, post_name):
|
|
Product = request.env["product.product"]
|
|
MembershipLine = request.env["membership.membership_line"]
|
|
today = fields.Date.today()
|
|
products = Product.sudo().search([("membership", "=", True)])
|
|
domain = [
|
|
("partner.website_published", "=", True),
|
|
("state", "=", "paid"),
|
|
("date_to", ">=", today),
|
|
("date_from", "<=", today),
|
|
("membership_id", "in", products.ids),
|
|
]
|
|
if membership_id and membership_id != "free":
|
|
domain.append(("membership_id", "=", int(membership_id)))
|
|
if post_name:
|
|
domain += [
|
|
"|",
|
|
("partner.name", "ilike", post_name),
|
|
("partner.website_description", "ilike", post_name),
|
|
]
|
|
if country_id:
|
|
domain.append(("partner.country_id", "=", country_id))
|
|
lines = MembershipLine.sudo().search(domain)
|
|
return set(lines.partner.ids)
|
|
|
|
def _get_all_free_host_ids(self, country_id, post_name):
|
|
domain = [
|
|
("membership_state", "=", "free"),
|
|
("website_published", "=", True),
|
|
]
|
|
if post_name:
|
|
domain += [
|
|
"|",
|
|
("name", "ilike", post_name),
|
|
("website_description", "ilike", post_name),
|
|
]
|
|
if country_id:
|
|
domain.append(("country_id", "=", country_id))
|
|
return set(request.env["res.partner"].sudo().search(domain).ids)
|
|
|
|
def _recompute_countries(
|
|
self, values, all_host_ids, all_free_host_ids, all_associates, country_id
|
|
):
|
|
visible_ids = all_host_ids | all_free_host_ids | set(all_associates.ids)
|
|
values["countries"] = self._build_countries(visible_ids, country_id)
|
|
|
|
def _build_countries(self, visible_ids, country_id):
|
|
Partner = request.env["res.partner"]
|
|
Country = request.env["res.country"]
|
|
current_country = None
|
|
countries = Partner.sudo().read_group(
|
|
[("id", "in", list(visible_ids))],
|
|
["__count"],
|
|
groupby="country_id",
|
|
)
|
|
countries_total = sum(
|
|
country_dict["country_id_count"] for country_dict in countries
|
|
)
|
|
if country_id:
|
|
current_country = Country.browse(country_id).read(["id", "name"])[0]
|
|
if not any(
|
|
x["country_id"] and x["country_id"][0] == country_id
|
|
for x in countries
|
|
):
|
|
countries.append(
|
|
{
|
|
"country_id_count": 0,
|
|
"country_id": (country_id, current_country["name"]),
|
|
}
|
|
)
|
|
countries = [d for d in countries if d["country_id"]]
|
|
countries.sort(key=lambda d: d["country_id"][1])
|
|
countries.insert(
|
|
0,
|
|
{
|
|
"country_id_count": countries_total,
|
|
"country_id": (0, _("All Countries")),
|
|
},
|
|
)
|
|
return countries
|
|
|
|
def _update_google_map(self, values, country_id, post_name):
|
|
map_ids_str = values.get("google_map_partner_ids", "")
|
|
if not map_ids_str:
|
|
return
|
|
map_ids = [int(pid) for pid in map_ids_str.split(",") if pid]
|
|
if not map_ids:
|
|
return
|
|
partners = request.env["res.partner"].sudo().browse(map_ids)
|
|
if country_id:
|
|
partners = partners.filtered(
|
|
lambda p: p.country_id.id == country_id
|
|
)
|
|
if post_name:
|
|
partners = partners.filtered(
|
|
lambda p: self._partner_matches_search(p, post_name)
|
|
)
|
|
values["google_map_partner_ids"] = ",".join(
|
|
str(pid) for pid in partners.ids
|
|
)
|
|
|
|
def _update_pager(
|
|
self,
|
|
values,
|
|
membership_id,
|
|
country_id,
|
|
page,
|
|
post,
|
|
all_host_ids,
|
|
all_free_host_ids,
|
|
):
|
|
post_name = post.get("search") or post.get("name", "")
|
|
if membership_id == "free":
|
|
displayed_host_ids = set()
|
|
else:
|
|
host_records = request.env["res.partner"].sudo().browse(
|
|
list(all_host_ids)
|
|
)
|
|
displayed_host_ids = {
|
|
host.id
|
|
for host in host_records
|
|
if self._partner_matches_filters(host, country_id, post_name)
|
|
}
|
|
count_members = len(displayed_host_ids) + len(all_free_host_ids)
|
|
limit = self._references_per_page
|
|
base_url = "/members%s%s" % (
|
|
"/association/%s" % membership_id if membership_id else "",
|
|
"/country/%s" % country_id if country_id else "",
|
|
)
|
|
values["pager"] = request.website.pager(
|
|
url=base_url,
|
|
total=count_members,
|
|
page=page,
|
|
step=limit,
|
|
scope=7,
|
|
url_args=post,
|
|
)
|
|
values["search_count"] = count_members
|