00c13a9aa3663caecd167e009ae5534f16afc893
[htsworkflow.git] / samplebc / samples / views.py
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
8
9 from django.utils.safestring import mark_safe
10
11 from samplebc.samples.forms import FreezerForm, ContainerForm, SampleForm
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
16
17 # Barcode Magic!
18 from samplebc.bcmagic.forms import BarcodeMagicForm
19
20
21 import random
22 import ftplib
23 import StringIO
24
25
26 ################################################
27 # Util functions
28 ################################################
29
30 @login_required
31 def print_zpl(zpl_text):
32     """
33     Sends zpl_text to printer
34     """
35     ftp = ftplib.FTP(host='131.215.54.194', user='blank', passwd='')
36     ftp.login()
37     ftp.storlines("STOR printme.txt", StringIO.StringIO(zpl_text))
38
39
40 def __center_line(line, width):
41     spaces_to_add = width - len(line)
42     
43     front_half = spaces_to_add / 2
44     back_half = spaces_to_add - front_half
45     
46     return (' ' * front_half) + line + (' ' * back_half)    
47
48
49   
50   
51 ################################################
52 # Container
53 ################################################
54 @login_required
55 def container_index(request):
56     """
57     Returns an index of available to containers
58     """
59     container_list = Container.objects.all()
60     c = Context({'title': 'Container Index',
61                  'container_list': container_list})
62     t = get_template('container_index.html')
63     
64     return render_to_response('app.html', {
65                                 'app_name': "HTSW-SampleTracker",
66                                 'page_name': 'Container Index',
67                                 'bcmagic': BarcodeMagicForm(),
68                                 'select': 'container',
69                                 'body': t.render(c)
70                             },
71                               context_instance=RequestContext(request))
72     
73
74
75 @login_required
76 def container_summary(request, container_id):
77     """
78     Returns details of a container
79     """
80     # Retrieve container by UUID
81     try:
82         container = models.Container.objects.get(uuid=container_id)
83     except ObjectDoesNotExist, e:
84         msg = "Container (%s) does not exist." % (container_id)
85         return render_to_response('app.html', {
86                                     'app_name': settings.HTSW_ST_APPNAME,
87                                     'page_name': 'Container Summary',
88                                     'media': '',
89                                     'bcmagic': BarcodeMagicForm(),
90                                     'select': 'container',
91                                     'body': msg
92                                 },
93                                   context_instance=RequestContext(request))
94     
95     # Retrieve samples from container
96     sample_list = container.sample_set.all()
97     
98     # Prepare a Sample Index of Contained Samples
99     cs = Context({'title': 'Contained Samples',
100                  'sample_list': sample_list})
101     ts = get_template('sample_index.html')
102     
103     # Render prepared samples into container summary
104     cc = Context({'container': container,
105                  'rendered_samples': ts.render(cs) })
106     tc = get_template('container_summary.html')
107     
108     # Render container summary to app html
109     return render_to_response('app.html', {
110                                 'app_name': settings.HTSW_ST_APPNAME,
111                                 'page_name': 'Container Summary',
112                                 'media': '',
113                                 'bcmagic': BarcodeMagicForm(),
114                                 'select': 'container',
115                                 'body': tc.render(cc)
116                             },
117                               context_instance=RequestContext(request))
118
119 @login_required
120 def container_add(request):
121     """
122     Form for adding a container.
123     """
124     # If user submitted the Container form.
125     if request.method == 'POST':
126         # Fill in ContainerForm with POSTed data.
127         form = ContainerForm(request.POST)
128         
129         # If the form is valid, process it.
130         if form.is_valid():
131             # Create new Container object from form data
132             c_obj = form.save(commit=False)
133             # Added UUID
134             c_obj.uuid = get_uuid()
135             # Save to DB.
136             c_obj.save()
137             # Save the many to many link data.
138             form.save_m2m()
139             return container_summary(request, c_obj.uuid)
140     else:
141         # If users first visit, create empty form.
142         form = ContainerForm()
143         
144     # Load form template
145     c = Context({'form': form,
146                  'action_url': '/samples/container/add/'})
147     t = get_template('generic_form.html')
148
149     return render_to_response('app.html', {
150                                 'app_name': settings.HTSW_ST_APPNAME,
151                                 'page_name': 'Container Add',
152                                 'media': form.media,
153                                 'bcmagic': BarcodeMagicForm(),
154                                 'select': 'container',
155                                 'body': t.render(c)
156                             },
157                               context_instance=RequestContext(request))
158
159 @login_required    
160 def container_edit(request, container_id):
161     """
162     Allow editing of a container
163     """
164     try:
165         container = models.Container.objects.get(uuid=container_id)
166     except ObjectDoesNotExist, e:
167         msg = "Container (%s) cannot be edited as it does not exist." % (container_id)
168         return render_to_response('app.html', {
169                                     'app_name': settings.HTSW_ST_APPNAME,
170                                     'page_name': 'Container Edit',
171                                     'media': '',
172                                     'bcmagic': BarcodeMagicForm(),
173                                     'select': 'container',
174                                     'body': msg
175                                 },
176                                   context_instance=RequestContext(request))
177     
178     # If user submitted the container form.
179     if request.method == 'POST':
180         # Fill in ContainerForm with POSTed data.
181         form = ContainerForm(request.POST, instance=container)
182         
183         # If the form is valid, process it.
184         if form.is_valid():
185             # Save Container object from form data
186             c_obj = form.save(commit=True)
187             # Save many2many changes as well
188             #form.save_m2m() #Not needed when form.save(commit=True)
189             
190             return container_summary(request, c_obj.uuid)
191     else:
192         # If users first visit, create form from Container instance.
193         form = ContainerForm(instance=container)
194
195     # Load form template
196     c = Context({'form': form,
197                  'action_url': '%sedit/' % (container.get_absolute_url())})
198     t = get_template('generic_form.html')
199
200     return render_to_response('app.html', {
201                                 'app_name': settings.HTSW_ST_APPNAME,
202                                 'page_name': 'Container Edit',
203                                 'media': form.media,
204                                 'bcmagic': BarcodeMagicForm(),
205                                 'select': 'container',
206                                 'body': t.render(c)
207                             },
208                               context_instance=RequestContext(request))
209
210 @login_required
211 def container_print(request, container_id):
212     """
213     prints a container label
214     """
215     
216     try:
217         container = models.Container.objects.get(uuid=container_id)
218     except ObjectDoesNotExist:
219         return HttpResponse('Container (%s) does not exist!' % (container_id))
220     
221     params = {}
222     params['line1'] = __center_line('', 10)
223     params['line2'] = __center_line('', 14)
224     params['line3'] = __center_line('%s' % (container.name[16:16+15]), 15)
225     params['container_name'] = __center_line(container.name[0:16], 16)
226     params['barcode'] = 'cntr|%s' % (container.uuid)
227     params['symbol'] = ''
228     
229     c = Context(params)
230     t = get_template('zpl_container_label.txt')
231     print_zpl(t.render(c))
232     
233     return HttpResponse('print command for container %s sent.' % (container.uuid))
234
235
236 ################################################
237 # Freezer
238 ################################################
239 @login_required
240 def freezer_index(request):
241     """
242     Returns an index of available freezers
243     """
244     freezer_list = Freezer.objects.all()
245     c = Context({'freezer_list': freezer_list})
246     t = get_template('freezer_index.html')
247     
248     return render_to_response('app.html', {
249                                 'app_name': "HTSW-SampleTracker",
250                                 'page_name': 'Freezer Index',
251                                 'media': '',
252                                 'bcmagic': BarcodeMagicForm(),
253                                 'select': 'freezer',
254                                 'body': t.render(c)
255                             },
256                               context_instance=RequestContext(request))
257     
258 @login_required    
259 def freezer_summary(request, freezer_id):
260     """
261     Returns summary of freezer_id
262     """
263     # Retrieve freezer by UUID
264     try:
265         freezer = models.Freezer.objects.get(uuid=freezer_id)
266     except ObjectDoesNotExist, e:
267         msg = "Freezer (%s) does not exist." % (freezer_id)
268         return render_to_response('app.html', {
269                                     'app_name': settings.HTSW_ST_APPNAME,
270                                     'page_name': 'Freezer Summary',
271                                     'media': '',
272                                     'bcmagic': BarcodeMagicForm(),
273                                     'select': 'freezer',
274                                     'body': msg
275                                     },
276                                   context_instance=RequestContext(request))
277     
278     # List of contained containers
279     container_list = freezer.container_set.all()
280     
281     
282     # Render prepared container index into freezer summary
283     cf = Context({'freezer': freezer })
284     tf = get_template('freezer_summary.html')
285     
286     # Render Freezer summary to app html
287     return render_to_response('app.html', {
288                                 'app_name': settings.HTSW_ST_APPNAME,
289                                 'page_name': 'Freezer Summary',
290                                 'media': '',
291                                 'bcmagic': BarcodeMagicForm(),
292                                 'select': 'freezer',
293                                 'body': tf.render(cf)
294                             },
295                               context_instance=RequestContext(request))
296
297 @login_required
298 def freezer_add(request):
299     """
300     Allows you to add a new freezer.
301     """
302     # If user submitted the freezer form.
303     if request.method == 'POST':
304         # Fill in FreezerForm with POSTed data.
305         form = FreezerForm(request.POST)
306         
307         # If the form is valid, process it.
308         if form.is_valid():
309             # Create new Freezer object from form data
310             f_obj = form.save(commit=False)
311             # Added UUID
312             f_obj.uuid = get_uuid()
313             # Save to DB.
314             f_obj.save()
315             return freezer_summary(request, f_obj.uuid)
316     else:
317         # If users first visit, create empty form.
318         form = FreezerForm()
319
320     # Load form template
321     c = Context({'form': form,
322                  'action_url': '/samples/freezer/add/'})
323     t = get_template('generic_form.html')
324
325     return render_to_response('app.html', {
326                                 'app_name': settings.HTSW_ST_APPNAME,
327                                 'page_name': 'Freezer Add',
328                                 'media': form.media,
329                                 'bcmagic': BarcodeMagicForm(),
330                                 'select': 'freezer',
331                                 'body': t.render(c)
332                             },
333                               context_instance=RequestContext(request))
334
335 @login_required
336 def freezer_edit(request, freezer_id):
337     """
338     Allow editing of a freezer
339     """
340     try:
341         freezer = models.Freezer.objects.get(uuid=freezer_id)
342     except ObjectDoesNotExist, e:
343         msg = "Freezer (%s) cannot be edited as it does not exist." % (freezer_id)
344         return render_to_response('app.html', {
345                                     'app_name': settings.HTSW_ST_APPNAME,
346                                     'page_name': 'Freezer Summary',
347                                     'media': '',
348                                     'bcmagic': BarcodeMagicForm(),
349                                     'select': 'freezer',
350                                     'body': msg
351                                     },
352                                   context_instance=RequestContext(request))
353     
354     # If user submitted the freezer form.
355     if request.method == 'POST':
356         # Fill in FreezerForm with POSTed data.
357         form = FreezerForm(request.POST, instance=freezer)
358         
359         # If the form is valid, process it.
360         if form.is_valid():
361             # Save Freezer object from form data
362             f_obj = form.save(commit=True)
363             
364             return freezer_summary(request, f_obj.uuid)
365     else:
366         # If users first visit, create form from freezer instance.
367         form = FreezerForm(instance=freezer)
368
369     # Load form template
370     c = Context({'form': form,
371                  'action_url': '%sedit/' % (freezer.get_absolute_url())})
372     t = get_template('generic_form.html')
373
374     return render_to_response('app.html', {
375                                 'app_name': settings.HTSW_ST_APPNAME,
376                                 'page_name': 'Freezer Edit',
377                                 'media': form.media,
378                                 'bcmagic': BarcodeMagicForm(),
379                                 'select': 'freezer',
380                                 'body': t.render(c)
381                             },
382                               context_instance=RequestContext(request))
383
384 @login_required
385 def freezer_print(request, freezer_id):
386     """
387     prints a freezer label
388     """
389     
390     try:
391         freezer = models.Freezer.objects.get(uuid=freezer_id)
392     except ObjectDoesNotExist:
393         return HttpResponse('Freezer (%s) does not exist!' % (freezer_id))
394     
395     params = {}
396     params['line1'] = __center_line('', 10)
397     params['line2'] = __center_line('', 14)
398     params['line3'] = __center_line('Temp: %s C' % (freezer.temperature), 15)
399     params['freezer_name'] = __center_line(freezer.name, 16)
400     params['barcode'] = 'frzr|%s' % (freezer.uuid)
401     params['symbol'] = ''
402     
403     c = Context(params)
404     t = get_template('zpl_freezer_label.txt')
405     print_zpl(t.render(c))
406     
407     return HttpResponse('print command for freezer %s sent.' % (freezer.uuid))
408
409
410 ################################################
411 # Samples
412 ################################################
413 @login_required
414 def sample_index(request):
415     """
416     return a list of samples and what we can do with them.
417     """
418     sample_list = models.Sample.objects.all()
419     
420     # Load form template
421     c = Context({'title': 'Sample Index',
422                  'sample_list': sample_list})
423     t = get_template('sample_index.html')
424     #html.append('%s <a href="/samples/sample/%s/print">(print)</a>' \
425     #            % (sample, sample.sampleid))
426         
427     return render_to_response('app.html', {
428                                 'app_name': settings.HTSW_ST_APPNAME,
429                                 'page_name': 'Samples Index',
430                                 'media': '',
431                                 'bcmagic': BarcodeMagicForm(),
432                                 'select': 'samples',
433                                 'body': t.render(c)
434                             },
435                               context_instance=RequestContext(request))
436
437 @login_required
438 def sample_homeless(request):
439     """
440     Returns an index of homeless samples
441     """
442     sample_list = Sample.objects.filter(container=None)
443     c = Context({'title': 'Homeless Samples',
444                  'sample_list': sample_list})
445     t = get_template('sample_homeless.html')
446     
447     return render_to_response('app.html', {
448                                 'app_name': "HTSW-SampleTracker",
449                                 'page_name': 'Homeless Samples',
450                                 'bcmagic': BarcodeMagicForm(),
451                                 'select': 'samples',
452                                 'body': t.render(c)
453                             },
454                               context_instance=RequestContext(request))
455     
456 @login_required    
457 def sample_add(request):
458     """
459     Allow adding of a new sample
460     """
461     ASSIGNED_CONTAINER = False
462     
463     # If user submitted the sample form.
464     if request.method == 'POST':
465         # Fill in SampleForm with POSTed data.
466         form = SampleForm(request.POST)
467         
468         # If the form is valid, process it.
469         if form.is_valid():
470             # Create new Sample object from form data
471             s_obj = form.save(commit=False)
472             
473             # Add sample ID
474             s_obj.sampleid = get_sampleid()
475             
476             # If the user wants us to assign a container.
477             if form.cleaned_data['assign_container']:
478                 # Choose container
479                 try:
480                     assign_to_container(s_obj)
481                     ASSIGNED_CONTAINER = True
482                 except NoSpaceAvaliable, e:
483                     #return HttpResponse("<b>Error:</b> %s<br /><i>You will need to prepare a new container before continuing.</i>" \
484                     #                    % (e))
485                     ASSIGNED_CONTAINER = False
486                                     
487             # Save to DB.
488             s_obj.save()
489             
490             if not ASSIGNED_CONTAINER:
491                 msg = "NOTE: Sample is homeless"
492                 return sample_summary(request, s_obj.sampleid, msg=msg)
493
494             
495             msg = "Sample created."
496             return sample_summary(request, s_obj.sampleid, msg=msg)
497     else:
498         # If users first visit, create empty form.
499         form = SampleForm()
500
501     # Load form template
502     c = Context({'form': form,
503                  'action_url': '/samples/sample/add/'})
504     t = get_template('generic_form.html')
505
506     return render_to_response('app.html', {
507                                 'app_name': settings.HTSW_ST_APPNAME,
508                                 'page_name': 'Sample Add',
509                                 'media': form.media,
510                                 'bcmagic': BarcodeMagicForm(),
511                                 'select': 'samples',
512                                 'body': t.render(c)
513                             },
514                               context_instance=RequestContext(request))
515     
516 @login_required
517 def sample_edit(request, sampleid):
518     """
519     Allow editing of a sample
520     """
521     try:
522         sample = models.Sample.objects.get(sampleid=sampleid)
523     except ObjectDoesNotExist, e:
524         msg = "Sample (%s) cannot be edited as it does not exist." % (sampleid)
525         return render_to_response('app.html', {
526                     'app_name': settings.HTSW_ST_APPNAME,
527                     'page_name': 'Sample Edit',
528                     'media': '',
529                     'bcmagic': BarcodeMagicForm(),
530                     'select': 'samples',
531                     'body': msg
532                 })
533     
534     # If user submitted the sample form.
535     if request.method == 'POST':
536         # Fill in SampleForm with POSTed data.
537         form = SampleForm(request.POST, instance=sample)
538         
539         # If the form is valid, process it.
540         if form.is_valid():
541             # Save Sample object from form data
542             s_obj = form.save(commit=True)
543             
544             msg = "Sample Update Saved"
545             return sample_summary(request, s_obj.sampleid, msg)
546     else:
547         # If users first visit, create form from sample instance.
548         form = SampleForm(instance=sample)
549
550     # Load form template
551     c = Context({'form': form,
552                  'action_url': '%sedit/' % (sample.get_absolute_url())})
553     t = get_template('generic_form.html')
554
555     return render_to_response('app.html', {
556                                 'app_name': settings.HTSW_ST_APPNAME,
557                                 'page_name': 'Sample Edit',
558                                 'media': form.media,
559                                 'bcmagic': BarcodeMagicForm(),
560                                 'select': 'samples',
561                                 'body': t.render(c)
562                             },
563                               context_instance=RequestContext(request))
564
565 @login_required
566 def sample_assign_container(request, sampleid):
567     """
568     Assigns sample to container using the assign to container algorithm
569     """
570     
571     sample = Sample.objects.get(sampleid=sampleid)
572     
573     try:
574         assign_to_container(sample)
575     except NoSpaceAvaliable, e:
576         return render_to_response('app.html', {
577                                     'app_name': settings.HTSW_ST_APPNAME,
578                                     'page_name': 'Sample Assign',
579                                     'media': '',
580                                     'bcmagic': BarcodeMagicForm(),
581                                     'select': 'samples',
582                                     'body': mark_safe("<b>Error:</b> %s<br /><i>You will need to prepare a new container before continuing.</i>" \
583                                                         % (e))
584                                     },
585                                   context_instance=RequestContext(request))
586         
587     sample.save()
588     
589     body = 'Sample (<a href="%s">%s</a>) assigned to container (<a href="%s">%s</a>)' \
590            % (sample.get_absolute_url(), str(sample), sample.container.get_absolute_url(), str(sample.container))
591     
592     return render_to_response('app.html', {
593                                 'app_name': settings.HTSW_ST_APPNAME,
594                                 'page_name': 'Sample Assign',
595                                 'media': '',
596                                 'bcmagic': BarcodeMagicForm(),
597                                 'select': 'samples',
598                                 'body': mark_safe(body),
599                             },
600                             context_instance=RequestContext(request))
601
602 @login_required
603 def sample_summary(request, sampleid, msg=None):
604     """
605     Display a summary of a given sample
606     """
607     try:
608         sample = models.Sample.objects.get(sampleid=sampleid)
609     except ObjectDoesNotExist, e:
610         msg = "Sample (%s) does not exist." % (sampleid)
611         return render_to_response('app.html', {
612                                     'app_name': settings.HTSW_ST_APPNAME,
613                                     'page_name': 'Sample Summary',
614                                     'media': '',
615                                     'bcmagic': BarcodeMagicForm(),
616                                     'select': 'samples',
617                                     'body': msg
618                                 },
619                                   context_instance=RequestContext(request))
620     
621     c = Context({'sample': sample,
622                  'msg': msg,})
623     t = get_template('sample_summary.html')
624     
625     return render_to_response('app.html', {
626                                 'app_name': settings.HTSW_ST_APPNAME,
627                                 'page_name': 'Sample Summary',
628                                 'media': '',
629                                 'bcmagic': BarcodeMagicForm(),
630                                 'select': 'samples',
631                                 'body': t.render(c)
632                             },
633                               context_instance=RequestContext(request))
634
635 @login_required  
636 def sample_print(request, sampleid):
637     """
638     prints a sample!
639     """
640     
641     try:
642         sample = models.Sample.objects.get(sampleid=sampleid)
643     except ObjectDoesNotExist:
644         return HttpResponse('Sample (%s) does not exist!' % (sampleid))
645     
646     params = {}
647     params['fullid'] = str(sample)
648     params['sampleid'] = __center_line("s|%s" % (sample.sampleid), 16)
649     params['line1'] = __center_line(sample.name[0:10], 10)
650     params['line2'] = __center_line(sample.name[10:25], 14)
651     params['line3'] = __center_line('ExpType %s' % (sample.sample_type.name[0:8]), 15)
652     params['slot_num'] = random.randint(1,81)
653     
654     c = RequestContext(request, params)
655     t = get_template('half_inch_samples.txt')
656     print_zpl(t.render(c))
657     
658     return HttpResponse('print command for sample %s sent.' % (sample.sampleid))
659
660 @login_required
661 def user_profile(request):
662     """
663     Information about the user
664     """
665     return render_to_response('registration/profile.html', {
666                                 'app_name': settings.HTSW_ST_APPNAME,
667                                 'page_name': 'User Profile',
668                                 'media': '',
669                                 'bcmagic': BarcodeMagicForm(),
670                                 'select': 'settings',
671                             },
672                               context_instance=RequestContext(request))
673
674 ################################################
675 # Barcode Magic Commands
676 ################################################
677 @login_required
678 def cmd_move_sample(request):
679     """
680     Moves a sample to a target container
681     """
682     return render_to_response('app.html', {
683                                 'app_name': settings.HTSW_ST_APPNAME,
684                                 'page_name': 'CMD: Move Sample',
685                                 'media': '',
686                                 'bcmagic': BarcodeMagicForm(),
687                                 'select': 'samples',
688                                 'body': ""
689                             },
690                               context_instance=RequestContext(request))