Beispiel #1
0
def send_autopay_failed(invoice, payment_method):
    subscription = invoice.subscription
    auto_payer = subscription.account.auto_pay_user
    payment_method = StripePaymentMethod.objects.get(web_user=auto_payer)
    autopay_card = payment_method.get_autopay_card(subscription.account)
    try:
        recipient = WebUser.get_by_username(auto_payer).get_email()
    except ResourceNotFound:
        recipient = auto_payer
    domain = invoice.get_domain()

    context = {
        'domain': domain,
        'subscription_plan': subscription.plan_version.plan.name,
        'billing_date': datetime.date.today(),
        'invoice_number': invoice.invoice_number,
        'autopay_card': autopay_card,
        'domain_url': absolute_reverse('dashboard_default', args=[domain]),
        'billing_info_url': absolute_reverse('domain_update_billing_info', args=[domain]),
        'support_email': settings.INVOICING_CONTACT_EMAIL,
    }

    template_html = 'accounting/autopay_failed_email.html'
    template_plaintext = 'accounting/autopay_failed_email.txt'

    send_HTML_email(
        subject="Subscription Payment for CommCare Invoice %s was declined" % invoice.invoice_number,
        recipient=recipient,
        html_content=render_to_string(template_html, context),
        text_content=render_to_string(template_plaintext, context),
        email_from=get_dimagi_from_email_by_product(subscription.plan_version.product_rate.product.product_type),
    )
Beispiel #2
0
 def url(self):
     try:
         if self.is_configurable_report:
             url_base = absolute_reverse(self.report_slug, args=[self.domain, self.subreport_slug])
         else:
             url_base = absolute_reverse(self._dispatcher.name(), kwargs=self.url_kwargs)
         return url_base + '?' + self.query_string
     except UnsupportedSavedReportError:
         return "#"
     except Exception as e:
         logging.exception(e.message)
         return "#"
Beispiel #3
0
def process_email_request(domain, download_id, email_address):
    dropbox_url = absolute_reverse('dropbox_upload', args=(download_id,))
    download_url = "{}?get_file".format(absolute_reverse('retrieve_download', args=(download_id,)))
    try:
        allow_dropbox_sync = get_download_context(download_id).get('allow_dropbox_sync', False)
    except TaskFailedError:
        allow_dropbox_sync = False
    dropbox_message = ''
    if allow_dropbox_sync:
        dropbox_message = _('<br/><br/>You can also upload your data to Dropbox with the link below:<br/>'
                            '{}').format(dropbox_url)
    email_body = _('Your CommCare export for {} is ready! Click on the link below to download your requested data:'
                   '<br/>{}{}').format(domain, download_url, dropbox_message)
    send_HTML_email(_('CommCare Export Complete'), email_address, email_body)
Beispiel #4
0
 def get_name_or_link(self, d, internal_settings=False):
     if not getattr(self, 'show_name', None):
         reverse_str = "domain_homepage" if not internal_settings else "domain_internal_settings"
         return mark_safe('<a href="%s">%s</a>' %
                          (absolute_reverse(reverse_str, args=[d['name']]), d.get('hr_name') or d['name']))
     else:
         return d['name']
Beispiel #5
0
    def report_context(self):
        ret = {}

        try:
            patient_doc = self.get_case()
            has_error = False
        except Exception:
            has_error = True
            patient_doc = None

        if patient_doc is None:
            self.report_template_path = "reports/careplan/nopatient.html"
            if has_error:
                ret['error_message'] = "Patient not found"
            else:
                ret['error_message'] = "No patient selected"
            return ret

        ret['patient_doc'] = patient_doc

        ret.update({
            'case_hierarchy_options': {
                "show_view_buttons": False,
                "get_case_url": lambda case_id: absolute_reverse('case_details', args=[self.domain, case_id]),
                "columns": self.related_cases_columns,
                "related_type_info": self.related_type_info
            },
            'case': patient_doc,
        })
        self.report_template_path = "reports/careplan/patient_careplan.html"
        return ret
Beispiel #6
0
    def page_context(self):
        # The webhook secret is a piece of data that is sent to hq on each
        # Telerivet inbound request. It's used to tie an inbound request to
        # a Telerivet backend.
        webhook_secret = uuid.uuid4().hex

        # The request token is only used for the purposes of using this UI to
        # setup a Telerivet backend. We need a way to post the webhook_secret
        # to create the backend, but we want hq to be the origin of the secret
        # generation. So instead, the request_token resolves to the webhook_secret
        # via a redis lookup which expires in 1 week.
        request_token = uuid.uuid4().hex

        self.set_cached_webhook_secret(request_token, webhook_secret)
        domain_has_default_gateway = SQLMobileBackend.get_domain_default_backend(
            SQLMobileBackend.SMS,
            self.domain,
            id_only=True
        ) is not None

        return {
            'outgoing_sms_form': TelerivetOutgoingSMSForm(),
            'test_sms_form': TelerivetPhoneNumberForm(),
            'finalize_gateway_form': FinalizeGatewaySetupForm(
                initial={
                    'set_as_default': (FinalizeGatewaySetupForm.NO
                                       if domain_has_default_gateway
                                       else FinalizeGatewaySetupForm.YES),
                }
            ),
            'webhook_url': absolute_reverse('telerivet_in'),
            'webhook_secret': webhook_secret,
            'request_token': request_token,
        }
Beispiel #7
0
def email_enterprise_report(domain, slug, couch_user):
    account = BillingAccount.get_account_by_domain(domain)
    report = EnterpriseReport.create(slug, account.id, couch_user)

    # Generate file
    csv_file = io.StringIO()
    writer = csv.writer(csv_file)
    writer.writerow(report.headers)
    writer.writerows(report.rows)

    # Store file in redis
    hash_id = uuid.uuid4().hex
    redis = get_redis_client()
    redis.set(hash_id, csv_file.getvalue())
    redis.expire(hash_id, 60 * 60 * 24)
    csv_file.close()

    # Send email
    url = absolute_reverse("enterprise_dashboard_download", args=[domain, report.slug, str(hash_id)])
    link = "<a href='{}'>{}</a>".format(url, url)
    subject = _("Enterprise Dashboard: {}").format(report.title)
    body = "The enterprise report you requested for the account {} is ready.<br>" \
           "You can download the data at the following link: {}<br><br>" \
           "Please remember that this link will only be active for 24 hours.".format(account.name, link)
    send_html_email_async(subject, couch_user.username, body)
Beispiel #8
0
 def _link(self):
     try:
         link = absolute_reverse('case_data', args=[self.report.domain, self.case.get('_id')])
     except NoReverseMatch:
         return _("No link found")
     return html.mark_safe(
         "<a class='ajax_dialog' href='{}' target='_blank'>{}</a>".format(link, _("View Case"))
     )
