diff --git a/CPM/ComboBox/LV_COMBOBOX.cs b/CPM/ComboBox/LV_COMBOBOX.cs new file mode 100644 index 0000000..1478e52 --- /dev/null +++ b/CPM/ComboBox/LV_COMBOBOX.cs @@ -0,0 +1,242 @@ +using System; +using System.Drawing; +using System.Drawing.Drawing2D; +using System.Windows.Forms; + +namespace CPM +{ + /// + /// ComboBox customizado do sistema LevelOS. + /// Segue o mesmo padrão visual do LV_TEXTBOX1. + /// + public class LV_COMBOBOX : UserControl + { + // ── CAMPOS INTERNOS ─────────────────────────────────────────────────── + private ComboBox _combo; + private bool _isFocused = false; + + // ── PROPRIEDADES VISUAIS ────────────────────────────────────────────── + private Color _borderColor = Color.FromArgb(226, 232, 240); + private Color _borderFocusColor = Color.FromArgb(37, 99, 235); + private Color _arrowColor = Color.FromArgb(100, 116, 139); + private int _borderRadius = 6; + private int _borderSize = 1; + + public Color BorderColor + { + get => _borderColor; + set { _borderColor = value; Invalidate(); } + } + + public Color BorderFocusColor + { + get => _borderFocusColor; + set { _borderFocusColor = value; Invalidate(); } + } + + public Color ArrowColor + { + get => _arrowColor; + set { _arrowColor = value; Invalidate(); } + } + + public int BorderRadius + { + get => _borderRadius; + set { _borderRadius = value; Invalidate(); } + } + + public int BorderSize + { + get => _borderSize; + set { _borderSize = value; Invalidate(); } + } + + // ── PROPRIEDADES DO COMBOBOX ────────────────────────────────────────── + public ComboBoxStyle DropDownStyle + { + get => _combo.DropDownStyle; + set => _combo.DropDownStyle = value; + } + + public System.Windows.Forms.ComboBox.ObjectCollection Items => _combo.Items; + + public object? SelectedItem + { + get => _combo.SelectedItem; + set => _combo.SelectedItem = value; + } + + public int SelectedIndex + { + get => _combo.SelectedIndex; + set => _combo.SelectedIndex = value; + } + + public string Text + { + get => _combo.Text; + set => _combo.Text = value; + } + + public override Font Font + { + get => base.Font; + set + { + base.Font = value; + _combo.Font = value; + AjustarAltura(); + } + } + + public new bool Enabled + { + get => base.Enabled; + set + { + base.Enabled = value; + _combo.Enabled = value; + BackColor = value ? Color.White : Color.FromArgb(241, 245, 249); + Invalidate(); + } + } + + // ── EVENTOS REPASSADOS ──────────────────────────────────────────────── + public event EventHandler? SelectedIndexChanged + { + add => _combo.SelectedIndexChanged += value; + remove => _combo.SelectedIndexChanged -= value; + } + + public new event EventHandler? TextChanged + { + add => _combo.TextChanged += value; + remove => _combo.TextChanged -= value; + } + + // ── CONSTRUTOR ──────────────────────────────────────────────────────── + public LV_COMBOBOX() + { + _combo = new ComboBox + { + DropDownStyle = ComboBoxStyle.DropDownList, + FlatStyle = FlatStyle.Flat, + Font = new Font("Segoe UI", 9f), + BackColor = Color.White, + ForeColor = Color.FromArgb(30, 41, 59), + Dock = DockStyle.None, + IntegralHeight = false + }; + + // Configura o controle pai + Padding = new Padding(8, 0, 30, 0); // espaço para seta customizada + BackColor = Color.White; + ForeColor = Color.FromArgb(30, 41, 59); + Font = new Font("Segoe UI", 9f); + Size = new Size(200, 36); + DoubleBuffered = true; + + Controls.Add(_combo); + AjustarAltura(); + + // Eventos de foco + _combo.GotFocus += (s, e) => { _isFocused = true; Invalidate(); }; + _combo.LostFocus += (s, e) => { _isFocused = false; Invalidate(); }; + + // Propaga clique na área do controle para o combo + this.Click += (s, e) => _combo.Focus(); + + _combo.DropDown += (s, e) => Invalidate(); + _combo.DropDownClosed += (s, e) => Invalidate(); + } + + // ── AJUSTE DE ALTURA ────────────────────────────────────────────────── + private void AjustarAltura() + { + int altura = _combo.PreferredHeight; + this.Height = altura + 10; + _combo.Width = this.Width - 38; // reserva espaço para seta + _combo.Left = 8; + _combo.Top = (this.Height - _combo.Height) / 2; + } + + // ── RESIZE ──────────────────────────────────────────────────────────── + protected override void OnResize(EventArgs e) + { + base.OnResize(e); + _combo.Width = this.Width - 38; + _combo.Left = 8; + _combo.Top = (this.Height - _combo.Height) / 2; + Invalidate(); + } + + // ── PAINT ───────────────────────────────────────────────────────────── + protected override void OnPaint(PaintEventArgs e) + { + base.OnPaint(e); + + var g = e.Graphics; + g.SmoothingMode = SmoothingMode.AntiAlias; + + var cor = _isFocused ? _borderFocusColor : _borderColor; + var rect = new Rectangle(0, 0, Width - 1, Height - 1); + var bgRect = new Rectangle(1, 1, Width - 2, Height - 2); + + // Fundo + using var bgBrush = new SolidBrush(Enabled ? BackColor : Color.FromArgb(241, 245, 249)); + g.FillRoundedRectangle(bgBrush, bgRect, _borderRadius); + + // Borda + using var pen = new Pen(cor, _borderSize); + g.DrawRoundedRectangle(pen, rect, _borderRadius); + + // Seta customizada + DesenharSeta(g); + } + + private void DesenharSeta(Graphics g) + { + int arrowX = Width - 22; + int arrowY = Height / 2; + + using var brush = new SolidBrush(_isFocused ? _borderFocusColor : _arrowColor); + var pontos = new Point[] + { + new Point(arrowX - 5, arrowY - 3), + new Point(arrowX + 5, arrowY - 3), + new Point(arrowX, arrowY + 4) + }; + g.FillPolygon(brush, pontos); + } + } + + // ── EXTENSÕES DE GRAPHICS PARA ROUNDED RECT ─────────────────────────────── + internal static class GraphicsExtensions + { + public static void FillRoundedRectangle(this Graphics g, Brush brush, Rectangle rect, int radius) + { + using var path = GetRoundedPath(rect, radius); + g.FillPath(brush, path); + } + + public static void DrawRoundedRectangle(this Graphics g, Pen pen, Rectangle rect, int radius) + { + using var path = GetRoundedPath(rect, radius); + g.DrawPath(pen, path); + } + + private static GraphicsPath GetRoundedPath(Rectangle rect, int radius) + { + int r = Math.Min(radius, Math.Min(rect.Width, rect.Height) / 2); + var d = r * 2; + var path = new GraphicsPath(); + path.AddArc(rect.X, rect.Y, d, d, 180, 90); + path.AddArc(rect.Right - d, rect.Y, d, d, 270, 90); + path.AddArc(rect.Right - d, rect.Bottom - d, d, d, 0, 90); + path.AddArc(rect.X, rect.Bottom - d, d, d, 90, 90); + path.CloseFigure(); + return path; + } + } +} diff --git a/MLL/ModeloBoletos.cs b/MLL/ModeloBoletos.cs index a912390..09aa30d 100644 --- a/MLL/ModeloBoletos.cs +++ b/MLL/ModeloBoletos.cs @@ -4,71 +4,122 @@ namespace MLL { public class ModeloBoletos { + // ── CONSTRUTOR VAZIO ────────────────────────────────────────────────── public ModeloBoletos() { - this.ID_BOLETO = 0; - this.CODIGO = string.Empty; - this.EMITIDO = string.Empty; - this.VENCE = string.Empty; - this.VALOR = string.Empty; - this.NUMERO = string.Empty; - this.PG = string.Empty; - this.SACADO = string.Empty; - this.CONTA = string.Empty; - this.OBSERVACAO = string.Empty; - this.COD_CONTA = string.Empty; - this.NOSSO_NUMERO = string.Empty; - this.ACEITE = string.Empty; - this.IMPRESSO = string.Empty; - this.IMPORTACAO = string.Empty; - } - public ModeloBoletos(int iD_BOLETO, string cODIGO, string eMITIDO, string vENCE, string vALOR, string nUMERO, string pG, string sACADO, string cONTA, string oBSERVACAO, string cOD_CONTA, string nOSSO_NUMERO, string aCEITE, string iMPRESSO, string iMPORTACAO) - { - ID_BOLETO = iD_BOLETO; - CODIGO = cODIGO; - EMITIDO = eMITIDO; - VENCE = vENCE; - VALOR = vALOR; - NUMERO = nUMERO; - PG = pG; - SACADO = sACADO; - CONTA = cONTA; - OBSERVACAO = oBSERVACAO; - COD_CONTA = cOD_CONTA; - NOSSO_NUMERO = nOSSO_NUMERO; - ACEITE = aCEITE; - IMPRESSO = iMPRESSO; - IMPORTACAO = iMPORTACAO; + ID_BOLETO = 0; + CODIGO = string.Empty; + NUMERO = string.Empty; + NOSSO_NUMERO = string.Empty; + CHAVE_BOLETO = string.Empty; + LINHA_DIGITAVEL = string.Empty; + EMITIDO = null; + VENCE = null; + DT_PAGAMENTO = null; + VALOR = 0m; + VL_PAGO = null; + VL_MULTA = null; + VL_DESCONTO = null; + STATUS = "ABERTO"; + PG = false; + SACADO = string.Empty; + CONTA = string.Empty; + COD_CONTA = string.Empty; + ACEITE = false; + IMPRESSO = false; + IMPORTACAO = false; + ARQUIVO_NOME = string.Empty; + ARQUIVO_TIPO = string.Empty; + ARQUIVO_CAMINHO = string.Empty; + ARQUIVO_DADOS = null; + OBSERVACAO = string.Empty; + DT_CADASTRO = DateTime.Now; + DT_ALTERACAO = null; + ID_USUARIO = null; } + // ── IDENTIFICAÇÃO ───────────────────────────────────────────────────── public int ID_BOLETO { get; set; } - public string CODIGO { get; set; } - - public string EMITIDO { get; set; } - - public string VENCE { get; set; } - - public string VALOR { get; set; } - public string NUMERO { get; set; } - - public string PG { get; set; } - - public string SACADO { get; set; } - - public string CONTA { get; set; } - - public string OBSERVACAO { get; set; } - - public string COD_CONTA { get; set; } - public string NOSSO_NUMERO { get; set; } - public string ACEITE { get; set; } + /// Chave única para baixa/integração bancária. + public string CHAVE_BOLETO { get; set; } - public string IMPRESSO { get; set; } + /// Código de barras / linha digitável (47 ou 48 dígitos). + public string LINHA_DIGITAVEL { get; set; } - public string IMPORTACAO { get; set; } + // ── DATAS ───────────────────────────────────────────────────────────── + public DateTime? EMITIDO { get; set; } + public DateTime? VENCE { get; set; } + + /// Data efetiva em que o boleto foi pago. + public DateTime? DT_PAGAMENTO { get; set; } + + // ── VALORES ─────────────────────────────────────────────────────────── + public decimal VALOR { get; set; } + + /// Valor efetivamente pago (pode diferir de VALOR por multa/desconto). + public decimal? VL_PAGO { get; set; } + + /// Multa por atraso aplicada no pagamento. + public decimal? VL_MULTA { get; set; } + + /// Desconto concedido no pagamento. + public decimal? VL_DESCONTO { get; set; } + + // ── STATUS ──────────────────────────────────────────────────────────── + /// + /// Status do boleto. + /// Valores: ABERTO | PAGO | VENCIDO | CANCELADO | BAIXADO + /// + public string STATUS { get; set; } + + // ── FLAGS ───────────────────────────────────────────────────────────── + public bool PG { get; set; } + public bool ACEITE { get; set; } + public bool IMPRESSO { get; set; } + public bool IMPORTACAO { get; set; } + + // ── SACADO E CONTA ──────────────────────────────────────────────────── + public string SACADO { get; set; } + public string CONTA { get; set; } + public string COD_CONTA { get; set; } + + // ── ARQUIVO (XML / PDF) ─────────────────────────────────────────────── + /// Nome original do arquivo anexado. + public string ARQUIVO_NOME { get; set; } + + /// Tipo do arquivo: "XML" ou "PDF". + public string ARQUIVO_TIPO { get; set; } + + /// Caminho completo do arquivo em disco. + public string ARQUIVO_CAMINHO { get; set; } + + /// Conteúdo binário do arquivo (para armazenamento no banco). + public byte[]? ARQUIVO_DADOS { get; set; } + + // ── OBSERVAÇÃO ──────────────────────────────────────────────────────── + public string OBSERVACAO { get; set; } + + // ── RASTREABILIDADE ─────────────────────────────────────────────────── + public DateTime DT_CADASTRO { get; set; } + public DateTime? DT_ALTERACAO { get; set; } + public int? ID_USUARIO { get; set; } + + // ── HELPERS ─────────────────────────────────────────────────────────── + + /// Retorna true se o boleto está vencido e ainda não foi pago. + public bool EstaVencido => + !PG && VENCE.HasValue && VENCE.Value.Date < DateTime.Today; + + /// Retorna true se há arquivo anexado (caminho ou binário). + public bool TemArquivo => + !string.IsNullOrEmpty(ARQUIVO_CAMINHO) || ARQUIVO_DADOS != null; + + /// Valor com multa e desconto aplicados. + public decimal ValorFinal => + VALOR + (VL_MULTA ?? 0m) - (VL_DESCONTO ?? 0m); } } \ No newline at end of file diff --git a/UI/ArquivosAuxiliares/BoletoTableNew.sql b/UI/ArquivosAuxiliares/BoletoTableNew.sql new file mode 100644 index 0000000..5453093 --- /dev/null +++ b/UI/ArquivosAuxiliares/BoletoTableNew.sql @@ -0,0 +1,189 @@ +USE [Levelcode-LevelOS] +GO + +-- ============================================================ +-- MIGRAÇÃO DA TABELA [dbo].[Boletos] +-- Gerado em: 20/04/2026 +-- Descrição: Melhoria de tipos, rastreabilidade, +-- suporte a arquivo (XML/PDF) e baixa bancária +-- ============================================================ + +-- ── PASSO 1: Corrigir tipos das colunas existentes ────────── + +-- Datas +ALTER TABLE [dbo].[Boletos] + ALTER COLUMN [EMITIDO] DATE NULL; +GO + +ALTER TABLE [dbo].[Boletos] + ALTER COLUMN [VENCE] DATE NULL; +GO + +-- Valor +ALTER TABLE [dbo].[Boletos] + ALTER COLUMN [VALOR] DECIMAL(10,2) NULL; +GO + +-- Flags booleanas (S/N → BIT) +-- Precisa converter os dados antes de mudar o tipo +UPDATE [dbo].[Boletos] SET [PG] = CASE WHEN [PG] = 'S' THEN '1' ELSE '0' END; +UPDATE [dbo].[Boletos] SET [ACEITE] = CASE WHEN [ACEITE] = 'S' THEN '1' ELSE '0' END; +UPDATE [dbo].[Boletos] SET [IMPRESSO] = CASE WHEN [IMPRESSO] = 'S' THEN '1' ELSE '0' END; +UPDATE [dbo].[Boletos] SET [IMPORTACAO]= CASE WHEN [IMPORTACAO]= 'S' THEN '1' ELSE '0' END; +GO + +ALTER TABLE [dbo].[Boletos] ALTER COLUMN [PG] BIT NOT NULL; +ALTER TABLE [dbo].[Boletos] ALTER COLUMN [ACEITE] BIT NOT NULL; +ALTER TABLE [dbo].[Boletos] ALTER COLUMN [IMPRESSO] BIT NOT NULL; +ALTER TABLE [dbo].[Boletos] ALTER COLUMN [IMPORTACAO] BIT NOT NULL; +GO + +-- Campos de texto: limitar tamanho adequado +ALTER TABLE [dbo].[Boletos] ALTER COLUMN [CODIGO] VARCHAR(50) NULL; +ALTER TABLE [dbo].[Boletos] ALTER COLUMN [NUMERO] VARCHAR(50) NULL; +ALTER TABLE [dbo].[Boletos] ALTER COLUMN [NOSSO_NUMERO] VARCHAR(50) NULL; +ALTER TABLE [dbo].[Boletos] ALTER COLUMN [SACADO] VARCHAR(200) NULL; +ALTER TABLE [dbo].[Boletos] ALTER COLUMN [CONTA] VARCHAR(100) NULL; +ALTER TABLE [dbo].[Boletos] ALTER COLUMN [COD_CONTA] VARCHAR(30) NULL; +ALTER TABLE [dbo].[Boletos] ALTER COLUMN [OBSERVACAO] VARCHAR(500) NULL; +GO + +-- ── PASSO 2: Adicionar colunas novas ──────────────────────── + +-- Baixa bancária / integração +ALTER TABLE [dbo].[Boletos] + ADD [CHAVE_BOLETO] VARCHAR(100) NULL; -- Chave única para baixa/integração bancária +GO + +ALTER TABLE [dbo].[Boletos] + ADD [LINHA_DIGITAVEL] VARCHAR(60) NULL; -- Código de barras / linha digitável +GO + +-- Pagamento +ALTER TABLE [dbo].[Boletos] + ADD [DT_PAGAMENTO] DATE NULL; -- Data efetiva do pagamento +GO + +ALTER TABLE [dbo].[Boletos] + ADD [VL_PAGO] DECIMAL(10,2) NULL; -- Valor pago (pode ter multa/desconto) +GO + +ALTER TABLE [dbo].[Boletos] + ADD [VL_MULTA] DECIMAL(10,2) NULL; -- Multa por atraso +GO + +ALTER TABLE [dbo].[Boletos] + ADD [VL_DESCONTO] DECIMAL(10,2) NULL; -- Desconto concedido +GO + +-- Arquivo (XML ou PDF) — caminho em disco +ALTER TABLE [dbo].[Boletos] + ADD [ARQUIVO_NOME] VARCHAR(255) NULL; -- Nome original do arquivo +GO + +ALTER TABLE [dbo].[Boletos] + ADD [ARQUIVO_TIPO] VARCHAR(10) NULL; -- 'XML' ou 'PDF' +GO + +ALTER TABLE [dbo].[Boletos] + ADD [ARQUIVO_CAMINHO] VARCHAR(500) NULL; -- Caminho completo em disco +GO + +-- Arquivo — binário no banco +ALTER TABLE [dbo].[Boletos] + ADD [ARQUIVO_DADOS] VARBINARY(MAX) NULL; -- Conteúdo binário do arquivo +GO + +-- Rastreabilidade +ALTER TABLE [dbo].[Boletos] + ADD [DT_CADASTRO] DATETIME NOT NULL DEFAULT GETDATE(); -- Data de criação +GO + +ALTER TABLE [dbo].[Boletos] + ADD [DT_ALTERACAO] DATETIME NULL; -- Última alteração +GO + +ALTER TABLE [dbo].[Boletos] + ADD [ID_USUARIO] INT NULL; -- Usuário responsável +GO + +ALTER TABLE [dbo].[Boletos] + ADD [STATUS] VARCHAR(20) NOT NULL DEFAULT 'ABERTO'; + -- Valores possíveis: 'ABERTO', 'PAGO', 'VENCIDO', 'CANCELADO', 'BAIXADO' +GO + +-- ── PASSO 3: Índices para performance ─────────────────────── + +-- Busca por número do boleto +CREATE NONCLUSTERED INDEX [IX_Boletos_Numero] + ON [dbo].[Boletos] ([NUMERO] ASC) + WHERE [NUMERO] IS NOT NULL; +GO + +-- Busca por chave bancária +CREATE NONCLUSTERED INDEX [IX_Boletos_Chave] + ON [dbo].[Boletos] ([CHAVE_BOLETO] ASC) + WHERE [CHAVE_BOLETO] IS NOT NULL; +GO + +-- Busca por vencimento (relatórios de inadimplência) +CREATE NONCLUSTERED INDEX [IX_Boletos_Vence] + ON [dbo].[Boletos] ([VENCE] ASC); +GO + +-- Busca por status +CREATE NONCLUSTERED INDEX [IX_Boletos_Status] + ON [dbo].[Boletos] ([STATUS] ASC); +GO + +-- ── PASSO 4: Constraint de validação de status ────────────── + +ALTER TABLE [dbo].[Boletos] + ADD CONSTRAINT [CK_Boletos_Status] + CHECK ([STATUS] IN ('ABERTO', 'PAGO', 'VENCIDO', 'CANCELADO', 'BAIXADO')); +GO + +ALTER TABLE [dbo].[Boletos] + ADD CONSTRAINT [CK_Boletos_ArquivoTipo] + CHECK ([ARQUIVO_TIPO] IN ('XML', 'PDF') OR [ARQUIVO_TIPO] IS NULL); +GO + +-- ── PASSO 5: FK para usuário (se a tabela existir) ────────── +-- Descomente quando a tabela de usuários estiver criada: +-- ALTER TABLE [dbo].[Boletos] +-- ADD CONSTRAINT [FK_Boletos_Usuario] +-- FOREIGN KEY ([ID_USUARIO]) REFERENCES [dbo].[Usuarios]([ID_USUARIO]); +-- GO + +-- ── RESULTADO FINAL ────────────────────────────────────────── +-- Tabela com a estrutura completa após migração: +-- +-- ID_BOLETO INT IDENTITY PK +-- CODIGO VARCHAR(50) +-- NUMERO VARCHAR(50) +-- NOSSO_NUMERO VARCHAR(50) +-- CHAVE_BOLETO VARCHAR(100) ← novo +-- LINHA_DIGITAVEL VARCHAR(60) ← novo +-- EMITIDO DATE ← tipo corrigido +-- VENCE DATE ← tipo corrigido +-- DT_PAGAMENTO DATE ← novo +-- VALOR DECIMAL(10,2) ← tipo corrigido +-- VL_PAGO DECIMAL(10,2) ← novo +-- VL_MULTA DECIMAL(10,2) ← novo +-- VL_DESCONTO DECIMAL(10,2) ← novo +-- STATUS VARCHAR(20) ← novo +-- PG BIT ← tipo corrigido +-- SACADO VARCHAR(200) ← tipo corrigido +-- CONTA VARCHAR(100) ← tipo corrigido +-- COD_CONTA VARCHAR(30) ← tipo corrigido +-- ACEITE BIT ← tipo corrigido +-- IMPRESSO BIT ← tipo corrigido +-- IMPORTACAO BIT ← tipo corrigido +-- ARQUIVO_NOME VARCHAR(255) ← novo +-- ARQUIVO_TIPO VARCHAR(10) ← novo +-- ARQUIVO_CAMINHO VARCHAR(500) ← novo +-- ARQUIVO_DADOS VARBINARY(MAX) ← novo +-- OBSERVACAO VARCHAR(500) ← tipo corrigido +-- DT_CADASTRO DATETIME ← novo +-- DT_ALTERACAO DATETIME ← novo +-- ID_USUARIO INT ← novo \ No newline at end of file diff --git a/UI/Dashboards/Cadastros/BoletoCadastroPanel.cs b/UI/Dashboards/Cadastros/BoletoCadastroPanel.cs new file mode 100644 index 0000000..ac7127a --- /dev/null +++ b/UI/Dashboards/Cadastros/BoletoCadastroPanel.cs @@ -0,0 +1,741 @@ +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; + } + } +} \ No newline at end of file diff --git a/UI/Dashboards/Cadastros/BoletoCadastroPanel.resx b/UI/Dashboards/Cadastros/BoletoCadastroPanel.resx new file mode 100644 index 0000000..1af7de1 --- /dev/null +++ b/UI/Dashboards/Cadastros/BoletoCadastroPanel.resx @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/UI/Dashboards/Cadastros/ContratosCadastroPanel.cs b/UI/Dashboards/Cadastros/ContratosCadastroPanel.cs new file mode 100644 index 0000000..083bb3c --- /dev/null +++ b/UI/Dashboards/Cadastros/ContratosCadastroPanel.cs @@ -0,0 +1,176 @@ +using CPM; +using MLL; // Namespace da sua model +using System; +using System.Drawing; +using System.Windows.Forms; +using UI; // Namespace do seu FormularioModelo + +namespace UI +{ + public partial class ContratosCadastroPanel : FormularioModelo + { + private ModeloContrato _contrato = new ModeloContrato(); + + // Controles específicos + private LV_TEXTBOX1 txtId, txtEmpresaId, txtClienteId, txtDescricao; + private LV_TEXTBOX1 txtValor, txtDataInicio, txtDataValidade, txtFranquia; + private LV_TEXTBOX1 txtObservacoes; + private CheckBox chkAtivo; + private LV_TEXTBOX1 txtNomeCliente; // Novo campo para o nome + private Button btnBuscaCliente; // Botão da lupa + public ContratosCadastroPanel() + { + this.Titulo = "Gestão de Contratos"; + MontarInterface(); + } + + //private void MontarInterface() + //{ + // // --- SEÇÃO 1: Vínculos e Descrição --- + // content.Controls.Add(CreateSectionHeader("IDENTIFICAÇÃO DO CONTRATO", 20)); + + // txtId = AddInput(content, "ID", 20, 50, 80, 30, true); + // txtEmpresaId = AddInput(content, "ID EMPRESA", 110, 50, 100, 30); + // txtClienteId = AddInput(content, "ID CLIENTE", 220, 50, 100, 30); + // txtDescricao = AddInput(content, "DESCRIÇÃO DO CONTRATO", 330, 50, 550, 30); + + // // --- SEÇÃO 2: Valores e Prazos --- + // content.Controls.Add(CreateSectionHeader("FINANCEIRO E VIGÊNCIA", 110)); + + // txtValor = AddInput(content, "VALOR MENSAL (R$)", 20, 140, 150, 30); + // txtDataInicio = AddInput(content, "DATA INÍCIO", 180, 140, 150, 30); + // txtDataValidade = AddInput(content, "VALIDADE/TÉRMINO", 340, 140, 150, 30); + // txtFranquia = AddInput(content, "FRANQUIA (HORAS/MIN)", 500, 140, 180, 30); + + // chkAtivo = CreateCheckBox("CONTRATO ATIVO", 700, 158); + // content.Controls.Add(chkAtivo); + + // // --- SEÇÃO 3: Observações --- + // content.Controls.Add(CreateSectionHeader("DETALHES E OBSERVAÇÕES", 200)); + + // txtObservacoes = AddInput(content, "OBSERVAÇÕES INTERNAS", 20, 230, 860, 80); + + // // Ajuste para o campo de observações ser maior (se o seu LV_TEXTBOX1 permitir) + // txtObservacoes.Height = 80; + //} + private void MontarInterface() + { + // --- SEÇÃO 1: Identificação e Vínculos --- + content.Controls.Add(CreateSectionHeader("IDENTIFICAÇÃO DO CONTRATO", 20)); + + // Linha 1: IDs e Busca + txtId = AddInput(content, "ID CONTRATO", 20, 50, 90, 30, true); + txtClienteId = AddInput(content, "ID CLIENTE", 120, 50, 80, 30); + + // Botão Lupa + btnBuscaCliente = new Button + { + Text = "🔍", + Location = new Point(205, 66), // Alinhado ao topo do textbox (50 + 16) + Size = new Size(32, 30), + BackColor = AccentBlue, + ForeColor = Color.White, + FlatStyle = FlatStyle.Flat, + Cursor = Cursors.Hand + }; + btnBuscaCliente.FlatAppearance.BorderSize = 0; + btnBuscaCliente.Click += (s, e) => OnLocalizarCliente(); + content.Controls.Add(btnBuscaCliente); + + txtNomeCliente = AddInput(content, "NOME DO CLIENTE / RAZÃO SOCIAL", 247, 50, 410, 30, true); + txtEmpresaId = AddInput(content, "ID EMPRESA", 667, 50, 80, 30); + + // Linha 2: Descrição (abaixo dos IDs) + txtDescricao = AddInput(content, "DESCRIÇÃO DO CONTRATO", 20, 105, 727, 30); + + // --- SEÇÃO 2: Valores e Prazos --- + // Aumentei o Y para 170 para dar espaço à descrição acima + content.Controls.Add(CreateSectionHeader("FINANCEIRO E VIGÊNCIA", 175)); + + txtValor = AddInput(content, "VALOR MENSAL (R$)", 20, 205, 150, 30); + txtDataInicio = AddInput(content, "DATA INÍCIO", 185, 205, 150, 30); + txtDataValidade = AddInput(content, "VALIDADE/TÉRMINO", 350, 205, 150, 30); + txtFranquia = AddInput(content, "FRANQUIA (HORAS/MIN)", 515, 205, 170, 30); + + // Checkbox Alinhado com os inputs + chkAtivo = CreateCheckBox("CONTRATO ATIVO", 700, 223); // Y do input (205) + ~18px + content.Controls.Add(chkAtivo); + + // --- SEÇÃO 3: Detalhes e Notas --- + content.Controls.Add(CreateSectionHeader("DETALHES E OBSERVAÇÕES", 275)); + + txtObservacoes = AddInput(content, "OBSERVAÇÕES INTERNAS", 20, 305, 860, 100); + + // Forçar a altura maior para o campo de observações + txtObservacoes.Height = 100; + // Se o seu LV_TEXTBOX1 tiver a propriedade Multiline, ative-a aqui: + // txtObservacoes.Multiline = true; + } + + // Método que você precisará implementar para a busca + private void OnLocalizarCliente() + { + //Logica para abrir o form de busca e retornar os dados + //Exemplo: + // var busca = new FormBuscaCliente(); + //if (busca.ShowDialog() == DialogResult.OK) + //{ + // txtClienteId.Text = busca.IdSelecionado; + // txtNomeCliente.Text = busca.NomeSelecionado; + //} + } + + private void PreencherModel() + { + _contrato.Descricao = txtDescricao.Text; + _contrato.Observacoes = txtObservacoes.Text; + _contrato.Ativo = chkAtivo.Checked; + + // Conversões seguras + if (decimal.TryParse(txtValor.Text, out decimal v)) _contrato.Valor = v; + if (int.TryParse(txtEmpresaId.Text, out int emp)) _contrato.EmpresaId = emp; + if (int.TryParse(txtClienteId.Text, out int cli)) _contrato.ClienteId = cli; + if (int.TryParse(txtFranquia.Text, out int fra)) _contrato.FranquiaTempo = fra; + + if (DateTime.TryParse(txtDataInicio.Text, out DateTime dtIn)) _contrato.DataInicio = dtIn; + if (DateTime.TryParse(txtDataValidade.Text, out DateTime dtVal)) _contrato.DataValidade = dtVal; + } + + // --- MÉTODOS OBRIGATÓRIOS DA BASE --- + + protected override void OnNovo() + { + _contrato = new ModeloContrato(); + // Limpar campos... + txtDescricao.Focus(); + } + + protected override void OnSalvar() + { + try + { + PreencherModel(); + // Chamar BLL.Salvar(_contrato); + MessageBox.Show("Contrato processado com sucesso!", "Aviso", MessageBoxButtons.OK, MessageBoxIcon.Information); + } + catch (Exception ex) + { + MessageBox.Show("Erro ao salvar contrato: " + ex.Message); + } + } + + protected override void OnAlterar() { /* Implementar busca/edição */ } + + protected override void OnExcluir() + { + if (MessageBox.Show("Deseja rescindir/excluir este contrato?", "Confirmação", MessageBoxButtons.YesNo) == DialogResult.Yes) + { + // Lógica de exclusão + } + } + + protected override void OnLocalizar() { /* Abrir grid de contratos */ } + + protected override void OnCancelar() { OnNovo(); } + } +} \ No newline at end of file diff --git a/UI/Dashboards/Cadastros/EquipamentosCadastroPanel.cs b/UI/Dashboards/Cadastros/EquipamentosCadastroPanel.cs new file mode 100644 index 0000000..a76dd0c --- /dev/null +++ b/UI/Dashboards/Cadastros/EquipamentosCadastroPanel.cs @@ -0,0 +1,123 @@ +using CPM; +using MLL; // Namespace da sua model +using System; +using System.Drawing; +using System.Windows.Forms; +using UI; // Namespace do seu FormularioModelo + +namespace UI +{ + public partial class EquipamentosCadastroPanel : FormularioModelo + { + // Instância da model para controle de dados + private ModeloEquipamentos _equipamento = new ModeloEquipamentos(); + + // Controles do formulário + private LV_TEXTBOX1 txtId, txtCodigo, txtDescricao, txtMarca, txtModelo; + private LV_TEXTBOX1 txtSerie, txtPatrimonio, txtDataCompra, txtRevenda; + private LV_TEXTBOX1 txtNF, txtCertificado, txtObservacoes; + + public EquipamentosCadastroPanel() + { + this.Titulo = "Cadastro de Equipamentos"; + MontarInterface(); + LimparTela(); + } + + private void MontarInterface() + { + // --- SEÇÃO 1: Identificação --- + content.Controls.Add(CreateSectionHeader("IDENTIFICAÇÃO E DESCRIÇÃO", 20)); + + txtId = AddInput(content, "ID", 20, 50, 80, 30, true); // Somente leitura + txtCodigo = AddInput(content, "CÓDIGO INTERNO", 110, 50, 150, 30); + txtDescricao = AddInput(content, "DESCRIÇÃO DO EQUIPAMENTO", 270, 50, 450, 30); + + // --- SEÇÃO 2: Detalhes Técnicos --- + content.Controls.Add(CreateSectionHeader("ESPECIFICAÇÕES TÉCNICAS", 110)); + + txtMarca = AddInput(content, "MARCA", 20, 140, 240, 30); + txtModelo = AddInput(content, "MODELO", 270, 140, 240, 30); + txtSerie = AddInput(content, "Nº DE SÉRIE", 520, 140, 200, 30); + txtPatrimonio = AddInput(content, "PATRIMÔNIO (PAT)", 730, 140, 150, 30); + + // --- SEÇÃO 3: Compra e Garantia --- + content.Controls.Add(CreateSectionHeader("DADOS DE AQUISIÇÃO E GARANTIA", 200)); + + txtDataCompra = AddInput(content, "DATA DA COMPRA", 20, 230, 150, 30); + txtRevenda = AddInput(content, "REVENDA / FORNECEDOR", 180, 230, 330, 30); + txtNF = AddInput(content, "NOTA FISCAL", 520, 230, 150, 30); + txtCertificado = AddInput(content, "Nº CERT. GARANTIA", 680, 230, 200, 30); + + // --- SEÇÃO 4: Observações --- + content.Controls.Add(CreateSectionHeader("OBSERVAÇÕES ADICIONAIS", 290)); + + txtObservacoes = AddInput(content, "NOTAS GERAIS", 20, 320, 860, 60); + // Se o seu LV_TEXTBOX1 suportar Multiline, você pode ajustar aqui + } + + private void LimparTela() + { + _equipamento = new ModeloEquipamentos(); + // Lógica para limpar todos os campos txtId.Text = "", etc. + // Dica: Você pode criar um método auxiliar na base para limpar o 'content' + } + + // --- IMPLEMENTAÇÃO DOS MÉTODOS DA BASE --- + + protected override void OnNovo() + { + LimparTela(); + txtCodigo.Focus(); + } + + protected override void OnSalvar() + { + try + { + // Mapeia a tela para a model + _equipamento.CODIGO = txtCodigo.Text; + _equipamento.DESCRICAO = txtDescricao.Text; + _equipamento.MARCA = txtMarca.Text; + _equipamento.MODELO = txtModelo.Text; + _equipamento.SERIE = txtSerie.Text; + _equipamento.PAT = txtPatrimonio.Text; + _equipamento.DATA_COMPRA = txtDataCompra.Text; + _equipamento.REVENDA = txtRevenda.Text; + _equipamento.NUM_NF = txtNF.Text; + _equipamento.NUM_CERTGAR = txtCertificado.Text; + _equipamento.OBSERVACOES = txtObservacoes.Text; + + // Aqui você chamaria sua BLL ou DAL passando o _equipamento + MessageBox.Show("Equipamento salvo com sucesso!", "Sucesso", MessageBoxButtons.OK, MessageBoxIcon.Information); + } + catch (Exception ex) + { + MessageBox.Show("Erro ao salvar: " + ex.Message); + } + } + + protected override void OnAlterar() + { + // Lógica para habilitar campos ou mudar estado + } + + protected override void OnExcluir() + { + if (MessageBox.Show("Deseja excluir este equipamento?", "Confirmar", MessageBoxButtons.YesNo) == DialogResult.Yes) + { + // Lógica de exclusão + } + } + + protected override void OnLocalizar() + { + // Aqui você abriria um formulário de busca + } + + protected override void OnCancelar() + { + LimparTela(); + } + } +} \ No newline at end of file diff --git a/UI/Dashboards/Cadastros/FornecedoresCadastroPanel.cs b/UI/Dashboards/Cadastros/FornecedoresCadastroPanel.cs new file mode 100644 index 0000000..3fae31a --- /dev/null +++ b/UI/Dashboards/Cadastros/FornecedoresCadastroPanel.cs @@ -0,0 +1,133 @@ +using CPM; +using MLL; +using System; +using System.Drawing; +using System.Windows.Forms; +using UI; + +namespace UI +{ + public partial class FornecedoresCadastroPanel : FormularioModelo + { + private ModeloFornecedores _fornecedor = new ModeloFornecedores(); + + // Controles - Identificação + private LV_TEXTBOX1 txtId, txtEmpresaId, txtNome, txtNomeFantasia, txtDocumento, txtIE, txtTipoPessoa; + + // Controles - Localização + private LV_TEXTBOX1 txtCep, txtEndereco, txtNumero, txtBairro, txtCidade, txtUF, txtComplemento; + + // Controles - Contato e Extras + private LV_TEXTBOX1 txtTelefone, txtCelular, txtWhatsapp, txtEmail, txtSite, txtObservacoes; + private CheckBox chkAtivo; + + public FornecedoresCadastroPanel() + { + this.Titulo = "Cadastro de Fornecedores"; + MontarInterface(); + } + + private void MontarInterface() + { + // --- SEÇÃO 1: Identificação --- + content.Controls.Add(CreateSectionHeader("IDENTIFICAÇÃO DO FORNECEDOR", 20)); + + txtId = AddInput(content, "ID", 20, 50, 70, 30, true); + txtEmpresaId = AddInput(content, "ID EMPRESA", 100, 50, 80, 30); + txtTipoPessoa = AddInput(content, "TIPO (PF/PJ)", 190, 50, 100, 30); + txtDocumento = AddInput(content, "CPF / CNPJ", 300, 50, 180, 30); + txtIE = AddInput(content, "INSC. ESTADUAL", 490, 50, 180, 30); + + txtNome = AddInput(content, "RAZÃO SOCIAL / NOME", 20, 105, 430, 30); + txtNomeFantasia = AddInput(content, "NOME FANTASIA", 460, 105, 420, 30); + + // --- SEÇÃO 2: Localização --- + content.Controls.Add(CreateSectionHeader("ENDEREÇO E LOCALIZAÇÃO", 175)); + + txtCep = AddInput(content, "CEP", 20, 205, 100, 30); + txtEndereco = AddInput(content, "LOGRADOURO", 130, 205, 350, 30); + txtNumero = AddInput(content, "Nº", 490, 205, 70, 30); + txtBairro = AddInput(content, "BAIRRO", 570, 205, 190, 30); + txtUF = AddInput(content, "UF", 770, 205, 50, 30); + + txtCidade = AddInput(content, "CIDADE", 20, 260, 300, 30); + txtComplemento = AddInput(content, "COMPLEMENTO", 330, 260, 550, 30); + + // --- SEÇÃO 3: Contato e Comunicação --- + content.Controls.Add(CreateSectionHeader("CONTATOS E DIGITAL", 330)); + + txtTelefone = AddInput(content, "TELEFONE", 20, 360, 150, 30); + txtCelular = AddInput(content, "CELULAR", 180, 360, 150, 30); + txtWhatsapp = AddInput(content, "WHATSAPP", 340, 360, 150, 30); + txtEmail = AddInput(content, "E-MAIL", 500, 360, 380, 30); + + txtSite = AddInput(content, "WEBSITE / PORTAL", 20, 415, 430, 30); + + chkAtivo = CreateCheckBox("FORNECEDOR ATIVO", 460, 433); + content.Controls.Add(chkAtivo); + + // --- SEÇÃO 4: Observações --- + content.Controls.Add(CreateSectionHeader("OBSERVAÇÕES GERAIS", 485)); + txtObservacoes = AddInput(content, "NOTAS INTERNAS", 20, 515, 860, 100); + txtObservacoes.Height = 100; + + // Ajuste automático da área de scroll para o conteúdo caber + content.Height = 650; + } + + private void PreencherModel() + { + _fornecedor.Nome = txtNome.Text; + _fornecedor.NomeFantasia = txtNomeFantasia.Text; + _fornecedor.TipoPessoa = txtTipoPessoa.Text; + _fornecedor.Documento = txtDocumento.Text; + _fornecedor.InscricaoEstadual = txtIE.Text; + + _fornecedor.Cep = txtCep.Text; + _fornecedor.Endereco = txtEndereco.Text; + _fornecedor.Bairro = txtBairro.Text; + _fornecedor.Cidade = txtCidade.Text; + _fornecedor.UF = txtUF.Text; + _fornecedor.Complemento = txtComplemento.Text; + + if (int.TryParse(txtNumero.Text, out int n)) _fornecedor.Numero = n; + if (int.TryParse(txtEmpresaId.Text, out int emp)) _fornecedor.EmpresaId = emp; + + _fornecedor.Telefone = txtTelefone.Text; + _fornecedor.Celular = txtCelular.Text; + _fornecedor.Whatsapp = txtWhatsapp.Text; + _fornecedor.Email = txtEmail.Text; + _fornecedor.Site = txtSite.Text; + _fornecedor.Observacoes = txtObservacoes.Text; + _fornecedor.Ativo = chkAtivo.Checked; + } + + // --- MÉTODOS OBRIGATÓRIOS --- + + protected override void OnNovo() + { + _fornecedor = new ModeloFornecedores(); + // Implementar lógica de limpar campos se necessário + txtNome.Focus(); + } + + protected override void OnSalvar() + { + try + { + PreencherModel(); + // BLLFornecedor.Salvar(_fornecedor); + MessageBox.Show("Fornecedor salvo com sucesso!", "Sucesso", MessageBoxButtons.OK, MessageBoxIcon.Information); + } + catch (Exception ex) + { + MessageBox.Show("Erro ao salvar: " + ex.Message); + } + } + + protected override void OnAlterar() { } + protected override void OnExcluir() { } + protected override void OnLocalizar() { } + protected override void OnCancelar() { OnNovo(); } + } +} \ No newline at end of file diff --git a/UI/Dashboards/Cadastros/ServicosCadastroPanel.cs b/UI/Dashboards/Cadastros/ServicosCadastroPanel.cs new file mode 100644 index 0000000..d346bb9 --- /dev/null +++ b/UI/Dashboards/Cadastros/ServicosCadastroPanel.cs @@ -0,0 +1,104 @@ +using CPM; +using MLL; +using System; +using System.Drawing; +using System.Windows.Forms; +using UI; + +namespace UI +{ + public partial class ServicosCadastroPanel : FormularioModelo + { + private ModeloServicos _servico = new ModeloServicos(); + + // Controles - Identificação + private LV_TEXTBOX1 txtId, txtEmpresaId, txtNome, txtDescricao; + + // Controles - Financeiro e Comissão + private LV_TEXTBOX1 txtValorVenda, txtCusto, txtTipoComissao, txtValorComissao; + + // Controles - Operacional + private LV_TEXTBOX1 txtTempoEstimado; + private CheckBox chkAtivo; + + public ServicosCadastroPanel() + { + this.Titulo = "Cadastro de Serviços"; + MontarInterface(); + } + + private void MontarInterface() + { + // --- SEÇÃO 1: Definição do Serviço --- + content.Controls.Add(CreateSectionHeader("IDENTIFICAÇÃO DO SERVIÇO", 20)); + + txtId = AddInput(content, "ID", 20, 50, 70, 30, true); + txtEmpresaId = AddInput(content, "ID EMPRESA", 100, 50, 80, 30); + txtNome = AddInput(content, "NOME DO SERVIÇO", 190, 50, 690, 30); + + txtDescricao = AddInput(content, "DESCRIÇÃO DETALHADA / ESCOPO", 20, 105, 860, 50); + txtDescricao.Multiline = true; + + // --- SEÇÃO 2: Financeiro e Precificação --- + content.Controls.Add(CreateSectionHeader("VALORES E CUSTOS", 175)); + + txtValorVenda = AddInput(content, "VALOR DE VENDA (R$)", 20, 205, 180, 30); + txtCusto = AddInput(content, "CUSTO ESTIMADO (R$)", 210, 205, 180, 30); + + // --- SEÇÃO 3: Regras de Comissão e Tempo --- + content.Controls.Add(CreateSectionHeader("COMISSIONAMENTO E OPERAÇÃO", 270)); + + txtTipoComissao = AddInput(content, "TIPO COMISSÃO (FIXO/%)", 20, 300, 180, 30); + txtValorComissao = AddInput(content, "VALOR DA COMISSÃO", 210, 300, 180, 30); + + txtTempoEstimado = AddInput(content, "TEMPO ESTIMADO (MIN)", 400, 300, 180, 30); + + chkAtivo = CreateCheckBox("SERVIÇO ATIVO PARA VENDA", 600, 318); + content.Controls.Add(chkAtivo); + + // Ajuste da altura do conteúdo (Serviços costumam ser telas mais curtas) + content.Height = 450; + } + + private void PreencherModel() + { + _servico.Nome = txtNome.Text; + _servico.Descricao = txtDescricao.Text; + _servico.TipoComissao = txtTipoComissao.Text; + _servico.Ativo = chkAtivo.Checked; + + // Conversões Numéricas + if (int.TryParse(txtEmpresaId.Text, out int emp)) _servico.EmpresaId = emp; + if (int.TryParse(txtTempoEstimado.Text, out int tempo)) _servico.TempoEstimado = tempo; + + if (decimal.TryParse(txtValorVenda.Text, out decimal valor)) _servico.ValorPadrao = valor; + if (decimal.TryParse(txtCusto.Text, out decimal custo)) _servico.Custo = custo; + if (decimal.TryParse(txtValorComissao.Text, out decimal comissao)) _servico.ValorComissao = comissao; + } + + protected override void OnNovo() + { + _servico = new ModeloServicos(); + txtNome.Focus(); + } + + protected override void OnSalvar() + { + try + { + PreencherModel(); + // BLLServicos.Salvar(_servico); + MessageBox.Show("Serviço cadastrado com sucesso!", "Sucesso", MessageBoxButtons.OK, MessageBoxIcon.Information); + } + catch (Exception ex) + { + MessageBox.Show("Erro ao salvar serviço: " + ex.Message); + } + } + + protected override void OnAlterar() { } + protected override void OnExcluir() { } + protected override void OnLocalizar() { } + protected override void OnCancelar() { OnNovo(); } + } +} \ No newline at end of file diff --git a/UI/Dashboards/Cadastros/ServicosCadastroPanel.resx b/UI/Dashboards/Cadastros/ServicosCadastroPanel.resx new file mode 100644 index 0000000..1af7de1 --- /dev/null +++ b/UI/Dashboards/Cadastros/ServicosCadastroPanel.resx @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/UI/Dashboards/Cadastros/TransportadorasCadastroPanel.cs b/UI/Dashboards/Cadastros/TransportadorasCadastroPanel.cs new file mode 100644 index 0000000..7946b95 --- /dev/null +++ b/UI/Dashboards/Cadastros/TransportadorasCadastroPanel.cs @@ -0,0 +1,126 @@ +using CPM; +using MLL; +using System; +using System.Drawing; +using System.Windows.Forms; +using UI; + +namespace UI +{ + public partial class TransportadorasCadastroPanel : FormularioModelo + { + private ModeloTransportadoras _transportadora = new ModeloTransportadoras(); + + // Controles - Identificação + private LV_TEXTBOX1 txtId, txtEmpresaId, txtRazaoSocial, txtNomeFantasia, txtCNPJ; + + // Controles - Localização + private LV_TEXTBOX1 txtCep, txtEndereco, txtNumero, txtBairro, txtCidade, txtUF, txtComplemento; + + // Controles - Logística e Contato + private LV_TEXTBOX1 txtTelefone, txtEmail, txtTipoFrete, txtPrazo, txtValorFrete, txtObservacoes; + private CheckBox chkAtivo; + + public TransportadorasCadastroPanel() + { + this.Titulo = "Cadastro de Transportadoras"; + MontarInterface(); + } + + private void MontarInterface() + { + // --- SEÇÃO 1: Identificação --- + content.Controls.Add(CreateSectionHeader("DADOS DA TRANSPORTADORA", 20)); + + txtId = AddInput(content, "ID", 20, 50, 70, 30, true); + txtEmpresaId = AddInput(content, "ID EMPRESA", 100, 50, 80, 30); + txtCNPJ = AddInput(content, "CNPJ", 190, 50, 200, 30); + + txtRazaoSocial = AddInput(content, "RAZÃO SOCIAL", 20, 105, 430, 30); + txtNomeFantasia = AddInput(content, "NOME FANTASIA", 460, 105, 420, 30); + + // --- SEÇÃO 2: Localização --- + content.Controls.Add(CreateSectionHeader("ENDEREÇO SEDE", 175)); + + txtCep = AddInput(content, "CEP", 20, 205, 100, 30); + txtEndereco = AddInput(content, "LOGRADOURO", 130, 205, 350, 30); + txtNumero = AddInput(content, "Nº", 490, 205, 70, 30); + txtBairro = AddInput(content, "BAIRRO", 570, 205, 190, 30); + txtUF = AddInput(content, "UF", 770, 205, 50, 30); + + txtCidade = AddInput(content, "CIDADE", 20, 260, 300, 30); + txtComplemento = AddInput(content, "COMPLEMENTO", 330, 260, 550, 30); + + // --- SEÇÃO 3: Regras de Logística e Contato --- + content.Controls.Add(CreateSectionHeader("CONFIGURAÇÕES DE FRETE E CONTATO", 330)); + + txtTipoFrete = AddInput(content, "TIPO DE FRETE (CIF/FOB)", 20, 360, 180, 30); + txtPrazo = AddInput(content, "PRAZO MÉDIO (DIAS)", 210, 360, 150, 30); + txtValorFrete = AddInput(content, "VALOR PADRÃO (R$)", 370, 360, 150, 30); + + chkAtivo = CreateCheckBox("TRANSPORTADORA ATIVA", 540, 378); + content.Controls.Add(chkAtivo); + + txtTelefone = AddInput(content, "TELEFONE", 20, 415, 180, 30); + txtEmail = AddInput(content, "E-MAIL PARA COTAÇÃO", 210, 415, 670, 30); + + // --- SEÇÃO 4: Observações --- + content.Controls.Add(CreateSectionHeader("OBSERVAÇÕES ADICIONAIS", 485)); + txtObservacoes = AddInput(content, "NOTAS DE LOGÍSTICA", 20, 515, 860, 80); + txtObservacoes.Height = 80; + + content.Height = 630; + } + + private void PreencherModel() + { + _transportadora.RazaoSocial = txtRazaoSocial.Text; + _transportadora.NomeFantasia = txtNomeFantasia.Text; + _transportadora.CNPJ = txtCNPJ.Text; + + _transportadora.Cep = txtCep.Text; + _transportadora.Endereco = txtEndereco.Text; + _transportadora.Bairro = txtBairro.Text; + _transportadora.Cidade = txtCidade.Text; + _transportadora.UF = txtUF.Text; + _transportadora.Complemento = txtComplemento.Text; + + // Conversões numéricas + if (int.TryParse(txtNumero.Text, out int num)) _transportadora.Numero = num; + if (int.TryParse(txtEmpresaId.Text, out int emp)) _transportadora.EmpresaId = emp; + if (int.TryParse(txtPrazo.Text, out int prazo)) _transportadora.PrazoEntrega = prazo; + if (decimal.TryParse(txtValorFrete.Text, out decimal valor)) _transportadora.ValorFretePadrao = valor; + + _transportadora.TipoFrete = txtTipoFrete.Text; + _transportadora.Telefone = txtTelefone.Text; + _transportadora.Email = txtEmail.Text; + _transportadora.Observacoes = txtObservacoes.Text; + _transportadora.Ativo = chkAtivo.Checked; + } + + protected override void OnNovo() + { + _transportadora = new ModeloTransportadoras(); + txtCNPJ.Focus(); + } + + protected override void OnSalvar() + { + try + { + PreencherModel(); + // BLLTransportadora.Salvar(_transportadora); + MessageBox.Show("Transportadora registrada com sucesso!", "Sucesso", MessageBoxButtons.OK, MessageBoxIcon.Information); + } + catch (Exception ex) + { + MessageBox.Show("Erro ao processar dados: " + ex.Message); + } + } + + protected override void OnAlterar() { } + protected override void OnExcluir() { } + protected override void OnLocalizar() { } + protected override void OnCancelar() { OnNovo(); } + } +} \ No newline at end of file diff --git a/UI/Dashboards/Dashmain/MainForm.cs b/UI/Dashboards/Dashmain/MainForm.cs index 2f5d973..9dd8cc7 100644 --- a/UI/Dashboards/Dashmain/MainForm.cs +++ b/UI/Dashboards/Dashmain/MainForm.cs @@ -1,6 +1,7 @@ using CCH; using CustomMessageBox; using DAL; +using LevelOS; using System; using System.Drawing; using System.Windows.Forms; @@ -18,6 +19,15 @@ namespace UI private readonly AgendaCadastroPanel _pAgendaCadastro; private readonly AgendaConsultaPanel _pAgendaConsulta; private readonly FuncionariosCadastroPanel _pfuncionariosCadastro ; + + private readonly EquipamentosCadastroPanel _pequipamentosCadastroPanel; + private readonly ContratosCadastroPanel _pcontratosCadastroPanel; + private readonly FornecedoresCadastroPanel _pfornecedoresCadastroPanel; + private readonly TransportadorasCadastroPanel _ptransportadorasCadastroPanel; + private readonly ServicosCadastroPanel _pservicosCadastroPanel; + + //Painel financeiro + private readonly BoletoCadastroPanel _pboletoCadastroPanel; private readonly Panel _pOrdens; private readonly Panel _pProdutos; private readonly Panel _pEstoque; @@ -41,6 +51,12 @@ namespace UI _pAgendaCadastro = new AgendaCadastroPanel { Dock = DockStyle.Fill, Visible = false }; _pAgendaConsulta = new AgendaConsultaPanel { Dock = DockStyle.Fill, Visible = false }; _pfuncionariosCadastro = new FuncionariosCadastroPanel { Dock = DockStyle.Fill, Visible = false }; + _pboletoCadastroPanel = new BoletoCadastroPanel { Dock = DockStyle.Fill, Visible = false }; + _pequipamentosCadastroPanel = new EquipamentosCadastroPanel { Dock = DockStyle.Fill, Visible = false }; + _pcontratosCadastroPanel = new ContratosCadastroPanel { Dock = DockStyle.Fill, Visible = false }; + _pfornecedoresCadastroPanel = new FornecedoresCadastroPanel { Dock = DockStyle.Fill, Visible = false }; + _ptransportadorasCadastroPanel = new TransportadorasCadastroPanel { Dock = DockStyle.Fill, Visible = false }; + _pservicosCadastroPanel = new ServicosCadastroPanel { Dock = DockStyle.Fill, Visible = false }; _pOrdens = PlaceholderPanel("Ordens de Serviço", Color.FromArgb(22, 163, 74)); _pProdutos = PlaceholderPanel("Catálogo de Produtos", Color.FromArgb(217, 119, 6)); _pEstoque = PlaceholderPanel("Controle de Estoque", Color.FromArgb(234, 88, 12)); @@ -50,6 +66,12 @@ namespace UI mainContainer.Controls.Add(_pFinanceiro); mainContainer.Controls.Add(_pAgendaCadastro); mainContainer.Controls.Add(_pAgendaConsulta); + mainContainer.Controls.Add(_pboletoCadastroPanel); + mainContainer.Controls.Add(_pequipamentosCadastroPanel); + mainContainer.Controls.Add(_pcontratosCadastroPanel); + mainContainer.Controls.Add(_pfornecedoresCadastroPanel); + mainContainer.Controls.Add(_ptransportadorasCadastroPanel); + mainContainer.Controls.Add(_pservicosCadastroPanel); mainContainer.Controls.Add(_pEstoque); mainContainer.Controls.Add(_pProdutos); mainContainer.Controls.Add(_pOrdens); @@ -85,7 +107,12 @@ namespace UI case 5: ShowPanel(_pEstoque); break; case 9: ShowPanel(_pFinanceiro); break; case 99: ShowPanel(_pClientes); break; + case 100: ShowPanel(_pequipamentosCadastroPanel); break; + case 101: ShowPanel(_pcontratosCadastroPanel); break; + case 102: ShowPanel(_pfornecedoresCadastroPanel); break; case 103: ShowPanel(_pfuncionariosCadastro); break; + case 104: ShowPanel(_ptransportadorasCadastroPanel); break; + case 105: ShowPanel(_pservicosCadastroPanel); break; case 106: ShowPanel(_pEmpresa); break; @@ -94,6 +121,10 @@ namespace UI case 301: ShowPanel(_pAgendaConsulta); break; + + case 500: ShowPanel(_pboletoCadastroPanel); break; + + } } @@ -110,7 +141,12 @@ namespace UI _pAgendaCadastro.Visible = (panelToShow == _pAgendaCadastro); _pAgendaConsulta.Visible = (panelToShow == _pAgendaConsulta); _pfuncionariosCadastro.Visible = (panelToShow == _pfuncionariosCadastro); - + _pboletoCadastroPanel.Visible = (panelToShow == _pboletoCadastroPanel); + _pequipamentosCadastroPanel.Visible = (panelToShow == _pequipamentosCadastroPanel); + _pcontratosCadastroPanel.Visible = (panelToShow == _pcontratosCadastroPanel); + _pfornecedoresCadastroPanel.Visible = (panelToShow == _pfornecedoresCadastroPanel); + _ptransportadorasCadastroPanel.Visible = (panelToShow == _ptransportadorasCadastroPanel); + _pservicosCadastroPanel.Visible = (panelToShow == _pservicosCadastroPanel); if (panelToShow.Visible) { panelToShow.BringToFront(); diff --git a/UI/Dashboards/Dashmain/SidebarControl.cs b/UI/Dashboards/Dashmain/SidebarControl.cs index 6b5fbd8..9bc837a 100644 --- a/UI/Dashboards/Dashmain/SidebarControl.cs +++ b/UI/Dashboards/Dashmain/SidebarControl.cs @@ -156,6 +156,7 @@ namespace UI _subMenuFinanceiro.Items.Add("💳 Contas", null, (s, e) => { /* Lógica */ }); _subMenuFinanceiro.Items.Add("📈 Contas a receber", null, (s, e) => { /* Lógica */ }); _subMenuFinanceiro.Items.Add("📉 Contas a pagar", null, (s, e) => { /* Lógica */ }); + _subMenuFinanceiro.Items.Add("📉 Boletos/Duplicatas", null, (s, e) => { NavItemClicked?.Invoke(this, 500); }); _subMenuFinanceiro.Items.Add(new ToolStripSeparator()); // Linha divisória _subMenuFinanceiro.Items.Add("🛒 Compras", null, (s, e) => { /* Lógica */ }); _subMenuFinanceiro.Items.Add("💰 Vendas", null, (s, e) => { /* Lógica */ }); diff --git a/UI/ModeloPanel/Formulariomodelo.cs b/UI/ModeloPanel/Formulariomodelo.cs index 7a1d784..43e5bb9 100644 --- a/UI/ModeloPanel/Formulariomodelo.cs +++ b/UI/ModeloPanel/Formulariomodelo.cs @@ -4,7 +4,7 @@ using System; using System.Drawing; using System.Windows.Forms; -namespace LevelOS +namespace UI { /// /// Modelo base para todos os formulários do sistema. diff --git a/UI/ModeloPanel/Formulariomodelo.resx b/UI/ModeloPanel/Formulariomodelo.resx new file mode 100644 index 0000000..1af7de1 --- /dev/null +++ b/UI/ModeloPanel/Formulariomodelo.resx @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file