def setUp(self):
        super(TestUserRoleSubscriptionChanges, self).setUp()
        self.domain = generator.arbitrary_domain()
        UserRole.init_domain_with_presets(self.domain.name)
        self.user_roles = UserRole.by_domain(self.domain.name)
        self.custom_role = UserRole.get_or_create_with_permissions(
            self.domain.name,
            Permissions(edit_apps=True, edit_web_users=True),
            "Custom Role"
        )
        self.custom_role.save()
        self.read_only_role = UserRole.get_read_only_role_by_domain(self.domain.name)

        self.admin_user = generator.arbitrary_web_user()
        self.admin_user.add_domain_membership(self.domain.name, is_admin=True)
        self.admin_user.save()

        self.web_users = []
        self.commcare_users = []
        for role in [self.custom_role] + self.user_roles:
            web_user = generator.arbitrary_web_user()
            web_user.add_domain_membership(self.domain.name, role_id=role.get_id)
            web_user.save()
            self.web_users.append(web_user)

            commcare_user = generator.arbitrary_commcare_user(
                domain=self.domain.name)
            commcare_user.set_role(self.domain.name, role.get_qualified_id())
            commcare_user.save()
            self.commcare_users.append(commcare_user)

        self.account = BillingAccount.get_or_create_account_by_domain(
            self.domain.name,created_by=self.admin_user.username)[0]
        self.advanced_plan = DefaultProductPlan.get_default_plan_by_domain(
            self.domain.name,edition=SoftwarePlanEdition.ADVANCED)
示例#2
0
    def test_community_over_limit(self):
        """
        For a domain under community (no subscription) with users over the community limit, make sure that:
        - base_description is None
        - base_cost is 0.0
        - unit_description is not None
        - unit_cost is equal to the per_excess_fee on the user rate
        - quantity is equal to number of commcare users in that domain minus the monthly_limit on the user rate
        - total and subtotals are equal to number of extra users * per_excess_fee
        """
        domain = generator.arbitrary_domain()
        num_active = generator.create_excess_community_users(domain)

        account = BillingAccount.get_or_create_account_by_domain(
            domain, created_by=self.dimagi_user)[0]
        billing_contact = generator.arbitrary_contact_info(account, self.dimagi_user)
        billing_contact.save()
        account.date_confirmed_extra_charges = datetime.date.today()
        account.save()

        tasks.generate_invoices()
        subscriber = Subscriber.objects.get(domain=domain.name)
        invoice = Invoice.objects.filter(subscription__subscriber=subscriber).get()
        user_line_item = invoice.lineitem_set.get_feature_by_type(FeatureType.USER).get()

        self.assertIsNone(user_line_item.base_description)
        self.assertEqual(user_line_item.base_cost, Decimal('0.0000'))

        num_to_charge = num_active - self.community_plan.user_limit
        self.assertIsNotNone(user_line_item.unit_description)
        self.assertEqual(user_line_item.quantity, num_to_charge)
        self.assertEqual(user_line_item.unit_cost, self.user_rate.per_excess_fee)
        self.assertEqual(user_line_item.subtotal, num_to_charge * self.user_rate.per_excess_fee)
        self.assertEqual(user_line_item.total, num_to_charge * self.user_rate.per_excess_fee)
        domain.delete()
示例#3
0
    def test_community(self):
        """
        For Community plans (plan monthly fee is 0.0) that incur other rate charges, like users or SMS messages,
        make sure that the following is true:
        - base_description is None
        - unit_description is None
        - unit_cost is equal to 0
        - quantity is equal to 0
        - total and subtotal are 0.0
        """
        domain = generator.arbitrary_domain()
        generator.create_excess_community_users(domain)

        tasks.generate_invoices()
        subscriber = Subscriber.objects.get(domain=domain.name)
        invoice = Invoice.objects.filter(subscription__subscriber=subscriber).get()

        product_line_items = invoice.lineitem_set.filter(feature_rate__exact=None)
        self.assertEqual(product_line_items.count(), 1)
        product_line_item = product_line_items.get()
        self.assertIsNotNone(product_line_item.base_description)
        self.assertIsNone(product_line_item.unit_description)
        self.assertEqual(product_line_item.unit_cost, Decimal('0.0000'))
        self.assertEqual(product_line_item.quantity, 1)
        self.assertEqual(product_line_item.subtotal, Decimal('0.0000'))
        self.assertEqual(product_line_item.total, Decimal('0.0000'))

        domain.delete()