Beispiel #9
0
 def app_to_json(app):
     return {
         'name': app.name,
         'version': app.version,
         'app_id': app.get_id,
         'download_url': absolute_reverse('direct_ccz', args=[domain],
                                          params={'app_id': app.get_id})
     }
 def test_get_value(self):
     doc = {'external_blobs': {'1234.jpg': {}},
            'photo': '1234.jpg'}
     result = self.column.get_value('my-domain', '1234', doc, [PathNode(name='form')])
     self.assertEqual(
         result,
         absolute_reverse('api_form_attachment', args=('my-domain', '1234', '1234.jpg'))
     )
Beispiel #11
0
 def get_user_link(self, user):
     user_link_template = '<a href="%(link)s">%(username)s</a>'
     from corehq.apps.users.views.mobile import EditCommCareUserView
     user_link = user_link_template % {
         "link": absolute_reverse(EditCommCareUserView.urlname,
                                  args=[self.domain, user._id]),
         "username": user.username_in_report
     }
     return self.table_cell(user.raw_username, user_link)
Beispiel #12
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)
Beispiel #13
0
 def send_activation_email(self):
     url = absolute_reverse("orgs_accept_invitation",
                            args=[self.organization, self.get_id])
     params = {"organization": self.organization, "url": url,
               "inviter": self.get_inviter().formatted_name}
     text_content = render_to_string("orgs/email/org_invite.txt", params)
     html_content = render_to_string("orgs/email/org_invite.html", params)
     subject = 'Invitation from %s to join CommCareHQ' % self.get_inviter().formatted_name
     send_HTML_email(subject, self.email, html_content, text_content=text_content,
                     email_from=settings.DEFAULT_FROM_EMAIL)
Beispiel #14
0
 def _build_remote_request_queries(self):
     return [
         RemoteRequestQuery(
             url=absolute_reverse('remote_search', args=[self.app.domain]),
             storage_instance=RESULTS_INSTANCE,
             template='case',
             data=self._get_remote_request_query_datums(),
             prompts=self._build_query_prompts()
         )
     ]
Beispiel #15
0
 def _build_remote_request_post(self):
     return RemoteRequestPost(
         url=absolute_reverse('claim_case', args=[self.domain]),
         relevant=self.module.search_config.relevant,
         data=[
             QueryData(
                 key='case_id',
                 ref=QuerySessionXPath('case_id').instance(),
             ),
         ]
     )
    def test_get_value_excel_format(self):
        column = MultiMediaExportColumn(item=MultiMediaItem(path=[PathNode(name="form"), PathNode(name="photo")]))

        result = column.get_value(
            "my-domain", "1234", {"photo": "1234.jpg"}, [PathNode(name="form")], transform_dates=True
        )
        self.assertEqual(
            result,
            '=HYPERLINK("{}?attachment=1234.jpg")'.format(
                absolute_reverse("download_attachment", args=("my-domain", "1234"))
            ),
        )
    def test_get_value(self):
        column = MultiMediaExportColumn(item=MultiMediaItem(path=[PathNode(name="form"), PathNode(name="photo")]))

        result = column.get_value("my-domain", "1234", {"photo": "1234.jpg"}, [PathNode(name="form")])
        self.assertEqual(
            result, "{}?attachment=1234.jpg".format(absolute_reverse("download_attachment", args=("my-domain", "1234")))
        )
        result = column.get_value("my-domain", "1234", {"photo": None}, [PathNode(name="form")])
        self.assertEqual(result, MISSING_VALUE)

        result = column.get_value("my-domain", "1234", {"photo": ""}, [PathNode(name="form")])
        self.assertEqual(result, "")
Beispiel #18
0
    def to_json(self, data, options=None):
        options = options or {}
        domain = data.pop('domain', None)
        if not domain:
            raise Exception('API requires domain to be set! Did you add it in a custom create_response function?')
        case_type = data.pop('case_type', None)
        if not case_type:
            raise Exception(
                'API requires case_type to be set! Did you add it in a custom create_response function?'
            )
        api_path = data.pop('api_path', None)
        if not api_path:
            raise Exception(
                'API requires api_path to be set! Did you add it in a custom create_response function?'
            )
        data = self.to_simple(data, options)
        data['@odata.context'] = '{}#{}'.format(absolute_reverse('odata_meta', args=[domain]), case_type)

        next_url = data.pop('meta', {}).get('next')
        if next_url:
            data['@odata.nextLink'] = '{}{}{}'.format(get_url_base(), api_path, next_url)
        # move "objects" to "value"
        data['value'] = data.pop('objects')

        # clean properties
        def _clean_property_name(name):
            # for whatever ridiculous reason, at least in Tableau,
            # when these are nested inside an object they can't have underscores in them
            return name.replace('_', '')

        for i, case_json in enumerate(data['value']):
            case_json['properties'] = {_clean_property_name(k): v for k, v in case_json['properties'].items()}

        case_type_to_properties = get_case_type_to_properties(domain)
        properties_to_include = [
            'casename', 'casetype', 'dateopened', 'ownerid', 'backendid'
        ] + case_type_to_properties.get(case_type, [])

        for value in data['value']:
            for remove_property in [
                'id',
                'indexed_on',
                'indices',
                'resource_uri',
            ]:
                value.pop(remove_property)
            properties = value.get('properties')
            for property_name in list(properties):
                if property_name not in properties_to_include:
                    properties.pop(property_name)

        return json.dumps(data, cls=DjangoJSONEncoder, sort_keys=True)
Beispiel #19
0
 def get(self, request, domain):
     data = {
         '@odata.context': absolute_reverse('odata_meta', args=[domain]),
         'value': [
             {
                 'name': case_type,
                 'kind': 'EntitySet',
                 'url': case_type,
             }
             for case_type in get_case_types_for_domain_es(domain)
         ]
     }
     return add_odata_headers(JsonResponse(data))
Beispiel #20
0
    def get_resource_uri(self, bundle_or_obj=None):
        if isinstance(bundle_or_obj, Bundle):
            obj = bundle_or_obj.obj
        elif bundle_or_obj is None:
            return None
        else:
            obj = bundle_or_obj

        return absolute_reverse('api_dispatch_detail', kwargs={
            'resource_name': self._meta.resource_name,
            'domain': obj.domain,
            'api_name': self._meta.api_name,
            'location_id': obj.location_id
        })
    def test_get_value(self):
        column = MultiMediaExportColumn(
            item=MultiMediaItem(
                path=[PathNode(name='form'), PathNode(name='photo')],
            ),
        )

        result = column.get_value('my-domain', '1234', {'photo': '1234.jpg'}, [PathNode(name='form')])
        self.assertEqual(
            result,
            '{}?attachment=1234.jpg'.format(
                absolute_reverse('download_attachment', args=('my-domain', '1234'))
            )
        )
