def _change_to_extended_trial(self, domain_name):
     plan, subscription = Subscription.get_subscribed_plan_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 _change_to_probono(self, domain_name, pro_bono_status):
     plan, subscription = Subscription.get_subscribed_plan_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)
     )
Exemplo n.º 3
0
 def _change_to_probono(self, domain_name, pro_bono_status):
     plan, subscription = Subscription.get_subscribed_plan_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))
Exemplo n.º 4
0
def _terminate_subscriptions(domain_name):
    today = date.today()

    with transaction.atomic():
        current_subscription = Subscription.get_subscribed_plan_by_domain(
            domain_name)[1]

        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.objects.filter(
            Q(date_start__gt=today) | Q(date_start=today, is_active=False),
            subscriber__domain=domain_name,
        ).update(is_hidden_to_ops=True)
Exemplo n.º 5
0
 def _change_to_extended_trial(self, domain_name):
     plan, subscription = Subscription.get_subscribed_plan_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 test_that_upgrade_occurs(self):
     self.assertEqual(
         Subscription.get_subscribed_plan_by_domain(self.domain1),
         self.first_version)
     self.assertEqual(
         Subscription.get_subscribed_plan_by_domain(self.domain2),
         self.first_version)
     upgrade_subscriptions_to_latest_plan_version(
         self.first_version,
         self.admin_web_user,
         upgrade_note="test upgrading to latest version")
     self.assertEqual(
         Subscription.get_subscribed_plan_by_domain(self.domain1),
         self.newest_version)
     self.assertEqual(
         Subscription.get_subscribed_plan_by_domain(self.domain2),
         self.newest_version)
Exemplo n.º 7
0
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:
        plan_version, subscription = Subscription.get_subscribed_plan_by_domain(domain_name)
        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 ''

    return {
        'is_on_community_plan': _is_one_of_editions(SoftwarePlanEdition.COMMUNITY),
        'is_on_standard_plan': _is_one_of_editions(SoftwarePlanEdition.STANDARD),
        'is_on_pro_plan': _is_one_of_editions(SoftwarePlanEdition.PRO),
        'is_on_pro_bono_plan': _is_a_pro_bono_status(ProBonoStatus.YES),
        'is_on_discounted_plan': _is_a_pro_bono_status(ProBonoStatus.DISCOUNTED),
        'is_on_extended_trial_plan': _is_on_extended_trial(),
        'max_edition_of_paying_plan': _max_edition()
    }
    def _subscribe_to_pro_with_rb(self):
        subscription = Subscription.get_subscribed_plan_by_domain(self.project)[1]

        new_subscription = subscription.change_plan(
            self.pro_rb_version,
            date_end=None,
            web_user=self.admin_user,
            service_type=SubscriptionType.IMPLEMENTATION,
            pro_bono_status=ProBonoStatus.NO,
            internal_change=True,
        )
        return new_subscription
Exemplo n.º 9
0
 def dehydrate_billing_properties(self, bundle):
     domain = _get_domain(bundle)
     plan_version, subscription = (
         Subscription.get_subscribed_plan_by_domain(domain)
     )
     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": plan_version,
     }
Exemplo n.º 10
0
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_subscribed_plan_by_domain(request.domain)[1]
        if current_subscription is None or current_subscription.account.date_confirmed_extra_charges is None:
            return False
    return True
Exemplo n.º 11
0
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_subscribed_plan_by_domain(
                    domain)[1]
                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)
Exemplo n.º 12
0
 def dehydrate_billing_properties(self, bundle):
     domain = _get_domain(bundle)
     plan_version, subscription = (
         Subscription.get_subscribed_plan_by_domain(domain))
     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":
         plan_version,
     }
    def _subscribe_to_pro_with_rb(self):
        subscription = Subscription.get_subscribed_plan_by_domain(self.project)[1]

        new_subscription = subscription.change_plan(
            self.pro_rb_version,
            date_end=None,
            web_user=self.admin_user,
            service_type=SubscriptionType.IMPLEMENTATION,
            pro_bono_status=ProBonoStatus.NO,
            internal_change=True,
        )
        return new_subscription
Exemplo n.º 14
0
def domain_has_privilege(domain, privilege_slug, **assignment):
    from corehq.apps.accounting.models import Subscription
    try:
        plan_version = Subscription.get_subscribed_plan_by_domain(domain)[0]
        roles = Role.objects.filter(slug=privilege_slug)
        if not roles:
            return False
        privilege = roles[0].instantiate(assignment)
        if plan_version.role.has_privilege(privilege):
            return True
    except AccountingError:
        pass
    return False
