1 from django.http import HttpResponse, HttpResponseRedirect
2 from samplebc.samples import models
3 from django.core.exceptions import ObjectDoesNotExist
4 from django.template import Context, Template, RequestContext
5 from django.template.loader import get_template
6 from django.shortcuts import render_to_response
7 from django.contrib.auth.decorators import login_required
9 from django.utils.safestring import mark_safe
11 from samplebc.samples.forms import FreezerForm, ContainerForm, SampleForm, CmdMoveSampleForm
12 from samplebc.samples.models import Freezer, Container, Sample
13 from samplebc.samples.util import get_uuid, get_sampleid, assign_to_container
14 from samplebc.samples.errors import NoSpaceAvaliable
15 from samplebc import settings
18 from samplebc.bcmagic.forms import BarcodeMagicForm
21 from reversion import revision
29 ################################################
31 ################################################
33 def print_zpl(zpl_text):
35 Sends zpl_text to printer
37 ftp = ftplib.FTP(host='131.215.54.194', user='blank', passwd='')
39 ftp.storlines("STOR printme.txt", StringIO.StringIO(zpl_text))
42 def print_zpl_socket(zpl_text):
44 Sends zpl_text to printer via a socket
47 # PORT 9100 is default for Zebra tabletop/desktop printers
48 # PORT 6101 is default for Zebra mobile printers
49 s.connect((settings.PRINTER_HOST, settings.PRINTER_PORT))
53 def __center_line(line, width):
54 spaces_to_add = width - len(line)
56 front_half = spaces_to_add / 2
57 back_half = spaces_to_add - front_half
59 return (' ' * front_half) + line + (' ' * back_half)
64 ################################################
66 ################################################
68 def container_index(request):
70 Returns an index of available to containers
72 container_list = Container.objects.all()
73 c = Context({'title': 'Container Index',
74 'container_list': container_list})
75 t = get_template('container_index.html')
77 return render_to_response('app.html', {
78 'app_name': "HTSW-SampleTracker",
79 'page_name': 'Container Index',
80 'bcmagic': BarcodeMagicForm(),
81 'select': 'container',
84 context_instance=RequestContext(request))
89 def container_summary(request, container_id, msg=None):
91 Returns details of a container
93 # Retrieve container by UUID
95 container = models.Container.objects.get(uuid=container_id)
96 except ObjectDoesNotExist, e:
97 msg = "Container (%s) does not exist." % (container_id)
98 return render_to_response('app.html', {
99 'app_name': settings.HTSW_ST_APPNAME,
100 'page_name': 'Container Summary',
102 'bcmagic': BarcodeMagicForm(),
103 'select': 'container',
106 context_instance=RequestContext(request))
108 # Retrieve samples from container
109 sample_list = container.sample_set.all()
111 # Prepare a Sample Index of Contained Samples
112 cs = Context({'title': 'Contained Samples',
113 'sample_list': sample_list})
114 ts = get_template('sample_index.html')
116 # Render prepared samples into container summary
117 cc = Context({'container': container,
119 'rendered_samples': ts.render(cs) })
120 tc = get_template('container_summary.html')
122 # Render container summary to app html
123 return render_to_response('app.html', {
124 'app_name': settings.HTSW_ST_APPNAME,
125 'page_name': 'Container Summary',
127 'bcmagic': BarcodeMagicForm(),
128 'select': 'container',
129 'body': tc.render(cc)
131 context_instance=RequestContext(request))
134 @revision.create_on_success
135 def container_add(request):
137 Form for adding a container.
141 revision.comment = "New container created by user."
143 # If user submitted the Container form.
144 if request.method == 'POST':
145 # Fill in ContainerForm with POSTed data.
146 form = ContainerForm(request.POST)
148 # If the form is valid, process it.
150 # Create new Container object from form data
151 c_obj = form.save(commit=False)
153 c_obj.uuid = get_uuid()
156 # Save the many to many link data.
158 return container_summary(request, c_obj.uuid)
160 # If users first visit, create empty form.
161 form = ContainerForm()
164 c = Context({'form': form,
165 'action_url': '/samples/container/add/'})
166 t = get_template('generic_form.html')
168 return render_to_response('app.html', {
169 'app_name': settings.HTSW_ST_APPNAME,
170 'page_name': 'Container Add',
172 'bcmagic': BarcodeMagicForm(),
173 'select': 'container',
176 context_instance=RequestContext(request))
179 @revision.create_on_success
180 def container_edit(request, container_id):
182 Allow editing of a container
185 revision.comment = "Manual container edit by user."
188 container = models.Container.objects.get(uuid=container_id)
189 except ObjectDoesNotExist, e:
190 msg = "Container (%s) cannot be edited as it does not exist." % (container_id)
191 return render_to_response('app.html', {
192 'app_name': settings.HTSW_ST_APPNAME,
193 'page_name': 'Container Edit',
195 'bcmagic': BarcodeMagicForm(),
196 'select': 'container',
199 context_instance=RequestContext(request))
201 # If user submitted the container form.
202 if request.method == 'POST':
203 # Fill in ContainerForm with POSTed data.
204 form = ContainerForm(request.POST, instance=container)
206 # If the form is valid, process it.
208 # Save Container object from form data
209 c_obj = form.save(commit=True)
210 # Save many2many changes as well
211 #form.save_m2m() #Not needed when form.save(commit=True)
213 return container_summary(request, c_obj.uuid)
215 # If users first visit, create form from Container instance.
216 form = ContainerForm(instance=container)
219 c = Context({'form': form,
220 'action_url': '%sedit/' % (container.get_absolute_url())})
221 t = get_template('generic_form.html')
223 return render_to_response('app.html', {
224 'app_name': settings.HTSW_ST_APPNAME,
225 'page_name': 'Container Edit',
227 'bcmagic': BarcodeMagicForm(),
228 'select': 'container',
231 context_instance=RequestContext(request))
234 def container_print(request, container_id):
236 prints a container label
240 container = models.Container.objects.get(uuid=container_id)
241 except ObjectDoesNotExist:
242 return HttpResponse('Container (%s) does not exist!' % (container_id))
245 params['container_name'] = __center_line(container.name[0:17], 17)
246 params['line1'] = __center_line('%s' % (container.name[17:34]), 17)
247 params['line2'] = __center_line('%s' % (container.name[34:51]), 17)
248 params['line3'] = __center_line('%s' % (container.name[51:68]), 17)
249 params['line4'] = __center_line('%s' % (container.name[68:85]), 17)
250 params['barcode'] = 'cntr|%s' % (container.uuid)
251 params['symbol'] = ''
253 c = RequestContext(request, params)
254 t = get_template('zpl_container_label.txt')
255 print_zpl(t.render(c))
257 return container_summary(request, container_id, msg='print command for container %s sent.' % (container.uuid))
260 ################################################
262 ################################################
264 def freezer_index(request):
266 Returns an index of available freezers
268 freezer_list = Freezer.objects.all()
269 c = Context({'freezer_list': freezer_list})
270 t = get_template('freezer_index.html')
272 return render_to_response('app.html', {
273 'app_name': "HTSW-SampleTracker",
274 'page_name': 'Freezer Index',
276 'bcmagic': BarcodeMagicForm(),
280 context_instance=RequestContext(request))
283 def freezer_summary(request, freezer_id, msg=None):
285 Returns summary of freezer_id
287 # Retrieve freezer by UUID
289 freezer = models.Freezer.objects.get(uuid=freezer_id)
290 except ObjectDoesNotExist, e:
291 msg = "Freezer (%s) does not exist." % (freezer_id)
292 return render_to_response('app.html', {
293 'app_name': settings.HTSW_ST_APPNAME,
294 'page_name': 'Freezer Summary',
296 'bcmagic': BarcodeMagicForm(),
300 context_instance=RequestContext(request))
302 # List of contained containers
303 container_list = freezer.container_set.all()
306 # Render prepared container index into freezer summary
307 cf = Context({'freezer': freezer,
309 tf = get_template('freezer_summary.html')
311 # Render Freezer summary to app html
312 return render_to_response('app.html', {
313 'app_name': settings.HTSW_ST_APPNAME,
314 'page_name': 'Freezer Summary',
316 'bcmagic': BarcodeMagicForm(),
318 'body': tf.render(cf)
320 context_instance=RequestContext(request))
323 @revision.create_on_success
324 def freezer_add(request):
326 Allows you to add a new freezer.
329 revision.comment = "New freezer created by user."
331 # If user submitted the freezer form.
332 if request.method == 'POST':
333 # Fill in FreezerForm with POSTed data.
334 form = FreezerForm(request.POST)
336 # If the form is valid, process it.
338 # Create new Freezer object from form data
339 f_obj = form.save(commit=False)
341 f_obj.uuid = get_uuid()
344 return freezer_summary(request, f_obj.uuid)
346 # If users first visit, create empty form.
350 c = Context({'form': form,
351 'action_url': '/samples/freezer/add/'})
352 t = get_template('generic_form.html')
354 return render_to_response('app.html', {
355 'app_name': settings.HTSW_ST_APPNAME,
356 'page_name': 'Freezer Add',
358 'bcmagic': BarcodeMagicForm(),
362 context_instance=RequestContext(request))
365 @revision.create_on_success
366 def freezer_edit(request, freezer_id):
368 Allow editing of a freezer
371 revision.comment = "Manual freezer edit by user."
374 freezer = models.Freezer.objects.get(uuid=freezer_id)
375 except ObjectDoesNotExist, e:
376 msg = "Freezer (%s) cannot be edited as it does not exist." % (freezer_id)
377 return render_to_response('app.html', {
378 'app_name': settings.HTSW_ST_APPNAME,
379 'page_name': 'Freezer Summary',
381 'bcmagic': BarcodeMagicForm(),
385 context_instance=RequestContext(request))
387 # If user submitted the freezer form.
388 if request.method == 'POST':
389 # Fill in FreezerForm with POSTed data.
390 form = FreezerForm(request.POST, instance=freezer)
392 # If the form is valid, process it.
394 # Save Freezer object from form data
395 f_obj = form.save(commit=True)
397 return freezer_summary(request, f_obj.uuid)
399 # If users first visit, create form from freezer instance.
400 form = FreezerForm(instance=freezer)
403 c = Context({'form': form,
404 'action_url': '%sedit/' % (freezer.get_absolute_url())})
405 t = get_template('generic_form.html')
407 return render_to_response('app.html', {
408 'app_name': settings.HTSW_ST_APPNAME,
409 'page_name': 'Freezer Edit',
411 'bcmagic': BarcodeMagicForm(),
415 context_instance=RequestContext(request))
418 def freezer_print(request, freezer_id):
420 prints a freezer label
424 freezer = models.Freezer.objects.get(uuid=freezer_id)
425 except ObjectDoesNotExist:
426 return HttpResponse('Freezer (%s) does not exist!' % (freezer_id))
429 params['freezer_name'] = __center_line(freezer.name, 17)
430 params['line1'] = __center_line('%s' % (freezer.name[17:34]), 17)
431 params['line2'] = __center_line('%s' % (freezer.name[34:51]), 17)
432 params['line3'] = __center_line('%s' % (freezer.name[51:68]), 17)
433 params['line4'] = __center_line('Temp: %s C' % (freezer.temperature), 17)
434 params['barcode'] = 'frzr|%s' % (freezer.uuid)
435 params['symbol'] = ''
437 c = RequestContext(request, params)
438 t = get_template('zpl_freezer_label.txt')
439 print_zpl(t.render(c))
441 return freezer_summary(request, freezer_id, msg='print command for freezer %s sent.' % (freezer.uuid))
444 ################################################
446 ################################################
448 def sample_index(request):
450 return a list of samples and what we can do with them.
452 sample_list = models.Sample.objects.all()
455 c = Context({'title': 'Sample Index',
456 'sample_list': sample_list})
457 t = get_template('sample_index.html')
458 #html.append('%s <a href="/samples/sample/%s/print">(print)</a>' \
459 # % (sample, sample.sampleid))
461 return render_to_response('app.html', {
462 'app_name': settings.HTSW_ST_APPNAME,
463 'page_name': 'Samples Index',
465 'bcmagic': BarcodeMagicForm(),
469 context_instance=RequestContext(request))
472 def sample_homeless(request):
474 Returns an index of homeless samples
476 sample_list = Sample.objects.filter(container=None)
477 c = Context({'title': 'Homeless Samples',
478 'sample_list': sample_list})
479 t = get_template('sample_homeless.html')
481 return render_to_response('app.html', {
482 'app_name': "HTSW-SampleTracker",
483 'page_name': 'Homeless Samples',
484 'bcmagic': BarcodeMagicForm(),
488 context_instance=RequestContext(request))
491 @revision.create_on_success
492 def sample_add(request):
494 Allow adding of a new sample
497 revision.comment = "New sample created by user."
499 ASSIGNED_CONTAINER = False
501 # If user submitted the sample form.
502 if request.method == 'POST':
503 # Fill in SampleForm with POSTed data.
504 form = SampleForm(request.POST)
506 # If the form is valid, process it.
508 # Create new Sample object from form data
509 s_obj = form.save(commit=False)
512 #s_obj.sampleid = get_sampleid()
514 # If the user wants us to assign a container.
515 if form.cleaned_data['assign_container']:
518 assign_to_container(s_obj)
519 ASSIGNED_CONTAINER = True
520 except NoSpaceAvaliable, e:
521 #return HttpResponse("<b>Error:</b> %s<br /><i>You will need to prepare a new container before continuing.</i>" \
523 ASSIGNED_CONTAINER = False
528 if not ASSIGNED_CONTAINER:
529 msg = "NOTE: Sample is homeless"
530 return sample_summary(request, s_obj.sampleid, msg=msg)
533 msg = "Sample created."
534 return sample_summary(request, s_obj.sampleid, msg=msg)
536 # If users first visit, create empty form.
540 c = Context({'form': form,
541 'action_url': '/samples/sample/add/'})
542 t = get_template('generic_form.html')
544 return render_to_response('app.html', {
545 'app_name': settings.HTSW_ST_APPNAME,
546 'page_name': 'Sample Add',
548 'bcmagic': BarcodeMagicForm(),
552 context_instance=RequestContext(request))
555 @revision.create_on_success
556 def sample_edit(request, sampleid):
558 Allow editing of a sample
561 revision.comment = "Manual sample edit by user."
564 sample = models.Sample.objects.get(sampleid=sampleid)
565 except ObjectDoesNotExist, e:
566 msg = "Sample (%s) cannot be edited as it does not exist." % (sampleid)
567 return render_to_response('app.html', {
568 'app_name': settings.HTSW_ST_APPNAME,
569 'page_name': 'Sample Edit',
571 'bcmagic': BarcodeMagicForm(),
576 # If user submitted the sample form.
577 if request.method == 'POST':
578 # Fill in SampleForm with POSTed data.
579 form = SampleForm(request.POST, instance=sample)
581 # If the form is valid, process it.
583 # Save Sample object from form data
584 s_obj = form.save(commit=True)
586 msg = "Sample Update Saved"
587 return sample_summary(request, s_obj.sampleid, msg)
589 # If users first visit, create form from sample instance.
590 form = SampleForm(instance=sample)
593 c = Context({'form': form,
594 'action_url': '%sedit/' % (sample.get_absolute_url())})
595 t = get_template('generic_form.html')
597 return render_to_response('app.html', {
598 'app_name': settings.HTSW_ST_APPNAME,
599 'page_name': 'Sample Edit',
601 'bcmagic': BarcodeMagicForm(),
605 context_instance=RequestContext(request))
608 @revision.create_on_success
609 def sample_assign_container(request, sampleid):
611 Assigns sample to container using the assign to container algorithm
614 sample = Sample.objects.get(sampleid=sampleid)
617 assign_to_container(sample)
618 except NoSpaceAvaliable, e:
619 return render_to_response('app.html', {
620 'app_name': settings.HTSW_ST_APPNAME,
621 'page_name': 'Sample Assign',
623 'bcmagic': BarcodeMagicForm(),
625 'body': mark_safe("<b>Error:</b> %s<br /><i>You will need to prepare a new container before continuing.</i>" \
628 context_instance=RequestContext(request))
632 body = 'Sample (<a href="%s">%s</a>) assigned to container (<a href="%s">%s</a>)' \
633 % (sample.get_absolute_url(), str(sample), sample.container.get_absolute_url(), str(sample.container))
636 revision.comment = "Sample auto-assigned to container (%s: %s)" % (str(sample.container), sample.container.uuid)
638 return render_to_response('app.html', {
639 'app_name': settings.HTSW_ST_APPNAME,
640 'page_name': 'Sample Assign',
642 'bcmagic': BarcodeMagicForm(),
644 'body': mark_safe(body),
646 context_instance=RequestContext(request))
649 def sample_summary(request, sampleid, msg=None):
651 Display a summary of a given sample
654 sample = models.Sample.objects.get(sampleid=sampleid)
655 except ObjectDoesNotExist, e:
656 msg = "Sample (%s) does not exist." % (sampleid)
657 return render_to_response('app.html', {
658 'app_name': settings.HTSW_ST_APPNAME,
659 'page_name': 'Sample Summary',
661 'bcmagic': BarcodeMagicForm(),
665 context_instance=RequestContext(request))
667 c = Context({'sample': sample,
669 t = get_template('sample_summary.html')
671 return render_to_response('app.html', {
672 'app_name': settings.HTSW_ST_APPNAME,
673 'page_name': 'Sample Summary',
675 'bcmagic': BarcodeMagicForm(),
679 context_instance=RequestContext(request))
682 def sample_print(request, sampleid):
688 sample = models.Sample.objects.get(sampleid=sampleid)
689 except ObjectDoesNotExist:
690 return HttpResponse('Sample (%s) does not exist!' % (sampleid))
693 params['fullid'] = str(sample)
694 params['sampleid'] = __center_line("s|%s" % (sample.sampleid), 16)
695 params['line1'] = __center_line(sample.name[0:10], 10)
696 params['line2'] = __center_line(sample.name[10:25], 14)
697 params['line3'] = __center_line('ExpType %s' % (sample.sample_type.name[0:8]), 15)
698 params['slot_num'] = random.randint(1,81)
700 c = RequestContext(request, params)
701 t = get_template('half_inch_samples.txt')
702 print_zpl(t.render(c))
704 return sample_summary(request, sampleid, msg='print command for sample %s sent.' % (sample.sampleid))
707 def user_profile(request):
709 Information about the user
711 return render_to_response('registration/profile.html', {
712 'app_name': settings.HTSW_ST_APPNAME,
713 'page_name': 'User Profile',
715 'bcmagic': BarcodeMagicForm(),
716 'select': 'settings',
718 context_instance=RequestContext(request))
720 ################################################
721 # Barcode Magic Commands
722 ################################################
724 def __cmd_move_sample_return(form, request, msg=''):
726 A small helper function since this code is reused multiple times
729 c = Context({'form': form,
731 t = get_template('generic_form.html')
733 return render_to_response('app.html', {
734 'app_name': settings.HTSW_ST_APPNAME,
735 'page_name': 'CMD: Move Sample',
737 'bcmagic': BarcodeMagicForm({'bcm_mode': 'cmd_move_sample'}),
742 context_instance=RequestContext(request))
745 @revision.create_on_success
746 def cmd_move_sample(request):
748 Moves a sample to a target container
750 form = CmdMoveSampleForm()
752 if request.method == 'POST':
753 form = CmdMoveSampleForm(request.POST)
755 #If for some reason the form is not valid, return
756 if not form.is_valid():
757 msg = "Form is not valid."
758 return __cmd_move_sample_return(form, request, msg)
761 sample = models.Sample.objects.get(sampleid=form.cleaned_data['sampleid'])
762 except ObjectDoesNotExist, e:
763 msg = "Sample %s does not exist." % (form.cleaned_data['sampleid'])
764 return __cmd_move_sample_return(form, request, msg)
767 container = models.Container.objects.get(uuid=form.cleaned_data['container_id'])
768 except ObjectDoesNotExist, e:
769 msg = "Container %s does not exist." % (form.cleaned_data['container_id'])
770 return __cmd_move_sample_return(form, request, msg)
772 # Move the sample to the new container
773 old_container = sample.container
774 sample.container = container
775 if old_container is None:
776 revision.comment = "Sample (%s) moved from Homeless to Container(%s; uuid: %s)" \
777 % (str(sample), str(container), container.uuid)
779 revision.comment = "Sample (%s) moved from Container(%s; uuid: %s) to Container(%s; uuid: %s)" \
780 % (str(sample), str(old_container), old_container.uuid, str(container), container.uuid)
783 return __cmd_move_sample_return(CmdMoveSampleForm(), request, revision.comment)
785 return __cmd_move_sample_return(form, request)