Exemplo n.º 1
0
 def ensure_full_coverage(self, subscriptions):
     plan_version = DefaultProductPlan.get_default_plan_by_domain(
         self.domain,
         edition=SoftwarePlanEdition.COMMUNITY).plan.get_version()
     if not plan_version.feature_charges_exist_for_domain(self.domain):
         return
     community_ranges = self.get_community_ranges(subscriptions)
     if not community_ranges:
         return
     do_not_invoice = any([s.do_not_invoice for s in subscriptions])
     account = BillingAccount.get_or_create_account_by_domain(
         self.domain.name,
         created_by=self.__class__.__name__,
         created_by_invoicing=True)[0]
     if account.date_confirmed_extra_charges is None:
         subject = "[%s] Invoice Generation Issue" % self.domain.name
         email_content = render_to_string(
             'accounting/invoice_error_email.html', {
                 'project':
                 self.domain.name,
                 'error_msg':
                 "This project is incurring charges on their "
                 "Community subscription, but they haven't "
                 "agreed to the charges yet. Someone should "
                 "follow up with this project to see if everything "
                 "is configured correctly or if communication "
                 "needs to happen between Dimagi and the project's"
                 "admins. For now, the invoices generated are "
                 "marked as Do Not Invoice.",
             })
         send_HTML_email(subject,
                         settings.BILLING_EMAIL,
                         email_content,
                         email_from="Dimagi Billing Bot <%s>" %
                         settings.DEFAULT_FROM_EMAIL)
         do_not_invoice = True
     if not BillingContactInfo.objects.filter(account=account).exists():
         # No contact information exists for this account.
         # This shouldn't happen, but if it does, we can't continue
         # with the invoice generation.
         raise BillingContactInfoError(
             "Project %s has incurred charges, but does not have their "
             "Billing Contact Info filled out. Someone should follow up "
             "on this." % self.domain.name)
     # First check to make sure none of the existing subscriptions is set
     # to do not invoice. Let's be on the safe side and not send a
     # community invoice out, if that's the case.
     for c in community_ranges:
         # create a new community subscription for each
         # date range that the domain did not have a subscription
         community_subscription = Subscription(
             account=account,
             plan_version=plan_version,
             subscriber=self.subscriber,
             date_start=c[0],
             date_end=c[1],
             do_not_invoice=do_not_invoice,
         )
         community_subscription.save()
         subscriptions.append(community_subscription)
Exemplo n.º 2
0
def generate_domain_subscription_from_date(date_start,
                                           billing_account,
                                           domain,
                                           min_num_months=None,
                                           is_immediately_active=False,
                                           delay_invoicing_until=None,
                                           save=True):
    # make sure the first month is never a full month (for testing)
    date_start = date_start.replace(day=max(2, date_start.day))

    subscription_length = random.randint(min_num_months or 3, 25)
    date_end_year, date_end_month = add_months(date_start.year,
                                               date_start.month,
                                               subscription_length)
    date_end_last_day = calendar.monthrange(date_end_year, date_end_month)[1]

    # make sure that the last month is never a full month (for testing)
    date_end = datetime.date(date_end_year, date_end_month,
                             min(date_end_last_day - 1, date_start.day + 1))

    subscriber, _ = Subscriber.objects.get_or_create(domain=domain,
                                                     organization=None)
    subscription = Subscription(
        account=billing_account,
        plan_version=arbitrary_subscribable_plan(),
        subscriber=subscriber,
        salesforce_contract_id=data_gen.arbitrary_unique_name("SFC")[:80],
        date_start=date_start,
        date_end=date_end,
        is_active=is_immediately_active,
        date_delay_invoicing=delay_invoicing_until,
    )
    if save:
        subscription.save()
    return subscription, subscription_length
Exemplo n.º 3
0
 def test_next_subscription_filter_no_end_date(self):
     next_subscription = Subscription(
         account=self.subscription.account,
         plan_version=self.subscription.plan_version,
         subscriber=self.subscription.subscriber,
         date_start=self.subscription.date_end,
         date_end=None,
     )
     next_subscription.save()
     self.assertEqual(next_subscription, self.subscription.next_subscription)