Exemplo n.º 15
0
def domain_has_privilege(domain, privilege_slug, **assignment):
    from corehq.apps.accounting.models import Subscription
    try:
        plan_version = Subscription.get_subscribed_plan_by_domain(domain)[0]
        roles = Role.objects.filter(slug=privilege_slug)
        if not roles:
            return False
        privilege = roles[0].instantiate(assignment)
        if plan_version.role.has_privilege(privilege):
            return True
    except AccountingError:
        pass
    return False
Exemplo n.º 16
0
 def process_request(cls, request):
     if hasattr(request, 'domain'):
         try:
             plan_version = Subscription.get_subscribed_plan_by_domain(request.domain)[0]
             request.role = plan_version.role
             request.plan = plan_version
             return None
         except AccountingError:
             pass
     try:
         request.role = Role.objects.get(slug='community_plan_v0')
     except Role.DoesNotExist:
         request.role = Role()  # A fresh Role() has no privileges
Exemplo n.º 17
0
def domain_has_privilege(domain, privilege_slug, **assignment):
    from corehq.apps.accounting.models import Subscription
    try:
        plan_version = Subscription.get_subscribed_plan_by_domain(domain)[0]
        privilege = Role.get_privilege(privilege_slug, assignment)
        if privilege is None:
            return False
        if plan_version.role.has_privilege(privilege):
            return True
    except ProductPlanNotFoundError:
        return False
    except AccountingError:
        pass
    return False
Exemplo n.º 18
0
def domain_has_privilege(domain, privilege_slug, **assignment):
    from corehq.apps.accounting.models import Subscription
    try:
        plan_version = Subscription.get_subscribed_plan_by_domain(domain)[0]
        privilege = Role.get_privilege(privilege_slug, assignment)
        if privilege is None:
            return False
        if plan_version.role.has_privilege(privilege):
            return True
    except ProductPlanNotFoundError:
        return False
    except AccountingError:
        pass
    return False
Exemplo n.º 19
0
 def process_request(cls, request):
     if hasattr(request, 'domain'):
         try:
             plan_version, subscription = Subscription.get_subscribed_plan_by_domain(request.domain)
             request.role = plan_version.role
             request.plan = plan_version
             request.subscription = subscription
             return None
         except AccountingError:
             pass
     try:
         request.role = Role.objects.get(slug='community_plan_v0')
     except Role.DoesNotExist:
         request.role = Role()  # A fresh Role() has no privileges
Exemplo n.º 20
0
 def apply_prbac(cls, request):
     if hasattr(request, 'domain'):
         try:
             plan_version, subscription = Subscription.get_subscribed_plan_by_domain(request.domain)
             request.role = plan_version.role
             request.plan = plan_version
             request.subscription = subscription
             return None
         except AccountingError:
             pass
     privilege = Role.get_privilege('community_plan_v0')
     if privilege is not None:
         request.role = privilege.role
     else:
         request.role = Role()  # A fresh Role() has no privileges
Exemplo n.º 21
0
 def apply_prbac(cls, request):
     if hasattr(request, 'domain'):
         try:
             plan_version, subscription = Subscription.get_subscribed_plan_by_domain(request.domain)
             request.role = plan_version.role
             request.plan = plan_version
             request.subscription = subscription
             return None
         except AccountingError:
             pass
     privilege = Role.get_privilege('community_plan_v1')
     if privilege is not None:
         request.role = privilege.role
     else:
         request.role = Role()  # A fresh Role() has no privileges
Exemplo n.º 22
0
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_subscribed_plan_by_domain(domain)[1]
                if 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)
