adfc28dd22f22b281ab28666f1bc7cf8421ee55d
[pharos-tools.git] / dashboard / src / booking / models.py
1 ##############################################################################
2 # Copyright (c) 2016 Max Breitenfeldt and others.
3 # Copyright (c) 2018 Sawyer Bergeron, Parker Berberian, and others.
4 #
5 # All rights reserved. This program and the accompanying materials
6 # are made available under the terms of the Apache License, Version 2.0
7 # which accompanies this distribution, and is available at
8 # http://www.apache.org/licenses/LICENSE-2.0
9 ##############################################################################
10
11
12 from resource_inventory.models import ResourceBundle, ConfigBundle
13 from account.models import Lab
14 from django.conf import settings
15 from django.contrib.auth.models import User
16 from django.db import models
17 from jira import JIRA
18 from jira import JIRAError
19 import resource_inventory.resource_manager
20
21
22 class Scenario(models.Model):
23     id = models.AutoField(primary_key=True)
24     name = models.CharField(max_length=300)
25
26     def __str__(self):
27         return self.name
28
29
30 class Installer(models.Model):
31     id = models.AutoField(primary_key=True)
32     name = models.CharField(max_length=30)
33     sup_scenarios = models.ManyToManyField(Scenario, blank=True)
34
35     def __str__(self):
36         return self.name
37
38
39 class Opsys(models.Model):
40     id = models.AutoField(primary_key=True)
41     name = models.CharField(max_length=100)
42     sup_installers = models.ManyToManyField(Installer, blank=True)
43
44     def __str__(self):
45         return self.name
46
47
48 class Booking(models.Model):
49     id = models.AutoField(primary_key=True)
50     owner = models.ForeignKey(User, models.CASCADE, related_name='owner')  # delete if user is deleted
51     collaborators = models.ManyToManyField(User, related_name='collaborators')
52     start = models.DateTimeField()
53     end = models.DateTimeField()
54     reset = models.BooleanField(default=False)
55     jira_issue_id = models.IntegerField(null=True, blank=True)
56     jira_issue_status = models.CharField(max_length=50, blank=True)
57     purpose = models.CharField(max_length=300, blank=False)
58     ext_count = models.IntegerField(default=2)
59     resource = models.ForeignKey(ResourceBundle, on_delete=models.SET_NULL, null=True) #need to decide behavior here on delete
60     config_bundle = models.ForeignKey(ConfigBundle, on_delete=models.SET_NULL, null=True)
61     project = models.CharField(max_length=100, default="", blank=True, null=True)
62     lab = models.ForeignKey(Lab, null=True, on_delete=models.SET_NULL)
63
64     class Meta:
65         db_table = 'booking'
66
67     def save(self, *args, **kwargs):
68         """
69         Save the booking if self.user is authorized and there is no overlapping booking.
70         Raise PermissionError if the user is not authorized
71         Raise ValueError if there is an overlapping booking
72         """
73         if self.start >= self.end:
74             raise ValueError('Start date is after end date')
75         # conflicts end after booking starts, and start before booking ends
76         conflicting_dates = Booking.objects.filter(resource=self.resource).exclude(id=self.id)
77         conflicting_dates = conflicting_dates.filter(end__gt=self.start)
78         conflicting_dates = conflicting_dates.filter(start__lt=self.end)
79         if conflicting_dates.count() > 0:
80             raise ValueError('This booking overlaps with another booking')
81         return super(Booking, self).save(*args, **kwargs)
82
83     def delete(self, *args, **kwargs):
84         res = self.resource
85         self.resource = None
86         self.save()
87         resource_inventory.resource_manager.ResourceManager.getInstance().deleteResourceBundle(res)
88         return super(self.__class__, self).delete(*args, **kwargs)
89
90     def __str__(self):
91         return str(self.purpose) + ' from ' + str(self.start) + ' until ' + str(self.end)