12/05/2026 - Criando formulario Abertura de ordem de serviço

This commit is contained in:
levelcode developed 2026-05-12 00:53:34 -03:00
parent cd6c4165cb
commit f8a0ada711
14 changed files with 2282 additions and 4 deletions

8
UI/.github/agents/Ollama.agent.md vendored Normal file
View File

@ -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.

View File

@ -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);
}
}
}
}

View File

@ -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);
}
}
}
}

View File

@ -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);
}
}
}
}

View File

@ -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<ModeloOrcaPadraoItens> listaItens = new List<ModeloOrcaPadraoItens>();
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);
}
}
}
}

View File

@ -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
};
}
}

View File

@ -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 <<GARANTIA>>
var btnGar = LvBtn("<<GARANTIA>>", 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
// ══════════════════════════════════════════════════════════════════════
/// <summary>LV_BUTTON configurado.</summary>
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;
}
/// <summary>LV_TEXTBOX1 adicionado ao parent.</summary>
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;
}
/// <summary>Label de valor (painel financeiro).</summary>
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;
}
/// <summary>DataGridView padronizado.</summary>
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;
}
/// <summary>DateTimePicker padronizado.</summary>
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;
}
/// <summary>Label simples.</summary>
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;
}
}

View File

@ -0,0 +1,120 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
</root>

View File

@ -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<ModeloNotasXml> _todos = new();
private List<ModeloNotasXml> _filtrados = new();
private string _conexao = DadosDaConexao.ObterConexao();
public event Action<ModeloNotasXml>? 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 */ }
}
}

View File

@ -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<ModeloOrcaPadrao> _todos = new();
private List<ModeloOrcaPadrao> _filtrados = new();
private string _conexao = DadosDaConexao.ObterConexao();
public event Action<ModeloOrcaPadrao>? 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();
}
}
}

View File

@ -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<ModeloOrcas> _todos = new();
private List<ModeloOrcas> _filtrados = new();
public event Action<ModeloOrcas>? 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
};
}
}

View File

@ -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();

View File

@ -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"));

View File

@ -29,4 +29,8 @@
<Folder Include="ArquivosAuxiliares\Txt\" />
</ItemGroup>
<ItemGroup>
<None Include=".github\agents\Ollama.agent.md" />
</ItemGroup>
</Project>