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) )
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))
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)
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)
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
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 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
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)
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
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
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
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
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
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
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
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
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
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)
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, 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
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 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 }
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
def plan_name(self): plan_version, _ = Subscription.get_subscribed_plan_by_domain(self.domain) return plan_version.plan.name
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)
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
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
def plan_name(self): plan_version, _ = Subscription.get_subscribed_plan_by_domain( self.domain) return plan_version.plan.name
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)
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()