# -*- coding: utf-8 -*- import json from io import StringIO from gsxws import escalations from django import template from django.contrib import messages from django.http import HttpResponse from django.utils.translation import ugettext as _ from django.forms.models import modelformset_factory from django.views.decorators.csrf import csrf_exempt from django.shortcuts import render, redirect, get_object_or_404 from django.contrib.auth.decorators import permission_required from django.core.files.base import ContentFile from reportlab.lib.units import mm from reportlab.graphics.shapes import Drawing from reportlab.graphics.barcode import createBarcodeDrawing from servo.lib.utils import paginate from servo.models import (Order, Template, Tag, Customer, Note, Attachment, Escalation, Article,) from servo.forms import NoteForm, NoteSearchForm, EscalationForm class BarcodeDrawing(Drawing): """Pretty generic Reportlab drawing to render barcodes.""" def __init__(self, text_value, *args, **kwargs): barcode = createBarcodeDrawing("Code128", value=text_value.encode("utf-8"), barHeight=10 * mm, width=80 * mm) Drawing.__init__(self, barcode.width, barcode.height, *args, **kwargs) self.add(barcode, name="barcode") def show_barcode(request, text): """Return text as a barcode.""" if request.GET.get('f') == 'svg': import barcode output = StringIO.StringIO() code = barcode.Code39(text, add_checksum=False) code.write(output) contents = output.getvalue() output.close() return HttpResponse(contents, content_type="image/svg+xml") d = BarcodeDrawing(text) return HttpResponse(d.asString("png"), content_type="image/png") def prep_list_view(request, kind): """Prepare the view for listing notes/messages.""" data = {'title': _("Messages")} all_notes = Note.objects.all().order_by("-created_at") if kind == "articles": all_notes = Article.objects.all().order_by('-date_created') if kind == "inbox": all_notes = all_notes.filter(order=None).order_by("is_read", "-created_at") if kind == "sent": all_notes = all_notes.filter(created_by=request.user) if kind == "flagged": all_notes = all_notes.filter(is_flagged=True) if kind == "escalations": all_notes = Note.objects.all().exclude(escalation=None) page = request.GET.get("page") notes = paginate(all_notes, page, 20) data['kind'] = kind data['notes'] = notes data['search_hint'] = "notes" data['inbox_count'] = Note.objects.filter(order=None).count() return data @permission_required('servo.change_note') def copy(request, pk): """Copy a note with its attachments and labels.""" note = get_object_or_404(Note, pk=pk) new_note = Note(created_by=request.user) new_note.body = note.body new_note.order = note.order new_note.subject = note.subject new_note.save() new_note.labels = note.labels.all() for a in note.attachments.all(): # also copy the attachments a.pk = None a.content_object = new_note a.save() new_note.attachments.add(a) return redirect(edit, pk=new_note.pk, order_id=note.order_id) @permission_required('servo.change_note') def edit(request, pk=None, order_id=None, parent=None, recipient=None, customer=None): """ Edit a note. @FIXME: Should split this up into smaller pieces """ to = [] order = None command = _('Save') note = Note(order_id=order_id) excluded_emails = note.get_excluded_emails() if recipient is not None: to.append(recipient) command = _('Send') if order_id is not None: order = get_object_or_404(Order, pk=order_id) if order.user and (order.user != request.user): note.is_read = False if order.user.email not in excluded_emails: to.append(order.user.email) if order.customer is not None: customer = order.customer_id if customer is not None: customer = get_object_or_404(Customer, pk=customer) note.customer = customer if order_id is None: to.append(customer.email) tpl = template.Template(note.subject) note.subject = tpl.render(template.Context({'note': note})) note.recipient = ', '.join(to) note.created_by = request.user note.sender = note.get_default_sender() fields = escalations.CONTEXTS try: note.escalation = Escalation(created_by=request.user) except Exception as e: messages.error(request, e) return redirect(request.META['HTTP_REFERER']) AttachmentFormset = modelformset_factory(Attachment, fields=('content',), can_delete=True, extra=3, exclude=[]) formset = AttachmentFormset(queryset=Attachment.objects.none()) if pk is not None: note = get_object_or_404(Note, pk=pk) formset = AttachmentFormset(queryset=note.attachments.all()) if parent is not None: parent = get_object_or_404(Note, pk=parent) note.parent = parent note.body = parent.quote() if parent.subject: note.subject = _(u'Re: %s') % parent.clean_subject() if parent.sender not in excluded_emails: note.recipient = parent.sender if parent.order: order = parent.order note.order = parent.order note.customer = parent.customer note.escalation = parent.escalation note.is_reported = parent.is_reported title = note.subject form = NoteForm(instance=note) if note.escalation: contexts = json.loads(note.escalation.contexts) escalation_form = EscalationForm(prefix='escalation', instance=note.escalation) if request.method == "POST": escalation_form = EscalationForm(request.POST, prefix='escalation', instance=note.escalation) if escalation_form.is_valid(): note.escalation = escalation_form.save() form = NoteForm(request.POST, instance=note) if form.is_valid(): note = form.save() formset = AttachmentFormset(request.POST, request.FILES) if formset.is_valid(): files = formset.save(commit=False) for f in files: f.content_object = note try: f.save() except ValueError as e: messages.error(request, e) return redirect(note) note.attachments.add(*files) if form.cleaned_data.get('attach_confirmation'): from servo.views.order import put_on_paper response = put_on_paper(request, note.order_id, fmt='pdf') filename = response.filename content = response.render().content content = ContentFile(content, filename) attachment = Attachment(content=content, content_object=note) attachment.save() attachment.content.save(filename, content) note.attachments.add(attachment) note.save() try: msg = note.send_and_save(request.user) messages.success(request, msg) except ValueError as e: messages.error(request, e) return redirect(note) return render(request, "notes/form.html", locals()) def delete_note(request, pk): """ Deletes a note """ note = get_object_or_404(Note, pk=pk) if request.method == 'POST': note.delete() messages.success(request, _("Note deleted")) if request.session.get('return_to'): url = request.session.get('return_to') del(request.session['return_to']) elif note.order_id: url = note.order.get_absolute_url() return redirect(url) return render(request, 'notes/remove.html', {'note': note}) @csrf_exempt def render_template(request, order_id=None): """ Renders the template with this title with the current Service Order as the context """ title = request.POST.get('title') tpl = get_object_or_404(Template, title=title) content = tpl.content if order_id: order = get_object_or_404(Order, pk=order_id) content = tpl.render(order) return HttpResponse(content) def templates(request, template_id=None): if template_id: tpl = get_object_or_404(Template, pk=template_id) content = tpl.content if request.session.get('current_order_id'): tpl = template.Template(content) order = Order.objects.get(pk=request.session['current_order_id']) content = tpl.render(template.Context({'order': order})) return HttpResponse(content) templates = Template.objects.all() return render(request, 'notes/templates.html', {'templates': templates}) def toggle_flag(request, kind, pk, flag): """ Toggles a flag of a note (read/unread, flagged/not, reported/not) """ if kind == 'articles': note = get_object_or_404(Article, pk=pk) if flag == 'flagged': note.toggle_flagged(request.user) return HttpResponse(note.get_flagged_title(request.user)) if flag == 'read': note.toggle_read(request.user) return HttpResponse(note.get_read_title(request.user)) field = 'is_%s' % flag note = get_object_or_404(Note, pk=pk) attr = getattr(note, field) setattr(note, field, not attr) note.save() return HttpResponse(getattr(note, 'get_%s_title' % flag)()) def toggle_tag(request, pk, tag_id): note = get_object_or_404(Note, pk=pk) tag = get_object_or_404(Tag, pk=tag_id) if tag in note.labels.all(): note.labels.remove(tag) else: note.labels.add(tag) if note.order: return redirect(note.order) return HttpResponse(_('OK')) def list_notes(request, kind="inbox"): data = prep_list_view(request, kind) request.session['return_to'] = request.path return render(request, "notes/list_notes.html", data) def view_note(request, kind, pk): data = prep_list_view(request, kind) if kind == 'articles': note = get_object_or_404(Article, pk=pk) data['read_title'] = note.get_read_title(request.user) data['flagged_title'] = note.get_flagged_title(request.user) else: note = get_object_or_404(Note, pk=pk) data['title'] = note.get_title() data['note'] = note if kind == 'escalations': return render(request, "notes/view_escalation.html", data) if kind == 'articles': return render(request, "notes/view_article.html", data) return render(request, "notes/view_note.html", data) def find(request): """ Notes advanced search """ form = NoteSearchForm(request.GET) results = Note.objects.none() if request.GET and form.is_valid(): fdata = form.cleaned_data results = Note.objects.all() if fdata.get('body'): results = results.filter(body__icontains=fdata['body']) if fdata.get('recipient'): results = results.filter(recipient__icontains=fdata['recipient']) if fdata.get('sender'): results = results.filter(sender__icontains=fdata['sender']) if fdata.get('order_code'): results = results.filter(order__code__icontains=fdata['order_code']) results = results.order_by('-created_at') title = _('Message search') notes = paginate(results, request.GET.get('page'), 10) return render(request, "notes/find.html", locals()) def edit_escalation(request): pass def create_escalation(request): esc = Escalation() form = EscalationForm() title = _('Edit Escalation') if request.method == 'POST': data = request.POST.copy() data['created_by'] = request.user form = EscalationForm(data, request.FILES, instance=esc) if form.is_valid(): note = form.save() #esc.submit(request.user) return redirect(view_note, 'escalations', note.pk) return render(request, 'notes/edit_escalation.html', locals()) def list_messages(request, pk): note = get_object_or_404(Note, pk=pk) messages = note.message_set.all() return render(request, "notes/messages.html", locals())