Beispiel #1
0
def create(request):
    choice_member = Member.objects.all()
    if not request.POST:
        return render(request, 'invoice.html',
                      {'choice_member': choice_member})
    else:
        member_id = request.POST['member_id']

        invoice_number_max = Invoice.objects.all().aggregate(
            Max('invoice_number'))['invoice_number__max']
        invoice_number = invoice_number_max + 1

        member = Member.objects.get(pk=member_id)
        usages = Usage.objects.filter(member=member, valid=True, invoice=None)

        total_amount = usages.aggregate(total=Sum('total_price'))['total']

        invoice = Invoice(amount=total_amount,
                          member=member,
                          invoice_number=invoice_number)
        invoice.save()

        usages.update(invoice=invoice)
        usages = Usage.objects.filter(invoice=invoice)

        return render(
            request, 'invoice.html', {
                'usages': usages,
                'member_info': member,
                'choice_member': choice_member,
                'invoice': invoice
            })
Beispiel #2
0
def generate_child_invoice(**kwargs):
    """
    function to generate a new child invoice based upon the parent
    """
    try:
        parent = Invoice.objects.get(
            invoice_number=kwargs['args'])  # invoice instance
        child = Invoice()
        child.client = parent.client
        child.tax = parent.tax
        child.discount_rate = parent.discount_rate
        child.issued_by = parent.issued_by
        child.invoice_status = Invoice.INVOICE_STATUS[1][0]
        child.recurring = Invoice.RECURRING[0][0]
        child.parent_invoice = parent
        child.date_due = timezone.now().date()
        child.save()
        # save the new m2m intermediary model
        parent_units = Units.objects.filter(invoice=parent)
        for item in parent_units.iterator():
            new = Units()
            new.invoice = child
            new.item = item.item
            new.quantity = item.quantity
            new.save()
        # generate pdf and send email (note: email=False, as already being dispatched due to creation of new PDF)
        invoicing_view.pdf_gen_or_fetch_or_email(
            invoice_number=child.invoice_number,
            type=invoicing_view.PDF_TYPES.get('invoice'),
            email=False,
            regenerate=False)
        return True
    except Invoice.DoesNotExist:
        return None
Beispiel #3
0
    def make_invoice(self, issuer):
        """Creates an invoice based on the current quotation/purchase order"""
        from invoicing.models import Invoice, InvoiceRevision
        # Initialize the invoice
        invoice = Invoice(full_init=False,
                          tenant=self.tenant,
                          account_type=self.account_type,
                          issuer=issuer,
                          organization=self.organization,
                          contact=self.contact,
                          related_to=self,
                          group=self.group,
                          attachments=self.attachments)

        # Save the invoice, based on the quotation/purchase order
        inv_data = invoice.add_revision(revision=InvoiceRevision(
            based_on=self.current_revision))
        inv_data.state = invoice.state
        inv_data.issuer = issuer
        inv_data.issue_date = datetime_now()
        inv_data.invoicing_date = datetime.date.today()
        inv_data.due_date = get_due_date(
            inv_data.invoicing_date,
            self.tenant.tenant_settings.invoicing.payment_conditions)
        invoice.save()

        # Update state
        if self.is_quotation():
            self.state = QUOTATION_STATES.INVOICED
        elif self.is_purchase_order():
            self.state = PURCHASE_ORDER_STATES.INVOICED
        self.save()
        return invoice
Beispiel #4
0
def preview(request):

    #Todo SELECT DISTINCT member from Usage where factNumber is null
    choice_member = Member.objects.exclude(usage=None)

    if not request.POST:
        return render(request, 'invoice.html',
                      {'choice_member': choice_member})

    else:
        member_id = request.POST['member_id']

        invoice_number_max = Invoice.objects.all().aggregate(
            Max('invoice_number'))['invoice_number__max']
        invoice_number = invoice_number_max + 1

        member = Member.objects.get(pk=member_id)
        usages = Usage.objects.filter(member=member, valid=True, invoice=None)

        total_amount = usages.aggregate(total=Sum('total_price'))['total'] or 0

        usages_annotated = usages.values(
            'resource__name', 'resource__unit__name', 'unit_price',
            'project__name').annotate(
                qty=Sum('qty'),
                total_price=Sum('total_price')).order_by('project__name')

        # information about machine hours for animators
        amount_machine_before = AccountEntry.objects.filter(
            member=member).aggregate(total=Sum('amount_machine'))['total'] or 0
        amount_machine_usages = usages.filter(
            resource__payable_by_animation_hours=True).aggregate(
                total=Sum('total_price'))['total'] or 0

        deduction = min(amount_machine_before, amount_machine_usages)

        amount_machine_after = amount_machine_before - deduction

        amount_due = total_amount - deduction

        invoice = Invoice(amount=total_amount,
                          amount_deduction=deduction,
                          amount_due=amount_due,
                          member=member,
                          invoice_number=invoice_number)

        print(total_amount)

        return render(
            request, 'invoice.html', {
                'usages': usages,
                'usages_anotated': usages_annotated,
                'member_info': member,
                'choice_member': choice_member,
                'invoice': invoice,
                'amount_machine_before': amount_machine_before,
                'amount_machine_after': amount_machine_after,
                'amount_machine_usages': amount_machine_usages
            })
