Skip to content

Commit

Permalink
Improve reportbro implementation
Browse files Browse the repository at this point in the history
  • Loading branch information
qgerome committed Mar 10, 2022
1 parent c0b37a6 commit a283c2a
Show file tree
Hide file tree
Showing 7 changed files with 126 additions and 183 deletions.
4 changes: 2 additions & 2 deletions report/apps.py
Expand Up @@ -56,9 +56,9 @@ def _configure_permissions(self, cfg):
ReportConfig.gql_mutation_report_delete_perms = cfg["gql_mutation_report_delete_perms"]

@classmethod
def get_report(cls, module_name, report_name):
def get_report(cls, report_name):
for report in cls.reports:
if report["module"] == module_name and report["name"] == report_name:
if report["name"] == report_name:
return report
return None

Expand Down
26 changes: 26 additions & 0 deletions report/migrations/0002_auto_20220308_1414.py
@@ -0,0 +1,26 @@
# Generated by Django 3.0.14 on 2022-03-08 14:14

import datetime
from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
("report", "0001_initial"),
]

operations = [
migrations.AlterField(
model_name="reportdefinition",
name="name",
field=models.CharField(max_length=255),
),
migrations.AlterField(
model_name="reportdefinition",
name="validity_from",
field=models.DateTimeField(
blank=True, default=datetime.datetime.now, null=True
),
),
]
54 changes: 37 additions & 17 deletions report/models.py
@@ -1,29 +1,24 @@
from django.db import models
from core import models as core_models
from datetime import datetime as py_datetime


class ReportDefinition(core_models.UUIDModel):
"""
Record report (business modules) templates to be generated by the templating engine (reportbro for PDF,...)
Initial implementation only integrate ReportBro templating engine
"""

REPORT_BRO = 0
REPORT_ENGINE_CHOICES = (
(REPORT_BRO, "Report Bro - PDF"),
)
REPORT_ENGINE_CHOICES = ((REPORT_BRO, "Report Bro - PDF"),)

name = models.CharField(
max_length=255, blank=False, null=False, unique=True)
# module = models.CharField(
# max_length=255, blank=True, null=True
# )
name = models.CharField(max_length=255, blank=False, null=False)
# alternate_of = models.CharField(
# max_length=255, blank=True, null=True
# )
engine = models.IntegerField(
choices=REPORT_ENGINE_CHOICES, default=REPORT_BRO)
engine = models.IntegerField(choices=REPORT_ENGINE_CHOICES, default=REPORT_BRO)
definition = models.TextField()
validity_from = models.DateTimeField(blank=True, null=True)
validity_from = models.DateTimeField(blank=True, null=True, default=py_datetime.now)
validity_to = models.DateTimeField(blank=True, null=True)

class Meta:
Expand All @@ -34,16 +29,41 @@ class Meta:
class GeneratedReports(models.Model):
id = models.AutoField(db_column="ReportingId", primary_key=True)
reporting_date = models.TextField(db_column="ReportingDate")
location = models.ForeignKey("location.Location", models.DO_NOTHING, db_column="LocationId", related_name="+")
product = models.ForeignKey("product.Product", models.DO_NOTHING, db_column="ProdId", related_name="+")
payer = models.ForeignKey("payer.Payer", models.DO_NOTHING, db_column="PayerId", blank=True, null=True, related_name="generated_reports")
location = models.ForeignKey(
"location.Location", models.DO_NOTHING, db_column="LocationId", related_name="+"
)
product = models.ForeignKey(
"product.Product", models.DO_NOTHING, db_column="ProdId", related_name="+"
)
payer = models.ForeignKey(
"payer.Payer",
models.DO_NOTHING,
db_column="PayerId",
blank=True,
null=True,
related_name="generated_reports",
)
start_date = models.DateField(db_column="StartDate")
end_date = models.DateField(db_column="EndDate")
record_found = models.IntegerField(db_column="RecordFound")
officer = models.ForeignKey("core.Officer", on_delete=models.DO_NOTHING, db_column="OfficerID", null=True, blank=True)
officer = models.ForeignKey(
"core.Officer",
on_delete=models.DO_NOTHING,
db_column="OfficerID",
null=True,
blank=True,
)
report_type = models.IntegerField(db_column="ReportType", null=True, blank=True)
commission_rate = models.DecimalField(db_column="CommissionRate", max_digits=18, decimal_places=2, null=True, blank=True)
report_mode = models.IntegerField(db_column="ReportMode", default=0, null=True, blank=True)
commission_rate = models.DecimalField(
db_column="CommissionRate",
max_digits=18,
decimal_places=2,
null=True,
blank=True,
)
report_mode = models.IntegerField(
db_column="ReportMode", default=0, null=True, blank=True
)
scope = models.IntegerField(db_column="Scope", null=True, blank=True)