示例#4
0
 def test_community_invoice(self):
     """
     For an unsubscribed domain with any charges over the community limit for the month of invoicing,
     make sure that an invoice is generated in addition to a subscription for that month to
     the community plan.
     """
     domain = generator.arbitrary_domain()
     generator.create_excess_community_users(domain)
     account = BillingAccount.get_or_create_account_by_domain(
         domain, created_by=self.dimagi_user)[0]
     billing_contact = generator.arbitrary_contact_info(account, self.dimagi_user)
     billing_contact.save()
     account.date_confirmed_extra_charges = datetime.date.today()
     account.save()
     tasks.generate_invoices()
     subscriber = Subscriber.objects.get(domain=domain.name)
     invoices = Invoice.objects.filter(subscription__subscriber=subscriber)
     self.assertEqual(invoices.count(), 1)
     invoice = invoices.get()
     self.assertEqual(invoice.subscription.subscriber.domain, domain.name)
     self.assertEqual(invoice.subscription.date_start, invoice.date_start)
     self.assertEqual(
         invoice.subscription.date_end - datetime.timedelta(days=1),
         invoice.date_end
     )
     domain.delete()
    def test_invoice_credit(self):
        """
        Make sure that subscription and account level credits get applied to the invoice balance appropriately.
        """
        invoice_monthly_total = self.product_rate.monthly_fee + self.monthly_user_fee

        subscription_credit, account_credit = self._generate_subscription_and_account_invoice_credits(
            invoice_monthly_total, self.subscription, self.account)

        # other subscription credit that shouldn't count toward this invoice
        other_domain = generator.arbitrary_domain()
        # so that the other subscription doesn't draw from the same account credits, have it start 4 months later
        new_subscription_start = utils.months_from_date(
            self.subscription.date_start, 4)
        other_subscription, _ = generator.generate_domain_subscription_from_date(
            new_subscription_start,
            self.account,
            other_domain.name,
            min_num_months=self.min_subscription_length,
        )
        # other account credit that shouldn't count toward this invoice
        other_account = generator.billing_account(
            self.dimagi_user, generator.arbitrary_web_user())

        self._generate_subscription_and_account_invoice_credits(
            invoice_monthly_total, other_subscription, other_account)

        self._test_final_invoice_balance()

        self._test_credit_use(subscription_credit)
        self._test_credit_use(account_credit)
        self._clean_credits()
示例#6
0
 def test_community_invoice(self):
     """
     For an unsubscribed domain with any charges over the community limit for the month of invoicing,
     make sure that an invoice is generated in addition to a subscription for that month to
     the community plan.
     """
     domain = generator.arbitrary_domain()
     generator.create_excess_community_users(domain)
     account = BillingAccount.get_or_create_account_by_domain(
         domain, created_by=self.dimagi_user)[0]
     billing_contact = generator.arbitrary_contact_info(
         account, self.dimagi_user)
     billing_contact.save()
     account.date_confirmed_extra_charges = datetime.date.today()
     account.save()
     tasks.generate_invoices()
     subscriber = Subscriber.objects.get(domain=domain.name)
     invoices = Invoice.objects.filter(subscription__subscriber=subscriber)
     self.assertEqual(invoices.count(), 1)
     invoice = invoices.get()
     self.assertEqual(invoice.subscription.subscriber.domain, domain.name)
     self.assertEqual(invoice.subscription.date_start, invoice.date_start)
     self.assertEqual(
         invoice.subscription.date_end - datetime.timedelta(days=1),
         invoice.date_end)
     domain.delete()