Beispiel #5
0
    def test_invoiced_true(self):
        unit = ResourceUnit(name="heure")
        resource = Resource(name="Laser",
                            slug="laser",
                            unit=unit,
                            price_not_member=2,
                            price_member=1)
        usage = Usage(resource=resource, qty=5)

        invoice = Invoice(invoice_number=100, amount=50)
        usage.invoice = invoice

        self.assertTrue(usage.invoiced())
Beispiel #6
0
def test_pay_invoice(client):
    with db.connection() as DB:
        invoice = Invoice(amount=5, description='Test invoice')
        DB.add(invoice)

    request_data = {'amount': 5}

    response = client.post('/invoices/{0}/pay/'.format(invoice.id),
                           json=request_data)
    data = response.json

    print(data)

    assert data['amount_remaining'] == 0
    assert data['status'] == 'Paid'
Beispiel #7
0
def test_get_invoice(client):
    with db.connection() as DB:
        invoice = Invoice(amount=5, description='Test invoice')
        DB.add(invoice)

    response = client.get('/invoices/{0}/'.format(invoice.id))
    data = response.json
    data['amount'] = Decimal(data['amount'])
    data['amount_remaining'] = Decimal(data['amount_remaining'])

    invoice_details = invoice.to_json()
    invoice_details['created_at'] = invoice_details['created_at'].strftime(DATE_FORMAT)  # noqa
    invoice_details['updated_at'] = invoice_details['updated_at'].strftime(DATE_FORMAT)  # noqa

    assert data == invoice_details
Beispiel #8
0
def test_list_invoices(client):
    with db.connection() as DB:
        invoice = Invoice(amount=5, description='Test invoice')
        DB.add(invoice)

    response = client.get('/invoices/')
    data = response.json
    for n in range(len(data)):
        data[n]['amount'] = Decimal(data[n]['amount'])
        data[n]['amount_remaining'] = Decimal(data[n]['amount_remaining'])

    invoice_details = invoice.to_json()
    invoice_details['created_at'] = invoice_details['created_at'].strftime(DATE_FORMAT)  # noqa
    invoice_details['updated_at'] = invoice_details['updated_at'].strftime(DATE_FORMAT)  # noqa

    assert data == [invoice_details]
Beispiel #9
0
    def setUpClass(cls):
        from contacts.models import Organization
        from invoicing.models import Invoice, Currency
        from notification import models as notification_models
        super(NotificationResourceTest, cls).setUpClass()

        cls.payload_kwargs = {
            'data': {},
            'HTTP_X_TENANT': settings.TENANT.slug
        }

        # Retrieve currency which will be referenced
        eur = Currency.objects.get(symbol='EUR')

        # Create an organization which will be referenced
        organization = Organization.objects.create(tenant=settings.TENANT,
                                                   creator=settings.VOSAE_USER,
                                                   corporate_name="My Company",
                                                   private=False)

        # Create deps documents
        invoice = Invoice(tenant=settings.TENANT,
                          account_type='RECEIVABLE',
                          issuer=settings.VOSAE_USER)
        invoice.current_revision.currency = eur.get_snapshot()
        invoice.current_revision.organization = organization
        invoice.save()

        # Create a notification
        notification = notification_models.InvoiceChangedState()
        notification.previous_state = "DRAFT"
        notification.new_state = "REGISTERED"
        notification.issuer = settings.VOSAE_USER
        notification.recipient = settings.VOSAE_USER
        notification.tenant = settings.TENANT
        notification.invoice = invoice
        notification.save()

        cls.cached_data = {
            'invoice_uri':
            cls.resourceDetailURI('invoice', unicode(invoice.id)),
            'notification_uri':
            cls.resourceDetailURI('notification', unicode(notification.id))
        }
        cls.created_documents = [organization, notification, invoice]
Beispiel #10
0
def prepare(request, create=False):
    member_id = request.POST['member_id']

    invoice_number_max = Invoice.objects.all().aggregate(Max('invoice_number'))['invoice_number__max'] or 0
    invoice_number = invoice_number_max + 1

    member = Member.objects.get(pk=member_id)
    usages = Usage.objects.filter(member=member, valid=True, invoice=None)

    total_amount = usages.aggregate(total=Sum('total_price'))['total'] or 0

    usages_annotated = usages.values('resource__name',
                                     'resource__unit__name',
                                     'unit_price',
                                     'project__name').annotate(qty=Sum('qty'), total_price=Sum('total_price')
                                                               ).order_by('project__name')

    balance = AccountEntry.objects.filter(member=member).aggregate(machine=Sum('amount_machine'),
                                                                   cash=Sum('amount_cash'))

    print(balance)
    # information about machine hours balance
    amount_machine_before = balance['machine'] or 0
    amount_machine_usages = usages.filter(resource__payable_by_animation_hours=True).aggregate(
        total=Sum('total_price'))['total'] or 0

    deduction_machine = min(amount_machine_before, amount_machine_usages)
    amount_machine_after = amount_machine_before - deduction_machine

    # information about cash balance
    cash_before = balance['cash'] or 0
    remaining_amount = total_amount - deduction_machine
    deduction_cash = min(cash_before, remaining_amount)
    cash_after = cash_before - deduction_cash

    deduction = deduction_machine + deduction_cash

    invoice = Invoice(amount=total_amount,
                      amount_deduction=deduction,
                      member=member,
                      invoice_number=invoice_number)

    print(total_amount)
    if create:
        invoice.save()
        if deduction > 0:
            AccountEntry.objects.create(member=member, amount_machine=-deduction_machine, amount_cash=-deduction_cash, invoice=invoice)

        usages.update(invoice=invoice)
        usages = Usage.objects.filter(invoice=invoice)

    return {'usages': usages,
            'usages_anotated': usages_annotated,
            'member_info': member,
            'invoice': invoice,
            'amount_machine_before': amount_machine_before,
            'amount_machine_after': amount_machine_after,
            'amount_machine_usages': amount_machine_usages,
            'deduction_machine': deduction_machine,
            'cash_before': cash_before,
            'cash_after': cash_after,
            'deduction_cash': deduction_cash
            }
