""" Data import views (Excel, CSV, Transponders, VCH, etc.). """ from io import BytesIO from django.contrib import messages from django.contrib.auth.mixins import LoginRequiredMixin from django.http import HttpResponse from django.shortcuts import redirect from django.urls import reverse_lazy from django.views import View from django.views.generic import FormView import pandas as pd from ..forms import ( LoadCsvData, LoadExcelData, NewEventForm, UploadFileForm, UploadVchLoad, VchLinkForm, ) from ..mixins import FormMessageMixin from ..utils import ( add_satellite_list, compare_and_link_vch_load, fill_data_from_df, get_points_from_csv, get_vch_load_from_html, kub_report, ) from mapsapp.utils import parse_transponders_from_xml class AddSatellitesView(LoginRequiredMixin, View): """View for adding satellites to the database.""" def get(self, request): add_satellite_list() return redirect("mainapp:source_list") class AddTranspondersView(LoginRequiredMixin, FormMessageMixin, FormView): """View for uploading and parsing transponder data from XML.""" template_name = "mainapp/transponders_upload.html" form_class = UploadFileForm success_message = "Файл успешно обработан" error_message = "Форма заполнена некорректно" def form_valid(self, form): uploaded_file = self.request.FILES["file"] try: content = uploaded_file.read() # Передаем текущего пользователя в функцию парсинга parse_transponders_from_xml(BytesIO(content), self.request.user.customuser) except ValueError as e: messages.error(self.request, f"Ошибка при чтении таблиц: {e}") return redirect("mainapp:add_trans") except Exception as e: messages.error(self.request, f"Неизвестная ошибка: {e}") return redirect("mainapp:add_trans") return super().form_valid(form) def get_success_url(self): return reverse_lazy("mainapp:add_trans") class LoadExcelDataView(LoginRequiredMixin, FormMessageMixin, FormView): """View for loading data from Excel files.""" template_name = "mainapp/add_data_from_excel.html" form_class = LoadExcelData error_message = "Форма заполнена некорректно" def form_valid(self, form): uploaded_file = self.request.FILES["file"] selected_sat = form.cleaned_data["sat_choice"] number = form.cleaned_data["number_input"] is_automatic = form.cleaned_data.get("is_automatic", False) try: import io df = pd.read_excel(io.BytesIO(uploaded_file.read())) if number > 0: df = df.head(number) result = fill_data_from_df(df, selected_sat, self.request.user.customuser, is_automatic) # Формируем сообщение об успехе if is_automatic: success_msg = f"Данные успешно загружены как автоматические! Добавлено точек: {result['added']}" else: success_msg = f"Данные успешно загружены! Создано источников: {result['new_sources']}, добавлено точек: {result['added']}" if result['skipped'] > 0: success_msg += f", пропущено дубликатов: {result['skipped']}" messages.success(self.request, success_msg) # Показываем ошибки, если они есть if result['errors']: error_count = len(result['errors']) messages.warning( self.request, f"Обнаружено ошибок: {error_count}. Первые ошибки: " + "; ".join(result['errors'][:5]) ) except Exception as e: messages.error(self.request, f"Ошибка при обработке файла: {str(e)}") return redirect("mainapp:load_excel_data") def get_success_url(self): return reverse_lazy("mainapp:load_excel_data") class LoadCsvDataView(LoginRequiredMixin, FormMessageMixin, FormView): """View for loading data from CSV files.""" template_name = "mainapp/add_data_from_csv.html" form_class = LoadCsvData success_message = "Данные успешно загружены!" error_message = "Форма заполнена некорректно" def form_valid(self, form): uploaded_file = self.request.FILES["file"] is_automatic = form.cleaned_data.get("is_automatic", False) try: content = uploaded_file.read() if isinstance(content, bytes): content = content.decode("utf-8") result = get_points_from_csv(content, self.request.user.customuser, is_automatic) # Формируем сообщение об успехе if is_automatic: success_msg = f"Данные успешно загружены как автоматические! Добавлено точек: {result['added']}" else: success_msg = f"Данные успешно загружены! Создано источников: {result['new_sources']}, добавлено точек: {result['added']}" if result['skipped'] > 0: success_msg += f", пропущено дубликатов: {result['skipped']}" messages.success(self.request, success_msg) # Показываем ошибки, если они есть if result['errors']: error_count = len(result['errors']) messages.warning( self.request, f"Обнаружено ошибок: {error_count}. Первые ошибки: " + "; ".join(result['errors'][:5]) ) except Exception as e: messages.error(self.request, f"Ошибка при обработке файла: {str(e)}") return redirect("mainapp:load_csv_data") return super().form_valid(form) def get_success_url(self): return reverse_lazy("mainapp:load_csv_data") class UploadVchLoadView(LoginRequiredMixin, FormMessageMixin, FormView): """View for uploading VCH load data from HTML files.""" template_name = "mainapp/upload_html.html" form_class = UploadVchLoad success_message = "Файл успешно обработан" error_message = "Форма заполнена некорректно" def form_valid(self, form): selected_sat = form.cleaned_data["sat_choice"] uploaded_file = self.request.FILES["file"] try: get_vch_load_from_html(uploaded_file, selected_sat) except ValueError as e: messages.error(self.request, f"Ошибка при чтении таблиц: {e}") return redirect("mainapp:vch_load") except Exception as e: messages.error(self.request, f"Неизвестная ошибка: {e}") return redirect("mainapp:vch_load") return super().form_valid(form) def get_success_url(self): return reverse_lazy("mainapp:vch_load") class LinkVchSigmaView(LoginRequiredMixin, FormView): """View for linking VCH data with Sigma parameters.""" template_name = "mainapp/link_vch.html" form_class = VchLinkForm def form_valid(self, form): # value1 is no longer used - frequency tolerance is determined automatically freq_range = form.cleaned_data["value2"] sat_id = form.cleaned_data["sat_choice"] # Pass 0 for eps_freq and ku_range as they are not used count_all, link_count = compare_and_link_vch_load(sat_id, 0, freq_range, 0) messages.success( self.request, f"Привязано {link_count} из {count_all} объектов" ) return redirect("mainapp:link_vch_sigma") def form_invalid(self, form): return self.render_to_response(self.get_context_data(form=form)) class ProcessKubsatView(LoginRequiredMixin, FormMessageMixin, FormView): """View for processing Kubsat event data.""" template_name = "mainapp/process_kubsat.html" form_class = NewEventForm error_message = "Форма заполнена некорректно" def form_valid(self, form): uploaded_file = self.request.FILES["file"] try: content = uploaded_file.read() df = kub_report(BytesIO(content)) output = BytesIO() with pd.ExcelWriter(output, engine="openpyxl") as writer: df.to_excel(writer, index=False, sheet_name="Результат") output.seek(0) response = HttpResponse( output.getvalue(), content_type="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", ) response["Content-Disposition"] = ( 'attachment; filename="kubsat_report.xlsx"' ) messages.success(self.request, "Событие успешно обработано!") return response except Exception as e: messages.error(self.request, f"Ошибка при обработке файла: {str(e)}") return redirect("mainapp:kubsat_excel")