DinaFatikh commited on
Commit
e24243b
·
verified ·
1 Parent(s): 23cbb5a

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +76 -20
app.py CHANGED
@@ -6,6 +6,7 @@ import matplotlib.pyplot as plt
6
  from io import BytesIO
7
  import tempfile
8
  import os
 
9
 
10
  # Функция для обработки PDF и извлечения данных
11
  def process_pdf(file):
@@ -76,7 +77,7 @@ def process_pdf(file):
76
 
77
  except Exception as e:
78
  print(f"Ошибка при обработке PDF-файла: {e}")
79
- return pd.DataFrame(), pd.DataFrame(), pd.DataFrame(), None, None, None # Возвращаем пустые данные в случае ошибки
80
 
81
  # Преобразуем список данных в DataFrame
82
  df = pd.DataFrame(data_list)
@@ -104,7 +105,7 @@ def process_pdf(file):
104
  df_percentage = df[['№ локальной сметы', 'Наименование']].copy()
105
  df_percentage['Процент от общей суммы'] = ((df['ВСЕГО ПО СМЕТЕ'].iloc[:-1] / total_sum) * 100).round(2)
106
 
107
- # Создание таблицы структуры расходов по категориям
108
  category_sums = {
109
  'Категория': ['Рабочие', 'Техника', 'Материалы', 'Перевозки', 'Оборудование'],
110
  'Сумма': [
@@ -119,7 +120,40 @@ def process_pdf(file):
119
  df_category_percentage = pd.DataFrame(category_sums)
120
  df_category_percentage['Процент от общей суммы'] = ((df_category_percentage['Сумма'] / total_sum) * 100).round(2)
121
 
122
- # Создание словаря сопоставления категорий и цветов (для диаграммы, если понадобится)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
123
 
124
  # Форматирование чисел с пробелами в качестве разделителей тысяч
125
  def format_number(x):
@@ -146,8 +180,8 @@ def process_pdf(file):
146
  df_percentage.to_excel(percentage_report_path, index=False)
147
  df_category_percentage.to_excel(category_report_path, index=False)
148
 
149
- # Возвращаем форматированные DataFrame и пути к файлам
150
- return df_formatted, df_percentage_formatted, df_category_percentage_formatted, detailed_report_path, percentage_report_path, category_report_path
151
 
152
  # CSS для блокировки копирования текста
153
  custom_css = """
@@ -166,7 +200,7 @@ with gr.Blocks(css=custom_css) as demo:
166
  gr.Markdown("### **AIGineer | ИИ УПРАВЛЕНИЕ СТРОИТЕЛЬСТВОМ**", elem_id="header")
167
  gr.Markdown("**На текущий момент система считает сметы в ценах от 2023**", elem_id="subheader")
168
 
169
- # Загрузка файла
170
  with gr.Row():
171
  upload_button = gr.File(label="ЗАГРУЗИТЕ СМЕТУ В PDF", elem_id="upload")
172
 
@@ -178,50 +212,72 @@ with gr.Blocks(css=custom_css) as demo:
178
  "% соотношение локальных смет",
179
  "Структура расходов по категориям"
180
  ],
181
- label="Выберите отчет"
182
  )
183
 
 
 
 
 
184
  # Кнопка для получения отчета
185
  with gr.Row():
186
  get_report_button = gr.Button("Получить отчет")
187
 
188
- # Заголовок отчета
189
- report_title = gr.Markdown(visible=False)
190
-
191
  # Отображение отчета и кнопка скачивания
192
  with gr.Row():
193
  output_table = gr.Dataframe(visible=False)
194
- # Кнопка для скачивания отчета
 
195
  with gr.Row():
196
  download_excel = gr.File(label="Скачать отчет", visible=False)
197
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
198
  # Функция обновления отчета
199
  def update_report(file, selected_report):
200
  if not file or not selected_report:
201
  return gr.update(visible=False), gr.update(visible=False), gr.update(visible=False)
202
 
203
  # Обрабатываем PDF и получаем данные
204
- df_formatted, df_percentage_formatted, df_category_percentage_formatted, detailed_report_path, percentage_report_path, category_report_path = process_pdf(file.name)
205
 
206
  if selected_report == "Детализированный бюджет":
207
- title = "### ДЕТАЛИЗИРОВАННЫЙ БЮДЖЕТ"
208
  return (
209
- gr.update(value=title, visible=True),
210
  gr.update(value=df_formatted, visible=True),
 
211
  gr.update(value=detailed_report_path, visible=True, label="Скачать детализированный отчет")
212
  )
213
  elif selected_report == "% соотношение локальных смет":
214
- title = "### ПРОЦЕНТНОЕ РАСПРЕДЕЛЕНИЕ ЛОКАЛЬНЫХ СМЕТ"
215
  return (
216
- gr.update(value=title, visible=True),
217
  gr.update(value=df_percentage_formatted, visible=True),
 
218
  gr.update(value=percentage_report_path, visible=True, label="Скачать процентное соотношение")
219
  )
220
  elif selected_report == "Структура расходов по категориям":
221
- title = "### СТРУКТУРА РАСХОДОВ ПО КАТЕГОРИЯМ"
222
  return (
223
- gr.update(value=title, visible=True),
224
- gr.update(value=df_category_percentage_formatted, visible=True),
225
  gr.update(value=category_report_path, visible=True, label="Скачать отчет по категориям")
226
  )
227
  else:
@@ -231,7 +287,7 @@ with gr.Blocks(css=custom_css) as demo:
231
  get_report_button.click(
232
  update_report,
233
  inputs=[upload_button, report_selector],
234
- outputs=[report_title, output_table, download_excel]
235
  )
236
 
237
  # Запуск приложения
 
6
  from io import BytesIO
7
  import tempfile
8
  import os
9
+ from PIL import Image
10
 
11
  # Функция для обработки PDF и извлечения данных
12
  def process_pdf(file):
 
77
 
78
  except Exception as e:
79
  print(f"Ошибка при обработке PDF-файла: {e}")
80
+ return pd.DataFrame(), pd.DataFrame(), None, None, None, None # Возвращаем пустые данные в случае ошибки
81
 
82
  # Преобразуем список данных в DataFrame
83
  df = pd.DataFrame(data_list)
 
105
  df_percentage = df[['№ локальной сметы', 'Наименование']].copy()
106
  df_percentage['Процент от общей суммы'] = ((df['ВСЕГО ПО СМЕТЕ'].iloc[:-1] / total_sum) * 100).round(2)
107
 
108
+ # Создание круговой диаграммы
109
  category_sums = {
110
  'Категория': ['Рабочие', 'Техника', 'Материалы', 'Перевозки', 'Оборудование'],
111
  'Сумма': [
 
120
  df_category_percentage = pd.DataFrame(category_sums)
121
  df_category_percentage['Процент от общей суммы'] = ((df_category_percentage['Сумма'] / total_sum) * 100).round(2)
122
 
123
+ # Создание словаря сопоставления категорий и цветов
124
+ color_map = {
125
+ 'Рабочие': '#DCEDFC',
126
+ 'Техника': '#94B4D4',
127
+ 'Материалы': '#3C47D6',
128
+ 'Перевозки': '#94B4D4',
129
+ 'Оборудование': '#0E86D4'
130
+ }
131
+
132
+ # Фильтрация категорий с процентом >=1%
133
+ filtered_df = df_category_percentage[df_category_percentage['Процент от общей суммы'] >= 1].reset_index(drop=True)
134
+
135
+ # Генерация списка цветов в соответствии с порядком категорий
136
+ colors = [color_map.get(category, '#FFFFFF') for category in filtered_df['Категория']]
137
+
138
+ # Сохраняем диаграмму в BytesIO с добавлением пустого пространства
139
+ fig, ax = plt.subplots(figsize=(7, 7)) # Увеличенный размер фигуры
140
+ ax.pie(
141
+ filtered_df['Сумма'],
142
+ labels=filtered_df['Категория'],
143
+ autopct='%1.2f%%',
144
+ startangle=90,
145
+ colors=colors, # Используем пользовательские цвета
146
+ labeldistance=1.1, # Расстояние до надписей
147
+ pctdistance=0.8 # Расстояние до процентных надписей
148
+ )
149
+ plt.title('')
150
+ plt.axis('equal') # Круговая диаграмма круглая по форме
151
+ plt.tight_layout() # Оптимизация расположения элементов
152
+
153
+ pie_chart = BytesIO()
154
+ plt.savefig(pie_chart, format='png', bbox_inches='tight') # bbox_inches='tight' для оптимизации
155
+ plt.close(fig)
156
+ pie_chart.seek(0)
157
 
158
  # Форматирование чисел с пробелами в качестве разделителей тысяч
159
  def format_number(x):
 
180
  df_percentage.to_excel(percentage_report_path, index=False)
181
  df_category_percentage.to_excel(category_report_path, index=False)
182
 
183
+ # Возвращаем форматированные DataFrame и диаграмму
184
+ return df_formatted, df_percentage_formatted, df_category_percentage_formatted, pie_chart, detailed_report_path, percentage_report_path, category_report_path
185
 
186
  # CSS для блокировки копирования текста
187
  custom_css = """
 
200
  gr.Markdown("### **AIGineer | ИИ УПРАВЛЕНИЕ СТРОИТЕЛЬСТВОМ**", elem_id="header")
201
  gr.Markdown("**На текущий момент система считает сметы в ценах от 2023**", elem_id="subheader")
202
 
203
+ # Загрузка файла (текст выравнивается по центру)
204
  with gr.Row():
205
  upload_button = gr.File(label="ЗАГРУЗИТЕ СМЕТУ В PDF", elem_id="upload")
206
 
 
212
  "% соотношение локальных смет",
213
  "Структура расходов по категориям"
214
  ],
215
+ label="ВЫБЕРИТЕ ОТЧЕТ"
216
  )