Exemplo n.º 4
0
def generate_domain_subscription(account, domain, date_start, date_end,
                                 plan_version=None, service_type=SubscriptionType.NOT_SET):
    subscriber, _ = Subscriber.objects.get_or_create(domain=domain.name)
    subscription = Subscription(
        account=account,
        plan_version=plan_version or subscribable_plan_version(),
        subscriber=subscriber,
        date_start=date_start,
        date_end=date_end,
        service_type=service_type,
    )
    subscription.save()
    return subscription
Exemplo n.º 5
0
 def ensure_full_coverage(self, subscriptions):
     plan_version = DefaultProductPlan.get_default_plan_by_domain(
         self.domain, edition=SoftwarePlanEdition.COMMUNITY
     ).plan.get_version()
     if not plan_version.feature_charges_exist_for_domain(self.domain):
         return
     community_ranges = self.get_community_ranges(subscriptions)
     if not community_ranges:
         return
     do_not_invoice = any([s.do_not_invoice for s in subscriptions])
     account = BillingAccount.get_or_create_account_by_domain(
         self.domain.name, created_by=self.__class__.__name__,
         created_by_invoicing=True)[0]
     if account.date_confirmed_extra_charges is None:
         logger.error(
             "[BILLING] "
             "Domain '%s' is going to get charged on "
             "Community, but they haven't formally acknowledged this. "
             "Someone on ops should reconcile this soon. To be on the "
             "safe side, we've marked the invoices as Do Not Invoice."
             % self.domain.name
         )
         do_not_invoice = True
     if not BillingContactInfo.objects.filter(account=account).exists():
         # No contact information exists for this account.
         # This shouldn't happen, but if it does, we can't continue
         # with the invoice generation.
         raise InvoiceError("No Billing Contact Info could be found "
                            "for domain '%s'." % self.domain.name)
     # First check to make sure none of the existing subscriptions is set
     # to do not invoice. Let's be on the safe side and not send a
     # community invoice out, if that's the case.
     for c in community_ranges:
         # create a new community subscription for each
         # date range that the domain did not have a subscription
         community_subscription = Subscription(
             account=account,
             plan_version=plan_version,
             subscriber=self.subscriber,
             date_start=c[0],
             date_end=c[1],
             do_not_invoice=do_not_invoice,
         )
         community_subscription.save()
         subscriptions.append(community_subscription)
Exemplo n.º 6
0
 def ensure_full_coverage(self, subscriptions):
     plan_version = DefaultProductPlan.get_default_plan_by_domain(
         self.domain,
         edition=SoftwarePlanEdition.COMMUNITY).plan.get_version()
     if not plan_version.feature_charges_exist_for_domain(self.domain):
         return
     community_ranges = self.get_community_ranges(subscriptions)
     if not community_ranges:
         return
     do_not_invoice = any([s.do_not_invoice for s in subscriptions])
     account = BillingAccount.get_or_create_account_by_domain(
         self.domain.name,
         created_by=self.__class__.__name__,
         created_by_invoicing=True,
         entry_point=EntryPoint.SELF_STARTED,
     )[0]
     if account.date_confirmed_extra_charges is None:
         logger.info(
             "Did not generate invoice because date_confirmed_extra_charges "
             "was null for domain %s" % self.domain.name)
         do_not_invoice = True
     if not BillingContactInfo.objects.filter(account=account).exists():
         # No contact information exists for this account.
         # This shouldn't happen, but if it does, we can't continue
         # with the invoice generation.
         raise BillingContactInfoError(
             "Project %s has incurred charges, but does not have their "
             "Billing Contact Info filled out." % self.domain.name)
     # First check to make sure none of the existing subscriptions is set
     # to do not invoice. Let's be on the safe side and not send a
     # community invoice out, if that's the case.
     for c in community_ranges:
         # create a new community subscription for each
         # date range that the domain did not have a subscription
         community_subscription = Subscription(
             account=account,
             plan_version=plan_version,
             subscriber=self.subscriber,
             date_start=c[0],
             date_end=c[1],
             do_not_invoice=do_not_invoice,
         )
         community_subscription.save()
         subscriptions.append(community_subscription)
