using System; using System.Data; using System.Data.SQLite; using System.Windows.Forms; using Электронная_Фармация.Classes; namespace Электронная_Фармация.Forms { public partial class FConsignees : Form { public string SelectedConsigneeNameAfterSave { get; private set; } = string.Empty; public FConsignees() { InitializeComponent(); } private void FConsignees_Load(object sender, EventArgs e) { UiThemeHelper.ApplyToControlTree(this); showMeContentFromConsigneesTable(); } void showMeContentFromConsigneesTable() { using (SQLiteConnection conConsignees = new SQLiteConnection(AppConfig.SqliteConnectionString)) { string selectFromConsignees = @" select [idConsignees] as [Id], [codeConsignees] as [Код], [ConsigneesName] as [Наименование], [ConsigneesAddress] as [Адрес], ifnull([LocationId], '') as [Location ID], [ConsigneesUseAsDefault] as [По умолчанию] from [Consignees] order by [ConsigneesUseAsDefault] desc, [ConsigneesName]"; try { conConsignees.Open(); SQLiteCommand cmdShowConsigneesList = new SQLiteCommand(selectFromConsignees, conConsignees); DataTable tableConsignees = new DataTable(); SQLiteDataAdapter daConsigneeList = new SQLiteDataAdapter(cmdShowConsigneesList); daConsigneeList.Fill(tableConsignees); dgvConsignees.DataSource = tableConsignees; if (dgvConsignees.Columns.Contains("Id")) { dgvConsignees.Columns["Id"].Visible = false; } foreach (DataGridViewColumn column in dgvConsignees.Columns) { column.ReadOnly = column.Name != "Location ID" && column.Name != "Адрес"; } } catch (Exception ex) { MessageBox.Show($"Возникла ошибка при заполнении данных о грузополучателях.\nТекст ошибки:\n{ex}", "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Error); } } } private void txtInteractiveShowMeConsignees_KeyPress(object sender, KeyPressEventArgs e) { if (e.KeyChar == (char)Keys.Enter) { if (dgvConsignees.Rows.Count > 0 && dgvConsignees.DataSource is DataTable table) { table.DefaultView.RowFilter = $"[Наименование] like '%{txtInteractiveShowMeConsignees.Text.Replace("'", "''")}%'"; if (dgvConsignees.Rows.Count == 0) { showMeContentFromConsigneesTable(); } } else { showMeContentFromConsigneesTable(); } txtInteractiveShowMeConsignees.Text = string.Empty; } } private void btnSave_Click(object sender, EventArgs e) { if (!(dgvConsignees.DataSource is DataTable table)) { return; } dgvConsignees.EndEdit(); // Кто должен стать активной аптекой после сохранения. // По вашему ТЗ: "аптека выбранная в этом окне" => текущая выделенная строка. var selectedName = dgvConsignees.CurrentRow?.Cells["Наименование"]?.Value?.ToString()?.Trim() ?? string.Empty; SelectedConsigneeNameAfterSave = selectedName; using (var connection = new SQLiteConnection(AppConfig.SqliteConnectionString)) { connection.Open(); using (var tx = connection.BeginTransaction()) { foreach (DataRow row in table.Rows) { if (row.RowState == DataRowState.Unchanged) { continue; } using (var cmd = new SQLiteCommand( @"UPDATE Consignees SET ConsigneesAddress = @address, LocationId = @locationId WHERE idConsignees = @id", connection, tx)) { cmd.Parameters.AddWithValue("@address", row["Адрес"]?.ToString() ?? string.Empty); cmd.Parameters.AddWithValue("@locationId", row["Location ID"]?.ToString()?.Trim() ?? string.Empty); cmd.Parameters.AddWithValue("@id", Convert.ToInt64(row["Id"])); cmd.ExecuteNonQuery(); } } tx.Commit(); } } table.AcceptChanges(); ToastNotification.ShowSuccess("Грузополучатели сохранены"); if (!string.IsNullOrWhiteSpace(selectedName)) { ConsigneeHelper.SetActiveConsignee(selectedName); } DialogResult = DialogResult.OK; Close(); } private void btnAdd_Click(object sender, EventArgs e) { using (var dialog = new Form()) { dialog.Text = "Новая аптека"; dialog.FormBorderStyle = FormBorderStyle.FixedDialog; dialog.StartPosition = FormStartPosition.CenterParent; // Немного увеличиваем высоту/ширину на случай DPI/шрифтов. dialog.ClientSize = new System.Drawing.Size(480, 310); dialog.MaximizeBox = false; dialog.MinimizeBox = false; dialog.ShowInTaskbar = false; var lblName = new Label { Text = "Наименование", Left = 16, Top = 16, AutoSize = true }; var txtName = new TextBox { Left = 16, Top = 42, Width = 440, Height = 28 }; var lblAddress = new Label { Text = "Адрес", Left = 16, Top = 82, AutoSize = true }; var txtAddress = new TextBox { Left = 16, Top = 108, Width = 440, Height = 28 }; var lblLocation = new Label { Text = "Location ID", Left = 16, Top = 148, AutoSize = true }; var txtLocation = new TextBox { Left = 16, Top = 174, Width = 440, Height = 28 }; var btnOk = new Elfisa.UI.Controls.ModernButton { Text = "Добавить", DialogResult = DialogResult.OK }; var btnCancel = new Elfisa.UI.Controls.ModernButton { Text = "Отмена", DialogResult = DialogResult.Cancel }; dialog.Controls.AddRange(new Control[] { lblName, txtName, lblAddress, txtAddress, lblLocation, txtLocation, btnOk, btnCancel }); dialog.AcceptButton = btnOk; dialog.CancelButton = btnCancel; UiThemeHelper.ApplyToControlTree(dialog); btnOk.Padding = new Padding(12, 4, 12, 4); btnCancel.Padding = new Padding(12, 4, 12, 4); Elfisa.UI.Controls.ModernButtonStyles.FitToText(btnOk, 36); Elfisa.UI.Controls.ModernButtonStyles.FitToText(btnCancel, 36); btnOk.Height = 36; btnCancel.Height = 36; const int padding = 16; const int gap = 10; // Минимально гарантируем ширину, чтобы обе кнопки поместились. var requiredWidth = btnOk.Width + btnCancel.Width + gap + padding * 2; if (dialog.ClientSize.Width < requiredWidth) { dialog.ClientSize = new System.Drawing.Size(requiredWidth, dialog.ClientSize.Height); } // Всегда зажимаем в границы формы после вычисления ширины ModernButton'ов. btnCancel.Left = Math.Max(padding, dialog.ClientSize.Width - btnCancel.Width - padding); btnCancel.Top = dialog.ClientSize.Height - btnCancel.Height - padding; btnOk.Left = Math.Max(padding, btnCancel.Left - btnOk.Width - gap); btnOk.Top = btnCancel.Top; if (dialog.ShowDialog(this) != DialogResult.OK) { return; } var name = (txtName.Text ?? string.Empty).Trim(); var address = (txtAddress.Text ?? string.Empty).Trim(); var locationId = (txtLocation.Text ?? string.Empty).Trim(); if (string.IsNullOrWhiteSpace(name)) { UiDialogs.ShowError("Укажите наименование аптеки.", "Грузополучатели", this); return; } using (var connection = new SQLiteConnection(AppConfig.SqliteConnectionString)) { connection.Open(); int nextCode = 1; using (var codeCmd = new SQLiteCommand("SELECT ifnull(MAX(codeConsignees), 0) + 1 FROM Consignees", connection)) { nextCode = Convert.ToInt32(codeCmd.ExecuteScalar()); } using (var insert = new SQLiteCommand( @"INSERT INTO Consignees (codeConsignees, ConsigneesName, ConsigneesAddress, ConsigneesUseAsDefault, LocationId) VALUES (@code, @name, @address, 0, @locationId)", connection)) { insert.Parameters.AddWithValue("@code", nextCode); insert.Parameters.AddWithValue("@name", name); insert.Parameters.AddWithValue("@address", address); insert.Parameters.AddWithValue("@locationId", locationId); insert.ExecuteNonQuery(); } } ToastNotification.ShowSuccess("Аптека добавлена"); showMeContentFromConsigneesTable(); } } private void btnSetDefault_Click(object sender, EventArgs e) { if (dgvConsignees.CurrentRow == null) { UiDialogs.ShowInfo("Выберите аптеку в списке.", "Грузополучатели", this); return; } var name = dgvConsignees.CurrentRow.Cells["Наименование"]?.Value?.ToString(); if (string.IsNullOrWhiteSpace(name)) { return; } ConsigneeHelper.SetActiveConsignee(name); ToastNotification.ShowSuccess($"Аптека по умолчанию: {name}"); showMeContentFromConsigneesTable(); } } }