From f8a0ada7117e1fc5b713b8db6a50289c49520bef Mon Sep 17 00:00:00 2001 From: levelcode365 Date: Tue, 12 May 2026 00:53:34 -0300 Subject: [PATCH] =?UTF-8?q?12/05/2026=20-=20Criando=20formulario=20Abertur?= =?UTF-8?q?a=20de=20ordem=20de=20servi=C3=A7o?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- UI/.github/agents/Ollama.agent.md | 8 + .../NotasItensRastreabilidadePanel.cs | 91 ++ UI/Dashboards/Cadastros/NotasRefNFPPanel.cs | 90 ++ .../Cadastros/NotasRetencoesPanel.cs | 85 ++ .../Cadastros/OrcaPadraoCadastroPanel.cs | 206 +++++ UI/Dashboards/Cadastros/OrcasCadastroPanel.cs | 237 +++++ .../Cadastros/OrdensCadastroPanel.cs | 837 ++++++++++++++++++ .../Cadastros/OrdensCadastroPanel.resx | 120 +++ .../Consultas/NotasXmlConsultaPanel.cs | 204 +++++ .../Consultas/OrcaPadraoConsultaPanel.cs | 207 +++++ UI/Dashboards/Consultas/OrcasConsultaPanel.cs | 179 ++++ UI/Dashboards/Dashmain/MainForm.cs | 14 +- UI/Dashboards/Dashmain/SidebarControl.cs | 4 +- UI/UI.csproj | 4 + 14 files changed, 2282 insertions(+), 4 deletions(-) create mode 100644 UI/.github/agents/Ollama.agent.md create mode 100644 UI/Dashboards/Cadastros/NotasItensRastreabilidadePanel.cs create mode 100644 UI/Dashboards/Cadastros/NotasRefNFPPanel.cs create mode 100644 UI/Dashboards/Cadastros/NotasRetencoesPanel.cs create mode 100644 UI/Dashboards/Cadastros/OrcaPadraoCadastroPanel.cs create mode 100644 UI/Dashboards/Cadastros/OrcasCadastroPanel.cs create mode 100644 UI/Dashboards/Cadastros/OrdensCadastroPanel.cs create mode 100644 UI/Dashboards/Cadastros/OrdensCadastroPanel.resx create mode 100644 UI/Dashboards/Consultas/NotasXmlConsultaPanel.cs create mode 100644 UI/Dashboards/Consultas/OrcaPadraoConsultaPanel.cs create mode 100644 UI/Dashboards/Consultas/OrcasConsultaPanel.cs diff --git a/UI/.github/agents/Ollama.agent.md b/UI/.github/agents/Ollama.agent.md new file mode 100644 index 0000000..a206883 --- /dev/null +++ b/UI/.github/agents/Ollama.agent.md @@ -0,0 +1,8 @@ +--- +name: Ollama +description: Descreva o que esse agente personalizado faz e quando usá-lo. +--- + +# Ollama + +Defina o que esse agente personalizado faz, incluindo o seu comportamento, funcionalidades e quaisquer instruções específicas de operação. \ No newline at end of file diff --git a/UI/Dashboards/Cadastros/NotasItensRastreabilidadePanel.cs b/UI/Dashboards/Cadastros/NotasItensRastreabilidadePanel.cs new file mode 100644 index 0000000..fd09ac5 --- /dev/null +++ b/UI/Dashboards/Cadastros/NotasItensRastreabilidadePanel.cs @@ -0,0 +1,91 @@ +using CPM; +using MLL; +using System; +using System.Drawing; +using System.Windows.Forms; +using UI; + +namespace UI +{ + public partial class NotasItensRastreabilidadePanel : FormularioModelo + { + private ModeloNotasItensRastreabilidade _rastreio = new ModeloNotasItensRastreabilidade(); + + public NotasItensRastreabilidadePanel() + { + this.Titulo = "Rastreabilidade de Lote e Logística"; + this.Size = new Size(650, 450); + MontarInterface(); + } + + private void MontarInterface() + { + // IDs de Vinculação + AddInput(content, "ID RASTREIO", 20, 20, 100, 30, true); + AddInput(content, "CÓD. ITEM", 130, 20, 100, 30, true); + + content.Controls.Add(CreateSectionHeader("INFORMAÇÕES DO LOTE", 70)); + + // Dados do Lote + var txtLote = AddInput(content, "NÚMERO DO LOTE", 20, 100, 250, 30); + txtLote.ForeColor = Color.DarkRed; // Destaque para campo crítico + + AddInput(content, "QUANTIDADE NO LOTE", 280, 100, 150, 30); + + // Datas + AddInput(content, "DATA FABRICAÇÃO", 20, 160, 180, 30); + AddInput(content, "DATA VALIDADE", 210, 160, 180, 30); + + // Código de Agregação (Logística Avançada) + content.Controls.Add(CreateSectionHeader("AGREGAÇÃO E LOGÍSTICA", 220)); + var txtAgreg = AddInput(content, "CÓDIGO DE AGREGAÇÃO (CAgreg)", 20, 250, 400, 30); + + Label lblObs = new Label + { + Text = "* Utilizado para identificar volumes/paletes que agrupam unidades rastreáveis.", + Location = new Point(20, 285), + AutoSize = true, + Font = new Font("Segoe UI", 8, FontStyle.Italic), + ForeColor = Color.Gray + }; + content.Controls.Add(lblObs); + + content.Height = 330; + } + + // --- LÓGICA DE OPERAÇÃO --- + + protected override void OnSalvar() + { + // Validação de segurança: Validade não pode ser menor que fabricação + // No LevelOS, poderíamos disparar um alerta se o lote estiver vencido. + MessageBox.Show("Dados de rastreabilidade salvos. O item está pronto para o XML.", "LevelOS Logística"); + + } + protected override void OnAlterar() + { + throw new NotImplementedException(); + } + protected override void OnLocalizar() + { + throw new NotImplementedException(); + } + protected override void OnNovo() => LimparCamposRecursivo(content); + protected override void OnExcluir() + { + if (MessageBox.Show("Remover rastreabilidade deste item?", "Confirmação", MessageBoxButtons.YesNo) == DialogResult.Yes) + { + MessageBox.Show("Rastreio removido."); + } + } + protected override void OnCancelar() { } + private void LimparCamposRecursivo(Control container) + { + foreach (Control c in container.Controls) + { + if (c is LV_TEXTBOX1 t) t.Text = ""; + if (c.HasChildren) LimparCamposRecursivo(c); + } + } + } +} \ No newline at end of file diff --git a/UI/Dashboards/Cadastros/NotasRefNFPPanel.cs b/UI/Dashboards/Cadastros/NotasRefNFPPanel.cs new file mode 100644 index 0000000..b1ec09c --- /dev/null +++ b/UI/Dashboards/Cadastros/NotasRefNFPPanel.cs @@ -0,0 +1,90 @@ +using CPM; +using MLL; +using System; +using System.Drawing; +using System.Windows.Forms; +using UI; + +namespace UI +{ + public partial class NotasRefNFPPanel : FormularioModelo + { + private ModeloNotasRefNFP _refNfp = new ModeloNotasRefNFP(); + + public NotasRefNFPPanel() + { + this.Titulo = "Referenciar Nota Fiscal de Produtor Rural"; + this.Size = new Size(750, 500); + MontarInterface(); + } + + private void MontarInterface() + { + // Vinculação com a Nota Atual + AddInput(content, "ID REF", 20, 20, 80, 30, true); + AddInput(content, "CÓD. NOTA PRINCIPAL", 110, 20, 150, 30, true); + + content.Controls.Add(CreateSectionHeader("LOCALIZAÇÃO E PERÍODO", 70)); + + // UF e Período (AAMM) + AddInput(content, "UF (CÓDIGO)", 20, 100, 100, 30); // Ex: 35 para SP + var txtPeriodo = AddInput(content, "MÊS/ANO (AAMM)", 130, 100, 120, 30); + Label lblDica = new Label + { + Text = "Formato: YYMM (Ex: 2605)", + Location = new Point(130, 135), + Font = new Font("Segoe UI", 7, FontStyle.Italic), + AutoSize = true + }; + content.Controls.Add(lblDica); + + content.Controls.Add(CreateSectionHeader("IDENTIFICAÇÃO DO PRODUTOR", 170)); + + AddInput(content, "CNPJ / CPF", 20, 200, 200, 30); + AddInput(content, "INSCRIÇÃO ESTADUAL", 230, 200, 200, 30); + AddInput(content, "NOME DO PRODUTOR", 20, 250, 410, 30); + + content.Controls.Add(CreateSectionHeader("DADOS DO DOCUMENTO", 300)); + + AddInput(content, "MODELO", 20, 330, 80, 30); // Geralmente 04 ou 55 + AddInput(content, "SÉRIE", 110, 330, 80, 30); + AddInput(content, "Nº DA NOTA (NNF)", 200, 330, 150, 30); + + content.Height = 420; + } + + // --- MÉTODOS DE AÇÃO --- + + protected override void OnSalvar() + { + // Validação Básica de NFP + if (string.IsNullOrEmpty(_refNfp.NNF)) + { + MessageBox.Show("O número da nota referenciada é obrigatório para a SEFAZ.", "Validação LevelOS"); + return; + } + + MessageBox.Show("Nota de Produtor Rural referenciada com sucesso!", "Financeiro/Fiscal"); + + } + + protected override void OnNovo() => LimparCamposRecursivo(content); + protected override void OnExcluir() { } + protected override void OnLocalizar() { } + protected override void OnAlterar() + { + throw new NotImplementedException(); + } + + protected override void OnCancelar() { } + + private void LimparCamposRecursivo(Control container) + { + foreach (Control c in container.Controls) + { + if (c is LV_TEXTBOX1 t) t.Text = string.Empty; + if (c.HasChildren) LimparCamposRecursivo(c); + } + } + } +} \ No newline at end of file diff --git a/UI/Dashboards/Cadastros/NotasRetencoesPanel.cs b/UI/Dashboards/Cadastros/NotasRetencoesPanel.cs new file mode 100644 index 0000000..9c02bee --- /dev/null +++ b/UI/Dashboards/Cadastros/NotasRetencoesPanel.cs @@ -0,0 +1,85 @@ +using CPM; +using MLL; +using System; +using System.Drawing; +using System.Windows.Forms; +using UI; + +namespace UI +{ + public partial class NotasRetencoesPanel : FormularioModelo + { + private ModeloNotasRetencoes _retencao = new ModeloNotasRetencoes(); + + public NotasRetencoesPanel() + { + this.Titulo = "Retenções de Tributos Federais (Deduções)"; + this.Size = new Size(650, 550); + MontarInterface(); + } + + private void MontarInterface() + { + // IDs de Vinculação + AddInput(content, "ID RETENÇÃO", 20, 20, 100, 30, true); + AddInput(content, "CÓD. NOTA", 130, 20, 100, 30, true); + + // Seção de Imposto de Renda (IRRF) + content.Controls.Add(CreateSectionHeader("IMPOSTO DE RENDA (IRRF)", 70)); + AddInput(content, "BASE DE CÁLCULO IRRF", 20, 100, 180, 30); + var txtIrrf = AddInput(content, "VALOR RETIDO IRRF", 210, 100, 180, 30); + txtIrrf.ForeColor = Color.Red; + + // Seção de Previdência (INSS) + content.Controls.Add(CreateSectionHeader("RETENÇÃO PREVIDENCIÁRIA (INSS)", 160)); + AddInput(content, "BASE RET. PREV.", 20, 190, 180, 30); + var txtPrev = AddInput(content, "VALOR RET. PREV.", 210, 190, 180, 30); + txtPrev.ForeColor = Color.Red; + + // Seção de CSRF (PIS/COFINS/CSLL) - Famosos 4,65% + content.Controls.Add(CreateSectionHeader("CONTRIBUIÇÕES SOCIAIS (CSRF)", 250)); + AddInput(content, "RETENÇÃO PIS", 20, 280, 120, 30); + AddInput(content, "RETENÇÃO COFINS", 150, 280, 120, 30); + AddInput(content, "RETENÇÃO CSLL", 280, 280, 120, 30); + + // Informativo de Totalizador + Label lblAviso = new Label + { + Text = "* Estes valores serão subtraídos do valor total bruto para gerar o Valor Líquido da Fatura.", + Location = new Point(20, 330), + AutoSize = true, + Font = new Font("Segoe UI", 8, FontStyle.Italic), + ForeColor = Color.DarkSlateBlue + }; + content.Controls.Add(lblAviso); + + content.Height = 380; + } + + protected override void OnSalvar() + { + // Lógica: No LevelOS, salvar aqui deve atualizar o "Valor Líquido" na tela principal da Nota + MessageBox.Show("Retenções calculadas e aplicadas ao documento.", "LevelOS Fiscal"); + + } + + protected override void OnNovo() => LimparCamposRecursivo(content); + + protected override void OnCancelar() { } + protected override void OnExcluir() { } + protected override void OnAlterar() { } + protected override void OnLocalizar() + { + throw new NotImplementedException(); + } + + private void LimparCamposRecursivo(Control container) + { + foreach (Control c in container.Controls) + { + if (c is LV_TEXTBOX1 t) t.Text = string.Empty; + if (c.HasChildren) LimparCamposRecursivo(c); + } + } + } +} \ No newline at end of file diff --git a/UI/Dashboards/Cadastros/OrcaPadraoCadastroPanel.cs b/UI/Dashboards/Cadastros/OrcaPadraoCadastroPanel.cs new file mode 100644 index 0000000..e726ac9 --- /dev/null +++ b/UI/Dashboards/Cadastros/OrcaPadraoCadastroPanel.cs @@ -0,0 +1,206 @@ +using BLL; +using MLL; +using System; +using System.Collections.Generic; +using System.Drawing; +using System.Windows.Forms; +using System.Linq; + +namespace UI +{ + public class OrcaPadraoCadastroPanel : UserControl + { + // ── DESIGN ────────────────────────────────────────────────────────── + private readonly Color AccentBlue = Color.FromArgb(37, 99, 235); + private readonly Color BorderColor = Color.FromArgb(226, 232, 240); + private readonly Color TextDark = Color.FromArgb(30, 41, 59); + + // ── CONTROLES ─────────────────────────────────────────────────────── + private RoundTextBox txtCodigo = null!; + private RoundTextBox txtNome = null!; + private TextBox txtObs = null!; + private ComboBox cmbUsado = null!; + private ComboBox cmbShowObs = null!; + private DataGridView dgvItens = null!; + + private ModeloOrcaPadrao _modelo = null!; + public event Action? OnVoltar; + + public OrcaPadraoCadastroPanel(ModeloOrcaPadrao modelo) + { + _modelo = modelo; + Dock = DockStyle.Fill; + BackColor = Color.White; + InitializeComponent(); + PreencherCampos(); + CarregarItens(); + } + + private void InitializeComponent() + { + var pnlHeader = new Panel { Dock = DockStyle.Top, Height = 60, BackColor = Color.FromArgb(248, 250, 252) }; + + var lblTitulo = new Label + { + Text = _modelo.ID_ORCA_PADRAO == 0 ? "Novo Orçamento Padrão" : "Editando Modelo", + Font = new Font("Segoe UI", 12f, FontStyle.Bold), + ForeColor = TextDark, + Location = new Point(20, 18), + AutoSize = true + }; + + var btnSalvar = new RoundButton + { + Text = "Salvar Modelo", + Size = new Size(130, 35), + Location = new Point(Width - 150, 12), + Anchor = AnchorStyles.Top | AnchorStyles.Right, + BackColor = AccentBlue, + ForeColor = Color.White, + Cursor = Cursors.Hand + }; + btnSalvar.Click += (s, e) => Salvar(); + + var btnVoltar = new RoundButton + { + Text = "Voltar", + Size = new Size(80, 35), + Location = new Point(Width - 240, 12), + Anchor = AnchorStyles.Top | AnchorStyles.Right, + BackColor = Color.FromArgb(203, 213, 225), + ForeColor = TextDark, + Cursor = Cursors.Hand + }; + btnVoltar.Click += (s, e) => OnVoltar?.Invoke(); + + pnlHeader.Controls.AddRange(new Control[] { lblTitulo, btnSalvar, btnVoltar }); + Controls.Add(pnlHeader); + + // Campos de Cabeçalho + txtCodigo = AddCampo("Código", 20, 80, 150); + txtNome = AddCampo("Nome do Modelo (Ex: Manutenção Básica)", 180, 80, 400); + + AddLabel("Ativo?", 20, 140); + cmbUsado = new ComboBox { Location = new Point(20, 160), Size = new Size(150, 26), DropDownStyle = ComboBoxStyle.DropDownList }; + cmbUsado.Items.AddRange(new[] { "S", "N" }); + + AddLabel("Exibir Obs no Impresso?", 180, 140); + cmbShowObs = new ComboBox { Location = new Point(180, 160), Size = new Size(150, 26), DropDownStyle = ComboBoxStyle.DropDownList }; + cmbShowObs.Items.AddRange(new[] { "S", "N" }); + + // Campo de Observação (Ajustado para dar espaço ao Grid) + AddLabel("Texto Padrão do Orçamento / Observações", 20, 205); + txtObs = new TextBox + { + Location = new Point(20, 225), + Size = new Size(Width - 40, 120), // Altura fixa para caber o grid embaixo + Anchor = AnchorStyles.Top | AnchorStyles.Left | AnchorStyles.Right, + Multiline = true, + ScrollBars = ScrollBars.Vertical, + Font = new Font("Consolas", 10f), + BorderStyle = BorderStyle.FixedSingle + }; + + // Grid de Itens + AddLabel("Itens do Modelo (Peças / Serviços)", 20, 360); + dgvItens = new DataGridView + { + Location = new Point(20, 380), + Size = new Size(Width - 40, Height - 400), + Anchor = AnchorStyles.Top | AnchorStyles.Bottom | AnchorStyles.Left | AnchorStyles.Right, + BackgroundColor = Color.White, + BorderStyle = BorderStyle.FixedSingle, + AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.Fill, + AllowUserToResizeRows = false, + RowHeadersVisible = false + }; + + ConfigurarGridItens(); + + Controls.AddRange(new Control[] { cmbUsado, cmbShowObs, txtObs, dgvItens }); + } + + private void ConfigurarGridItens() + { + dgvItens.Columns.Clear(); + dgvItens.Columns.Add(new DataGridViewTextBoxColumn { Name = "colTipo", HeaderText = "Tipo (P/S)", FillWeight = 15 }); + dgvItens.Columns.Add(new DataGridViewTextBoxColumn { Name = "colCodItem", HeaderText = "Cód. Item", FillWeight = 25 }); + dgvItens.Columns.Add(new DataGridViewTextBoxColumn { Name = "colQtd", HeaderText = "Quantidade", FillWeight = 20 }); + dgvItens.Columns.Add(new DataGridViewTextBoxColumn { Name = "colCodigoInterno", HeaderText = "Código Barras", FillWeight = 40 }); + } + + private RoundTextBox AddCampo(string label, int x, int y, int w) + { + AddLabel(label, x, y - 20); + var txt = new RoundTextBox { Location = new Point(x, y), Size = new Size(w, 30), Radius = 5, BorderColor = BorderColor }; + Controls.Add(txt); + return txt; + } + + private void AddLabel(string texto, int x, int y) + { + Controls.Add(new Label { Text = texto, Location = new Point(x, y), AutoSize = true, Font = new Font("Segoe UI", 8.5f, FontStyle.Bold), ForeColor = TextDark }); + } + + private void PreencherCampos() + { + txtCodigo.Text = _modelo.CODIGO; + txtNome.Text = _modelo.NOME; + txtObs.Text = _modelo.OBS; + cmbUsado.SelectedItem = string.IsNullOrEmpty(_modelo.USADO) ? "S" : _modelo.USADO; + cmbShowObs.SelectedItem = string.IsNullOrEmpty(_modelo.SHOW_OBS) ? "S" : _modelo.SHOW_OBS; + } + + private void CarregarItens() + { + if (_modelo.ID_ORCA_PADRAO == 0) return; + + // BLLOrcaPadraoItens bllItens = new BLLOrcaPadraoItens(DadosDaConexao.ObterConexao()); + // var itens = bllItens.ListarPorOrcamento(_modelo.CODIGO); + // foreach(var i in itens) dgvItens.Rows.Add(i.ITEM_TIPO, i.ITEM_COD, i.ITEM_QTD, i.CODIGO); + } + + private void Salvar() + { + if (string.IsNullOrEmpty(txtCodigo.Text)) + { + MessageBox.Show("Informe o código do modelo."); return; + } + + _modelo.CODIGO = txtCodigo.Text; + _modelo.NOME = txtNome.Text; + _modelo.OBS = txtObs.Text; + _modelo.USADO = cmbUsado.SelectedItem?.ToString() ?? "S"; + _modelo.SHOW_OBS = cmbShowObs.SelectedItem?.ToString() ?? "S"; + + // Coleta os itens do Grid + List listaItens = new List(); + foreach (DataGridViewRow row in dgvItens.Rows) + { + if (row.IsNewRow) continue; + + listaItens.Add(new ModeloOrcaPadraoItens + { + COD_ORCA = _modelo.CODIGO, + ITEM_TIPO = row.Cells["colTipo"].Value?.ToString() ?? "", + ITEM_COD = row.Cells["colCodItem"].Value?.ToString() ?? "", + ITEM_QTD = row.Cells["colQtd"].Value?.ToString() ?? "1", + CODIGO = row.Cells["colCodigoInterno"].Value?.ToString() ?? "" + }); + } + + try + { + // BLLOrcaPadrao bll = new BLLOrcaPadrao(DadosDaConexao.ObterConexao()); + // bll.SalvarComItens(_modelo, listaItens); + + MessageBox.Show("Modelo e Itens salvos com sucesso!", "LevelOS", MessageBoxButtons.OK, MessageBoxIcon.Information); + OnVoltar?.Invoke(); + } + catch (Exception ex) + { + MessageBox.Show("Erro ao salvar: " + ex.Message); + } + } + } +} \ No newline at end of file diff --git a/UI/Dashboards/Cadastros/OrcasCadastroPanel.cs b/UI/Dashboards/Cadastros/OrcasCadastroPanel.cs new file mode 100644 index 0000000..b937002 --- /dev/null +++ b/UI/Dashboards/Cadastros/OrcasCadastroPanel.cs @@ -0,0 +1,237 @@ +using BLL; +using MLL; +using System; +using System.Collections.Generic; +using System.Drawing; +using System.Linq; +using System.Windows.Forms; + +namespace UI +{ + public class OrcasCadastroPanel : UserControl + { + // ── DESIGN ────────────────────────────────────────────────────────── + private readonly Color AccentBlue = Color.FromArgb(37, 99, 235); + private readonly Color GreenColor = Color.FromArgb(34, 197, 94); + private readonly Color TextDark = Color.FromArgb(30, 41, 59); + private readonly Color BorderColor = Color.FromArgb(226, 232, 240); + + // ── CONTROLES ─────────────────────────────────────────────────────── + private RoundTextBox txtCodigo = null!, txtCliente = null!, txtDesconto = null!; + private Label lblTotalGeral = null!, lblTotalServicos = null!, lblTotalPecas = null!; + private ComboBox cmbSituacao = null!; + private TextBox txtObs = null!; + private DataGridView dgvItens = null!; + + private ModeloOrcas _orca = null!; + public event Action? OnVoltar; + + // ── CONSTRUTORES ───────────────────────────────────────────────────── + + // Construtor Vazio (Resolve o erro da sua variável global) + public OrcasCadastroPanel() + { + _orca = new ModeloOrcas(); // Inicializa um modelo limpo + Dock = DockStyle.Fill; + BackColor = Color.White; + InitializeComponent(); + } + + // Construtor com parâmetro (Para abrir direto na edição) + public OrcasCadastroPanel(ModeloOrcas orca) + { + _orca = orca; + Dock = DockStyle.Fill; + BackColor = Color.White; + InitializeComponent(); + PreencherCampos(); + } + + // ── MÉTODOS PÚBLICOS ──────────────────────────────────────────────── + + // Método para carregar um orçamento quando o painel já está instanciado + public void CarregarOrcamento(ModeloOrcas orca) + { + _orca = orca; + PreencherCampos(); + } + + // ── UI LOGIC ──────────────────────────────────────────────────────── + + private void InitializeComponent() + { + // HEADER + var pnlHeader = new Panel { Dock = DockStyle.Top, Height = 60, BackColor = Color.FromArgb(248, 250, 252) }; + + // Título dinâmico (se ID for 0 é novo) + var lblTitulo = new Label + { + Text = "Cadastro de Orçamento", + Font = new Font("Segoe UI", 12f, FontStyle.Bold), + ForeColor = TextDark, + Location = new Point(20, 18), + AutoSize = true + }; + + var btnSalvar = CreateHeaderButton("Gravar Orçamento", AccentBlue, Width - 160); + btnSalvar.Click += (s, e) => Salvar(); + + var btnImportar = CreateHeaderButton("Importar Padrão", GreenColor, Width - 320); + btnImportar.Click += (s, e) => ImportarModeloPadrao(); + + var btnVoltar = CreateHeaderButton("Voltar", Color.FromArgb(203, 213, 225), Width - 410, 80); + btnVoltar.ForeColor = TextDark; + btnVoltar.Click += (s, e) => OnVoltar?.Invoke(); + + pnlHeader.Controls.AddRange(new Control[] { lblTitulo, btnSalvar, btnImportar, btnVoltar }); + Controls.Add(pnlHeader); + + // CAMPOS PRINCIPAIS + txtCodigo = AddCampo("Nº Orçamento", 20, 80, 120); + txtCliente = AddCampo("Cliente (F2 para buscar)", 150, 80, 430); + + AddLabel("Situação", 590, 60); + cmbSituacao = new ComboBox + { + Location = new Point(590, 80), + Size = new Size(150, 30), + DropDownStyle = ComboBoxStyle.DropDownList, + FlatStyle = FlatStyle.Flat + }; + cmbSituacao.Items.AddRange(new[] { "Aberto", "Aprovado", "Cancelado", "Finalizado" }); + cmbSituacao.SelectedIndex = 0; + Controls.Add(cmbSituacao); + + // GRID DE ITENS + AddLabel("Itens do Orçamento (Produtos e Serviços)", 20, 130); + BuildGrid(); + + // PAINEL LATERAL DE TOTAIS + var pnlTotais = new Panel + { + Anchor = AnchorStyles.Bottom | AnchorStyles.Right, + Size = new Size(300, 180), + Location = new Point(Width - 320, Height - 190), + BackColor = Color.FromArgb(241, 245, 249) + }; + BuildTotais(pnlTotais); + Controls.Add(pnlTotais); + + // OBSERVAÇÕES + AddLabel("Observações do Orçamento", 20, Height - 190); + txtObs = new TextBox + { + Location = new Point(20, Height - 170), + Size = new Size(Width - 350, 150), + Multiline = true, + Anchor = AnchorStyles.Bottom | AnchorStyles.Left | AnchorStyles.Right, + BorderStyle = BorderStyle.FixedSingle + }; + Controls.Add(txtObs); + } + + private void BuildGrid() + { + dgvItens = new DataGridView + { + Location = new Point(20, 150), + Size = new Size(Width - 40, Height - 360), + Anchor = AnchorStyles.Top | AnchorStyles.Bottom | AnchorStyles.Left | AnchorStyles.Right, + BackgroundColor = Color.White, + BorderStyle = BorderStyle.None, + AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.Fill, + RowTemplate = { Height = 35 } + }; + + dgvItens.Columns.Add("colTipo", "Tipo (P/S)"); + dgvItens.Columns.Add("colCod", "Cód. Item"); + dgvItens.Columns.Add("colDesc", "Descrição"); + dgvItens.Columns.Add("colQtd", "Qtd"); + dgvItens.Columns.Add("colVunit", "V. Unit"); + dgvItens.Columns.Add("colTotal", "Total"); + + dgvItens.CellValueChanged += (s, e) => CalcularTotais(); + Controls.Add(dgvItens); + } + + private void BuildTotais(Panel p) + { + lblTotalServicos = AddLabelTotal(p, "Total Serviços: R$ 0,00", 15, 20); + lblTotalPecas = AddLabelTotal(p, "Total Peças: R$ 0,00", 15, 50); + + var lblDesc = new Label { Text = "Desconto R$:", Location = new Point(15, 85), AutoSize = true, Font = new Font("Segoe UI", 9f, FontStyle.Bold) }; + txtDesconto = new RoundTextBox { Location = new Point(120, 80), Size = new Size(150, 25), Radius = 2 }; + txtDesconto.TextChanged += (s, e) => CalcularTotais(); + + lblTotalGeral = new Label + { + Text = "TOTAL: R$ 0,00", + Location = new Point(15, 130), + Size = new Size(270, 30), + Font = new Font("Segoe UI", 14f, FontStyle.Bold), + ForeColor = AccentBlue, + TextAlign = ContentAlignment.MiddleRight + }; + + p.Controls.AddRange(new Control[] { lblTotalServicos, lblTotalPecas, lblTotalGeral, lblDesc, txtDesconto }); + } + + private void CalcularTotais() + { + // Lógica de soma simplificada para exemplo + lblTotalGeral.Text = "TOTAL: R$ 0,00"; + } + + private void PreencherCampos() + { + if (_orca == null) return; + + txtCodigo.Text = _orca.CODIGO; + txtCliente.Text = _orca.CLIENTE_NOME; + txtObs.Text = _orca.OBS; + cmbSituacao.SelectedItem = _orca.SITUACAO ?? "Aberto"; + txtDesconto.Text = _orca.DESCONTO; + } + + private void ImportarModeloPadrao() { /* Lógica de Importação */ } + + private void Salvar() + { + MessageBox.Show("Orçamento salvo com sucesso!"); + OnVoltar?.Invoke(); + } + + // ── AUXILIARES DE DESIGN ───────────────────────────────────────────── + + private RoundTextBox AddCampo(string label, int x, int y, int w) + { + AddLabel(label, x, y - 20); + var txt = new RoundTextBox { Location = new Point(x, y), Size = new Size(w, 30), Radius = 5, BorderColor = BorderColor }; + Controls.Add(txt); + return txt; + } + + private void AddLabel(string texto, int x, int y) + { + Controls.Add(new Label { Text = texto, Location = new Point(x, y), AutoSize = true, Font = new Font("Segoe UI", 8.5f, FontStyle.Bold), ForeColor = TextDark }); + } + + private Label AddLabelTotal(Panel p, string texto, int x, int y) + { + var lbl = new Label { Text = texto, Location = new Point(x, y), AutoSize = true, Font = new Font("Segoe UI", 9f) }; + p.Controls.Add(lbl); + return lbl; + } + + private RoundButton CreateHeaderButton(string text, Color color, int x, int w = 130) => new RoundButton + { + Text = text, + Size = new Size(w, 35), + Location = new Point(x, 12), + Anchor = AnchorStyles.Top | AnchorStyles.Right, + BackColor = color, + ForeColor = Color.White, + Cursor = Cursors.Hand + }; + } +} \ No newline at end of file diff --git a/UI/Dashboards/Cadastros/OrdensCadastroPanel.cs b/UI/Dashboards/Cadastros/OrdensCadastroPanel.cs new file mode 100644 index 0000000..04481cf --- /dev/null +++ b/UI/Dashboards/Cadastros/OrdensCadastroPanel.cs @@ -0,0 +1,837 @@ +using CPM; +using MLL; +using System; +using System.Drawing; +using System.Windows.Forms; + +namespace UI +{ + public partial class OrdensCadastroPanel : UserControl + { + //Variaveis auxiliares + private string nomeCliente = "Nicolas Felipe G. dos santos"; + // ── CORES ────────────────────────────────────────────────────────────── + private readonly Color CorPreta = Color.FromArgb(20, 20, 20); + private readonly Color CorVerde = Color.FromArgb(22, 163, 74); + private readonly Color CorVerdeHover = Color.FromArgb(16, 120, 55); + private readonly Color CorVermelha = Color.FromArgb(220, 38, 38); + private readonly Color CorVermelhaHov = Color.FromArgb(170, 20, 20); + private readonly Color CorAzul = Color.FromArgb(37, 99, 235); + private readonly Color CorCinzaClaro = Color.FromArgb(245, 245, 245); + private readonly Color CorCinzaBorda = Color.FromArgb(200, 200, 200); + private readonly Color CorTexto = Color.FromArgb(30, 41, 59); + private readonly Color CorFocoBorda = Color.FromArgb(37, 99, 235); + private readonly Color CorLaranja = Color.FromArgb(253, 186, 116); + private readonly Color CorBranca = Color.FromArgb(255, 255, 255); + + // ── CAMPOS ───────────────────────────────────────────────────────────── + private Label lblNumOS; + private Label lblCliente; + private Label lblEndereco; + private Label lblTelefone; + private Label lblCodVal; + private DateTimePicker dtpEntrada; + private DateTimePicker dtpPronto; + private DateTimePicker dtpSaida; + private ComboBox cmbSituacao; + private Label lblGarantia; + private LV_TEXTBOX1 txtAdiantamento; + private Label lblVMao; + private Label lblVPecas; + private Label lblVDesloca; + private Label lblVTerceiro; + private Label lblVOutros; + private Label lblVTotal; + private LV_TEXTBOX1 txtModelo; + private LV_TEXTBOX1 txtMarca; + private LV_TEXTBOX1 txtOperadora; + private LV_TEXTBOX1 txtSerial; + private LV_TEXTBOX1 txtPatrimonio; + private TextBox txtAcessorios; + private TextBox txtDefeito; + private TextBox txtObsAparelho; + private DataGridView dgvServicos; + private DataGridView dgvPecas; + private TextBox txtLaudo; + private TextBox txtObsServico; + private ComboBox cmbTecnico; + private ComboBox cmbPrioridade; + private TabControl tabs; + + private ModeloOrdens _os; + public event Action? OnVoltar; + + // ══════════════════════════════════════════════════════════════════════ + // CONSTRUTOR + // ══════════════════════════════════════════════════════════════════════ + public OrdensCadastroPanel() + { + _os = new ModeloOrdens(); + this.Dock = DockStyle.Fill; + this.BackColor = Color.White; + MontarInterface(); + } + + private void InitializeComponent() { } + + public void CarregarOS(ModeloOrdens os) + { + _os = os; + PreencherCampos(); + } + + // ══════════════════════════════════════════════════════════════════════ + // MONTAGEM PRINCIPAL + // ══════════════════════════════════════════════════════════════════════ + private void MontarInterface() + { + // Usamos posicionamento manual com Anchor/Dock + eventos Resize + // para controle preciso igual ao print. + + // 1) HEADER (topo fixo, 56px) + var pnlHeader = CriarHeader(); + pnlHeader.Dock = DockStyle.Top; + pnlHeader.Height = 56; + + // 2) RODAPÉ (base fixa, 46px) + var pnlRodape = CriarRodape(); + pnlRodape.Dock = DockStyle.Bottom; + pnlRodape.Height = 46; + + // 3) ÁREA CENTRAL (Fill) — contém cliente + meio + abas + var pnlCentral = new Panel { Dock = DockStyle.Fill, BackColor = Color.White }; + + // 3a) PAINEL CLIENTE (topo da área central, 72px) + var pnlCliente = CriarPainelCliente(); + pnlCliente.Dock = DockStyle.Top; + pnlCliente.Height = 72; + + // 3b) PAINEL MEIO (datas + situação + financeiro, 115px) + var pnlMeio = CriarPainelMeio(); + pnlMeio.Dock = DockStyle.Top; + pnlMeio.Height = 115; + + // 3c) ABAS (Fill restante) + var tabCtrl = CriarAbas(); + + // Adiciona em ordem inversa (DockStyle.Top empilha de cima pra baixo) + pnlCentral.Controls.Add(tabCtrl); // Fill — vai primeiro + pnlCentral.Controls.Add(pnlMeio); // Top + pnlCentral.Controls.Add(pnlCliente); // Top + + // Adiciona ao UserControl + this.Controls.Add(pnlCentral); + this.Controls.Add(pnlRodape); + this.Controls.Add(pnlHeader); + } + + // ══════════════════════════════════════════════════════════════════════ + // HEADER + // ══════════════════════════════════════════════════════════════════════ + private Panel CriarHeader() + { + var pnl = new Panel { BackColor = CorPreta }; + + lblNumOS = new Label + { + Text = "O.S. nº —", + Font = new Font("Segoe UI", 18f, FontStyle.Bold), + ForeColor = CorVermelha, + Location = new Point(16, 10), + AutoSize = true + }; + pnl.Controls.Add(lblNumOS); + + var btnGravar = LvBtn("✔ Gravar OS", CorVerde, CorVerdeHover, CorVerdeHover, 130, 36, br: 6); + var btnCancelar = LvBtn("✖ Cancelar", CorVermelha, CorVermelhaHov, CorVermelhaHov, 120, 36, br: 6); + + btnGravar.Click += (s, e) => Salvar(); + btnCancelar.Click += (s, e) => OnVoltar?.Invoke(); + + pnl.Resize += (s, e) => + { + btnCancelar.Location = new Point(pnl.Width - 128, 10); + btnGravar.Location = new Point(pnl.Width - 266, 10); + }; + + pnl.Controls.Add(btnGravar); + pnl.Controls.Add(btnCancelar); + return pnl; + } + + // ══════════════════════════════════════════════════════════════════════ + // PAINEL CLIENTE + // ══════════════════════════════════════════════════════════════════════ + private Panel CriarPainelCliente() + { + var pnl = new Panel { BackColor = Color.White, Padding = new Padding(10, 6, 10, 4) }; + pnl.Paint += (s, e) => + { + // Linha inferior separadora + using var pen = new Pen(CorCinzaBorda); + e.Graphics.DrawLine(pen, 0, pnl.Height - 1, pnl.Width, pnl.Height - 1); + }; + + // Linha 1 — "Cliente:" + nome + pnl.Controls.Add(Lbl("Cliente:", 10, 6, 60, bold: true, fs: 9f)); + lblCliente = new Label + { + ////Text = "—", + Text = this.nomeCliente, + Font = new Font("Segoe UI", 9.5f, FontStyle.Bold), + ForeColor = CorTexto, + Location = new Point(72, 6), + AutoSize = true + }; + pnl.Controls.Add(lblCliente); + + // "Cod.:" ancorado à direita + var lblRotCod = Lbl("Cod.:", 0, 6, 36, fs: 8.5f); + lblCodVal = Lbl("—", 0, 6, 60, fs: 8.5f); + lblRotCod.Anchor = AnchorStyles.Top | AnchorStyles.Right; + lblCodVal.Anchor = AnchorStyles.Top | AnchorStyles.Right; + pnl.Resize += (s, e) => + { + lblRotCod.Location = new Point(pnl.Width - 98, 6); + lblCodVal.Location = new Point(pnl.Width - 60, 6); + }; + pnl.Controls.Add(lblRotCod); + pnl.Controls.Add(lblCodVal); + + // Linha 2 — Endereço + pnl.Controls.Add(Lbl("Endereço:", 10, 28, 68, bold: true, fs: 8.5f)); + lblEndereco = new Label + { + Text = "—", + Font = new Font("Segoe UI", 8.5f), + ForeColor = CorAzul, + Location = new Point(80, 28), + AutoSize = true + }; + pnl.Controls.Add(lblEndereco); + + // Linha 3 — Telefones + pnl.Controls.Add(Lbl("Telefones:", 10, 50, 70, bold: true, fs: 8.5f)); + lblTelefone = new Label + { + Text = "—", + Font = new Font("Segoe UI", 8.5f), + ForeColor = CorAzul, + Location = new Point(82, 50), + AutoSize = true + }; + pnl.Controls.Add(lblTelefone); + + return pnl; + } + + // ══════════════════════════════════════════════════════════════════════ + // PAINEL MEIO — datas à esquerda | financeiro à direita + // ══════════════════════════════════════════════════════════════════════ + private Panel CriarPainelMeio() + { + var pnl = new Panel { BackColor = Color.White }; + pnl.Paint += (s, e) => + { + using var pen = new Pen(CorCinzaBorda); + e.Graphics.DrawLine(pen, 0, pnl.Height - 1, pnl.Width, pnl.Height - 1); + }; + + // ── FINANCEIRO (direita, largura fixa 270) ───────────────────────── + var pnlFin = CriarPainelFinanceiro(); + pnlFin.Anchor = AnchorStyles.Top | AnchorStyles.Right | AnchorStyles.Bottom; + + pnl.Resize += (s, e) => + { + pnlFin.Location = new Point(pnl.Width - 272, 0); + pnlFin.Size = new Size(272, pnl.Height); + }; + pnl.Controls.Add(pnlFin); + + // ── DATAS + SITUAÇÃO (esquerda) ──────────────────────────────────── + int lx = 10, lw = 62, tw = 148, th = 22; + + // Entrada + pnl.Controls.Add(Lbl("Entrada", lx, 12, lw, bold: true)); + dtpEntrada = DTP(pnl, lx + lw, 10, tw, th); + + // Pronto + pnl.Controls.Add(Lbl("Pronto", lx, 38, lw, bold: true)); + dtpPronto = DTP(pnl, lx + lw, 36, tw, th); + + // Saída + pnl.Controls.Add(Lbl("Saída", lx, 64, lw, bold: true)); + dtpSaida = DTP(pnl, lx + lw, 62, tw, th); + + // Situação da OS + int sx = 240; + pnl.Controls.Add(Lbl("Situação da OS", sx, 4, 130, bold: true)); + cmbSituacao = new ComboBox + { + Location = new Point(sx, 22), + Size = new Size(220, 26), + DropDownStyle = ComboBoxStyle.DropDownList, + Font = new Font("Segoe UI", 9f), + FlatStyle = FlatStyle.Flat + }; + cmbSituacao.Items.AddRange(new object[] + { + "Aguardando avaliação do técnico", + "Em Orçamento", + "Orçamento Aprovado", + "Em Reparo", + "Pronto", + "Entregue", + "Cancelado" + }); + cmbSituacao.SelectedIndex = 0; + pnl.Controls.Add(cmbSituacao); + + // Garantia até + lblGarantia = new Label + { + Text = "Garantia até —", + Font = new Font("Segoe UI", 9f, FontStyle.Bold), + ForeColor = CorVermelha, + Location = new Point(sx, 54), + AutoSize = true + }; + pnl.Controls.Add(lblGarantia); + + // Botão Histórico + var btnHist = LvBtn("Histórico", CorCinzaClaro, Color.FromArgb(180, 180, 180), Color.FromArgb(150, 150, 150), 88, 24, br: 4, bs: 1, bc: CorCinzaBorda); + btnHist.ForeColor = CorTexto; + btnHist.Location = new Point(sx, 80); + pnl.Controls.Add(btnHist); + + return pnl; + } + + // ── PAINEL FINANCEIRO ────────────────────────────────────────────────── + private Panel CriarPainelFinanceiro() + { + var pnl = new Panel { BackColor = Color.White }; + pnl.Paint += (s, e) => + { + using var pen = new Pen(CorCinzaBorda); + e.Graphics.DrawLine(pen, 0, 0, 0, pnl.Height); // borda esquerda + }; + + int lx = 10, vx = 160, vw = 100, rh = 17; + int[] yy = { 4, 22, 40, 58, 76, 94 }; + + // Adiantamento + pnl.Controls.Add(Lbl("Adiantamento", lx, yy[0] + 1, 110)); + txtAdiantamento = new LV_TEXTBOX1 + { + Location = new Point(vx, yy[0]), + Size = new Size(vw, 20), + BorderColor = CorCinzaBorda, + BorderFocusColor = CorFocoBorda, + BorderSize = 2, + Text = "0,00" + }; + pnl.Controls.Add(txtAdiantamento); + + // Valores somente leitura + lblVMao = LblV(pnl, "Mão-de-obra", lx, yy[1], vx, vw, rh); + lblVPecas = LblV(pnl, "Peças", lx, yy[2], vx, vw, rh); + lblVDesloca = LblV(pnl, "Deslocamento", lx, yy[3], vx, vw, rh); + lblVTerceiro = LblV(pnl, "Serviço terceiros", lx, yy[4], vx, vw, rh); + lblVOutros = LblV(pnl, "Outros", lx, yy[5], vx, vw, rh); + + // Botão <> + var btnGar = LvBtn("<>", CorVermelha, CorVermelhaHov, CorVermelhaHov, 108, 20, br: 3); + btnGar.Font = new Font("Segoe UI", 7.5f, FontStyle.Bold); + btnGar.Location = new Point(lx, 78); + pnl.Controls.Add(btnGar); + + // Total — linha inferior destacada + lblVTotal = new Label + { + Text = "R$ 0,00", + Font = new Font("Segoe UI", 11f, FontStyle.Bold), + ForeColor = CorVermelha, + Dock = DockStyle.Bottom, + Height = 26, + TextAlign = ContentAlignment.MiddleRight, + Padding = new Padding(0, 0, 6, 0), + BackColor = Color.FromArgb(255, 240, 240) + }; + pnl.Controls.Add(lblVTotal); + + return pnl; + } + + // ══════════════════════════════════════════════════════════════════════ + // ABAS + // ══════════════════════════════════════════════════════════════════════ + private TabControl CriarAbas() + { + tabs = new TabControl + { + Dock = DockStyle.Fill, + Font = new Font("Segoe UI", 9f), + DrawMode = TabDrawMode.OwnerDrawFixed, + ItemSize = new Size(0, 28), + Padding = new Point(12, 4) + }; + + tabs.DrawItem += (s, e) => + { + var pg = tabs.TabPages[e.Index]; + bool sel = (e.Index == tabs.SelectedIndex); + var rect = e.Bounds; + + using var bg = new SolidBrush(sel ? CorVermelha : CorCinzaClaro); + e.Graphics.FillRectangle(bg, rect); + + if (!sel) + { + using var pen = new Pen(CorCinzaBorda); + e.Graphics.DrawRectangle(pen, rect.X, rect.Y, rect.Width - 1, rect.Height - 1); + } + + var sf = new StringFormat { Alignment = StringAlignment.Center, LineAlignment = StringAlignment.Center }; + using var fg = new SolidBrush(sel ? Color.White : CorTexto); + e.Graphics.DrawString(pg.Text, + new Font("Segoe UI", 9f, sel ? FontStyle.Bold : FontStyle.Regular), + fg, rect, sf); + }; + + var pgAparelho = new TabPage("Aparelho") { BackColor = Color.White }; + var pgMaoObra = new TabPage("Mão de obra/Serviços") { BackColor = Color.White }; + var pgPecas = new TabPage("Peças utilizadas") { BackColor = Color.White }; + var pgLaudo = new TabPage("Obs/Laudo técnico") { BackColor = Color.White }; + var pgMisc = new TabPage("Miscelânea") { BackColor = Color.White }; + + ConfigAbaAparelho(pgAparelho); + ConfigAbaMaoObra(pgMaoObra); + ConfigAbaPecas(pgPecas); + ConfigAbaLaudo(pgLaudo); + ConfigAbaMisc(pgMisc); + + tabs.TabPages.AddRange(new[] { pgAparelho, pgMaoObra, pgPecas, pgLaudo, pgMisc }); + return tabs; + } + + // ── Aba Aparelho ─────────────────────────────────────────────────────── + private void ConfigAbaAparelho(TabPage page) + { + page.Padding = new Padding(6, 4, 6, 4); + + // Usamos posicionamento manual + Anchor para evitar TableLayoutPanel + // (que causava o problema dos campos desaparecendo) + + // ── Linha 1: Modelo | Marca ── + var lblModelo = Lbl("Modelo", 0, 0, 100); + txtModelo = LvTxt(page, 0, 16, 420, 26); + + var lblMarca = Lbl("Marca", 430, 0, 100); + txtMarca = new LV_TEXTBOX1 + { + BorderColor = CorCinzaBorda, + BorderFocusColor = CorFocoBorda, + BorderSize = 2, + Font = new Font("Segoe UI", 9.5f), + Location = new Point(430, 16), + Size = new Size(200, 26) // ajustado via Resize + }; + txtMarca.Anchor = AnchorStyles.Top | AnchorStyles.Left | AnchorStyles.Right; + + // ── Linha 2: Operadora | Serial | Nº Patrimônio ── + var lblOper = Lbl("Operadora", 0, 52, 100); + txtOperadora = LvTxt(page, 0, 68, 420, 26); + + var lblSer = Lbl("Serial", 430, 52, 100); + txtSerial = LvTxt(page, 430, 68, 200, 26); + + var lblPat = Lbl("Nº Patrimônio", 640, 52, 120); + txtPatrimonio = new LV_TEXTBOX1 + { + BorderColor = CorCinzaBorda, + BorderFocusColor = CorFocoBorda, + BorderSize = 2, + Font = new Font("Segoe UI", 9.5f), + Location = new Point(640, 68), + Size = new Size(200, 26) + }; + txtPatrimonio.Anchor = AnchorStyles.Top | AnchorStyles.Left | AnchorStyles.Right; + + // ── Linha 3: Acessórios | Defeito/Reclamação ── + var lblAces = Lbl("Acessórios", 0, 106, 120); + var lblDef = Lbl("Defeito/Reclamação", 430, 106, 200); + + txtAcessorios = new TextBox + { + Multiline = true, + ScrollBars = ScrollBars.Vertical, + BorderStyle = BorderStyle.FixedSingle, + Font = new Font("Segoe UI", 9.5f), + Location = new Point(0, 122), + Size = new Size(422, 140) + }; + + txtDefeito = new TextBox + { + Multiline = true, + ScrollBars = ScrollBars.Vertical, + BorderStyle = BorderStyle.FixedSingle, + Font = new Font("Segoe UI", 9.5f), + Location = new Point(430, 122), + Size = new Size(500, 140) // ajustado via Resize + }; + txtDefeito.Anchor = AnchorStyles.Top | AnchorStyles.Left | AnchorStyles.Right; + + // ── Linha 4: Observações (laranja) ── + var lblObs = Lbl("Observações", 0, 272, 120); + txtObsAparelho = new TextBox + { + Multiline = true, + ScrollBars = ScrollBars.Vertical, + BorderStyle = BorderStyle.FixedSingle, + Font = new Font("Segoe UI", 9.5f), + BackColor = CorLaranja, + Location = new Point(0, 288), + Size = new Size(930, 120) // ajustado via Resize + }; + txtObsAparelho.Anchor = AnchorStyles.Top | AnchorStyles.Left | AnchorStyles.Right | AnchorStyles.Bottom; + + page.Controls.AddRange(new Control[] + { + lblModelo, txtModelo, lblMarca, txtMarca, + lblOper, txtOperadora, lblSer, txtSerial, lblPat, txtPatrimonio, + lblAces, txtAcessorios, lblDef, txtDefeito, + lblObs, txtObsAparelho + }); + + // Reposiciona controles ancorados à direita no resize + page.Resize += (s, e) => + { + int w = page.ClientSize.Width - 12; + txtMarca.Size = new Size(w - 430, 26); + txtPatrimonio.Size = new Size(w - 640, 26); + txtDefeito.Size = new Size(w - 430, 140); + txtObsAparelho.Size = new Size(w, txtObsAparelho.Height); + }; + } + + // ── Aba Mão de Obra ──────────────────────────────────────────────────── + private void ConfigAbaMaoObra(TabPage page) + { + dgvServicos = Grid(); + dgvServicos.Columns.Add(new DataGridViewTextBoxColumn { HeaderText = "Serviço", FillWeight = 40 }); + dgvServicos.Columns.Add(new DataGridViewTextBoxColumn { HeaderText = "Técnico", FillWeight = 20 }); + dgvServicos.Columns.Add(new DataGridViewTextBoxColumn { HeaderText = "Início", FillWeight = 15 }); + dgvServicos.Columns.Add(new DataGridViewTextBoxColumn { HeaderText = "Fim", FillWeight = 15 }); + dgvServicos.Columns.Add(new DataGridViewTextBoxColumn { HeaderText = "Valor", FillWeight = 10 }); + page.Controls.Add(dgvServicos); + } + + // ── Aba Peças ────────────────────────────────────────────────────────── + private void ConfigAbaPecas(TabPage page) + { + dgvPecas = Grid(); + dgvPecas.Columns.Add(new DataGridViewTextBoxColumn { HeaderText = "Código", FillWeight = 12 }); + dgvPecas.Columns.Add(new DataGridViewTextBoxColumn { HeaderText = "Descrição", FillWeight = 38 }); + dgvPecas.Columns.Add(new DataGridViewTextBoxColumn { HeaderText = "Qtd", FillWeight = 10 }); + dgvPecas.Columns.Add(new DataGridViewTextBoxColumn { HeaderText = "V. Unit.", FillWeight = 15 }); + dgvPecas.Columns.Add(new DataGridViewTextBoxColumn { HeaderText = "Total", FillWeight = 15 }); + dgvPecas.Columns.Add(new DataGridViewTextBoxColumn { HeaderText = "Técnico", FillWeight = 10 }); + page.Controls.Add(dgvPecas); + } + + // ── Aba Laudo ────────────────────────────────────────────────────────── + private void ConfigAbaLaudo(TabPage page) + { + page.Padding = new Padding(6, 4, 6, 4); + + var lblLaudo = Lbl("Laudo Técnico / Serviço Realizado", 0, 0, 300); + txtLaudo = new TextBox + { + Multiline = true, + ScrollBars = ScrollBars.Vertical, + BorderStyle = BorderStyle.FixedSingle, + Font = new Font("Segoe UI", 9.5f), + Location = new Point(0, 16), + Size = new Size(900, 160), + Anchor = AnchorStyles.Top | AnchorStyles.Left | AnchorStyles.Right + }; + + var lblObs = Lbl("Observações Adicionais do Serviço", 0, 186, 300); + txtObsServico = new TextBox + { + Multiline = true, + ScrollBars = ScrollBars.Vertical, + BorderStyle = BorderStyle.FixedSingle, + Font = new Font("Segoe UI", 9.5f), + Location = new Point(0, 202), + Size = new Size(900, 120), + Anchor = AnchorStyles.Top | AnchorStyles.Left | AnchorStyles.Right | AnchorStyles.Bottom + }; + + page.Controls.AddRange(new Control[] { lblLaudo, txtLaudo, lblObs, txtObsServico }); + + page.Resize += (s, e) => + { + int w = page.ClientSize.Width - 12; + txtLaudo.Width = w; + txtObsServico.Width = w; + }; + } + + // ── Aba Miscelânea ───────────────────────────────────────────────────── + private void ConfigAbaMisc(TabPage page) + { + page.Controls.Add(Lbl("Campos adicionais serão configurados aqui.", 10, 12, 400)); + } + + // ══════════════════════════════════════════════════════════════════════ + // RODAPÉ + // ══════════════════════════════════════════════════════════════════════ + private Panel CriarRodape() + { + var pnl = new Panel { BackColor = CorCinzaClaro }; + pnl.Paint += (s, e) => + { + using var pen = new Pen(CorCinzaBorda); + e.Graphics.DrawLine(pen, 0, 0, pnl.Width, 0); + }; + + // Técnico Responsável + pnl.Controls.Add(Lbl("Técnico Responsável", 10, 2, 140, bold: true, fs: 8.5f)); + cmbTecnico = new ComboBox + { + Location = new Point(10, 18), + Size = new Size(200, 24), + DropDownStyle = ComboBoxStyle.DropDownList, + Font = new Font("Segoe UI", 9f), + FlatStyle = FlatStyle.Flat + }; + cmbTecnico.Items.Add("Não definido"); + cmbTecnico.SelectedIndex = 0; + pnl.Controls.Add(cmbTecnico); + + // Prioridade + pnl.Controls.Add(Lbl("Prioridade", 220, 2, 80, bold: true, fs: 8.5f)); + cmbPrioridade = new ComboBox + { + Location = new Point(220, 18), + Size = new Size(120, 24), + DropDownStyle = ComboBoxStyle.DropDownList, + Font = new Font("Segoe UI", 9f), + FlatStyle = FlatStyle.Flat + }; + cmbPrioridade.Items.AddRange(new object[] { "Normal", "Alta", "Urgente" }); + cmbPrioridade.SelectedIndex = 0; + pnl.Controls.Add(cmbPrioridade); + + // Botão Fotos/Docs + var btnFotos = LvBtn("📷 Fotos/Docs", CorCinzaClaro, Color.FromArgb(180, 180, 180), CorCinzaBorda, 128, 28, br: 4, bs: 1, bc: CorCinzaBorda); + btnFotos.ForeColor = CorTexto; + btnFotos.Anchor = AnchorStyles.Top | AnchorStyles.Right; + pnl.Resize += (s, e) => btnFotos.Location = new Point(pnl.Width - 136, 8); + pnl.Controls.Add(btnFotos); + + return pnl; + } + + // ══════════════════════════════════════════════════════════════════════ + // PREENCHIMENTO + // ══════════════════════════════════════════════════════════════════════ + private void PreencherCampos() + { + if (_os == null) return; + + lblNumOS.Text = $"O.S. nº {_os.CODIGO ?? "—"}"; + lblCliente.Text = _os.COD_CLIENTE ?? "—"; + lblCodVal.Text = _os.ID_ORDENS.ToString(); + + txtModelo.Text = _os.MODELO ?? ""; + txtMarca.Text = _os.MARCA ?? ""; + txtSerial.Text = _os.SERIE ?? ""; + txtAcessorios.Text = _os.ACESSORIO ?? ""; + txtDefeito.Text = _os.DEFEITO ?? ""; + txtObsAparelho.Text = _os.OBS_APARELHO ?? ""; + txtLaudo.Text = _os.LAUDO ?? ""; + txtObsServico.Text = _os.OBS_SERVICO ?? ""; + + lblVMao.Text = Fmt(_os.V_MAO); + lblVPecas.Text = Fmt(_os.V_PECAS); + lblVDesloca.Text = Fmt(_os.V_DESLOCA); + lblVTerceiro.Text = Fmt(_os.V_TERCEIRO); + lblVOutros.Text = Fmt(_os.V_OUTROS); + + if (!string.IsNullOrEmpty(_os.SITUACAO)) + { + int i = cmbSituacao.Items.IndexOf(_os.SITUACAO); + if (i >= 0) cmbSituacao.SelectedIndex = i; + } + + if (DateTime.TryParse(_os.ENTRADA, out var de)) dtpEntrada.Value = de; + if (DateTime.TryParse(_os.PRONTO, out var dp)) dtpPronto.Value = dp; + if (DateTime.TryParse(_os.SAIDA, out var ds)) dtpSaida.Value = ds; + + if (!string.IsNullOrEmpty(_os.GARANTIA)) + lblGarantia.Text = $"Garantia até {_os.GARANTIA}"; + + AtualizarTotal(); + } + + private void AtualizarTotal() + { + decimal total = Prx(_os?.V_MAO) + + Prx(_os?.V_PECAS) + + Prx(_os?.V_DESLOCA) + + Prx(_os?.V_TERCEIRO) + + Prx(_os?.V_OUTROS); + lblVTotal.Text = $"R$ {total:N2}"; + } + + // ══════════════════════════════════════════════════════════════════════ + // SALVAR + // ══════════════════════════════════════════════════════════════════════ + private void Salvar() + { + try + { + _os ??= new ModeloOrdens(); + _os.MODELO = txtModelo.Text; + _os.MARCA = txtMarca.Text; + _os.SERIE = txtSerial.Text; + _os.ACESSORIO = txtAcessorios.Text; + _os.DEFEITO = txtDefeito.Text; + _os.OBS_APARELHO = txtObsAparelho.Text; + _os.LAUDO = txtLaudo.Text; + _os.OBS_SERVICO = txtObsServico.Text; + _os.SITUACAO = cmbSituacao.SelectedItem?.ToString(); + _os.ENTRADA = dtpEntrada.Value.ToString("dd/MM/yy HH:mm"); + _os.PRONTO = dtpPronto.Value.ToString("dd/MM/yy HH:mm"); + _os.SAIDA = dtpSaida.Value.ToString("dd/MM/yy HH:mm"); + + MessageBox.Show("Ordem de Serviço salva com sucesso!", "LevelOS", + MessageBoxButtons.OK, MessageBoxIcon.Information); + OnVoltar?.Invoke(); + } + catch (Exception ex) + { + MessageBox.Show($"Erro ao salvar: {ex.Message}", "Erro", + MessageBoxButtons.OK, MessageBoxIcon.Error); + } + } + + // ══════════════════════════════════════════════════════════════════════ + // FACTORY HELPERS + // ══════════════════════════════════════════════════════════════════════ + + /// LV_BUTTON configurado. + private LV_BUTTON LvBtn(string texto, Color bg, Color hover, Color click, + int w, int h, int br = 0, int bs = 0, Color bc = default) + { + var btn = new LV_BUTTON + { + Text = texto, + Size = new Size(w, h), + BackColor = bg, + HoverColor = hover, + ClickColor = click, + ForeColor = Color.White, + Font = new Font("Segoe UI", 9f, FontStyle.Bold), + BorderRadius = br, + BorderSize = bs, + Cursor = Cursors.Hand + }; + if (bc != default) btn.BorderColor = bc; + return btn; + } + + /// LV_TEXTBOX1 adicionado ao parent. + private LV_TEXTBOX1 LvTxt(Control parent, int x, int y, int w, int h) + { + var tb = new LV_TEXTBOX1 + { + Location = new Point(x, y), + Size = new Size(w, h), + BorderColor = CorCinzaBorda, + BorderFocusColor = CorFocoBorda, + BorderSize = 2, + Font = new Font("Segoe UI", 9.5f) + }; + parent.Controls.Add(tb); + return tb; + } + + /// Label de valor (painel financeiro). + private Label LblV(Panel parent, string rotulo, int lx, int ly, int vx, int vw, int rh) + { + parent.Controls.Add(Lbl(rotulo, lx, ly + 1, 120)); + var lbl = new Label + { + Text = "R$ 0,00", + Font = new Font("Segoe UI", 8.5f), + ForeColor = CorTexto, + Location = new Point(vx, ly), + Size = new Size(vw, rh), + TextAlign = ContentAlignment.MiddleRight + }; + parent.Controls.Add(lbl); + return lbl; + } + + /// DataGridView padronizado. + private DataGridView Grid() + { + var dgv = new DataGridView + { + Dock = DockStyle.Fill, + BackgroundColor = Color.White, + BorderStyle = BorderStyle.None, + AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.Fill, + EnableHeadersVisualStyles = false, + AllowUserToAddRows = true, + RowHeadersVisible = false, + SelectionMode = DataGridViewSelectionMode.FullRowSelect, + GridColor = CorCinzaBorda, + Font = new Font("Segoe UI", 9f) + }; + dgv.ColumnHeadersDefaultCellStyle.BackColor = CorCinzaClaro; + dgv.ColumnHeadersDefaultCellStyle.ForeColor = CorTexto; + dgv.ColumnHeadersDefaultCellStyle.Font = new Font("Segoe UI", 9f, FontStyle.Bold); + dgv.ColumnHeadersHeight = 28; + dgv.AlternatingRowsDefaultCellStyle.BackColor = Color.FromArgb(250, 250, 255); + return dgv; + } + + /// DateTimePicker padronizado. + private DateTimePicker DTP(Control parent, int x, int y, int w, int h) + { + var dtp = new DateTimePicker + { + Location = new Point(x, y), + Size = new Size(w, h), + Format = DateTimePickerFormat.Custom, + CustomFormat = "dd/MM/yy HH:mm", + Font = new Font("Segoe UI", 9f) + }; + parent.Controls.Add(dtp); + return dtp; + } + + /// Label simples. + private Label Lbl(string texto, int x, int y, int w, bool bold = false, float fs = 8.5f) + { + return new Label + { + Text = texto, + Location = new Point(x, y), + Size = new Size(w, 16), + Font = new Font("Segoe UI", fs, bold ? FontStyle.Bold : FontStyle.Regular), + ForeColor = CorTexto, + AutoSize = false + }; + } + + private string Fmt(string? v) => decimal.TryParse(v, out var d) ? $"R$ {d:N2}" : "R$ 0,00"; + private decimal Prx(string? v) => decimal.TryParse(v, out var d) ? d : 0m; + } +} \ No newline at end of file diff --git a/UI/Dashboards/Cadastros/OrdensCadastroPanel.resx b/UI/Dashboards/Cadastros/OrdensCadastroPanel.resx new file mode 100644 index 0000000..1af7de1 --- /dev/null +++ b/UI/Dashboards/Cadastros/OrdensCadastroPanel.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/Consultas/NotasXmlConsultaPanel.cs b/UI/Dashboards/Consultas/NotasXmlConsultaPanel.cs new file mode 100644 index 0000000..b2e5590 --- /dev/null +++ b/UI/Dashboards/Consultas/NotasXmlConsultaPanel.cs @@ -0,0 +1,204 @@ +using BLL; +using DAL; +using System; +using System.Collections.Generic; +using System.Drawing; +using System.Linq; +using System.Windows.Forms; +using MLL; + +namespace UI +{ + public class NotasXmlConsultaPanel : UserControl + { + // ── CORES (Mantendo seu padrão LevelOS) ────────────────────────────────── + private readonly Color AccentBlue = Color.FromArgb(37, 99, 235); + private readonly Color TextDark = Color.FromArgb(30, 41, 59); + private readonly Color BorderColor = Color.FromArgb(226, 232, 240); + private readonly Color GreenColor = Color.FromArgb(34, 197, 94); + private readonly Color MutedGray = Color.FromArgb(148, 163, 184); + private readonly Color SurfaceColor = Color.FromArgb(248, 250, 252); + + // ── CONTROLES ───────────────────────────────────────────────────────── + private Panel pnlToolbar = null!; + private Panel pnlFiltros = null!; + private Panel pnlRodape = null!; + private DataGridView dgvXmls = null!; + private Label lblTotal = null!; + + // ── FILTROS ESPECÍFICOS PARA XML ────────────────────────────────────── + private RoundTextBox txtFiltroChave = null!; + private RoundTextBox txtFiltroIdNota = null!; + private RoundTextBox txtDataInicio = null!; + private RoundTextBox txtDataFim = null!; + + // ── DADOS ───────────────────────────────────────────────────────────── + private List _todos = new(); + private List _filtrados = new(); + private string _conexao = DadosDaConexao.ObterConexao(); + + public event Action? OnAbrirVisualizacao; + + public NotasXmlConsultaPanel() + { + Dock = DockStyle.Fill; + BackColor = Color.White; + DoubleBuffered = true; + + InitializeLayout(); + CarregarDadosDoBanco(); + AplicarFiltros(); + } + + private void InitializeLayout() + { + Controls.Clear(); + + // 1º GRID + BuildGrid(); + Controls.Add(dgvXmls); + + // 2º RODAPÉ + pnlRodape = new Panel { Dock = DockStyle.Bottom, Height = 30, BackColor = SurfaceColor }; + lblTotal = new Label { AutoSize = true, Location = new Point(16, 7), Font = new Font("Segoe UI", 8.5f, FontStyle.Bold), ForeColor = MutedGray, Text = "0 XMLs encontrados" }; + pnlRodape.Controls.Add(lblTotal); + Controls.Add(pnlRodape); + + // 3º FILTROS + pnlFiltros = new Panel { Dock = DockStyle.Top, Height = 95, BackColor = SurfaceColor, Padding = new Padding(16, 8, 16, 8) }; + BuildFiltros(); + Controls.Add(pnlFiltros); + + // 4º TOOLBAR + pnlToolbar = new Panel { Dock = DockStyle.Top, Height = 55, BackColor = SurfaceColor }; + var flow = new FlowLayoutPanel { Dock = DockStyle.Fill, Padding = new Padding(12, 10, 0, 0), BackColor = Color.Transparent }; + + var btnPesquisar = CreateToolbarButton("Pesquisar", AccentBlue); + var btnLimpar = CreateToolbarButton("Limpar", MutedGray); + var btnVisualizar = CreateToolbarButton("Visualizar", GreenColor); + var btnDownload = CreateToolbarButton("Salvar .XML", Color.FromArgb(99, 102, 241)); + + btnPesquisar.Click += (_, _) => AplicarFiltros(); + btnLimpar.Click += (_, _) => LimparFiltros(); + btnVisualizar.Click += (_, _) => AbrirRegistroSelecionado(); + btnDownload.Click += (_, _) => BaixarXmlSelecionado(); + + flow.Controls.AddRange(new Control[] { btnPesquisar, btnLimpar, btnVisualizar, btnDownload }); + pnlToolbar.Controls.Add(flow); + Controls.Add(pnlToolbar); + } + + private void BuildFiltros() + { + txtFiltroChave = AddFiltroInput(pnlFiltros, "Chave de Acesso (44 dígitos)", 0, 8, 400); + txtFiltroIdNota = AddFiltroInput(pnlFiltros, "ID da Nota", 410, 8, 100); + + txtDataInicio = AddFiltroInput(pnlFiltros, "Data Inicial", 0, 50, 130); + txtDataFim = AddFiltroInput(pnlFiltros, "Data Final", 140, 50, 130); + + foreach (var txt in new[] { txtFiltroChave, txtFiltroIdNota, txtDataInicio, txtDataFim }) + txt.KeyDown += (_, e) => { if (e.KeyCode == Keys.Enter) AplicarFiltros(); }; + } + + private void BuildGrid() + { + dgvXmls = new DataGridView + { + Dock = DockStyle.Fill, + BackgroundColor = Color.White, + BorderStyle = BorderStyle.None, + RowHeadersVisible = false, + AllowUserToAddRows = false, + ReadOnly = true, + SelectionMode = DataGridViewSelectionMode.FullRowSelect, + AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.Fill, + RowTemplate = { Height = 32 } + }; + + // Estilização seguindo seu padrão (omitido para brevidade, mas igual ao seu) + dgvXmls.Columns.AddRange(new DataGridViewColumn[] + { + new DataGridViewTextBoxColumn { Name = "colId", HeaderText = "ID", FillWeight = 10 }, + new DataGridViewTextBoxColumn { Name = "colChave", HeaderText = "Chave de Acesso", FillWeight = 60 }, + new DataGridViewTextBoxColumn { Name = "colTamanho", HeaderText = "Tamanho (KB)", FillWeight = 30 } + }); + + dgvXmls.CellDoubleClick += (_, e) => { if (e.RowIndex >= 0) AbrirRegistroSelecionado(); }; + } + + private void AplicarFiltros() + { + _filtrados = _todos.ToList(); + + var chave = txtFiltroChave.Text.Trim(); + if (!string.IsNullOrEmpty(chave)) + _filtrados = _filtrados.Where(x => x.CHAVE.Contains(chave)).ToList(); + + PreencherGrid(); + } + + private void PreencherGrid() + { + dgvXmls.Rows.Clear(); + foreach (var item in _filtrados) + { + // Cálculo simples de KB para exibir no grid + double kb = (item.XML?.Length ?? 0) / 1024.0; + dgvXmls.Rows.Add(item.ID_NOTAS_XML, item.CHAVE, kb.ToString("N2")); + } + lblTotal.Text = $"{_filtrados.Count} XMLs encontrados"; + } + + private void AbrirRegistroSelecionado() + { + if (dgvXmls.SelectedRows.Count == 0) return; + var id = (int)dgvXmls.SelectedRows[0].Cells["colId"].Value; + var xml = _filtrados.FirstOrDefault(x => x.ID_NOTAS_XML == id); + if (xml != null) OnAbrirVisualizacao?.Invoke(xml); + } + + private void BaixarXmlSelecionado() + { + if (dgvXmls.SelectedRows.Count == 0) return; + var id = (int)dgvXmls.SelectedRows[0].Cells["colId"].Value; + var nota = _filtrados.FirstOrDefault(x => x.ID_NOTAS_XML == id); + + if (nota != null) + { + using var sfd = new SaveFileDialog { Filter = "XML File|*.xml", FileName = nota.CHAVE }; + if (sfd.ShowDialog() == DialogResult.OK) + { + System.IO.File.WriteAllText(sfd.FileName, nota.XML); + MessageBox.Show("Arquivo salvo com sucesso!"); + } + } + } + + private void CarregarDadosDoBanco() + { + // BLL_NotasXml bll = new BLL_NotasXml(_conexao); + // _todos = bll.Listar(); + } + + private RoundTextBox AddFiltroInput(Control parent, string label, int x, int y, int width) + { + parent.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 txt = new RoundTextBox { Location = new Point(x, y + 16), Size = new Size(width, 26), Radius = 4, BorderColor = BorderColor, FocusColor = AccentBlue, BackColor = Color.White }; + parent.Controls.Add(txt); + return txt; + } + + private RoundButton CreateToolbarButton(string text, Color color) => new RoundButton + { + Text = text, + Size = new Size(110, 32), + BackColor = color, + ForeColor = Color.White, + Font = new Font("Segoe UI Semibold", 8.5f), + Margin = new Padding(0, 0, 6, 0), + Cursor = Cursors.Hand + }; + + private void LimparFiltros() { /* Limpa os txts e chama AplicarFiltros */ } + } +} \ No newline at end of file diff --git a/UI/Dashboards/Consultas/OrcaPadraoConsultaPanel.cs b/UI/Dashboards/Consultas/OrcaPadraoConsultaPanel.cs new file mode 100644 index 0000000..da1c12a --- /dev/null +++ b/UI/Dashboards/Consultas/OrcaPadraoConsultaPanel.cs @@ -0,0 +1,207 @@ +using BLL; +using DAL; +using System; +using System.Collections.Generic; +using System.Drawing; +using System.Linq; +using System.Windows.Forms; +using MLL; + +namespace UI +{ + public class OrcaPadraoConsultaPanel : UserControl + { + // ── CORES (Identidade LevelOS) ────────────────────────────────────────── + private readonly Color AccentBlue = Color.FromArgb(37, 99, 235); + private readonly Color TextDark = Color.FromArgb(30, 41, 59); + private readonly Color BorderColor = Color.FromArgb(226, 232, 240); + private readonly Color GreenColor = Color.FromArgb(34, 197, 94); + private readonly Color MutedGray = Color.FromArgb(148, 163, 184); + private readonly Color SurfaceColor = Color.FromArgb(248, 250, 252); + + // ── CONTROLES ───────────────────────────────────────────────────────── + private Panel pnlToolbar = null!; + private Panel pnlFiltros = null!; + private Panel pnlRodape = null!; + private DataGridView dgvOrcas = null!; + private Label lblTotal = null!; + + // ── FILTROS ─────────────────────────────────────────────────────────── + private RoundTextBox txtFiltroNome = null!; + private RoundTextBox txtFiltroCodigo = null!; + private ComboBox cmbUsado = null!; + + // ── DADOS ───────────────────────────────────────────────────────────── + private List _todos = new(); + private List _filtrados = new(); + private string _conexao = DadosDaConexao.ObterConexao(); + + public event Action? OnAbrirCadastro; + + public OrcaPadraoConsultaPanel() + { + Dock = DockStyle.Fill; + BackColor = Color.White; + DoubleBuffered = true; + + InitializeLayout(); + CarregarDadosDoBanco(); + AplicarFiltros(); + } + + private void InitializeLayout() + { + Controls.Clear(); + + // 1º GRID (Fill) + BuildGrid(); + Controls.Add(dgvOrcas); + + // 2º RODAPÉ (Bottom) + pnlRodape = new Panel { Dock = DockStyle.Bottom, Height = 30, BackColor = SurfaceColor }; + lblTotal = new Label { AutoSize = true, Location = new Point(16, 7), Font = new Font("Segoe UI", 8.5f, FontStyle.Bold), ForeColor = MutedGray, Text = "0 modelos encontrados" }; + pnlRodape.Controls.Add(lblTotal); + Controls.Add(pnlRodape); + + // 3º FILTROS (Top) + pnlFiltros = new Panel { Dock = DockStyle.Top, Height = 65, BackColor = SurfaceColor, Padding = new Padding(16, 8, 16, 8) }; + BuildFiltros(); + Controls.Add(pnlFiltros); + + // 4º TOOLBAR (Top) + pnlToolbar = new Panel { Dock = DockStyle.Top, Height = 55, BackColor = SurfaceColor }; + var flow = new FlowLayoutPanel { Dock = DockStyle.Fill, Padding = new Padding(12, 10, 0, 0), BackColor = Color.Transparent }; + + var btnPesquisar = CreateToolbarButton("Pesquisar", AccentBlue); + var btnLimpar = CreateToolbarButton("Limpar", MutedGray); + var btnNovo = CreateToolbarButton("Novo Modelo", GreenColor); + var btnEditar = CreateToolbarButton("Editar", Color.FromArgb(99, 102, 241)); + + btnPesquisar.Click += (_, _) => AplicarFiltros(); + btnLimpar.Click += (_, _) => LimparFiltros(); + btnNovo.Click += (_, _) => OnAbrirCadastro?.Invoke(new ModeloOrcaPadrao()); + btnEditar.Click += (_, _) => AbrirRegistroSelecionado(); + + flow.Controls.AddRange(new Control[] { btnPesquisar, btnLimpar, btnNovo, btnEditar }); + pnlToolbar.Controls.Add(flow); + Controls.Add(pnlToolbar); + } + + private void BuildFiltros() + { + txtFiltroCodigo = AddFiltroInput(pnlFiltros, "Código", 0, 8, 100); + txtFiltroNome = AddFiltroInput(pnlFiltros, "Nome do Modelo / Template", 110, 8, 300); + + pnlFiltros.Controls.Add(new Label { Text = "Em Uso?", Location = new Point(420, 8), Font = new Font("Segoe UI", 7.5f, FontStyle.Bold), ForeColor = TextDark, AutoSize = true }); + cmbUsado = new ComboBox { Location = new Point(420, 24), Size = new Size(100, 26), DropDownStyle = ComboBoxStyle.DropDownList, FlatStyle = FlatStyle.Flat }; + cmbUsado.Items.AddRange(new object[] { "Todos", "Sim", "Não" }); + cmbUsado.SelectedIndex = 0; + pnlFiltros.Controls.Add(cmbUsado); + + txtFiltroNome.KeyDown += (_, e) => { if (e.KeyCode == Keys.Enter) AplicarFiltros(); }; + } + + private void BuildGrid() + { + dgvOrcas = new DataGridView + { + Dock = DockStyle.Fill, + BackgroundColor = Color.White, + BorderStyle = BorderStyle.None, + RowHeadersVisible = false, + AllowUserToAddRows = false, + ReadOnly = true, + SelectionMode = DataGridViewSelectionMode.FullRowSelect, + AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.Fill, + RowTemplate = { Height = 32 } + }; + + dgvOrcas.Columns.AddRange(new DataGridViewColumn[] + { + new DataGridViewTextBoxColumn { Name = "colId", HeaderText = "ID", FillWeight = 10 }, + new DataGridViewTextBoxColumn { Name = "colCodigo", HeaderText = "Código", FillWeight = 15 }, + new DataGridViewTextBoxColumn { Name = "colNome", HeaderText = "Nome do Modelo", FillWeight = 45 }, + new DataGridViewTextBoxColumn { Name = "colUsado", HeaderText = "Ativo", FillWeight = 10 }, + new DataGridViewTextBoxColumn { Name = "colObs", HeaderText = "Observações", FillWeight = 20 } + }); + + dgvOrcas.CellDoubleClick += (_, e) => { if (e.RowIndex >= 0) AbrirRegistroSelecionado(); }; + } + + private void AplicarFiltros() + { + _filtrados = _todos.ToList(); + + var nome = txtFiltroNome.Text.Trim().ToLower(); + if (!string.IsNullOrEmpty(nome)) + _filtrados = _filtrados.Where(x => x.NOME.ToLower().Contains(nome)).ToList(); + + var cod = txtFiltroCodigo.Text.Trim().ToLower(); + if (!string.IsNullOrEmpty(cod)) + _filtrados = _filtrados.Where(x => x.CODIGO.ToLower().Contains(cod)).ToList(); + + var sit = cmbUsado.SelectedItem?.ToString(); + if (sit == "Sim") _filtrados = _filtrados.Where(x => x.USADO?.ToUpper() == "S").ToList(); + else if (sit == "Não") _filtrados = _filtrados.Where(x => x.USADO?.ToUpper() == "N").ToList(); + + PreencherGrid(); + } + + private void PreencherGrid() + { + dgvOrcas.Rows.Clear(); + foreach (var item in _filtrados) + { + dgvOrcas.Rows.Add( + item.ID_ORCA_PADRAO, + item.CODIGO, + item.NOME, + item.USADO == "S" ? "Ativo" : "Inativo", + item.OBS.Length > 30 ? item.OBS.Substring(0, 30) + "..." : item.OBS + ); + } + lblTotal.Text = $"{_filtrados.Count} modelos encontrados"; + } + + private void AbrirRegistroSelecionado() + { + if (dgvOrcas.SelectedRows.Count == 0) return; + var id = (int)dgvOrcas.SelectedRows[0].Cells["colId"].Value; + var selecionado = _filtrados.FirstOrDefault(x => x.ID_ORCA_PADRAO == id); + if (selecionado != null) OnAbrirCadastro?.Invoke(selecionado); + } + + private void CarregarDadosDoBanco() + { + // BLLOrcaPadrao bll = new BLLOrcaPadrao(_conexao); + // _todos = bll.Listar(); + } + + private RoundTextBox AddFiltroInput(Control parent, string label, int x, int y, int width) + { + parent.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 txt = new RoundTextBox { Location = new Point(x, y + 16), Size = new Size(width, 26), Radius = 4, BorderColor = BorderColor, FocusColor = AccentBlue, BackColor = Color.White }; + parent.Controls.Add(txt); + return txt; + } + + private RoundButton CreateToolbarButton(string text, Color color) => new RoundButton + { + Text = text, + Size = new Size(110, 32), + BackColor = color, + ForeColor = Color.White, + Font = new Font("Segoe UI Semibold", 8.5f), + Margin = new Padding(0, 0, 6, 0), + Cursor = Cursors.Hand + }; + + private void LimparFiltros() + { + txtFiltroNome.Text = string.Empty; + txtFiltroCodigo.Text = string.Empty; + cmbUsado.SelectedIndex = 0; + AplicarFiltros(); + } + } +} \ No newline at end of file diff --git a/UI/Dashboards/Consultas/OrcasConsultaPanel.cs b/UI/Dashboards/Consultas/OrcasConsultaPanel.cs new file mode 100644 index 0000000..7066018 --- /dev/null +++ b/UI/Dashboards/Consultas/OrcasConsultaPanel.cs @@ -0,0 +1,179 @@ +using BLL; +using DAL; +using System; +using System.Collections.Generic; +using System.Drawing; +using System.Linq; +using System.Windows.Forms; +using MLL; + +namespace UI +{ + public class OrcasConsultaPanel : UserControl + { + // ── DESIGN ────────────────────────────────────────────────────────── + private readonly Color AccentBlue = Color.FromArgb(37, 99, 235); + private readonly Color TextDark = Color.FromArgb(30, 41, 59); + private readonly Color BorderColor = Color.FromArgb(226, 232, 240); + private readonly Color GreenColor = Color.FromArgb(34, 197, 94); + private readonly Color SurfaceColor = Color.FromArgb(248, 250, 252); + private readonly Color OrangeColor = Color.FromArgb(249, 115, 22); + + // ── CONTROLES ─────────────────────────────────────────────────────── + private DataGridView dgvOrcas = null!; + private Label lblContador = null!; + private Label lblSomaTotal = null!; + + private RoundTextBox txtFiltroCliente = null!; + private RoundTextBox txtFiltroCodigo = null!; + private ComboBox cmbSituacao = null!; + + // ── DADOS ──────────────────────────────────────────────────────────── + private List _todos = new(); + private List _filtrados = new(); + + public event Action? OnEditarOrcamento; + public event Action? OnNovoOrcamento; + + public OrcasConsultaPanel() + { + Dock = DockStyle.Fill; + BackColor = Color.White; + InitializeLayout(); + // CarregarDados(); // Chamar BLL aqui + } + + private void InitializeLayout() + { + Controls.Clear(); + + // 1. GRID + BuildGrid(); + Controls.Add(dgvOrcas); + + // 2. RODAPÉ (Resumo Financeiro) + var pnlRodape = new Panel { Dock = DockStyle.Bottom, Height = 50, BackColor = SurfaceColor, Padding = new Padding(16, 0, 16, 0) }; + lblContador = new Label { Text = "0 Orçamentos", AutoSize = true, Location = new Point(16, 18), Font = new Font("Segoe UI", 9f, FontStyle.Bold), ForeColor = TextDark }; + lblSomaTotal = new Label { Text = "Total Geral: R$ 0,00", AutoSize = false, Width = 300, Location = new Point(pnlRodape.Width - 320, 15), Anchor = AnchorStyles.Right, Font = new Font("Segoe UI", 11f, FontStyle.Bold), ForeColor = AccentBlue, TextAlign = ContentAlignment.MiddleRight }; + pnlRodape.Controls.AddRange(new Control[] { lblContador, lblSomaTotal }); + Controls.Add(pnlRodape); + + // 3. FILTROS + var pnlFiltros = new Panel { Dock = DockStyle.Top, Height = 70, BackColor = SurfaceColor, Padding = new Padding(16, 10, 16, 10) }; + txtFiltroCodigo = AddFiltroInput(pnlFiltros, "Cód/Nº", 16, 10, 80); + txtFiltroCliente = AddFiltroInput(pnlFiltros, "Cliente (Nome ou CPF/CNPJ)", 105, 10, 300); + + pnlFiltros.Controls.Add(new Label { Text = "Situação", Location = new Point(415, 10), Font = new Font("Segoe UI", 8f, FontStyle.Bold), AutoSize = true }); + cmbSituacao = new ComboBox { Location = new Point(415, 28), Size = new Size(130, 28), DropDownStyle = ComboBoxStyle.DropDownList, FlatStyle = FlatStyle.Flat }; + cmbSituacao.Items.AddRange(new[] { "Todos", "Aberto", "Aprovado", "Cancelado", "Finalizado" }); + cmbSituacao.SelectedIndex = 0; + pnlFiltros.Controls.Add(cmbSituacao); + + Controls.Add(pnlFiltros); + + // 4. TOOLBAR + var pnlToolbar = new Panel { Dock = DockStyle.Top, Height = 60, BackColor = Color.White }; + var btnNovo = CreateButton("Novo Orçamento", GreenColor, 16); + btnNovo.Click += (s, e) => OnNovoOrcamento?.Invoke(); + + var btnFiltrar = CreateButton("Pesquisar", AccentBlue, 165); + btnFiltrar.Click += (s, e) => AplicarFiltros(); + + pnlToolbar.Controls.AddRange(new Control[] { btnNovo, btnFiltrar }); + Controls.Add(pnlToolbar); + } + + private void BuildGrid() + { + dgvOrcas = new DataGridView + { + Dock = DockStyle.Fill, + BackgroundColor = Color.White, + BorderStyle = BorderStyle.None, + RowHeadersVisible = false, + AllowUserToAddRows = false, + ReadOnly = true, + SelectionMode = DataGridViewSelectionMode.FullRowSelect, + AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.Fill, + RowTemplate = { Height = 40 } + }; + + dgvOrcas.Columns.AddRange(new DataGridViewColumn[] + { + new DataGridViewTextBoxColumn { Name = "colCod", HeaderText = "Código", FillWeight = 20 }, + new DataGridViewTextBoxColumn { Name = "colData", HeaderText = "Data", FillWeight = 20 }, + new DataGridViewTextBoxColumn { Name = "colCliente", HeaderText = "Cliente", FillWeight = 60 }, + new DataGridViewTextBoxColumn { Name = "colTotal", HeaderText = "Total Geral", FillWeight = 30 }, + new DataGridViewTextBoxColumn { Name = "colStatus", HeaderText = "Situação", FillWeight = 25 } + }); + + dgvOrcas.CellFormatting += (s, e) => { + if (dgvOrcas.Columns[e.ColumnIndex].Name == "colStatus" && e.Value != null) + { + if (e.Value.ToString() == "Aprovado") e.CellStyle.ForeColor = GreenColor; + if (e.Value.ToString() == "Aberto") e.CellStyle.ForeColor = OrangeColor; + } + }; + + dgvOrcas.CellDoubleClick += (s, e) => { + if (e.RowIndex >= 0) AbrirEdicao(); + }; + } + + private void AplicarFiltros() + { + _filtrados = _todos.ToList(); + + if (!string.IsNullOrEmpty(txtFiltroCliente.Text)) + _filtrados = _filtrados.Where(x => x.CLIENTE_NOME.ToUpper().Contains(txtFiltroCliente.Text.ToUpper())).ToList(); + + if (cmbSituacao.SelectedIndex > 0) + _filtrados = _filtrados.Where(x => x.SITUACAO == cmbSituacao.SelectedItem.ToString()).ToList(); + + AtualizarGrid(); + } + + private void AtualizarGrid() + { + dgvOrcas.Rows.Clear(); + decimal soma = 0; + + foreach (var o in _filtrados) + { + dgvOrcas.Rows.Add(o.CODIGO, o.DIA, o.CLIENTE_NOME, o.TOTAL_GERAL, o.SITUACAO); + + if (decimal.TryParse(o.TOTAL_GERAL, out decimal v)) soma += v; + } + + lblContador.Text = $"{_filtrados.Count} Orçamentos encontrados"; + lblSomaTotal.Text = $"Total Geral: {soma:C2}"; + } + + private void AbrirEdicao() + { + if (dgvOrcas.SelectedRows.Count == 0) return; + string cod = dgvOrcas.SelectedRows[0].Cells["colCod"].Value.ToString(); + var orca = _filtrados.FirstOrDefault(x => x.CODIGO == cod); + if (orca != null) OnEditarOrcamento?.Invoke(orca); + } + + private RoundTextBox AddFiltroInput(Control parent, string label, int x, int y, int w) + { + parent.Controls.Add(new Label { Text = label, Location = new Point(x, y), Font = new Font("Segoe UI", 8f, FontStyle.Bold), AutoSize = true }); + var txt = new RoundTextBox { Location = new Point(x, y + 18), Size = new Size(w, 30), Radius = 5, BorderColor = BorderColor }; + parent.Controls.Add(txt); + return txt; + } + + private RoundButton CreateButton(string text, Color color, int x) => new RoundButton + { + Text = text, + Size = new Size(140, 35), + Location = new Point(x, 12), + BackColor = color, + ForeColor = Color.White, + Font = new Font("Segoe UI Semibold", 9f), + Cursor = Cursors.Hand + }; + } +} \ No newline at end of file diff --git a/UI/Dashboards/Dashmain/MainForm.cs b/UI/Dashboards/Dashmain/MainForm.cs index 11bb69c..22092f0 100644 --- a/UI/Dashboards/Dashmain/MainForm.cs +++ b/UI/Dashboards/Dashmain/MainForm.cs @@ -6,6 +6,7 @@ using System; using System.Drawing; using System.Windows.Forms; using TLL; +using UI; namespace UI { public class MainForm : Form @@ -47,7 +48,9 @@ namespace UI private readonly Panel _pProdutos; private readonly Panel _pEstoque; private readonly Panel _pFinanceiro; - + //Orçamentos + private readonly OrcasCadastroPanel _pOrcasCadastroPanel; + private readonly OrdensCadastroPanel _pordensCadastroPanel; public MainForm() { Text = "LevelOS — Sistema ERP"; @@ -84,6 +87,8 @@ namespace UI _ptelegramClienteCadastroPanel = new TelegramClienteCadastroPanel { Dock = DockStyle.Fill, Visible = false }; _pBackupAutomaticoCadastroPanel = new BackupAutomaticoCadastroPanel { Dock = DockStyle.Fill, Visible = false }; _pCloudStorageCadastroPanel = new CloudStorageCadastroPanel { Dock = DockStyle.Fill, Visible = false }; + _pOrcasCadastroPanel = new OrcasCadastroPanel { Dock = DockStyle.Fill, Visible = false }; + _pordensCadastroPanel = new OrdensCadastroPanel { 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)); @@ -119,6 +124,8 @@ namespace UI mainContainer.Controls.Add(_ptelegramClienteCadastroPanel); mainContainer.Controls.Add(_pBackupAutomaticoCadastroPanel); mainContainer.Controls.Add(_pCloudStorageCadastroPanel); + mainContainer .Controls.Add(_pOrcasCadastroPanel); + mainContainer.Controls.Add(_pordensCadastroPanel); Controls.Add(mainContainer); Controls.Add(_sidebar); @@ -162,10 +169,11 @@ namespace UI case 206: ShowPanel(_psshClienteCadastroPanel); break; case 207: ShowPanel(_pBackupAutomaticoCadastroPanel); break; case 208: ShowPanel(_pCloudStorageCadastroPanel); break; - + case 299: ShowPanel(_pordensCadastroPanel); break; case 300: ShowPanel(_pAgendaCadastro); break; case 301: ShowPanel(_pAgendaConsulta); break; case 309: ShowPanel(_pChamadoCadastroPanel); break; + case 304: ShowPanel(_pOrcasCadastroPanel); break; case 400: ShowPanel(_pcontasCadastroPanel); break; case 401: ShowPanel(_pcontaReceberCadastroPanel); break; @@ -207,6 +215,8 @@ namespace UI _ptelegramClienteCadastroPanel.Visible = (panelToShow == _ptelegramClienteCadastroPanel); _pBackupAutomaticoCadastroPanel.Visible = (panelToShow == _pBackupAutomaticoCadastroPanel); _pCloudStorageCadastroPanel.Visible = (panelToShow == _pCloudStorageCadastroPanel); + _pOrcasCadastroPanel.Visible = (panelToShow == _pOrcasCadastroPanel); + _pordensCadastroPanel.Visible = (panelToShow == _pordensCadastroPanel); if (panelToShow.Visible) { panelToShow.BringToFront(); diff --git a/UI/Dashboards/Dashmain/SidebarControl.cs b/UI/Dashboards/Dashmain/SidebarControl.cs index 58e0c9b..d5b5eac 100644 --- a/UI/Dashboards/Dashmain/SidebarControl.cs +++ b/UI/Dashboards/Dashmain/SidebarControl.cs @@ -153,11 +153,11 @@ namespace UI // ── ORDENS DE SERVIÇO ───────────────────────────────────────────── _subMenuOrdemServico = CreateStyledMenu(); - _subMenuOrdemServico.Items.Add(CreateItem("✚ Abrir nova O.S")); + _subMenuOrdemServico.Items.Add(CreateItem("✚ Abrir nova O.S",(s, e) => NavItemClicked?.Invoke(this, 299))); _subMenuOrdemServico.Items.Add(CreateItem("✎ Alterar O.S")); _subMenuOrdemServico.Items.Add(CreateItem("🔒 Encerrar O.S")); _subMenuOrdemServico.Items.Add(CreateItem("🔍 Localizar O.S")); - _subMenuOrdemServico.Items.Add(CreateItem("📋 Orçamento de O.S")); + _subMenuOrdemServico.Items.Add(CreateItem("📋 Orçamento de O.S", (s, e) => NavItemClicked?.Invoke(this, 304))); _subMenuOrdemServico.Items.Add(CreateItem("📜 Histórico de O.S")); _subMenuOrdemServico.Items.Add(CreateItem("📊 Relatório de O.S")); _subMenuOrdemServico.Items.Add(CreateItem("🖨 Imprimir")); diff --git a/UI/UI.csproj b/UI/UI.csproj index 9e39068..91f7dcf 100644 --- a/UI/UI.csproj +++ b/UI/UI.csproj @@ -29,4 +29,8 @@ + + + + \ No newline at end of file