예제 #1
0
    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.auto_generate_credits:
            for product_rate in subscription.plan_version.product_rates.all():
                CreditLine.add_credit(
                    product_rate.monthly_fee, subscription=subscription, product_type=product_rate.product.product_type
                )

        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)
        date_due = self.date_end + datetime.timedelta(days_until_due)

        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 = Invoice(
            subscription=subscription,
            date_start=invoice_start,
            date_end=invoice_end,
            date_due=date_due,
            is_hidden=subscription.do_not_invoice,
        )
        invoice.save()

        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()

        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
예제 #2
0
    def _create_invoice_for_subscription(self, subscription):
        def _get_invoice_start(sub, date_start):
            if sub.date_start > date_start:
                return sub.date_start
            else:
                return date_start

        def _get_invoice_end(sub, date_end):
            if sub.date_end is not None and sub.date_end <= date_end:
                # Since the Subscription is actually terminated on date_end
                # have the invoice period be until the day before date_end.
                return sub.date_end - datetime.timedelta(days=1)
            else:
                return date_end

        if subscription.is_trial:
            # Don't create invoices for trial subscriptions
            log_accounting_info(
                "Skipping invoicing for Subscription %s because it's a trial."
                % subscription.pk
            )
            return

        if (
            subscription.skip_invoicing_if_no_feature_charges
            and not subscription.plan_version.feature_charges_exist_for_domain(self.domain)
        ):
            log_accounting_info(
                "Skipping invoicing for Subscription %s because there are no feature charges."
                % subscription.pk
            )
            return

        invoice_start = _get_invoice_start(subscription, self.date_start)
        invoice_end = _get_invoice_end(subscription, self.date_end)

        with transaction.atomic():
            invoice = self._generate_invoice(subscription, invoice_start, invoice_end)
            record = BillingRecord.generate_record(invoice)
        if record.should_send_email:
            try:
                record.send_email(contact_emails=self.recipients)
            except InvoiceEmailThrottledError as e:
                if not self.logged_throttle_error:
                    log_accounting_error(e.message)
                    self.logged_throttle_error = True
        else:
            record.skipped_email = True
            record.save()

        return invoice
예제 #3
0
    def _create_invoice_for_subscription(self, subscription):
        def _get_invoice_start(sub, date_start):
            return max(sub.date_start, date_start)

        def _get_invoice_end(sub, date_end):
            if sub.date_end is not None and sub.date_end <= date_end:
                # Since the Subscription is actually terminated on date_end
                # have the invoice period be until the day before date_end.
                return sub.date_end - datetime.timedelta(days=1)
            else:
                return date_end

        invoice_start = _get_invoice_start(subscription, self.date_start)
        invoice_end = _get_invoice_end(subscription, self.date_end)

        with transaction.atomic():
            invoice = self._generate_invoice(subscription, invoice_start,
                                             invoice_end)
            record = BillingRecord.generate_record(invoice)
        if record.should_send_email:
            try:
                if invoice.subscription.service_type == SubscriptionType.IMPLEMENTATION:
                    if self.recipients:
                        for email in self.recipients:
                            record.send_email(contact_email=email)
                    elif invoice.account.dimagi_contact:
                        record.send_email(
                            contact_email=invoice.account.dimagi_contact,
                            cc_emails=[settings.ACCOUNTS_EMAIL])
                    else:
                        record.send_email(
                            contact_email=settings.ACCOUNTS_EMAIL)
                else:
                    for email in self.recipients or invoice.get_contact_emails(
                    ):
                        record.send_email(contact_email=email)
            except InvoiceEmailThrottledError as e:
                if not self.logged_throttle_error:
                    log_accounting_error(str(e))
                    self.logged_throttle_error = True
        else:
            record.skipped_email = True
            record.save()

        return invoice