Beispiel #22
0
    def setUpClass(cls):
        super(RemoteAuthTest, cls).setUpClass()

        cls.master_domain = uuid.uuid4().hex
        cls.linked_domain = uuid.uuid4().hex

        cls.domain = create_domain(cls.master_domain)
        cls.couch_user = WebUser.create(cls.master_domain, "test", "foobar")
        cls.django_user = cls.couch_user.get_django_user()
        cls.api_key, _ = ApiKey.objects.get_or_create(user=cls.django_user)

        cls.auth_headers = {'HTTP_AUTHORIZATION': 'apikey test:%s' % cls.api_key.key}

        cls.linked_domain_requester = absolute_reverse('domain_homepage', args=[cls.linked_domain])
        cls.domain_link = DomainLink.link_domains(cls.linked_domain_requester, cls.master_domain)
Beispiel #23
0
def _apply_downgrade_process(oldest_unpaid_invoice, total, today, subscription=None):
    from corehq.apps.domain.views.accounting import DomainBillingStatementsView, DomainSubscriptionView
    from corehq.apps.accounting.views import EnterpriseBillingStatementsView

    context = {
        'total': format(total, '7.2f'),
        'date_60': oldest_unpaid_invoice.date_due + datetime.timedelta(days=60),
        'contact_email': settings.INVOICING_CONTACT_EMAIL
    }
    if oldest_unpaid_invoice.is_customer_invoice:
        domain = oldest_unpaid_invoice.subscriptions.first().subscriber.domain
        context.update({
            'statements_url': absolute_reverse(
                EnterpriseBillingStatementsView.urlname, args=[domain]),
            'domain_or_account': oldest_unpaid_invoice.account.name
        })
    else:
        domain = subscription.subscriber.domain
        context.update({
            'domain': domain,
            'subscription_url': absolute_reverse(DomainSubscriptionView.urlname,
                                                 args=[domain]),
            'statements_url': absolute_reverse(DomainBillingStatementsView.urlname,
                                               args=[domain]),
            'domain_or_account': domain
        })

    days_ago = (today - oldest_unpaid_invoice.date_due).days
    if days_ago == 61:
        if not oldest_unpaid_invoice.is_customer_invoice:  # We do not automatically downgrade customer invoices
            _downgrade_domain(subscription)
            _send_downgrade_notice(oldest_unpaid_invoice, context)
    elif days_ago == 58:
        _send_downgrade_warning(oldest_unpaid_invoice, context)
    elif days_ago == 30:
        _send_overdue_notice(oldest_unpaid_invoice, context)
Beispiel #24
0
def _apply_downgrade_process(subscription, oldest_unpaid_invoice, total, today):
    from corehq.apps.domain.views.accounting import DomainBillingStatementsView, DomainSubscriptionView

    days_ago = (today - oldest_unpaid_invoice.date_due).days
    domain = subscription.subscriber.domain
    context = {
        'domain': domain,
        'total': total,
        'subscription_url': absolute_reverse(DomainSubscriptionView.urlname,
                                             args=[domain]),
        'statements_url': absolute_reverse(DomainBillingStatementsView.urlname,
                                           args=[domain]),
        'date_60': oldest_unpaid_invoice.date_due + datetime.timedelta(days=60),
        'contact_email': settings.INVOICING_CONTACT_EMAIL
    }
    if days_ago == 61:
        _downgrade_domain(subscription)
        _send_downgrade_notice(oldest_unpaid_invoice, context)
    elif days_ago == 58:
        _send_downgrade_warning(oldest_unpaid_invoice, context)
    elif days_ago == 30:
        _send_overdue_notice(oldest_unpaid_invoice, context)
    elif days_ago == 1:
        _create_overdue_notification(oldest_unpaid_invoice, context)
 def test_get_value_excel_format(self):
     doc = {'external_blobs': {'1234.jpg': {}},
            'photo': '1234.jpg'}
     result = self.column.get_value(
         'my-domain',
         '1234',
         doc,
         [PathNode(name='form')],
         transform_dates=True,
     )
     self.assertEqual(
         result,
         '=HYPERLINK("{}")'.format(
             absolute_reverse('api_form_attachment', args=('my-domain', '1234', '1234.jpg'))
         )
     )
Beispiel #26
0
def _send_email(user, report, hash_id):
    domain = report.domain or user.get_domains()[0]
    link = absolute_reverse("export_report", args=[domain, str(hash_id),
                                                   report.export_format])

    title = "%s: Requested export excel data"
    body = "The export you requested for the '%s' report is ready.<br>" \
           "You can download the data at the following link: %s<br><br>" \
           "Please remember that this link will only be active for 24 hours."

    send_HTML_email(
        _(title) % report.name,
        user.get_email(),
        _(body) % (report.name, "<a href='%s'>%s</a>" % (link, link)),
        email_from=settings.DEFAULT_FROM_EMAIL
    )
Beispiel #27
0
    def get_url(cls, domain=None, render_as=None, **kwargs):
        # NOTE: I'm pretty sure this doesn't work if you ever pass in render_as
        # but leaving as is for now, as it should be obvious as soon as that 
        # breaks something

        if isinstance(cls, cls):
            domain = getattr(cls, 'domain')
            render_as = getattr(cls, 'rendered_as')
        if render_as is not None and render_as not in cls.dispatcher.allowed_renderings():
            raise ValueError('The render_as parameter is not one of the following allowed values: %s' %
                             ', '.join(cls.dispatcher.allowed_renderings()))
        url_args = [domain] if domain is not None else []
        if render_as is not None:
            url_args.append(render_as+'/')
        return absolute_reverse(cls.dispatcher.name(),
                                args=url_args + [cls.slug])