示例#7
0
    def setUp(self):
        super(TestBillingAutoPay, self).setUp()
        self.account.created_by_domain = self.domain
        self.account.save()

        self.currency = generator.init_default_currency()

        self.web_user = generator.arbitrary_web_user()
        self.dimagi_user = generator.arbitrary_web_user(is_dimagi=True)
        self.fake_card = FakeStripeCard()
        self.fake_stripe_customer = FakeStripeCustomer(cards=[self.fake_card])

        self.account.update_autopay_user(self.web_user.username, self.domain)
        self.invoice_date = utils.months_from_date(self.subscription.date_start,
                                                   random.randint(2, self.subscription_length))

        self.account_2 = generator.billing_account(self.dimagi_user, self.web_user)
        self.domain_2 = generator.arbitrary_domain()

        self.subscription_2, self.subscription_length_2 = generator.generate_domain_subscription_from_date(
            generator.get_start_date(), self.account_2, self.domain_2.name,
            min_num_months=self.min_subscription_length,
        )

        tasks.generate_invoices(self.invoice_date)
 def test_feature_charges(self):
     domain_under_limits = generator.arbitrary_domain()
     self.assertTrue(
         self.community.feature_charges_exist_for_domain(self.domain))
     self.assertFalse(
         self.community.feature_charges_exist_for_domain(
             domain_under_limits))
示例#9
0
    def test_community_over_limit(self):
        """
        For a domain under community (no subscription) with users over the community limit, make sure that:
        - base_description is None
        - base_cost is 0.0
        - unit_description is not None
        - unit_cost is equal to the per_excess_fee on the user rate
        - quantity is equal to number of commcare users in that domain minus the monthly_limit on the user rate
        - total and subtotals are equal to number of extra users * per_excess_fee
        """
        domain = generator.arbitrary_domain()
        num_active = generator.create_excess_community_users(domain)

        tasks.generate_invoices()
        subscriber = Subscriber.objects.get(domain=domain.name)
        invoice = Invoice.objects.filter(subscription__subscriber=subscriber).get()
        user_line_item = invoice.lineitem_set.get_feature_by_type(FeatureType.USER).get()

        self.assertIsNone(user_line_item.base_description)
        self.assertEqual(user_line_item.base_cost, Decimal('0.0000'))

        num_to_charge = num_active - generator.MAX_COMMUNITY_USERS
        self.assertIsNotNone(user_line_item.unit_description)
        self.assertEqual(user_line_item.quantity, num_to_charge)
        self.assertEqual(user_line_item.unit_cost, self.user_rate.per_excess_fee)
        self.assertEqual(user_line_item.subtotal, num_to_charge * self.user_rate.per_excess_fee)
        self.assertEqual(user_line_item.total, num_to_charge * self.user_rate.per_excess_fee)
        domain.delete()
示例#10
0
    def test_invoice_credit(self):
        """
        Make sure that subscription and account level credits get applied to the invoice balance appropriately.
        """
        invoice_monthly_total = self.product_rate.monthly_fee + self.monthly_user_fee

        subscription_credit, account_credit = self._generate_subscription_and_account_invoice_credits(
            invoice_monthly_total, self.subscription, self.account
        )

        # other subscription credit that shouldn't count toward this invoice
        other_domain = generator.arbitrary_domain()
        # so that the other subscription doesn't draw from the same account credits, have it start 4 months later
        new_subscription_start = utils.months_from_date(self.subscription.date_start, 4)

        other_subscription = generator.generate_domain_subscription(
            self.account,
            other_domain,
            date_start=new_subscription_start,
            date_end=add_months_to_date(new_subscription_start, self.min_subscription_length),
        )

        # other account credit that shouldn't count toward this invoice
        other_account = generator.billing_account(self.dimagi_user, generator.arbitrary_web_user())

        self._generate_subscription_and_account_invoice_credits(
            invoice_monthly_total, other_subscription, other_account
        )

        self._test_final_invoice_balance()

        self._test_credit_use(subscription_credit)
        self._test_credit_use(account_credit)
示例#11
0
 def setUp(self):
     super(TestCreditTransfers, self).setUp()
     self.product_credit_amt = Decimal("500.00")
     self.feature_credit_amt = Decimal("200.00")
     self.subscription_credit_amt = Decimal("600.00")
     self.domain = generator.arbitrary_domain()
     self.account = BillingAccount.get_or_create_account_by_domain(self.domain, created_by="*****@*****.**")[0]
