126 lines
3.1 KiB
Python
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 |