Exemplo n.º 23
0
    def handle(self, dry_run=False, log_file=False, *args, **options):
        if not dry_run:
            confirm_force_reset = raw_input(
                "Are you sure you want to apply downgrades and upgrades to "
                "ALL domains? Type 'yes' to continue. \n")
            if confirm_force_reset != 'yes':
                return

        if log_file:
            orig_stdout = sys.stdout
            f = file('subscription_changes.txt', 'w')
            sys.stdout = f

        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 = Domain.wrap(domain_doc)
            logging.info("%s START" % domain.name)
            print("\n")
            plan_version, subscription = Subscription.get_subscribed_plan_by_domain(
                domain)
            if not subscription:
                subscriber = Subscriber.objects.get_or_create(
                    domain=domain.name)[0]
                print("Active subscription not found for domain %s" %
                      domain.name)
            else:
                subscriber = subscription.subscriber

            if not dry_run:
                print("%s => %s" % (domain.name, plan_version.plan.name))
                subscriber.apply_upgrades_and_downgrades(
                    new_plan_version=plan_version,
                    verbose=True,
                    new_subscription=subscription,
                )
            else:
                print("[DRY RUN] %s => %s" %
                      (domain.name, plan_version.plan.name))

            logging.info("%s END" % domain.name)

        if log_file:
            sys.stdout = orig_stdout
            f.close()
Exemplo n.º 24
0
    def handle(self, dry_run=False, log_file=False, *args, **options):
        if not dry_run:
            confirm_force_reset = raw_input(
                "Are you sure you want to apply downgrades and upgrades to "
                "ALL domains? Type 'yes' to continue. \n"
            )
            if confirm_force_reset != 'yes':
                return

        if log_file:
            orig_stdout = sys.stdout
            f = file('subscription_changes.txt', 'w')
            sys.stdout = f

        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 = Domain.wrap(domain_doc)
            logging.info("%s START" % domain.name)
            print ("\n")
            plan_version, subscription = Subscription.get_subscribed_plan_by_domain(domain)
            if not subscription:
                subscriber = Subscriber.objects.get_or_create(domain=domain.name)[0]
                print ("Active subscription not found for domain %s"
                       % domain.name)
            else:
                subscriber = subscription.subscriber

            if not dry_run:
                print ("%s => %s" %
                       (domain.name, plan_version.plan.name))
                subscriber.apply_upgrades_and_downgrades(
                    new_plan_version=plan_version,
                    verbose=True,
                    new_subscription=subscription,
                )
            else:
                print ("[DRY RUN] %s => %s" %
                       (domain.name, plan_version.plan.name))

            logging.info("%s END" % domain.name)

        if log_file:
            sys.stdout = orig_stdout
            f.close()
    def handle(self, *args, **options):
        if len(args) != 1:
            print "Invalid arguments: %s" % str(args)
            return
        domain = Domain.get_by_name(args[0])
        if not domain:
            print "Invalid domain name: %s" % args[0]
            return

        plan_version, subscription = Subscription.get_subscribed_plan_by_domain(domain.name)
        if plan_version.plan.edition == SoftwarePlanEdition.ENTERPRISE:
            print "Domain %s is already enterprise level" % domain.name
            return

        if subscription:
            subscription.change_plan(self.enterprise_plan_version)
        else:
            try:
                self.make_new_enterprise_subscription(domain)
            except NewSubscriptionError as e:
                print e.message
                return
        print 'Domain %s has been upgraded to enterprise level.' % domain.name
Exemplo n.º 26
0
def update_subscription_properties_by_user(couch_user):

    # 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)
    properties = {
        SoftwarePlanEdition.COMMUNITY: "no",
        SoftwarePlanEdition.STANDARD: "no",
        SoftwarePlanEdition.PRO: "no",
        SoftwarePlanEdition.ADVANCED: "no",
        SoftwarePlanEdition.ENTERPRISE: "no",
        "Pro Bono": "no",
    }

    for domain_name in couch_user.domains:
        plan_version, subscription = Subscription.get_subscribed_plan_by_domain(domain_name)
        if subscription is not None:
            if subscription.pro_bono_status == ProBonoStatus.YES:
                properties["Pro Bono"] = "yes"
        edition = plan_version.plan.edition
        if edition in properties:
            properties[edition] = "yes"

    identify.delay(couch_user.username, properties)
Exemplo n.º 27
0
    def get_notifications(self, in_data):
        # todo always grab alerts if they are still relevant
        subscribed_plan = Subscription.get_subscribed_plan_by_domain(
            self.get_domain())
        pro_tier_editions = [
            SoftwarePlanEdition.PRO, SoftwarePlanEdition.ADVANCED,
            SoftwarePlanEdition.ENTERPRISE
        ]
        if subscribed_plan.plan.edition in pro_tier_editions:
            plan_tier = 'pro'
        else:
            plan_tier = 'basic'

        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

        notifications = Notification.get_by_user(
            self.request.user,
            self.request.couch_user,
            plan_tier=plan_tier,
            hide_features=should_hide_feature_notifs(self.get_domain(),
                                                     plan_tier))
        has_unread = len([x for x in notifications if not x['isRead']]) > 0
        last_seen_notification_date = LastSeenNotification.get_last_seen_notification_date_for_user(
            self.request.user)
        return {
            'hasUnread': has_unread,
            'notifications': notifications,
            'lastSeenNotificationDate': last_seen_notification_date
        }
