Coverage for core/models/organization.py: 100.00%
47 statements
« prev ^ index » next coverage.py v7.8.0, created at 2025-06-06 22:17 +0000
« prev ^ index » next coverage.py v7.8.0, created at 2025-06-06 22:17 +0000
1import uuid
3from django.db import models, transaction
4from django.forms.models import model_to_dict
5from django.utils import timezone
7from phone_field import PhoneField
9from core.models import core as core_models
10from core.models import user as core_user_models
11from project.models import git_repository as git_repository_models
12from project.models import project as project_models
15class OrganizationData(core_models.CoreModel):
16 """
17 Information about an Organization, both past and present.
18 """
20 class Meta:
21 ordering = ['-created_on', 'name']
23 name = models.CharField(max_length=255)
24 description = models.TextField(max_length=255, blank=True, null=True, default="")
25 responsible_party_email = models.EmailField(max_length=255)
26 responsible_party_phone = PhoneField()
27 address_line_1 = models.CharField(max_length=255)
28 address_line_2 = models.CharField(max_length=255, blank=True, null=True, default="")
29 postal_code = models.CharField(max_length=255)
30 city = models.CharField(max_length=255)
31 state = models.CharField(max_length=255)
32 country = models.CharField(max_length=255)
33 timezone = models.CharField(max_length=255, default=timezone.get_default_timezone_name())
35 is_paid = models.BooleanField(default=False)
36 renewal_date = models.DateField(blank=True, null=True)
37 number_users_allowed = models.IntegerField(default=5)
40class OrganizationActiveManager(models.Manager):
41 """
42 Active Organizations are not deleted.
43 """
45 def get_queryset(self):
46 return super().get_queryset().filter(deleted=None)
49class Organization(core_models.CoreModel):
50 """
51 An organization. The _real_ inforomation about an Organization is stored in `current` as OrganizationData.
53 Every time a user or a git repository or a project is added to an organization, a new OrganizationData object is created and the `current` field is updated to reflect the new data.
54 """
56 class Meta:
57 ordering = ['current__name']
59 active_objects = OrganizationActiveManager()
61 current = models.ForeignKey(OrganizationData, on_delete=models.CASCADE)
63 # TODO: Activity Tracking for tracking changes to these things
64 members = models.ManyToManyField(core_user_models.CoreUser, related_name='organizationmembers_set')
65 git_repositories = models.ManyToManyField(git_repository_models.GitRepository, related_name='organizationgitrepositories_set')
66 projects = models.ManyToManyField(project_models.Project, related_name='organizationprojects_set')
68 def update_organization_data(self, user_id: uuid.UUID, new_organization_data: dict) -> 'Organization':
69 """
70 Updates an organization's data. This is a helper function to illustrate the use of `current` retention since we do not delete data.
72 Args:
73 user_id (uuid): The ID of the user updating the organization.
74 organization_data (dictionary): The data to update in an organization.
76 Returns:
77 Organization: The updated organization.
78 """
80 with transaction.atomic():
81 current_organization_data = model_to_dict(self.current)
82 current_organization_data.update(new_organization_data)
83 current_organization_data['created_by_id'] = user_id
84 new_organization_data = OrganizationData.objects.create(**current_organization_data)
85 new_organization_data.save()
86 self.current = new_organization_data
87 self.save()
89 return self
91 def __str__(self) -> str:
92 return self.current.name