diff --git a/src/servala/core/odoo.py b/src/servala/core/odoo.py index baeff4c..3d98e18 100644 --- a/src/servala/core/odoo.py +++ b/src/servala/core/odoo.py @@ -1,6 +1,7 @@ import xmlrpc.client from django.conf import settings +from django_scopes import scopes_disabled ADDRESS_FIELDS = [ "id", @@ -116,9 +117,7 @@ def get_odoo_countries(): return COUNTRIES -def get_invoice_addresses(user): - """Used during organization creation: retrieves all invoice - addresses the user owns or is connected to from the Odoo API.""" +def get_odoo_access_conditions(user): # We’re building our conditions in order: # - in exceptions, users may be using a billing account’s email # - if the user is an admin or owner of a Servala organization @@ -134,17 +133,6 @@ def get_invoice_addresses(user): email = user.email or_conditions = [("email", "ilike", email)] - servala_invoice_ids = list( - OrganizationMembership.objects.filter( - user=user, role__in=[OrganizationRole.ADMIN, OrganizationRole.OWNER] - ) - .values_list("organization__billing_entity__odoo_invoice_id", flat=True) - .distinct() - ) - servala_invoice_ids = [pk for pk in servala_invoice_ids if pk] - if servala_invoice_ids: - or_conditions.append(("id", "in", servala_invoice_ids)) - odoo_users = CLIENT.search_read( model="res.users", domain=[("login", "=", email), ("active", "=", True)], @@ -155,8 +143,9 @@ def get_invoice_addresses(user): if odoo_users: odoo_user = odoo_users[0] if odoo_user.get("share") is False: - # An Odoo internal user (share=False) should see all invoice addresses. - or_conditions = [] + # An Odoo internal user (share=False) should see all invoice addresses, + # so we short-circuit the entire search logic here + return [] elif uid := odoo_user.get("id"): # For portal users or users not in Odoo, apply standard filters. or_conditions.append(("create_uid", "=", uid)) @@ -174,13 +163,28 @@ def get_invoice_addresses(user): for contact in odoo_contacts: or_conditions.append(("parent_id", "=", contact["parent_id"][0])) + with scopes_disabled(): + servala_invoice_ids = list( + OrganizationMembership.objects.filter( + user=user, role__in=[OrganizationRole.ADMIN, OrganizationRole.OWNER] + ) + .values_list("organization__billing_entity__odoo_invoice_id", flat=True) + .distinct() + ) + servala_invoice_ids = [pk for pk in servala_invoice_ids if pk] + if servala_invoice_ids: + or_conditions.append(("id", "in", servala_invoice_ids)) + if len(or_conditions) > 1: or_conditions = ["|"] * (len(or_conditions) - 1) + or_conditions + return or_conditions - # The domain requires the partner to be an invoice address, that is: - # Of the company_type=person, and type=invoice. - # If we were searching for an existing organization, we would also have to - # filter for parent_id=odoo_company_id + +def get_invoice_addresses(user): + """Used during organization creation: retrieves all invoice + addresses the user owns or is connected to from the Odoo API.""" + + or_conditions = get_odoo_access_conditions(user) domain = [ ("company_type", "=", "person"), ("type", "=", "invoice"),