From b69b9a607e823f704f0e9951b9e28401a27341bc Mon Sep 17 00:00:00 2001 From: mpeltriaux <michel.peltriaux@sgdnord.rlp.de> Date: Fri, 22 Oct 2021 12:36:39 +0200 Subject: [PATCH] #26 Annual conservation report * enhancements for report2excel functionality * improvements for report2html layout + --- .../templates/analysis/reports/detail.html | 2 +- .../reports/includes/eco_account/amount.html | 14 +-- .../reports/includes/old_data/amount.html | 40 ++++++ .../card_old_interventions.html | 2 +- .../includes/old_intervention/amount.html | 30 ----- analysis/utils/excel/excel.py | 46 +++---- analysis/utils/excel/excel_report.xlsx | Bin 6433 -> 10693 bytes analysis/utils/report.py | 114 +++++++++++++----- locale/de/LC_MESSAGES/django.po | 16 +-- 9 files changed, 158 insertions(+), 106 deletions(-) create mode 100644 analysis/templates/analysis/reports/includes/old_data/amount.html rename analysis/templates/analysis/reports/includes/{old_intervention => old_data}/card_old_interventions.html (97%) delete mode 100644 analysis/templates/analysis/reports/includes/old_intervention/amount.html diff --git a/analysis/templates/analysis/reports/detail.html b/analysis/templates/analysis/reports/detail.html index 9cdae7d2..ac4f08e2 100644 --- a/analysis/templates/analysis/reports/detail.html +++ b/analysis/templates/analysis/reports/detail.html @@ -31,6 +31,6 @@ {% include 'analysis/reports/includes/intervention/card_intervention.html' %} {% include 'analysis/reports/includes/compensation/card_compensation.html' %} {% include 'analysis/reports/includes/eco_account/card_eco_account.html' %} - {% include 'analysis/reports/includes/old_intervention/card_old_interventions.html' %} + {% include 'analysis/reports/includes/old_data/card_old_interventions.html' %} </div> {% endblock %} \ No newline at end of file diff --git a/analysis/templates/analysis/reports/includes/eco_account/amount.html b/analysis/templates/analysis/reports/includes/eco_account/amount.html index becdfff9..668250e6 100644 --- a/analysis/templates/analysis/reports/includes/eco_account/amount.html +++ b/analysis/templates/analysis/reports/includes/eco_account/amount.html @@ -2,10 +2,6 @@ <h3>{% trans 'Amount' %}</h3> <strong> - {% blocktrans %} - Checked = Has been checked by the registration office according to LKompVzVo - {% endblocktrans %} - <br> {% blocktrans %} Recorded = Has been checked and published by the conservation office {% endblocktrans %} @@ -14,18 +10,14 @@ <table class="table table-hover"> <thead> <tr> - <th scope="col">{% trans 'Before' %} LKompVzVo</th> - <th scope="col">{% trans 'After' %} LKompVzVo</th> - <th scope="col">{% fa5_icon 'bookmark' %} {% trans 'Recorded' %}</th> - <th scope="col" class="w-25">{% trans 'Total' %}</th> + <th scope="col" class="w-25">{% fa5_icon 'bookmark' %} {% trans 'Recorded' %}</th> + <th scope="col">{% trans 'Total' %}</th> </tr> </thead> <tbody> <tr> - <td>{{report.eco_account_report.queryset_old_count|default_if_zero:"-"}}</td> - <td>{{report.eco_account_report.queryset_count|default_if_zero:"-"}}</td> <td>{{report.eco_account_report.queryset_recorded_count|default_if_zero:"-"}}</td> - <td>{{report.eco_account_report.queryset_total_count|default_if_zero:"-"}}</td> + <td>{{report.eco_account_report.queryset_count|default_if_zero:"-"}}</td> </tr> </tbody> </table> diff --git a/analysis/templates/analysis/reports/includes/old_data/amount.html b/analysis/templates/analysis/reports/includes/old_data/amount.html new file mode 100644 index 00000000..cd79cb6f --- /dev/null +++ b/analysis/templates/analysis/reports/includes/old_data/amount.html @@ -0,0 +1,40 @@ +{% load i18n fontawesome_5 ksp_filters %} + +<h3>{% trans 'Amount' %}</h3> +<strong> + {% blocktrans %} + Checked = Has been checked by the registration office according to LKompVzVo + {% endblocktrans %} + <br> + {% blocktrans %} + Recorded = Has been checked and published by the conservation office + {% endblocktrans %} +</strong> +<div class="table-container"> + <table class="table table-hover"> + <thead> + <tr> + <th scope="col" class="w-25">{% fa5_icon 'star' %} {% trans 'Type' %}</th> + <th scope="col">{% fa5_icon 'bookmark' %} {% trans 'Recorded' %}</th> + <th scope="col">{% trans 'Total' %}</th> + </tr> + </thead> + <tbody> + <tr> + <td>{% trans 'Intervention' %}</td> + <td>{{report.old_data_report.queryset_intervention_recorded_count|default_if_zero:"-"}}</td> + <td>{{report.old_data_report.queryset_intervention_count|default_if_zero:"-"}}</td> + </tr> + <tr> + <td>{% trans 'Compensation' %}</td> + <td>{{report.old_data_report.queryset_comps_recorded_count|default_if_zero:"-"}}</td> + <td>{{report.old_data_report.queryset_comps_count|default_if_zero:"-"}}</td> + </tr> + <tr> + <td>{% trans 'Eco-account' %}</td> + <td>{{report.old_data_report.queryset_acc_recorded_count|default_if_zero:"-"}}</td> + <td>{{report.old_data_report.queryset_acc_count|default_if_zero:"-"}}</td> + </tr> + </tbody> + </table> +</div> \ No newline at end of file diff --git a/analysis/templates/analysis/reports/includes/old_intervention/card_old_interventions.html b/analysis/templates/analysis/reports/includes/old_data/card_old_interventions.html similarity index 97% rename from analysis/templates/analysis/reports/includes/old_intervention/card_old_interventions.html rename to analysis/templates/analysis/reports/includes/old_data/card_old_interventions.html index 3a272874..a25a5712 100644 --- a/analysis/templates/analysis/reports/includes/old_intervention/card_old_interventions.html +++ b/analysis/templates/analysis/reports/includes/old_data/card_old_interventions.html @@ -16,7 +16,7 @@ </div> <div id="oldInterventionBody" class="collapse" aria-labelledby="oldIntervention"> <div class="card-body"> - {% include 'analysis/reports/includes/old_intervention/amount.html' %} + {% include 'analysis/reports/includes/old_data/amount.html' %} </div> </div> </div> diff --git a/analysis/templates/analysis/reports/includes/old_intervention/amount.html b/analysis/templates/analysis/reports/includes/old_intervention/amount.html deleted file mode 100644 index 8a6b4be0..00000000 --- a/analysis/templates/analysis/reports/includes/old_intervention/amount.html +++ /dev/null @@ -1,30 +0,0 @@ -{% load i18n fontawesome_5 ksp_filters %} - -<h3>{% trans 'Amount' %}</h3> -<strong> - {% blocktrans %} - Checked = Has been checked by the registration office according to LKompVzVo - {% endblocktrans %} - <br> - {% blocktrans %} - Recorded = Has been checked and published by the conservation office - {% endblocktrans %} -</strong> -<div class="table-container"> - <table class="table table-hover"> - <thead> - <tr> - <th scope="col">{% fa5_icon 'star' %} {% trans 'Checked' %}</th> - <th scope="col">{% fa5_icon 'bookmark' %} {% trans 'Recorded' %}</th> - <th scope="col" class="w-25">{% trans 'Total' %}</th> - </tr> - </thead> - <tbody> - <tr> - <td>{{report.old_intervention_report.queryset_checked_count|default_if_zero:"-"}}</td> - <td>{{report.old_intervention_report.queryset_recorded_count|default_if_zero:"-"}}</td> - <td>{{report.old_intervention_report.queryset_count|default_if_zero:"-"}}</td> - </tr> - </tbody> - </table> -</div> \ No newline at end of file diff --git a/analysis/utils/excel/excel.py b/analysis/utils/excel/excel.py index 69fbcdfe..611f6a0c 100644 --- a/analysis/utils/excel/excel.py +++ b/analysis/utils/excel/excel.py @@ -47,28 +47,30 @@ class TempExcelFile: Returns: """ - ws = self._workbook.active - # Always activate sheet protection - ws.protection.sheet = True - ws.protection.enable() - _rows = ws.iter_rows(start_row) - for row in _rows: - for cell in row: - val = cell.value - if val in self._template_map: - attr = self._template_map[val] - # If keyword '_iter' can be found inside the placeholder value it's an iterable and we - # need to process it differently - if isinstance(attr, dict): - # Read the iterable object and related attributes from the dict - _iter_obj = attr.get("iterable", None) - _attrs = attr.get("attrs", []) - self._add_cells_from_iterable(ws, cell, _iter_obj, _attrs) - # Since the sheet length did change now, we need to rerun this function starting with the new - # row counter - self._replace_template_placeholders(start_row=cell.row + len(_iter_obj)) - else: - cell.value = attr + sheets = self._workbook.worksheets + for sheet in sheets: + ws = sheet + # Always activate sheet protection + ws.protection.sheet = True + ws.protection.enable() + _rows = ws.iter_rows(start_row) + for row in _rows: + for cell in row: + val = cell.value + if val in self._template_map: + attr = self._template_map[val] + # If keyword '_iter' can be found inside the placeholder value it's an iterable and we + # need to process it differently + if isinstance(attr, dict): + # Read the iterable object and related attributes from the dict + _iter_obj = attr.get("iterable", None) + _attrs = attr.get("attrs", []) + self._add_cells_from_iterable(ws, cell, _iter_obj, _attrs) + # Since the sheet length did change now, we need to rerun this function starting with the new + # row counter + self._replace_template_placeholders(start_row=cell.row + len(_iter_obj)) + else: + cell.value = attr self._workbook.save(self._file.name) self._file.seek(0) self.stream = self._file.read() diff --git a/analysis/utils/excel/excel_report.xlsx b/analysis/utils/excel/excel_report.xlsx index 4383fbe8a80f4a056579b72136dc1c19759745bf..72cf1295461bac4f862d9bc163f7601c7c32ba20 100644 GIT binary patch literal 10693 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 delta 5748 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 XO`4p=MnixNzy?U&?{Ads&+7jGY?@7& diff --git a/analysis/utils/report.py b/analysis/utils/report.py index d3341a1a..1fd86604 100644 --- a/analysis/utils/report.py +++ b/analysis/utils/report.py @@ -379,14 +379,10 @@ class TimespanReport: self.queryset_registration_office_other_recorded_count = self.queryset_registration_office_other_recorded.count() class EcoAccountReport: - queryset_total = EcoAccount.objects.none() queryset = EcoAccount.objects.none() queryset_recorded = EcoAccount.objects.none() - queryset_old = EcoAccount.objects.none() - queryset_total_count = -1 queryset_count = -1 queryset_recorded_count = -1 - queryset_old_count = -1 queryset_deductions = EcoAccountDeduction.objects.none() queryset_deductions_recorded = EcoAccountDeduction.objects.none() @@ -401,23 +397,15 @@ class TimespanReport: def __init__(self, id: str, date_from: str, date_to: str): # First fetch all eco account for this office - self.queryset_total = EcoAccount.objects.filter( + self.queryset = EcoAccount.objects.filter( responsible__conservation_office__id=id, deleted=None, created__timestamp__gte=date_from, created__timestamp__lte=date_to, ) - self.queryset_recorded = self.queryset_total.filter( + self.queryset_recorded = self.queryset.filter( recorded__isnull=False ) - # Then fetch the old ones (pre-LKompVzVo) - self.queryset_old = self.queryset_total.filter( - recorded__timestamp__lte=LKOMPVZVO_PUBLISH_DATE, - ) - # Then fetch the default queryset with the new ones (post-LKompVzVo) - self.queryset = self.queryset_total.filter( - recorded__timestamp__gte=LKOMPVZVO_PUBLISH_DATE, - ) # Fetch all related deductions self.queryset_deductions = EcoAccountDeduction.objects.filter( account__id__in=self.queryset.values_list("id") @@ -427,15 +415,29 @@ class TimespanReport: intervention__recorded__isnull=False ) - self.queryset_total_count = self.queryset_total.count() self.queryset_count = self.queryset.count() - self.queryset_old_count = self.queryset_old.count() - self.queryset_recorded = self.queryset_recorded.count() + self.queryset_recorded_count = self.queryset_recorded.count() self.queryset_deductions_count = self.queryset_deductions.count() self.queryset_deductions_recorded_count = self.queryset_deductions_recorded.count() self.queryset_has_deductions_count = self.queryset_has_deductions.count() self._create_report() + self._define_excel_map() + + def _define_excel_map(self): + """ Define the excel map, which holds values for each placeholder used in the template + + Returns: + + """ + self.excel_map = { + "acc_total": self.queryset_count, + "acc_recorded": self.queryset_recorded_count, + "acc_deduc_recorded": self.queryset_deductions_recorded_count, + "acc_deduc_surface_recorded": self.recorded_deductions_sq_m, + "acc_deduc_total": self.queryset_deductions_count, + "acc_deduc_surface_total": self.deductions_sq_m, + } def _create_report(self): """ Creates all report information @@ -453,32 +455,76 @@ class TimespanReport: sum=Sum("surface") )["sum"] or 0 - class OldInterventionReport: - queryset = Compensation.objects.none() - queryset_checked = Compensation.objects.none() - queryset_recorded = Compensation.objects.none() + class OldDataReport: + """ + Evaluates 'old data' (registered (zugelassen) before 16.06.2018) + """ + queryset_intervention = Intervention.objects.none() + queryset_intervention_recorded = Intervention.objects.none() + queryset_intervention_count = -1 + queryset_intervention_recorded_count = -1 - queryset_count = -1 - queryset_checked_count = -1 - queryset_recorded_count = -1 + queryset_comps = Compensation.objects.none() + queryset_comps_recorded = Compensation.objects.none() + queryset_comps_count = -1 + queryset_comps_recorded_count = -1 + + queryset_acc = EcoAccount.objects.none() + queryset_acc_recorded = EcoAccount.objects.none() + queryset_acc_count = -1 + queryset_acc_recorded_count = -1 def __init__(self, id: str, date_from: str, date_to: str): - self.queryset = Intervention.objects.filter( + self.queryset_intervention = Intervention.objects.filter( legal__registration_date__lte=LKOMPVZVO_PUBLISH_DATE, responsible__conservation_office__id=id, deleted=None, created__timestamp__gte=date_from, created__timestamp__lte=date_to, ) - self.queryset_checked = self.queryset.filter( - checked__isnull=False - ) - self.queryset_recorded = self.queryset.filter( + self.queryset_intervention_recorded = self.queryset_intervention.filter( recorded__isnull=False ) - self.queryset_count = self.queryset.count() - self.queryset_checked = self.queryset_checked.count() - self.queryset_recorded = self.queryset_recorded.count() + self.queryset_intervention_count = self.queryset_intervention.count() + self.queryset_intervention_recorded_count = self.queryset_intervention_recorded.count() + + self.queryset_comps = Compensation.objects.filter( + intervention__in=self.queryset_intervention + ) + self.queryset_comps_recorded = Compensation.objects.filter( + intervention__in=self.queryset_intervention_recorded, + ) + self.queryset_comps_count = self.queryset_comps.count() + self.queryset_comps_recorded_count = self.queryset_comps_recorded.count() + + self.queryset_acc = EcoAccount.objects.filter( + #legal__registration_date__lte=LKOMPVZVO_PUBLISH_DATE, + responsible__conservation_office__id=id, + deleted=None, + created__timestamp__gte=date_from, + created__timestamp__lte=date_to, + ) + self.queryset_acc_recorded = self.queryset_acc.filter( + recorded__isnull=False, + ) + self.queryset_acc_count = self.queryset_acc.count() + self.queryset_acc_recorded_count = self.queryset_acc_recorded.count() + self._define_excel_map() + + def _define_excel_map(self): + """ Define the excel map, which holds values for each placeholder used in the template + + Returns: + + """ + self.excel_map = { + "old_i_recorded": self.queryset_intervention_recorded_count, + "old_i_total": self.queryset_intervention_count, + "old_c_recorded": self.queryset_comps_recorded_count, + "old_c_total": self.queryset_comps_count, + "old_ea_recorded": self.queryset_acc_recorded_count, + "old_ea_total": self.queryset_acc_count, + } def __init__(self, office_id: str, date_from: str, date_to: str): self.office_id = office_id @@ -488,7 +534,7 @@ class TimespanReport: self.intervention_report = self.InterventionReport(self.office_id, date_from, date_to) self.compensation_report = self.CompensationReport(self.office_id, date_from, date_to) self.eco_account_report = self.EcoAccountReport(self.office_id, date_from, date_to) - self.old_intervention_report = self.OldInterventionReport(self.office_id, date_from, date_to) + self.old_data_report = self.OldDataReport(self.office_id, date_from, date_to) # Build excel map self.excel_map = { @@ -497,3 +543,5 @@ class TimespanReport: } self.excel_map.update(self.intervention_report.excel_map) self.excel_map.update(self.compensation_report.excel_map) + self.excel_map.update(self.eco_account_report.excel_map) + self.excel_map.update(self.old_data_report.excel_map) diff --git a/locale/de/LC_MESSAGES/django.po b/locale/de/LC_MESSAGES/django.po index 764b7349..74b0ecab 100644 --- a/locale/de/LC_MESSAGES/django.po +++ b/locale/de/LC_MESSAGES/django.po @@ -77,7 +77,7 @@ msgstr "bis" #: analysis/templates/analysis/reports/includes/compensation/amount.html:3 #: analysis/templates/analysis/reports/includes/eco_account/amount.html:3 #: analysis/templates/analysis/reports/includes/intervention/amount.html:3 -#: analysis/templates/analysis/reports/includes/old_intervention/amount.html:3 +#: analysis/templates/analysis/reports/includes/old_data/amount.html:3 #: compensation/forms/modalForms.py:351 #: compensation/templates/compensation/detail/eco_account/includes/deductions.html:34 #: intervention/templates/intervention/detail/includes/deductions.html:31 @@ -87,7 +87,7 @@ msgstr "Menge" #: analysis/templates/analysis/reports/includes/compensation/amount.html:5 #: analysis/templates/analysis/reports/includes/eco_account/amount.html:5 #: analysis/templates/analysis/reports/includes/intervention/amount.html:5 -#: analysis/templates/analysis/reports/includes/old_intervention/amount.html:5 +#: analysis/templates/analysis/reports/includes/old_data/amount.html:5 msgid "" "\n" " Checked = Has been checked by the registration office according to " @@ -101,7 +101,7 @@ msgstr "" #: analysis/templates/analysis/reports/includes/compensation/amount.html:9 #: analysis/templates/analysis/reports/includes/eco_account/amount.html:9 #: analysis/templates/analysis/reports/includes/intervention/amount.html:9 -#: analysis/templates/analysis/reports/includes/old_intervention/amount.html:9 +#: analysis/templates/analysis/reports/includes/old_data/amount.html:9 msgid "" "\n" " Recorded = Has been checked and published by the conservation office\n" @@ -120,7 +120,7 @@ msgstr "Zuständigkeitsbereich" #: analysis/templates/analysis/reports/includes/intervention/amount.html:17 #: analysis/templates/analysis/reports/includes/intervention/compensated_by.html:8 #: analysis/templates/analysis/reports/includes/intervention/laws.html:17 -#: analysis/templates/analysis/reports/includes/old_intervention/amount.html:17 +#: analysis/templates/analysis/reports/includes/old_data/amount.html:17 #: compensation/tables.py:35 #: compensation/templates/compensation/detail/compensation/view.html:43 #: intervention/tables.py:33 @@ -135,7 +135,7 @@ msgstr "Geprüft" #: analysis/templates/analysis/reports/includes/intervention/amount.html:18 #: analysis/templates/analysis/reports/includes/intervention/compensated_by.html:9 #: analysis/templates/analysis/reports/includes/intervention/laws.html:20 -#: analysis/templates/analysis/reports/includes/old_intervention/amount.html:18 +#: analysis/templates/analysis/reports/includes/old_data/amount.html:18 #: compensation/tables.py:41 compensation/tables.py:181 #: compensation/templates/compensation/detail/compensation/view.html:57 #: compensation/templates/compensation/detail/eco_account/includes/deductions.html:31 @@ -159,7 +159,7 @@ msgstr "Einzelflächen" #: analysis/templates/analysis/reports/includes/intervention/compensated_by.html:10 #: analysis/templates/analysis/reports/includes/intervention/laws.html:23 #: analysis/templates/analysis/reports/includes/intervention/laws.html:43 -#: analysis/templates/analysis/reports/includes/old_intervention/amount.html:19 +#: analysis/templates/analysis/reports/includes/old_data/amount.html:19 #: konova/templates/konova/home.html:23 konova/templates/konova/home.html:61 #: konova/templates/konova/home.html:100 msgid "Total" @@ -185,7 +185,7 @@ msgid "Compensations" msgstr "Kompensationen" #: analysis/templates/analysis/reports/includes/eco_account/amount.html:17 -#: analysis/templates/analysis/reports/includes/old_intervention/card_old_interventions.html:13 +#: analysis/templates/analysis/reports/includes/old_data/card_old_interventions.html:13 msgid "Before" msgstr "Vor" @@ -265,7 +265,7 @@ msgstr "" msgid "Law" msgstr "Gesetz" -#: analysis/templates/analysis/reports/includes/old_intervention/card_old_interventions.html:11 +#: analysis/templates/analysis/reports/includes/old_data/card_old_interventions.html:11 msgid "Old interventions" msgstr "Altfälle"