1 from __future__ import absolute_import, print_function
3 from django.conf import settings
4 from django.contrib.auth.decorators import login_required
5 from django.core.exceptions import ObjectDoesNotExist
6 from django.http import HttpResponse, HttpResponseRedirect
7 from django.shortcuts import render_to_response
8 from django.template import RequestContext, Template
9 from django.template.loader import get_template
11 from samples.changelist import HTSChangeList
12 from .models import Item, LongTermStorage, ItemType
13 from .admin import ItemAdmin, ItemTypeAdmin
14 from .bcmagic import item_search
15 from experiments.models import FlowCell
16 from bcmagic.plugin import register_search_plugin
17 from bcmagic.forms import BarcodeMagicForm
18 from bcmagic.utils import print_zpl_socket
20 register_search_plugin('Inventory Item', item_search)
24 except ImportError, e:
25 import simplejson as json
27 INVENTORY_CONTEXT_DEFAULTS = {
28 'app_name': 'Inventory Tracker',
29 'bcmagic': BarcodeMagicForm()
32 def __flowcell_rundate_sort(x, y):
36 if x.run_date > y.run_date:
38 elif x.run_date == y.run_date:
43 def __expand_longtermstorage_context(context, item):
45 Expand information for LongTermStorage
51 for lts in item.longtermstorage_set.all():
52 flowcell_list.append(lts.flowcell)
53 flowcell_id_list.append(lts.flowcell.flowcell_id)
54 library_id_list.extend([ lib.id for lib in lts.libraries.all() ])
56 flowcell_list.sort(__flowcell_rundate_sort)
57 context['oldest_rundate'] = flowcell_list[0].run_date
58 context['latest_rundate'] = flowcell_list[-1].run_date
60 context['flowcell_id_list'] = flowcell_id_list
61 context['library_id_list_1_to_20'] = library_id_list[0:20]
62 context['library_id_list_21_to_40'] = library_id_list[20:40]
63 context['library_id_list_41_to_60'] = library_id_list[40:60]
64 context['library_id_list_61_to_80'] = library_id_list[60:80]
68 'Hard Drive': __expand_longtermstorage_context
71 #INVENTORY_ITEM_PRINT_DEFAULTS = {
72 # 'Hard Drive': 'inventory/hard_drive_shell.zpl',
73 # 'default': 'inventory/default.zpl',
74 # 'host': settings.BCPRINTER_PRINTER1_HOST
77 def getPrinterTemplateByType(item_type):
79 returns template to use given item_type
81 assert item_type.printertemplate_set.count() < 2
83 # Get the template for item_type
84 if item_type.printertemplate_set.count() > 0:
85 printer_template = item_type.printertemplate_set.all()[0]
86 return printer_template
90 printer_template = PrinterTemplate.objects.get(default=True)
91 except ObjectDoesNotExist:
92 msg = "No template for item type (%s) and no default template found" % (item_type.name)
95 return printer_template
99 def data_items(request):
101 Returns items in json format
103 item_list = Item.objects.all()
104 d = { 'results': len(item_list) }
107 for item in item_list:
109 item_d['uuid'] = item.uuid
110 item_d['barcode_id'] = item.barcode_id
111 item_d['model_id'] = item.item_info.model_id
112 item_d['part_number'] = item.item_info.part_number
113 item_d['lot_number'] = item.item_info.lot_number
114 item_d['vendor'] = item.item_info.vendor.name
115 item_d['creation_date'] = item.creation_date.strftime('%Y-%m-%d %H:%M:%S')
116 item_d['modified_date'] = item.modified_date.strftime('%Y-%m-%d %H:%M:%S')
117 item_d['location'] = item.location.name
119 # Item status if exists
120 if item.status is None:
121 item_d['status'] = ''
123 item_d['status'] = item.status.name
125 # Stored flowcells on device
126 if item.longtermstorage_set.count() > 0:
127 item_d['flowcells'] = ','.join([ lts.flowcell.flowcell_id for lts in item.longtermstorage_set.all() ])
129 item_d['flowcells'] = ''
131 item_d['type'] = item.item_type.name
136 return HttpResponse(json.dumps(d), content_type="application/javascript")
139 def all_index(request):
144 item_changelist = HTSChangeList(request, Item,
148 model_admin=ItemAdmin(Item, None)
152 'item_changelist': item_changelist,
153 'page_name': 'Inventory Index'
155 context_dict.update(INVENTORY_CONTEXT_DEFAULTS)
157 return render_to_response('inventory/inventory_all_index.html',
159 context_instance=RequestContext(request))
167 item_changelist = HTSChangeList(request, ItemType,
169 search_fields=['name', 'description'],
171 model_admin=ItemTypeAdmin(ItemType, None)
175 'item_changelist': item_changelist,
176 'page_name': 'Inventory Index'
178 context_dict.update(INVENTORY_CONTEXT_DEFAULTS)
179 return render_to_response('inventory/inventory_index.html',
181 context_instance=RequestContext(request))
184 def itemtype_index(request, name):
189 name = name.replace('%20', ' ')
191 itemtype = ItemType.objects.get(name=name)
194 item_changelist = HTSChangeList(request, Item,
198 model_admin=ItemAdmin(Item, None)
202 'item_changelist': item_changelist,
203 'page_name': 'Inventory Index'
205 context_dict.update(INVENTORY_CONTEXT_DEFAULTS)
207 return render_to_response('inventory/inventory_itemtype_index.html',
209 context_instance=RequestContext(request))
213 def item_summary_by_barcode(request, barcode_id, msg=''):
215 Display a summary for an item by barcode
218 item = Item.objects.get(barcode_id=barcode_id)
219 except ObjectDoesNotExist, e:
222 return item_summary_by_uuid(request, None, msg, item)
226 def item_summary_by_uuid(request, uuid, msg='', item=None):
228 Display a summary for an item
230 # Use item instead of looking it up if it is passed.
233 item = Item.objects.get(uuid=uuid)
234 except ObjectDoesNotExist, e:
238 'page_name': 'Item Summary',
243 context_dict.update(INVENTORY_CONTEXT_DEFAULTS)
245 return render_to_response('inventory/inventory_summary.html',
247 context_instance=RequestContext(request))
254 def __expand_context(context, item):
256 If EXPAND_CONTEXT dictionary has item.item_type.name function registered, use it to expand context
258 if item.item_type.name in EXPAND_CONTEXT:
259 expand_func = EXPAND_CONTEXT[item.item_type.name]
260 expand_func(context, item)
262 def _item_print(item, request):
264 Prints an item given a type of item label to print
266 #FIXME: Hard coding this for now... need to abstract later.
267 context = {'item': item}
268 __expand_context(context, item)
270 # Print using barcode_id
271 if not item.force_use_uuid and (item.barcode_id is None or len(item.barcode_id.strip())):
272 context['use_uuid'] = False
273 msg = 'Printing item with barcode id: %s' % (item.barcode_id)
276 context['use_uuid'] = True
277 msg = 'Printing item with UUID: %s' % (item.uuid)
279 printer_template = getPrinterTemplateByType(item.item_type)
281 c = RequestContext(request, context)
282 t = Template(printer_template.template)
283 print_zpl_socket(t.render(c), host=printer_template.printer.ip_address)
288 def item_print(request, uuid):
290 Print a label for a given item
293 item = Item.objects.get(uuid=uuid)
294 except ObjectDoesNotExist, e:
296 msg = "Item with UUID %s does not exist" % (uuid)
299 msg = _item_print(item, request)
301 return item_summary_by_uuid(request, uuid, msg)
304 def link_flowcell_and_device(request, flowcell, serial):
306 Updates database records of a flowcell being archived on a device with a particular serial #
308 assert flowcell is not None
309 assert serial is not None
313 LIBRARY_UPDATED = False
315 ###########################################
316 # Retrieve Storage Device
318 sd = Item.objects.get(barcode_id=serial)
319 except ObjectDoesNotExist, e:
320 msg = "Item with barcode_id of %s not found." % (serial)
321 raise ObjectDoesNotExist(msg)
323 ###########################################
326 fc = FlowCell.objects.get(flowcell_id__startswith=flowcell)
327 except ObjectDoesNotExist, e:
328 msg = "FlowCell with flowcell_id of %s not found." % (flowcell)
329 raise ObjectDoesNotExist(msg)
331 ###########################################
332 # Retrieve or create LongTermStorage Object
333 count = fc.longtermstorage_set.count()
336 msg = "There really should only be one longtermstorage object per flowcell"
337 raise ValueError, msg
339 # lts already attached to flowcell
340 lts = fc.longtermstorage_set.all()[0]
342 lts = LongTermStorage()
345 # Need a primary keey before linking to storage devices
350 ############################################
351 # Link Storage to Flowcell
353 # Add a link to this storage device if it is not already linked.
354 if sd not in lts.storage_devices.all():
355 lts.storage_devices.add(sd)
358 ###########################################
359 # Add Library Links to LTS
361 for lane in fc.lane_set.all():
362 if lane.library not in lts.libraries.all():
363 lts.libraries.add(lane.library)
364 LIBRARY_UPDATED = True
370 if LTS_UPDATED or SD_UPDATED or LIBRARY_UPDATED:
371 msg.append(' LongTermStorage (LTS) Created: %s' % (LTS_UPDATED))
372 msg.append(' Storage Device Linked to LTS: %s' % (SD_UPDATED))
373 msg.append(' Libraries updated in LTS: %s' % (LIBRARY_UPDATED))
375 msg.append(' No Updates Needed.')
377 return HttpResponse('\n'.join(msg))