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 })
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
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
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 })
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())
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'
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
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]
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]
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()