예제 #4
0
 def setUp(self):
     super(TestBillingRecord, self).setUp()
     self.billing_contact = generator.arbitrary_web_user()
     self.dimagi_user = generator.arbitrary_web_user(is_dimagi=True)
     self.domain = Domain(name='test')
     self.domain.save()
     self.invoice_start, self.invoice_end = get_previous_month_date_range()
     self.currency = generator.init_default_currency()
     self.account = generator.billing_account(self.dimagi_user, self.billing_contact)
     self.subscription, self.subscription_length = generator.generate_domain_subscription_from_date(
         datetime.date.today(), self.account, self.domain.name
     )
     self.invoice = Invoice(
         subscription=self.subscription,
         date_start=self.invoice_start,
         date_end=self.invoice_end,
         is_hidden=False,
     )
     self.billing_record = BillingRecord(invoice=self.invoice)
예제 #5
0
    def _create_invoice_for_subscription(self, subscription):
        def _get_invoice_start(sub, date_start):
            return max(sub.date_start, date_start)

        def _get_invoice_end(sub, date_end):
            if sub.date_end is not None and sub.date_end <= date_end:
                # Since the Subscription is actually terminated on date_end
                # have the invoice period be until the day before date_end.
                return sub.date_end - datetime.timedelta(days=1)
            else:
                return date_end

        invoice_start = _get_invoice_start(subscription, self.date_start)
        invoice_end = _get_invoice_end(subscription, self.date_end)

        with transaction.atomic():
            invoice = self._generate_invoice(subscription, invoice_start, invoice_end)
            record = BillingRecord.generate_record(invoice)
        if record.should_send_email:
            try:
                if invoice.subscription.service_type == SubscriptionType.IMPLEMENTATION:
                    if self.recipients:
                        for email in self.recipients:
                            record.send_email(contact_email=email)
                    elif invoice.account.dimagi_contact:
                        record.send_email(contact_email=invoice.account.dimagi_contact,
                                          cc_emails=[settings.ACCOUNTS_EMAIL])
                    else:
                        record.send_email(contact_email=settings.ACCOUNTS_EMAIL)
                else:
                    for email in self.recipients or invoice.contact_emails:
                        record.send_email(contact_email=email)
            except InvoiceEmailThrottledError as e:
                if not self.logged_throttle_error:
                    log_accounting_error(six.text_type(e))
                    self.logged_throttle_error = True
        else:
            record.skipped_email = True
            record.save()

        return invoice
예제 #6
0
    def _create_invoice_for_subscription(self, subscription):
        def _get_invoice_start(sub, date_start):
            if sub.date_start > date_start:
                return sub.date_start
            else:
                return date_start

        def _get_invoice_end(sub, date_end):
            if (
                sub.date_end is not None
                and sub.date_end <= date_end
            ):
                # Since the Subscription is actually terminated on date_end
                # have the invoice period be until the day before date_end.
                return sub.date_end - datetime.timedelta(days=1)
            else:
                return date_end

        if subscription.is_trial:
            # Don't create invoices for trial subscriptions
            log_accounting_info(
                "Skipping invoicing for Subscription %s because it's a trial."
                % subscription.pk
            )
            return

        invoice_start = _get_invoice_start(subscription, self.date_start)
        invoice_end = _get_invoice_end(subscription, self.date_end)

        with transaction.atomic():
            invoice = self._generate_invoice(subscription, invoice_start, invoice_end)
            record = BillingRecord.generate_record(invoice)
        try:
            record.send_email()
        except InvoiceEmailThrottledError as e:
            if not self.logged_throttle_error:
                log_accounting_error(e.message)
                self.logged_throttle_error = True

        return invoice
예제 #7
0
    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
예제 #8
0
    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.auto_generate_credits:
            for product_rate in subscription.plan_version.product_rates.all():
                CreditLine.add_credit(
                    product_rate.monthly_fee,
                    subscription=subscription,
                    product_type=product_rate.product.product_type,
                )

        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)
        date_due = self.date_end + datetime.timedelta(days_until_due)

        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 = Invoice(
            subscription=subscription,
            date_start=invoice_start,
            date_end=invoice_end,
            date_due=date_due,
            is_hidden=subscription.do_not_invoice,
        )
        invoice.save()

        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()

        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
예제 #9
0
    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