Prototype of bcmagic search plugin.
[htsworkflow.git] / htsworkflow / frontend / inventory / views.py
1 from htsworkflow.frontend.inventory.models import Item, LongTermStorage
2 from htsworkflow.frontend.inventory.bcmagic import item_search
3 from htsworkflow.frontend.bcmagic.plugin import register_search_plugin
4 from htsworkflow.frontend.experiments.models import FlowCell
5 from htsworkflow.frontend.bcmagic.forms import BarcodeMagicForm
6 from htsworkflow.frontend.bcprinter.util import print_zpl_socket
7 from htsworkflow.frontend import settings
8 #from htsworkflow.util.jsonutil import encode_json
9
10 from django.core.exceptions import ObjectDoesNotExist
11 from django.http import HttpResponse, HttpResponseRedirect
12 from django.shortcuts import render_to_response
13 from django.template import RequestContext
14 from django.template.loader import get_template
15 from django.contrib.auth.decorators import login_required
16
17 register_search_plugin('Inventory Item', item_search)
18
19 try:
20     import json
21 except ImportError, e:
22     import simplejson as json
23
24 INVENTORY_CONTEXT_DEFAULTS = {
25     'app_name': 'Inventory Tracker',
26     'bcmagic': BarcodeMagicForm()
27 }
28
29 INVENTORY_ITEM_PRINT_DEFAULTS = {
30     'default': 'inventory/default.zpl',
31     'host': settings.BCPRINTER_PRINTER1_HOST
32 }
33
34 def getTemplateByType(item_type):
35     """
36     returns template to use given item_type
37     """
38     if item_type in INVENTORY_ITEM_PRINT_DEFAULTS:
39         return INVENTORY_ITEM_PRINT_DEFAULTS[item_type]
40     else:
41         return INVENTORY_ITEM_PRINT_DEFAULTS['default']
42
43 @login_required
44 def data_items(request):
45     """
46     Returns items in json format
47     """
48     item_list = Item.objects.all()
49     d = { 'results': len(item_list) }
50     rows = []
51     
52     for item in item_list:
53         item_d = {}
54         item_d['uuid'] = item.uuid
55         item_d['barcode_id'] = item.barcode_id
56         item_d['model_id'] = item.item_info.model_id
57         item_d['part_number'] = item.item_info.part_number
58         item_d['lot_number'] = item.item_info.lot_number
59         item_d['vendor'] = item.item_info.vendor.name
60         item_d['creation_date'] = item.creation_date.strftime('%Y-%m-%d %H:%M:%S')
61         item_d['modified_date'] = item.modified_date.strftime('%Y-%m-%d %H:%M:%S')
62         item_d['location'] = item.location.name
63         
64         # Item status if exists
65         if item.status is None:
66             item_d['status'] = ''
67         else:
68             item_d['status'] = item.status.name
69             
70         # Stored flowcells on device
71         if item.longtermstorage_set.count() > 0:
72             item_d['flowcells'] = ','.join([ lts.flowcell.flowcell_id for lts in item.longtermstorage_set.all() ])
73         else:
74             item_d['flowcells'] = ''
75         
76         item_d['type'] = item.item_type.name
77         rows.append(item_d)
78     
79     d['rows'] = rows
80     
81     return HttpResponse(json.dumps(d), content_type="application/javascript")
82
83 @login_required
84 def index(request):
85     """
86     Inventory Index View
87     """
88     context_dict = {
89         'page_name': 'Inventory Index'
90     }
91     context_dict.update(INVENTORY_CONTEXT_DEFAULTS)
92     
93     return render_to_response('inventory/inventory_index.html',
94                               context_dict,
95                               context_instance=RequestContext(request))
96     
97
98 @login_required
99 def item_summary_by_barcode(request, barcode_id, msg=''):
100     """
101     Display a summary for an item by barcode
102     """
103     try:
104         item = Item.objects.get(barcode_id=barcode_id)
105     except ObjectDoesNotExist, e:
106         item = None
107         
108     return item_summary_by_uuid(request, None, msg, item)
109     
110
111 @login_required
112 def item_summary_by_uuid(request, uuid, msg='', item=None):
113     """
114     Display a summary for an item
115     """
116     # Use item instead of looking it up if it is passed.
117     if item is None:
118         try:
119             item = Item.objects.get(uuid=uuid)
120         except ObjectDoesNotExist, e:
121             item = None
122     
123     context_dict = {
124         'page_name': 'Item Summary',
125         'item': item,
126         'uuid': uuid,
127         'msg': msg
128     }
129     context_dict.update(INVENTORY_CONTEXT_DEFAULTS)
130     
131     return render_to_response('inventory/inventory_summary.html',
132                               context_dict,
133                               context_instance=RequestContext(request))
134
135
136 def _item_print(item, request):
137     """
138     Prints an item given a type of item label to print
139     """
140     #FIXME: Hard coding this for now... need to abstract later.
141     context = {'item': item}
142     
143     # Print using barcode_id
144     if not item.force_use_uuid and (item.barcode_id is None or len(item.barcode_id.strip())):
145         context['use_uuid'] = False
146         msg = 'Printing item with barcode id: %s' % (item.barcode_id)
147     # Print using uuid
148     else:
149         context['use_uuid'] = True
150         msg = 'Printing item with UUID: %s' % (item.uuid)
151     
152     c = RequestContext(request, context)
153     t = get_template(getTemplateByType(item.item_type.name))
154     print_zpl_socket(t.render(c))
155     
156     return msg
157
158 @login_required
159 def item_print(request, uuid):
160     """
161     Print a label for a given item
162     """
163     try:
164         item = Item.objects.get(uuid=uuid)
165     except ObjectDoesNotExist, e:
166         item = None
167         msg = "Item with UUID %s does not exist" % (uuid)
168     
169     if item is not None:
170         msg = _item_print(item, request)
171     
172     return item_summary_by_uuid(request, uuid, msg)
173
174
175 def link_flowcell_and_device(request, flowcell, serial):
176     """
177     Updates database records of a flowcell being archived on a device with a particular serial #
178     """
179     assert flowcell is not None
180     assert serial is not None
181     
182     LTS_UPDATED = False
183     SD_UPDATED = False
184     LIBRARY_UPDATED = False
185         
186     ###########################################
187     # Retrieve Storage Device
188     try:
189         sd = Item.objects.get(barcode_id=serial)
190     except ObjectDoesNotExist, e:
191         msg = "Item with barcode_id of %s not found." % (serial)
192         raise ObjectDoesNotExist(msg)
193     
194     ###########################################
195     # Retrieve FlowCell
196     try:    
197         fc = FlowCell.objects.get(flowcell_id=flowcell)
198     except ObjectDoesNotExist, e:
199         msg = "FlowCell with flowcell_id of %s not found." % (flowcell)
200         raise ObjectDoesNotExist(msg)
201     
202     ###########################################
203     # Retrieve or create LongTermStorage Object
204     count = fc.longtermstorage_set.count()
205     lts = None
206     if count > 1:
207         msg = "There really should only be one longtermstorage object per flowcell"
208         raise ValueError, msg
209     elif count == 1:
210         # lts already attached to flowcell
211         lts = fc.longtermstorage_set.all()[0]
212     else:
213         lts = LongTermStorage()
214         # Attach flowcell
215         lts.flowcell = fc
216         # Need a primary keey before linking to storage devices
217         lts.save()
218         LTS_UPDATED = True
219         
220         
221     ############################################
222     # Link Storage to Flowcell
223     
224     # Add a link to this storage device if it is not already linked.
225     if sd not in lts.storage_devices.all():
226         lts.storage_devices.add(sd)
227         SD_UPDATED = True
228     
229     ###########################################
230     # Add Library Links to LTS
231     
232     if fc.lane_1_library not in lts.libraries.all():
233         lts.libraries.add(fc.lane_1_library)
234         LIBRARY_UPDATED = True
235         print 1
236     
237     if fc.lane_2_library not in lts.libraries.all():
238         lts.libraries.add(fc.lane_2_library)
239         LIBRARY_UPDATED = True
240         print 2
241     
242     if fc.lane_3_library not in lts.libraries.all():
243         lts.libraries.add(fc.lane_3_library)
244         LIBRARY_UPDATED = True
245         print 3
246     
247     if fc.lane_4_library not in lts.libraries.all():
248         lts.libraries.add(fc.lane_4_library)
249         LIBRARY_UPDATED = True
250         print 4
251     
252     
253     if fc.lane_5_library not in lts.libraries.all():
254         lts.libraries.add(fc.lane_5_library)
255         LIBRARY_UPDATED = True
256         print 5
257     
258     if fc.lane_6_library not in lts.libraries.all():
259         lts.libraries.add(fc.lane_6_library)
260         LIBRARY_UPDATED = True
261         print 6
262     
263     if fc.lane_7_library not in lts.libraries.all():
264         lts.libraries.add(fc.lane_7_library)
265         LIBRARY_UPDATED = True
266         print 7
267     
268     if fc.lane_8_library not in lts.libraries.all():
269         lts.libraries.add(fc.lane_8_library)
270         LIBRARY_UPDATED = True
271         print 8
272         
273     # Save Changes
274     lts.save()
275     
276     msg = ['Success:']
277     if LTS_UPDATED or SD_UPDATED or LIBRARY_UPDATED:
278         msg.append('  LongTermStorage (LTS) Created: %s' % (LTS_UPDATED))
279         msg.append('   Storage Device Linked to LTS: %s' % (SD_UPDATED))
280         msg.append('       Libraries updated in LTS: %s' % (LIBRARY_UPDATED))
281     else:
282         msg.append('  No Updates Needed.')
283     
284     return HttpResponse('\n'.join(msg))