Exemplo n.º 28
0
def update_subscription_properties_by_user(couch_user):

    # 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)
    properties = {
        SoftwarePlanEdition.COMMUNITY: "no",
        SoftwarePlanEdition.STANDARD: "no",
        SoftwarePlanEdition.PRO: "no",
        SoftwarePlanEdition.ADVANCED: "no",
        SoftwarePlanEdition.ENTERPRISE: "no",
        "Pro Bono": "no",
    }

    for domain_name in couch_user.domains:
        plan_version, subscription = Subscription.get_subscribed_plan_by_domain(
            domain_name)
        if subscription is not None:
            if subscription.pro_bono_status == ProBonoStatus.YES:
                properties["Pro Bono"] = "yes"
        edition = plan_version.plan.edition
        if edition in properties:
            properties[edition] = "yes"

    identify.delay(couch_user.username, properties)
    def handle(self, *args, **options):
        if len(args) != 1:
            print "Invalid arguments: %s" % str(args)
            return
        domain = Domain.get_by_name(args[0])
        if not domain:
            print "Invalid domain name: %s" % args[0]
            return

        plan_version, subscription = Subscription.get_subscribed_plan_by_domain(
            domain.name)
        if plan_version.plan.edition == SoftwarePlanEdition.ENTERPRISE:
            print "Domain %s is already enterprise level" % domain.name
            return

        if subscription:
            subscription.change_plan(self.enterprise_plan_version)
        else:
            try:
                self.make_new_enterprise_subscription(domain)
            except NewSubscriptionError as e:
                print e.message
                return
        print 'Domain %s has been upgraded to enterprise level.' % domain.name
Exemplo n.º 30
0
 def plan_name(self):
     plan_version, _ = Subscription.get_subscribed_plan_by_domain(self.domain)
     return plan_version.plan.name
