ReportsForm.cs 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210
  1. using System.Data;
  2. using Npgsql;
  3. using TravelAgencyWinForms.Data;
  4. using TravelAgencyWinForms.Models;
  5. using TravelAgencyWinForms.Utils;
  6. namespace TravelAgencyWinForms.Forms;
  7. public partial class ReportsForm : Form
  8. {
  9. private readonly List<Button> _reportButtons = new();
  10. private DataTable _currentTable = new();
  11. public ReportsForm()
  12. {
  13. InitializeComponent();
  14. ApplyStyle();
  15. LoadIllustration();
  16. RegisterButtons();
  17. Load += (_, _) => LoadBookingsReport();
  18. }
  19. private void ApplyStyle()
  20. {
  21. AppTheme.ApplyForm(this);
  22. headerPanel.BackColor = AppTheme.Surface;
  23. titleLabel.ForeColor = AppTheme.Text;
  24. subtitleLabel.ForeColor = AppTheme.Muted;
  25. AppTheme.StyleGrid(reportGrid);
  26. AppTheme.StyleSelectedButton(bookingsButton);
  27. AppTheme.StyleSecondaryButton(scheduleButton);
  28. AppTheme.StyleSecondaryButton(overdueButton);
  29. AppTheme.StyleSecondaryButton(employeesButton);
  30. employeesButton.Visible = CurrentUser.IsAdmin;
  31. }
  32. private void LoadIllustration()
  33. {
  34. var image = AppTheme.LoadImage("booking_report.png");
  35. if (image != null)
  36. reportPictureBox.Image = image;
  37. var emptyImage = AppTheme.LoadImage("empty_results.png");
  38. if (emptyImage != null)
  39. emptyPictureBox.Image = emptyImage;
  40. }
  41. private void RegisterButtons()
  42. {
  43. _reportButtons.Clear();
  44. _reportButtons.Add(scheduleButton);
  45. _reportButtons.Add(bookingsButton);
  46. _reportButtons.Add(overdueButton);
  47. if (CurrentUser.IsAdmin)
  48. _reportButtons.Add(employeesButton);
  49. }
  50. private void ScheduleButton_Click(object? sender, EventArgs e)
  51. {
  52. SetActiveButton(scheduleButton);
  53. LoadScheduleReport();
  54. }
  55. private void BookingsButton_Click(object? sender, EventArgs e)
  56. {
  57. SetActiveButton(bookingsButton);
  58. LoadBookingsReport();
  59. }
  60. private void OverdueButton_Click(object? sender, EventArgs e)
  61. {
  62. SetActiveButton(overdueButton);
  63. LoadOverdueReport();
  64. }
  65. private void EmployeesButton_Click(object? sender, EventArgs e)
  66. {
  67. SetActiveButton(employeesButton);
  68. LoadEmployeesReport();
  69. }
  70. private void SetActiveButton(Button selectedButton)
  71. {
  72. foreach (var button in _reportButtons)
  73. {
  74. if (button == selectedButton)
  75. AppTheme.StyleSelectedButton(button);
  76. else
  77. AppTheme.StyleSecondaryButton(button);
  78. }
  79. }
  80. private void LoadScheduleReport()
  81. {
  82. titleLabel.Text = "Расписание туров";
  83. subtitleLabel.Text = "График выездов и длительность поездок";
  84. BindReport(Db.Query(@"
  85. SELECT
  86. tour_name AS ""Тур"",
  87. cities AS ""Города"",
  88. start_date AS ""Дата начала"",
  89. end_date AS ""Дата окончания"",
  90. duration_days AS duration_days,
  91. price AS ""Стоимость""
  92. FROM v_tour_schedule
  93. ORDER BY start_date, tour_name;"));
  94. }
  95. private void LoadBookingsReport()
  96. {
  97. titleLabel.Text = CurrentUser.IsAdmin ? "Бронирования" : "Мои бронирования";
  98. subtitleLabel.Text = CurrentUser.IsAdmin ? "Полный список оформленных бронирований" : "Бронирования, связанные с текущим клиентом";
  99. var table = CurrentUser.IsAdmin
  100. ? Db.Query("SELECT * FROM v_booking_details ORDER BY booking_date DESC, booking_id DESC;")
  101. : Db.Query("SELECT * FROM v_booking_details WHERE client_id = @client_id ORDER BY booking_date DESC, booking_id DESC;", new NpgsqlParameter("client_id", CurrentUser.ClientId ?? -1));
  102. BindReport(table);
  103. }
  104. private void LoadOverdueReport()
  105. {
  106. titleLabel.Text = CurrentUser.IsAdmin ? "Просроченные бронирования" : "Мои просроченные бронирования";
  107. subtitleLabel.Text = "Туры с прошедшей датой начала и незавершённым статусом";
  108. var table = CurrentUser.IsAdmin
  109. ? Db.Query("SELECT * FROM v_overdue_client_bookings ORDER BY days_overdue DESC, booking_id DESC;")
  110. : Db.Query("SELECT * FROM v_overdue_client_bookings WHERE client_id = @client_id ORDER BY days_overdue DESC, booking_id DESC;", new NpgsqlParameter("client_id", CurrentUser.ClientId ?? -1));
  111. BindReport(table);
  112. }
  113. private void LoadEmployeesReport()
  114. {
  115. titleLabel.Text = "Сотрудники";
  116. subtitleLabel.Text = "Возраст и основные сведения по сотрудникам";
  117. BindReport(Db.Query("SELECT * FROM v_employee_details ORDER BY employee_name;"));
  118. }
  119. private void BindReport(DataTable table)
  120. {
  121. _currentTable = table;
  122. reportGrid.DataSource = _currentTable;
  123. UpdateEmptyState(_currentTable.Rows.Count == 0);
  124. PresentationHelper.ApplyHeaders(reportGrid);
  125. PresentationHelper.HideReportColumns(reportGrid);
  126. HideCalculatedColumns();
  127. UpdateCalculatedPanel();
  128. if (reportGrid.Rows.Count > 0 && reportGrid.Columns.Cast<DataGridViewColumn>().Any(c => c.Visible))
  129. {
  130. var firstVisible = reportGrid.Columns.Cast<DataGridViewColumn>().First(c => c.Visible);
  131. reportGrid.CurrentCell = reportGrid.Rows[0].Cells[firstVisible.Index];
  132. }
  133. }
  134. private void UpdateEmptyState(bool isEmpty)
  135. {
  136. reportGrid.Visible = !isEmpty;
  137. emptyPanel.Visible = isEmpty;
  138. }
  139. private void HideCalculatedColumns()
  140. {
  141. foreach (DataGridViewColumn column in reportGrid.Columns)
  142. if (CalculatedFields.IsCalculated(column.Name))
  143. column.Visible = false;
  144. }
  145. private void UpdateCalculatedPanel()
  146. {
  147. calculatedPanel.Controls.Clear();
  148. var calculatedColumns = CalculatedFields.GetColumns(_currentTable);
  149. if (calculatedColumns.Count == 0)
  150. {
  151. calculatedPanel.Visible = false;
  152. return;
  153. }
  154. calculatedPanel.Visible = true;
  155. var selectedRow = GetSelectedRow();
  156. foreach (var columnName in calculatedColumns)
  157. {
  158. var value = "—";
  159. if (selectedRow != null && selectedRow.Table.Columns.Contains(columnName))
  160. value = CalculatedFields.FormatValue(columnName, selectedRow[columnName]);
  161. calculatedPanel.Controls.Add(AppTheme.CreateCard(CalculatedFields.GetLabel(columnName), value));
  162. }
  163. }
  164. private DataRow? GetSelectedRow()
  165. {
  166. if (reportGrid.CurrentRow?.DataBoundItem is DataRowView view)
  167. return view.Row;
  168. return null;
  169. }
  170. private void ReportGrid_SelectionChanged(object? sender, EventArgs e)
  171. {
  172. UpdateCalculatedPanel();
  173. }
  174. }