Beispiel #1
0
def run_dynamic_report(request):
    """Run a dynamic report.

    report_data_id: Report Presentation ID
    name: name of report
    filter_spec: JSON string with user filter to use

    response: {'id': new dynamic report id}
    """
    validator = ApiValidator()
    company = get_company_or_404(request)
    report_data_id = request.POST['report_data_id']
    name = request.POST.get('name', '')
    if not name:
        validator.note_field_error("name", "Report name must not be empty.")
    filter_spec = request.POST.get('filter', '{}')
    report_data = ReportTypeDataTypes.objects.get(id=report_data_id)

    if validator.has_errors():
        return validator.build_error_response()

    report = DynamicReport.objects.create(
        report_data=report_data,
        filters=filter_spec,
        name=name,
        owner=company)

    report.regenerate()

    data = {'id': report.id}
    return HttpResponse(content_type='application/json',
                        content=json.dumps(data))
Beispiel #2
0
def get_report_info(request):
    """Get information about an analytics report.

    analytics_report_id: string id obtained from get_available_analytics
        under 'value'

    {
        'dimensions': [
            {
                'value': 'country',
                'display': 'Country',
                'interface_type': 'map:world',
            },
            {
                'value': 'title',
                'display': 'Job Title',
                'interface_type': 'string',
            },
            ...
        ]
    }
    """
    validator = ApiValidator()

    analytics_report_id = request.GET.get('analytics_report_id', '')
    if not analytics_report_id:
        validator.note_field_error(
            "analytics_report_id", "Value required.")

    if validator.has_errors():
        return validator.build_error_response()

    report_data = get_analytics_reporttype_datatype(analytics_report_id)

    if not report_data:
        validator.note_field_error(
            "analytics_report_id", "No analytics report found.")

    if validator.has_errors():
        return validator.build_error_response()

    config = report_data.configuration

    result = {
        'dimensions': [
            {
                'value': r.column_name,
                'display': r.filter_interface_display,
                'interface_type': r.filter_interface_type,
            }
            for r in config.configurationcolumn_set.all().order_by('order')
        ],
    }

    return HttpResponse(json.dumps(result), content_type="application/json")
Beispiel #3
0
def get_default_report_name(request):
    validator = ApiValidator()
    # We don't actually need this but it seems like it will be important
    # if we ever start picking meaningful names.
    report_data_id = request.POST.get('report_data_id')
    if not report_data_id:
        validator.note_field_error(
            "report_data_id",
            "Report data id must not be empty.")

    if validator.has_errors():
        return validator.build_error_response()

    data = {'name': str(datetime.now())}
    return HttpResponse(content_type='application/json',
                        content=json.dumps(data))
Beispiel #4
0
def get_dynamic_report_info(request):
    company = get_company_or_404(request)
    validator = ApiValidator()
    report_id = request.GET.get('report_id')
    if report_id is None:
        validator.note_field_error('report_id', 'Missing report id.')

    if validator.has_errors():
        return validator.build_error_response()

    report_list = list(DynamicReport.objects.filter(id=report_id))
    if len(report_list) < 1:
        validator.note_field_error('report_id', 'Unknown report id.')

    if validator.has_errors():
        return validator.build_error_response()

    report = report_list[0]

    # Guessing here. Many to many makes this ambiguous.
    reporting_type = (
        report.report_data.report_type.reportingtype_set.all()[0]
        .reporting_type)
    report_type = (
        report.report_data.report_type.report_type)
    data_type = (
        report.report_data.data_type.data_type)

    driver = ds_json_drivers[report.report_data.report_type.datasource]
    adorned_filter = driver.adorn_filter(company, report.filters)

    response = {
        'report_details': {
            'id': report.pk,
            'report_data_id': report.report_data.pk,
            'reporting_type': reporting_type,
            'report_type': report_type,
            'data_type': data_type,
            'name': report.name,
            'filter': adorned_filter,
        }
    }
    return HttpResponse(content_type='application/json',
                        content=driver.serialize_filterlike(response))
