Example #1
0
def email2ticket(string):
    """ Parse un mail et crée ou modifie le ticket concerné """
    errors = []

    mail = email.message_from_string(string)
    cur = None

    match = pattern_from.search(mail.get('From', ''))

    mail_from = mail.get('Return-Path',
        mail.get('Reply-To', match.groups()[0] if match else None))

    references = mail.get('References', '').split()

    if not references:
        references = mail.get('In-Reply-To', '').split()

    if references:
        ticket = Ticket.objects.get(message_id__in=references)
    else:
        ticket = Ticket()

    # Get first part
    for part in mail.walk():
        if part.get_content_type() in ('text/html', 'text/plain'):
            cur = part
            break

    if cur is None:
        return send_error(mail_from, ['Impossible de parser le message'])

    content = cur.get_payload(decode=True)

    if cur.get_content_type() == 'text/html':
        enc = cur.get_charsets()[0]
        content = content.decode(enc, 'ignore')
        content = html2text(content)

    match = pattern_body.search(content)

    if not match:
        errors.append('Contenu vide ou non encadré par [contenu][/contenu]')
        content = None
    else:
        content = match.groups()[0]

    user = User.objects.get(pk=settings.EMAIL_USER_PK)

    if references and content:  # New comment
        form = type("", (), {})()
        form.cleaned_data = {'comment': content, 'internal': False}
        form.instance = ticket
        request = type("", (), {})()
        request.user = user
        post_comment(form, request)
        print "Ticket commenté ", ticket.pk
    elif not references:  # New ticket
        try:
            subject = mail.get('Subject', '')
            match = pattern_subject.search(subject)
            ticket.client = Client.objects.get(pk=match.groups()[0])
            subject = subject[match.span()[1]:]
            ticket.title = " ".join([part[0].decode(part[1] or 'utf8') for part in email.header.decode_header(subject)])
        except:
            errors.append('Impossible de parser le sujet, client invalide ou sujet mal formé')

        if errors:
            send_error(mail_from, errors)
        else:
            ticket.message_id = mail.get('Message-ID', None)
            ticket.opened_by = user
            ticket.state = State.objects.get(pk=settings.TICKET_STATE_NEW)
            ticket.category = Category.objects.get(pk=settings.EMAIL_TICKET_CATEGORY_DEFAULT)
            ticket.text = content
            ticket.save()
            print "Ticket crée : ", ticket.pk
    elif errors:
        send_error(mail_from, errors)

    # Get attachements
    for part in mail.walk():
        filename = part.get_filename()
        content_type = part.get_content_type()
        if filename and content_type in settings.IMAP_ALLOWED_CONTENT_TYPES:
            ticket_file = TicketFile(ticket=ticket,
                                     filename=filename,
                                     content_type=content_type,
                                     data=part.get_payload(decode=True))
            ticket_file.save()