Beispiel #28
0
def _do_request_to_remote_hq(relative_url, remote_details, linked_domain, params=None, method='get'):
    """
    :param relative_url: Relative URL on remote HQ
    :param remote_details: RemoteDetails object containing remote URL base and auth details
    :param linked_domain: Used for permission check on remote system
    :param params: GET/POST params to include
    :param method:
    :return:
    """
    url_base = remote_details.url_base
    username = remote_details.username
    api_key = remote_details.api_key
    full_url = '%s%s' % (url_base, relative_url)
    headers = {
        'HQ-REMOTE-REQUESTER': absolute_reverse('domain_homepage', args=[linked_domain])
    }
    try:
        response = requests.request(
            method, full_url,
            params=params, auth=ApiKeyAuth(username, api_key), headers=headers
        )
    except ConnectionError:
        notify_exception(None, "Error performing remote app request", details={
            'remote_url': full_url,
            'params': params,
            'headers': headers
        })
        raise RemoteRequestError()
    if response.status_code == 401:
        raise RemoteAuthError(response.status_code)
    elif response.status_code == 403:
        raise ActionNotPermitted(response.status_code)
    elif response.status_code != 200:
        notify_exception(None, "Error performing remote app request", details={
            'remote_url': full_url,
            'response_code': response.status_code,
            'params': params
        })
        raise RemoteRequestError(response.status_code)
    return response
Beispiel #29
0
def check_es_index():
    """
    Verify that the Case and soon to be added XForm Elastic indices are up to date with what's in couch

    This code is also called in the HQ admin page as well
    """

    es_status = {}
    es_status.update(check_es_cluster_health())

    es_status.update(check_case_es_index())
    es_status.update(check_xform_es_index())

    es_status.update(check_reportcase_es_index())
    es_status.update(check_reportxform_es_index())

    do_notify = False
    message = []
    if es_status[CLUSTER_HEALTH] == 'red':
        do_notify = True
        message.append("Cluster health is red - something is up with the ES machine")

    for index in es_status.keys():
        if index == CLUSTER_HEALTH:
            continue
        pillow_status = es_status[index]
        if not pillow_status['status']:
            do_notify = True
            message.append(
                "Elasticsearch %s Index Issue: %s" % (index, es_status[index]['message']))

    if do_notify:
        message.append(
            "This alert can give false alarms due to timing lag, so please double check "
            + absolute_reverse("system_info")
            + " and the Elasticsearch Status section to make sure."
        )
        notify_exception(None, message='\n'.join(message))
Beispiel #30
0
def send_mobile_experience_reminder(recipient, full_name):
    url = absolute_reverse("login")

    params = {
        "full_name": full_name,
        "url": url,
        'url_prefix': '' if settings.STATIC_CDN else 'http://' + get_site_domain(),
    }
    message_plaintext = render_to_string(
        'registration/email/mobile_signup_reminder.txt', params)
    message_html = render_to_string(
        'registration/email/mobile_signup_reminder.html', params)

    subject = ugettext('Visit CommCareHQ on your computer!')

    try:
        send_html_email_async.delay(subject, recipient, message_html,
                                    text_content=message_plaintext,
                                    email_from=settings.DEFAULT_FROM_EMAIL)
    except Exception:
        logging.warning(
            "Can't send email, but the message was:\n%s" % message_plaintext)
        raise
Beispiel #31
0
def _bulk_case_upload_api(request, domain):
    try:
        upload_file = request.FILES["file"]
        case_type = request.POST["case_type"]
        if not upload_file or not case_type:
            raise Exception
    except Exception:
        raise ImporterError("Invalid POST request. "
                            "Both 'file' and 'case_type' are required")

    search_field = request.POST.get('search_field', 'case_id')
    create_new_cases = request.POST.get('create_new_cases') == 'on'

    if search_field == 'case_id':
        default_search_column = 'case_id'
    elif search_field == 'external_id':
        default_search_column = 'external_id'
    else:
        raise ImporterError("Illegal value for search_field: %s" %
                            search_field)

    search_column = request.POST.get('search_column', default_search_column)
    name_column = request.POST.get('name_column', 'name')

    upload_comment = request.POST.get('comment')

    case_upload, context = _process_file_and_get_upload(
        upload_file, request, domain)

    case_upload.check_file()

    with case_upload.get_spreadsheet() as spreadsheet:
        columns = spreadsheet.get_header_columns()
        excel_fields = columns

    # hide search column and matching case fields from the update list
    if search_column in excel_fields:
        excel_fields.remove(search_column)

    custom_fields = []
    case_fields = []

    #Create the field arrays for the importer in the same format
    #as the "Step 2" Web UI from the manual process
    for f in excel_fields:
        if f == name_column:
            custom_fields.append("")
            case_fields.append("name")
        else:
            custom_fields.append(f)
            case_fields.append("")

    config = importer_util.ImporterConfig(couch_user_id=request.couch_user._id,
                                          excel_fields=excel_fields,
                                          case_fields=case_fields,
                                          custom_fields=custom_fields,
                                          search_column=search_column,
                                          case_type=case_type,
                                          search_field=search_field,
                                          create_new_cases=create_new_cases)

    case_upload.trigger_upload(domain, config, comment=upload_comment)

    upload_id = case_upload.upload_id
    status_url = absolute_reverse('case_importer_upload_status',
                                  args=(domain, upload_id))

    return json_response({
        "code": 200,
        "message": "success",
        "status_url": status_url
    })
Beispiel #32
0
    def draw_footer(self):
        width = inches(5.00)
        left_x = inches(0.5)

        options = "PAYMENT OPTIONS:"
        self.canvas.setFontSize(SMALL_FONT_SIZE)
        options_text = Paragraph(options, ParagraphStyle(''))
        options_text.wrapOn(self.canvas, width, inches(.12))
        options_text.drawOn(self.canvas, left_x, inches(3.5))
        self.canvas.setFontSize(DEFAULT_FONT_SIZE)

        flywire = """<strong>International payments:</strong>
                            Make payments in your local currency
                            via bank transfer or credit card by following this link:
                            <link href='{flywire_link}' color='blue'>{flywire_link}</link><br />""".format(
            flywire_link="https://wl.flywire.com/?destination=DMG")
        flywire_text = Paragraph(flywire, ParagraphStyle(''))
        flywire_text.wrapOn(self.canvas, width, inches(.4))
        flywire_text.drawOn(self.canvas, left_x, inches(2.95))

        from corehq.apps.domain.views.accounting import DomainBillingStatementsView
        credit_card = """<strong>Credit card payments (USD)</strong> can be made online here:<br />
                            <link href='{payment_page}' color='blue'>{payment_page}</link><br />""".format(
            payment_page=absolute_reverse(DomainBillingStatementsView.urlname,
                                          args=[self.project_name]))
        credit_card_text = Paragraph(credit_card, ParagraphStyle(''))
        credit_card_text.wrapOn(self.canvas, width, inches(.5))
        credit_card_text.drawOn(self.canvas, left_x, inches(2.4))

        ach_or_wire = """<strong>ACH or Wire:</strong> If you make payment via ACH
                            or Wire, please make sure to email
                            <font color='blue'>{invoicing_contact_email}</font>
                            so that we can match your payment to the correct invoice.  Please include:
                            Invoice No., Project Space, and payment date in the email. <br />""".format(
            invoicing_contact_email=settings.INVOICING_CONTACT_EMAIL, )
        ach_or_wire_text = Paragraph(ach_or_wire, ParagraphStyle(''))
        ach_or_wire_text.wrapOn(self.canvas, width, inches(.5))
        ach_or_wire_text.drawOn(self.canvas, left_x, inches(1.7))

        ach_payment_text = """<strong>ACH payment</strong>
                            (preferred over wire payment for transfer in the US):<br />
                            Bank: {bank_name}
                            Bank Address: {bank_address}
                            Account Number: {account_number}
                            Routing Number or ABA: {routing_number_ach}<br />""".format(
            bank_name=self.bank_name,
            bank_address=self.bank_address,
            account_number=self.account_number,
            routing_number_ach=self.routing_number_ach)
        wire_payment_text = """<strong>Wire payment</strong>:<br />
                            Bank: {bank_name}
                            Bank Address: {bank_address}
                            Account Number: {account_number}
                            Routing Number or ABA: {routing_number_wire}
                            Swift Code: {swift_code}<br/>""".format(
            bank_name=self.bank_name,
            bank_address=self.bank_address,
            account_number=self.account_number,
            routing_number_wire=self.routing_number_wire,
            swift_code=self.swift_code)
        payment_info2 = Paragraph(
            '\n'.join([
                ach_payment_text,
                wire_payment_text,
            ]), ParagraphStyle(''))
        payment_info2.wrapOn(self.canvas, width - inches(0.1), inches(0.9))
        payment_info2.drawOn(self.canvas, inches(0.6), inches(0.5))