217
 
218
+ # Описание и поля отчета
219
+ description = gr.Markdown(visible=False)
220
+ preview_table = gr.Dataframe(visible=False)
221
+
222
  # Кнопка для получения отчета
223
  with gr.Row():
224
  get_report_button = gr.Button("Получить отчет")
225
 
 
 
 
226
  # Отображение отчета и кнопка скачивания
227
  with gr.Row():
228
  output_table = gr.Dataframe(visible=False)
229
+ output_image = gr.Image(type="pil", visible=False)
230
+
231
  with gr.Row():
232
  download_excel = gr.File(label="Скачать отчет", visible=False)
233
 
234
+ # Функция для обновления описания и полей отчета при выборе
235
+ def update_preview(selected_report):
236
+ if selected_report == "Детализированный бюджет":
237
+ description_text = "Отчет дает полное представление о том, как распределяются средства по каждому разделу сметной документации..."
238
+ preview_df = pd.DataFrame(columns=["№ локальной сметы", "Наименование", "Рабочие", "Техника", "Материалы", "Перевозки", "Оборудование", "ВСЕГО ПО СМЕТЕ"])
239
+ return gr.update(value=description_text, visible=True), gr.update(value=preview_df, visible=True)
240
+ elif selected_report == "% соотношение локальных смет":
241
+ description_text = "Важный инструмент для стратегического планирования, который помогает легко сравнивать между собой разделы проекта..."
242
+ preview_df = pd.DataFrame(columns=["№ локальной сметы", "Наименование", "Процент от общей суммы"])
243
+ return gr.update(value=description_text, visible=True), gr.update(value=preview_df, visible=True)
244
+ elif selected_report == "Структура расходов по категориям":
245
+ description_text = "Позволяет увидеть, как распределяются затраты по основным категориям..."
246
+ return gr.update(value=description_text, visible=True), gr.update(visible=False)
247
+ else:
248
+ return gr.update(visible=False), gr.update(visible=False)
249
+
250
+ # Связываем выбор отчета с обновлением описания и полей
251
+ report_selector.change(
252
+ update_preview,
253
+ inputs=report_selector,
254
+ outputs=[description, preview_table]
255
+ )
256
+
257
  # Функция обновления отчета
