From 05acf1c7afccdc6b5582456b3a93d48e8ec98b41 Mon Sep 17 00:00:00 2001
From: sergei kasianenko <monitor84@list.ru>
Date: Thu, 24 Oct 2024 20:37:54 +0800
Subject: [PATCH 1/7] together param

---
 api/reports/sql_func.py                     | 21 ++++----
 api/reports/statistic_model/base_columns.py | 32 ++++++------
 api/reports/views.py                        | 56 ++++++++++++++++++++-
 directory/models.py                         | 36 +++++++++++++
 4 files changed, 120 insertions(+), 25 deletions(-)

diff --git a/api/reports/sql_func.py b/api/reports/sql_func.py
index 235ae2e37a..8b5d635b5c 100644
--- a/api/reports/sql_func.py
+++ b/api/reports/sql_func.py
@@ -86,20 +86,23 @@ def get_field_results(directions, input_field, fraction_field):
         cursor.execute(
             """ 
         SELECT
-        dn.id as direction_id,
+        dn.id as protocol_direction_id,
         to_char(directions_issledovaniya.time_confirmation AT TIME ZONE %(tz)s, 'DD.MM.YYYY HH24:MI') AS time_confirm,
         dp.value as input_value, 
         dpif.title as field_title,
-        dpif.statistic_pattern_param_id as input_static_param,
+        dpif.statistic_pattern_param_id as input_static_param_id,
         dr.value as fraction_value,
-        df.statistic_pattern_param_id as fraction_static_param,
+        df.statistic_pattern_param_id as fraction_static_param_id,
         dn.parent_id as parrent_iss,
-        pd.napravleniye_id as hosp_direction,
-        ci.family,
-        ci.name,
-        ci.patronymic,
-        to_char(ci.birthday, 'DD.MM.YYYY') as born,
-        to_char(EXTRACT(YEAR from age(directions_issledovaniya.time_confirmation, ci.birthday)), '999') as ind_age
+        pd.napravleniye_id as hospital_direction,
+        ci.sex,
+        ci.family as patient_family,
+        ci.name as patient_name,
+        ci.patronymic as patient_patronymic,
+        to_char(ci.birthday, 'DD.MM.YYYY') as patient_birthday,
+        to_char(EXTRACT(YEAR from age(directions_issledovaniya.time_confirmation, ci.birthday)), '999') as patient_age,
+        cc.main_address as patient_main_address,
+        cc.fact_address as patient_fact_address
         
         FROM directions_issledovaniya
         LEFT JOIN directions_napravleniya dn on directions_issledovaniya.napravleniye_id = dn.id 
diff --git a/api/reports/statistic_model/base_columns.py b/api/reports/statistic_model/base_columns.py
index 7ace91d0cc..649e8d2995 100644
--- a/api/reports/statistic_model/base_columns.py
+++ b/api/reports/statistic_model/base_columns.py
@@ -8,7 +8,7 @@ def custom_research_data(query_sql):
     step = 0
     tmp_result = {
         "permanent_field": {
-            "Случай": "",
+            "Случай ": "",
             "Протокол": "",
             "Пациент": "",
             "Пол": "",
@@ -20,25 +20,27 @@ def custom_research_data(query_sql):
     }
     custom_fields = []
     for i in query_sql:
-        if prev_direction != i.direction_id and step != 0:
+        if prev_direction != i.hosp_direction and step != 0:
             result.append(tmp_result.copy())
-        if prev_direction != i.direction_number:
-            tmp_result = {
-                "permanent_field": {
-                    "Случай": f"{i.hosp_direction}",
-                    "Протокол": f"{i.direction_id}",
-                    "Пациент": f"{i.family} {i.name} {i.patronymic}",
-                    "Пол": i.patient_sex,
-                    "Дата рождения": i.born,
-                    "Возраст": i.ind_age,
-                    "Адрес": i.patient_fact_address if i.patient_fact_address else i.patient_main_address,
-                }
+        tmp_result = {
+            "permanent_field": {
+                "Случай": f"{i.hosp_direction}",
+                "Пациент": f"{i.family} {i.name} {i.patronymic}",
+                "Пол": i.patient_sex,
+                "Дата рождения": i.born,
+                "Возраст": i.ind_age,
+                "Адрес": i.patient_fact_address if i.patient_fact_address else i.patient_main_address,
             }
-        tmp_result["custom_field"][i.field_title] = i.field_value
+        }
+        if tmp_result["custom_field"].get(i.field_title):
+            tmp_result["custom_field"]
+
+        else:
+            tmp_result["custom_field"][i.field_title] = i.field_value
         if i.field_title not in custom_fields:
             custom_fields.append(i.field_title)
         step += 1
-        prev_direction = i.direction_id
+        prev_direction = i.hosp_direction
     result.append(tmp_result.copy())
     fields = ["Случай", "Протокол", "Пациент", "Пол", "Дата рождения", "Возраст", "Адрес"]
     fields.extend(custom_fields)
diff --git a/api/reports/views.py b/api/reports/views.py
index a0aa536bd6..b8af973ed0 100644
--- a/api/reports/views.py
+++ b/api/reports/views.py
@@ -6,7 +6,7 @@
 from api.reports import sql_func
 from api.reports import handle_func
 from api.reports.sql_func import get_pair_direction_iss, get_simple_directions_for_hosp_stationar, get_field_results
-from directory.models import StatisticPatternParamSet, ParaclinicInputField, Fractions
+from directory.models import StatisticPatternParamSet, ParaclinicInputField, Fractions, PatternParam, PatternParamTogether
 from laboratory.settings import SEARCH_PAGE_STATISTIC_PARAMS
 from django.http import JsonResponse
 from django.contrib.auth.decorators import login_required
@@ -91,5 +91,59 @@ def xlsx_model(request):
         if len(laboratory_fractions_statistic_param) == 0:
             laboratory_fractions_statistic_param = [-1]
         result_directions = get_field_results(tuple(res_dir), tuple(input_field_statistic_param), tuple(laboratory_fractions_statistic_param))
+        pattern_params = PatternParam.objects.filter(id__in=list(statistic_param_data.keys())).order_by("order").values("pk", "title")
+        order_custom_field = {i.get('pk'): i.get('title') for i in pattern_params}
+        print(order_custom_field)
+        together_params = PatternParamTogether.get_together_param(list(order_custom_field.keys()))
+        together_params_by_group = together_params.get("by_group")
+        together_params_by_params = together_params.get("by_param")
+        intermediate_structure_result = {}
+        for i in result_directions:
+            if not intermediate_structure_result.get(i.hospital_direction):
+                intermediate_structure_result[i.hospital_direction] = {
+                    "patient_fio": f"{i.patient_family} {i.patient_name} {i.patient_patronymic}",
+                    "sex": i.sex,
+                    "birthday": i.patient_birthday,
+                    "age": i.patient_age,
+                    "address": i.patient_fact_address if i.patient_fact_address else i.patient_main_address,
+                    "protocol_directions": {}
+                }
+            if not intermediate_structure_result[i.hospital_direction]["protocol_directions"].get(i.protocol_direction_id):
+                intermediate_structure_result[i.hospital_direction]["protocol_directions"][i.protocol_direction_id] = []
+            intermediate_structure_result[i.hospital_direction]["protocol_directions"][i.protocol_direction_id].append(
+                {
+                    "input_static_param_id": i.input_static_param_id,
+                    "field_title": i.field_title,
+                    "input_value": i.input_value,
+                    "fraction_static_param_id": i.fraction_static_param_id,
+                    "fraction_value": i.fraction_value,
+                    "time_confirm": i.time_confirm
+                }
+            )
+
+        # print(result_directions)
+        # print(intermediate_structure_result)
+        fields = {"Случай": "", "Пациент": "", "Пол": "", "Дата рождения": "", "Возраст": "", "Адрес": ""}
+        fields.update({i: "" for i in order_custom_field.values()})
+        final_result = []
+        for k, v in intermediate_structure_result.items():
+            print(k)
+            print(v)
+            print("--")
+            intermediate_result = fields.copy()
+            intermediate_result["Случай"] = k
+            intermediate_result["Пациент"] = v.get('patient_fio')
+            intermediate_result["Пол"] = v.get("sex")
+            intermediate_result["Дата рождения"] = v.get("birthday")
+            intermediate_result["Возраст"] = v.get("age")
+            intermediate_result["Адрес"] = v.get("address")
+            for data in v.get("protocol_directions").values():
+                title_field = ""
+                if data.get("input_value"):
+                    title_field = order_custom_field.get(data["input_static_param_id"])
+                elif data.get("fraction_value"):
+                    title_field = order_custom_field.get(data["fraction_static_param_id"])
+                if intermediate_result.get(title_field):
+                    pass # сделай вторую строку для текущего параметра текущей истории
 
     return JsonResponse({"results": "file-xls-model", "link": "open-xls", "result": result_directions})
diff --git a/directory/models.py b/directory/models.py
index f609857501..8c89d1d614 100644
--- a/directory/models.py
+++ b/directory/models.py
@@ -1105,6 +1105,42 @@ def get_statistic_param(statistic_pattern_id):
         return {p.statistic_param_id: {"title": p.statistic_param.title, "isDynamic": p.statistic_param.is_dynamic_param} for p in params}
 
 
+class GroupPatternParams(models.Model):
+    title = models.CharField(max_length=400, unique=True, help_text="Название группы-блока параметра вместе")
+
+    def __str__(self):
+        return f"{self.title}"
+
+    class Meta:
+        verbose_name = "Статистическая модель - группа-блок"
+        verbose_name_plural = "Статистическая модель - группы-блоки"
+
+
+class PatternParamTogether(models.Model):
+    statistic_param = models.ForeignKey(PatternParam, default=None, null=True, blank=True, help_text="Параметр статистической модели отчет", on_delete=models.CASCADE)
+    group_pattern_param = models.ForeignKey(GroupPatternParams, default=None, null=True, blank=True, help_text="Статистическая модель", on_delete=models.CASCADE)
+
+    def __str__(self):
+        return f"{self.statistic_param}-{self.group_pattern_param}"
+
+    class Meta:
+        verbose_name = "Статистическая модель - группа-блок и параметры ВМЕСТЕ"
+        verbose_name_plural = "Статистическая модель - группы-блоки и параметры ВМЕСТЕ"
+
+    @staticmethod
+    def get_together_param(statistic_pattern_ids):
+        groups_data = PatternParamTogether.objects.filter(statistic_param_id__in=statistic_pattern_ids)
+        result_by_group = {}
+        result_by_param = {g.statistic_param_id: g.group_pattern_param_id for g in groups_data}
+
+        for g in groups_data:
+            if not result_by_group.get(g.group_pattern_param_id):
+                result_by_group[g.group_pattern_param_id] = []
+            result_by_group[g.group_pattern_param_id].append(g.statistic_param_id)
+
+        return {"by_group": result_by_group, "by_param": result_by_param}
+
+
 class ParaclinicInputGroups(models.Model):
     title = models.CharField(max_length=255, help_text="Название группы")
     show_title = models.BooleanField()

From db0c179d425e48f8d40d6bbcc2781d92256ed856 Mon Sep 17 00:00:00 2001
From: sergei kasianenko <monitor84@list.ru>
Date: Thu, 24 Oct 2024 23:11:23 +0800
Subject: [PATCH 2/7] .

---
 api/reports/views.py | 33 +++++++++++++++++++++++++--------
 1 file changed, 25 insertions(+), 8 deletions(-)

diff --git a/api/reports/views.py b/api/reports/views.py
index b8af973ed0..4ae024acd2 100644
--- a/api/reports/views.py
+++ b/api/reports/views.py
@@ -124,7 +124,10 @@ def xlsx_model(request):
         # print(result_directions)
         # print(intermediate_structure_result)
         fields = {"Случай": "", "Пациент": "", "Пол": "", "Дата рождения": "", "Возраст": "", "Адрес": ""}
-        fields.update({i: "" for i in order_custom_field.values()})
+        custom_fields = {v: "" for k, v in order_custom_field.items()}
+        fields.update(custom_fields)
+        print("custom_fields")
+        print(custom_fields)
         final_result = []
         for k, v in intermediate_structure_result.items():
             print(k)
@@ -137,13 +140,27 @@ def xlsx_model(request):
             intermediate_result["Дата рождения"] = v.get("birthday")
             intermediate_result["Возраст"] = v.get("age")
             intermediate_result["Адрес"] = v.get("address")
-            for data in v.get("protocol_directions").values():
+            for direction_num, data_direction in v.get("protocol_directions").items():
                 title_field = ""
-                if data.get("input_value"):
-                    title_field = order_custom_field.get(data["input_static_param_id"])
-                elif data.get("fraction_value"):
-                    title_field = order_custom_field.get(data["fraction_static_param_id"])
-                if intermediate_result.get(title_field):
-                    pass # сделай вторую строку для текущего параметра текущей истории
+                print("-----")
+                for current_data in data_direction:
+                    print(current_data)
+                    group_id_block_param = None
+                    if current_data.get("input_value"):
+                        title_field = order_custom_field.get(current_data["input_static_param_id"])
+                        group_id_block_param = together_params_by_params.get(current_data["input_static_param_id"])
+                    elif current_data.get("fraction_value"):
+                        title_field = order_custom_field.get(current_data["fraction_static_param_id"])
+                        group_id_block_param = together_params_by_params.get(current_data["fraction_static_param_id"])
+                    param_ids_in_group_block = together_params_by_group.get(group_id_block_param)
+                    used_block_in_order_custom_field = [v for k, v in order_custom_field.items() if k in param_ids_in_group_block]
+                    # проверить были ли значения полей заполнены уже БЛОКА-ВМЕСТЕ ранее
+                    later_value = []
+                    if len(used_block_in_order_custom_field) > 0:
+                        later_value = [k for k in used_block_in_order_custom_field if intermediate_result.get(k)]
+                    if len(later_value) > 0 or intermediate_result.get(title_field):
+                        pass # сделай вторую строку для текущего параметра текущей истории
+                    else:
+                        pass # добавить в текущее поле
 
     return JsonResponse({"results": "file-xls-model", "link": "open-xls", "result": result_directions})

From a6c318588cc44b727e5c597cc6a6c032b7123dc2 Mon Sep 17 00:00:00 2001
From: sergei kasianenko <monitor84@list.ru>
Date: Mon, 28 Oct 2024 10:59:03 +0800
Subject: [PATCH 3/7] sava statistic-model file to xls

---
 api/reports/statistic_model/base_columns.py   | 21 ++---
 .../statistic_model/save_file_model.py        | 11 +++
 .../statistic_model/variable_columns.py       |  0
 api/reports/views.py                          | 83 ++++++++++++-------
 directory/models.py                           |  2 +-
 statistic/report/base_data.py                 | 19 +++++
 6 files changed, 93 insertions(+), 43 deletions(-)
 create mode 100644 api/reports/statistic_model/save_file_model.py
 delete mode 100644 api/reports/statistic_model/variable_columns.py

diff --git a/api/reports/statistic_model/base_columns.py b/api/reports/statistic_model/base_columns.py
index 20ea0e7178..895a2d82ef 100644
--- a/api/reports/statistic_model/base_columns.py
+++ b/api/reports/statistic_model/base_columns.py
@@ -47,31 +47,26 @@ def custom_research_data(query_sql):
     return {"result": result, "custom_fields": custom_fields, "fields": fields}
 
 
-def custom_research_base(ws1, d1, d2, result_query, research_title):
+def custom_research_base(ws1, custom_fields, title_model):
     style_border = NamedStyle(name="style_border_ca")
     bd = Side(style='thin', color="000000")
     style_border.border = Border(left=bd, top=bd, right=bd, bottom=bd)
     style_border.font = Font(bold=True, size=11)
     style_border.alignment = Alignment(wrap_text=True, horizontal='center', vertical='center')
 
-    ws1.cell(row=1, column=1).value = 'Услуга:'
-    ws1.cell(row=1, column=2).value = research_title
-    ws1.cell(row=2, column=1).value = 'Период:'
-    ws1.cell(row=3, column=1).value = f'c {d1} по {d2}'
+    ws1.cell(row=1, column=1).value = 'Модель:'
+    ws1.cell(row=1, column=2).value = title_model
 
     columns = [
-        ('Направление', 15),
-        ('Источник', 15),
-        ('Пациент', 45),
-        ('Пол', 10),
-        ('Дата рождения', 26),
+        ('Случай', 15),
+        ('Пациент', 15),
+        ('Пол', 45),
+        ('Дата рождения', 10),
         ('Возраст', 10),
         ('Адрес', 40),
-        ('Исполнитель', 35),
-        ('Код врача', 15),
     ]
 
-    columns2 = [(i, 25) for i in result_query["custom_fields"]]
+    columns2 = [(i, 25) for i in custom_fields]
     columns.extend(columns2)
     row = 5
     for idx, column in enumerate(columns, 1):
diff --git a/api/reports/statistic_model/save_file_model.py b/api/reports/statistic_model/save_file_model.py
new file mode 100644
index 0000000000..09cf4f0e8f
--- /dev/null
+++ b/api/reports/statistic_model/save_file_model.py
@@ -0,0 +1,11 @@
+from statistic.report import base_data
+from statistic.statistic_func import initial_work_book, save_file_disk
+
+
+
+def data_model_save_to_file(final_result, head_data, sheet_name, permanent_head_data, custom_fields):
+    wb, ws = initial_work_book(sheet_name)
+    ws = base_data.fill_default_base(ws, head_data)
+    ws = base_data.fill_xls_model_statistic_data(ws, final_result, permanent_head_data, custom_fields)
+    file_dir = save_file_disk(wb)
+    return file_dir
\ No newline at end of file
diff --git a/api/reports/statistic_model/variable_columns.py b/api/reports/statistic_model/variable_columns.py
deleted file mode 100644
index e69de29bb2..0000000000
diff --git a/api/reports/views.py b/api/reports/views.py
index 4ae024acd2..e0551dd3e3 100644
--- a/api/reports/views.py
+++ b/api/reports/views.py
@@ -6,6 +6,8 @@
 from api.reports import sql_func
 from api.reports import handle_func
 from api.reports.sql_func import get_pair_direction_iss, get_simple_directions_for_hosp_stationar, get_field_results
+from api.reports.statistic_model import base_columns
+from api.reports.statistic_model.save_file_model import data_model_save_to_file
 from directory.models import StatisticPatternParamSet, ParaclinicInputField, Fractions, PatternParam, PatternParamTogether
 from laboratory.settings import SEARCH_PAGE_STATISTIC_PARAMS
 from django.http import JsonResponse
@@ -93,7 +95,6 @@ def xlsx_model(request):
         result_directions = get_field_results(tuple(res_dir), tuple(input_field_statistic_param), tuple(laboratory_fractions_statistic_param))
         pattern_params = PatternParam.objects.filter(id__in=list(statistic_param_data.keys())).order_by("order").values("pk", "title")
         order_custom_field = {i.get('pk'): i.get('title') for i in pattern_params}
-        print(order_custom_field)
         together_params = PatternParamTogether.get_together_param(list(order_custom_field.keys()))
         together_params_by_group = together_params.get("by_group")
         together_params_by_params = together_params.get("by_param")
@@ -121,46 +122,70 @@ def xlsx_model(request):
                 }
             )
 
-        # print(result_directions)
-        # print(intermediate_structure_result)
-        fields = {"Случай": "", "Пациент": "", "Пол": "", "Дата рождения": "", "Возраст": "", "Адрес": ""}
         custom_fields = {v: "" for k, v in order_custom_field.items()}
-        fields.update(custom_fields)
-        print("custom_fields")
-        print(custom_fields)
+
         final_result = []
         for k, v in intermediate_structure_result.items():
-            print(k)
-            print(v)
-            print("--")
-            intermediate_result = fields.copy()
-            intermediate_result["Случай"] = k
-            intermediate_result["Пациент"] = v.get('patient_fio')
-            intermediate_result["Пол"] = v.get("sex")
-            intermediate_result["Дата рождения"] = v.get("birthday")
-            intermediate_result["Возраст"] = v.get("age")
-            intermediate_result["Адрес"] = v.get("address")
+            field_data = [custom_fields.copy()]
+            prev_direction_num = None
             for direction_num, data_direction in v.get("protocol_directions").items():
-                title_field = ""
-                print("-----")
                 for current_data in data_direction:
-                    print(current_data)
                     group_id_block_param = None
+                    value_field = None
+                    title_field = None
                     if current_data.get("input_value"):
                         title_field = order_custom_field.get(current_data["input_static_param_id"])
                         group_id_block_param = together_params_by_params.get(current_data["input_static_param_id"])
+                        value_field = current_data.get("input_value")
                     elif current_data.get("fraction_value"):
                         title_field = order_custom_field.get(current_data["fraction_static_param_id"])
                         group_id_block_param = together_params_by_params.get(current_data["fraction_static_param_id"])
-                    param_ids_in_group_block = together_params_by_group.get(group_id_block_param)
-                    used_block_in_order_custom_field = [v for k, v in order_custom_field.items() if k in param_ids_in_group_block]
+                        value_field = current_data.gey("fraction_value")
+                    param_ids_in_group_block = []
+                    if group_id_block_param:
+                        param_ids_in_group_block = together_params_by_group.get(group_id_block_param)
+                    used_block_in_order_custom_field = []
+                    if len(param_ids_in_group_block) > 0:
+                        used_block_in_order_custom_field = [field_v for field_k, field_v in order_custom_field.items() if field_k in param_ids_in_group_block]
                     # проверить были ли значения полей заполнены уже БЛОКА-ВМЕСТЕ ранее
                     later_value = []
-                    if len(used_block_in_order_custom_field) > 0:
-                        later_value = [k for k in used_block_in_order_custom_field if intermediate_result.get(k)]
-                    if len(later_value) > 0 or intermediate_result.get(title_field):
-                        pass # сделай вторую строку для текущего параметра текущей истории
+                    if len(used_block_in_order_custom_field) > 0 and prev_direction_num != direction_num:
+                        later_value = [used for used in used_block_in_order_custom_field if used in field_data[-1].values()]
+                    if (prev_direction_num != direction_num and len(later_value) > 0) or field_data[-1].get(title_field):
+                        # сделай вторую строку для текущего параметра текущей истории
+                        field_data.append(custom_fields.copy())
+
+                        field_data[-1][title_field] = value_field
+                        field_data[-1]["proto_direction"] = direction_num
                     else:
-                        pass # добавить в текущее поле
-
-    return JsonResponse({"results": "file-xls-model", "link": "open-xls", "result": result_directions})
+                        # добавить в начальную строку текущее поле
+                        if len(field_data) == 0:
+                            field_data.append(custom_fields.copy())
+                        field_data[-1][title_field] = value_field
+                        field_data[-1]["proto_direction"] = direction_num
+                prev_direction_num = direction_num
+            final_result.append({
+                "Случай": k,
+                "Пациент": v.get('patient_fio'),
+                "Пол": v.get("sex"),
+                "Дата рождения": v.get("birthday"),
+                "Возраст": v.get("age"),
+                "Адрес": v.get("address"),
+                "field_data": field_data.copy()
+            })
+
+        permanent_head_data = [
+            'Случай',
+            'Пациент',
+            'Пол',
+            'Дата рождения',
+            'Возраст',
+            'Адрес',
+        ]
+        all_head_data = [*permanent_head_data, *custom_fields.keys()]
+        head_data_dict = {i: i for i in all_head_data}
+
+        results = data_model_save_to_file(final_result, head_data_dict, "Гиршпрунга", permanent_head_data, list(custom_fields.keys()))
+        link = "open-xls"
+
+        return JsonResponse({"ok": True, "results": results, "link": link})
diff --git a/directory/models.py b/directory/models.py
index 8c89d1d614..f06a3530a1 100644
--- a/directory/models.py
+++ b/directory/models.py
@@ -1084,7 +1084,7 @@ class Meta:
     @staticmethod
     def get_pattern_params():
         params = PatternParam.objects.all().order_by("title").values("title", "pk")
-        result = [{"label": p["title"], "id": p["pk"]} for p in params]
+        result = [{"id": -1, "label": "Пусто"}, *[{"label": p["title"], "id": p["pk"]} for p in params]]
         return result
 
 
diff --git a/statistic/report/base_data.py b/statistic/report/base_data.py
index 4b4c5eba71..4ecfcd2c90 100644
--- a/statistic/report/base_data.py
+++ b/statistic/report/base_data.py
@@ -84,3 +84,22 @@ def fill_xls_check_research_exam_data(ws1, value_data):
             column += 1
             ws1.cell(row=r, column=column).value = v
     return ws1
+
+
+def fill_xls_model_statistic_data(ws1, final_data, permanent_head_data, custom_fields):
+    style_border1 = NamedStyle(name="style_border1")
+    bd = Side(style='thin', color="000000")
+    style_border1.border = Border(left=bd, top=bd, right=bd, bottom=bd)
+    style_border1.font = Font(bold=False, size=11)
+    style_border1.alignment = Alignment(wrap_text=True, horizontal='center', vertical='center')
+
+    r = 5
+    for row_data in final_data:
+        r += 1
+        for current_col in range(0, len(permanent_head_data)):
+            ws1.cell(row=r, column=current_col + 1).value = row_data.get(permanent_head_data[current_col])
+        for custom_field in row_data.get("field_data"):
+            for current_col in range(len(permanent_head_data), len(custom_fields) + len(permanent_head_data)):
+                ws1.cell(row=r, column=current_col + 1).value = custom_field.get(custom_fields[current_col - len(permanent_head_data)])
+            r += 1
+    return ws1

From 26faa7caf2ca763be1028a8a0c3e87d152798849 Mon Sep 17 00:00:00 2001
From: sergei kasianenko <monitor84@list.ru>
Date: Mon, 28 Oct 2024 11:01:15 +0800
Subject: [PATCH 4/7] fix

---
 api/reports/statistic_model/base_columns.py   | 77 -------------------
 .../statistic_model/save_file_model.py        |  1 -
 api/reports/views.py                          |  1 -
 3 files changed, 79 deletions(-)
 delete mode 100644 api/reports/statistic_model/base_columns.py

diff --git a/api/reports/statistic_model/base_columns.py b/api/reports/statistic_model/base_columns.py
deleted file mode 100644
index 895a2d82ef..0000000000
--- a/api/reports/statistic_model/base_columns.py
+++ /dev/null
@@ -1,77 +0,0 @@
-from openpyxl.styles import Border, Side, Alignment, Font, NamedStyle
-from openpyxl.utils.cell import get_column_letter
-
-
-def custom_research_data(query_sql):
-    result = []
-    prev_direction = None
-    step = 0
-    tmp_result = {
-        "permanent_field": {
-            "Случай ": "",
-            "Протокол": "",
-            "Пациент": "",
-            "Пол": "",
-            "Дата рождения": "",
-            "Возраст": "",
-            "Адрес": "",
-        },
-        "custom_field": {},
-    }
-    custom_fields = []
-    for i in query_sql:
-        if prev_direction != i.hosp_direction and step != 0:
-            result.append(tmp_result.copy())
-        tmp_result = {
-            "permanent_field": {
-                "Случай": f"{i.hosp_direction}",
-                "Пациент": f"{i.family} {i.name} {i.patronymic}",
-                "Пол": i.patient_sex,
-                "Дата рождения": i.born,
-                "Возраст": i.ind_age,
-                "Адрес": i.patient_fact_address if i.patient_fact_address else i.patient_main_address,
-            }
-        }
-        if tmp_result["custom_field"].get(i.field_title):
-            tmp_result["custom_field"]
-
-        else:
-            tmp_result["custom_field"][i.field_title] = i.field_value
-        if i.field_title not in custom_fields:
-            custom_fields.append(i.field_title)
-        step += 1
-        prev_direction = i.hosp_direction
-    result.append(tmp_result.copy())
-    fields = ["Случай", "Протокол", "Пациент", "Пол", "Дата рождения", "Возраст", "Адрес"]
-    fields.extend(custom_fields)
-    return {"result": result, "custom_fields": custom_fields, "fields": fields}
-
-
-def custom_research_base(ws1, custom_fields, title_model):
-    style_border = NamedStyle(name="style_border_ca")
-    bd = Side(style='thin', color="000000")
-    style_border.border = Border(left=bd, top=bd, right=bd, bottom=bd)
-    style_border.font = Font(bold=True, size=11)
-    style_border.alignment = Alignment(wrap_text=True, horizontal='center', vertical='center')
-
-    ws1.cell(row=1, column=1).value = 'Модель:'
-    ws1.cell(row=1, column=2).value = title_model
-
-    columns = [
-        ('Случай', 15),
-        ('Пациент', 15),
-        ('Пол', 45),
-        ('Дата рождения', 10),
-        ('Возраст', 10),
-        ('Адрес', 40),
-    ]
-
-    columns2 = [(i, 25) for i in custom_fields]
-    columns.extend(columns2)
-    row = 5
-    for idx, column in enumerate(columns, 1):
-        ws1.cell(row=row, column=idx).value = column[0]
-        ws1.column_dimensions[get_column_letter(idx)].width = column[1]
-        ws1.cell(row=row, column=idx).style = style_border
-
-    return ws1
\ No newline at end of file
diff --git a/api/reports/statistic_model/save_file_model.py b/api/reports/statistic_model/save_file_model.py
index 09cf4f0e8f..034ebb8cd1 100644
--- a/api/reports/statistic_model/save_file_model.py
+++ b/api/reports/statistic_model/save_file_model.py
@@ -2,7 +2,6 @@
 from statistic.statistic_func import initial_work_book, save_file_disk
 
 
-
 def data_model_save_to_file(final_result, head_data, sheet_name, permanent_head_data, custom_fields):
     wb, ws = initial_work_book(sheet_name)
     ws = base_data.fill_default_base(ws, head_data)
diff --git a/api/reports/views.py b/api/reports/views.py
index e0551dd3e3..c8be552e34 100644
--- a/api/reports/views.py
+++ b/api/reports/views.py
@@ -6,7 +6,6 @@
 from api.reports import sql_func
 from api.reports import handle_func
 from api.reports.sql_func import get_pair_direction_iss, get_simple_directions_for_hosp_stationar, get_field_results
-from api.reports.statistic_model import base_columns
 from api.reports.statistic_model.save_file_model import data_model_save_to_file
 from directory.models import StatisticPatternParamSet, ParaclinicInputField, Fractions, PatternParam, PatternParamTogether
 from laboratory.settings import SEARCH_PAGE_STATISTIC_PARAMS

From a10dbdb0f5b486520942586d81e08f6abfe42596 Mon Sep 17 00:00:00 2001
From: Sergei Kasianenko <41939763+urchinpro@users.noreply.github.com>
Date: Mon, 28 Oct 2024 13:30:23 +0800
Subject: [PATCH 5/7] Update api/reports/views.py

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
---
 api/reports/views.py | 20 +++++++++++---------
 1 file changed, 11 insertions(+), 9 deletions(-)

diff --git a/api/reports/views.py b/api/reports/views.py
index c8be552e34..63e65c8c66 100644
--- a/api/reports/views.py
+++ b/api/reports/views.py
@@ -163,15 +163,17 @@ def xlsx_model(request):
                         field_data[-1][title_field] = value_field
                         field_data[-1]["proto_direction"] = direction_num
                 prev_direction_num = direction_num
-            final_result.append({
-                "Случай": k,
-                "Пациент": v.get('patient_fio'),
-                "Пол": v.get("sex"),
-                "Дата рождения": v.get("birthday"),
-                "Возраст": v.get("age"),
-                "Адрес": v.get("address"),
-                "field_data": field_data.copy()
-            })
+            final_result.append(
+                {
+                    "Случай": k,
+                    "Пациент": v.get('patient_fio'),
+                    "Пол": v.get("sex"),
+                    "Дата рождения": v.get("birthday"),
+                    "Возраст": v.get("age"),
+                    "Адрес": v.get("address"),
+                    "field_data": field_data.copy(),
+                }
+            )
 
         permanent_head_data = [
             'Случай',

From 506be8ee406f5121b0b7892c1127aac5e537789d Mon Sep 17 00:00:00 2001
From: Sergei Kasianenko <41939763+urchinpro@users.noreply.github.com>
Date: Mon, 28 Oct 2024 13:30:37 +0800
Subject: [PATCH 6/7] Update api/reports/views.py

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
---
 api/reports/views.py | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/api/reports/views.py b/api/reports/views.py
index 63e65c8c66..0cbeca68f1 100644
--- a/api/reports/views.py
+++ b/api/reports/views.py
@@ -117,7 +117,7 @@ def xlsx_model(request):
                     "input_value": i.input_value,
                     "fraction_static_param_id": i.fraction_static_param_id,
                     "fraction_value": i.fraction_value,
-                    "time_confirm": i.time_confirm
+                    "time_confirm": i.time_confirm,
                 }
             )
 

From 079bc1721216448db71bf242677e1f3ffab6b926 Mon Sep 17 00:00:00 2001
From: Sergei Kasianenko <41939763+urchinpro@users.noreply.github.com>
Date: Mon, 28 Oct 2024 13:30:51 +0800
Subject: [PATCH 7/7] Update api/reports/views.py

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
---
 api/reports/views.py | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/api/reports/views.py b/api/reports/views.py
index 0cbeca68f1..6c79b62bd5 100644
--- a/api/reports/views.py
+++ b/api/reports/views.py
@@ -106,7 +106,7 @@ def xlsx_model(request):
                     "birthday": i.patient_birthday,
                     "age": i.patient_age,
                     "address": i.patient_fact_address if i.patient_fact_address else i.patient_main_address,
-                    "protocol_directions": {}
+                    "protocol_directions": {},
                 }
             if not intermediate_structure_result[i.hospital_direction]["protocol_directions"].get(i.protocol_direction_id):
                 intermediate_structure_result[i.hospital_direction]["protocol_directions"][i.protocol_direction_id] = []