Beispiel #33
0
 def _fmt_submission_link(self, submission_id):
     url = absolute_reverse("render_form_data", args=[self.domain, submission_id])
     display_text = _("View Submission")
     ret = self.table_cell(display_text, '<a href="%s">%s</a>' % (url, display_text))
     ret['raw'] = submission_id
     return ret
    def draw_footer(self):
        from corehq.apps.domain.views import DomainBillingStatementsView

        totals_x = inches(5.85)
        line_height = inches(0.25)
        subtotal_y = inches(3.5)
        tax_y = subtotal_y - line_height
        credit_y = tax_y - line_height
        total_y = credit_y - (line_height * 2)

        totals_money_x = totals_x + inches(1)

        self.canvas.setFillColorRGB(*LIGHT_GRAY)
        self.canvas.rect(
            inches(5.7),
            inches(2.3),
            inches(2.05),
            inches(0.5),
            fill=1
        )
        self.canvas.setFillColorRGB(*BLACK)

        self.canvas.drawString(totals_x, subtotal_y, "Subtotal:")
        self.canvas.drawString(totals_x, tax_y,
                               "Tax (%0.2f%%):" % self.tax_rate)
        self.canvas.drawString(totals_x, credit_y, "Credit:")
        self.canvas.drawString(totals_x, total_y, "Total:")
        self.canvas.drawString(
            totals_money_x,
            subtotal_y,
            get_money_str(self.subtotal)
        )
        self.canvas.drawString(
            totals_money_x,
            tax_y,
            get_money_str(self.applied_tax)
        )
        self.canvas.drawString(
            totals_money_x,
            credit_y,
            get_money_str(self.applied_credit)
        )
        self.canvas.drawString(
            totals_money_x,
            total_y,
            get_money_str(self.total)
        )

        self.canvas.setFontSize(SMALL_FONT_SIZE)
        self.canvas.drawString(inches(5.85), inches(2.1),
                               "Thank you for using CommCare HQ.")
        self.canvas.setFontSize(DEFAULT_FONT_SIZE)

        width = inches(5.00)
        left_x = inches(0.5)

        options = "PAYMENT OPTIONS:"
        self.canvas.setFontSize(SMALL_FONT_SIZE)
        options_text = Paragraph(options, ParagraphStyle(''))
        options_text.wrapOn(self.canvas, width, inches(.12))
        options_text.drawOn(self.canvas, left_x, inches(3.5))
        self.canvas.setFontSize(DEFAULT_FONT_SIZE)

        flywire = """<strong>International payments:</strong>
Make payments in your local currency
via bank transfer or credit card by following this link:
<link href='{flywire_link}' color='blue'>{flywire_link}</link><br />""".format(
            flywire_link="https://wl.flywire.com/?destination=DMG"
        )
        flywire_text = Paragraph(flywire, ParagraphStyle(''))
        flywire_text.wrapOn(self.canvas, width, inches(.4))
        flywire_text.drawOn(self.canvas, left_x, inches(2.95))

        credit_card = """<strong>Credit card payments (USD)</strong> can be made online here:<br />
<link href='{payment_page}' color='blue'>{payment_page}</link><br />""".format(
            payment_page=absolute_reverse(
                DomainBillingStatementsView.urlname, args=[self.project_name])
        )
        credit_card_text = Paragraph(credit_card, ParagraphStyle(''))
        credit_card_text.wrapOn(self.canvas, width, inches(.5))
        credit_card_text.drawOn(self.canvas, left_x, inches(2.4))

        ach_or_wire = """<strong>ACH or Wire:</strong> If you make payment via ACH
or Wire, please make sure to email
<font color='blue'>{invoicing_contact_email}</font>
so that we can match your payment to the correct invoice.  Please include:
Invoice No., Project Space, and payment date in the email. <br />""".format(
            invoicing_contact_email=settings.INVOICING_CONTACT_EMAIL,
        )
        ach_or_wire_text = Paragraph(ach_or_wire, ParagraphStyle(''))
        ach_or_wire_text.wrapOn(self.canvas, width, inches(.5))
        ach_or_wire_text.drawOn(self.canvas, left_x, inches(1.7))

        ach_payment_text = """<strong>ACH payment</strong>
(preferred over wire payment for transfer in the US):<br />
Bank: {bank_name}
Bank Address: {bank_address}
Account Number: {account_number}
Routing Number or ABA: {routing_number_ach}<br />""".format(
            bank_name=self.bank_name,
            bank_address=self.bank_address,
            account_number=self.account_number,
            routing_number_ach=self.routing_number_ach
        )
        wire_payment_text = """<strong>Wire payment</strong>:<br />
Bank: {bank_name}
Bank Address: {bank_address}
Account Number: {account_number}
Routing Number or ABA: {routing_number_wire}
Swift Code: {swift_code}<br/>""".format(
            bank_name=self.bank_name,
            bank_address=self.bank_address,
            account_number=self.account_number,
            routing_number_wire=self.routing_number_wire,
            swift_code=self.swift_code
        )
        payment_info2 = Paragraph('\n'.join([
            ach_payment_text,
            wire_payment_text,
        ]), ParagraphStyle(''))
        payment_info2.wrapOn(self.canvas, width - inches(0.1), inches(0.9))
        payment_info2.drawOn(self.canvas, inches(0.6), inches(0.5))
