def test_user_over_limit_in_yearly_invoice(self):
        num_users = self.user_rate.monthly_limit + 1
        generator.arbitrary_commcare_users_for_domain(self.domain.name,
                                                      num_users)

        num_users_advanced = self.advanced_rate.monthly_limit + 2
        generator.arbitrary_commcare_users_for_domain(self.domain2.name,
                                                      num_users_advanced)

        self.account.invoicing_plan = InvoicingPlan.YEARLY
        self.account.save()
        invoice_date = utils.months_from_date(self.subscription.date_start, 14)
        invoice_start, invoice_end = get_previous_month_date_range(
            invoice_date)
        invoice_start = invoice_start - relativedelta(months=11)
        invoice_factory = CustomerAccountInvoiceFactory(
            account=self.account,
            date_start=invoice_start,
            date_end=invoice_end)
        invoice_factory.create_invoice()
        self.assertEqual(CustomerInvoice.objects.count(), 1)

        invoice = CustomerInvoice.objects.first()
        user_line_items = invoice.lineitem_set.get_feature_by_type(
            FeatureType.USER)
        self.assertEqual(user_line_items.count(), 2)
        for user_line_item in user_line_items:
            if self.user_rate.feature.name == user_line_item.feature_rate.feature.name:
                self.assertEqual(user_line_item.quantity, 12)
            elif user_line_item.feature_rate.feature.name == self.advanced_rate.feature.name:
                self.assertEqual(user_line_item.quantity, 24)
    def test_under_limit(self):
        num_users = random.randint(0, self.user_rate.monthly_limit)
        generator.arbitrary_commcare_users_for_domain(self.domain.name,
                                                      num_users)

        num_users_advanced = random.randint(0,
                                            self.advanced_rate.monthly_limit)
        generator.arbitrary_commcare_users_for_domain(self.domain2.name,
                                                      num_users_advanced)

        invoice_date = utils.months_from_date(
            self.subscription.date_start,
            random.randint(2, self.subscription_length))
        invoice_start, invoice_end = get_previous_month_date_range(
            invoice_date)
        invoice_factory = CustomerAccountInvoiceFactory(
            account=self.account,
            date_start=invoice_start,
            date_end=invoice_end)
        invoice_factory.create_invoice()
        self.assertEqual(CustomerInvoice.objects.count(), 1)

        invoice = CustomerInvoice.objects.first()
        self.assertEqual(invoice.balance, Decimal('1100.0000'))
        user_line_items = invoice.lineitem_set.get_feature_by_type(
            FeatureType.USER)
        self.assertEqual(user_line_items.count(), 2)
        for user_line_item in user_line_items:
            self.assertEqual(user_line_item.quantity, 0)
            self.assertEqual(user_line_item.subtotal, Decimal('0.0000'))
            self.assertEqual(user_line_item.total, Decimal('0.0000'))
            self.assertIsNone(user_line_item.base_description)
            self.assertEqual(user_line_item.base_cost, Decimal('0.0000'))
            self.assertIsNone(user_line_item.unit_description)
            self.assertEqual(user_line_item.unit_cost, Decimal('2.0000'))
    def test_product_line_items(self):
        invoice_date = utils.months_from_date(
            self.subscription.date_start,
            random.randint(2, self.subscription_length))
        invoice_start, invoice_end = get_previous_month_date_range(
            invoice_date)
        invoice_factory = CustomerAccountInvoiceFactory(
            account=self.account,
            date_start=invoice_start,
            date_end=invoice_end)
        invoice_factory.create_invoice()
        self.assertEqual(CustomerInvoice.objects.count(), 1)

        invoice = CustomerInvoice.objects.first()
        product_line_items = invoice.lineitem_set.get_products()
        self.assertEqual(product_line_items.count(), 2)
        for line_item in product_line_items:
            self.assertTrue(line_item.base_description
                            == 'One month of CommCare Advanced Software Plan.'
                            or line_item.base_description
                            == 'One month of CommCare Standard Software Plan.')
            self.assertTrue(
                line_item.base_cost == self.product_rate.monthly_fee
                or line_item.base_cost
                == self.advanced_plan.product_rate.monthly_fee)
    def test_only_invoice_active_subscriptions(self):
        """
        Test that only active subscriptions are invoiced.
        Two subscriptions of the same plan only create one product line item and one set of feature line items
        """
        invoice_date = utils.months_from_date(self.sub2.date_end, 1)
        invoice_start, invoice_end = get_previous_month_date_range(
            invoice_date)
        invoice_factory = CustomerAccountInvoiceFactory(
            account=self.account,
            date_start=invoice_start,
            date_end=invoice_end)
        invoice_factory.create_invoice()

        self.assertEqual(CustomerInvoice.objects.count(), 1)
        invoice = CustomerInvoice.objects.first()
        self.assertEqual(invoice.balance, Decimal('1000.0000'))
        self.assertEqual(invoice.account, self.account)

        num_product_line_items = invoice.lineitem_set.get_products().count()
        self.assertEqual(num_product_line_items, 1)

        num_feature_line_items = invoice.lineitem_set.get_features().count()
        self.assertEqual(num_feature_line_items,
                         self.sub2.plan_version.feature_rates.count())
    def test_multiple_subscription_invoice(self):
        invoice_date = utils.months_from_date(
            self.subscription.date_start,
            random.randint(2, self.subscription_length))
        invoice_start, invoice_end = get_previous_month_date_range(
            invoice_date)
        invoice_factory = CustomerAccountInvoiceFactory(
            account=self.account,
            date_start=invoice_start,
            date_end=invoice_end)
        invoice_factory.create_invoice()

        self.assertEqual(CustomerInvoice.objects.count(), 1)
        invoice = CustomerInvoice.objects.first()
        self.assertGreater(invoice.balance, Decimal('0.0000'))
        self.assertEqual(invoice.account, self.account)

        num_product_line_items = invoice.lineitem_set.get_products().count()
        self.assertEqual(num_product_line_items, 2)

        num_feature_line_items = invoice.lineitem_set.get_features().count()
        self.assertEqual(
            num_feature_line_items,
            self.subscription.plan_version.feature_rates.count() +
            self.sub2.plan_version.feature_rates.count())
 def _create_sms_line_items_for_quarter(self):
     invoice_start, invoice_end = get_previous_month_date_range(
         self.invoice_date)
     invoice_factory = CustomerAccountInvoiceFactory(
         account=self.account,
         date_start=invoice_start,
         date_end=invoice_end)
     invoice_factory.create_invoice()
     self.assertEqual(CustomerInvoice.objects.count(), 1)
     invoice = CustomerInvoice.objects.first()
     return invoice.lineitem_set.get_feature_by_type(FeatureType.SMS)
 def test_no_invoice_before_start(self):
     """
     Test that an invoice is not created if its subscriptions didn't start in the previous month.
     """
     invoice_start, invoice_end = get_previous_month_date_range(
         self.subscription.date_start)
     invoice_factory = CustomerAccountInvoiceFactory(
         account=self.account,
         date_start=invoice_start,
         date_end=invoice_end)
     invoice_factory.create_invoice()
     self.assertEqual(CustomerInvoice.objects.count(), 0)
 def test_no_invoice_after_end(self):
     """
     No invoices should be generated for the months after the end date of the subscriptions.
     """
     invoice_date = utils.months_from_date(self.sub2.date_end, 2)
     invoice_start, invoice_end = get_previous_month_date_range(
         invoice_date)
     invoice_factory = CustomerAccountInvoiceFactory(
         account=self.account,
         date_start=invoice_start,
         date_end=invoice_end)
     invoice_factory.create_invoice()
     self.assertEqual(CustomerInvoice.objects.count(), 0)
    def test_over_limit(self):
        num_users = self.user_rate.monthly_limit + 1
        generator.arbitrary_commcare_users_for_domain(self.domain.name,
                                                      num_users)

        num_users_advanced = self.advanced_rate.monthly_limit + 1
        generator.arbitrary_commcare_users_for_domain(self.domain2.name,
                                                      num_users_advanced)

        invoice_date = utils.months_from_date(
            self.subscription.date_start,
            random.randint(2, self.subscription_length))
        invoice_start, invoice_end = get_previous_month_date_range(
            invoice_date)
        invoice_factory = CustomerAccountInvoiceFactory(
            account=self.account,
            date_start=invoice_start,
            date_end=invoice_end)
        invoice_factory.create_invoice()
        self.assertEqual(CustomerInvoice.objects.count(), 1)

        invoice = CustomerInvoice.objects.first()
        user_line_items = invoice.lineitem_set.get_feature_by_type(
            FeatureType.USER)
        self.assertEqual(user_line_items.count(), 2)
        for user_line_item in user_line_items:
            self.assertIsNone(user_line_item.base_description)
            self.assertEqual(user_line_item.base_cost, Decimal('0.0000'))
            num_to_charge = num_users - self.user_rate.monthly_limit
            self.assertEqual(num_to_charge, user_line_item.quantity)
            if self.user_rate.feature.name == user_line_item.feature_rate.feature.name:
                self.assertEqual(user_line_item.unit_cost,
                                 self.user_rate.per_excess_fee)
                self.assertEqual(user_line_item.total,
                                 self.user_rate.per_excess_fee * num_to_charge)
                self.assertEqual(user_line_item.subtotal,
                                 self.user_rate.per_excess_fee * num_to_charge)
            elif user_line_item.feature_rate.feature.name == self.advanced_rate.feature.name:
                self.assertEqual(user_line_item.unit_cost,
                                 self.advanced_rate.per_excess_fee)
                self.assertEqual(
                    user_line_item.total,
                    self.advanced_rate.per_excess_fee * num_to_charge)
                self.assertEqual(
                    user_line_item.subtotal,
                    self.advanced_rate.per_excess_fee * num_to_charge)
    def test_sms_over_limit_in_yearly_invoice(self):
        num_sms = random.randint(self.sms_rate.monthly_limit + 1,
                                 self.sms_rate.monthly_limit + 2)
        billables = arbitrary_sms_billables_for_domain(self.domain,
                                                       self.sms_date, num_sms)
        num_sms_advanced = random.randint(
            self.advanced_sms_rate.monthly_limit + 1,
            self.advanced_sms_rate.monthly_limit + 2)
        advanced_billables = arbitrary_sms_billables_for_domain(
            self.domain2, self.sms_date, num_sms_advanced)

        invoice_start, invoice_end = get_previous_month_date_range(
            self.invoice_date)
        invoice_start = invoice_start - relativedelta(months=11)
        invoice_factory = CustomerAccountInvoiceFactory(
            account=self.account,
            date_start=invoice_start,
            date_end=invoice_end)
        invoice_factory.create_invoice()
        self.assertEqual(CustomerInvoice.objects.count(), 1)
        invoice = CustomerInvoice.objects.first()

        sms_line_items = invoice.lineitem_set.get_feature_by_type(
            FeatureType.SMS)
        self.assertEqual(sms_line_items.count(), 2)
        for sms_line_item in sms_line_items:
            self.assertIsNone(sms_line_item.base_description)
            self.assertEqual(sms_line_item.base_cost, Decimal('0.0000'))
            self.assertEqual(sms_line_item.quantity, 1)

            if self.advanced_sms_rate.feature == sms_line_item.feature_rate.feature:
                sms_cost = sum(
                    billable.gateway_charge + billable.usage_charge
                    for billable in
                    advanced_billables[self.advanced_sms_rate.monthly_limit:])
            else:
                sms_cost = sum(
                    billable.gateway_charge + billable.usage_charge
                    for billable in billables[self.sms_rate.monthly_limit:])
            self.assertEqual(sms_line_item.unit_cost, sms_cost)
            self.assertEqual(sms_line_item.total, sms_cost)
    def test_product_line_items_in_yearly_invoice(self):
        self.account.invoicing_plan = InvoicingPlan.YEARLY
        self.account.save()
        invoice_date = utils.months_from_date(self.subscription.date_start, 14)
        invoice_start, invoice_end = get_previous_month_date_range(
            invoice_date)
        invoice_start = invoice_start - relativedelta(months=11)
        invoice_factory = CustomerAccountInvoiceFactory(
            account=self.account,
            date_start=invoice_start,
            date_end=invoice_end)
        invoice_factory.create_invoice()

        self.assertEqual(CustomerInvoice.objects.count(), 1)
        invoice = CustomerInvoice.objects.first()
        self.assertGreater(invoice.balance, Decimal('0.0000'))
        self.assertEqual(invoice.account, self.account)

        # There should be two product line items, with 3 months billed for each
        num_product_line_items = invoice.lineitem_set.get_products().count()
        self.assertEqual(num_product_line_items, 2)
        for product_line_item in invoice.lineitem_set.get_products().all():
            self.assertEqual(product_line_item.quantity, 12)
    def setUp(self):
        super(TestInvoicingMethods, self).setUp()
        self.invoice_start = datetime.date(2018, 5, 1)
        self.invoice_end = datetime.date(2018, 5, 31)

        self.domain = generator.arbitrary_domain()
        self.account = BillingAccount.get_or_create_account_by_domain(
            domain=self.domain, created_by="TEST"
        )[0]
        self.account.is_customer_billing_account = True
        self.account.save()
        self.invoice_factory = CustomerAccountInvoiceFactory(self.invoice_start, self.invoice_end, self.account)
        self.advanced_plan = DefaultProductPlan.get_default_plan_version(edition=SoftwarePlanEdition.ADVANCED)
        self.advanced_plan.plan.is_customer_software_plan = True
        self.pro_plan = DefaultProductPlan.get_default_plan_version(edition=SoftwarePlanEdition.PRO)
        self.pro_plan.plan.is_customer_software_plan = True
        self.subscription = Subscription.new_domain_subscription(
            self.account,
            self.domain.name,
            self.advanced_plan,
            date_start=self.invoice_start,
            date_end=self.invoice_end
        )
