Initialize Django project #8
2 changed files with 109 additions and 0 deletions
15
src/servala/core/models/__init__.py
Normal file
15
src/servala/core/models/__init__.py
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
from .organization import (
|
||||||
|
BillingEntity,
|
||||||
|
Organization,
|
||||||
|
OrganizationMembership,
|
||||||
|
OrganizationOrigin,
|
||||||
|
OrganizationRole,
|
||||||
|
)
|
||||||
|
|
||||||
|
__all__ = [
|
||||||
|
"BillingEntity",
|
||||||
|
"Organization",
|
||||||
|
"OrganizationMembership",
|
||||||
|
"OrganizationOrigin",
|
||||||
|
"OrganizationRole",
|
||||||
|
]
|
94
src/servala/core/models/organization.py
Normal file
94
src/servala/core/models/organization.py
Normal file
|
@ -0,0 +1,94 @@
|
||||||
|
from django.contrib.auth import get_user_model
|
||||||
|
from django.db import models
|
||||||
|
from django.utils.translation import gettext_lazy as _
|
||||||
|
|
||||||
|
|
||||||
|
class Organization(models.Model):
|
||||||
|
name = models.CharField(max_length=100, verbose_name=_("Name"))
|
||||||
|
|
||||||
|
billing_entity = models.ForeignKey(
|
||||||
|
to="BillingEntity",
|
||||||
|
on_delete=models.PROTECT,
|
||||||
|
related_name="organizations",
|
||||||
|
verbose_name=_("Billing entity"),
|
||||||
|
)
|
||||||
|
origin = models.ForeignKey(
|
||||||
|
to="OrganizationOrigin",
|
||||||
|
on_delete=models.PROTECT,
|
||||||
|
related_name="organizations",
|
||||||
|
verbose_name=_("Origin"),
|
||||||
|
)
|
||||||
|
|
||||||
|
members = models.ManyToManyField(
|
||||||
|
to=get_user_model(),
|
||||||
|
through="OrganizationMembership",
|
||||||
|
related_name="organizations",
|
||||||
|
verbose_name=_("Members"),
|
||||||
|
)
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return self.name
|
||||||
|
|
||||||
|
|
||||||
|
class BillingEntity(models.Model):
|
||||||
|
"""
|
||||||
|
Every organization has a billing entity, though billing entities
|
||||||
|
may be shared across different organizations.
|
||||||
|
"""
|
||||||
|
|
||||||
|
name = models.CharField(max_length=100, verbose_name=_("Name"))
|
||||||
|
description = models.TextField(blank=True, verbose_name=_("Description"))
|
||||||
|
erp_reference = models.CharField(
|
||||||
|
max_length=100, blank=True, verbose_name=_("ERP reference")
|
||||||
|
)
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return self.name
|
||||||
|
|
||||||
|
|
||||||
|
class OrganizationOrigin(models.Model):
|
||||||
|
"""
|
||||||
|
Every organization has an origin, though origins may be
|
||||||
|
shared across different organizations.
|
||||||
|
"""
|
||||||
|
|
||||||
|
name = models.CharField(max_length=100, verbose_name=_("Name"))
|
||||||
|
description = models.TextField(blank=True, verbose_name=_("Description"))
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return self.name
|
||||||
|
|
||||||
|
|
||||||
|
class OrganizationRole(models.TextChoices):
|
||||||
|
MEMBER = "member", _("Member")
|
||||||
|
ADMIN = "admin", _("Administrator")
|
||||||
|
OWNER = "owner", _("Owner")
|
||||||
|
|
||||||
|
|
||||||
|
class OrganizationMembership(models.Model):
|
||||||
|
"""Through-model for the many-to-many relationship between organizations and users."""
|
||||||
|
|
||||||
|
user = models.ForeignKey(
|
||||||
|
to=get_user_model(),
|
||||||
|
on_delete=models.CASCADE,
|
||||||
|
related_name="organization_memberships",
|
||||||
|
verbose_name=_("User"),
|
||||||
|
)
|
||||||
|
organization = models.ForeignKey(
|
||||||
|
to=Organization,
|
||||||
|
on_delete=models.CASCADE,
|
||||||
|
related_name="memberships",
|
||||||
|
verbose_name=_("Organization"),
|
||||||
|
)
|
||||||
|
date_joined = models.DateTimeField(
|
||||||
|
verbose_name=_("Date joined"), auto_now_add=True, editable=False
|
||||||
|
)
|
||||||
|
role = models.CharField(
|
||||||
|
max_length=20,
|
||||||
|
choices=OrganizationRole.choices,
|
||||||
|
default=OrganizationRole.MEMBER,
|
||||||
|
verbose_name=_("Role"),
|
||||||
|
)
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return f"{self.user} in {self.organization} as {self.role}"
|
Loading…
Add table
Add a link
Reference in a new issue