def _generate_invoice(self, subscription, invoice_start, invoice_end): invoice, is_new_invoice = Invoice.objects.get_or_create( subscription=subscription, date_start=invoice_start, date_end=invoice_end, is_hidden=subscription.do_not_invoice, ) if not is_new_invoice: raise InvoiceAlreadyCreatedError( "invoice id: {id}".format(id=invoice.id)) if subscription.subscriptionadjustment_set.count() == 0: # record that the subscription was created SubscriptionAdjustment.record_adjustment( subscription, method=SubscriptionAdjustmentMethod.TASK, invoice=invoice, ) DomainInvoiceFactory._generate_line_items(invoice, subscription) invoice.calculate_credit_adjustments() invoice.update_balance() invoice.save() visible_domain_invoices = Invoice.objects.filter( is_hidden=False, subscription__subscriber__domain=invoice.get_domain(), ) total_balance = sum(invoice.balance for invoice in visible_domain_invoices) should_set_date_due = (total_balance > SMALL_INVOICE_THRESHOLD or (invoice.account.auto_pay_enabled and total_balance > Decimal(0))) if should_set_date_due: days_until_due = DEFAULT_DAYS_UNTIL_DUE if subscription.date_delay_invoicing is not None: td = subscription.date_delay_invoicing - self.date_end days_until_due = max(days_until_due, td.days) invoice.date_due = self.date_end + datetime.timedelta( days_until_due) invoice.save() return invoice
def _generate_customer_invoice(self): invoice, is_new_invoice = CustomerInvoice.objects.get_or_create( account=self.account, date_start=self.date_start, date_end=self.date_end) if not is_new_invoice: raise InvoiceAlreadyCreatedError( "invoice id: {id}".format(id=invoice.id)) all_subscriptions = [] for plan in self.subscriptions: # Use oldest subscription to bill client for the full length of their software plan self.subscriptions[plan].sort(key=lambda s: s.date_start) oldest_subscription = self.subscriptions[plan][0] generate_line_items(invoice, oldest_subscription) all_subscriptions.extend(self.subscriptions[plan]) invoice.subscriptions.set(all_subscriptions) invoice.calculate_credit_adjustments() invoice.update_balance() invoice.save() self._update_invoice_due_date(invoice, self.date_end) self.customer_invoice = invoice
def create_invoice_for_subscription(self, subscription): if subscription.is_trial: # Don't create invoices for trial subscriptions logger.info("[BILLING] Skipping invoicing for Subscription " "%s because it's a trial." % subscription.pk) return if subscription.date_start > self.date_start: invoice_start = subscription.date_start else: invoice_start = self.date_start if (subscription.date_end is not None and subscription.date_end <= self.date_end): # Since the Subscription is actually terminated on date_end # have the invoice period be until the day before date_end. invoice_end = subscription.date_end - datetime.timedelta(days=1) else: invoice_end = self.date_end invoice, is_new_invoice = Invoice.objects.get_or_create( subscription=subscription, date_start=invoice_start, date_end=invoice_end, is_hidden=subscription.do_not_invoice, ) if not is_new_invoice: raise InvoiceAlreadyCreatedError( "invoice id: {id}".format(id=invoice.id)) if subscription.subscriptionadjustment_set.count() == 0: # record that the subscription was created SubscriptionAdjustment.record_adjustment( subscription, method=SubscriptionAdjustmentMethod.TASK, invoice=invoice, ) self.generate_line_items(invoice, subscription) invoice.calculate_credit_adjustments() invoice.update_balance() invoice.save() total_balance = sum( invoice.balance for invoice in Invoice.objects.filter( is_hidden=False, subscription__subscriber__domain=invoice.get_domain(), )) if total_balance > SMALL_INVOICE_THRESHOLD: days_until_due = DEFAULT_DAYS_UNTIL_DUE if subscription.date_delay_invoicing is not None: td = subscription.date_delay_invoicing - self.date_end days_until_due = max(days_until_due, td.days) invoice.date_due = self.date_end + datetime.timedelta( days_until_due) invoice.save() record = BillingRecord.generate_record(invoice) try: record.send_email() except InvoiceEmailThrottledError as e: if not self.logged_throttle_error: logger.error("[BILLING] %s" % e) self.logged_throttle_error = True return invoice