Files
centurion_erp/app/access/models/tenancy_abstract.py

126 lines
3.1 KiB
Python

from django.core.exceptions import (
ValidationError,
)
from django.db import models
from access.models.tenancy import (
TenancyManager as TenancyManagerDepreciated
)
from access.models.tenant import Tenant
class TenancyManager(
models.Manager
):
"""Multi-Tennant Object Manager
This manager specifically caters for the multi-tenancy features of Centurion ERP.
"""
def get_queryset(self):
""" Fetch the data
When the model contains the user data, the query is filtered to their
and the globally defined Tenancy only.
Returns:
(queryset): **super user**: return unfiltered data.
(queryset): **not super user**: return data from the stored unique organizations.
"""
user = None # When CenturionUser in use
if hasattr(self.model, 'context'):
user = self.model.context['user']
has_tenant_field = False
if getattr(self.model, 'organization', None) is not None:
has_tenant_field = True
if user:
tenancies = user.get_tenancies(int_list = True)
if len(tenancies) > 0 and not request.user.is_superuser:
if has_tenant_field:
return super().get_queryset().select_related('organization').filter(
models.Q(organization__in = tenancies)
)
return super().get_queryset().filter()
if has_tenant_field:
return super().get_queryset().select_related('organization')
return super().get_queryset()
class TenancyAbstractModel(
models.Model,
):
""" Tenancy Model Abstract class.
This class is for inclusion within **every** model within Centurion ERP.
Provides the required fields, functions and methods for multi tennant objects.
Unless otherwise stated, **no** object within this class may be overridden.
Raises:
ValidationError: User failed to supply organization
"""
objects = TenancyManagerDepreciated()
""" ~~Multi-Tenant Manager~~
**Note:** ~~This manager relies upon the model class having `context['user']`
set. without a user the manager can not perform multi-tenant queries.~~
"""
class Meta:
abstract = True
def validatate_organization_exists(self):
"""Ensure that the user did provide an organization
Raises:
ValidationError: User failed to supply organization.
"""
if not self:
raise ValidationError(
code = 'required',
message = 'You must provide an organization'
)
organization = models.ForeignKey(
Tenant,
blank = False,
help_text = 'Tenant this belongs to',
null = False,
on_delete = models.CASCADE,
related_name = '+',
validators = [
validatate_organization_exists
],
verbose_name = 'Tenant'
)
def get_tenant(self) -> Tenant:
""" Return the models Tenancy
This model can be safely over-ridden as long as it returns the models
tenancy
"""
return self.organization