示例#12
0
 def test_community_no_charges_no_invoice(self):
     """
     No invoices should be generated for domains that are not on a subscription and do not
     have any per_excess charges on users or SMS messages
     """
     domain = generator.arbitrary_domain()
     tasks.generate_invoices()
     self.assertRaises(ObjectDoesNotExist, lambda: Invoice.objects.get(subscription__subscriber__domain=domain.name))
     domain.delete()
 def setUp(self):
     super(TestCreditTransfers, self).setUp()
     self.product_credit_amt = Decimal('500.00')
     self.feature_credit_amt = Decimal('200.00')
     self.subscription_credit_amt = Decimal('600.00')
     self.domain = generator.arbitrary_domain()
     self.account = BillingAccount.get_or_create_account_by_domain(
         self.domain,
         created_by="*****@*****.**",
     )[0]
示例#14
0
 def test_community_no_charges_no_invoice(self):
     """
     No invoices should be generated for domains that are not on a subscription and do not
     have any per_excess charges on users or SMS messages
     """
     domain = generator.arbitrary_domain()
     tasks.generate_invoices()
     self.assertRaises(
         ObjectDoesNotExist, lambda: Invoice.objects.get(
             subscription__subscriber__domain=domain.name))
     domain.delete()
示例#15
0
    def setUp(self):
        self.billing_contact = generator.arbitrary_web_user()
        self.dimagi_user = generator.arbitrary_web_user(is_dimagi=True)
        self.currency = generator.init_default_currency()
        self.account = generator.billing_account(self.dimagi_user, self.billing_contact)
        self.domain = generator.arbitrary_domain()

        generator.instantiate_subscribable_plans()
        generator.instantiate_community_plans()
        self.subscription, self.subscription_length = generator.generate_domain_subscription_from_date(
            generator.get_start_date(), self.account, self.domain.name, min_num_months=self.min_subscription_length,
        )
示例#16
0
    def setUp(self):
        super(BaseInvoiceTestCase, self).setUp()
        self.billing_contact = generator.arbitrary_web_user()
        self.dimagi_user = generator.arbitrary_web_user(is_dimagi=True)
        self.currency = generator.init_default_currency()
        self.account = generator.billing_account(self.dimagi_user, self.billing_contact)
        self.domain = generator.arbitrary_domain()

        self.subscription, self.subscription_length = generator.generate_domain_subscription_from_date(
            generator.get_start_date(), self.account, self.domain.name, min_num_months=self.min_subscription_length
        )
        self.community_plan = DefaultProductPlan.objects.get(
            product_type=SoftwareProductType.COMMCARE, edition=SoftwarePlanEdition.COMMUNITY
        ).plan.get_version()
    def setUp(self):
        super(TestDomainInvoiceFactory, self).setUp()
        self.invoice_start, self.invoice_end = get_previous_month_date_range()

        self.domain = generator.arbitrary_domain()
        self.account = BillingAccount.get_or_create_account_by_domain(
            domain=self.domain.name, created_by="TEST")[0]
        self.community = DefaultProductPlan.get_default_plan_by_domain(
            self.domain).plan.get_version()
        generator.arbitrary_commcare_users_for_domain(
            self.domain.name, self.community.user_limit + 1)

        self.invoice_factory = DomainInvoiceFactory(self.invoice_start,
                                                    self.invoice_end,
                                                    self.domain)