Exemplo n.º 31
0
    def post(self, req, *args, **kwargs):
        report = dict([(key, req.POST.get(key, '')) for key in (
            'subject',
            'username',
            'domain',
            'url',
            'message',
            'app_id',
            'cc',
            'email',
            '500traceback',
            'sentry_id',
        )])

        try:
            couch_user = req.couch_user
            full_name = couch_user.full_name
            if couch_user.is_commcare_user():
                email = report['email']
            else:
                email = couch_user.get_email()
        except Exception:
            full_name = None
            email = report['email']
        report['full_name'] = full_name
        report['email'] = email or report['username']

        if report['domain']:
            domain = report['domain']
        elif len(couch_user.domains) == 1:
            # This isn't a domain page, but the user has only one domain, so let's use that
            domain = couch_user.domains[0]
        else:
            domain = "<no domain>"

        message = ("username: {username}\n"
                   "full name: {full_name}\n"
                   "domain: {domain}\n"
                   "url: {url}\n").format(**report)

        domain_object = Domain.get_by_name(
            domain) if report['domain'] else None
        debug_context = {
            'datetime':
            datetime.utcnow(),
            'self_started':
            '<unknown>',
            'scale_backend':
            '<unknown>',
            'has_handoff_info':
            '<unknown>',
            'project_description':
            '<unknown>',
            'sentry_error':
            '{}{}'.format(getattr(settings, 'SENTRY_QUERY_URL', ''),
                          report['sentry_id'])
        }
        if domain_object:
            current_project_description = domain_object.project_description if domain_object else None
            new_project_description = req.POST.get('project_description')
            if (domain_object and req.couch_user.is_domain_admin(domain=domain)
                    and new_project_description and
                    current_project_description != new_project_description):
                domain_object.project_description = new_project_description
                domain_object.save()

            message += (("software plan: {software_plan}\n").format(
                software_plan=Subscription.get_subscribed_plan_by_domain(
                    domain), ))

            debug_context.update({
                'self_started':
                domain_object.internal.self_started,
                'scale_backend':
                should_use_sql_backend(domain),
                'has_handoff_info':
                bool(domain_object.internal.partner_contact),
                'project_description':
                domain_object.project_description,
            })

        subject = '{subject} ({domain})'.format(subject=report['subject'],
                                                domain=domain)
        cc = [el for el in report['cc'].strip().split(",") if el]

        if full_name and not any([c in full_name for c in '<>"']):
            reply_to = '"{full_name}" <{email}>'.format(**report)
        else:
            reply_to = report['email']

        # if the person looks like a commcare user, fogbugz can't reply
        # to their email, so just use the default
        if settings.HQ_ACCOUNT_ROOT in reply_to:
            reply_to = settings.SERVER_EMAIL

        message += "Message:\n\n{message}\n".format(message=report['message'])
        if req.POST.get('five-hundred-report'):
            extra_message = (
                "This message was reported from a 500 error page! "
                "Please fix this ASAP (as if you wouldn't anyway)...")
            extra_debug_info = (
                "datetime: {datetime}\n"
                "Is self start: {self_started}\n"
                "Is scale backend: {scale_backend}\n"
                "Has Support Hand-off Info: {has_handoff_info}\n"
                "Project description: {project_description}\n"
                "Sentry Error: {sentry_error}\n").format(**debug_context)
            traceback_info = cache.cache.get(
                report['500traceback']) or 'No traceback info available'
            cache.cache.delete(report['500traceback'])
            message = "\n\n".join(
                [message, extra_debug_info, extra_message, traceback_info])

        email = EmailMessage(subject=subject,
                             body=message,
                             to=self.recipients,
                             headers={'Reply-To': reply_to},
                             cc=cc)

        uploaded_file = req.FILES.get('report_issue')
        if uploaded_file:
            filename = uploaded_file.name
            content = uploaded_file.read()
            email.attach(filename=filename, content=content)

        # only fake the from email if it's an @dimagi.com account
        is_icds_env = settings.SERVER_ENVIRONMENT in settings.ICDS_ENVS
        if re.search(r'@dimagi\.com$', report['username']) and not is_icds_env:
            email.from_email = report['username']
        else:
            email.from_email = settings.CCHQ_BUG_REPORT_EMAIL

        email.send(fail_silently=False)

        if req.POST.get('five-hundred-report'):
            messages.success(
                req,
                "Your CommCare HQ Issue Report has been sent. We are working quickly to resolve this problem."
            )
            return HttpResponseRedirect(reverse('homepage'))

        return HttpResponse()
    def handle(self, *args, **options):
        if len(args) != 1:
            print "Invalid arguments: %s" % str(args)
            return

        completed = 0
        total = 0
        filename = args[0]
        with open(filename) as f:
            reader = csv.reader(f)
            reader.next()
            for row in reader:
                total = total + 1
                domain = row[0]
                plan_version, subscription = Subscription.get_subscribed_plan_by_domain(domain)
                if subscription is None:
                    print "Could not find Subscription for %s" % domain

                account = BillingAccount.get_account_by_domain(domain)
                if account is None:
                    print "Could not find BillingAccount for %s" % domain

                if account is not None and subscription is not None:
                    '''
                    service_type = self.normalize(row[1])  # self service, contracted, or not set
                    if service_type == "selfservice":
                        #print "%s service_type => SELF_SERVICE" % domain
                        subscription.service_type = SubscriptionType.SELF_SERVICE
                    elif service_type == "contracted":
                        #print "%s service_type => CONTRACTED" % domain
                        subscription.service_type = SubscriptionType.CONTRACTED
                    elif service_type == "notset":
                        #print "%s service_type => NOT_SET" % domain
                        subscription.service_type = SubscriptionType.NOT_SET
                    else:
                        pass
                        #print "Skipping service type for %s" % domain

                    entry_point = self.normalize(row[2])  # yes if self starter, might be missing
                    if entry_point == "yes":
                        #print "%s entry_point => SELF_STARTED" % domain
                        account.entry_point = EntryPoint.SELF_STARTED
                    elif entry_point == "no":
                        #print "%s entry_point => CONTRACTED" % domain
                        account.entry_point = EntryPoint.CONTRACTED
                    else:
                        #print "Skipping entry point for %s" % domain
                        pass
                    '''

                    pro_bono_status = self.normalize(row[3])  # yes/no
                    if pro_bono_status == "yes":
                        #print "%s pro_bono_status => YES" % domain
                        subscription.pro_bono_status = ProBonoStatus.YES
                    elif pro_bono_status == "discounted":
                        #print "%s pro_bono_status => DISCOUNTED" % domain
                        subscription.pro_bono_status = ProBonoStatus.DISCOUNTED
                    else:
                        #print "%s pro_bono_status => NO" % domain
                        subscription.pro_bono_status = ProBonoStatus.NO

                    '''print "setting %s's service_type=%s, entry_point=%s, pro_bono=%s" % (
                        domain, subscription.service_type, account.entry_point, subscription.pro_bono_status
                    )'''

                    subscription.save()
                    account.save()
                    completed = completed + 1

        print "Completed %i of %i domains" % (completed, total)
