| 1 |  |  | from django.db import models | 
            
                                                                                                            
                            
            
                                    
            
            
                | 2 |  |  | from django.contrib.auth.models import User | 
            
                                                                                                            
                            
            
                                    
            
            
                | 3 |  |  | from django.contrib.contenttypes.fields import GenericForeignKey | 
            
                                                                                                            
                            
            
                                    
            
            
                | 4 |  |  | from django.contrib.contenttypes.models import ContentType | 
            
                                                                                                            
                            
            
                                    
            
            
                | 5 |  |  | from django.contrib.postgres.fields import JSONField | 
            
                                                                                                            
                            
            
                                    
            
            
                | 6 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 7 |  |  | from common.constants import STATUSES, WAITING, READY | 
            
                                                                                                            
                            
            
                                    
            
            
                | 8 |  |  | from uid.models import Submission as UIDSubmission | 
            
                                                                                                            
                            
            
                                    
            
            
                | 9 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 10 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 11 |  |  | # Create your models here. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 12 |  |  | class Account(models.Model): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 13 |  |  |     user = models.OneToOneField( | 
            
                                                                                                            
                            
            
                                    
            
            
                | 14 |  |  |         User, | 
            
                                                                                                            
                            
            
                                    
            
            
                | 15 |  |  |         on_delete=models.CASCADE, | 
            
                                                                                                            
                            
            
                                    
            
            
                | 16 |  |  |         related_name='biosample_account') | 
            
                                                                                                            
                            
            
                                    
            
            
                | 17 |  |  |     name = models.SlugField() | 
            
                                                                                                            
                            
            
                                    
            
            
                | 18 |  |  |     team = models.ForeignKey( | 
            
                                                                                                            
                            
            
                                    
            
            
                | 19 |  |  |         'ManagedTeam', | 
            
                                                                                                            
                            
            
                                    
            
            
                | 20 |  |  |         on_delete=models.CASCADE, | 
            
                                                                                                            
                            
            
                                    
            
            
                | 21 |  |  |         help_text="Your AAP Team") | 
            
                                                                                                            
                            
            
                                    
            
            
                | 22 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 23 |  |  |     def __str__(self): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 24 |  |  |         full_name = " ".join([self.user.first_name, self.user.last_name]) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 25 |  |  |         return "%s (%s)" % (self.name, full_name) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 26 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 27 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 28 |  |  | class ManagedTeam(models.Model): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 29 |  |  |     name = models.CharField(max_length=255, unique=True) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 30 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 31 |  |  |     @classmethod | 
            
                                                                                                            
                            
            
                                    
            
            
                | 32 |  |  |     def get_teams(cls): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 33 |  |  |         teams = cls.objects.all() | 
            
                                                                                                            
                            
            
                                    
            
            
                | 34 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 35 |  |  |         return [team.name for team in teams] | 
            
                                                                                                            
                            
            
                                    
            
            
                | 36 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 37 |  |  |     def __str__(self): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 38 |  |  |         return self.name | 
            
                                                                                                            
                            
            
                                    
            
            
                | 39 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 40 |  |  |     class Meta: | 
            
                                                                                                            
                            
            
                                    
            
            
                | 41 |  |  |         verbose_name = "managed team" | 
            
                                                                                                            
                            
            
                                    
            
            
                | 42 |  |  |         verbose_name_plural = "managed teams" | 
            
                                                                                                            
                            
            
                                    
            
            
                | 43 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 44 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 45 |  |  | class BaseSubmission(models.Model): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 46 |  |  |     usi_submission_name = models.CharField( | 
            
                                                                                                            
                            
            
                                    
            
            
                | 47 |  |  |         max_length=255, | 
            
                                                                                                            
                            
            
                                    
            
            
                | 48 |  |  |         blank=True, | 
            
                                                                                                            
                            
            
                                    
            
            
                | 49 |  |  |         null=True, | 
            
                                                                                                            
                            
            
                                    
            
            
                | 50 |  |  |         db_index=True, | 
            
                                                                                                            
                            
            
                                    
            
            
                | 51 |  |  |         unique=True, | 
            
                                                                                                            
                            
            
                                    
            
            
                | 52 |  |  |         help_text='USI submission name') | 
            
                                                                                                            
                            
            
                                    
            
            
                | 53 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 54 |  |  |     created_at = models.DateTimeField(auto_now_add=True) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 55 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 56 |  |  |     updated_at = models.DateTimeField(auto_now=True) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 57 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 58 |  |  |     # a field to track errors in UID loading. Should be blank if no errors | 
            
                                                                                                            
                            
            
                                    
            
            
                | 59 |  |  |     # are found | 
            
                                                                                                            
                            
            
                                    
            
            
                | 60 |  |  |     message = models.TextField( | 
            
                                                                                                            
                            
            
                                    
            
            
                | 61 |  |  |         null=True, | 
            
                                                                                                            
                            
            
                                    
            
            
                | 62 |  |  |         blank=True) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 63 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 64 |  |  |     # a column to track submission status | 
            
                                                                                                            
                            
            
                                    
            
            
                | 65 |  |  |     # HINT: should I limit by biosample status? | 
            
                                                                                                            
                            
            
                                    
            
            
                | 66 |  |  |     status = models.SmallIntegerField( | 
            
                                                                                                            
                            
            
                                    
            
            
                | 67 |  |  |         choices=[x.value for x in STATUSES], | 
            
                                                                                                            
                            
            
                                    
            
            
                | 68 |  |  |         help_text='example: Waiting', | 
            
                                                                                                            
                            
            
                                    
            
            
                | 69 |  |  |         default=WAITING) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 70 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 71 |  |  |     samples_count = models.PositiveIntegerField(default=0) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 72 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 73 |  |  |     samples_status = JSONField(default=dict) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 74 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 75 |  |  |     class Meta: | 
            
                                                                                                            
                            
            
                                    
            
            
                | 76 |  |  |         # Abstract base classes are useful when you want to put some common | 
            
                                                                                                            
                            
            
                                    
            
            
                | 77 |  |  |         # information into a number of other models | 
            
                                                                                                            
                            
            
                                    
            
            
                | 78 |  |  |         abstract = True | 
            
                                                                                                            
                            
            
                                    
            
            
                | 79 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 80 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 81 |  |  | class Submission(BaseSubmission): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 82 |  |  |     uid_submission = models.ForeignKey( | 
            
                                                                                                            
                            
            
                                    
            
            
                | 83 |  |  |         UIDSubmission, | 
            
                                                                                                            
                            
            
                                    
            
            
                | 84 |  |  |         on_delete=models.CASCADE, | 
            
                                                                                                            
                            
            
                                    
            
            
                | 85 |  |  |         related_name='usi_submissions') | 
            
                                                                                                            
                            
            
                                    
            
            
                | 86 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 87 |  |  |     def __str__(self): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 88 |  |  |         return "%s <%s> (%s): %s" % ( | 
            
                                                                                                            
                            
            
                                    
            
            
                | 89 |  |  |             self.id, | 
            
                                                                                                            
                            
            
                                    
            
            
                | 90 |  |  |             self.usi_submission_name, | 
            
                                                                                                            
                            
            
                                    
            
            
                | 91 |  |  |             self.uid_submission, | 
            
                                                                                                            
                            
            
                                    
            
            
                | 92 |  |  |             self.get_status_display()) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 93 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 94 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 95 |  |  | class SubmissionData(models.Model): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 96 |  |  |     submission = models.ForeignKey( | 
            
                                                                                                            
                            
            
                                    
            
            
                | 97 |  |  |         Submission, | 
            
                                                                                                            
                            
            
                                    
            
            
                | 98 |  |  |         on_delete=models.CASCADE, | 
            
                                                                                                            
                            
            
                                    
            
            
                | 99 |  |  |         related_name='submission_data') | 
            
                                                                                                            
                            
            
                                    
            
            
                | 100 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 101 |  |  |     # limit choices for contenttypes | 
            
                                                                                                            
                            
            
                                    
            
            
                | 102 |  |  |     # https://axiacore.com/blog/how-use-genericforeignkey-django-531/ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 103 |  |  |     name_limit = models.Q(app_label='uid', model='animal') | \ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 104 |  |  |         models.Q(app_label='uid', model='sample') | 
            
                                                                                                            
                            
            
                                    
            
            
                | 105 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 106 |  |  |     # Below the mandatory fields for generic relation | 
            
                                                                                                            
                            
            
                                    
            
            
                | 107 |  |  |     # https://simpleisbetterthancomplex.com/tutorial/2016/10/13/how-to-use-generic-relations.html | 
            
                                                                                                            
                            
            
                                    
            
            
                | 108 |  |  |     content_type = models.ForeignKey( | 
            
                                                                                                            
                            
            
                                    
            
            
                | 109 |  |  |         ContentType, | 
            
                                                                                                            
                            
            
                                    
            
            
                | 110 |  |  |         on_delete=models.CASCADE, | 
            
                                                                                                            
                            
            
                                    
            
            
                | 111 |  |  |         limit_choices_to=name_limit) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 112 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 113 |  |  |     object_id = models.PositiveIntegerField() | 
            
                                                                                                            
                            
            
                                    
            
            
                | 114 |  |  |     content_object = GenericForeignKey('content_type', 'object_id') | 
            
                                                                                                            
                            
            
                                    
            
            
                | 115 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 116 |  |  |     def __str__(self): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 117 |  |  |         return "%s <%s>: %s" % ( | 
            
                                                                                                            
                            
            
                                    
            
            
                | 118 |  |  |             self.submission.id, | 
            
                                                                                                            
                            
            
                                    
            
            
                | 119 |  |  |             self.submission.usi_submission_name, | 
            
                                                                                                            
                            
            
                                    
            
            
                | 120 |  |  |             self.content_object.name) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 121 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 122 |  |  |     class Meta: | 
            
                                                                                                            
                            
            
                                    
            
            
                | 123 |  |  |         verbose_name = "submission data" | 
            
                                                                                                            
                            
            
                                    
            
            
                | 124 |  |  |         verbose_name_plural = "submission data" | 
            
                                                                                                            
                            
            
                                    
            
            
                | 125 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 126 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 127 |  |  | class OrphanSubmission(BaseSubmission): | 
            
                                                                                                            
                                                                
            
                                    
            
            
                | 128 |  |  |  | 
            
                                                                        
                            
            
                                    
            
            
                | 129 |  |  |     def __str__(self): | 
            
                                                                        
                            
            
                                    
            
            
                | 130 |  |  |         return "%s <%s>: %s" % ( | 
            
                                                                        
                            
            
                                    
            
            
                | 131 |  |  |             self.id, | 
            
                                                                        
                            
            
                                    
            
            
                | 132 |  |  |             self.usi_submission_name, | 
            
                                                                        
                            
            
                                    
            
            
                | 133 |  |  |             self.get_status_display()) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 134 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 135 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 136 |  |  | class OrphanSample(models.Model): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 137 |  |  |     submission = models.ForeignKey( | 
            
                                                                                                            
                            
            
                                    
            
            
                | 138 |  |  |         OrphanSubmission, | 
            
                                                                                                            
                            
            
                                    
            
            
                | 139 |  |  |         on_delete=models.PROTECT, | 
            
                                                                                                            
                            
            
                                    
            
            
                | 140 |  |  |         null=True, | 
            
                                                                                                            
                            
            
                                    
            
            
                | 141 |  |  |         default=None, | 
            
                                                                                                            
                            
            
                                    
            
            
                | 142 |  |  |         blank=True, | 
            
                                                                                                            
                            
            
                                    
            
            
                | 143 |  |  |         related_name='submission_data') | 
            
                                                                                                            
                            
            
                                    
            
            
                | 144 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 145 |  |  |     # This will be assigned after submission | 
            
                                                                                                            
                            
            
                                    
            
            
                | 146 |  |  |     biosample_id = models.CharField( | 
            
                                                                                                            
                            
            
                                    
            
            
                | 147 |  |  |         max_length=255, | 
            
                                                                                                            
                            
            
                                    
            
            
                | 148 |  |  |         unique=True) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 149 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 150 |  |  |     found_at = models.DateTimeField(auto_now_add=True) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 151 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 152 |  |  |     ignore = models.BooleanField( | 
            
                                                                                                            
                            
            
                                    
            
            
                | 153 |  |  |         default=False, | 
            
                                                                                                            
                            
            
                                    
            
            
                | 154 |  |  |         help_text='Should I ignore this record or not?') | 
            
                                                                                                            
                            
            
                                    
            
            
                | 155 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 156 |  |  |     name = models.CharField( | 
            
                                                                                                            
                            
            
                                    
            
            
                | 157 |  |  |         max_length=255) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 158 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 159 |  |  |     team = models.ForeignKey( | 
            
                                                                                                            
                            
            
                                    
            
            
                | 160 |  |  |         'ManagedTeam', | 
            
                                                                                                            
                            
            
                                    
            
            
                | 161 |  |  |         on_delete=models.CASCADE, | 
            
                                                                                                            
                            
            
                                    
            
            
                | 162 |  |  |         help_text="Your AAP Team") | 
            
                                                                                                            
                            
            
                                    
            
            
                | 163 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 164 |  |  |     # a column to track sample status | 
            
                                                                                                            
                            
            
                                    
            
            
                | 165 |  |  |     status = models.SmallIntegerField( | 
            
                                                                                                            
                            
            
                                    
            
            
                | 166 |  |  |         choices=[x.value for x in STATUSES], | 
            
                                                                                                            
                            
            
                                    
            
            
                | 167 |  |  |         help_text='example: Waiting', | 
            
                                                                                                            
                            
            
                                    
            
            
                | 168 |  |  |         default=READY) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 169 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 170 |  |  |     removed = models.BooleanField( | 
            
                                                                                                            
                            
            
                                    
            
            
                | 171 |  |  |         default=False, | 
            
                                                                                                            
                            
            
                                    
            
            
                | 172 |  |  |         help_text='Is this sample still available?') | 
            
                                                                                                            
                            
            
                                    
            
            
                | 173 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 174 |  |  |     removed_at = models.DateTimeField( | 
            
                                                                                                            
                            
            
                                    
            
            
                | 175 |  |  |         null=True, | 
            
                                                                                                            
                            
            
                                    
            
            
                | 176 |  |  |         blank=True) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 177 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 178 |  |  |     def __str__(self): | 
            
                                                                                                            
                                                                
            
                                    
            
            
                | 179 |  |  |         return "%s (%s)" % (self.biosample_id, self.found_at) | 
            
                                                        
            
                                    
            
            
                | 180 |  |  |  |