# Used by Overview of Commissions
Expand Down
173 changes: 33 additions & 140 deletions report/schema.py
@@ -1,41 +1,18 @@
import graphene
import logging

from core.schema import OpenIMISMutation
from report.apps import ReportConfig
from report.models import ReportDefinition
from core import ExtendedConnection
import graphene
from graphene.relay import Node
from django.utils.translation import gettext_lazy
from graphene_django import DjangoObjectType
from graphene_django.filter import DjangoFilterConnectionField
from django.core.exceptions import ValidationError, PermissionDenied
from core.schema import OpenIMISMutation
from django.contrib.auth.models import AnonymousUser
import graphene_django_optimizer as gql_optimizer
from django.core.exceptions import ValidationError
from django.utils.translation import gettext as _

from core.utils import TimeUtils
from report.apps import ReportConfig
from report.models import ReportDefinition
from report.services import get_report_definition

import logging

logger = logging.getLogger(__file__)


class ReportDefinitionGQLType(DjangoObjectType):
@classmethod
def get_queryset(cls, queryset, info):
return queryset.filter(validity_to=None)

class Meta:
model = ReportDefinition
interfaces = (Node,)
filter_fields = {
"id": ["exact"],
"name": ["exact", "icontains"],
}
connection_class = ExtendedConnection


class ReportGQLType(graphene.ObjectType):
name = graphene.String()
default_report = graphene.String()
Expand All @@ -49,153 +26,69 @@ def resolve_definition(self, info, **kwargs):


class Query(graphene.ObjectType):
report_definitions = DjangoFilterConnectionField(
ReportDefinitionGQLType,
show_history=graphene.Boolean(),
search=graphene.String(description=gettext_lazy("Search in `name` & `code`")),
)
report_definition = graphene.Field(
ReportDefinitionGQLType, id=graphene.ID(), uuid=graphene.String()
)
reports = graphene.List(ReportGQLType)
report = graphene.Field(ReportGQLType, name=graphene.String(required=True))
report = graphene.Field(
ReportGQLType,
name=graphene.String(required=True),
)

def resolve_reports(self, info, **kwargs):
return [report for report in ReportConfig.reports]

def resolve_report(self, info, name, **kwargs):
for report in ReportConfig.reports:
if report.get("name") == name:
return report

def resolve_report_definition(self, info, **kwargs):
# if not info.context.user.has_perms(ReportConfig.gql_query_report_definitions_perms):
# raise PermissionDenied(_("unauthorized"))
if kwargs.get("id", None) is not None:
return Node.get_node_from_global_id(info, kwargs["id"])
elif kwargs.get("uuid", None) is not None:
return ReportDefinition.objects.get(id=kwargs["uuid"])

return None

def resolve_report_definitions(
self, info, search=None, show_history=False, **kwargs
):
# if not info.context.user.has_perms(ReportConfig.gql_query_report_definitions_perms):
# raise PermissionDenied(_("unauthorized"))

qs = ReportDefinition.objects
# if not show_history:
# qs = qs.filter(*filter_validity(**kwargs))

# if search is not None:
# qs = qs.filter(Q(name__icontains=search) | Q(code__icontains=search))

# if location is not None:
# from location.models import Location
#
# qs = qs.filter(
# Q(location__in=Location.objects.parents(location))
# | Q(location__id=location)
# )

return gql_optimizer.query(qs, info)
return ReportConfig.get_report(name)


def update_or_create_report_definition(data, user):
data.pop("client_mutation_id", None)
data.pop("client_mutation_label", None)
report_definition_uuid = data.pop("uuid", None)
if report_definition_uuid:
report_definition = ReportDefinition.objects.get(uuid=report_definition_uuid)
# reset_report_definition_before_update(report_definition)
[setattr(report_definition, k, v) for k, v in data.items()]
name = data.pop("name", None)

