using CPM; using DAL; using MLL; using System; using System.Drawing; using System.IO; using System.Windows.Forms; namespace UI { public class BoletoCadastroPanel : FormularioModelo { // ── MODELO ──────────────────────────────────────────────────────────── private ModeloBoletos _modelo = new ModeloBoletos(); // ── SEÇÃO 1: Identificação ──────────────────────────────────────────── private LV_TEXTBOX1 txtCodigo = null!; private LV_TEXTBOX1 txtNumero = null!; private LV_TEXTBOX1 txtNossoNumero = null!; private LV_TEXTBOX1 txtChaveBoleto = null!; private LV_TEXTBOX1 txtLinhaDigitavel = null!; // ── SEÇÃO 2: Datas e Valores ────────────────────────────────────────── private DateTimePicker dtpEmitido = null!; private DateTimePicker dtpVence = null!; private DateTimePicker dtpPagamento = null!; private LV_TEXTBOX1 txtValor = null!; private LV_TEXTBOX1 txtVlPago = null!; private LV_TEXTBOX1 txtVlMulta = null!; private LV_TEXTBOX1 txtVlDesconto = null!; // ── SEÇÃO 3: Sacado e Conta ─────────────────────────────────────────── private LV_TEXTBOX1 txtSacado = null!; private LV_COMBOBOX cmbConta = null!; private LV_COMBOBOX cmbCodConta = null!; // ── SEÇÃO 4: Status e Flags ─────────────────────────────────────────── private LV_COMBOBOX cmbStatus = null!; private CheckBox chkPago = null!; private CheckBox chkAceite = null!; private CheckBox chkImpresso = null!; private CheckBox chkImportado = null!; // ── SEÇÃO 5: Arquivo ────────────────────────────────────────────────── private LV_TEXTBOX1 txtArquivoNome = null!; private LV_TEXTBOX1 txtArquivoCaminho = null!; private LV_COMBOBOX cmbArquivoTipo = null!; private Button btnAnexar = null!; private Button btnVisualizarArq = null!; private Label lblArquivoInfo = null!; // ── SEÇÃO 6: Observação ─────────────────────────────────────────────── private LV_TEXTBOX1 txtObservacao = null!; // ── BOTÃO EXTRA DA TOOLBAR ──────────────────────────────────────────── private Button btnBaixar = null!; // ── CONSTRUTOR ──────────────────────────────────────────────────────── public BoletoCadastroPanel() { Titulo = "Cadastro de Boletos"; BuildToolbarExtra(); BuildForm(); SetEstadoInicial(); } // ── TOOLBAR EXTRA ───────────────────────────────────────────────────── private void BuildToolbarExtra() { btnBaixar = CreateToolbarButton("Baixar", Color.FromArgb(99, 102, 241)); btnBaixar.Click += (s, e) => OnBaixarBoleto(); AddToolbarButton(btnBaixar); } // ── CONSTRUÇÃO DO FORMULÁRIO ────────────────────────────────────────── private void BuildForm() { content.Height = 1050; // ── SEÇÃO 1: Identificação ───────────────────────────────────── content.Controls.Add(CreateSectionHeader("Identificação", 20)); txtCodigo = AddInput(content, "Código", 20, 55, 120, 32, readOnly: true); txtNumero = AddInput(content, "Número do Boleto", 155, 55, 200, 32); txtNossoNumero = AddInput(content, "Nosso Número", 370, 55, 200, 32); txtChaveBoleto = AddInput(content, "Chave do Boleto", 585, 55, 235, 32); txtLinhaDigitavel = AddInput(content, "Linha Digitável / Código de Barras", 20, 110, 800, 32); // ── SEÇÃO 2: Datas e Valores ─────────────────────────────────── content.Controls.Add(CreateSectionHeader("Datas e Valores", 165)); dtpEmitido = BuildDatePicker("Data de Emissão", 20, 200); dtpVence = BuildDatePicker("Data de Vencimento", 210, 200); dtpPagamento = BuildDatePicker("Data de Pagamento", 400, 200); dtpPagamento.Enabled = false; txtValor = AddInput(content, "Valor (R$)", 600, 200, 140, 32); txtVlPago = AddInput(content, "Valor Pago (R$)", 20, 260, 140, 32); txtVlMulta = AddInput(content, "Multa (R$)", 175, 260, 140, 32); txtVlDesconto = AddInput(content, "Desconto (R$)", 330, 260, 140, 32); var lblVFLabel = new Label { Text = "Valor Final (R$)", Location = new Point(490, 260), Font = new Font("Segoe UI", 7.5f, FontStyle.Bold), ForeColor = AccentBlue, AutoSize = true }; var lblVFValor = new Label { Name = "lblValorFinal", Text = "R$ 0,00", Location = new Point(490, 276), Font = new Font("Segoe UI", 10f, FontStyle.Bold), ForeColor = AccentBlue, AutoSize = true }; content.Controls.AddRange(new Control[] { lblVFLabel, lblVFValor }); txtValor.Leave += (s, e) => AtualizarValorFinal(); txtVlMulta.Leave += (s, e) => AtualizarValorFinal(); txtVlDesconto.Leave += (s, e) => AtualizarValorFinal(); // ── SEÇÃO 3: Sacado e Conta ──────────────────────────────────── content.Controls.Add(CreateSectionHeader("Sacado e Conta", 315)); txtSacado = AddInput(content, "Sacado", 20, 350, 430, 32); content.Controls.Add(new Label { Text = "Conta", Location = new Point(465, 350), Font = new Font("Segoe UI", 7.5f, FontStyle.Bold), ForeColor = TextDark, AutoSize = true }); cmbConta = new LV_COMBOBOX { Location = new Point(465, 366), Size = new Size(200, 32), Font = new Font("Segoe UI", 9f), DropDownStyle = ComboBoxStyle.DropDownList, BackColor = Color.White, }; content.Controls.Add(new Label { Text = "Cód. Conta", Location = new Point(680, 350), Font = new Font("Segoe UI", 7.5f, FontStyle.Bold), ForeColor = TextDark, AutoSize = true }); cmbCodConta = new LV_COMBOBOX { Location = new Point(680, 366), Size = new Size(150, 32), Font = new Font("Segoe UI", 9f), DropDownStyle = ComboBoxStyle.DropDownList, BackColor = Color.White, }; content.Controls.AddRange(new Control[] { cmbConta, cmbCodConta }); // ── SEÇÃO 4: Status e Flags ──────────────────────────────────── content.Controls.Add(CreateSectionHeader("Status e Flags", 415)); content.Controls.Add(new Label { Text = "Status", Location = new Point(20, 450), Font = new Font("Segoe UI", 7.5f, FontStyle.Bold), ForeColor = TextDark, AutoSize = true }); cmbStatus = new LV_COMBOBOX { Location = new Point(20, 466), Size = new Size(160, 32), Font = new Font("Segoe UI", 9f), DropDownStyle = ComboBoxStyle.DropDownList, BackColor = Color.White, }; cmbStatus.Items.AddRange(new object[] { "ABERTO", "PAGO", "VENCIDO", "CANCELADO", "BAIXADO" }); cmbStatus.SelectedIndex = 0; cmbStatus.SelectedIndexChanged += (s, e) => OnStatusChanged(); content.Controls.Add(cmbStatus); chkPago = CreateCheckBox("Pago", 200, 470); chkAceite = CreateCheckBox("Aceite", 300, 470); chkImpresso = CreateCheckBox("Impresso", 400, 470); chkImportado = CreateCheckBox("Importado", 510, 470); chkPago.CheckedChanged += (s, e) => { dtpPagamento.Enabled = chkPago.Checked; if (chkPago.Checked && cmbStatus.SelectedItem?.ToString() != "PAGO") cmbStatus.SelectedItem = "PAGO"; }; content.Controls.AddRange(new Control[] { chkPago, chkAceite, chkImpresso, chkImportado }); // ── SEÇÃO 5: Arquivo ─────────────────────────────────────────── content.Controls.Add(CreateSectionHeader("Arquivo Anexo (XML / PDF)", 510)); content.Controls.Add(new Label { Text = "Tipo", Location = new Point(20, 545), Font = new Font("Segoe UI", 7.5f, FontStyle.Bold), ForeColor = TextDark, AutoSize = true }); cmbArquivoTipo = new LV_COMBOBOX { Location = new Point(20, 561), Size = new Size(80, 32), Font = new Font("Segoe UI", 9f), DropDownStyle = ComboBoxStyle.DropDownList, BackColor = Color.White, }; cmbArquivoTipo.Items.AddRange(new object[] { "", "XML", "PDF" }); cmbArquivoTipo.SelectedIndex = 0; content.Controls.Add(cmbArquivoTipo); txtArquivoNome = AddInput(content, "Nome do Arquivo", 115, 545, 220, 32, readOnly: true); txtArquivoCaminho = AddInput(content, "Caminho em Disco", 350, 545, 340, 32, readOnly: true); btnAnexar = new Button { Text = "📎 Anexar", Location = new Point(705, 561), Size = new Size(95, 32), BackColor = Color.FromArgb(100, 116, 139), ForeColor = Color.White, Font = new Font("Segoe UI Semibold", 8.5f), Cursor = Cursors.Hand, }; btnAnexar.FlatAppearance.BorderSize = 0; btnAnexar.Click += (s, e) => OnAnexarArquivo(); btnVisualizarArq = new Button { Text = "👁 Abrir", Location = new Point(705, 599), Size = new Size(95, 28), BackColor = AccentBlue, ForeColor = Color.White, Font = new Font("Segoe UI Semibold", 8f), Cursor = Cursors.Hand, Enabled = false }; btnVisualizarArq.FlatAppearance.BorderSize = 0; btnVisualizarArq.Click += (s, e) => OnAbrirArquivo(); lblArquivoInfo = new Label { Text = "Nenhum arquivo anexado.", Location = new Point(20, 603), Font = new Font("Segoe UI", 8f, FontStyle.Italic), ForeColor = Color.Gray, AutoSize = true }; content.Controls.AddRange(new Control[] { btnAnexar, btnVisualizarArq, lblArquivoInfo }); // ── SEÇÃO 6: Observação ──────────────────────────────────────── content.Controls.Add(CreateSectionHeader("Observação", 640)); content.Controls.Add(new Label { Text = "Observação", Location = new Point(20, 675), Font = new Font("Segoe UI", 7.5f, FontStyle.Bold), ForeColor = TextDark, AutoSize = true }); txtObservacao = new LV_TEXTBOX1 { Location = new Point(20, 691), Size = new Size(830, 80), BorderColor = BorderColor, BorderFocusColor = AccentBlue, Multiline = true }; content.Controls.Add(txtObservacao); } // ── HELPER: DateTimePicker padronizado ──────────────────────────────── private DateTimePicker BuildDatePicker(string label, int x, int y) { content.Controls.Add(new Label { Text = label, Location = new Point(x, y), Font = new Font("Segoe UI", 7.5f, FontStyle.Bold), ForeColor = TextDark, AutoSize = true }); var dtp = new DateTimePicker { Location = new Point(x, y + 16), Size = new Size(175, 32), Format = DateTimePickerFormat.Short, Font = new Font("Segoe UI", 9f) }; content.Controls.Add(dtp); return dtp; } // ── VALOR FINAL ─────────────────────────────────────────────────────── private void AtualizarValorFinal() { decimal valor = ParseDecimal(txtValor.Text); decimal multa = ParseDecimal(txtVlMulta.Text); decimal desconto = ParseDecimal(txtVlDesconto.Text); decimal final = valor + multa - desconto; var lbl = content.Controls["lblValorFinal"] as Label; if (lbl != null) { lbl.Text = final.ToString("C2"); lbl.ForeColor = final < 0 ? Color.FromArgb(239, 68, 68) : AccentBlue; } } private static decimal ParseDecimal(string text) { text = text.Replace("R$", "").Replace(".", "").Replace(",", ".").Trim(); return decimal.TryParse(text, System.Globalization.NumberStyles.Any, System.Globalization.CultureInfo.InvariantCulture, out var v) ? v : 0m; } // ── STATUS CHANGED ──────────────────────────────────────────────────── private void OnStatusChanged() { var status = cmbStatus.SelectedItem?.ToString(); if (status == "PAGO" && !chkPago.Checked) chkPago.Checked = true; dtpPagamento.Enabled = status == "PAGO"; } // ── ARQUIVO ─────────────────────────────────────────────────────────── private void OnAnexarArquivo() { using var dlg = new OpenFileDialog { Title = "Selecionar Arquivo do Boleto", Filter = "Arquivos Suportados (*.xml;*.pdf)|*.xml;*.pdf|XML|*.xml|PDF|*.pdf" }; if (dlg.ShowDialog() != DialogResult.OK) return; var caminho = dlg.FileName; var nome = Path.GetFileName(caminho); var ext = Path.GetExtension(caminho).TrimStart('.').ToUpper(); txtArquivoNome.Text = nome; txtArquivoCaminho.Text = caminho; cmbArquivoTipo.Text = ext; _modelo.ARQUIVO_DADOS = File.ReadAllBytes(caminho); lblArquivoInfo.Text = $"✔ {nome} ({new FileInfo(caminho).Length / 1024} KB)"; lblArquivoInfo.ForeColor = Color.FromArgb(34, 197, 94); btnVisualizarArq.Enabled = true; } private void OnAbrirArquivo() { var caminho = txtArquivoCaminho.Text; if (!string.IsNullOrEmpty(caminho) && File.Exists(caminho)) { System.Diagnostics.Process.Start( new System.Diagnostics.ProcessStartInfo { FileName = caminho, UseShellExecute = true }); return; } // Sem caminho em disco — reconstrói do binário para temp if (_modelo.ARQUIVO_DADOS != null && _modelo.ARQUIVO_DADOS.Length > 0) { var ext = string.IsNullOrEmpty(cmbArquivoTipo.Text) ? "tmp" : cmbArquivoTipo.Text.ToLower(); var temp = Path.Combine(Path.GetTempPath(), $"boleto_{_modelo.ID_BOLETO}.{ext}"); File.WriteAllBytes(temp, _modelo.ARQUIVO_DADOS); System.Diagnostics.Process.Start( new System.Diagnostics.ProcessStartInfo { FileName = temp, UseShellExecute = true }); } else { MessageBox.Show("Nenhum arquivo disponível para visualização.", "Aviso", MessageBoxButtons.OK, MessageBoxIcon.Warning); } } // ── BAIXAR BOLETO ───────────────────────────────────────────────────── private void OnBaixarBoleto() { var chave = txtChaveBoleto.Text.Trim(); var linha = txtLinhaDigitavel.Text.Trim(); var numero = txtNumero.Text.Trim(); if (string.IsNullOrEmpty(chave) && string.IsNullOrEmpty(linha) && string.IsNullOrEmpty(numero)) { MessageBox.Show( "Informe a Chave do Boleto, a Linha Digitável ou o Número para realizar a baixa.", "Atenção", MessageBoxButtons.OK, MessageBoxIcon.Warning); return; } // TODO: implementar integração bancária // Fluxo sugerido: // 1. BLLBoletos.BaixarBoleto(chave / linha / numero, _cx) // 2. BLL aciona API do banco escolhido // 3. Retorna status: BAIXADO | PAGO | ERRO // 4. Atualiza _modelo e recarrega tela MessageBox.Show( $"Baixa bancária ainda não implementada.\n\n" + $"Dados disponíveis:\n" + $"• Chave: {chave}\n" + $"• Linha Digitável: {linha}\n" + $"• Número: {numero}", "Baixar Boleto", MessageBoxButtons.OK, MessageBoxIcon.Information); } // ── MÁQUINA DE ESTADOS ──────────────────────────────────────────────── private void SetEstadoInicial() { SetCamposEnabled(false); btnSalvar.Enabled = false; btnCancelar.Enabled = false; btnAlterar.Enabled = false; btnExcluir.Enabled = false; btnBaixar.Enabled = false; } private void SetCamposEnabled(bool enabled) { txtNumero.ReadOnly = !enabled; txtNossoNumero.ReadOnly = !enabled; txtChaveBoleto.ReadOnly = !enabled; txtLinhaDigitavel.ReadOnly = !enabled; txtValor.ReadOnly = !enabled; txtVlPago.ReadOnly = !enabled; txtVlMulta.ReadOnly = !enabled; txtVlDesconto.ReadOnly = !enabled; txtSacado.ReadOnly = !enabled; txtObservacao.ReadOnly = !enabled; dtpEmitido.Enabled = enabled; dtpVence.Enabled = enabled; dtpPagamento.Enabled = enabled && chkPago.Checked; cmbConta.Enabled = enabled; cmbCodConta.Enabled = enabled; cmbStatus.Enabled = enabled; cmbArquivoTipo.Enabled = enabled; chkPago.Enabled = enabled; chkAceite.Enabled = enabled; chkImpresso.Enabled = enabled; chkImportado.Enabled = enabled; btnAnexar.Enabled = enabled; } private void SetEstadoEdicao() { SetCamposEnabled(true); btnSalvar.Enabled = true; btnCancelar.Enabled = true; btnNovo.Enabled = false; btnAlterar.Enabled = false; btnExcluir.Enabled = false; btnLocalizar.Enabled = false; btnBaixar.Enabled = false; } private void SetEstadoConsulta() { SetCamposEnabled(false); btnSalvar.Enabled = false; btnCancelar.Enabled = false; btnNovo.Enabled = true; btnAlterar.Enabled = true; btnExcluir.Enabled = true; btnLocalizar.Enabled = true; btnBaixar.Enabled = _modelo.ID_BOLETO > 0; } // ── CARGA / LIMPEZA / COLETA ────────────────────────────────────────── private void CarregarModelo() { txtCodigo.Text = _modelo.ID_BOLETO == 0 ? "" : _modelo.ID_BOLETO.ToString(); txtNumero.Text = _modelo.NUMERO; txtNossoNumero.Text = _modelo.NOSSO_NUMERO; txtChaveBoleto.Text = _modelo.CHAVE_BOLETO; txtLinhaDigitavel.Text = _modelo.LINHA_DIGITAVEL; txtSacado.Text = _modelo.SACADO; txtValor.Text = _modelo.VALOR.ToString("N2"); txtVlPago.Text = _modelo.VL_PAGO?.ToString("N2") ?? ""; txtVlMulta.Text = _modelo.VL_MULTA?.ToString("N2") ?? ""; txtVlDesconto.Text = _modelo.VL_DESCONTO?.ToString("N2") ?? ""; txtObservacao.Text = _modelo.OBSERVACAO; dtpEmitido.Value = _modelo.EMITIDO ?? DateTime.Today; dtpVence.Value = _modelo.VENCE ?? DateTime.Today; dtpPagamento.Value = _modelo.DT_PAGAMENTO ?? DateTime.Today; cmbStatus.SelectedItem = _modelo.STATUS ?? "ABERTO"; chkPago.Checked = _modelo.PG; chkAceite.Checked = _modelo.ACEITE; chkImpresso.Checked = _modelo.IMPRESSO; chkImportado.Checked = _modelo.IMPORTACAO; if (!string.IsNullOrEmpty(_modelo.CONTA)) cmbConta.Text = _modelo.CONTA; if (!string.IsNullOrEmpty(_modelo.COD_CONTA)) cmbCodConta.Text = _modelo.COD_CONTA; txtArquivoNome.Text = _modelo.ARQUIVO_NOME; txtArquivoCaminho.Text = _modelo.ARQUIVO_CAMINHO; cmbArquivoTipo.Text = _modelo.ARQUIVO_TIPO; bool temArquivo = _modelo.TemArquivo; btnVisualizarArq.Enabled = temArquivo; lblArquivoInfo.Text = temArquivo ? $"✔ {_modelo.ARQUIVO_NOME}" : "Nenhum arquivo anexado."; lblArquivoInfo.ForeColor = temArquivo ? Color.FromArgb(34, 197, 94) : Color.Gray; AtualizarValorFinal(); } private void LimparCampos() { _modelo = new ModeloBoletos(); txtCodigo.Text = ""; txtNumero.Text = ""; txtNossoNumero.Text = ""; txtChaveBoleto.Text = ""; txtLinhaDigitavel.Text = ""; txtSacado.Text = ""; txtValor.Text = ""; txtVlPago.Text = ""; txtVlMulta.Text = ""; txtVlDesconto.Text = ""; txtObservacao.Text = ""; txtArquivoNome.Text = ""; txtArquivoCaminho.Text = ""; dtpEmitido.Value = DateTime.Today; dtpVence.Value = DateTime.Today; dtpPagamento.Value = DateTime.Today; cmbStatus.SelectedIndex = 0; cmbConta.SelectedIndex = -1; cmbCodConta.SelectedIndex = -1; cmbArquivoTipo.SelectedIndex = 0; chkPago.Checked = false; chkAceite.Checked = false; chkImpresso.Checked = false; chkImportado.Checked = false; btnVisualizarArq.Enabled = false; lblArquivoInfo.Text = "Nenhum arquivo anexado."; lblArquivoInfo.ForeColor = Color.Gray; AtualizarValorFinal(); } private ModeloBoletos ColetarModelo() => new ModeloBoletos { ID_BOLETO = _modelo.ID_BOLETO, NUMERO = txtNumero.Text.Trim(), NOSSO_NUMERO = txtNossoNumero.Text.Trim(), CHAVE_BOLETO = txtChaveBoleto.Text.Trim(), LINHA_DIGITAVEL = txtLinhaDigitavel.Text.Trim(), EMITIDO = dtpEmitido.Value.Date, VENCE = dtpVence.Value.Date, DT_PAGAMENTO = chkPago.Checked ? dtpPagamento.Value.Date : (DateTime?)null, VALOR = ParseDecimal(txtValor.Text), VL_PAGO = string.IsNullOrWhiteSpace(txtVlPago.Text) ? null : ParseDecimal(txtVlPago.Text), VL_MULTA = string.IsNullOrWhiteSpace(txtVlMulta.Text) ? null : ParseDecimal(txtVlMulta.Text), VL_DESCONTO = string.IsNullOrWhiteSpace(txtVlDesconto.Text) ? null : ParseDecimal(txtVlDesconto.Text), STATUS = cmbStatus.SelectedItem?.ToString() ?? "ABERTO", PG = chkPago.Checked, ACEITE = chkAceite.Checked, IMPRESSO = chkImpresso.Checked, IMPORTACAO = chkImportado.Checked, SACADO = txtSacado.Text.Trim(), CONTA = cmbConta.Text, COD_CONTA = cmbCodConta.Text, ARQUIVO_NOME = txtArquivoNome.Text.Trim(), ARQUIVO_TIPO = cmbArquivoTipo.Text, ARQUIVO_CAMINHO = txtArquivoCaminho.Text.Trim(), ARQUIVO_DADOS = _modelo.ARQUIVO_DADOS, OBSERVACAO = txtObservacao.Text.Trim(), DT_CADASTRO = _modelo.DT_CADASTRO == default ? DateTime.Now : _modelo.DT_CADASTRO, DT_ALTERACAO = _modelo.ID_BOLETO > 0 ? DateTime.Now : (DateTime?)null, ID_USUARIO = _modelo.ID_USUARIO }; // ── EVENTOS ABSTRATOS ───────────────────────────────────────────────── protected override void OnNovo() { LimparCampos(); SetEstadoEdicao(); txtNumero.Focus(); } protected override void OnAlterar() { if (_modelo.ID_BOLETO == 0) { MessageBox.Show("Localize um boleto antes de alterar.", "Atenção", MessageBoxButtons.OK, MessageBoxIcon.Warning); return; } SetEstadoEdicao(); txtNumero.Focus(); } protected override void OnExcluir() { if (_modelo.ID_BOLETO == 0) { MessageBox.Show("Localize um boleto antes de excluir.", "Atenção", MessageBoxButtons.OK, MessageBoxIcon.Warning); return; } var confirm = MessageBox.Show( $"Deseja excluir o boleto Nº {_modelo.NUMERO}?", "Confirmar Exclusão", MessageBoxButtons.YesNo, MessageBoxIcon.Question); if (confirm == DialogResult.Yes) { // TODO: DALBoletos.Excluir(_modelo.ID_BOLETO, _cx); LimparCampos(); SetEstadoInicial(); MessageBox.Show("Boleto excluído com sucesso.", "Sucesso", MessageBoxButtons.OK, MessageBoxIcon.Information); } } protected override void OnLocalizar() { // TODO: abrir form de pesquisa // var frm = new FormLocalizarBoleto(); // if (frm.ShowDialog() == DialogResult.OK) // { // _modelo = frm.ModeloSelecionado; // CarregarModelo(); // SetEstadoConsulta(); // } } protected override void OnSalvar() { if (!Validar()) return; var modelo = ColetarModelo(); try { if (modelo.ID_BOLETO == 0) { // TODO: DALBoletos.Inserir(modelo, _cx); MessageBox.Show("Boleto cadastrado com sucesso.", "Sucesso", MessageBoxButtons.OK, MessageBoxIcon.Information); } else { // TODO: DALBoletos.Atualizar(modelo, _cx); MessageBox.Show("Boleto atualizado com sucesso.", "Sucesso", MessageBoxButtons.OK, MessageBoxIcon.Information); } _modelo = modelo; SetEstadoConsulta(); } catch (Exception ex) { MessageBox.Show($"Erro ao salvar boleto:\n{ex.Message}", "Erro", MessageBoxButtons.OK, MessageBoxIcon.Error); } } protected override void OnCancelar() { if (_modelo.ID_BOLETO == 0) LimparCampos(); else CarregarModelo(); SetEstadoConsulta(); } // ── VALIDAÇÃO ───────────────────────────────────────────────────────── private bool Validar() { if (string.IsNullOrWhiteSpace(txtNumero.Text)) { MessageBox.Show("Informe o número do boleto.", "Validação", MessageBoxButtons.OK, MessageBoxIcon.Warning); txtNumero.Focus(); return false; } if (ParseDecimal(txtValor.Text) <= 0) { MessageBox.Show("Informe um valor válido para o boleto.", "Validação", MessageBoxButtons.OK, MessageBoxIcon.Warning); txtValor.Focus(); return false; } if (dtpVence.Value.Date < dtpEmitido.Value.Date) { MessageBox.Show("A data de vencimento não pode ser anterior à data de emissão.", "Validação", MessageBoxButtons.OK, MessageBoxIcon.Warning); dtpVence.Focus(); return false; } if (string.IsNullOrWhiteSpace(txtSacado.Text)) { MessageBox.Show("Informe o sacado.", "Validação", MessageBoxButtons.OK, MessageBoxIcon.Warning); txtSacado.Focus(); return false; } if (cmbConta.SelectedIndex < 0) { MessageBox.Show("Selecione a conta.", "Validação", MessageBoxButtons.OK, MessageBoxIcon.Warning); cmbConta.Focus(); return false; } return true; } } }