def _link_domains(domain, other_domain): plan_version = Subscription.get_active_subscription_by_domain( domain).plan_version plan = plan_version.plan plan.is_customer_software_plan = True plan.save() other_subscription = Subscription.get_active_subscription_by_domain( other_domain) other_subscription.plan_version = plan_version other_subscription.save()
def _change_to_probono(self, domain_name, pro_bono_status): subscription = Subscription.get_active_subscription_by_domain( domain_name) subscription.update_subscription( pro_bono_status=pro_bono_status, date_start=datetime.date.today() - datetime.timedelta(days=1), date_end=datetime.date.today() + datetime.timedelta(days=5))
def _get_users_included_in_subscription(domain): from corehq.apps.accounting.models import Subscription subscription = Subscription.get_active_subscription_by_domain(domain) if subscription: plan_version = subscription.plan_version n_included_users = (plan_version.feature_rates.get( feature__feature_type='User').monthly_limit) if plan_version.plan.is_customer_software_plan: # For now just give each domain that's part of an enterprise account # access to nearly all of the throughput allocation. # Really what we want is to limit enterprise accounts' submissions accross all # their domains together, but right now what we care about # is not unfairly limiting high-paying enterprise accounts. n_domains = len( plan_version.subscription_set.filter(is_active=True)) # Heavily bias towards allowing high throughput # 80% minimum, plus a fraction of 20% inversely proportional # to the number of domains that share the throughput allocation. return n_included_users * (.8 + .2 / n_domains) else: return n_included_users else: return 0
def log_module_info(self, module, path, domains, in_module_map): domains_exist = [] plans = [] last_form_submissions = [] all_community = True for domain in domains: domain_obj = Domain.get_by_name(domain) plan = "Not Found" domains_exist.append(domain_obj is not None) if domain_obj: subscription = Subscription.get_active_subscription_by_domain(domain) if subscription: plan = subscription.plan_version.plan.name if subscription.plan_version.plan.edition != SoftwarePlanEdition.COMMUNITY: all_community = False last_form_submissions.append("{}".format(get_last_form_submission_received(domain))) else: last_form_submissions.append("None") plans.append(plan) return [ module, path[len(settings.FILEPATH) + 1:], " | ".join(domains), " | ".join(map(str, domains_exist)), " | ".join(plans), " | ".join(last_form_submissions), in_module_map, all(domains_exist) and all_community, ]
def _terminate_subscriptions(domain_name): today = date.today() with transaction.atomic(): current_subscription = Subscription.get_active_subscription_by_domain(domain_name) if current_subscription: current_subscription.date_end = today current_subscription.is_active = False current_subscription.save() current_subscription.transfer_credits() _, downgraded_privs, upgraded_privs = get_change_status(current_subscription.plan_version, None) current_subscription.subscriber.deactivate_subscription( downgraded_privileges=downgraded_privs, upgraded_privileges=upgraded_privs, old_subscription=current_subscription, new_subscription=None, ) Subscription.visible_objects.filter( Q(date_start__gt=today) | Q(date_start=today, is_active=False), subscriber__domain=domain_name, ).update(is_hidden_to_ops=True)
def _update_subscriptions_to_new_plans(domains_by_plan_version, privilege_slug, dry_run=False): """ :param domains_by_plan_version: {'<plan_version_id>': [domains_for_version]} :param privilege_slug: slug for Role obj representing privilege to add """ dry_run_tag = '[DRY_RUN]' if dry_run else '' for version_id, domains in domains_by_plan_version.items(): current_version = SoftwarePlanVersion.objects.get(id=version_id) current_plan = current_version.plan new_role = _get_or_create_role_with_privilege( current_version.role.slug, privilege_slug, dry_run=dry_run) new_plan = _get_or_create_new_software_plan(current_plan, dry_run=dry_run) new_version = _get_or_create_new_software_plan_version(new_plan, current_version, new_role, dry_run=dry_run) if new_role and new_plan and new_version: for domain in domains: subscription = Subscription.get_active_subscription_by_domain( domain) subscription.plan_version = new_plan.get_version() if not dry_run: subscription.save() logger.info( f'{dry_run_tag}Updated subscription\'s software plan to {new_plan.name} for {domain}.' )
def _change_to_extended_trial(self, domain_name): subscription = Subscription.get_active_subscription_by_domain(domain_name) subscription.update_subscription( service_type=SubscriptionType.EXTENDED_TRIAL, date_start=datetime.date.today() - datetime.timedelta(days=1), date_end=datetime.date.today() + datetime.timedelta(days=5) )
def run_downgrade_process(today=None): today = today or datetime.date.today() for domain, oldest_unpaid_invoice, total in _get_domains_with_invoices_over_threshold(today): current_subscription = Subscription.get_active_subscription_by_domain(domain) if _is_subscription_eligible_for_downgrade_process(current_subscription): _apply_downgrade_process(current_subscription, oldest_unpaid_invoice, total, today)
def _change_to_probono(self, domain_name, pro_bono_status): subscription = Subscription.get_active_subscription_by_domain(domain_name) subscription.update_subscription( pro_bono_status=pro_bono_status, date_start=datetime.date.today() - datetime.timedelta(days=1), date_end=datetime.date.today() + datetime.timedelta(days=5) )
def run_downgrade_process(today=None): today = today or datetime.date.today() for domain, oldest_unpaid_invoice, total in _get_domains_with_invoices_over_threshold(today): current_subscription = Subscription.get_active_subscription_by_domain(domain) if _is_subscription_eligible_for_downgrade_process(current_subscription): _apply_downgrade_process(current_subscription, oldest_unpaid_invoice, total, today)
def downgrade_eligible_domains(only_downgrade_domain=None): today = datetime.date.today() for domain, oldest_unpaid_invoice, total in get_domains_with_subscription_invoices_over_threshold(today): try: if only_downgrade_domain and domain != only_downgrade_domain: continue current_subscription = Subscription.get_active_subscription_by_domain(domain) if current_subscription and is_subscription_eligible_for_downgrade_process(current_subscription): _apply_downgrade_process( oldest_unpaid_invoice, total, today, current_subscription ) except Exception: log_accounting_error( f"There was an issue applying the downgrade process " f"to {domain}.", show_stack_trace=True ) for oldest_unpaid_invoice, total in get_accounts_with_customer_invoices_over_threshold(today): try: subscription_on_invoice = oldest_unpaid_invoice.subscriptions.first() if only_downgrade_domain and subscription_on_invoice.subscriber.domain != only_downgrade_domain: continue if is_subscription_eligible_for_downgrade_process(subscription_on_invoice): _apply_downgrade_process(oldest_unpaid_invoice, total, today, subscription_on_invoice) except Exception: log_accounting_error( f"There was an issue applying the downgrade process " f"to customer invoice {oldest_unpaid_invoice.id}.", show_stack_trace=True )
def _terminate_subscriptions(domain_name): today = date.today() with transaction.atomic(): current_subscription = Subscription.get_active_subscription_by_domain(domain_name) if current_subscription: current_subscription.date_end = today current_subscription.is_active = False current_subscription.save() current_subscription.transfer_credits() _, downgraded_privs, upgraded_privs = get_change_status(current_subscription.plan_version, None) current_subscription.subscriber.deactivate_subscription( downgraded_privileges=downgraded_privs, upgraded_privileges=upgraded_privs, old_subscription=current_subscription, new_subscription=None, ) Subscription.visible_objects.filter( Q(date_start__gt=today) | Q(date_start=today, is_active=False), subscriber__domain=domain_name, ).update(is_hidden_to_ops=True)
def _low_credits_context(self): context = {} current_subscription = Subscription.get_active_subscription_by_domain( self.domain) if current_subscription: monthly_fee = current_subscription.plan_version.product_rate.monthly_fee if monthly_fee: prepaid_credits = get_total_credits_available_for_product( current_subscription) num_months_remaining = prepaid_credits / monthly_fee prepaid_remaining_date = months_from_date( date.today(), num_months_remaining) partial_month_remaining = num_months_remaining % 1 num_days_in_month = 30 # Approximate prepaid_remaining_date += timedelta( days=int(partial_month_remaining * num_days_in_month)) prepaid_days_remaining = (prepaid_remaining_date - date.today()).days if 0 < prepaid_days_remaining < 63: context['show_prepaid_modal'] = True context['prepaid_days_remaining'] = prepaid_days_remaining context['prepaid_weeks_remaining'] = max( prepaid_days_remaining // 7, 1) context['monthly_fee'] = monthly_fee context[ 'edition'] = current_subscription.plan_version.plan.edition context['prepaid_remaining_date'] = prepaid_remaining_date return context
def _change_to_extended_trial(self, domain_name): subscription = Subscription.get_active_subscription_by_domain( domain_name) subscription.update_subscription( service_type=SubscriptionType.EXTENDED_TRIAL, date_start=datetime.date.today() - datetime.timedelta(days=1), date_end=datetime.date.today() + datetime.timedelta(days=5))
def get_overdue_invoice(domain_name): current_subscription = Subscription.get_active_subscription_by_domain( domain_name) if current_subscription and is_subscription_eligible_for_downgrade_process( current_subscription): overdue_invoice, _ = get_unpaid_invoices_over_threshold_by_domain( date.today(), domain_name) return overdue_invoice
def get_n_users_in_subscription(domain): from corehq.apps.accounting.models import Subscription subscription = Subscription.get_active_subscription_by_domain(domain) if subscription: plan_version = subscription.plan_version return plan_version.feature_rates.get( feature__feature_type='User').monthly_limit else: return 0
def should_hide_feature_notifs(domain, plan): groups = Group.get_case_sharing_groups(domain, wrap=False) subscription_type = Subscription.get_active_subscription_by_domain( domain).service_type if plan == 'pro' and groups != []: return True if subscription_type == 'IMPLEMENTATION' or subscription_type == 'SANDBOX': return True return False
def _get_service_type(toggle): """Returns subscription service type for each toggle """ service_type = {} for enabled in toggle.enabled_users: name = _enabled_item_name(enabled) if _namespace_domain(enabled): subscription = Subscription.get_active_subscription_by_domain(name) if subscription: service_type[name] = subscription.service_type return service_type
def dehydrate_billing_properties(self, bundle): domain = _get_domain(bundle) subscription = Subscription.get_active_subscription_by_domain(domain.name) return { "date_start": (subscription.date_start if subscription is not None else None), "date_end": (subscription.date_end if subscription is not None else None), "plan_version": (subscription.plan_version if subscription is not None else None), }
def _get_service_type(toggle): """Returns subscription service type for each toggle """ service_type = {} for enabled in toggle.enabled_users: name = _enabled_item_name(enabled) if _namespace_domain(enabled): subscription = Subscription.get_active_subscription_by_domain(name) if subscription: service_type[name] = subscription.service_type return service_type
def dehydrate_billing_properties(self, bundle): domain_obj = _get_domain(bundle) subscription = Subscription.get_active_subscription_by_domain(domain_obj.name) return { "date_start": (subscription.date_start if subscription is not None else None), "date_end": (subscription.date_end if subscription is not None else None), "plan_version": (subscription.plan_version if subscription is not None else None), }
def send_overdue_reminders(today=None): from corehq.apps.domain.views import DomainSubscriptionView from corehq.apps.domain.views import DomainBillingStatementsView today = today or datetime.date.today() invoices = Invoice.objects.filter(is_hidden=False, subscription__service_type=SubscriptionType.PRODUCT, date_paid__isnull=True, date_due__lt=today)\ .exclude(subscription__plan_version__plan__edition=SoftwarePlanEdition.ENTERPRISE)\ .order_by('date_due')\ .select_related('subscription__subscriber') domains = set() for invoice in invoices: if invoice.get_domain() not in domains: domains.add(invoice.get_domain()) total = Invoice.objects.filter(is_hidden=False, subscription__subscriber__domain=invoice.get_domain())\ .aggregate(Sum('balance'))['balance__sum'] if total >= 100: domain = Domain.get_by_name(invoice.get_domain()) current_subscription = Subscription.get_active_subscription_by_domain( domain.name) if (current_subscription.plan_version.plan.edition != SoftwarePlanEdition.COMMUNITY and not current_subscription.skip_auto_downgrade): days_ago = (today - invoice.date_due).days context = { 'domain': invoice.get_domain(), 'total': total, 'subscription_url': absolute_reverse(DomainSubscriptionView.urlname, args=[invoice.get_domain()]), 'statements_url': absolute_reverse(DomainBillingStatementsView.urlname, args=[invoice.get_domain()]), 'date_60': invoice.date_due + datetime.timedelta(days=60), 'contact_email': settings.INVOICING_CONTACT_EMAIL } if days_ago == 61: _downgrade_domain(current_subscription) _send_downgrade_notice(invoice, context) elif days_ago == 58: _send_downgrade_warning(invoice, context) elif days_ago == 30: _send_overdue_notice(invoice, context) elif days_ago == 1: _create_overdue_notification(invoice, context)
def run_downgrade_process(): today = datetime.date.today() for domain, oldest_unpaid_invoice, total in _get_domains_with_subscription_invoices_over_threshold(today): current_subscription = Subscription.get_active_subscription_by_domain(domain) if is_subscription_eligible_for_downgrade_process(current_subscription): _apply_downgrade_process(oldest_unpaid_invoice, total, today, current_subscription) for oldest_unpaid_invoice, total in get_accounts_with_customer_invoices_over_threshold(today): subscription_on_invoice = oldest_unpaid_invoice.subscriptions.first() if is_subscription_eligible_for_downgrade_process(subscription_on_invoice): _apply_downgrade_process(oldest_unpaid_invoice, total, today)
def apply_prbac(cls, request): subscription = (Subscription.get_active_subscription_by_domain( request.domain) if hasattr(request, 'domain') else None) if subscription: plan_version = subscription.plan_version request.role = plan_version.role request.plan = plan_version request.subscription = subscription else: plan_version = DefaultProductPlan.get_default_plan_version() request.role = plan_version.role request.plan = plan_version
def rows_for_domain(self, domain): subscription = Subscription.get_active_subscription_by_domain( domain.name) plan_version = subscription.plan_version if subscription else DefaultProductPlan.get_default_plan_version( ) return [[ plan_version.plan.name, self.format_date(domain.date_created), get_mobile_user_count(domain.name, include_inactive=False), get_web_user_count(domain.name, include_inactive=False), self.format_date(get_last_form_submission_received(domain.name)), ] + self.domain_properties(domain)]
def can_add_extra_mobile_workers(request): from corehq.apps.users.models import CommCareUser from corehq.apps.accounting.models import Subscription num_web_users = CommCareUser.total_by_domain(request.domain) user_limit = request.plan.user_limit if user_limit == -1 or num_web_users < user_limit: return True if not has_privilege(request, privileges.ALLOW_EXCESS_USERS): current_subscription = Subscription.get_active_subscription_by_domain(request.domain) if current_subscription is None or current_subscription.account.date_confirmed_extra_charges is None: return False return True
def run_downgrade_process(): today = datetime.date.today() for domain, oldest_unpaid_invoice, total in _get_domains_with_subscription_invoices_over_threshold(today): current_subscription = Subscription.get_active_subscription_by_domain(domain) if is_subscription_eligible_for_downgrade_process(current_subscription): _apply_downgrade_process(oldest_unpaid_invoice, total, today, current_subscription) for oldest_unpaid_invoice, total in get_accounts_with_customer_invoices_over_threshold(today): subscription_on_invoice = oldest_unpaid_invoice.subscriptions.first() if is_subscription_eligible_for_downgrade_process(subscription_on_invoice): _apply_downgrade_process(oldest_unpaid_invoice, total, today)
def _subscribe_to_pro_with_rb(self): subscription = Subscription.get_active_subscription_by_domain(self.project.name) new_subscription = subscription.change_plan( self.pro_rb_version, date_end=None, web_user=self.admin_username, service_type=SubscriptionType.IMPLEMENTATION, pro_bono_status=ProBonoStatus.NO, internal_change=True, ) return new_subscription
def _subscribe_to_pro_with_rb(self): subscription = Subscription.get_active_subscription_by_domain( self.project.name) new_subscription = subscription.change_plan( self.pro_rb_version, date_end=None, web_user=self.admin_username, service_type=SubscriptionType.IMPLEMENTATION, pro_bono_status=ProBonoStatus.NO, internal_change=True, ) return new_subscription
def _domain_rows(self, domain): subscription = Subscription.get_active_subscription_by_domain( domain.name) plan_version = subscription.plan_version if subscription else DefaultProductPlan.get_default_plan_version( ) return [ self._domain_properties(domain) + [ plan_version.plan.name, str(get_mobile_user_count(domain.name, include_inactive=False)), str(get_web_user_count(domain.name, include_inactive=False)), ] ]
def test_downgrade(self): domain, latest_invoice = self._simulate_downgrade( DAYS_PAST_DUE_TO_TRIGGER_DOWNGRADE ) # confirm a downgrade wasn't actually initiated because a warning # email has not been sent subscription = Subscription.get_active_subscription_by_domain(domain) self.assertNotEqual(subscription.plan_version.plan.edition, SoftwarePlanEdition.PAUSED) # fake the warning to have been triggered a few days ago warning_days_ago = DAYS_PAST_DUE_TO_TRIGGER_DOWNGRADE - DAYS_PAST_DUE_TO_TRIGGER_DOWNGRADE_WARNING history = InvoiceCommunicationHistory.objects.filter( invoice=latest_invoice ).latest('date_created') history.date_created = datetime.date.today() - datetime.timedelta(days=warning_days_ago) history.save() # now trigger a successful downgrade downgrade_eligible_domains(only_downgrade_domain=domain.name) subscription = Subscription.get_active_subscription_by_domain(domain) self.assertEqual(subscription.plan_version.plan.edition, SoftwarePlanEdition.PAUSED)
def get_default_export_settings_if_available(domain): """ Only creates settings if the domain has the DEFAULT_EXPORT_SETTINGS privilege """ settings = None current_subscription = Subscription.get_active_subscription_by_domain( domain) if current_subscription and domain_has_privilege(domain, DEFAULT_EXPORT_SETTINGS): from corehq.apps.export.models import DefaultExportSettings settings = DefaultExportSettings.objects.get_or_create( account=current_subscription.account)[0] return settings
def appcues_template_app_test(request): # See if user is in test test = ABTest(APPCUES_TEMPLATE_APP, request) if test.version(assign_if_blank=False) != APPCUES_TEMPLATE_APP_OPTION_ON: return False # If the user's trial has run out, they may no longer have access to web apps domain = getattr(request, 'domain', None) if domain: subscription = Subscription.get_active_subscription_by_domain(domain) if not subscription or not subscription.is_trial: return False return True
def apply_prbac(cls, request): subscription = ( Subscription.get_active_subscription_by_domain(request.domain) if hasattr(request, 'domain') else None ) if subscription: plan_version = subscription.plan_version request.role = plan_version.role request.plan = plan_version request.subscription = subscription else: plan_version = DefaultProductPlan.get_default_plan_version() request.role = plan_version.role request.plan = plan_version
def notify_repeater_admins(repeater): msg = (f'Forwarding data to {repeater} has consistently failed, ' 'and has been paused.') send_mail_async.delay( f'Repeater threshold exceeded on domain {repeater.domain}', msg, from_email=settings.DEFAULT_FROM_EMAIL, recipient_list=[MOTECH_DEV], ) if repeater.notify_addresses: recipient_list = repeater.notify_addresses else: subs = Subscription.get_active_subscription_by_domain(repeater.domain) recipient_list = subs.account.billingcontactinfo.email_list send_mail_async.delay( 'Data forwarding paused', msg, from_email=settings.DEFAULT_FROM_EMAIL, recipient_list=recipient_list, )
def get_paused_plan_context(request, domain): from corehq.apps.accounting.models import Subscription from corehq.apps.domain.views import SelectPlanView current_sub = Subscription.get_active_subscription_by_domain(domain) if (not current_sub or not current_sub.plan_version.is_paused or not current_sub.previous_subscription): return {} previous_edition = ( current_sub.previous_subscription.plan_version.plan.edition if current_sub.previous_subscription else "") return { 'is_paused': True, 'previous_edition': previous_edition, 'paused_date': current_sub.date_start.strftime(USER_DATE_FORMAT), 'change_plan_url': reverse(SelectPlanView.urlname, args=[domain]), 'can_edit_billing_info': request.couch_user.is_domain_admin(domain), }
def get_default_export_settings_for_domain(domain): """ Only creates settings if the the subscription level supports it Currently only available to Enterprise accounts with the DEFAULT_EXPORT_SETTINGS FF enabled """ if not toggles.DEFAULT_EXPORT_SETTINGS.enabled(domain): return None settings = None current_subscription = Subscription.get_active_subscription_by_domain( domain) # currently only available for enterprise customers supported_editions = [SoftwarePlanEdition.ENTERPRISE] if current_subscription.plan_version.plan.edition in supported_editions: from corehq.apps.export.models import DefaultExportSettings settings = DefaultExportSettings.objects.get_or_create( account=current_subscription.account)[0] return settings
def _low_credits_context(self): context = {} current_subscription = Subscription.get_active_subscription_by_domain(self.domain) if current_subscription: monthly_fee = current_subscription.plan_version.product_rate.monthly_fee if monthly_fee: prepaid_credits = get_total_credits_available_for_product(current_subscription) num_months_remaining = prepaid_credits / monthly_fee prepaid_remaining_date = months_from_date(date.today(), num_months_remaining) partial_month_remaining = num_months_remaining % 1 num_days_in_month = 30 # Approximate prepaid_remaining_date += timedelta(days=int(partial_month_remaining * num_days_in_month)) prepaid_days_remaining = (prepaid_remaining_date - date.today()).days if 0 < prepaid_days_remaining < 63: context['show_prepaid_modal'] = True context['prepaid_days_remaining'] = prepaid_days_remaining context['prepaid_weeks_remaining'] = max(prepaid_days_remaining // 7, 1) context['monthly_fee'] = monthly_fee context['edition'] = current_subscription.plan_version.plan.edition context['prepaid_remaining_date'] = prepaid_remaining_date return context
def get_subscription_properties_by_user(couch_user): def _is_paying_subscription(subscription, plan_version): NON_PAYING_SERVICE_TYPES = [ SubscriptionType.TRIAL, SubscriptionType.EXTENDED_TRIAL, SubscriptionType.SANDBOX, SubscriptionType.INTERNAL, ] NON_PAYING_PRO_BONO_STATUSES = [ ProBonoStatus.YES, ProBonoStatus.DISCOUNTED, ] return (plan_version.plan.visibility != SoftwarePlanVisibility.TRIAL and subscription.service_type not in NON_PAYING_SERVICE_TYPES and subscription.pro_bono_status not in NON_PAYING_PRO_BONO_STATUSES and plan_version.plan.edition != SoftwarePlanEdition.COMMUNITY) # Note: using "yes" and "no" instead of True and False because spec calls # for using these values. (True is just converted to "True" in KISSmetrics) all_subscriptions = [] paying_subscribed_editions = [] subscribed_editions = [] for domain_name in couch_user.domains: subscription = Subscription.get_active_subscription_by_domain( domain_name) plan_version = (subscription.plan_version if subscription is not None else DefaultProductPlan.get_default_plan_version()) subscribed_editions.append(plan_version.plan.edition) if subscription is not None: all_subscriptions.append(subscription) if subscription is not None and _is_paying_subscription( subscription, plan_version): paying_subscribed_editions.append(plan_version.plan.edition) def _is_one_of_editions(edition): return 'yes' if edition in subscribed_editions else 'no' def _is_a_pro_bono_status(status): return 'yes' if status in [ s.pro_bono_status for s in all_subscriptions ] else 'no' def _is_on_extended_trial(): service_types = [s.service_type for s in all_subscriptions] return 'yes' if SubscriptionType.EXTENDED_TRIAL in service_types else 'no' def _max_edition(): for edition in paying_subscribed_editions: assert edition in [e[0] for e in SoftwarePlanEdition.CHOICES] return max( paying_subscribed_editions) if paying_subscribed_editions else '' env = get_instance_string() return { '{}is_on_community_plan'.format(env): _is_one_of_editions(SoftwarePlanEdition.COMMUNITY), '{}is_on_standard_plan'.format(env): _is_one_of_editions(SoftwarePlanEdition.STANDARD), '{}is_on_pro_plan'.format(env): _is_one_of_editions(SoftwarePlanEdition.PRO), '{}is_on_pro_bono_plan'.format(env): _is_a_pro_bono_status(ProBonoStatus.YES), '{}is_on_discounted_plan'.format(env): _is_a_pro_bono_status(ProBonoStatus.DISCOUNTED), '{}is_on_extended_trial_plan'.format(env): _is_on_extended_trial(), '{}max_edition_of_paying_plan'.format(env): _max_edition() }
def get_overdue_invoice(domain_name): current_subscription = Subscription.get_active_subscription_by_domain(domain_name) if current_subscription and is_subscription_eligible_for_downgrade_process(current_subscription): overdue_invoice, _ = get_unpaid_invoices_over_threshold_by_domain(date.today(), domain_name) return overdue_invoice
def domain_is_on_trial(domain_name): from corehq.apps.accounting.models import Subscription subscription = Subscription.get_active_subscription_by_domain(domain_name) return subscription and subscription.is_trial
def get_subscription_properties_by_user(couch_user): def _is_paying_subscription(subscription, plan_version): NON_PAYING_SERVICE_TYPES = [ SubscriptionType.TRIAL, SubscriptionType.EXTENDED_TRIAL, SubscriptionType.SANDBOX, SubscriptionType.INTERNAL, ] NON_PAYING_PRO_BONO_STATUSES = [ ProBonoStatus.YES, ProBonoStatus.DISCOUNTED, ] return (plan_version.plan.visibility != SoftwarePlanVisibility.TRIAL and subscription.service_type not in NON_PAYING_SERVICE_TYPES and subscription.pro_bono_status not in NON_PAYING_PRO_BONO_STATUSES and plan_version.plan.edition != SoftwarePlanEdition.COMMUNITY) # Note: using "yes" and "no" instead of True and False because spec calls # for using these values. (True is just converted to "True" in KISSmetrics) all_subscriptions = [] paying_subscribed_editions = [] subscribed_editions = [] for domain_name in couch_user.domains: subscription = Subscription.get_active_subscription_by_domain(domain_name) plan_version = ( subscription.plan_version if subscription is not None else DefaultProductPlan.get_default_plan_version() ) subscribed_editions.append(plan_version.plan.edition) if subscription is not None: all_subscriptions.append(subscription) if _is_paying_subscription(subscription, plan_version): paying_subscribed_editions.append(plan_version.plan.edition) def _is_one_of_editions(edition): return 'yes' if edition in subscribed_editions else 'no' def _is_a_pro_bono_status(status): return 'yes' if status in [s.pro_bono_status for s in all_subscriptions] else 'no' def _is_on_extended_trial(): service_types = [s.service_type for s in all_subscriptions] return 'yes' if SubscriptionType.EXTENDED_TRIAL in service_types else 'no' def _max_edition(): for edition in paying_subscribed_editions: assert edition in [e[0] for e in SoftwarePlanEdition.CHOICES] return max(paying_subscribed_editions) if paying_subscribed_editions else '' env = get_instance_string() return { '{}is_on_community_plan'.format(env): _is_one_of_editions(SoftwarePlanEdition.COMMUNITY), '{}is_on_standard_plan'.format(env): _is_one_of_editions(SoftwarePlanEdition.STANDARD), '{}is_on_pro_plan'.format(env): _is_one_of_editions(SoftwarePlanEdition.PRO), '{}is_on_pro_bono_plan'.format(env): _is_a_pro_bono_status(ProBonoStatus.YES), '{}is_on_discounted_plan'.format(env): _is_a_pro_bono_status(ProBonoStatus.DISCOUNTED), '{}is_on_extended_trial_plan'.format(env): _is_on_extended_trial(), '{}max_edition_of_paying_plan'.format(env): _max_edition() }
def domain_is_on_trial(domain_name): from corehq.apps.accounting.models import Subscription subscription = Subscription.get_active_subscription_by_domain(domain_name) return subscription and subscription.is_trial