report_definition = ReportDefinition.objects.filter(
name=name, validity_to__isnull=True
).first()
if report_definition:
report_definition.validity_to = TimeUtils.now()
else:
report_definition = ReportDefinition.objects.create(**data)
template = ReportConfig.get_report(name)
report_definition = ReportDefinition.objects.create(
name=template.get("name"), engine=template.get("engine")
)

[setattr(report_definition, k, v) for k, v in data.items()]
report_definition.save()
return report_definition


class ReportDefinitionInputType(OpenIMISMutation.Input):
id = graphene.Int(required=False, read_only=True)
name = graphene.String(required=True, max_length=255)
engine = graphene.Int(required=False) # Always 0 for ReportBro for now
definition = graphene.String(required=True)
validity_from = graphene.DateTime(required=False)


class CreateReportDefinitionMutation(OpenIMISMutation):
"""
Create a new Report Definition Override (the default is provided by the report itself)
"""

_mutation_module = "report"
_mutation_class = "CreateReportDefinitionMutation"

class Input(ReportDefinitionInputType):
pass

@classmethod
def async_mutate(cls, user, **data):
try:
if type(user) is AnonymousUser or not user.id:
raise ValidationError(_("mutation.authentication_required"))
# if not user.has_perms(ReportConfig.gql_mutation_create_families_perms):
# raise PermissionDenied(_("unauthorized"))
# data['audit_user_id'] = user.id_for_audit

from core.utils import TimeUtils

if "validity_from" not in data:
data["validity_from"] = TimeUtils.now()
update_or_create_report_definition(data, user)
return None
except Exception as exc:
logger.exception("report.mutation.failed_to_create_report_definition")
return [
{
"message": _("report.mutation.failed_to_create_report_definition"),
"detail": str(exc),
}
]


class UpdateReportDefinitionMutation(OpenIMISMutation):
class OverrideReportMutation(OpenIMISMutation):
"""
Update an existing Report Definition Override (the default is provided by the report itself)
Override an existing Report (the default is provided by the report itself)
"""

_mutation_module = "report"
_mutation_class = "UpdateReportDefinitionMutation"
_mutation_class = "OverrideReportMutation"

class Input(ReportDefinitionInputType):
uuid = graphene.String(required=True)
class Input(OpenIMISMutation.Input):
name = graphene.String(required=True)
definition = graphene.String(required=True)

@classmethod
def async_mutate(cls, user, **data):
try:
if type(user) is AnonymousUser or not user.id:
raise ValidationError(_("mutation.authentication_required"))
# if not user.has_perms(ReportConfig.gql_mutation_create_families_perms):
# raise PermissionDenied(_("unauthorized"))
# data['audit_user_id'] = user.id_for_audit

from core.utils import TimeUtils

if "validity_from" not in data:
data["validity_from"] = TimeUtils.now()
update_or_create_report_definition(data, user)
return None
except Exception as exc:
logger.exception("report.mutation.failed_to_update_report_definition")
logger.exception("report.mutation.failed_to_override_report")
return [
{
"message": _("report.mutation.failed_to_update_report_definition"),
"message": _("report.mutation.failed_to_override_report"),
"detail": str(exc),
}
]


class Mutation(graphene.ObjectType):
create_report_definition = CreateReportDefinitionMutation.Field()
update_report_definition = UpdateReportDefinitionMutation.Field()
override_report = OverrideReportMutation.Field()
20 changes: 11 additions & 9 deletions report/templates/report/reportbro.html
Expand Up @@ -12,23 +12,25 @@
<script type="text/javascript">

window.addEventListener('message', function (event) {
if (!event.data || !event.data.type) {
if (!event.data) {
return;
}
console.log("Message", event)
if (event.data.type === "LOAD") {
console.log($("#reportbro").reportBro())
$("#reportbro").reportBro('load', event.data.payload);
try {
const data = JSON.parse(event.data);
if (data.type === "LOAD") {
$("#reportbro").reportBro('load', data.payload);
$('#reportbro').reportBro('setModified', true); // Always enable the 'save' button
}
} catch (err) {
throw err;
}
})
function post(data) {
console.log('postMessage()', data)
if (window.parent === window) {
if (parent === window) {
console.warn('Report Designer is not embedded. We will not send messages.');
console.log(data)
return;
}
return window.parent.postMessage(data, '*');
return parent.postMessage(JSON.stringify(data), '*');
};

function onReportSave() {
Expand Down

0 comments on commit a283c2a

Please sign in to comment.