Beispiel #35
0
def get_awc_reports_pse(config, month, domain, show_test=False):
    selected_month = datetime(*month)
    last_months = (selected_month - relativedelta(months=1))
    last_day_of_selected_month = (
        selected_month + relativedelta(months=1)) - relativedelta(days=1)

    map_image_data = DailyAttendanceView.objects.filter(
        pse_date__range=(selected_month, last_day_of_selected_month),
        **config).values('awc_name', 'form_location_lat', 'form_location_long',
                         'image_name', 'doc_id',
                         'pse_date').order_by('-pse_date')

    kpi_data_tm = AggAwcMonthly.objects.filter(
        month=selected_month,
        **config).values('awc_name').annotate(days_open=Sum('awc_days_open'))
    kpi_data_lm = AggAwcMonthly.objects.filter(
        month=last_months,
        **config).values('awc_name').annotate(days_open=Sum('awc_days_open'))

    open_count_data = DailyAttendanceView.objects.filter(
        pse_date__range=(selected_month, last_day_of_selected_month),
        **config).values('awc_name', 'pse_date').annotate(
            open_count=Sum('awc_open_count'), ).order_by('pse_date')

    daily_attendance = DailyAttendanceView.objects.filter(
        pse_date__range=(selected_month, last_day_of_selected_month),
        **config).values('awc_name', 'pse_date').annotate(
            avg_percent=Avg('attended_children_percent'),
            attended=Sum('attended_children'),
            eligible=Sum('eligible_children'))

    if not show_test:
        map_image_data = apply_exclude(domain, map_image_data)
        kpi_data_tm = apply_exclude(domain, kpi_data_tm)
        kpi_data_lm = apply_exclude(domain, kpi_data_lm)
        open_count_data = apply_exclude(domain, open_count_data)
        daily_attendance = apply_exclude(domain, daily_attendance)

    attended_children_chart = {}
    dates = [
        dt for dt in rrule(
            DAILY, dtstart=selected_month, until=last_day_of_selected_month)
    ]
    for date in dates:
        attended_children_chart[int(date.strftime("%s")) * 1000] = {
            'avg_percent': 0,
            'attended': 0,
            'eligible': 0
        }

    open_count_chart = {}

    open_count_dates = [
        dt for dt in rrule(WEEKLY,
                           dtstart=selected_month,
                           until=last_day_of_selected_month,
                           byweekday=MO)
    ]
    for date in open_count_dates:
        first_day_of_week = date - timedelta(days=date.isoweekday() - 1)
        milliseconds = int(first_day_of_week.strftime("%s")) * 1000
        open_count_chart[milliseconds] = 0

    for chart_row in open_count_data:
        first_day_of_week = chart_row['pse_date'] - timedelta(
            days=chart_row['pse_date'].isoweekday() - 1)
        pse_week = int(first_day_of_week.strftime("%s")) * 1000

        if pse_week in open_count_chart:
            open_count_chart[pse_week] += (chart_row['open_count'] or 0)
        else:
            open_count_chart[pse_week] = (chart_row['open_count'] or 0)

    for daily_attendance_row in daily_attendance:
        pse_day = int(daily_attendance_row['pse_date'].strftime("%s")) * 1000
        attended_children_chart[pse_day] = {
            'avg_percent': daily_attendance_row['avg_percent'] or 0,
            'attended': daily_attendance_row['attended'] or 0,
            'eligible': daily_attendance_row['eligible'] or 0
        }

    map_data = {}

    date_to_image_data = {}

    for map_row in map_image_data:
        lat = map_row['form_location_lat']
        longitude = map_row['form_location_long']
        awc_name = map_row['awc_name']
        image_name = map_row['image_name']
        doc_id = map_row['doc_id']
        pse_date = map_row['pse_date']
        if lat and longitude:
            key = doc_id.replace('-', '')
            map_data.update({
                key: {
                    'lat': float(lat),
                    'lng': float(longitude),
                    'focus': 'true',
                    'message': awc_name,
                }
            })
        if image_name:
            date_str = pse_date.strftime("%d/%m/%Y")
            date_to_image_data[date_str] = map_row

    images = []
    tmp_image = []

    for idx, date in enumerate(
            rrule(DAILY,
                  dtstart=selected_month,
                  until=last_day_of_selected_month)):
        date_str = date.strftime("%d/%m/%Y")
        image_data = date_to_image_data.get(date_str)

        if image_data:
            image_name = image_data['image_name']
            doc_id = image_data['doc_id']

            tmp_image.append({
                'id':
                idx,
                'image':
                absolute_reverse('icds_image_accessor',
                                 args=(domain, doc_id, image_name)),
                'date':
                date_str
            })
        else:
            tmp_image.append({'id': idx, 'image': None, 'date': date_str})

        if (idx + 1) % 4 == 0:
            images.append(tmp_image)
            tmp_image = []

    if tmp_image:
        images.append(tmp_image)

    return {
        'kpi': [[{
            'label':
            _('AWC Days Open'),
            'help_text':
            _(("""
                        Total number of days the AWC is open in the given month.
                        The AWC is expected to be open 6 days a week (Not on Sundays and public holidays)
                        """)),
            'percent':
            percent_increase(
                'days_open',
                kpi_data_tm,
                kpi_data_lm,
            ),
            'value':
            get_value(kpi_data_tm, 'days_open'),
            'all':
            '',
            'format':
            'number',
            'frequency':
            'month',
            'color':
            'green' if percent_increase(
                'days_open',
                kpi_data_tm,
                kpi_data_lm,
            ) > 0 else 'red',
        }]],
        'charts':
        [[{
            'key':
            'AWC Days Open per week',
            'values':
            sorted([
                dict(x=x_val, y=y_val)
                for x_val, y_val in six.iteritems(open_count_chart)
            ],
                   key=lambda d: d['x']),
            "strokeWidth":
            2,
            "classed":
            "dashed",
            "color":
            MapColors.BLUE
        }],
         [
             {
                 'key':
                 'PSE - Daily Attendance',
                 'values':
                 sorted([
                     dict(x=x_val,
                          y=y_val['avg_percent'],
                          attended=y_val['attended'],
                          eligible=y_val['eligible'])
                     for x_val, y_val in six.iteritems(attended_children_chart)
                 ],
                        key=lambda d: d['x']),
                 "strokeWidth":
                 2,
                 "classed":
                 "dashed",
                 "color":
                 MapColors.BLUE
             },
         ]],
        'map': {
            'markers': map_data,
        },
        'images':
        images
    }