示例#18
0
 def _generate_non_autopayable_entities(self):
     """
     Create account, domain, and subscription linked to the autopay user, but that don't have autopay enabled
     """
     self.non_autopay_account = generator.billing_account(
         web_user_creator=generator.arbitrary_web_user(is_dimagi=True),
         web_user_contact=self.autopay_user
     )
     self.non_autopay_domain = generator.arbitrary_domain()
     # Non-autopay subscription has same parameters as the autopayable subscription
     self.non_autopay_subscription = generator.generate_domain_subscription(
         self.non_autopay_account,
         self.non_autopay_domain,
         date_start=self.subscription.date_start,
         date_end=add_months_to_date(self.subscription.date_start, self.subscription_length),
     )
    def setUp(self):
        super(TestDomainInvoiceFactory, self).setUp()
        self.invoice_start, self.invoice_end = get_previous_month_date_range()

        self.domain = generator.arbitrary_domain()
        self.account = BillingAccount.get_or_create_account_by_domain(
            domain=self.domain.name, created_by="TEST"
        )[0]
        self.community = DefaultProductPlan.get_default_plan_by_domain(
            self.domain).plan.get_version()
        generator.arbitrary_commcare_users_for_domain(
            self.domain.name, self.community.user_limit + 1
        )

        self.invoice_factory = DomainInvoiceFactory(
            self.invoice_start, self.invoice_end, self.domain
        )
示例#20
0
    def setUp(self):
        super(BaseInvoiceTestCase, self).setUp()
        self.billing_contact = generator.arbitrary_web_user()
        self.dimagi_user = generator.arbitrary_web_user(is_dimagi=True)
        self.currency = generator.init_default_currency()
        self.account = generator.billing_account(self.dimagi_user,
                                                 self.billing_contact)
        self.domain = generator.arbitrary_domain()

        self.subscription, self.subscription_length = generator.generate_domain_subscription_from_date(
            generator.get_start_date(),
            self.account,
            self.domain.name,
            min_num_months=self.min_subscription_length,
        )
        self.community_plan = DefaultProductPlan.objects.get(
            product_type=SoftwareProductType.COMMCARE,
            edition=SoftwarePlanEdition.COMMUNITY).plan.get_version()
示例#21
0
    def test_community_invoice(self):
        """
        For an unsubscribed domain with any charges over the community limit for the month of invoicing,
        make sure that an invoice is generated in addition to a subscription for that month to
        the community plan.
        """
        domain = generator.arbitrary_domain()
        generator.create_excess_community_users(domain)

        tasks.generate_invoices()
        subscriber = Subscriber.objects.get(domain=domain.name)
        invoices = Invoice.objects.filter(subscription__subscriber=subscriber)
        self.assertEqual(invoices.count(), 1)
        invoice = invoices.get()
        self.assertEqual(invoice.subscription.subscriber.domain, domain.name)
        self.assertEqual(invoice.subscription.date_start, invoice.date_start)
        self.assertEqual(invoice.subscription.date_end, invoice.date_end)
        domain.delete()
示例#22
0
    def test_community_over_limit(self):
        """
        For a domain under community (no subscription) with users over the community limit, make sure that:
        - base_description is None
        - base_cost is 0.0
        - unit_description is not None
        - unit_cost is equal to the per_excess_fee on the user rate
        - quantity is equal to number of commcare users in that domain minus the monthly_limit on the user rate
        - total and subtotals are equal to number of extra users * per_excess_fee
        """
        domain = generator.arbitrary_domain()
        num_active = generator.create_excess_community_users(domain)

        account = BillingAccount.get_or_create_account_by_domain(
            domain, created_by=self.dimagi_user)[0]
        billing_contact = generator.arbitrary_contact_info(
            account, self.dimagi_user)
        billing_contact.save()
        account.date_confirmed_extra_charges = datetime.date.today()
        account.save()

        tasks.generate_invoices()
        subscriber = Subscriber.objects.get(domain=domain.name)
        invoice = Invoice.objects.filter(
            subscription__subscriber=subscriber).get()
        user_line_item = invoice.lineitem_set.get_feature_by_type(
            FeatureType.USER).get()

        self.assertIsNone(user_line_item.base_description)
        self.assertEqual(user_line_item.base_cost, Decimal('0.0000'))

        num_to_charge = num_active - self.community_plan.user_limit
        self.assertIsNotNone(user_line_item.unit_description)
        self.assertEqual(user_line_item.quantity, num_to_charge)
        self.assertEqual(user_line_item.unit_cost,
                         self.user_rate.per_excess_fee)
        self.assertEqual(user_line_item.subtotal,
                         num_to_charge * self.user_rate.per_excess_fee)
        self.assertEqual(user_line_item.total,
                         num_to_charge * self.user_rate.per_excess_fee)
        domain.delete()
