deefeedb64e50c37c0855d4c66fb0b24eaf214c9
[htsworkflow.git] / inventory / models.py
1 from __future__ import absolute_import, print_function
2
3 import logging
4
5 from django.db import models
6 from django.db.models.signals import pre_save, post_init
7
8 from samples.models import Library
9 from experiments.models import FlowCell
10 from bcmagic.models import Printer
11
12 LOGGER = logging.getLogger(__name__)
13
14 try:
15     import uuid
16 except ImportError, e:
17     # Some systems are using python 2.4, which doesn't have uuid
18     # this is a stub
19     LOGGER.warning('Real uuid is not available, initializing fake uuid module')
20
21     class uuid:
22         def uuid1(self):
23             self.hex = None
24             return self
25
26
27 def _assign_uuid(sender, instance, **kwargs):
28     """
29     Assigns a UUID to model on save
30     """
31     #print 'Entered _assign_uuid'
32     if instance.uuid is None or len(instance.uuid) != 32:
33         instance.uuid = uuid.uuid1().hex
34
35
36 def _switch_default(sender, instance, **kwargs):
37     """
38     When new instance has default == True, uncheck all other defaults
39     """
40     if instance.default:
41         other_defaults = PrinterTemplate.objects.filter(default=True)
42
43         for other in other_defaults:
44             other.default = False
45             other.save()
46
47
48 class Vendor(models.Model):
49     name = models.CharField(max_length=256)
50     url = models.URLField(blank=True, null=True)
51
52     def __unicode__(self):
53         return u"%s" % (self.name)
54
55
56 class Location(models.Model):
57
58     name = models.CharField(max_length=256, unique=True)
59     location_description = models.TextField()
60
61     uuid = models.CharField(max_length=32,
62                             blank=True,
63                             help_text="Leave blank for automatic UUID generation",
64                             editable=False)
65
66     notes = models.TextField(blank=True, null=True)
67
68     def __unicode__(self):
69         if len(self.location_description) > 16:
70             return u"%s: %s" % (self.name, self.location_description[0:16]+u"...")
71         else:
72             return u"%s: %s" % (self.name, self.location_description)
73
74 post_init.connect(_assign_uuid, sender=Location)
75
76
77 class ItemInfo(models.Model):
78     model_id = models.CharField(max_length=256, blank=True, null=True)
79     part_number = models.CharField(max_length=256, blank=True, null=True)
80     lot_number = models.CharField(max_length=256, blank=True, null=True)
81
82     url = models.URLField(blank=True, null=True)
83
84     qty_purchased = models.IntegerField(default=1)
85
86     vendor = models.ForeignKey(Vendor)
87     purchase_date = models.DateField(blank=True, null=True)
88     warranty_months = models.IntegerField(blank=True, null=True)
89
90     notes = models.TextField(blank=True, null=True)
91
92     def __unicode__(self):
93         name = u''
94         if self.model_id:
95             name += u"model:%s " % (self.model_id)
96         if self.part_number:
97             name += u"part:%s " % (self.part_number)
98         if self.lot_number:
99             name += u"lot:%s " % (self.lot_number)
100
101         return u"%s: %s" % (name, self.purchase_date)
102
103     class Meta:
104         verbose_name_plural = "Item Info"
105
106
107 class ItemType(models.Model):
108
109     name = models.CharField(max_length=64, unique=True)
110     description = models.TextField(blank=True, null=True)
111
112     def __unicode__(self):
113         return u"%s" % (self.name)
114
115
116 class ItemStatus(models.Model):
117     name = models.CharField(max_length=64, unique=True)
118     notes = models.TextField(blank=True, null=True)
119
120     def __unicode__(self):
121         return self.name
122
123     class Meta:
124         verbose_name_plural = "Item Status"
125
126
127 class Item(models.Model):
128     item_type = models.ForeignKey(ItemType)
129
130     #Automatically assigned uuid; used for barcode if one is not provided in
131     # barcode_id
132     uuid = models.CharField(max_length=32,
133                             blank=True,
134                             help_text="Leave blank for automatic UUID generation",
135                             unique=True,
136                             editable=False)
137
138     # field for existing barcodes; used instead of uuid if provided
139     barcode_id = models.CharField(max_length=256, blank=True, null=True)
140     force_use_uuid = models.BooleanField(default=False)
141
142     item_info = models.ForeignKey(ItemInfo)
143
144     location = models.ForeignKey(Location)
145
146     status = models.ForeignKey(ItemStatus, blank=True, null=True)
147
148     creation_date = models.DateTimeField(auto_now_add=True)
149     modified_date = models.DateTimeField(auto_now=True)
150
151     notes = models.TextField(blank=True, null=True)
152
153     def __unicode__(self):
154         if self.barcode_id is None or len(self.barcode_id) == 0:
155             return u"invu|%s" % (self.uuid)
156         else:
157             return u"invb|%s" % (self.barcode_id)
158
159     def get_absolute_url(self):
160         return '/inventory/%s/' % (self.uuid)
161
162 post_init.connect(_assign_uuid, sender=Item)
163
164
165 class PrinterTemplate(models.Model):
166     """
167     Maps templates to printer to use
168     """
169     item_type = models.ForeignKey(ItemType)
170     printer = models.ForeignKey(Printer)
171
172     default = models.BooleanField(default=False)
173
174     template = models.TextField()
175
176     def __unicode__(self):
177         if self.default:
178             return u'%s %s' % (self.item_type.name, self.printer.name)
179         else:
180             return u'%s %s (default)' % (self.item_type.name, self.printer.name)
181
182 pre_save.connect(_switch_default, sender=PrinterTemplate)
183
184
185 class LongTermStorage(models.Model):
186     flowcell = models.ForeignKey(FlowCell)
187     libraries = models.ManyToManyField(Library)
188
189     storage_devices = models.ManyToManyField(Item)
190
191     creation_date = models.DateTimeField(auto_now_add=True)
192     modified_date = models.DateTimeField(auto_now=True)
193
194     def __unicode__(self):
195         return u"%s: %s" % (str(self.flowcell), ', '.join([str(s) for s in self.storage_devices.iterator()]))
196
197     class Meta:
198         verbose_name_plural = "Long Term Storage"
199
200
201 class ReagentBase(models.Model):
202     reagent = models.ManyToManyField(Item)
203
204     creation_date = models.DateTimeField(auto_now_add=True)
205     modified_date = models.DateTimeField(auto_now=True)
206
207     class Meta:
208         abstract = True
209
210
211 class ReagentFlowcell(ReagentBase):
212     """
213     Links reagents and flowcells
214     """
215     flowcell = models.ForeignKey(FlowCell)
216
217     def __unicode__(self):
218         return u"%s: %s" % (str(self.flowcell), ', '.join([str(s) for s in self.reagent.iterator()]))
219
220
221 class ReagentLibrary(ReagentBase):
222     """
223     Links libraries and flowcells
224     """
225     library = models.ForeignKey(Library)
226
227     def __unicode__(self):
228         return u"%s: %s" % (str(self.library), ', '.join([str(s) for s in self.reagent.iterator()]))