Beispiel #36
0
 def case_detail_url(self):
     try:
         return absolute_reverse('case_details',
                                 args=[self.report.domain, self.case_id])
     except NoReverseMatch:
         return None
Beispiel #37
0
 def _normalize_meta(name, meta):
     return {
         'content_type': meta.content_type,
         'length': meta.content_length,
         'url': absolute_reverse('api_form_attachment', args=(domain, form_id, name))
     }
Beispiel #38
0
    def get_report_content(self, lang, attach_excel=False):
        """
        Get the report's HTML content as rendered by the static view format.

        """
        try:
            if self.report is None:
                return ReportContent(
                    _("The report used to create this scheduled report is no"
                      " longer available on CommCare HQ.  Please delete this"
                      " scheduled report and create a new one using an available"
                      " report."),
                    None,
                )
        except Exception:
            pass

        from django.http import HttpRequest, QueryDict
        mock_request = HttpRequest()
        mock_request.couch_user = self.owner
        mock_request.user = self.owner.get_django_user()
        mock_request.domain = self.domain
        mock_request.couch_user.current_domain = self.domain
        mock_request.couch_user.language = lang
        mock_request.method = 'GET'

        mock_query_string_parts = [self.query_string, 'filterSet=true']
        if self.is_configurable_report:
            mock_query_string_parts.append(urlencode(self.filters, True))
            mock_query_string_parts.append(
                urlencode(self.get_date_range(), True))
        mock_request.GET = QueryDict('&'.join(mock_query_string_parts))

        # Make sure the request gets processed by PRBAC Middleware
        CCHQPRBACMiddleware.apply_prbac(mock_request)

        try:
            dispatch_func = functools.partial(
                self._dispatcher.__class__.as_view(), mock_request,
                **self.view_kwargs)
            email_response = dispatch_func(render_as='email')
            if email_response.status_code == 302:
                return ReportContent(
                    _("We are sorry, but your saved report '%(config_name)s' "
                      "is no longer accessible because the owner %(username)s "
                      "is no longer active.") % {
                          'config_name': self.name,
                          'username': self.owner.username
                      },
                    None,
                )
            return ReportContent(
                json.loads(email_response.content)['report'],
                dispatch_func(render_as='excel') if attach_excel else None,
            )
        except PermissionDenied:
            return ReportContent(
                _("We are sorry, but your saved report '%(config_name)s' "
                  "is no longer accessible because your subscription does "
                  "not allow Custom Reporting. Please talk to your Project "
                  "Administrator about enabling Custom Reports. If you "
                  "want CommCare HQ to stop sending this message, please "
                  "visit %(saved_reports_url)s to remove this "
                  "Emailed Report.") % {
                      'config_name':
                      self.name,
                      'saved_reports_url':
                      absolute_reverse('saved_reports',
                                       args=[mock_request.domain]),
                  },
                None,
            )
        except Http404:
            return ReportContent(
                _("We are sorry, but your saved report '%(config_name)s' "
                  "can not be generated since you do not have the correct permissions. "
                  "Please talk to your Project Administrator about getting permissions for this"
                  "report.") % {
                      'config_name': self.name,
                  },
                None,
            )
        except UnsupportedSavedReportError:
            return ReportContent(
                _("We are sorry, but your saved report '%(config_name)s' "
                  "is no longer available. If you think this is a mistake, please report an issue."
                  ) % {
                      'config_name': self.name,
                  },
                None,
            )
        except Exception:
            notify_exception(None,
                             "Error generating report: {}".format(
                                 self.report_slug),
                             details={
                                 'domain': self.domain,
                                 'user': self.owner.username,
                                 'report': self.report_slug,
                                 'report config': self.get_id
                             })
            return ReportContent(
                _("An error occurred while generating this report."), None)
Beispiel #39
0
 def case_detail_url(self):
     try:
         return absolute_reverse('case_data', args=[self.case['domain'], self.case_id])
     except NoReverseMatch:
         return None
Beispiel #40
0
def get_default_domain_url(domain):
    from corehq.apps.domain.views import DefaultProjectSettingsView
    return absolute_reverse(
        DefaultProjectSettingsView.urlname,
        args=[domain],
    )
Beispiel #41
0
def _send_email(user, report, hash_id, recipient, subject=None):
    link = absolute_reverse(
        "export_report",
        args=[report.domain, str(hash_id), report.export_format])

    send_report_download_email(report.name, recipient, link, subject)