Exemplo n.º 7
0
    def _ensure_full_coverage(self, subscriptions):
        plan_version = DefaultProductPlan.get_default_plan(
            edition=SoftwarePlanEdition.COMMUNITY).plan.get_version()
        if not plan_version.feature_charges_exist_for_domain(self.domain):
            return

        community_ranges = self._get_community_ranges(subscriptions)
        if not community_ranges:
            return

        # First check to make sure none of the existing subscriptions is set
        # to do not invoice. Let's be on the safe side and not send a
        # community invoice out, if that's the case.
        do_not_invoice = any([s.do_not_invoice for s in subscriptions])

        account = BillingAccount.get_or_create_account_by_domain(
            self.domain.name,
            created_by=self.__class__.__name__,
            entry_point=EntryPoint.SELF_STARTED,
        )[0]
        if account.date_confirmed_extra_charges is None:
            log_accounting_info(
                "Did not generate invoice because date_confirmed_extra_charges "
                "was null for domain %s" % self.domain.name)
            do_not_invoice = True

        for start_date, end_date in community_ranges:
            # create a new community subscription for each
            # date range that the domain did not have a subscription
            community_subscription = Subscription(
                account=account,
                plan_version=plan_version,
                subscriber=self.subscriber,
                date_start=start_date,
                date_end=end_date,
                do_not_invoice=do_not_invoice,
            )
            community_subscription.save()
            subscriptions.append(community_subscription)
Exemplo n.º 8
0
 def test_non_trial_with_previous(self):
     self._run_test(Subscription(is_trial=False),
                    Subscription(is_trial=False), True)
     self._run_test(Subscription(is_trial=True),
                    Subscription(is_trial=False), True)
Exemplo n.º 9
0
 def test_non_trial_with_no_previous(self):
     self._run_test(None, Subscription(is_trial=False), False)
Exemplo n.º 10
0
    def setUpClass(cls):
        super().setUpClass()

        cls.domain1, subscriber1 = generator.arbitrary_domain_and_subscriber()
        cls.domain2, subscriber2 = generator.arbitrary_domain_and_subscriber()
        cls.admin_web_user = generator.create_arbitrary_web_user_name()

        account = generator.billing_account(cls.admin_web_user,
                                            cls.admin_web_user)
        account.is_customer_billing_account = True
        account.save()

        enterprise_plan = SoftwarePlan.objects.create(
            name="Helping Earth INGO Enterprise Plan",
            description="Enterprise plan for Helping Earth",
            edition=SoftwarePlanEdition.ENTERPRISE,
            visibility=SoftwarePlanVisibility.INTERNAL,
            is_customer_software_plan=True,
        )

        first_product_rate = SoftwareProductRate.objects.create(
            monthly_fee=3000, name="HQ Enterprise")
        cls.first_version = SoftwarePlanVersion.objects.create(
            plan=enterprise_plan,
            role=Role.objects.first(),
            product_rate=first_product_rate)
        cls.first_version.save()

        today = datetime.date.today()
        two_months_ago = today - datetime.timedelta(days=60)
        next_month = today + datetime.timedelta(days=30)

        subscription1 = Subscription(
            account=account,
            plan_version=cls.first_version,
            subscriber=subscriber1,
            date_start=two_months_ago,
            date_end=None,
            service_type=SubscriptionType.IMPLEMENTATION,
        )
        subscription1.is_active = True
        subscription1.save()

        subscription2 = Subscription(
            account=account,
            plan_version=cls.first_version,
            subscriber=subscriber2,
            date_start=two_months_ago,
            date_end=next_month,
            service_type=SubscriptionType.IMPLEMENTATION,
        )
        subscription2.is_active = True
        subscription2.save()

        new_product_rate = SoftwareProductRate.objects.create(
            monthly_fee=5000, name="HQ Enterprise")
        cls.newest_version = SoftwarePlanVersion.objects.create(
            plan=enterprise_plan,
            role=Role.objects.first(),
            product_rate=new_product_rate)
        cls.newest_version.save()