Example #2
0
def modify(request, ticket_id):
    def exit_action():
        saveaction = request.POST.get("savebutton", "save")
        if saveaction == "save":
            return redirect("ticket_modify", ticket_id=ticket_id)
        elif saveaction == "new":
            return redirect("ticket_partial_new")
        elif saveaction == "return":
            backlinks = request.backlinks
            precedent = backlinks[-1:]
            if not precedent:
                return redirect("ticket_modify", ticket_id=ticket_id)
            else:
                return precedent[0].redirect(request)
        else:
            raise PermissionDenied("Hacking attempt!")

    qs = Ticket.objects.all().filter_ticket_by_user(request.user, no_client=True)
    ticket = get_object_or_404(qs, pk=ticket_id)

    # Si c'est un fils rediriger vers le pêre au bon endroit
    # (C'est utile uniquement pour le chargement de la page)
    if ticket.parent:
        return http.HttpResponseRedirect("/ticket/modify/%d/#child%s" % (ticket.parent_id, ticket_id))

    if not ticket.text and ticket.title == INVALID_TITLE:
        ticket.title = None

    # Si le ticket n'est pas rattaché à aucun client, on l'affecte au client de l'utilisateur
    if not ticket.client:
        ticket.client = request.user.my_userprofile.client

    if request.user.has_perm("ticket.add_ticket_full"):
        template_name = "ticket/modify.html"
        TicketForm = NewTicketForm
        child = ticket.child.order_by('date_open')
        TicketChildForm = ChildForm
    else:
        template_name = "ticket/modify_small.html"
        TicketForm = NewTicketSmallForm
        child = ticket.child.filter(diffusion=True).order_by('date_open')
        TicketChildForm = ChildFormSmall

    ChildFormSet = modelformset_factory(Ticket,
                                        form=TicketChildForm,
                                        extra=0,
                                        can_delete=True)

    if request.method == "POST":
        if (request.POST.get("_validate-ticket", None) and
        request.user.has_perm("ticket.can_validate_ticket") and
        ticket.validated_by is None):
            ticket.validated_by = request.user
            ticket.save()
        # Instanciating the TicketForm changes ticket... So we need to store it
        # Before in order to do permission checking.
        ticket_old_assigned_to_pk = ticket.assigned_to and ticket.assigned_to.pk or None

        form = TicketForm(request.POST,
                          request.FILES,
                          instance=ticket,
                          user=request.user)

        # Il faut valider les fils en premier pour ne pas se faire jetter si on ferme tout
        child_formset = ChildFormSet(request.POST, queryset=child)
        deleted_forms = child_formset.deleted_forms if hasattr(child_formset, 'deleted_forms') else []

        # Save existing childs
        for f in child_formset.initial_forms:
            if not f in deleted_forms and f.is_valid():
                f.save()
                post_comment(f, request)

        for f in deleted_forms:
            f.instance.delete()

        # Add new childs
        if request.user.has_perm('ticket.can_add_child'):
            for f in child_formset.extra_forms:
                if f.is_valid():
                    new_child = copy_model_instance(ticket)

                    # Valeurs à écraser
                    for a in f.Meta.fields:
                        setattr(new_child, a, f.cleaned_data.get(a))

                    new_child.opened_by = request.user
                    new_child.date_open = datetime.datetime.now()
                    new_child.parent = ticket
                    new_child.save()
                    f.instance = new_child
                    post_comment(f, request)

        if form.is_valid():
            # Si l'utilisateur peut assigner ce ticket à l'utilisateur passé en POST
            if not request.user.is_superuser and \
                    form.cleaned_data["assigned_to"] and \
                    ticket_old_assigned_to_pk != form.cleaned_data["assigned_to"].pk and \
                    form.cleaned_data["assigned_to"] not in ClaritickUser.objects.get(pk=request.user.pk).get_child_users():
                raise PermissionDenied()

            form.save()
            post_comment(form, request)
            update_ticket_last_seen(request, ticket.pk)

            # Alarme automatique
            if (ticket.priority
            and ticket.priority.alarm
            and not ticket.ticketalarm_set.all()):
                ticket.ticketalarm_set.create(reason=ticket.priority.alarm,
                                              user_open=request.user)

            # Appel du client
            if form.cleaned_data['appel']:
                ticket.ticketappel_set.create(user=request.user)

            # Rappels de ticket
            rappel = None

            if form.cleaned_data['calendar_rappel']:
                ident = ticket.pk
                current_user = User.objects.get(pk=request.user.id)
                # Select or create existing rappel
                try:
                    rappel = Rappel.objects.filter(ticket=ident) \
                        .filter(user=current_user).get()
                except Rappel.DoesNotExist:
                    rappel = Rappel()

                rappel.ticket = ticket
                rappel.date_email = None
                rappel.date = form.cleaned_data['calendar_rappel']
                rappel.user = current_user
                rappel.save()

            if form.cleaned_data['delete_rappel'] and rappel:
                rappel.delete()

            file = form.cleaned_data["file"]
            if file:
                ticket_file = TicketFile(ticket=ticket,
                                         filename=file.name,
                                         content_type=file.content_type)
                if file.multiple_chunks():
                    dataList = []
                    for chunk in file.chunks():
                        dataList.append(chunk)
                    data = "".join(dataList)
                else:
                    data = file.read()
                ticket_file.data = data
                ticket_file.save()

            # BonDeCommande
            if form.cleaned_data["bondecommande"]:
                bdc = form.cleaned_data["bondecommande"]
                if bdc.ticket:
                    raise PermissionDenied()
                if ticket.client and bdc.client != ticket.client:
                    raise PermissionDenied("Etes vous sur de vouloir faire ça ? Ce n'est pas le meme client.")
                bdc.ticket = ticket
                bdc.save()
            return exit_action()
    else:
        try:
            rappel = Rappel.objects.get(ticket=ticket, user=request.user)
            rappel_date = rappel.date
        except Rappel.DoesNotExist:
            rappel_date = ""

        form = TicketForm(instance=ticket,
                          user=request.user,
                          initial={"calendar_rappel": rappel_date})
        child_formset = ChildFormSet(queryset=child)
        for f in child_formset.forms:
            filter_form_for_user(f, request.user)

    comments = django.contrib.comments.get_model().objects.filter(content_type__model="ticket").\
        filter(models.Q(object_pk__in=[str(c.pk) for c in child]) | models.Q(object_pk=str(ticket.pk)))
    ticket.comment = []
    for c in comments:
        if c.object_pk == str(ticket.pk):
            ticket.comment.append(c)
        else:
            for f in child_formset.forms:
                if not hasattr(f.instance, 'comment'):
                    f.instance.comment = []
                if c.object_pk == str(f.instance.pk):
                    f.instance.comment.append(c)

    update_ticket_last_seen(request, ticket.pk)

    # List of rappel other user about the same ticket
    list_rappel_other_user = Rappel.objects.all() \
        .select_related('user__username') \
        .filter(ticket=ticket.pk) \
        .exclude(user=request.user)

    # Bon de commande
    bondecommades = BonDeCommande.objects.all().filter_by_user(request.user).filter(ticket=ticket.pk)

    return render_to_response(template_name,
        {
            "form": form,
            "child_formset": child_formset,
            "bondecommandes": bondecommades,
            "list_rappel_other_user": list_rappel_other_user,
        },
        context_instance=RequestContext(request))