Beispiel #5
0
def run_dynamic_report(request):
    """Run a dynamic report.

    report_data_id: Report Presentation ID
    name: name of report
    filter_spec: JSON string with user filter to use

    response: {'id': new dynamic report id}
    """
    validator = ApiValidator()
    company = get_company_or_404(request)
    report_data_id = request.POST['report_data_id']
    name = request.POST.get('name', '')
    if not name:
        validator.note_field_error("name", "Report name must not be empty.")
    filter_spec = request.POST.get('filter', '{}')
    report_data = ReportTypeDataTypes.objects.get(id=report_data_id)

    if validator.has_errors():
        return validator.build_error_response()

    report = DynamicReport.objects.create(report_data=report_data,
                                          filters=filter_spec,
                                          name=name,
                                          owner=company)

    report.regenerate()

    data = {'id': report.id}
    return HttpResponse(content_type='application/json',
                        content=json.dumps(data))
 def test_note_field_error(self):
     '''We can build error documents with field specific errors.'''
     validator = ApiValidator()
     validator.note_field_error("name", "aaa")
     self.assertEqual(True, validator.has_errors())
     self.assertEqual([{
         "field": "name",
         "message": "aaa",
     }], validator.build_document())
Beispiel #7
0
def get_default_report_name(request):
    validator = ApiValidator()
    # We don't actually need this but it seems like it will be important
    # if we ever start picking meaningful names.
    report_data_id = request.POST.get('report_data_id')
    if not report_data_id:
        validator.note_field_error("report_data_id",
                                   "Report data id must not be empty.")

    if validator.has_errors():
        return validator.build_error_response()

    data = {'name': str(datetime.now())}
    return HttpResponse(content_type='application/json',
                        content=json.dumps(data))
Beispiel #8
0
def export_options_api(request):
    """Get options and defaults, etc. needed to drive a UI for downloads.

    Parameters:
        :report_id: Id of the report to download

    Outputs an object shaped like this:
        {
            'count': number of records in the report,
            'report_options': {
                'id': the report id,
                'formats': [
                    {
                        'value': format key,
                        'display': user visible title for format,
                    },
                ],
                'values': [
                    {
                        'value': key describing an available column,
                        'display': user visible title of column,
                    },
                ],
                'name': string containing the report name.
            },
        }
    """
    company = get_company_or_404(request)
    validator = ApiValidator()

    report_id = request.GET.get('report_id')
    if report_id is None:
        validator.note_field_error('report_id', 'Missing report id.')

    if validator.has_errors():
        return validator.build_error_response()

    report_list = list(
        DynamicReport.objects.filter(id=report_id, owner=company))
    if len(report_list) < 1:
        validator.note_field_error('report_id', 'Unknown report id.')

    if validator.has_errors():
        return validator.build_error_response()

    report = report_list[0]
    count = len(report.python)
    rps = (ReportPresentation.objects.active_for_report_type_data_type(
        report.report_data))

    cols = (ConfigurationColumn.objects.active_for_report_data(
        report.report_data).filter(
            Q(filter_only__isnull=True)
            | Q(filter_only=False)).order_by('order'))
    values = [{
        'value': c.column_name,
        'display': c.alias or c.column_name
    } for c in cols]

    data = {
        'count': count,
        'report_options': {
            'id': report.id,
            'formats': [{
                'value': rp.id,
                'display': rp.display_name
            } for rp in rps],
            'values': values,
            'name': report.name,
        },
    }
    return HttpResponse(content_type='application/json',
                        content=json.dumps(data))
Beispiel #9
0
def export_options_api(request):
    """Get options and defaults, etc. needed to drive a UI for downloads.

    Parameters:
        :report_id: Id of the report to download

    Outputs an object shaped like this:
        {
            'count': number of records in the report,
            'report_options': {
                'id': the report id,
                'formats': [
                    {
                        'value': format key,
                        'display': user visible title for format,
                    },
                ],
                'values': [
                    {
                        'value': key describing an available column,
                        'display': user visible title of column,
                    },
                ],
                'name': string containing the report name.
            },
        }
    """
    company = get_company_or_404(request)
    validator = ApiValidator()

    report_id = request.GET.get('report_id')
    if report_id is None:
        validator.note_field_error('report_id', 'Missing report id.')

    if validator.has_errors():
        return validator.build_error_response()

    report_list = list(DynamicReport.objects.filter(
        id=report_id, owner=company))
    if len(report_list) < 1:
        validator.note_field_error('report_id', 'Unknown report id.')

    if validator.has_errors():
        return validator.build_error_response()

    report = report_list[0]
    count = len(report.python)
    rps = (ReportPresentation.objects
           .active_for_report_type_data_type(report.report_data))

    cols = (
        ConfigurationColumn.objects
        .active_for_report_data(report.report_data)
        .filter(Q(filter_only__isnull=True) | Q(filter_only=False))
        .order_by('order'))
    values = [
        {'value': c.column_name, 'display': c.alias or c.column_name}
        for c in cols
    ]

    data = {
        'count': count,
        'report_options': {
            'id': report.id,
            'formats': [
                {'value': rp.id, 'display': rp.display_name}
                for rp in rps
            ],
            'values': values,
            'name': report.name,
        },
    }
    return HttpResponse(content_type='application/json',
                        content=json.dumps(data))