def main():
    """
    Find subscriptions that are due to be invoiced, generate the invoices, 
    update the accounts, update the subscription and kill all humans
    """

    invoices = []
    try:
        # Get current subscriptions and subscriptions that have not been (fully) invoiced and are due to be invoiced.
        subscriptions = Subscription.objects.filter(active = 1)
        subscriptions = subscriptions.filter(Q(invoiced_until_date__isnull = True) | Q(invoiced_until_date__gte = F('start_date')))
        subscriptions = subscriptions.filter(Q(end_date__isnull = True) | Q(invoiced_until_date__lte = F('end_date')))
        subscriptions = subscriptions.filter(Q(invoiced_until_date__isnull = True) | Q(invoiced_until_date__lte = datetime.utcnow()))

        for subscription in subscriptions:
            invoice = Invoice()
            invoice.customer = subscription.customer
            invoice.date = date.today()
            invoice.save()

            if subscription.invoiced_until_date:
                start_date = subscription.invoiced_until_date
            else:
                start_date = subscription.start_date

            # Invoice every invoice period that needs to be invoiced.
            while start_date < datetime.utcnow():
                #
                # Calculate the date until which we are invoicing
                #
    
                if subscription.product.invoice_interval == 0:
                    subscription.invoiced_until_date = start_date + timedelta(days = subscription.product.invoice_interval_count * subscription.intervals_per_invoice)

                if subscription.product.invoice_interval == 1:
                    subscription.invoiced_until_date = start_date + timedelta(weeks = subscription.product.invoice_interval_count * subscription.intervals_per_invoice)

                elif subscription.product.invoice_interval == 2:
                    months = subscription.product.invoice_interval_count * subscription.intervals_per_invoice
                    month = start_date.month + months % 12
                    year = start_date.year + int(months / 12)
                    subscription.invoiced_until_date = datetime(year, month, start_date.day, 0, 0, 0)

                elif subscription.product.invoice_interval == 3:
                    quarters = subscription.product.invoice_interval_count * subscription.intervals_per_invoice
                    month = start_date.month + (quarters * 3) % 12
                    year = start_date.year + int((quarters * 3) / 12)
                    subscription.invoiced_until_date = datetime(year, month, start_date.day, 0, 0, 0)
    
                elif subscription.product.invoice_interval == 4:
                    years = subscription.product.invoice_interval_count * subscription.intervals_per_invoice
                    subscription.invoiced_until_date = datetime(start_date.year + years, month, day, 0, 0, 0)

                # Add the subscription lines to the invoice
                invoiceitem = InvoiceItem()
                invoiceitem.invoice = invoice
                invoiceitem.item = None # Only used for products with serials
                invoiceitem.product = subscription.product
                invoiceitem.period = start_date.strftime("%Y-%m-%d") + " - " + subscription.invoiced_until_date.strftime("%Y-%m-%d")
                invoiceitem.description = subscription.extra_info
                invoiceitem.count = 1
                invoiceitem.amount = subscription.product.get_price()
                if invoiceitem.amount == None:
                    # This item has no price
                    raise LookupError
    
                invoiceitem.amount *= subscription.intervals_per_invoice
                invoiceitem.vat = subscription.product.vat
                invoiceitem.save()

                start_date = subscription.invoiced_until_date

            # This subscription has been invoiced.
            subscription.save()

            # The transactions should be made to the VAT tables and accounts receivable
            invoice.book()        

            invoices.append(invoice)

    except:
        db_trans.rollback()
        raise
    else:
        db_trans.commit()

    for invoice in invoices:
            # Mail the invoice to the client if requested, otherwise put the PDF in the outgoing snailmail queue
            if invoice.customer.invoice_by_email:
                pdf = invoice.pdf()
                send_mail("%s <%s>" % (invoice.customer.displayname, invoice.customer.invoice_email), invoice.full_invoice_no, pdf)
            else:
                # FIXME Snailmail queue should be here
                pass
    db_trans.commit()