Пример #13
0
def generate_invoices(based_on_date=None):
    """
    Generates all invoices for the past month.
    """
    today = based_on_date or datetime.date.today()
    invoice_start, invoice_end = get_previous_month_date_range(today)
    log_accounting_info(
        "Starting up invoices for %(start)s - %(end)s" % {
            'start': invoice_start.strftime(USER_DATE_FORMAT),
            'end': invoice_end.strftime(USER_DATE_FORMAT),
        })
    all_domain_ids = [d['id'] for d in Domain.get_all(include_docs=False)]
    for domain_doc in iter_docs(Domain.get_db(), all_domain_ids):
        domain_obj = Domain.wrap(domain_doc)
        if not domain_obj.is_active:
            continue
        try:
            invoice_factory = DomainInvoiceFactory(invoice_start, invoice_end,
                                                   domain_obj)
            invoice_factory.create_invoices()
            log_accounting_info("Sent invoices for domain %s" %
                                domain_obj.name)
        except CreditLineError as e:
            log_accounting_error(
                "There was an error utilizing credits for "
                "domain %s: %s" % (domain_obj.name, e),
                show_stack_trace=True,
            )
        except InvoiceError as e:
            log_accounting_error(
                "Could not create invoice for domain %s: %s" %
                (domain_obj.name, e),
                show_stack_trace=True,
            )
        except Exception as e:
            log_accounting_error(
                "Error occurred while creating invoice for "
                "domain %s: %s" % (domain_obj.name, e),
                show_stack_trace=True,
            )
    all_customer_billing_accounts = BillingAccount.objects.filter(
        is_customer_billing_account=True)
    for account in all_customer_billing_accounts:
        try:
            if account.invoicing_plan == InvoicingPlan.QUARTERLY:
                customer_invoice_start = invoice_start - relativedelta(
                    months=2)
            elif account.invoicing_plan == InvoicingPlan.YEARLY:
                customer_invoice_start = invoice_start - relativedelta(
                    months=11)
            else:
                customer_invoice_start = invoice_start
            invoice_factory = CustomerAccountInvoiceFactory(
                account=account,
                date_start=customer_invoice_start,
                date_end=invoice_end)
            invoice_factory.create_invoice()
        except CreditLineError as e:
            log_accounting_error(
                "There was an error utilizing credits for "
                "domain %s: %s" % (domain_obj.name, e),
                show_stack_trace=True,
            )
        except InvoiceError as e:
            log_accounting_error(
                "Could not create invoice for domain %s: %s" %
                (domain_obj.name, e),
                show_stack_trace=True,
            )
        except Exception as e:
            log_accounting_error(
                "Error occurred while creating invoice for "
                "domain %s: %s" % (domain_obj.name, e),
                show_stack_trace=True,
            )

    if not settings.UNIT_TESTING:
        _invoicing_complete_soft_assert(False, "Invoicing is complete!")