示例#23
0
    def test_use_prev_billing_account_for_community_invoice(self):
        """
        Make sure that if a billing account was already auto generated for a previous community invoice,
        that a new one is not created.
        """
        domain = generator.arbitrary_domain()
        generator.create_excess_community_users(domain)

        second_invoicing_date = datetime.date.today()
        second_invoice_start, second_invoice_end = utils.get_previous_month_date_range(second_invoicing_date)
        first_invoicing_date = second_invoice_start - datetime.timedelta(days=random.randint(0, 365))

        tasks.generate_invoices(first_invoicing_date)
        tasks.generate_invoices(second_invoicing_date)
        subscriber = Subscriber.objects.get(domain=domain.name)
        invoices = Invoice.objects.filter(subscription__subscriber=subscriber)
        self.assertEqual(invoices.count(), 2)
        invoices = invoices.all()
        self.assertNotEqual(invoices[0].subscription, invoices[1].subscription)
        self.assertEqual(invoices[0].subscription.account, invoices[1].subscription.account)
        for invoice in invoices:
            self.assertEqual(invoice.subscription.subscriber.domain, domain.name)
        domain.delete()
示例#24
0
    def setUp(self):
        super(BaseInvoiceTestCase, self).setUp()
        self.billing_contact = generator.arbitrary_web_user()
        self.dimagi_user = generator.arbitrary_web_user(is_dimagi=True)
        self.currency = generator.init_default_currency()
        self.account = generator.billing_account(
            self.dimagi_user, self.billing_contact)
        self.domain = generator.arbitrary_domain()

        self.subscription_length = 15  # months
        subscription_start_date = datetime.date(2016, 2, 23)
        subscription_end_date = add_months_to_date(subscription_start_date, self.subscription_length)
        self.subscription = generator.generate_domain_subscription(
            self.account,
            self.domain,
            date_start=subscription_start_date,
            date_end=subscription_end_date,
        )

        self.community_plan = DefaultProductPlan.objects.get(
            product_type=SoftwareProductType.COMMCARE,
            edition=SoftwarePlanEdition.COMMUNITY
        ).plan.get_version()
示例#25
0
    def test_community_over_limit(self):
        """
        For a domain under community (no subscription) with SMS over the community limit, make sure that:
        - base_description is None
        - base_cost is 0.0
        - unit_description is not None
        - unit_cost is greater than 0.0
        - quantity is equal to 1
        - total and subtotals are greater than zero
        """
        domain = generator.arbitrary_domain()
        invoice_date = datetime.date.today()
        sms_date = utils.months_from_date(invoice_date, -1)

        num_sms = random.randint(1, 5)
        generator.arbitrary_sms_billables_for_domain(
            domain.name, INCOMING, sms_date, num_sms
        )

        tasks.generate_invoices(invoice_date)
        subscriber = Subscriber.objects.get(domain=domain.name)
        invoice = Invoice.objects.filter(subscription__subscriber=subscriber).get()
        sms_line_item = invoice.lineitem_set.get_feature_by_type(FeatureType.SMS).get()

        # there is no base cost
        self.assertIsNone(sms_line_item.base_description)
        self.assertEqual(sms_line_item.base_cost, Decimal('0.0000'))

        self.assertEqual(sms_line_item.quantity, 1)
        self.assertGreater(sms_line_item.unit_cost, Decimal('0.0000'))
        self.assertIsNotNone(sms_line_item.unit_description)

        self.assertGreater(sms_line_item.subtotal, Decimal('0.0000'))
        self.assertGreater(sms_line_item.total, Decimal('0.0000'))

        self._delete_sms_billables()
        domain.delete()
 def test_feature_charges(self):
     domain_under_limits = generator.arbitrary_domain()
     self.assertTrue(self.community.feature_charges_exist_for_domain(self.domain))
     self.assertFalse(self.community.feature_charges_exist_for_domain(domain_under_limits))