Exemplo n.º 33
0
def domain_is_on_trial(domain):
    from corehq.apps.accounting.models import Subscription
    subscription = Subscription.get_subscribed_plan_by_domain(domain)[1]
    return subscription.is_trial
Exemplo n.º 34
0
def domain_is_on_trial(domain):
    from corehq.apps.accounting.models import Subscription
    subscription = Subscription.get_subscribed_plan_by_domain(domain)[1]
    return subscription.is_trial
Exemplo n.º 35
0
 def plan_name(self):
     plan_version, _ = Subscription.get_subscribed_plan_by_domain(
         self.domain)
     return plan_version.plan.name
Exemplo n.º 36
0
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:
        plan_version, subscription = Subscription.get_subscribed_plan_by_domain(
            domain_name)
        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 handle(self, *args, **options):
        if len(args) != 1:
            print "Invalid arguments: %s" % str(args)
            return

        completed = 0
        total = 0
        filename = args[0]
        with open(filename) as f:
            reader = csv.reader(f)
            reader.next()
            for row in reader:
                total = total + 1
                domain = row[0]
                plan_version, subscription = Subscription.get_subscribed_plan_by_domain(
                    domain)
                if subscription is None:
                    print "Could not find Subscription for %s" % domain

                account = BillingAccount.get_account_by_domain(domain)
                if account is None:
                    print "Could not find BillingAccount for %s" % domain

                if account is not None and subscription is not None:
                    '''
                    service_type = self.normalize(row[1])  # self service, contracted, or not set
                    if service_type == "selfservice":
                        #print "%s service_type => SELF_SERVICE" % domain
                        subscription.service_type = SubscriptionType.SELF_SERVICE
                    elif service_type == "contracted":
                        #print "%s service_type => CONTRACTED" % domain
                        subscription.service_type = SubscriptionType.CONTRACTED
                    elif service_type == "notset":
                        #print "%s service_type => NOT_SET" % domain
                        subscription.service_type = SubscriptionType.NOT_SET
                    else:
                        pass
                        #print "Skipping service type for %s" % domain

                    entry_point = self.normalize(row[2])  # yes if self starter, might be missing
                    if entry_point == "yes":
                        #print "%s entry_point => SELF_STARTED" % domain
                        account.entry_point = EntryPoint.SELF_STARTED
                    elif entry_point == "no":
                        #print "%s entry_point => CONTRACTED" % domain
                        account.entry_point = EntryPoint.CONTRACTED
                    else:
                        #print "Skipping entry point for %s" % domain
                        pass
                    '''

                    pro_bono_status = self.normalize(row[3])  # yes/no
                    if pro_bono_status == "yes":
                        #print "%s pro_bono_status => YES" % domain
                        subscription.pro_bono_status = ProBonoStatus.YES
                    elif pro_bono_status == "discounted":
                        #print "%s pro_bono_status => DISCOUNTED" % domain
                        subscription.pro_bono_status = ProBonoStatus.DISCOUNTED
                    else:
                        #print "%s pro_bono_status => NO" % domain
                        subscription.pro_bono_status = ProBonoStatus.NO
                    '''print "setting %s's service_type=%s, entry_point=%s, pro_bono=%s" % (
                        domain, subscription.service_type, account.entry_point, subscription.pro_bono_status
                    )'''

                    subscription.save()
                    account.save()
                    completed = completed + 1

        print "Completed %i of %i domains" % (completed, total)
