Report

List of available reports:

from report.models import ReportSpecification
[(x.app, x.module, x.report_class) for x in ReportSpecification.objects.all()]

To get a list of outstanding reports:

from report.models import ReportSchedule
ReportSchedule.objects.outstanding()

New Report

To write a new report:

Create a report based on the ReportMixin class e.g. https://gitlab.com/kb/report/blob/master/example_report/service.py

Note

The report must be created in the app folder in service.py e.g. example_report/service.py.

Initialise the report:

from report.models import ReportSpecification

ReportSpecification.objects.init_reportspecification(
    slug="squares",
    title="Squares and Cubes",
    app="example_report",
    report_class="SampleReport",
)

Tip

When naming a report (using the slug), it might be a good idea to start with the name of the app e.g. invoice-time-analysis-contact.

To schedule a report:

report_specification = ReportSpecification.objects.get(slug="squares")
with transaction.atomic():
    report_specification.schedule(
        self.request.user,
        parameters={"contact_pk": contact.pk}
    )

Or see the ReportScheduleCreateView: https://gitlab.com/kb/report/blob/master/report/views.py#L165

Parameters

To handle report parameters, you could create a _check_parameters method in your report class e.g. https://gitlab.com/kb/invoice/blob/master/invoice/service.py#L432

e.g:

class TimeAnalysisByContact(ReportMixin):
    def _check_parameters(self, parameters):
        if not parameters:
            raise ReportError("Cannot run report without any parameters")
        contact_pk = parameters.get("contact_pk")
        return contact_pk

    def run_csv_report(self, csv_writer, parameters=None):
        contact_pk = self._check_parameters(parameters)

Testing

Content

To check the CSV content:

Initialise the app / project so the ReportSpecification is created e.g:

from django.core.management import call_command
call_command("init_app_invoice")

Get the report, prepare the parameters and schedule the report:

from report.models import ReportSchedule, ReportSpecification
report_specification = ReportSpecification.objects.get(
    slug="invoice-time-analysis-contact"
)
parameters = {"contact_pk": contact.pk}
report_specification.schedule(user, parameters=parameters)

Run the report and find the schedule:

schedule_pks = ReportSchedule.objects.run_reports()
assert 1 == len(schedule_pks)
schedule_pk = schedule_pks[0]
schedule = ReportSchedule.objects.get(pk=schedule_pk)

Check the report output:

import csv
reader = csv.reader(open(schedule.output_file.path), "excel")
first_row = None
result = []
for row in reader:
    if not first_row:
        first_row = row
    else:
        result.append(row)
assert ["Ticket", "Contact", "Charge", "Fixed", "Non-Charge"] == first_row
assert [
    ["Apple", "pat", "30.0", "0", "0"],
] == result

Scheduled

To check a report has been scheduled:

# make sure the report is scheduled
qs = ReportSchedule.objects.current()
assert 1 == qs.count()
# optional checks
schedule = qs.first()
assert report_specification.slug == schedule.report.slug
assert timezone.now().date() == schedule.created.date()