Beispiel #42
0
def get_awc_reports_pse(config, month, domain, show_test=False):
    now = datetime.utcnow()
    last_30_days = (now - relativedelta(days=30))
    selected_month = datetime(*month)
    last_months = (selected_month - relativedelta(months=1))
    last_three_months = (selected_month - relativedelta(months=3))

    last_day_of_next_month = (selected_month +
                              relativedelta(months=1)) - relativedelta(days=1)

    map_image_data = DailyAttendanceView.objects.filter(
        pse_date__range=(last_30_days, now),
        **config).values('awc_name', 'form_location_lat', 'form_location_long',
                         'image_name', 'doc_id',
                         'pse_date').order_by('-pse_date')

    kpi_data_tm = AggAwcMonthly.objects.filter(
        month=selected_month,
        **config).values('awc_name').annotate(days_open=Sum('awc_days_open'))
    kpi_data_lm = AggAwcMonthly.objects.filter(
        month=last_months,
        **config).values('awc_name').annotate(days_open=Sum('awc_days_open'))

    chart_data = DailyAttendanceView.objects.filter(
        pse_date__range=(last_three_months, last_day_of_next_month),
        **config).values(
            'awc_name', 'pse_date', 'attended_children_percent').annotate(
                open_count=Sum('awc_open_count'), ).order_by('pse_date')

    if not show_test:
        map_image_data = apply_exclude(domain, map_image_data)
        kpi_data_tm = apply_exclude(domain, kpi_data_tm)
        kpi_data_lm = apply_exclude(domain, kpi_data_lm)
        chart_data = apply_exclude(domain, chart_data)

    open_count_chart = {}
    attended_children_chart = {}
    for chart_row in chart_data:
        first_day_of_week = chart_row['pse_date'] - timedelta(
            days=chart_row['pse_date'].isoweekday() - 1)
        pse_week = int(first_day_of_week.strftime("%s")) * 1000
        if pse_week in open_count_chart:
            open_count_chart[pse_week] += (chart_row['open_count'] or 0)
            attended_children_chart[pse_week].append(
                (chart_row['attended_children_percent'] or 0))
        else:
            open_count_chart[pse_week] = (chart_row['open_count'] or 0)
            attended_children_chart[pse_week] = [
                chart_row['attended_children_percent'] or 0
            ]

    map_data = {}

    date_to_image_data = {}

    for map_row in map_image_data:
        lat = map_row['form_location_lat']
        long = map_row['form_location_long']
        awc_name = map_row['awc_name']
        image_name = map_row['image_name']
        doc_id = map_row['doc_id']
        pse_date = map_row['pse_date']
        if lat and long:
            key = doc_id.replace('-', '')
            map_data.update({
                key: {
                    'lat': float(lat),
                    'lng': float(long),
                    'focus': 'true',
                    'message': awc_name,
                }
            })
        if image_name:
            date_str = pse_date.strftime("%d/%m/%Y")
            date_to_image_data[date_str] = map_row

    images = []
    tmp_image = []

    for idx, date in enumerate(rrule(DAILY, dtstart=last_30_days, until=now)):
        date_str = date.strftime("%d/%m/%Y")
        image_data = date_to_image_data.get(date_str)

        if image_data:
            image_name = image_data['image_name']
            doc_id = image_data['doc_id']

            tmp_image.append({
                'id':
                idx,
                'image':
                absolute_reverse('api_form_attachment',
                                 args=(domain, doc_id, image_name)),
                'date':
                date_str
            })
        else:
            tmp_image.append({'id': idx, 'image': None, 'date': date_str})

        if (idx + 1) % 4 == 0:
            images.append(tmp_image)
            tmp_image = []

    if tmp_image:
        images.append(tmp_image)

    return {
        'kpi': [[{
            'label':
            _('AWC Days Open'),
            'help_text':
            _(("""
                        Total number of days the AWC is open in the given month.
                        The AWC is expected to be open 6 days a week (Not on Sundays and public holidays)
                        """)),
            'percent':
            percent_increase(
                'days_open',
                kpi_data_tm,
                kpi_data_lm,
            ),
            'value':
            get_value(kpi_data_tm, 'days_open'),
            'all':
            '',
            'format':
            'number',
            'frequency':
            'month',
            'color':
            'green' if percent_increase(
                'days_open',
                kpi_data_tm,
                kpi_data_lm,
            ) > 0 else 'red',
        }]],
        'charts':
        [[{
            'key':
            'AWC Days Open per week',
            'values':
            sorted([
                dict(x=x_val, y=y_val)
                for x_val, y_val in open_count_chart.iteritems()
            ],
                   key=lambda d: d['x']),
            "strokeWidth":
            2,
            "classed":
            "dashed",
            "color":
            BLUE
        }],
         [
             {
                 'key':
                 'PSE- Average Weekly Attendance',
                 'values':
                 sorted([
                     dict(x=x_val, y=(sum(y_val) / len(y_val)))
                     for x_val, y_val in attended_children_chart.iteritems()
                 ],
                        key=lambda d: d['x']),
                 "strokeWidth":
                 2,
                 "classed":
                 "dashed",
                 "color":
                 BLUE
             },
         ]],
        'map': {
            'markers': map_data,
        },
        'images':
        images
    }
Beispiel #43
0
    def get_report_content(self, lang, attach_excel=False):
        """
        Get the report's HTML content as rendered by the static view format.

        """
        from corehq.apps.locations.middleware import LocationAccessMiddleware

        try:
            if self.report is None:
                return ReportContent(
                    _("The report used to create this scheduled report is no"
                      " longer available on CommCare HQ.  Please delete this"
                      " scheduled report and create a new one using an available"
                      " report."),
                    None,
                )
        except Exception:
            pass

        if getattr(self.report, 'is_deprecated', False):
            return ReportContent(
                self.report.deprecation_email_message or
                _("[DEPRECATED] %s report has been deprecated and will stop working soon. "
                  "Please update your saved reports email settings if needed." % self.report.name
                  ),
                None,
            )

        mock_request = HttpRequest()
        mock_request.couch_user = self.owner
        mock_request.user = self.owner.get_django_user()
        mock_request.domain = self.domain
        mock_request.couch_user.current_domain = self.domain
        mock_request.couch_user.language = lang
        mock_request.method = 'GET'
        mock_request.bypass_two_factor = True

        mock_query_string_parts = [self.query_string, 'filterSet=true']
        if self.is_configurable_report:
            mock_query_string_parts.append(urlencode(self.filters, True))
            mock_query_string_parts.append(urlencode(self.get_date_range(), True))
        mock_request.GET = QueryDict('&'.join(mock_query_string_parts))

        # Make sure the request gets processed by PRBAC Middleware
        CCHQPRBACMiddleware.apply_prbac(mock_request)
        LocationAccessMiddleware.apply_location_access(mock_request)

        try:
            dispatch_func = functools.partial(self._dispatcher.__class__.as_view(),
                                              mock_request, **self.view_kwargs)
            email_response = dispatch_func(render_as='email')
            if email_response.status_code == 302:
                return ReportContent(
                    _(
                        "We are sorry, but your saved report '%(config_name)s' "
                        "is no longer accessible because the owner %(username)s "
                        "is no longer active."
                    ) % {
                        'config_name': self.name,
                        'username': self.owner.username
                    },
                    None,
                )
            try:
                content_json = json.loads(email_response.content)
            except ValueError:
                email_text = email_response.content
            else:
                email_text = content_json['report']
            excel_attachment = dispatch_func(render_as='excel') if attach_excel else None
            return ReportContent(email_text, excel_attachment)
        except PermissionDenied:
            return ReportContent(
                _(
                    "We are sorry, but your saved report '%(config_name)s' "
                    "is no longer accessible because your subscription does "
                    "not allow Custom Reporting. Please talk to your Project "
                    "Administrator about enabling Custom Reports. If you "
                    "want CommCare HQ to stop sending this message, please "
                    "visit %(saved_reports_url)s to remove this "
                    "Emailed Report."
                ) % {
                    'config_name': self.name,
                    'saved_reports_url': absolute_reverse(
                        'saved_reports', args=[mock_request.domain]
                    ),
                },
                None,
            )
        except Http404:
            return ReportContent(
                _(
                    "We are sorry, but your saved report '%(config_name)s' "
                    "can not be generated since you do not have the correct permissions. "
                    "Please talk to your Project Administrator about getting permissions for this"
                    "report."
                ) % {
                    'config_name': self.name,
                },
                None,
            )
        except UnsupportedSavedReportError:
            return ReportContent(
                _(
                    "We are sorry, but your saved report '%(config_name)s' "
                    "is no longer available. If you think this is a mistake, please report an issue."
                ) % {
                    'config_name': self.name,
                },
                None,
            )