Exemplo n.º 38
0
    def post(self, req, *args, **kwargs):
        report = dict([(key, req.POST.get(key, '')) for key in (
            'subject',
            'username',
            'domain',
            'url',
            'message',
            'app_id',
            'cc',
            'email',
            '500traceback',
            'sentry_id',
        )])

        try:
            couch_user = req.couch_user
            full_name = couch_user.full_name
            if couch_user.is_commcare_user():
                email = report['email']
            else:
                email = couch_user.get_email()
        except Exception:
            full_name = None
            email = report['email']
        report['full_name'] = full_name
        report['email'] = email or report['username']

        if report['domain']:
            domain = report['domain']
        elif len(couch_user.domains) == 1:
            # This isn't a domain page, but the user has only one domain, so let's use that
            domain = couch_user.domains[0]
        else:
            domain = "<no domain>"

        message = (
            "username: {username}\n"
            "full name: {full_name}\n"
            "domain: {domain}\n"
            "url: {url}\n"
        ).format(**report)

        domain_object = Domain.get_by_name(domain) if report['domain'] else None
        debug_context = {
            'datetime': datetime.utcnow(),
            'self_started': '<unknown>',
            'scale_backend': '<unknown>',
            'has_handoff_info': '<unknown>',
            'project_description': '<unknown>',
            'sentry_error': '{}{}'.format(getattr(settings, 'SENTRY_QUERY_URL'), report['sentry_id'])
        }
        if domain_object:
            current_project_description = domain_object.project_description if domain_object else None
            new_project_description = req.POST.get('project_description')
            if (domain_object and
                    req.couch_user.is_domain_admin(domain=domain) and
                    new_project_description and current_project_description != new_project_description):
                domain_object.project_description = new_project_description
                domain_object.save()

            message += ((
                "software plan: {software_plan}\n"
            ).format(
                software_plan=Subscription.get_subscribed_plan_by_domain(domain),
            ))

            debug_context.update({
                'self_started': domain_object.internal.self_started,
                'scale_backend': should_use_sql_backend(domain),
                'has_handoff_info': bool(domain_object.internal.partner_contact),
                'project_description': domain_object.project_description,
            })

        subject = '{subject} ({domain})'.format(subject=report['subject'], domain=domain)
        cc = [el for el in report['cc'].strip().split(",") if el]

        if full_name and not any([c in full_name for c in '<>"']):
            reply_to = '"{full_name}" <{email}>'.format(**report)
        else:
            reply_to = report['email']

        # if the person looks like a commcare user, fogbugz can't reply
        # to their email, so just use the default
        if settings.HQ_ACCOUNT_ROOT in reply_to:
            reply_to = settings.SERVER_EMAIL

        message += "Message:\n\n{message}\n".format(message=report['message'])
        if req.POST.get('five-hundred-report'):
            extra_message = ("This message was reported from a 500 error page! "
                             "Please fix this ASAP (as if you wouldn't anyway)...")
            extra_debug_info = (
                "datetime: {datetime}\n"
                "Is self start: {self_started}\n"
                "Is scale backend: {scale_backend}\n"
                "Has Support Hand-off Info: {has_handoff_info}\n"
                "Project description: {project_description}\n"
                "Sentry Error: {sentry_error}\n"
            ).format(**debug_context)
            traceback_info = cache.cache.get(report['500traceback']) or 'No traceback info available'
            cache.cache.delete(report['500traceback'])
            message = "\n\n".join([message, extra_debug_info, extra_message, traceback_info])

        email = EmailMessage(
            subject=subject,
            body=message,
            to=self.recipients,
            headers={'Reply-To': reply_to},
            cc=cc
        )

        uploaded_file = req.FILES.get('report_issue')
        if uploaded_file:
            filename = uploaded_file.name
            content = uploaded_file.read()
            email.attach(filename=filename, content=content)

        # only fake the from email if it's an @dimagi.com account
        is_icds_env = settings.SERVER_ENVIRONMENT in settings.ICDS_ENVS
        if re.search(r'@dimagi\.com$', report['username']) and not is_icds_env:
            email.from_email = report['username']
        else:
            email.from_email = settings.CCHQ_BUG_REPORT_EMAIL

        email.send(fail_silently=False)

        if req.POST.get('five-hundred-report'):
            messages.success(
                req,
                "Your CommCare HQ Issue Report has been sent. We are working quickly to resolve this problem."
            )
            return HttpResponseRedirect(reverse('homepage'))

        return HttpResponse()