<commit_before># -*- encoding: utf-8 -*-
from __future__ import unicode_literals

import io

from datetime import date
from decimal import Decimal

from django.core.files.base import ContentFile

from reportlab.lib import colors
from reportlab.lib.pagesizes import A4
from reportlab import platypus

from crm.models import Contact
from .models import (
    Invoice,
    InvoiceError,
    InvoiceLine,
    InvoiceSettings,
    TimeRecord,
)
from .pdf_utils import (
    MyReport,
    NumberedCanvas,
)


class InvoiceCreate(object):
    """ Create invoices for outstanding time records """

    def _add_time_records(self, user, invoice, time_records):
        """Add time records to a draft invoice."""
        print_settings = self._get_print_settings()
        for tr in time_records:
            invoice_line = InvoiceLine(
                user=user,
                invoice=invoice,
                line_number=invoice.get_next_line_number(),
                quantity=tr.invoice_quantity,
                price=invoice.contact.hourly_rate,
                units='hours',
                vat_rate=print_settings.vat_rate
            )
            invoice_line.save()
            # link time record to invoice line
            tr.invoice_line = invoice_line
            tr.save()

    def create(self, user, contact, iteration_end):
        """ Create invoices from time records """
        self.is_valid(contact, raise_exception=True)
        invoice = None
        time_records = TimeRecord.objects.to_invoice(contact, iteration_end)
        if time_records.count():
            invoice = Invoice(
                invoice_date=date.today(),
                contact=contact,
                user=user,
            )
            invoice.save()
        self._add_time_records(user, invoice, time_records)
        return invoice

    def draft(self, contact, iteration_end):
        """Return a queryset with time records selected to invoice"""
        return TimeRecord.objects.to_invoice(contact, iteration_end)

    def refresh(self, user, invoice, iteration_end):
        """Add invoice lines to a previously created (draft) invoice."""
        if not invoice.is_draft:
            raise InvoiceError(
                "Time records can only be added to a draft invoice."
            )
        self._add_time_records(
            user,
            invoice,
            TimeRecord.objects.to_invoice(invoice.contact, iteration_end)
        )

    def is_valid(self, contact, raise_exception=None):
        result = []
        try:
            InvoiceSettings.objects.get()
        except InvoiceSettings.DoesNotExist:
            result.append(
                'Invoice print settings have not been set-up in admin'
            )<commit_msg>invoice - use a transaction #650<commit_after># -*- encoding: utf-8 -*-
from __future__ import unicode_literals

import io

from datetime import date
from decimal import Decimal

from django.core.files.base import ContentFile
from django.db import transaction

from reportlab.lib import colors
from reportlab.lib.pagesizes import A4
from reportlab import platypus

from crm.models import Contact
from .models import (
    Invoice,
    InvoiceError,
    InvoiceLine,
    InvoiceSettings,
    TimeRecord,
)
from .pdf_utils import (
    MyReport,
    NumberedCanvas,
)


class InvoiceCreate(object):
    """ Create invoices for outstanding time records """

    def _add_time_records(self, user, invoice, time_records):
        """Add time records to a draft invoice."""
        print_settings = self._get_print_settings()
        for tr in time_records:
            invoice_line = InvoiceLine(
                user=user,
                invoice=invoice,
                line_number=invoice.get_next_line_number(),
                quantity=tr.invoice_quantity,
                price=invoice.contact.hourly_rate,
                units='hours',
                vat_rate=print_settings.vat_rate
            )
            invoice_line.save()
            # link time record to invoice line
            tr.invoice_line = invoice_line
            tr.save()

    def create(self, user, contact, iteration_end):
        """ Create invoices from time records """
        self.is_valid(contact, raise_exception=True)
        invoice = None
        time_records = TimeRecord.objects.to_invoice(contact, iteration_end)
        with transaction.atomic():
            if time_records.count():
                invoice = Invoice(
                    invoice_date=date.today(),
                    contact=contact,
                    user=user,
                )
                invoice.save()
            self._add_time_records(user, invoice, time_records)
        return invoice

    def draft(self, contact, iteration_end):
        """Return a queryset with time records selected to invoice"""
        return TimeRecord.objects.to_invoice(contact, iteration_end)

    def refresh(self, user, invoice, iteration_end):
        """Add invoice lines to a previously created (draft) invoice."""
        if not invoice.is_draft:
            raise InvoiceError(
                "Time records can only be added to a draft invoice."
            )
        self.is_valid(invoice.contact, raise_exception=True)
        with transaction.atomic():
            self._add_time_records(
                user,
                invoice,
                TimeRecord.objects.to_invoice(invoice.contact, iteration_end)
            )

    def is_valid(self, contact, raise_exception=None):
        result = []
        try:
            InvoiceSettings.objects.get()
        except InvoiceSettings.DoesNotExist:
            result.append(
                'Invoice print settings have not been set-up in admin'
            )
{'fraction_non_alphanumeric': 0.07707095421181405, 'fraction_numerical': 0.001223348479552604, 'mean_word_length': 2.100216684723727, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5351368', 'n_tokens_mistral': 1564, 'n_tokens_neox': 1468, 'n_words': 402}