Beispiel #10
0
def dynamic_chart(request):
    """
    return charting data given a set of filters, date range, and drilldown
    selection

    request
    {
        "date_start": "01/01/2016 00:00:00",
        "date_end": "01/08/2016 00:00:00",
        "active_filters": [{"type": "country", "value": "USA"},
                         {"type": "state", "value": "Indiana"}],
        "report": "found_on",
        "group_overwrite": "browser",
    }

    response
    {
        "column_names":
            [
                {"key": "browser", "label": "Browser"},
                {"key": "job_views", "label": "Job Views"},
             ],
        "rows":
            [
                {"browser": "Chrome", "job_views": "101",  "visits": "1050"},
                {"browser": "IE11", "job_views": "231", "visits": "841"},
                {"browser": "IE8", "job_views": "23", "visits": "341"},
                {"browser": "Firefox", "job_views": "21", "visits": "298"},
                {"browser": "Netscape Navigator", "job_views": "1", "visits": "1"},
                {"browser": "Dolphin", "job_views": "1", "visits": "1"}
             ]
    }


    """
    if request.method != 'POST':
        return HttpResponseNotAllowed(['POST'])

    validator = ApiValidator()

    query_data = json.loads(request.POST.get('request', '{}'))
    if not query_data:
        validator.note_error("No data provided.")

    if validator.has_errors():
        return validator.build_error_response()

    required_fields = ['date_end', 'date_start', 'report']
    for field in required_fields:
        if not query_data.get(field):
            validator.note_field_error(field, '%s is required' % field)

    if validator.has_errors():
        return validator.build_error_response()

    try:
        date_start = dateparser.parse(query_data['date_start'])
    except ValueError:
        validator.note_field_error('date_start',
                                   'Invalid date start: ' +
                                    query_data['date_end'])

    try:
        date_end = dateparser.parse(query_data['date_end'])
    except ValueError:
        validator.note_field_error('date_end',
                                   'Invalid date end: ' +
                                   query_data['date_end'])

    report_data = get_analytics_reporttype_datatype(query_data['report'])

    if not report_data:
        validator.note_field_error(
            "analytics_report_id", "No analytics report found.")

    if validator.has_errors():
        return validator.build_error_response()

    sample_size = 50000 # TODO: Add sample size to request object

    job_views = get_mongo_db().job_views

    buids = get_company_buids(request)

    top_query = build_top_query(date_start, date_end, buids)

    sample_query, total_count = retrieve_sampling_query_and_count(job_views,
                                                                  top_query,
                                                                  sample_size)

    if not sample_query:
        sample_size = total_count

    active_filter_query = build_active_filter_query(query_data)

    group_by, remaining_dimensions = determine_data_group_by_and_remaining(
        query_data, report_data
    )

    group_query = build_group_by_query(group_by.column_name)

    query = [
        {'$match': top_query},
    ] + sample_query + active_filter_query + group_query

    records = job_views.aggregate(query, allowDiskUse=True)

    if sample_query:
        def curried_query(count):
            return calculate_error_and_count(total_count, sample_size, count)

        records = adjust_records_for_sampling(records, curried_query)

    response = {
        "column_names":
            [
                {"key": group_by.column_name,
                 "label": group_by.filter_interface_display},
                {"key": "job_views", "label": "Job Views"},
                {"key": "visitors", "label": "Visitors"},
             ],
        "rows":
            [format_return_dict(r, group_by.column_name) for r in records],
        "chart_type": group_by.filter_interface_type,
        "group_by": group_by.column_name,
        "remaining_dimensions": [{"key": d.column_name,
                                  "label": d.filter_interface_display}
                                 for d in remaining_dimensions]
    }

    return HttpResponse(json.dumps(response))
    def test_note_error(self):
        '''We know when we have errors and can build error documents.'''
        validator = ApiValidator()
        self.assertEqual(False, validator.has_errors())

        validator.note_error("aaa")
        self.assertEqual(True, validator.has_errors())
        self.assertEqual([{
            "message": "aaa",
        }], validator.build_document())

        validator.note_error("bbb")
        self.assertEqual(True, validator.has_errors())
        self.assertEqual([{
            "message": "aaa",
        }, {
            "message": "bbb",
        }], validator.build_document())