258
  def update_report(file, selected_report):
259
  if not file or not selected_report:
260
  return gr.update(visible=False), gr.update(visible=False), gr.update(visible=False)
261
 
262
  # Обрабатываем PDF и получаем данные
263
+ df_formatted, df_percentage_formatted, df_category_percentage_formatted, pie_chart, detailed_report_path, percentage_report_path, category_report_path = process_pdf(file.name)
264
 
265
  if selected_report == "Детализированный бюджет":
 
266
  return (
 
267
  gr.update(value=df_formatted, visible=True),
268
+ gr.update(visible=False),
269
  gr.update(value=detailed_report_path, visible=True, label="Скачать детализированный отчет")
270
  )
271
  elif selected_report == "% соотношение локальных смет":
 
272
  return (
 
273
  gr.update(value=df_percentage_formatted, visible=True),
274
+ gr.update(visible=False),
275
  gr.update(value=percentage_report_path, visible=True, label="Скачать процентное соотношение")
276
  )
277
  elif selected_report == "Структура расходов по категориям":
 
278
  return (
279
+ gr.update(visible=False),
280
+ gr.update(value=Image.open(pie_chart), visible=True),
281
  gr.update(value=category_report_path, visible=True, label="Скачать отчет по категориям")
282
  )
283
  else:
 
287
  get_report_button.click(
288
  update_report,
289
  inputs=[upload_button, report_selector],
290
+ outputs=[output_table, output_image, download_excel]
291
  )
292
 
293
  # Запуск приложения