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