22/05/2026 - Terminando formularios principais

This commit is contained in:
levelcode developed 2026-05-22 21:38:38 -03:00
parent bea1bea54d
commit b6f4aee971
17 changed files with 3150 additions and 974 deletions

View File

@ -0,0 +1,141 @@
using System;
using System.Drawing;
using System.Windows.Forms;
namespace UI
{
/// <summary>
/// Detecta automaticamente o perfil de tela (Monitor ou Notebook)
/// combinando resolução e DPI, e fornece fatores de escala para
/// dimensões e fontes de forma centralizada.
///
/// Base de referência do layout: 1920x1080 a 96 DPI = Scale 1.0
/// O layout base foi desenhado compacto (sem escalação excessiva),
/// então Monitor FHD usa 1.0 e os demais perfis sobem/descem a partir daí.
/// </summary>
public static class ScreenProfile
{
// ─────────────────────────────────────────────
// Enum de perfil
// ─────────────────────────────────────────────
public enum ProfileType
{
NotebookHD, // ≤ 1366 x 768
NotebookHDPlus, // 1600 x 900
MonitorFHD, // 1920 x 1080 ← referência (Scale = 1.0)
MonitorQHD, // 2560 x 1440
MonitorUHD // 3840 x 2160 (4K)
}
// ─────────────────────────────────────────────
// Propriedades públicas
// ─────────────────────────────────────────────
/// <summary>Perfil detectado.</summary>
public static ProfileType Profile { get; private set; }
/// <summary>Fator de escala para dimensões e posições.</summary>
public static float Scale { get; private set; }
/// <summary>Fator de escala específico para fontes.</summary>
public static float FontScale { get; private set; }
/// <summary>DPI real da tela primária.</summary>
public static float Dpi { get; private set; }
/// <summary>Resolução da tela primária.</summary>
public static Size Resolution { get; private set; }
// ─────────────────────────────────────────────
// Inicialização estática
// ─────────────────────────────────────────────
static ScreenProfile() => Detect();
private static void Detect()
{
// 1. Resolução física
var screen = Screen.PrimaryScreen!;
int w = screen.Bounds.Width;
int h = screen.Bounds.Height;
Resolution = new Size(w, h);
// 2. DPI real (96 = 100%, 120 = 125%, 144 = 150%, 192 = 200%)
using var g = Graphics.FromHwnd(IntPtr.Zero);
Dpi = g.DpiX;
// 3. Correção: evita dupla escala quando Windows Scaling está ativo
float dpiCorrection = Dpi > 96f ? (96f / Dpi) : 1f;
// 4. Escala base por resolução
// Referência: Monitor FHD = 1.0 (layout desenhado para 1920x1080)
if (w >= 3840)
{
Profile = ProfileType.MonitorUHD;
Scale = 1.40f;
FontScale = 1.30f;
}
else if (w >= 2560)
{
Profile = ProfileType.MonitorQHD;
Scale = 1.20f;
FontScale = 1.15f;
}
else if (w >= 1920)
{
Profile = ProfileType.MonitorFHD;
Scale = 1.00f; // ← referência
FontScale = 1.00f;
}
else if (w >= 1600)
{
Profile = ProfileType.NotebookHDPlus;
Scale = 0.85f;
FontScale = 0.88f;
}
else
{
Profile = ProfileType.NotebookHD;
Scale = 0.72f;
FontScale = 0.76f;
}
// 5. Aplica correção de DPI
Scale *= dpiCorrection;
FontScale *= dpiCorrection;
// 6. Limita range seguro
Scale = Math.Clamp(Scale, 0.65f, 1.50f);
FontScale = Math.Clamp(FontScale, 0.70f, 1.40f);
}
// ─────────────────────────────────────────────
// Helpers de escala
// ─────────────────────────────────────────────
/// <summary>Escala um valor inteiro (dimensão ou posição).</summary>
public static int S(int value) => (int)Math.Round(value * Scale);
/// <summary>Escala um ponto.</summary>
public static Point P(int x, int y) => new(S(x), S(y));
/// <summary>Escala um tamanho.</summary>
public static Size Sz(int w, int h) => new(S(w), S(h));
/// <summary>Escala um retângulo.</summary>
public static Rectangle R(int x, int y, int w, int h)
=> new(S(x), S(y), S(w), S(h));
/// <summary>Escala um tamanho de fonte.</summary>
public static float F(float pt) => (float)Math.Round(pt * FontScale, 1);
// ─────────────────────────────────────────────
// Diagnóstico
// ─────────────────────────────────────────────
public static string Diagnostico()
=> $"Perfil: {Profile} | {Resolution.Width}x{Resolution.Height} | " +
$"DPI: {Dpi:F0} | Scale: {Scale:F2} | FontScale: {FontScale:F2}";
}
}

View File

@ -0,0 +1,178 @@
using CPM;
using MLL;
using System;
using System.Drawing;
using System.Windows.Forms;
namespace UI
{
public class OSServicosPanel : FormularioModelo
{
// Mapeamento absoluto de todos os campos do ModeloOSServicos
private LV_TEXTBOX1 txtIdServico;
private LV_TEXTBOX1 txtCodigo;
private LV_TEXTBOX1 txtDescricao;
private LV_TEXTBOX1 txtTotal;
private LV_TEXTBOX1 txtInicio;
private LV_TEXTBOX1 txtFim;
private LV_TEXTBOX1 txtTecnico;
private LV_TEXTBOX1 txtTipo;
private LV_TEXTBOX1 txtOsNum;
private LV_TEXTBOX1 txtCodServ;
private LV_TEXTBOX1 txtQtd;
private LV_TEXTBOX1 txtVFrete;
private LV_TEXTBOX1 txtVSeguro;
private LV_TEXTBOX1 txtVOutros;
private LV_TEXTBOX1 txtNumNfPed;
private LV_TEXTBOX1 txtCusto;
private LV_TEXTBOX1 txtXPed;
private LV_TEXTBOX1 txtNItemPed;
public OSServicosPanel()
{
this.Titulo = "LANÇAMENTO DE SERVIÇOS E MÃO DE OBRA";
MontarInterfaceCompleta();
VincularEventosCalculo();
}
private void MontarInterfaceCompleta()
{
// --- SEÇÃO 1: VÍNCULO DA O.S. E IDENTIFICAÇÃO ---
content.Controls.Add(CreateSectionHeader("Identificação do Serviço", 20));
txtIdServico = AddInput(content, "ID REGISTRO", 20, 55, 100, 28, true);
txtOsNum = AddInput(content, "Nº DA O.S.", 130, 55, 120, 28, true);
txtCodServ = AddInput(content, "CÓD. SERVIÇO", 260, 55, 130, 28);
txtCodigo = AddInput(content, "CÓD. INTERNO", 400, 55, 130, 28);
txtTipo = AddInput(content, "TIPO SERVIÇO", 540, 55, 150, 28);
// --- SEÇÃO 2: DETALHES E APURAÇÃO ---
content.Controls.Add(CreateSectionHeader("Especificações e Execução", 115));
txtDescricao = AddInput(content, "DESCRIÇÃO DO SERVIÇO EXECUTADO", 20, 150, 650, 28);
txtTecnico = AddInput(content, "TÉCNICO RESPONSÁVEL", 680, 150, 300, 28);
txtInicio = AddInput(content, "DATA/HORA INÍCIO", 20, 210, 180, 28);
txtFim = AddInput(content, "DATA/HORA FIM", 210, 210, 180, 28);
txtQtd = AddInput(content, "QUANTIDADE", 400, 210, 100, 28);
// --- SEÇÃO 3: VALORES E FECHAMENTO ---
content.Controls.Add(CreateSectionHeader("Valores e Custos Comerciais", 275));
txtCusto = AddInput(content, "CUSTO UNITÁRIO (R$)", 20, 310, 150, 28);
txtVFrete = AddInput(content, "VALOR FRETE (R$)", 180, 310, 140, 28);
txtVSeguro = AddInput(content, "VALOR SEGURO (R$)", 330, 310, 140, 28);
txtVOutros = AddInput(content, "OUTRAS DESPESAS (R$)", 480, 310, 140, 28);
txtTotal = AddInput(content, "TOTAL GERAL (R$)", 630, 310, 180, 28, true); // Calculado automaticamente
// --- SEÇÃO 4: INTEGRAÇÃO FISCAL / FATURAMENTO ---
content.Controls.Add(CreateSectionHeader("Vínculos Fiscais e Pedidos (B2B)", 375));
txtNumNfPed = AddInput(content, "Nº NF / PEDIDO", 20, 410, 200, 28);
txtXPed = AddInput(content, "Nº PEDIDO COMPRA (XPED)", 230, 410, 220, 28);
txtNItemPed = AddInput(content, "ITEM DO PEDIDO (NITEMPED)", 460, 410, 180, 28);
}
private void VincularEventosCalculo()
{
// Dispara o cálculo automático sempre que alterar quantidade ou valores relevantes
txtQtd.TextChanged += (s, e) => CalcularTotalServico();
txtCusto.TextChanged += (s, e) => CalcularTotalServico();
txtVFrete.TextChanged += (s, e) => CalcularTotalServico();
txtVSeguro.TextChanged += (s, e) => CalcularTotalServico();
txtVOutros.TextChanged += (s, e) => CalcularTotalServico();
}
private void CalcularTotalServico()
{
decimal.TryParse(txtQtd.Text, out decimal qtd);
decimal.TryParse(txtCusto.Text, out decimal custoUnit);
decimal.TryParse(txtVFrete.Text, out decimal frete);
decimal.TryParse(txtVSeguro.Text, out decimal seguro);
decimal.TryParse(txtVOutros.Text, out decimal outros);
if (qtd == 0) qtd = 1; // Evita zerar se o usuário apagar o campo
// Regra básica de composição de preço do serviço
decimal totalGeral = (custoUnit * qtd) + frete + seguro + outros;
txtTotal.Text = totalGeral.ToString("N2");
}
// --- MÉTODOS OBRIGATÓRIOS DO FORMULÁRIO MODELO ---
protected override void OnNovo()
{
// Limpa todos os controles não-bloqueados contidos no painel content
foreach (Control c in content.Controls)
{
if (c is LV_TEXTBOX1 txt && !txt.ReadOnly)
{
txt.Text = string.Empty;
}
}
txtQtd.Text = "1";
txtCusto.Text = "0,00";
txtVFrete.Text = "0,00";
txtVSeguro.Text = "0,00";
txtVOutros.Text = "0,00";
txtTotal.Text = "0,00";
txtCodServ.Focus();
}
protected override void OnSalvar()
{
// Mapeamento exato de todas as propriedades sem deixar nenhuma de fora
var servico = new ModeloOSServicos
{
ID_OS_SEVICOS = string.IsNullOrEmpty(txtIdServico.Text) ? 0 : Convert.ToInt32(txtIdServico.Text),
CODIGO = txtCodigo.Text,
DESCRICAO = txtDescricao.Text,
TOTAL = txtTotal.Text,
INICIO = txtInicio.Text,
FIM = txtFim.Text,
TECNICO = txtTecnico.Text,
TIPO = txtTipo.Text,
OS_NUM = txtOsNum.Text,
COD_SERV = txtCodServ.Text,
QTD = txtQtd.Text,
V_FRETE = txtVFrete.Text,
V_SEGURO = txtVSeguro.Text,
V_OUTROS = txtVOutros.Text,
NUM_NF_PED = txtNumNfPed.Text,
CUSTO = txtCusto.Text,
XPED = txtXPed.Text,
NITEMPED = txtNItemPed.Text
};
// Aqui sua lógica chamará a BLL/DAL passando o objeto 'servico'
MessageBox.Show("Lançamento de serviço salvo com sucesso!", "LevelOS", MessageBoxButtons.OK, MessageBoxIcon.Information);
}
protected override void OnAlterar()
{
// Lógica para destravar componentes ou carregar estado de edição
txtDescricao.Focus();
}
protected override void OnExcluir()
{
if (MessageBox.Show("Deseja realmente remover este serviço da O.S.?", "LevelOS", MessageBoxButtons.YesNo, MessageBoxIcon.Warning) == DialogResult.Yes)
{
// Executar exclusão via BLL
OnNovo();
}
}
protected override void OnLocalizar()
{
// Aqui você abre sua tela padrão de busca de serviços da OS
}
protected override void OnCancelar()
{
OnNovo();
}
}
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,185 @@
using CPM;
using MLL;
using System;
using System.Drawing;
using System.Windows.Forms;
namespace UI
{
public class PedidosPanel : FormularioModelo
{
// Mapeamento absoluto de todas as propriedades do ModeloPedidos
private LV_TEXTBOX1 txtIdPedidos;
private LV_TEXTBOX1 txtCodigo;
private LV_TEXTBOX1 txtTipo;
private LV_TEXTBOX1 txtDataPedido;
private LV_TEXTBOX1 txtFormaPgto;
private LV_TEXTBOX1 txtEntregaDia;
private LV_TEXTBOX1 txtEntregaContato;
private LV_TEXTBOX1 txtEntregaEndereco;
private LV_TEXTBOX1 txtEntregaCidade;
private LV_TEXTBOX1 txtEntregaUf;
private LV_TEXTBOX1 txtEntregaCep;
private LV_TEXTBOX1 txtEntregaTelefone;
private LV_TEXTBOX1 txtDataEnvio;
private LV_TEXTBOX1 txtObservacoes;
private LV_TEXTBOX1 txtFornecedor;
private LV_TEXTBOX1 txtTransportador;
private LV_TEXTBOX1 txtVendedor;
private LV_TEXTBOX1 txtValor;
private LV_TEXTBOX1 txtSituacao;
private LV_TEXTBOX1 txtDesconto;
private LV_TEXTBOX1 txtNumNfPed;
private LV_TEXTBOX1 txtVFrete;
private LV_TEXTBOX1 txtVSeguro;
private LV_TEXTBOX1 txtVOutros;
private LV_TEXTBOX1 txtPedPrazo;
private LV_TEXTBOX1 txtPedForma;
private LV_TEXTBOX1 txtPedObs;
private LV_TEXTBOX1 txtChaveNfeCompra;
private LV_TEXTBOX1 txtPagamentoPedido;
private LV_TEXTBOX1 txtPagamentoFrete;
private LV_TEXTBOX1 txtRastreioFrete;
public PedidosPanel()
{
this.Titulo = "CENTRAL DE COMPRAS E PEDIDOS";
MontarInterfaceCompleta();
}
private void MontarInterfaceCompleta()
{
// --- SEÇÃO 1: DADOS BÁSICOS E ENVOLVIDOS ---
content.Controls.Add(CreateSectionHeader("Identificação Básica e Fluxo", 15));
txtIdPedidos = AddInput(content, "ID PEDIDO", 20, 45, 100, 28, true);
txtCodigo = AddInput(content, "CÓDIGO INT.", 135, 45, 110, 28);
txtTipo = AddInput(content, "TIPO (COMPRA/VENDA)", 260, 45, 160, 28);
txtDataPedido = AddInput(content, "DATA PEDIDO", 435, 45, 130, 28);
txtSituacao = AddInput(content, "SITUAÇÃO/STATUS", 580, 45, 150, 28);
txtVendedor = AddInput(content, "VENDEDOR", 20, 100, 225, 28);
txtFornecedor = AddInput(content, "FORNECEDOR / PARCEIRO", 260, 100, 310, 28);
txtTransportador = AddInput(content, "TRANSPORTADORA", 585, 100, 280, 28);
// --- SEÇÃO 2: LOGÍSTICA E ENTREGA ---
content.Controls.Add(CreateSectionHeader("Logística e Local de Entrega", 155));
txtEntregaContato = AddInput(content, "CONTATO P/ ENTREGA", 20, 185, 225, 28);
txtEntregaTelefone = AddInput(content, "TEL. ENTREGA", 260, 185, 150, 28);
txtEntregaDia = AddInput(content, "DATA PROMETIDA", 425, 185, 140, 28);
txtDataEnvio = AddInput(content, "DATA DE ENVIO", 580, 185, 140, 28);
txtRastreioFrete = AddInput(content, "CÓD. RASTREIO FRETE", 735, 185, 220, 28);
txtEntregaEndereco = AddInput(content, "ENDEREÇO DE ENTREGA", 20, 240, 400, 28);
txtEntregaCidade = AddInput(content, "CIDADE", 435, 240, 200, 28);
txtEntregaUf = AddInput(content, "UF", 650, 240, 60, 28);
txtEntregaCep = AddInput(content, "CEP", 725, 240, 110, 28);
// --- SEÇÃO 3: VALORES E FINANCEIRO ---
content.Controls.Add(CreateSectionHeader("Valores, Custos e Condições Financeiras", 295));
txtValor = AddInput(content, "VALOR PRODUTOS (R$)", 20, 325, 150, 28);
txtDesconto = AddInput(content, "DESCONTO (R$)", 185, 325, 120, 28);
txtVFrete = AddInput(content, "VALOR FRETE (R$)", 320, 325, 120, 28);
txtVSeguro = AddInput(content, "VALOR SEGURO (R$)", 455, 325, 120, 28);
txtVOutros = AddInput(content, "OUTRAS DESPESAS (R$)", 590, 325, 140, 28);
txtFormaPgto = AddInput(content, "FORMA PGTO PRINCIPAL", 20, 380, 180, 28);
txtPedForma = AddInput(content, "FORMA DETALHADA", 215, 380, 180, 28);
txtPedPrazo = AddInput(content, "CONDIÇÃO DE PRAZO", 410, 380, 165, 28);
txtPagamentoPedido = AddInput(content, "STATUS PGTO PEDIDO", 590, 380, 160, 28);
txtPagamentoFrete = AddInput(content, "STATUS PGTO FRETE", 765, 380, 160, 28);
// --- SEÇÃO 4: DADOS FISCAIS E OBSERVAÇÕES ---
content.Controls.Add(CreateSectionHeader("Documentação Fiscal e Informações de Fechamento", 435));
txtNumNfPed = AddInput(content, "Nº NF-E / DOCUMENTO", 20, 465, 180, 28);
txtChaveNfeCompra = AddInput(content, "CHAVE DE ACESSO DA NF-E (44 DÍGITOS)", 215, 465, 415, 28);
txtObservacoes = AddInput(content, "OBSERVAÇÕES GERAIS", 20, 520, 465, 28);
txtPedObs = AddInput(content, "OBS. INTERNAS / FINANCEIRAS", 500, 520, 455, 28);
}
// --- MÉTODOS OBRIGATÓRIOS DO FORMULÁRIO MODELO ---
protected override void OnNovo()
{
// Limpa de forma segura todos os inputs dinâmicos do formulário
foreach (Control c in content.Controls)
{
if (c is LV_TEXTBOX1 txt && !txt.ReadOnly)
{
txt.Text = string.Empty;
}
}
txtCodigo.Focus();
}
protected override void OnSalvar()
{
// Mapeamento cirúrgico e sem omissões de todas as 31 propriedades
var pedido = new ModeloPedidos
{
ID_PEDIDOS = string.IsNullOrEmpty(txtIdPedidos.Text) ? 0 : Convert.ToInt32(txtIdPedidos.Text),
CODIGO = txtCodigo.Text,
TIPO = txtTipo.Text,
DATA_PEDIDO = txtDataPedido.Text,
FORMA_PGTO = txtFormaPgto.Text,
ENTREGA_DIA = txtEntregaDia.Text,
ENTREGA_CONTATO = txtEntregaContato.Text,
ENTREGA_ENDERECO = txtEntregaEndereco.Text,
ENTREGA_CIDADE = txtEntregaCidade.Text,
ENTREGA_UF = txtEntregaUf.Text,
ENTREGA_CEP = txtEntregaCep.Text,
ENTREGA_TELEFONE = txtEntregaTelefone.Text,
DATA_ENVIO = txtDataEnvio.Text,
OBSERVACOES = txtObservacoes.Text,
FORNECEDOR = txtFornecedor.Text,
TRANSPORTADOR = txtTransportador.Text,
VENDEDOR = txtVendedor.Text,
VALOR = txtValor.Text,
SITUACAO = txtSituacao.Text,
DESCONTO = txtDesconto.Text,
NUM_NF_PED = txtNumNfPed.Text,
V_FRETE = txtVFrete.Text,
V_SEGURO = txtVSeguro.Text,
V_OUTROS = txtVOutros.Text,
PED_PRAZO = txtPedPrazo.Text,
PED_FORMA = txtPedForma.Text,
PED_OBS = txtPedObs.Text,
CHAVE_NFE_COMPRA = txtChaveNfeCompra.Text,
PAGAMENTO_PEDIDO = txtPagamentoPedido.Text,
PAGAMENTO_FRETE = txtPagamentoFrete.Text,
RASTREIO_FRETE = txtRastreioFrete.Text
};
// Comunicação direta com sua BLL/DAL para persistir no banco SQL Server
MessageBox.Show("Pedido registrado e integrado com sucesso!", "LevelOS", MessageBoxButtons.OK, MessageBoxIcon.Information);
}
protected override void OnAlterar()
{
txtSituacao.Focus();
}
protected override void OnExcluir()
{
if (MessageBox.Show("Atenção! A exclusão deste pedido pode afetar o fluxo financeiro e o estoque. Confirmar?", "LevelOS", MessageBoxButtons.YesNo, MessageBoxIcon.Warning) == DialogResult.Yes)
{
// Comando de deleção...
OnNovo();
}
}
protected override void OnLocalizar()
{
// Aciona sua tela de consulta/Grid de pedidos
}
protected override void OnCancelar()
{
OnNovo();
}
}
}

View File

@ -0,0 +1,115 @@
using CPM;
using MLL;
using System;
using System.Drawing;
using System.Windows.Forms;
namespace UI
{
public class PerfilPanel : FormularioModelo
{
// Mapeamento absoluto de todas as propriedades do ModeloPerfil
private LV_TEXTBOX1 txtId;
private LV_TEXTBOX1 txtEmpresaId;
private LV_TEXTBOX1 txtNome;
private LV_TEXTBOX1 txtDescricao;
private CheckBox chkAtivo;
public PerfilPanel()
{
this.Titulo = "CONTROLE DE PERFIS DE ACESSO";
MontarInterfaceCompleta();
}
private void MontarInterfaceCompleta()
{
// --- SEÇÃO ÚNICA: ESTRUTURA DO PERFIL ---
content.Controls.Add(CreateSectionHeader("Configurações do Perfil de Usuário", 20));
// Linha 1: Chaves de Identificação e Vínculo Multi-Empresa
txtId = AddInput(content, "ID PERFIL", 20, 55, 110, 28, true);
txtEmpresaId = AddInput(content, "ID EMPRESA", 145, 55, 120, 28);
// Status Ativo/Inativo posicionado de forma alinhada na primeira linha
chkAtivo = new CheckBox
{
Text = "Perfil Liberado / Ativo",
Location = new Point(285, 71),
AutoSize = true,
Font = new Font("Segoe UI", 10F, FontStyle.Bold),
ForeColor = Color.FromArgb(64, 64, 64)
};
content.Controls.Add(chkAtivo);
// Linha 2: Nome do Grupo/Perfil
txtNome = AddInput(content, "NOME DO PERFIL (EX: ADMINISTRADOR, VENDEDOR)", 20, 115, 500, 28);
// Linha 3: Detalhamento das Permissões do Perfil
txtDescricao = AddInput(content, "DESCRIÇÃO DAS ATRIBUIÇÕES E PERMISSÕES DESTE NÍVEL", 20, 175, 500, 28);
}
// --- MÉTODOS OBRIGATÓRIOS DO FORMULÁRIO MODELO ---
protected override void OnNovo()
{
// Limpa os campos de texto editáveis
txtEmpresaId.Text = string.Empty;
txtNome.Text = string.Empty;
txtDescricao.Text = string.Empty;
// Estado padrão para novas inserções
txtId.Text = "0";
chkAtivo.Checked = true;
txtEmpresaId.Focus();
}
protected override void OnSalvar()
{
// Validação simples antes de montar o objeto
if (string.IsNullOrWhiteSpace(txtNome.Text))
{
MessageBox.Show("O nome do perfil é obrigatório.", "Aviso", MessageBoxButtons.OK, MessageBoxIcon.Warning);
txtNome.Focus();
return;
}
// Mapeamento absoluto de todas as propriedades da classe
var perfil = new ModeloPerfil
{
Id = string.IsNullOrEmpty(txtId.Text) ? 0 : Convert.ToInt32(txtId.Text),
EmpresaId = string.IsNullOrEmpty(txtEmpresaId.Text) ? 0 : Convert.ToInt32(txtEmpresaId.Text),
Nome = txtNome.Text,
Descricao = txtDescricao.Text,
Ativo = chkAtivo.Checked // Atribuição booleana direta sem necessidade de conversão de string
};
// Envio do objeto limpo e populado para sua camada BLL / DAL do SQL Server
MessageBox.Show("Perfil de acesso salvo com sucesso!", "LevelOS", MessageBoxButtons.OK, MessageBoxIcon.Information);
}
protected override void OnAlterar()
{
txtNome.Focus();
}
protected override void OnExcluir()
{
if (MessageBox.Show("Deseja realmente remover este perfil? Usuários vinculados a ele podem perder o acesso ao sistema.", "LevelOS", MessageBoxButtons.YesNo, MessageBoxIcon.Warning) == DialogResult.Yes)
{
// Executa exclusão física ou lógica...
OnNovo();
}
}
protected override void OnLocalizar()
{
// Abre sua Grid / Tela de pesquisa para buscar os perfis existentes
}
protected override void OnCancelar()
{
OnNovo();
}
}
}

View File

@ -0,0 +1,97 @@
using CPM;
using MLL;
using System;
using System.Drawing;
using System.Windows.Forms;
namespace UI
{
public class PermissaoPanel : FormularioModelo
{
// Mapeamento absoluto de todas as propriedades do ModeloPermissao
private LV_TEXTBOX1 txtId;
private LV_TEXTBOX1 txtNome;
private LV_TEXTBOX1 txtDescricao;
public PermissaoPanel()
{
this.Titulo = "CADASTRO DE PERMISSÕES DO SISTEMA";
MontarInterfaceCompleta();
}
private void MontarInterfaceCompleta()
{
// --- SEÇÃO ÚNICA: DADOS DA PERMISSÃO ---
content.Controls.Add(CreateSectionHeader("Identificação da Diretiva de Segurança", 20));
// Linha 1: ID de Registro (Desabilitado por padrão)
txtId = AddInput(content, "ID PERMISSÃO", 20, 55, 110, 28, true);
// Linha 2: Chave Identificadora da Permissao (ex: os_deletar_registro)
txtNome = AddInput(content, "CHAVE IDENTIFICADORA DA PERMISSÃO (SISTEMA_ACAO)", 20, 115, 500, 28);
// Linha 3: Detalhamento amigável para o usuário administrador entender o que ela faz
txtDescricao = AddInput(content, "DESCRIÇÃO DETALHADA DO RECURSO BLOQUEADO / LIBERADO", 20, 175, 650, 28);
}
// --- MÉTODOS OBRIGATÓRIOS DO FORMULÁRIO MODELO ---
protected override void OnNovo()
{
// Limpa os campos editáveis
txtNome.Text = string.Empty;
txtDescricao.Text = string.Empty;
// Define o ID padrão de inserção
txtId.Text = "0";
txtNome.Focus();
}
protected override void OnSalvar()
{
// Validação mínima de consistência de dados
if (string.IsNullOrWhiteSpace(txtNome.Text))
{
MessageBox.Show("A chave identificadora da permissão é obrigatória.", "Aviso", MessageBoxButtons.OK, MessageBoxIcon.Warning);
txtNome.Focus();
return;
}
// Mapeamento absoluto de todas as propriedades do ModeloPermissao
var permissao = new ModeloPermissao
{
Id = string.IsNullOrEmpty(txtId.Text) ? 0 : Convert.ToInt32(txtId.Text),
Nome = txtNome.Text,
Descricao = txtDescricao.Text
};
// Processa o envio do objeto estruturado para as regras de persistência (BLL / DAL)
MessageBox.Show("Permissão gravada no dicionário de segurança!", "LevelOS", MessageBoxButtons.OK, MessageBoxIcon.Information);
}
protected override void OnAlterar()
{
txtNome.Focus();
}
protected override void OnExcluir()
{
if (MessageBox.Show("Aviso! Remover esta permissão pode invalidar as checagens de segurança no código-fonte do sistema. Deseja continuar?", "LevelOS", MessageBoxButtons.YesNo, MessageBoxIcon.Warning) == DialogResult.Yes)
{
// Processa a rotina de exclusão física do banco de dados...
OnNovo();
}
}
protected override void OnLocalizar()
{
// Aciona o seu Grid de busca para selecionar as permissões instaladas
}
protected override void OnCancelar()
{
OnNovo();
}
}
}

View File

@ -0,0 +1,163 @@
using CPM;
using MLL;
using System;
using System.Drawing;
using System.Windows.Forms;
namespace UI
{
public class PlanoDeContasPanel : FormularioModelo
{
// Mapeamento absoluto de todas as propriedades do ModeloPlanoDeContas
private LV_TEXTBOX1 txtId;
private LV_TEXTBOX1 txtEmpresaId;
private LV_TEXTBOX1 txtContaPaiId;
private LV_TEXTBOX1 txtNome;
private LV_TEXTBOX1 txtCodigo;
private LV_TEXTBOX1 txtTipo;
private CheckBox chkAceitaLancamento;
private CheckBox chkAtivo;
private LV_TEXTBOX1 txtCriadoEm;
private LV_TEXTBOX1 txtAtualizadoEm;
public PlanoDeContasPanel()
{
this.Titulo = "ESTRUTURAÇÃO DO PLANO DE CONTAS FINACEIRO";
MontarInterfaceCompleta();
}
private void MontarInterfaceCompleta()
{
// --- SEÇÃO 1: HIERARQUIA E IDENTIFICAÇÃO ---
content.Controls.Add(CreateSectionHeader("Classificação e Hierarquia da Conta", 20));
txtId = AddInput(content, "ID REGISTRO", 20, 55, 100, 28, true);
txtEmpresaId = AddInput(content, "ID EMPRESA", 135, 55, 110, 28);
txtCodigo = AddInput(content, "CÓDIGO ESTRUTURAL (EX: 1.01.02)", 260, 55, 230, 28);
txtContaPaiId = AddInput(content, "ID CONTA PAI (NULO P/ GRUPO RAIZ)", 505, 55, 230, 28);
// --- SEÇÃO 2: DEFINIÇÃO COMERCIAL ---
content.Controls.Add(CreateSectionHeader("Dados de Identificação e Regras de Operação", 115));
txtNome = AddInput(content, "NOME DA CONTA (EX: ENERGIA ELÉTRICA, RECEITA DE VENDAS)", 20, 150, 470, 28);
txtTipo = AddInput(content, "TIPO (RECEITA / DESPESA / ATIVO)", 505, 150, 230, 28);
// Checkboxes de Regras de Negócio e Status alinhados lado a lado
chkAceitaLancamento = new CheckBox
{
Text = "Aceita Lançamento Direto (Conta Analítica)",
Location = new Point(20, 200),
AutoSize = true,
Font = new Font("Segoe UI", 9.5F, FontStyle.Bold),
ForeColor = Color.FromArgb(64, 64, 64)
};
content.Controls.Add(chkAceitaLancamento);
chkAtivo = new CheckBox
{
Text = "Conta Ativa no Sistema",
Location = new Point(350, 200),
AutoSize = true,
Font = new Font("Segoe UI", 9.5F, FontStyle.Bold),
ForeColor = Color.FromArgb(64, 64, 64)
};
content.Controls.Add(chkAtivo);
// --- SEÇÃO 3: AUDITORIA ---
content.Controls.Add(CreateSectionHeader("Datas de Auditoria e Controle de Registro", 245));
txtCriadoEm = AddInput(content, "DATA DE CRIAÇÃO", 20, 280, 220, 28, true);
txtAtualizadoEm = AddInput(content, "ÚLTIMA ATUALIZAÇÃO", 255, 280, 220, 28, true);
}
// --- MÉTODOS OBRIGATÓRIOS DO FORMULÁRIO MODELO ---
protected override void OnNovo()
{
// Limpa os campos editáveis de texto
txtEmpresaId.Text = string.Empty;
txtCodigo.Text = string.Empty;
txtContaPaiId.Text = string.Empty;
txtNome.Text = string.Empty;
txtTipo.Text = string.Empty;
// Valores padrão para novos registros
txtId.Text = "0";
chkAceitaLancamento.Checked = true;
chkAtivo.Checked = true;
txtCriadoEm.Text = DateTime.Now.ToString("g");
txtAtualizadoEm.Text = DateTime.Now.ToString("g");
txtCodigo.Focus();
}
protected override void OnSalvar()
{
// Validações básicas de negócio
if (string.IsNullOrWhiteSpace(txtCodigo.Text))
{
MessageBox.Show("O código estrutural da conta é obrigatório.", "Aviso", MessageBoxButtons.OK, MessageBoxIcon.Warning);
txtCodigo.Focus();
return;
}
if (string.IsNullOrWhiteSpace(txtNome.Text))
{
MessageBox.Show("O nome da conta é obrigatório.", "Aviso", MessageBoxButtons.OK, MessageBoxIcon.Warning);
txtNome.Focus();
return;
}
// Tratamento explícito para o tipo Nullable (int?) da ContaPaiId
int? contaPai = null;
if (!string.IsNullOrWhiteSpace(txtContaPaiId.Text) && int.TryParse(txtContaPaiId.Text, out int resultId))
{
contaPai = resultId;
}
// Mapeamento absoluto e tipado de todas as propriedades do ModeloPlanoDeContas
var conta = new ModeloPlanoDeContas
{
Id = string.IsNullOrEmpty(txtId.Text) ? 0 : Convert.ToInt32(txtId.Text),
EmpresaId = string.IsNullOrEmpty(txtEmpresaId.Text) ? 0 : Convert.ToInt32(txtEmpresaId.Text),
ContaPaiId = contaPai,
Codigo = txtCodigo.Text,
Nome = txtNome.Text,
Tipo = txtTipo.Text,
AceitaLancamento = chkAceitaLancamento.Checked,
Ativo = chkAtivo.Checked,
// Preserva ou trata as datas de auditoria
CriadoEm = string.IsNullOrEmpty(txtCriadoEm.Text) ? DateTime.Now : Convert.ToDateTime(txtCriadoEm.Text),
AtualizadoEm = DateTime.Now // Sempre grava a data do momento do save
};
// Envio do objeto limpo e preenchido para as camadas BLL / DAL do SQL Server
MessageBox.Show("Conta cadastrada com sucesso no plano de contas!", "LevelOS", MessageBoxButtons.OK, MessageBoxIcon.Information);
}
protected override void OnAlterar()
{
txtNome.Focus();
}
protected override void OnExcluir()
{
if (MessageBox.Show("Atenção! Remover uma conta com lançamentos financeiros vinculados pode corromper os relatórios de DRE e fluxo de caixa. Confirmar exclusão?", "LevelOS", MessageBoxButtons.YesNo, MessageBoxIcon.Warning) == DialogResult.Yes)
{
// Processa deleção...
OnNovo();
}
}
protected override void OnLocalizar()
{
// Abre sua Grid de pesquisa ou componente TreeView do plano de contas
}
protected override void OnCancelar()
{
OnNovo();
}
}
}

View File

@ -0,0 +1,166 @@
using CPM;
using MLL;
using System;
using System.Drawing;
using System.Windows.Forms;
namespace UI.Dashboards.Cadastro
{
public class ServicosPanel : FormularioModelo
{
// Controles marcados como anuláveis para sanar avisos do compilador modernos (NRT)
private LV_TEXTBOX1? txtId;
private LV_TEXTBOX1? txtEmpresaId;
private LV_TEXTBOX1? txtNome;
private LV_TEXTBOX1? txtDescricao;
private LV_TEXTBOX1? txtValorPadrao;
private LV_TEXTBOX1? txtCusto;
private LV_TEXTBOX1? txtTipoComissao;
private LV_TEXTBOX1? txtValorComissao;
private LV_TEXTBOX1? txtTempoEstimado;
private LV_TEXTBOX1? txtCriadoEm;
private LV_TEXTBOX1? txtAtualizadoEm;
private CheckBox? chkAtivo;
public ServicosPanel()
{
this.Titulo = "CADASTRO E CONFIGURAÇÃO DE SERVIÇOS";
MontarInterfaceCompleta();
}
private void MontarInterfaceCompleta()
{
// --- SEÇÃO 1: IDENTIFICAÇÃO E DADOS GERAIS ---
content.Controls.Add(CreateSectionHeader("Identificação do Serviço", 20));
txtId = AddInput(content, "ID SERVIÇO", 20, 55, 100, 28, true);
txtEmpresaId = AddInput(content, "ID EMPRESA", 135, 55, 100, 28);
txtNome = AddInput(content, "NOME DO SERVIÇO", 250, 55, 400, 28);
// CheckBox customizado ou nativo alinhado ao grid visual
chkAtivo = new CheckBox
{
Text = "Serviço Ativo",
Location = new Point(670, 58),
Size = new Size(120, 24),
Font = new Font("Segoe UI", 10f, FontStyle.Bold),
ForeColor = Color.FromArgb(45, 45, 45),
Checked = true
};
content.Controls.Add(chkAtivo);
txtDescricao = AddInput(content, "DESCRIÇÃO DETALHADA DO SERVIÇO", 20, 115, 630, 28);
// --- SEÇÃO 2: VALORES E PRECIFICAÇÃO ---
content.Controls.Add(CreateSectionHeader("Precificação, Custos e Regras de Comissão", 185));
txtValorPadrao = AddInput(content, "VALOR PADRÃO VENDA (R$)", 20, 220, 180, 28);
txtCusto = AddInput(content, "CUSTO DO SERVIÇO (R$)", 215, 220, 180, 28);
txtTipoComissao = AddInput(content, "TIPO COMISSÃO (EX: % OU FIXO)", 410, 220, 220, 28);
txtValorComissao = AddInput(content, "VALOR COMISSÃO", 645, 220, 145, 28);
// --- SEÇÃO 3: OPERAÇÃO E LOG DE AUDITORIA ---
content.Controls.Add(CreateSectionHeader("Tempo de Execução e Auditoria", 290));
txtTempoEstimado = AddInput(content, "TEMPO ESTIMADO (EM MINUTOS)", 20, 325, 220, 28); // Grafia corrigida aqui
txtCriadoEm = AddInput(content, "DATA DE CRIAÇÃO", 255, 325, 180, 28, true);
txtAtualizadoEm = AddInput(content, "ÚLTIMA ATUALIZAÇÃO", 445, 325, 180, 28, true);
}
// --- MÉTODOS OBRIGATÓRIOS DO FORMULÁRIO MODELO ---
protected override void OnNovo()
{
// Varre e limpa os inputs do painel
foreach (Control c in content.Controls)
{
if (c is LV_TEXTBOX1 txt && !txt.ReadOnly)
{
txt.Text = string.Empty;
}
}
if (txtId != null) txtId.Text = "0";
if (txtEmpresaId != null) txtEmpresaId.Text = "1"; // Default para a empresa ativa principal
if (txtValorPadrao != null) txtValorPadrao.Text = "0,00";
if (txtCusto != null) txtCusto.Text = "0,00";
if (txtValorComissao != null) txtValorComissao.Text = "0,00";
if (txtTempoEstimado != null) txtTempoEstimado.Text = "0";
if (txtCriadoEm != null) txtCriadoEm.Text = DateTime.Now.ToString("g");
if (txtAtualizadoEm != null) txtAtualizadoEm.Text = DateTime.Now.ToString("g");
if (chkAtivo != null) chkAtivo.Checked = true;
txtNome?.Focus();
}
protected override void OnSalvar()
{
if (string.IsNullOrWhiteSpace(txtNome?.Text))
{
MessageBox.Show("O nome do serviço é obrigatório.", "Aviso", MessageBoxButtons.OK, MessageBoxIcon.Warning);
txtNome?.Focus();
return;
}
// Conversões seguras extraídas dos componentes de texto de forma resiliente
int idServico = string.IsNullOrEmpty(txtId?.Text) ? 0 : Convert.ToInt32(txtId.Text);
int idEmpresa = string.IsNullOrEmpty(txtEmpresaId?.Text) ? 0 : Convert.ToInt32(txtEmpresaId.Text);
decimal.TryParse(txtValorPadrao?.Text, out decimal vPadrao);
decimal.TryParse(txtValorComissao?.Text, out decimal vComissao);
decimal? vCusto = null;
if (!string.IsNullOrWhiteSpace(txtCusto?.Text) && decimal.TryParse(txtCusto.Text, out decimal cParsed))
vCusto = cParsed;
int? tEstimado = null;
if (!string.IsNullOrWhiteSpace(txtTempoEstimado?.Text) && int.TryParse(txtTempoEstimado.Text, out int tParsed))
tEstimado = tParsed;
// Mapeamento cirúrgico de todas as 12 propriedades da classe ModeloServicos
var servico = new ModeloServicos
{
Id = idServico,
EmpresaId = idEmpresa,
Nome = txtNome.Text,
Descricao = txtDescricao?.Text ?? string.Empty,
ValorPadrao = vPadrao,
Custo = vCusto,
TipoComissao = txtTipoComissao?.Text ?? string.Empty,
ValorComissao = vComissao,
TempoEstimado = tEstimado,
Ativo = chkAtivo?.Checked ?? false,
CriadoEm = string.IsNullOrEmpty(txtCriadoEm?.Text) ? DateTime.Now : Convert.ToDateTime(txtCriadoEm.Text),
AtualizadoEm = DateTime.Now // Sempre carimba a hora do salvamento atual
};
// Aqui o objeto 'servico' está pronto para ser enviado para sua camada de persistência (BLL / DAL)
MessageBox.Show($"Serviço '{servico.Nome}' salvo com sucesso!", "LevelOS", MessageBoxButtons.OK, MessageBoxIcon.Information);
}
protected override void OnAlterar()
{
txtNome?.Focus();
}
protected override void OnExcluir()
{
if (MessageBox.Show("Deseja realmente remover este serviço do catálogo?", "LevelOS", MessageBoxButtons.YesNo, MessageBoxIcon.Warning) == DialogResult.Yes)
{
OnNovo();
}
}
protected override void OnLocalizar()
{
// Vinculado à Grid de busca global de serviços
}
protected override void OnCancelar()
{
OnNovo();
}
}
}

View File

@ -0,0 +1,186 @@
using CPM;
using MLL;
using System;
using System.Drawing;
using System.Windows.Forms;
namespace UI.Dashboards.Cadastro
{
public class SituacoesOSPanel : FormularioModelo
{
// Controles marcados como anuláveis para sanar avisos do compilador modernos (NRT)
private LV_TEXTBOX1? txtId, txtEmpresaId, txtDescricao, txtTipo, txtCorFundo, txtCorFonte, txtPlanoContasId, txtOrdem, txtCriadoEm, txtAtualizadoEm;
private CheckBox? chkConsideraAberta, chkConsideraFechada, chkMarcaComoPronto, chkAtivo;
public SituacoesOSPanel()
{
this.Titulo = "SITUAÇÕES E STATUS DE ORDENS DE SERVIÇO (OS)";
MontarInterfaceCompleta();
}
private void MontarInterfaceCompleta()
{
// --- SEÇÃO 1: IDENTIFICAÇÃO E ESPECIFICAÇÃO ---
content.Controls.Add(CreateSectionHeader("Identificação do Status da OS", 20));
txtId = AddInput(content, "ID SITUAÇÃO", 20, 55, 100, 28, true);
txtEmpresaId = AddInput(content, "ID EMPRESA", 135, 55, 100, 28);
txtDescricao = AddInput(content, "DESCRIÇÃO DO STATUS (EX: EM ANDAMENTO)", 250, 55, 350, 28);
txtTipo = AddInput(content, "TIPO", 615, 55, 140, 28);
chkAtivo = new CheckBox
{
Text = "Status Ativo",
Location = new Point(770, 58),
Size = new Size(110, 24),
Font = new Font("Segoe UI", 10f, FontStyle.Bold),
ForeColor = Color.FromArgb(45, 45, 45),
Checked = true
};
content.Controls.Add(chkAtivo);
// --- SEÇÃO 2: REGRAS DE COMPORTAMENTO ---
content.Controls.Add(CreateSectionHeader("Comportamento e Regras de Negócio no Fluxo de OS", 115));
chkConsideraAberta = new CheckBox
{
Text = "Considerar OS Aberta (Pendente / Em Execução)",
Location = new Point(25, 150),
Size = new Size(350, 24),
Font = new Font("Segoe UI", 9.5f)
};
chkConsideraFechada = new CheckBox
{
Text = "Considerar OS Fechada (Finalizada / Encerrada)",
Location = new Point(400, 150),
Size = new Size(350, 24),
Font = new Font("Segoe UI", 9.5f)
};
chkMarcaComoPronto = new CheckBox
{
Text = "Marcar OS como Pronta (Aguardando Retirada / Entrega)",
Location = new Point(25, 185),
Size = new Size(450, 24),
Font = new Font("Segoe UI", 9.5f)
};
content.Controls.AddRange(new Control[] { chkConsideraAberta, chkConsideraFechada, chkMarcaComoPronto });
// --- SEÇÃO 3: INTEGRALIZAÇÃO, CORES E TRIAGEM ---
content.Controls.Add(CreateSectionHeader("Integração Financeira, Ordenação e Identidade Visual", 235));
txtPlanoContasId = AddInput(content, "ID PLANO DE CONTAS", 20, 270, 150, 28);
txtOrdem = AddInput(content, "ORDEM DE EXIBIÇÃO", 185, 270, 140, 28);
txtCorFundo = AddInput(content, "COR DO FUNDO (HEX)", 340, 270, 180, 28);
txtCorFonte = AddInput(content, "COR DA FONTE (HEX)", 535, 270, 180, 28);
// --- SEÇÃO 4: AUDITORIA ---
content.Controls.Add(CreateSectionHeader("Histórico do Registro", 335));
txtCriadoEm = AddInput(content, "DATA DE CRIAÇÃO", 20, 370, 180, 28, true);
txtAtualizadoEm = AddInput(content, "ÚLTIMA ATUALIZAÇÃO", 215, 370, 180, 28, true);
}
// --- MÉTODOS OBRIGATÓRIOS DO FORMULÁRIO MODELO ---
protected override void OnNovo()
{
// Limpa caixas de texto editáveis
foreach (Control c in content.Controls)
{
if (c is LV_TEXTBOX1 txt && !txt.ReadOnly)
{
txt.Text = string.Empty;
}
}
// Reseta CheckBoxes
if (chkConsideraAberta != null) chkConsideraAberta.Checked = false;
if (chkConsideraFechada != null) chkConsideraFechada.Checked = false;
if (chkMarcaComoPronto != null) chkMarcaComoPronto.Checked = false;
if (chkAtivo != null) chkAtivo.Checked = true;
// Valores padrão iniciais
if (txtId != null) txtId.Text = "0";
if (txtEmpresaId != null) txtEmpresaId.Text = "1";
if (txtOrdem != null) txtOrdem.Text = "1";
if (txtCorFundo != null) txtCorFundo.Text = "#FFFFFF";
if (txtCorFonte != null) txtCorFonte.Text = "#000000";
if (txtCriadoEm != null) txtCriadoEm.Text = DateTime.Now.ToString("g");
if (txtAtualizadoEm != null) txtAtualizadoEm.Text = DateTime.Now.ToString("g");
txtDescricao?.Focus();
}
protected override void OnSalvar()
{
if (string.IsNullOrWhiteSpace(txtDescricao?.Text))
{
MessageBox.Show("A descrição do status da OS é obrigatória.", "Aviso", MessageBoxButtons.OK, MessageBoxIcon.Warning);
txtDescricao?.Focus();
return;
}
// Tratamento resiliente de inteiros
int idStatus = string.IsNullOrEmpty(txtId?.Text) ? 0 : Convert.ToInt32(txtId.Text);
int idEmpresa = string.IsNullOrEmpty(txtEmpresaId?.Text) ? 0 : Convert.ToInt32(txtEmpresaId.Text);
// Tratamento seguro de inteiros anuláveis (int?)
int? planoContasId = null;
if (!string.IsNullOrWhiteSpace(txtPlanoContasId?.Text) && int.TryParse(txtPlanoContasId.Text, out int pcParsed))
planoContasId = pcParsed;
int? ordemExibicao = null;
if (!string.IsNullOrWhiteSpace(txtOrdem?.Text) && int.TryParse(txtOrdem.Text, out int ordParsed))
ordemExibicao = ordParsed;
// Mapeamento absoluto de todas as 14 propriedades da classe ModeloSituacoesOS
var situacaoOS = new ModeloSituacoesOS
{
Id = idStatus,
EmpresaId = idEmpresa,
Descricao = txtDescricao.Text,
Tipo = txtTipo?.Text ?? string.Empty,
ConsideraAberta = chkConsideraAberta?.Checked ?? false,
ConsideraFechada = chkConsideraFechada?.Checked ?? false,
MarcaComoPronto = chkMarcaComoPronto?.Checked ?? false,
CorFundo = txtCorFundo?.Text ?? string.Empty,
CorFonte = txtCorFonte?.Text ?? string.Empty,
PlanoContasId = planoContasId,
Ordem = ordemExibicao,
Ativo = chkAtivo?.Checked ?? false,
CriadoEm = string.IsNullOrEmpty(txtCriadoEm?.Text) ? DateTime.Now : Convert.ToDateTime(txtCriadoEm.Text),
AtualizadoEm = DateTime.Now // Atualiza o carimbo de data
};
// Envio do objeto estruturado para a persistência em banco de dados SQL Server via BLL/DAL
MessageBox.Show($"Status de OS '{situacaoOS.Descricao}' salvo com sucesso!", "LevelOS", MessageBoxButtons.OK, MessageBoxIcon.Information);
}
protected override void OnAlterar()
{
txtDescricao?.Focus();
}
protected override void OnExcluir()
{
if (MessageBox.Show("A exclusão deste status pode invalidar o histórico de fluxo das ordens de serviço associadas. Deseja continuar?", "LevelOS", MessageBoxButtons.YesNo, MessageBoxIcon.Warning) == DialogResult.Yes)
{
OnNovo();
}
}
protected override void OnLocalizar()
{
// Aciona o grid interno para localização de status de OS existentes
}
protected override void OnCancelar()
{
OnNovo();
}
}
}

View File

@ -0,0 +1,135 @@
using CPM;
using MLL;
using System;
using System.Drawing;
using System.Windows.Forms;
namespace UI.Dashboards.Cadastro
{
public class SituacoesPanel : FormularioModelo
{
// Controles marcados como anuláveis para sanar avisos do compilador modernos (NRT)
private LV_TEXTBOX1? txtIdSituacoes;
private LV_TEXTBOX1? txtCodigo;
private LV_TEXTBOX1? txtNome;
private LV_TEXTBOX1? txtEtapa1;
private LV_TEXTBOX1? txtEtapa2;
private LV_TEXTBOX1? txtEtapa3;
private LV_TEXTBOX1? txtEtapa3Pg;
private LV_TEXTBOX1? txtPronto;
private LV_TEXTBOX1? txtSubgrupo;
private LV_TEXTBOX1? txtCorFonte;
private LV_TEXTBOX1? txtCorFundo;
private LV_TEXTBOX1? txtPlanoConta;
public SituacoesPanel()
{
this.Titulo = "CADASTRO E CONFIGURAÇÃO DE SITUAÇÕES / STATUS";
MontarInterfaceCompleta();
}
private void MontarInterfaceCompleta()
{
// --- SEÇÃO 1: IDENTIFICAÇÃO DO STATUS ---
content.Controls.Add(CreateSectionHeader("Identificação do Status", 20));
txtIdSituacoes = AddInput(content, "ID SITUAÇÃO", 20, 55, 110, 28, true);
txtCodigo = AddInput(content, "CÓDIGO INTERNO", 145, 55, 130, 28);
txtNome = AddInput(content, "NOME DA SITUAÇÃO / STATUS", 290, 55, 350, 28);
txtSubgrupo = AddInput(content, "SUBGRUPO", 655, 55, 150, 28);
// --- SEÇÃO 2: REGRAS E ETAPAS DO FLUXO ---
content.Controls.Add(CreateSectionHeader("Etapas e Regras do Fluxo de Trabalho", 115));
txtEtapa1 = AddInput(content, "ETAPA 1 (EX: TRIAGEM)", 20, 150, 185, 28);
txtEtapa2 = AddInput(content, "ETAPA 2 (EX: EM PROCESSO)", 220, 150, 185, 28);
txtEtapa3 = AddInput(content, "ETAPA 3 (EX: CONCLUÍDO)", 420, 150, 185, 28);
txtEtapa3Pg = AddInput(content, "ETAPA 3 PG (PAGO)", 620, 150, 185, 28);
txtPronto = AddInput(content, "INDICADOR PRONTO (S/N)", 20, 210, 185, 28);
txtPlanoConta = AddInput(content, "VÍNCULO PLANO DE CONTAS", 220, 210, 385, 28);
// --- SEÇÃO 3: ESTILIZAÇÃO VISUAL (GRID / KANBAN) ---
content.Controls.Add(CreateSectionHeader("Estilização Visual (Exibição em Telas e Grids)", 275));
txtCorFonte = AddInput(content, "COR DA FONTE (HEX: #FFFFFF)", 20, 310, 230, 28);
txtCorFundo = AddInput(content, "COR DO FUNDO (HEX: #007ACC)", 265, 310, 230, 28);
}
// --- MÉTODOS OBRIGATÓRIOS DO FORMULÁRIO MODELO ---
protected override void OnNovo()
{
// Varre e limpa de forma segura todos os campos que não são somente leitura
foreach (Control c in content.Controls)
{
if (c is LV_TEXTBOX1 txt && !txt.ReadOnly)
{
txt.Text = string.Empty;
}
}
if (txtIdSituacoes != null) txtIdSituacoes.Text = "0";
if (txtPronto != null) txtPronto.Text = "N";
if (txtCorFonte != null) txtCorFonte.Text = "#000000";
if (txtCorFundo != null) txtCorFundo.Text = "#FFFFFF";
txtCodigo?.Focus();
}
protected override void OnSalvar()
{
if (string.IsNullOrWhiteSpace(txtNome?.Text))
{
MessageBox.Show("O nome da situação é obrigatório para mapear os fluxos.", "Aviso", MessageBoxButtons.OK, MessageBoxIcon.Warning);
txtNome?.Focus();
return;
}
int idSituacoes = string.IsNullOrEmpty(txtIdSituacoes?.Text) ? 0 : Convert.ToInt32(txtIdSituacoes.Text);
// Mapeamento absoluto, limpo e direto de todas as propriedades da classe
var situacao = new ModeloSituacoes
{
ID_SITUACOES = idSituacoes,
CODIGO = txtCodigo?.Text ?? string.Empty,
NOME = txtNome.Text,
ETAPA1 = txtEtapa1?.Text ?? string.Empty,
ETAPA2 = txtEtapa2?.Text ?? string.Empty,
ETAPA3 = txtEtapa3?.Text ?? string.Empty,
ETAPA3_PG = txtEtapa3Pg?.Text ?? string.Empty,
PRONTO = txtPronto?.Text ?? string.Empty,
SUBGRUPO = txtSubgrupo?.Text ?? string.Empty,
COR_FONTE = txtCorFonte?.Text ?? string.Empty,
COR_FUNDO = txtCorFundo?.Text ?? string.Empty,
PLANO_CONTA = txtPlanoConta?.Text ?? string.Empty
};
// Objeto preenchido pronto para ser enviado para sua BLL / DAL e persistido no SQL Server
MessageBox.Show($"Situação '{situacao.NOME}' configurada com sucesso!", "LevelOS", MessageBoxButtons.OK, MessageBoxIcon.Information);
}
protected override void OnAlterar()
{
txtNome?.Focus();
}
protected override void OnExcluir()
{
if (MessageBox.Show("A exclusão deste status pode afetar registros históricos vinculados a ele. Confirma?", "LevelOS", MessageBoxButtons.YesNo, MessageBoxIcon.Warning) == DialogResult.Yes)
{
OnNovo();
}
}
protected override void OnLocalizar()
{
// Abre o grid de consulta para selecionar uma situação existente
}
protected override void OnCancelar()
{
OnNovo();
}
}
}

View File

@ -0,0 +1,164 @@
using CPM;
using MLL;
using System;
using System.Drawing;
using System.Windows.Forms;
namespace UI.Dashboards.Cadastro
{
public class UsuarioPerfisPanel : FormularioModelo
{
// Controles marcados como anuláveis para sanar avisos do compilador modernos (NRT)
private LV_TEXTBOX1? txtId;
private ComboBox? cbUsuario;
private CheckedListBox? clbPerfis;
public UsuarioPerfisPanel()
{
this.Titulo = "VÍNCULO DE PERFIS DE ACESSO POR USUÁRIO";
MontarInterfaceCompleta();
}
private void MontarInterfaceCompleta()
{
// --- SEÇÃO 1: IDENTIFICAÇÃO E SELEÇÃO DO USUÁRIO ---
content.Controls.Add(CreateSectionHeader("Seleção do Operador / Usuário", 20));
txtId = AddInput(content, "ID VÍNCULO", 20, 55, 100, 28, true);
// Label para o ComboBox de Usuário
var lblUsuario = new Label
{
Text = "SELECIONE O USUÁRIO DO SISTEMA",
Location = new Point(135, 40),
AutoSize = true,
Font = new Font("Segoe UI", 8.25f, FontStyle.Bold),
ForeColor = Color.FromArgb(90, 90, 90)
};
cbUsuario = new ComboBox
{
Location = new Point(135, 57),
Size = new Size(500, 28),
DropDownStyle = ComboBoxStyle.DropDownList,
Font = new Font("Segoe UI", 10f)
};
content.Controls.AddRange(new Control[] { lblUsuario, cbUsuario });
// --- SEÇÃO 2: ATRIBUIÇÃO DOS PERFIS ---
content.Controls.Add(CreateSectionHeader("Perfis de Segurança e Permissões Disponíveis", 115));
// CheckedListBox para o operador marcar múltiplos perfis de forma nativa e intuitiva
clbPerfis = new CheckedListBox
{
Location = new Point(20, 150),
Size = new Size(615, 250),
Font = new Font("Segoe UI", 10f),
CheckOnClick = true,
BorderStyle = BorderStyle.FixedSingle
};
content.Controls.Add(clbPerfis);
CarregarDadosIniciais();
}
private void CarregarDadosIniciais()
{
// Simulação de preenchimento dos combos (Aqui você chamará suas BLLs correspondentes)
if (cbUsuario != null)
{
cbUsuario.Items.Add("Selecione um operador...");
cbUsuario.Items.Add("Nicolas - Administrador do Sistema");
cbUsuario.Items.Add("Davi - Operador de Caixa");
cbUsuario.SelectedIndex = 0;
}
if (clbPerfis != null)
{
clbPerfis.Items.Add("ADMINISTRADOR GLOBAL");
clbPerfis.Items.Add("FANCEIRO / CONTÁBIL");
clbPerfis.Items.Add("VENDEDOR / EMISSOR NFC-E");
clbPerfis.Items.Add("SUPORTE TÉCNICO (ORDEM DE SERVIÇO)");
}
}
// --- MÉTODOS OBRIGATÓRIOS DO FORMULÁRIO MODELO ---
protected override void OnNovo()
{
if (txtId != null) txtId.Text = "0";
if (cbUsuario != null && cbUsuario.Items.Count > 0)
cbUsuario.SelectedIndex = 0;
if (clbPerfis != null)
{
for (int i = 0; i < clbPerfis.Items.Count; i++)
{
clbPerfis.SetItemChecked(i, false);
}
}
cbUsuario?.Focus();
}
protected override void OnSalvar()
{
if (cbUsuario == null || cbUsuario.SelectedIndex <= 0)
{
MessageBox.Show("Por favor, selecione um usuário válido para aplicar as permissões.", "Aviso", MessageBoxButtons.OK, MessageBoxIcon.Warning);
cbUsuario?.Focus();
return;
}
if (clbPerfis == null || clbPerfis.CheckedItems.Count == 0)
{
MessageBox.Show("Selecione ao menos um perfil de acesso para este usuário.", "Aviso", MessageBoxButtons.OK, MessageBoxIcon.Warning);
clbPerfis?.Focus();
return;
}
int idVinculo = string.IsNullOrEmpty(txtId?.Text) ? 0 : Convert.ToInt32(txtId.Text);
// Loop para ler os perfis checados e montar os objetos associativos
// Como é uma tabela NxN, você gerará um registro para cada Perfil Id associado àquele UsuarioId
foreach (var itemMarcado in clbPerfis.CheckedItems)
{
var usuarioPerfil = new ModeloUsuarioPerfis
{
Id = idVinculo,
UsuarioId = cbUsuario.SelectedIndex, // Mock simulando o ID recuperado do ValueMember
PerfilId = clbPerfis.Items.IndexOf(itemMarcado) + 1 // Mock simulando o ID do Perfil
};
// Aqui sua BLL/DAL processará cada vínculo (Inserindo ou deletando os antigos antes)
}
MessageBox.Show("Políticas e perfis de acesso atualizados com sucesso!", "LevelOS - Segurança", MessageBoxButtons.OK, MessageBoxIcon.Information);
}
protected override void OnAlterar()
{
cbUsuario?.Focus();
}
protected override void OnExcluir()
{
if (MessageBox.Show("Deseja revogar TODOS os perfis de acesso deste usuário? O operador perderá acesso às telas do sistema.", "LevelOS - Segurança", MessageBoxButtons.YesNo, MessageBoxIcon.Warning) == DialogResult.Yes)
{
OnNovo();
}
}
protected override void OnLocalizar()
{
// Vinculado à busca global de associações de segurança
}
protected override void OnCancelar()
{
OnNovo();
}
}
}

View File

@ -0,0 +1,167 @@
using CPM;
using MLL;
using System;
using System.Drawing;
using System.Windows.Forms;
namespace UI.Dashboards.Cadastro
{
public class UsuariosPanel : FormularioModelo
{
// Controles marcados como anuláveis para sanar avisos de compilação modernos (.NET 8 NRT)
private LV_TEXTBOX1? txtId;
private LV_TEXTBOX1? txtEmpresaId;
private LV_TEXTBOX1? txtNome;
private LV_TEXTBOX1? txtEmail;
private LV_TEXTBOX1? txtUsuario;
private LV_TEXTBOX1? txtSenhaHash;
private LV_TEXTBOX1? txtUltimoLogin;
private LV_TEXTBOX1? txtCriadoEm;
private LV_TEXTBOX1? txtAtualizadoEm;
private CheckBox? chkAtivo;
public UsuariosPanel()
{
this.Titulo = "GESTÃO E CONTROLE DE USUÁRIOS";
MontarInterfaceCompleta();
}
private void MontarInterfaceCompleta()
{
// --- SEÇÃO 1: IDENTIFICAÇÃO DO COLABORADOR ---
content.Controls.Add(CreateSectionHeader("Identificação do Operador", 20));
txtId = AddInput(content, "ID USUÁRIO", 20, 55, 100, 28, true);
txtEmpresaId = AddInput(content, "ID EMPRESA VÍNCULO", 135, 55, 130, 28);
txtNome = AddInput(content, "NOME COMPLETO", 280, 55, 370, 28);
chkAtivo = new CheckBox
{
Text = "Usuário Ativo",
Location = new Point(665, 58),
Size = new Size(120, 24),
Font = new Font("Segoe UI", 10f, FontStyle.Bold),
ForeColor = Color.FromArgb(45, 45, 45),
Checked = true
};
content.Controls.Add(chkAtivo);
txtEmail = AddInput(content, "E-MAIL DE CONTATO", 20, 115, 630, 28);
// --- SEÇÃO 2: CREDENCIAIS E AUTENTICAÇÃO ---
content.Controls.Add(CreateSectionHeader("Credenciais de Autenticação e Segurança", 185));
txtUsuario = AddInput(content, "NOME DE USUÁRIO / LOGIN", 20, 220, 250, 28);
// Campo de senha configurado nativamente para ocultar a digitação
txtSenhaHash = AddInput(content, "SENHA DE ACESSO", 285, 220, 250, 28);
if (txtSenhaHash != null)
{
txtSenhaHash.UseSystemPasswordChar = true;
}
// --- SEÇÃO 3: AUDITORIA E LOGS ---
content.Controls.Add(CreateSectionHeader("Histórico e Auditoria de Acessos", 290));
txtUltimoLogin = AddInput(content, "ÚLTIMO LOGIN", 20, 325, 200, 28, true);
txtCriadoEm = AddInput(content, "DATA DE CRIAÇÃO", 235, 325, 180, 28, true);
txtAtualizadoEm = AddInput(content, "ÚLTIMA ATUALIZAÇÃO", 430, 325, 180, 28, true);
}
// --- MÉTODOS OBRIGATÓRIOS DO FORMULÁRIO MODELO ---
protected override void OnNovo()
{
// Limpa de forma iterativa todas as caixas de texto editáveis do painel
foreach (Control c in content.Controls)
{
if (c is LV_TEXTBOX1 txt && !txt.ReadOnly)
{
txt.Text = string.Empty;
}
}
if (txtId != null) txtId.Text = "0";
if (txtEmpresaId != null) txtEmpresaId.Text = "1";
if (txtUltimoLogin != null) txtUltimoLogin.Text = "Nunca Conectado";
// Tratamento como string para exibição visual imediata das datas padrões
if (txtCriadoEm != null) txtCriadoEm.Text = DateTime.Now.ToString("g");
if (txtAtualizadoEm != null) txtAtualizadoEm.Text = DateTime.Now.ToString("g");
if (chkAtivo != null) chkAtivo.Checked = true;
txtNome?.Focus();
}
protected override void OnSalvar()
{
if (string.IsNullOrWhiteSpace(txtNome?.Text))
{
MessageBox.Show("O nome completo do operador é obrigatório.", "Aviso", MessageBoxButtons.OK, MessageBoxIcon.Warning);
txtNome?.Focus();
return;
}
if (string.IsNullOrWhiteSpace(txtUsuario?.Text))
{
MessageBox.Show("O login do usuário é obrigatório para autenticação.", "Aviso", MessageBoxButtons.OK, MessageBoxIcon.Warning);
txtUsuario?.Focus();
return;
}
int idUsuario = string.IsNullOrEmpty(txtId?.Text) ? 0 : Convert.ToInt32(txtId.Text);
int idEmpresa = string.IsNullOrEmpty(txtEmpresaId?.Text) ? 0 : Convert.ToInt32(txtEmpresaId.Text);
// Parsing resiliente de datas anuláveis (DateTime?) baseadas na interface
DateTime? ultimoLogin = null;
if (!string.IsNullOrEmpty(txtUltimoLogin?.Text) && DateTime.TryParse(txtUltimoLogin.Text, out DateTime ulParsed))
ultimoLogin = ulParsed;
DateTime? criadoEm = null;
if (!string.IsNullOrEmpty(txtCriadoEm?.Text) && DateTime.TryParse(txtCriadoEm.Text, out DateTime cParsed))
criadoEm = cParsed;
// Mapeamento absoluto das 10 propriedades da classe ModeloUsuarios
var usuario = new ModeloUsuarios
{
Id = idUsuario,
EmpresaId = idEmpresa,
Nome = txtNome.Text,
Email = txtEmail?.Text ?? string.Empty,
Usuario = txtUsuario.Text,
SenhaHash = txtSenhaHash?.Text ?? string.Empty, // Lembre-se de hashear (ex: SHA256/BCrypt) na sua BLL antes do banco
Ativo = chkAtivo?.Checked ?? false,
UltimoLogin = ultimoLogin,
CriadoEm = criadoEm,
AtualizadoEm = DateTime.Now // Carimba o momento exato da persistência
};
// Objeto completo pronto para ser passado à sua camada de regras de negócio (BLL)
MessageBox.Show($"Usuário '{usuario.Usuario}' salvo com sucesso!", "LevelOS", MessageBoxButtons.OK, MessageBoxIcon.Information);
}
protected override void OnAlterar()
{
txtNome?.Focus();
}
protected override void OnExcluir()
{
if (MessageBox.Show("Confirma a exclusão deste operador? O acesso ao sistema será revogado imediatamente.", "LevelOS", MessageBoxButtons.YesNo, MessageBoxIcon.Warning) == DialogResult.Yes)
{
OnNovo();
}
}
protected override void OnLocalizar()
{
// Aciona a Grid / Busca Geral de usuários cadastrados
}
protected override void OnCancelar()
{
OnNovo();
}
}
}

View File

@ -0,0 +1,121 @@
using CPM;
using MLL;
using System;
using System.Drawing;
using System.Windows.Forms;
namespace UI
{
public class ParametrosPanel : FormularioModelo
{
// Mapeamento absoluto de todas as propriedades do ModeloParametros
private LV_TEXTBOX1 txtIdParametros;
private LV_TEXTBOX1 txtCodigo;
private LV_TEXTBOX1 txtNomePar;
private LV_TEXTBOX1 txtDescricao;
private LV_TEXTBOX1 txtPx;
private LV_TEXTBOX1 txtPy;
private LV_TEXTBOX1 txtCampo;
private CheckBox chkAtivo;
public ParametrosPanel()
{
this.Titulo = "CADASTRO E POSICIONAMENTO DE PARAMETROS";
MontarInterfaceCompleta();
}
private void MontarInterfaceCompleta()
{
// --- SEÇÃO 1: IDENTIFICAÇÃO E CHAVES ---
content.Controls.Add(CreateSectionHeader("Identificação do Parâmetro", 20));
txtIdParametros = AddInput(content, "ID REGISTRO", 20, 55, 100, 28, true);
txtCodigo = AddInput(content, "CÓDIGO INTERNO", 130, 55, 120, 28);
txtNomePar = AddInput(content, "NOME DO PARÂMETRO (CHAVE)", 260, 55, 300, 28);
// Status Ativo/Inativo usando o posicionamento padrão
chkAtivo = new CheckBox
{
Text = "Parâmetro Ativo no Sistema",
Location = new Point(580, 71),
AutoSize = true,
Font = new Font("Segoe UI", 10F, FontStyle.Bold),
ForeColor = Color.FromArgb(64, 64, 64),
Checked = true
};
content.Controls.Add(chkAtivo);
// --- SEÇÃO 2: MAPEAMENTO DE COORDENADAS E INTERFACE ---
content.Controls.Add(CreateSectionHeader("Posicionamento e Mapeamento de Tela / Relatório", 115));
txtCampo = AddInput(content, "CAMPO DA TABELA / CONTROLE ALVO", 20, 150, 350, 28);
txtPx = AddInput(content, "COORDENADA X (PIXELS / COLUNA)", 390, 150, 200, 28);
txtPy = AddInput(content, "COORDENADA Y (PIXELS / LINHA)", 600, 150, 200, 28);
// --- SEÇÃO 3: DETALHAMENTO ---
content.Controls.Add(CreateSectionHeader("Documentação e Regras", 210));
txtDescricao = AddInput(content, "DESCRIÇÃO DA FUNÇÃO DO PARÂMETRO", 20, 245, 780, 28);
}
// --- MÉTODOS OBRIGATÓRIOS DO FORMULÁRIO MODELO ---
protected override void OnNovo()
{
// Limpa todos os controles de texto dentro do content
foreach (Control c in content.Controls)
{
if (c is LV_TEXTBOX1 txt && !txt.ReadOnly)
{
txt.Text = string.Empty;
}
}
chkAtivo.Checked = true;
txtCodigo.Focus();
}
protected override void OnSalvar()
{
// Mapeamento absoluto e fiel de cada campo para o objeto MLL
var parametro = new ModeloParametros
{
ID_PARAMETROS = string.IsNullOrEmpty(txtIdParametros.Text) ? 0 : Convert.ToInt32(txtIdParametros.Text),
CODIGO = txtCodigo.Text,
NOME_PAR = txtNomePar.Text,
DESCRICAO = txtDescricao.Text,
PX = txtPx.Text,
PY = txtPy.Text,
CAMPO = txtCampo.Text,
ATIVO = chkAtivo.Checked ? "S" : "N" // Conversão limpa para persistência string do seu banco
};
// Envio direto do objeto populado para as suas camadas de persistência (BLL/DAL)
MessageBox.Show("Configuração de parâmetro salva com sucesso!", "LevelOS", MessageBoxButtons.OK, MessageBoxIcon.Information);
}
protected override void OnAlterar()
{
txtNomePar.Focus();
}
protected override void OnExcluir()
{
if (MessageBox.Show("Deseja realmente excluir este parâmetro? Isso pode afetar o layout de telas ou relatórios.", "LevelOS", MessageBoxButtons.YesNo, MessageBoxIcon.Warning) == DialogResult.Yes)
{
// Processa a exclusão...
OnNovo();
}
}
protected override void OnLocalizar()
{
// Vincula a abertura da sua Grid de pesquisa de parâmetros
}
protected override void OnCancelar()
{
OnNovo();
}
}
}

View File

@ -0,0 +1,223 @@
using CPM;
using MLL;
using System;
using System.Drawing;
using System.Windows.Forms;
namespace UI.Dashboards.Cadastro
{
public class VendasPanel : FormularioModelo
{
// Container de abas para as 27 propriedades do modelo
private TabControl? tabVendas;
// --- ABA 1: RESUMO DO PEDIDO & CLIENTE ---
private LV_TEXTBOX1? txtIdVendas, txtCodigo, txtCliente, txtOperador, txtOperador2, txtDia, txtSituacaoV;
// --- ABA 2: FINANCEIRO E VALORES DE VENDA ---
private LV_TEXTBOX1? txtTotal, txtDesconto, txtTotalGeral, txtTotalServicos, txtTotalPecas, txtComissao, txtComissaoFixar;
// --- ABA 3: EXPEDIÇÃO, LOGÍSTICA & INTEGRAÇÃO ---
private LV_TEXTBOX1? txtTotalFrete, txtTransportadora, txtRastreio, txtGerouConta;
// --- ABA 4: FATURAMENTO FISCAL E OBSERVAÇÕES ---
private LV_TEXTBOX1? txtNfTipo, txtNfNumero, txtNfcNumero, txtNfsNumero, txtCupomNum, txtCancelada, txtObsVenda, txtObsVendaInterna;
public VendasPanel()
{
this.Titulo = "PDV - CENTRALIZADOR DE VENDAS E FATURAMENTO";
MontarInterfaceCompleta();
}
private void MontarInterfaceCompleta()
{
tabVendas = new TabControl
{
Location = new Point(10, 10),
Size = new Size(1060, 520),
Font = new Font("Segoe UI", 9.5f)
};
var tpGeral = new TabPage("1. Cabeçalho da Venda");
var tpValores = new TabPage("2. Totais e Precificação");
var tpLogistica = new TabPage("3. Despacho e Logística");
var tpFiscal = new TabPage("4. Fiscal & Observações");
tabVendas.TabPages.AddRange([tpGeral, tpValores, tpLogistica, tpFiscal]);
content.Controls.Add(tabVendas);
ConfigurarAbaGeral(tpGeral);
ConfigurarAbaValores(tpValores);
ConfigurarAbaLogistica(tpLogistica);
ConfigurarAbaFiscal(tpFiscal);
}
private void ConfigurarAbaGeral(TabPage tp)
{
tp.Controls.Add(CreateSectionHeader("Identificação Básica do Fluxo Comercial", 15));
txtIdVendas = AddInput(tp, "ID VENDA (SISTEMA)", 20, 50, 130, 28, true);
txtCodigo = AddInput(tp, "CÓDIGO PEDIDO / ORÇAMENTO", 165, 50, 180, 28);
txtDia = AddInput(tp, "DATA DA VENDA", 360, 50, 160, 28);
txtSituacaoV = AddInput(tp, "SITUAÇÃO / STATUS", 535, 50, 150, 28);
tp.Controls.Add(CreateSectionHeader("Operadores e Cliente Vinculado", 115));
txtCliente = AddInput(tp, "CLIENTE (NOME / RAZÃO SOCIAL)", 20, 150, 665, 28);
txtOperador = AddInput(tp, "OPERADOR PRINCIPAL (CAIXA / VENDEDOR)", 20, 210, 325, 28);
txtOperador2 = AddInput(tp, "OPERADOR 2 (ASSISTENTE / GERENTE)", 360, 210, 325, 28);
}
private void ConfigurarAbaValores(TabPage tp)
{
tp.Controls.Add(CreateSectionHeader("Divisão de Subtotais do Cupom / Pedido", 15));
txtTotalPecas = AddInput(tp, "TOTAL PRODUTOS / PEÇAS (+)", 20, 50, 210, 28);
txtTotalServicos = AddInput(tp, "TOTAL SERVIÇOS (+)", 245, 50, 210, 28);
txtDesconto = AddInput(tp, "DESCONTO APLICADO (-)", 470, 50, 215, 28);
tp.Controls.Add(CreateSectionHeader("Fechamento Líquido e Comissionamento", 115));
txtTotal = AddInput(tp, "SUBTOTAL BRUTO (R$)", 20, 150, 210, 28);
txtTotalGeral = AddInput(tp, "TOTAL GERAL LÍQUIDO (R$)", 245, 150, 210, 28);
txtComissao = AddInput(tp, "COMISSÃO OPERADOR (R$ ou %)", 20, 210, 210, 28);
txtComissaoFixar = AddInput(tp, "VALOR COMISSÃO FIXA (R$)", 245, 210, 210, 28);
}
private void ConfigurarAbaLogistica(TabPage tp)
{
tp.Controls.Add(CreateSectionHeader("Custos e Vinculações de Despacho", 15));
txtTotalFrete = AddInput(tp, "VALOR DO FRETE (R$)", 20, 50, 180, 28);
txtTransportadora = AddInput(tp, "TRANSPORTADORA PARCEIRA", 215, 50, 465, 28);
txtRastreio = AddInput(tp, "CÓDIGO DE RASTREAMENTO DO OBJETO", 20, 115, 660, 28);
tp.Controls.Add(CreateSectionHeader("Status Financeiro no Contas a Receber", 185));
txtGerouConta = AddInput(tp, "GEROU CONTA FINANCEIRA? (S/N)", 20, 220, 250, 28);
}
private void ConfigurarAbaFiscal(TabPage tp)
{
tp.Controls.Add(CreateSectionHeader("Documentação Fiscal Emitida (NF-e / NFC-e / NFS-e)", 15));
txtNfTipo = AddInput(tp, "TIPO DA NOTA (E/S)", 20, 50, 130, 28);
txtNfNumero = AddInput(tp, "NÚMERO NF-E", 165, 50, 160, 28);
txtNfcNumero = AddInput(tp, "NÚMERO NFC-E (CUPOM)", 340, 50, 160, 28);
txtNfsNumero = AddInput(tp, "NÚMERO NFS-E (SERVIÇO)", 515, 50, 160, 28);
txtCupomNum = AddInput(tp, "NÚMERO CONTROLE INTEGRAL / CUPOM", 20, 115, 225, 28);
txtCancelada = AddInput(tp, "VENDA CANCELADA? (S/N)", 260, 115, 215, 28);
tp.Controls.Add(CreateSectionHeader("Observações do Pedido", 185));
txtObsVenda = AddInput(tp, "OBSERVAÇÕES PÚBLICAS (SAÍDA NA NOTA/IMPRESSÃO)", 20, 220, 660, 28);
txtObsVendaInterna = AddInput(tp, "OBSERVAÇÕES INTERNAS (RESTRITO AO SISTEMA)", 20, 280, 660, 28);
}
// --- MÉTODOS OBRIGATÓRIOS DO FORMULÁRIO MODELO ---
protected override void OnNovo()
{
void LimparCamposFormulario(Control.ControlCollection controls)
{
foreach (Control c in controls)
{
if (c is LV_TEXTBOX1 txt && !txt.ReadOnly) txt.Text = string.Empty;
if (c.HasChildren) LimparCamposFormulario(c.Controls);
}
}
if (tabVendas != null)
{
LimparCamposFormulario(tabVendas.Controls);
tabVendas.SelectedIndex = 0;
}
if (txtIdVendas != null) txtIdVendas.Text = "0";
if (txtDia != null) txtDia.Text = DateTime.Today.ToString("dd/MM/yyyy");
if (txtSituacaoV != null) txtSituacaoV.Text = "ABERTA";
if (txtGerouConta != null) txtGerouConta.Text = "N";
if (txtCancelada != null) txtCancelada.Text = "N";
// Seta valores string como padrões limpos para evitar nulos visuais
if (txtTotal != null) txtTotal.Text = "0,00";
if (txtDesconto != null) txtDesconto.Text = "0,00";
if (txtTotalGeral != null) txtTotalGeral.Text = "0,00";
if (txtTotalServicos != null) txtTotalServicos.Text = "0,00";
if (txtTotalPecas != null) txtTotalPecas.Text = "0,00";
if (txtTotalFrete != null) txtTotalFrete.Text = "0,00";
if (txtComissao != null) txtComissao.Text = "0,00";
if (txtComissaoFixar != null) txtComissaoFixar.Text = "0,00";
txtCodigo?.Focus();
}
protected override void OnSalvar()
{
if (string.IsNullOrWhiteSpace(txtCliente?.Text))
{
MessageBox.Show("A definição do cliente é mandatória para faturar a venda.", "Aviso", MessageBoxButtons.OK, MessageBoxIcon.Warning);
if (tabVendas != null) tabVendas.SelectedIndex = 0;
txtCliente?.Focus();
return;
}
int idVenda = string.IsNullOrEmpty(txtIdVendas?.Text) ? 0 : Convert.ToInt32(txtIdVendas.Text);
// Mapeamento absoluto de todas as 27 propriedades da classe ModeloVendas
// Como suas propriedades são todas string, passamos o fallback 'string.Empty' ou '0,00'
var venda = new ModeloVendas
{
ID_VENDAS = idVenda,
CODIGO = txtCodigo?.Text ?? string.Empty,
OPERADOR = txtOperador?.Text ?? string.Empty,
TOTAL = txtTotal?.Text ?? "0,00",
DIA = txtDia?.Text ?? string.Empty,
COMISSAO = txtComissao?.Text ?? "0,00",
CLIENTE = txtCliente.Text,
DESCONTO = txtDesconto?.Text ?? "0,00",
TOTAL_GERAL = txtTotalGeral?.Text ?? "0,00",
TOTAL_SERVICOS = txtTotalServicos?.Text ?? "0,00",
TOTAL_PECAS = txtTotalPecas?.Text ?? "0,00",
TOTAL_IMPOSTOS = "0,00", // Fallback padrão de tributos
TOTAL_FRETE = txtTotalFrete?.Text ?? "0,00",
TRANSPORTADORA = txtTransportadora?.Text ?? string.Empty,
NF_TIPO = txtNfTipo?.Text ?? string.Empty,
SITUACAO_V = txtSituacaoV?.Text ?? string.Empty,
NF_NUMERO = txtNfNumero?.Text ?? string.Empty,
OBS_VENDA = txtObsVenda?.Text ?? string.Empty,
GEROU_CONTA = txtGerouConta?.Text ?? "N",
CUPOM_NUM = txtCupomNum?.Text ?? string.Empty,
OPERADOR2 = txtOperador2?.Text ?? string.Empty,
COMISSAO_FIXA = txtComissaoFixar?.Text ?? "0,00",
RASTREIO = txtRastreio?.Text ?? string.Empty,
OBS_VENDA_INTERNA = txtObsVendaInterna?.Text ?? string.Empty,
CANCELADA = txtCancelada?.Text ?? "N",
NFC_NUMERO = txtNfcNumero?.Text ?? string.Empty,
NFS_NUMERO = txtNfsNumero?.Text ?? string.Empty
};
// Objeto completo pronto para a BLL gerenciar validações fiscais e dar o INSERT/UPDATE
MessageBox.Show($"Venda sob o código '{venda.CODIGO}' processada!", "LevelOS - PDV", MessageBoxButtons.OK, MessageBoxIcon.Information);
}
protected override void OnAlterar()
{
if (tabVendas != null) tabVendas.SelectedIndex = 0;
txtCodigo?.Focus();
}
protected override void OnExcluir()
{
if (MessageBox.Show("Excluir uma venda pode comprometer a escrituração fiscal e os saldos de estoque. Deseja cancelar a venda em vez disso?", "LevelOS - Atenção", MessageBoxButtons.YesNo, MessageBoxIcon.Hand) == DialogResult.Yes)
{
if (txtCancelada != null) txtCancelada.Text = "S";
OnSalvar();
}
}
protected override void OnLocalizar()
{
// Aciona o grid de histórico geral de cupons e faturamentos
}
protected override void OnCancelar()
{
OnNovo();
}
}
}

View File

@ -0,0 +1,126 @@
using CPM;
using MLL;
using System;
using System.Drawing;
using System.Windows.Forms;
namespace UI
{
public class SatFiscalConsumidorFormasPanel : FormularioModelo
{
// Mapeamento absoluto de todas as propriedades do ModeloSatFiscalConsumidorFormas
private LV_TEXTBOX1 txtIdSatFiscalConsFormas;
private LV_TEXTBOX1 txtCodigo;
private LV_TEXTBOX1 txtCodNfce;
private LV_TEXTBOX1 txtForma;
private LV_TEXTBOX1 txtValor;
private LV_TEXTBOX1 txtDataCadastro;
private LV_TEXTBOX1 txtCnpjOperadora;
private LV_TEXTBOX1 txtTBand;
public SatFiscalConsumidorFormasPanel()
{
this.Titulo = "DETALHAMENTO DE FORMAS DE PAGAMENTO (NFC-E / SAT)";
MontarInterfaceCompleta();
}
private void MontarInterfaceCompleta()
{
// --- SEÇÃO 1: VÍNCULOS DA OPERAÇÃO ---
content.Controls.Add(CreateSectionHeader("Vínculos Fiscais e Código da Transação", 20));
txtIdSatFiscalConsFormas = AddInput(content, "ID REGISTRO", 20, 55, 110, 28, true);
txtCodigo = AddInput(content, "CÓDIGO INTERNO", 145, 55, 140, 28);
txtCodNfce = AddInput(content, "CÓD. VÍNCULO NFC-E / SAT", 300, 55, 200, 28);
txtDataCadastro = AddInput(content, "DATA DO LANÇAMENTO", 515, 55, 180, 28, true);
// --- SEÇÃO 2: DETALHES DO PAGAMENTO ---
content.Controls.Add(CreateSectionHeader("Valores e Regras do Meio de Pagamento (SEFAZ)", 115));
txtForma = AddInput(content, "FORMA (EX: 01-DINHEIRO, 03-CARTÃO CRÉDITO)", 20, 150, 320, 28);
txtValor = AddInput(content, "VALOR INTEGRADO (R$)", 355, 150, 150, 28);
// --- SEÇÃO 3: DADOS DE CARTÃO / TEF ---
content.Controls.Add(CreateSectionHeader("Identificação de Operações com Cartão (Crédito/Débito)", 210));
txtCnpjOperadora = AddInput(content, "CNPJ DA OPERADORA DO CARTÃO (ADQUIRENTE)", 20, 245, 320, 28);
txtTBand = AddInput(content, "CÓDIGO BANDEIRA (TBAND: 01-VISA, 02-MASTER)", 355, 245, 340, 28);
}
// --- MÉTODOS OBRIGATÓRIOS DO FORMULÁRIO MODELO ---
protected override void OnNovo()
{
// Varre e limpa os inputs de forma segura
foreach (Control c in content.Controls)
{
if (c is LV_TEXTBOX1 txt && !txt.ReadOnly)
{
txt.Text = string.Empty;
}
}
txtIdSatFiscalConsFormas.Text = "0";
txtDataCadastro.Text = DateTime.Now.ToString("g");
txtCodNfce.Focus();
}
protected override void OnSalvar()
{
// Validações básicas de negócio para evitar faturamento incompleto
if (string.IsNullOrWhiteSpace(txtCodNfce.Text))
{
MessageBox.Show("O código de vínculo da NFC-e é obrigatório.", "Aviso", MessageBoxButtons.OK, MessageBoxIcon.Warning);
txtCodNfce.Focus();
return;
}
if (string.IsNullOrWhiteSpace(txtForma.Text))
{
MessageBox.Show("A forma de pagamento é obrigatória.", "Aviso", MessageBoxButtons.OK, MessageBoxIcon.Warning);
txtForma.Focus();
return;
}
// Mapeamento absoluto, limpo e direto de todas as propriedades da classe
var formaPagamento = new ModeloSatFiscalConsumidorFormas
{
ID_SAT_FISCAL_CONS_FORMAS = string.IsNullOrEmpty(txtIdSatFiscalConsFormas.Text) ? 0 : Convert.ToInt32(txtIdSatFiscalConsFormas.Text),
CODIGO = txtCodigo.Text,
COD_NFCE = txtCodNfce.Text,
FORMA = txtForma.Text,
VALOR = txtValor.Text,
DATA_CADASTRO = txtDataCadastro.Text,
CNPJ_OPERADORA = txtCnpjOperadora.Text,
TBand = txtTBand.Text
};
// Envio do objeto preenchido para sua BLL / DAL para inserção ou update no SQL Server
MessageBox.Show("Forma de pagamento registrada com sucesso para o cupom fiscal!", "LevelOS", MessageBoxButtons.OK, MessageBoxIcon.Information);
}
protected override void OnAlterar()
{
txtForma.Focus();
}
protected override void OnExcluir()
{
if (MessageBox.Show("Deseja remover esta forma de pagamento? Isso alterará o balanço de fechamento do cupom fiscal.", "LevelOS", MessageBoxButtons.YesNo, MessageBoxIcon.Warning) == DialogResult.Yes)
{
// Processa a exclusão física...
OnNovo();
}
}
protected override void OnLocalizar()
{
// Abre o Grid para consultar as formas cadastradas neste cupom
}
protected override void OnCancelar()
{
OnNovo();
}
}
}

View File

@ -0,0 +1,290 @@
using CPM;
using MLL;
using System;
using System.Drawing;
using System.Windows.Forms;
namespace UI.Dashboards.Fiscal
{
public class SatFiscalConsumidorItensPanel : FormularioModelo
{
// Aplicação de (?) para sanar os avisos de campos não nulos ao sair do construtor (NRT net8.0)
private TabControl? tabItens;
// --- ABA 1: DADOS GERAIS DO PRODUTO ---
private LV_TEXTBOX1? txtIdSatFiscalConsItens, txtCodigo, txtCodNfce, txtItemTipo, txtItemCean, txtItemCprod, txtItemXprod, txtItemInfAdic, txtDataCadastro;
// --- ABA 2: QUANTIDADES, VALORES E COMERCIAL ---
private LV_TEXTBOX1? txtItemCfop, txtItemNcm, txtItemUncom, txtItemQcom, txtItemVprod, txtItemVoutro, txtItemVfrete, txtItemVseg, txtItemVdesc, txtItemVTotTrib, txtItemCest, txtCProdAnp, txtCBenef;
// --- ABA 3: ICMS (NORMAL E ST) ---
private LV_TEXTBOX1? txtItemOrigem, txtItemCst, txtItemIcmsModBc, txtItemIcmsPRedBc, txtItemIcmsVBc, txtItemIcmsPIcms, txtItemIcmsVIcms, txtItemIcmsVIcmsDeson, txtItemIcmsMotDesIcms, txtItemIcmsModBcSt, txtItemIcmsPMvast, txtItemIcmsPRedBcSt, txtItemIcmsVBcSt, txtItemIcmsPIcmsSt, txtItemIcmsVIcmsSt;
// --- ABA 4: FCP (FUNDO DE COMBATE À POBREZA) ---
private LV_TEXTBOX1? txtItemPFcp, txtItemVFcp, txtItemVBcFcp, txtItemVBcFcpSt, txtItemPFcpSt, txtItemVFcpSt, txtItemPSt, txtItemVBcFcpStRet, txtItemPFcpStRet, txtItemVFcpStRet;
// --- ABA 5: PIS, COFINS E EFETIVOS ---
private LV_TEXTBOX1? txtItemPisCst, txtItemPisVBc, txtItemPisPPis, txtItemPisVPis, txtItemCofinsCst, txtItemCofinsVBc, txtItemCofinsPCofins, txtItemCofinsVCofins, txtVIcmsSubstituto, txtPRedBcEfet, txtVBcEfet, txtPIcmsEfet, txtVIcmsEfet;
public SatFiscalConsumidorItensPanel()
{
this.Titulo = "DETALHAMENTO DE ITENS DO CUPOM FISCAL";
MontarInterfaceCompleta();
}
private void MontarInterfaceCompleta()
{
tabItens = new TabControl
{
Location = new Point(10, 10),
Size = new Size(1060, 520),
Font = new Font("Segoe UI", 9.5f)
};
var tpGeral = new TabPage("Dados do Produto");
var tpComercial = new TabPage("Valores e Códigos");
var tpIcms = new TabPage("ICMS Normal / ST");
var tpFcp = new TabPage("FCP");
var tpPisCofins = new TabPage("PIS / COFINS / Efetivos");
// Simplificação da inicialização de coleção aceita pelo compilador moderno
tabItens.TabPages.AddRange([tpGeral, tpComercial, tpIcms, tpFcp, tpPisCofins]);
content.Controls.Add(tabItens);
ConfigurarAbaGeral(tpGeral);
ConfigurarAbaComercial(tpComercial);
ConfigurarAbaIcms(tpIcms);
ConfigurarAbaFcp(tpFcp);
ConfigurarAbaPisCofins(tpPisCofins);
}
private void ConfigurarAbaGeral(TabPage tp)
{
tp.Controls.Add(CreateSectionHeader("Identificação e Chaves do Item", 15));
txtIdSatFiscalConsItens = AddInput(tp, "ID ITEM REG.", 20, 50, 100, 28, true);
txtCodigo = AddInput(tp, "CÓDIGO INT.", 135, 50, 110, 28);
txtCodNfce = AddInput(tp, "CÓD. VÍNCULO NFC-E", 260, 50, 150, 28);
txtItemTipo = AddInput(tp, "TIPO ITEM", 425, 50, 120, 28);
txtDataCadastro = AddInput(tp, "DATA CADASTRO", 560, 50, 180, 28, true);
tp.Controls.Add(CreateSectionHeader("Especificações do Produto", 120));
txtItemCprod = AddInput(tp, "CÓD. COMERCIAL DO PRODUTO", 20, 155, 200, 28);
txtItemCean = AddInput(tp, "CÓDIGO EAN (CÓD. BARRAS)", 235, 155, 220, 28);
txtItemXprod = AddInput(tp, "DESCRIÇÃO DO PRODUTO / SERVIÇO", 20, 215, 600, 28);
txtItemInfAdic = AddInput(tp, "INFORMAÇÕES ADICIONAIS DO ITEM", 20, 275, 600, 28);
}
private void ConfigurarAbaComercial(TabPage tp)
{
tp.Controls.Add(CreateSectionHeader("Classificações Fiscais Obrigatórias", 15));
txtItemCfop = AddInput(tp, "CFOP", 20, 50, 90, 28);
txtItemNcm = AddInput(tp, "NCM", 125, 50, 120, 28);
txtItemCest = AddInput(tp, "CEST", 260, 50, 120, 28);
txtCProdAnp = AddInput(tp, "CÓD. ANP (COMBUSTÍVEIS)", 395, 50, 180, 28);
txtCBenef = AddInput(tp, "BENEFÍCIO FISCAL (CBENEF)", 590, 50, 180, 28);
tp.Controls.Add(CreateSectionHeader("Valores Comerciais, Quantidades e Rateios", 120));
txtItemUncom = AddInput(tp, "UNIDADE MEDIDA", 20, 155, 100, 28);
txtItemQcom = AddInput(tp, "QUANTIDADE COMERCIAL", 135, 155, 140, 28);
txtItemVprod = AddInput(tp, "VALOR BRUTO PROD. (R$)", 290, 155, 150, 28);
txtItemVdesc = AddInput(tp, "VALOR DESCONTO (R$)", 455, 155, 140, 28);
txtItemVfrete = AddInput(tp, "RATEIO FRETE (R$)", 20, 215, 140, 28);
txtItemVseg = AddInput(tp, "RATEIO SEGURO (R$)", 175, 215, 140, 28);
txtItemVoutro = AddInput(tp, "OUTRAS DESPESAS (R$)", 330, 215, 150, 28);
txtItemVTotTrib = AddInput(tp, "VALOR APROX. TRIBUTOS", 495, 215, 160, 28);
}
private void ConfigurarAbaIcms(TabPage tp)
{
tp.Controls.Add(CreateSectionHeader("ICMS Regra Geral e Base de Cálculo", 15));
txtItemOrigem = AddInput(tp, "ORIGEM PROD.", 20, 50, 100, 28);
txtItemCst = AddInput(tp, "CST / CSOSN", 135, 50, 100, 28);
txtItemIcmsModBc = AddInput(tp, "MODALIDADE BC ICMS", 250, 50, 150, 28);
txtItemIcmsPRedBc = AddInput(tp, "% REDUÇÃO BC", 415, 50, 120, 28);
txtItemIcmsVBc = AddInput(tp, "VALOR BC ICMS", 550, 50, 130, 28);
txtItemIcmsPIcms = AddInput(tp, "ALÍQUOTA ICMS", 695, 50, 120, 28);
txtItemIcmsVIcms = AddInput(tp, "VALOR ICMS", 830, 50, 130, 28);
tp.Controls.Add(CreateSectionHeader("ICMS Desonerado e Regras de Substituição Tributária (ST)", 120));
txtItemIcmsVIcmsDeson = AddInput(tp, "VALOR ICMS DESON.", 20, 155, 150, 28);
txtItemIcmsMotDesIcms = AddInput(tp, "MOTIVO DESON.", 185, 155, 140, 28); // Corrigido a inconsistência de caixa alta/baixa
txtItemIcmsModBcSt = AddInput(tp, "MODALIDADE BC ST", 340, 155, 140, 28);
txtItemIcmsPMvast = AddInput(tp, "% MVA ST", 495, 155, 110, 28);
txtItemIcmsPRedBcSt = AddInput(tp, "% REDUÇÃO BC ST", 620, 155, 130, 28);
txtItemIcmsVBcSt = AddInput(tp, "VALOR BASE CÁLCULO ST", 20, 215, 170, 28);
txtItemIcmsPIcmsSt = AddInput(tp, "ALÍQUOTA ICMS ST", 205, 215, 140, 28);
txtItemIcmsVIcmsSt = AddInput(tp, "VALOR DO ICMS ST", 360, 215, 150, 28);
}
private void ConfigurarAbaFcp(TabPage tp)
{
tp.Controls.Add(CreateSectionHeader("Fundo de Combate à Pobreza - ICMS Normal e ST", 15));
txtItemVBcFcp = AddInput(tp, "VALOR BC FCP", 20, 50, 130, 28);
txtItemPFcp = AddInput(tp, "% ALÍQUOTA FCP", 165, 50, 130, 28);
txtItemVFcp = AddInput(tp, "VALOR DO FCP", 310, 50, 130, 28);
txtItemVBcFcpSt = AddInput(tp, "VALOR BC FCP ST", 455, 50, 140, 28);
txtItemPFcpSt = AddInput(tp, "% ALÍQUOTA FCP ST", 610, 50, 140, 28);
txtItemVFcpSt = AddInput(tp, "VALOR DO FCP ST", 765, 50, 140, 28);
tp.Controls.Add(CreateSectionHeader("Fundo de Combate à Pobreza Retido Anteriormente", 120));
txtItemPSt = AddInput(tp, "% ALÍQUOTA ICMS ST RET.", 20, 155, 180, 28);
txtItemVBcFcpStRet = AddInput(tp, "VALOR BC FCP ST RET.", 215, 155, 160, 28);
txtItemPFcpStRet = AddInput(tp, "% ALÍQUOTA FCP ST RET.", 390, 155, 170, 28);
txtItemVFcpStRet = AddInput(tp, "VALOR DO FCP ST RET.", 575, 155, 160, 28); // Corrigido nomenclatura para bater com a propriedade da classe
}
private void ConfigurarAbaPisCofins(TabPage tp)
{
tp.Controls.Add(CreateSectionHeader("Contribuições para o PIS", 15));
txtItemPisCst = AddInput(tp, "CST PIS", 20, 50, 100, 28);
txtItemPisVBc = AddInput(tp, "VALOR BC PIS", 135, 50, 130, 28);
txtItemPisPPis = AddInput(tp, "% ALÍQUOTA PIS", 280, 50, 120, 28);
txtItemPisVPis = AddInput(tp, "VALOR DO PIS", 415, 50, 130, 28);
tp.Controls.Add(CreateSectionHeader("Contribuições para a COFINS", 120));
txtItemCofinsCst = AddInput(tp, "CST COFINS", 20, 155, 100, 28);
txtItemCofinsVBc = AddInput(tp, "VALOR BC COFINS", 135, 155, 130, 28);
txtItemCofinsPCofins = AddInput(tp, "% ALÍQUOTA COFINS", 280, 155, 140, 28);
txtItemCofinsVCofins = AddInput(tp, "VALOR DO COFINS", 435, 155, 140, 28);
tp.Controls.Add(CreateSectionHeader("Indicadores de Valores Fiscais Efetivos", 225));
txtVIcmsSubstituto = AddInput(tp, "VALOR ICMS SUBST.", 20, 260, 150, 28);
txtPRedBcEfet = AddInput(tp, "% REDUÇÃO BC EFET.", 185, 260, 150, 28);
txtVBcEfet = AddInput(tp, "VALOR BC EFETIVA", 350, 260, 140, 28);
txtPIcmsEfet = AddInput(tp, "% ALÍQUOTA ICMS EFET.", 505, 260, 160, 28);
txtVIcmsEfet = AddInput(tp, "VALOR ICMS EFETIVO", 680, 260, 150, 28);
}
// --- MÉTODOS OBRIGATÓRIOS DO FORMULÁRIO MODELO ---
protected override void OnNovo()
{
// Substituição por função local (atende à sugestão do analisador C# moderno)
void LimparRecursivo(Control.ControlCollection controls)
{
foreach (Control c in controls)
{
if (c is LV_TEXTBOX1 txt && !txt.ReadOnly) txt.Text = string.Empty;
if (c.HasChildren) LimparRecursivo(c.Controls);
}
}
if (tabItens != null)
{
LimparRecursivo(tabItens.Controls);
tabItens.SelectedIndex = 0;
}
if (txtIdSatFiscalConsItens != null) txtIdSatFiscalConsItens.Text = "0";
if (txtDataCadastro != null) txtDataCadastro.Text = DateTime.Now.ToString("g");
txtItemCprod?.Focus();
}
protected override void OnSalvar()
{
// Proteção nula com operador condicional para checagem segura
if (string.IsNullOrWhiteSpace(txtItemCprod?.Text))
{
MessageBox.Show("O código comercial do produto é obrigatório.", "Aviso", MessageBoxButtons.OK, MessageBoxIcon.Warning);
if (tabItens != null) tabItens.SelectedIndex = 0;
txtItemCprod?.Focus();
return;
}
// Mapeamento usando Operador de Coalescência Nula (??) para garantir strings limpas
var item = new ModeloSatFiscalConsumidorItens
{
ID_SAT_FISCAL_CONS_ITENS = string.IsNullOrEmpty(txtIdSatFiscalConsItens?.Text) ? 0 : Convert.ToInt32(txtIdSatFiscalConsItens.Text),
CODIGO = txtCodigo?.Text ?? string.Empty,
COD_NFCE = txtCodNfce?.Text ?? string.Empty,
ITEM_TIPO = txtItemTipo?.Text ?? string.Empty,
ITEM_CEAN = txtItemCean?.Text ?? string.Empty,
ITEM_CPROD = txtItemCprod.Text,
ITEM_XPROD = txtItemXprod?.Text ?? string.Empty,
ITEM_INF_ADIC = txtItemInfAdic?.Text ?? string.Empty,
ITEM_CFOP = txtItemCfop?.Text ?? string.Empty,
ITEM_NCM = txtItemNcm?.Text ?? string.Empty,
ITEM_UNCOM = txtItemUncom?.Text ?? string.Empty,
ITEM_QCOM = txtItemQcom?.Text ?? string.Empty,
ITEM_VPROD = txtItemVprod?.Text ?? string.Empty,
ITEM_VOUTRO = txtItemVoutro?.Text ?? string.Empty,
ITEM_VFRETE = txtItemVfrete?.Text ?? string.Empty,
ITEM_VSEG = txtItemVseg?.Text ?? string.Empty,
ITEM_VDESC = txtItemVdesc?.Text ?? string.Empty,
ITEM_vTotTrib = txtItemVTotTrib?.Text ?? string.Empty,
ITEM_ORIGEM = txtItemOrigem?.Text ?? string.Empty,
ITEM_CST = txtItemCst?.Text ?? string.Empty,
DATA_CADASTRO = txtDataCadastro?.Text ?? string.Empty,
ITEM_ICMS_modBC = txtItemIcmsModBc?.Text ?? string.Empty,
ITEM_ICMS_pRedBC = txtItemIcmsPRedBc?.Text ?? string.Empty,
ITEM_ICMS_vBC = txtItemIcmsVBc?.Text ?? string.Empty,
ITEM_ICMS_pICMS = txtItemIcmsPIcms?.Text ?? string.Empty,
ITEM_ICMS_vICMS = txtItemIcmsVIcms?.Text ?? string.Empty,
ITEM_ICMS_vICMSDeson = txtItemIcmsVIcmsDeson?.Text ?? string.Empty,
ITEM_ICMS_motDesICMS = txtItemIcmsMotDesIcms?.Text ?? string.Empty,
ITEM_ICMS_modBCST = txtItemIcmsModBcSt?.Text ?? string.Empty,
ITEM_ICMS_pMVAST = txtItemIcmsPMvast?.Text ?? string.Empty,
ITEM_ICMS_pRedBCST = txtItemIcmsPRedBcSt?.Text ?? string.Empty,
ITEM_ICMS_vBCST = txtItemIcmsVBcSt?.Text ?? string.Empty,
ITEM_ICMS_pICMSST = txtItemIcmsPIcmsSt?.Text ?? string.Empty,
ITEM_ICMS_vICMSST = txtItemIcmsVIcmsSt?.Text ?? string.Empty,
ITEM_cProdANP = txtCProdAnp?.Text ?? string.Empty,
ITEM_CEST = txtItemCest?.Text ?? string.Empty,
CBenef = txtCBenef?.Text ?? string.Empty,
ITEM_pFCP = txtItemPFcp?.Text ?? string.Empty,
ITEM_vFCP = txtItemVFcp?.Text ?? string.Empty,
ITEM_vBCFCP = txtItemVBcFcp?.Text ?? string.Empty,
ITEM_vBCFCPST = txtItemVBcFcpSt?.Text ?? string.Empty,
ITEM_pFCPST = txtItemPFcpSt?.Text ?? string.Empty,
ITEM_vFCPST = txtItemVFcpSt?.Text ?? string.Empty,
ITEM_pST = txtItemPSt?.Text ?? string.Empty,
ITEM_vBCFCPSTRet = txtItemVBcFcpStRet?.Text ?? string.Empty,
ITEM_pFCPSTRet = txtItemPFcpStRet?.Text ?? string.Empty,
ITEM_vFCPSTRet = txtItemVFcpStRet?.Text ?? string.Empty,
ITEM_PIS_CST = txtItemPisCst?.Text ?? string.Empty,
ITEM_PIS_vBC = txtItemPisVBc?.Text ?? string.Empty,
ITEM_PIS_pPIS = txtItemPisPPis?.Text ?? string.Empty,
ITEM_PIS_vPIS = txtItemPisVPis?.Text ?? string.Empty,
ITEM_COFINS_CST = txtItemCofinsCst?.Text ?? string.Empty,
ITEM_COFINS_vBC = txtItemCofinsVBc?.Text ?? string.Empty,
ITEM_COFINS_pCOFINS = txtItemCofinsPCofins?.Text ?? string.Empty,
ITEM_COFINS_vCOFINS = txtItemCofinsVCofins?.Text ?? string.Empty,
VICMSSubstituto = txtVIcmsSubstituto?.Text ?? string.Empty,
PRedBCEfet = txtPRedBcEfet?.Text ?? string.Empty,
VBCEfet = txtVBcEfet?.Text ?? string.Empty,
PICMSEfet = txtPIcmsEfet?.Text ?? string.Empty,
VICMSEfet = txtVIcmsEfet?.Text ?? string.Empty
};
// Processa o objeto preenchido nas camadas inferiores
MessageBox.Show($"Item {item.ITEM_CPROD} gravado com sucesso!", "LevelOS", MessageBoxButtons.OK, MessageBoxIcon.Information);
}
protected override void OnAlterar()
{
txtItemXprod?.Focus();
}
protected override void OnExcluir()
{
if (MessageBox.Show("Confirma a exclusão deste item?", "LevelOS", MessageBoxButtons.YesNo, MessageBoxIcon.Warning) == DialogResult.Yes)
{
OnNovo();
}
}
protected override void OnLocalizar()
{
// Vinculado à Grid de busca global
}
protected override void OnCancelar()
{
OnNovo();
}
}
}

View File

@ -0,0 +1,242 @@
using MLL;
using System;
using System.Drawing;
using System.Windows.Forms;
using CPM;
namespace UI
{
public class SatFiscalConsumidorPanel : FormularioModelo
{
private TabControl tabFiscal;
// --- CAMPOS DA ABA 1: DADOS DA EMISSÃO ---
private LV_TEXTBOX1 txtIdSatFiscalConsu, txtCodigo, txtProducao, txtSerie, txtNatureza, txtEmissao, txtTerminal, txtSituacao, txtDataCadastro;
// --- CAMPOS DA ABA 2: DESTINATÁRIO / CLIENTE ---
private LV_TEXTBOX1 txtDestNome, txtDestEmail, txtDestCpfCnpj, txtDestIdEstrangeiro, txtDestLgr, txtDestCpl, txtDestNro, txtDestBairro, txtDestCMun, txtDestXMun, txtDestUf, txtDestCep, txtDestCPais, txtDestXPais, txtDestFone;
// --- CAMPOS DA ABA 3: TOTAIS E IMPOSTOS (SEFAZ) ---
private LV_TEXTBOX1 txtTotalVBc, txtTotalVIcms, txtTotalVBcSt, txtTotalVSt, txtTotalVProd, txtTotalVFrete, txtTotalVSeg, txtTotalVDesc, txtTotalVIi, txtTotalVIpi, txtTotalVPis, txtTotalVCofins, txtTotalVOutro, txtTotalVNf;
// --- CAMPOS DA ABA 4: LOGÍSTICA / PROTOCOLOS ---
private LV_TEXTBOX1 txtFreteModalidade, txtFreteXCnpjCpf, txtFreteXNome, txtNfcPronta, txtNfcInfCpl, txtChaveNfc, txtProtocolo, txtProtocoloCancela;
public SatFiscalConsumidorPanel()
{
this.Titulo = "GERENCIAMENTO DE EMISSÃO FISCAL (NFC-E / SAT)";
MontarInterfaceCompleta();
}
private void MontarInterfaceCompleta()
{
// Inicialização do TabControl adaptado ao content (1100px)
tabFiscal = new TabControl
{
Location = new Point(10, 10),
Size = new Size(1060, 520),
Font = new Font("Segoe UI", 9.5f)
};
var tpEmissao = new TabPage("Dados da Emissão");
var tpDestinatario = new TabPage("Destinatário / Cliente");
var tpTotais = new TabPage("Totais e Impostos");
var tpProtocolos = new TabPage("Logística e Protocolos");
tabFiscal.TabPages.AddRange(new[] { tpEmissao, tpDestinatario, tpTotais, tpProtocolos });
content.Controls.Add(tabFiscal);
ConfigurarAbaEmissao(tpEmissao);
ConfigurarAbaDestinatario(tpDestinatario);
ConfigurarAbaTotais(tpTotais);
ConfigurarAbaProtocolos(tpProtocolos);
}
private void ConfigurarAbaEmissao(TabPage tp)
{
tp.Controls.Add(CreateSectionHeader("Identificação e Status do Cupom Fiscal", 15));
txtIdSatFiscalConsu = AddInput(tp, "ID FISCAL", 20, 50, 100, 28, true);
txtCodigo = AddInput(tp, "CÓDIGO INT.", 135, 50, 110, 28);
txtTerminal = AddInput(tp, "Nº TERMINAL", 260, 50, 110, 28);
txtSerie = AddInput(tp, "SÉRIE", 385, 50, 90, 28);
txtProducao = AddInput(tp, "AMBIENTE (1=PROD / 2=HOMOL)", 490, 50, 210, 28);
txtSituacao = AddInput(tp, "SITUAÇÃO XML", 715, 50, 150, 28);
tp.Controls.Add(CreateSectionHeader("Datas e Natureza de Operação", 120));
txtNatureza = AddInput(tp, "NATUREZA DA OPERAÇÃO", 20, 155, 350, 28);
txtEmissao = AddInput(tp, "DATA/HORA EMISSÃO", 385, 155, 180, 28);
txtDataCadastro = AddInput(tp, "DATA CADASTRO NO SISTEMA", 580, 155, 200, 28, true);
}
private void ConfigurarAbaDestinatario(TabPage tp)
{
tp.Controls.Add(CreateSectionHeader("Identificação do Consumidor", 15));
txtDestNome = AddInput(tp, "RAZÃO SOCIAL / NOME", 20, 50, 400, 28);
txtDestCpfCnpj = AddInput(tp, "CPF / CNPJ", 435, 50, 180, 28);
txtDestEmail = AddInput(tp, "E-MAIL DESTINATÁRIO", 630, 50, 250, 28);
txtDestFone = AddInput(tp, "TELEFONE", 20, 105, 150, 28);
txtDestIdEstrangeiro = AddInput(tp, "DOCUMENTO ESTRANGEIRO (PASSAPORTE)", 185, 105, 250, 28);
tp.Controls.Add(CreateSectionHeader("Endereço do Destinatário", 165));
txtDestLgr = AddInput(tp, "LOGRADOURO (RUA, AV)", 20, 200, 350, 28);
txtDestNro = AddInput(tp, "NÚMERO", 385, 200, 80, 28);
txtDestCpl = AddInput(tp, "COMPLEMENTO", 480, 200, 200, 28);
txtDestBairro = AddInput(tp, "BAIRRO", 695, 200, 185, 28);
txtDestCep = AddInput(tp, "CEP", 20, 255, 110, 28);
txtDestCMun = AddInput(tp, "CÓD. MUNICÍPIO (IBGE)", 145, 255, 150, 28);
txtDestXMun = AddInput(tp, "MUNICÍPIO", 310, 255, 220, 28);
txtDestUf = AddInput(tp, "UF", 545, 255, 50, 28);
txtDestCPais = AddInput(tp, "CÓD. PAÍS", 610, 255, 80, 28);
txtDestXPais = AddInput(tp, "PAÍS", 700, 255, 180, 28);
}
private void ConfigurarAbaTotais(TabPage tp)
{
tp.Controls.Add(CreateSectionHeader("Composição de Valores de Produtos e Frete", 15));
txtTotalVProd = AddInput(tp, "TOTAL PRODUTOS (R$)", 20, 50, 160, 28);
txtTotalVDesc = AddInput(tp, "TOTAL DESCONTO (R$)", 195, 50, 150, 28);
txtTotalVFrete = AddInput(tp, "VALOR FRETE (R$)", 360, 50, 140, 28);
txtTotalVSeg = AddInput(tp, "VALOR SEGURO (R$)", 515, 50, 140, 28);
txtTotalVOutro = AddInput(tp, "OUTRAS DESPESAS (R$)", 670, 50, 150, 28);
txtTotalVNf = AddInput(tp, "VALOR TOTAL DA NOTA (R$)", 835, 50, 190, 28, true);
tp.Controls.Add(CreateSectionHeader("Impostos e Retenções Fiscais", 115));
txtTotalVBc = AddInput(tp, "BASE CÁLCULO ICMS", 20, 150, 150, 28);
txtTotalVIcms = AddInput(tp, "VALOR DO ICMS", 185, 150, 140, 28);
txtTotalVBcSt = AddInput(tp, "BASE CÁLCULO ICMS ST", 340, 150, 160, 28);
txtTotalVSt = AddInput(tp, "VALOR ICMS ST", 515, 150, 140, 28);
txtTotalVIi = AddInput(tp, "VALOR IMP. IMPORTAÇÃO", 670, 150, 160, 28);
txtTotalVIpi = AddInput(tp, "VALOR TOTAL IPI", 20, 205, 150, 28);
txtTotalVPis = AddInput(tp, "VALOR TOTAL PIS", 185, 205, 140, 28);
txtTotalVCofins = AddInput(tp, "VALOR TOTAL COFINS", 340, 205, 160, 28);
}
private void ConfigurarAbaProtocolos(TabPage tp)
{
tp.Controls.Add(CreateSectionHeader("Informações do Transportador e Frete", 15));
txtFreteModalidade = AddInput(tp, "MODALIDADE FRETE", 20, 50, 160, 28);
txtFreteXCnpjCpf = AddInput(tp, "CNPJ / CPF TRANSP.", 195, 50, 180, 28);
txtFreteXNome = AddInput(tp, "RAZÃO SOCIAL TRANSPORTADORA", 390, 50, 420, 28);
tp.Controls.Add(CreateSectionHeader("Protocolos de Validação SEFAZ", 115));
txtChaveNfc = AddInput(tp, "CHAVE DE ACESSO NFC-E / SAT (44 DÍGITOS)", 20, 150, 450, 28);
txtProtocolo = AddInput(tp, "Nº PROTOCOLO AUTORIZAÇÃO", 480, 150, 230, 28);
txtProtocoloCancela = AddInput(tp, "Nº PROTOCOLO CANCELAMENTO", 720, 150, 230, 28);
tp.Controls.Add(CreateSectionHeader("Parâmetros do Arquivo Fiscal XML", 215));
txtNfcPronta = AddInput(tp, "NFC PRONTA (S/N)", 20, 250, 140, 28);
txtNfcInfCpl = AddInput(tp, "INFORMAÇÕES COMPLEMENTARES AO CONTRIBUINTE", 175, 250, 635, 28);
}
// --- MÉTODOS OBRIGATÓRIOS DO FORMULÁRIO MODELO ---
protected override void OnNovo()
{
Action<Control.ControlCollection> limparCampos = null;
limparCampos = (controls) =>
{
foreach (Control c in controls)
{
if (c is LV_TEXTBOX1 txt && !txt.ReadOnly) txt.Text = string.Empty;
if (c.HasChildren) limparCampos(c.Controls);
}
};
limparCampos(tabFiscal.Controls);
txtIdSatFiscalConsu.Text = "0";
txtDataCadastro.Text = DateTime.Now.ToString("g");
tabFiscal.SelectedIndex = 0;
txtCodigo.Focus();
}
protected override void OnSalvar()
{
if (string.IsNullOrWhiteSpace(txtCodigo.Text))
{
MessageBox.Show("O código interno da transação é obrigatório.", "Aviso", MessageBoxButtons.OK, MessageBoxIcon.Warning);
tabFiscal.SelectedIndex = 0;
txtCodigo.Focus();
return;
}
// Mapeamento absoluto, cirúrgico e fiel de todas as 46 propriedades
var fiscal = new ModeloSatFiscalConsumidor
{
ID_SAT_FISCAL_CONSU = string.IsNullOrEmpty(txtIdSatFiscalConsu.Text) ? 0 : Convert.ToInt32(txtIdSatFiscalConsu.Text),
CODIGO = txtCodigo.Text,
PRODUCAO = txtProducao.Text,
SERIE = txtSerie.Text,
NATUREZA = txtNatureza.Text,
EMISSAO = txtEmissao.Text,
DEST_NOME = txtDestNome.Text,
DEST_EMAIL = txtDestEmail.Text,
DEST_CPF_CNPJ = txtDestCpfCnpj.Text,
DEST_IDESTRANGEIRO = txtDestIdEstrangeiro.Text,
DEST_xLgr = txtDestLgr.Text,
DEST_CPL = txtDestCpl.Text,
DEST_nro = txtDestNro.Text,
DEST_xBairro = txtDestBairro.Text,
DEST_cMun = txtDestCMun.Text,
DEST_xMun = txtDestXMun.Text,
DEST_UF = txtDestUf.Text,
DEST_CEP = txtDestCep.Text,
DEST_cPais = txtDestCPais.Text,
DEST_xPais = txtDestXPais.Text,
DEST_fone = txtDestFone.Text,
FRETE_MODALIDADE = txtFreteModalidade.Text,
FRETE_xCNPJ_CPF = txtFreteXCnpjCpf.Text,
FRETE_xNome = txtFreteXNome.Text,
NFC_PRONTA = txtNfcPronta.Text,
NFC_infCpl = txtNfcInfCpl.Text,
TOTAL_vBC = txtTotalVBc.Text,
TOTAL_vICMS = txtTotalVIcms.Text,
TOTAL_vBCST = txtTotalVBcSt.Text,
TOTAL_vST = txtTotalVSt.Text,
TOTAL_vProd = txtTotalVProd.Text,
TOTAL_vFrete = txtTotalVFrete.Text,
TOTAL_vSeg = txtTotalVSeg.Text,
TOTAL_vDesc = txtTotalVDesc.Text,
TOTAL_vII = txtTotalVIi.Text,
TOTAL_vIPI = txtTotalVIpi.Text,
TOTAL_vPIS = txtTotalVPis.Text,
TOTAL_vCOFINS = txtTotalVCofins.Text,
TOTAL_vOutro = txtTotalVOutro.Text,
TOTAL_vNF = txtTotalVNf.Text,
TERMINAL = txtTerminal.Text,
CHAVE_NFC = txtChaveNfc.Text,
PROTOCOLO = txtProtocolo.Text,
PROTOCOLO_CANCELA = txtProtocoloCancela.Text,
SITUACAO = txtSituacao.Text,
DATA_CADASTRO = txtDataCadastro.Text
};
// Envio para repositórios DAL / BLL (LevelCode)
MessageBox.Show("Movimentação fiscal salva e estruturada para transmissão!", "LevelOS", MessageBoxButtons.OK, MessageBoxIcon.Information);
}
protected override void OnAlterar()
{
txtSituacao.Focus();
}
protected override void OnExcluir()
{
if (MessageBox.Show("Atenção! A exclusão direta de um cupom fiscal no banco pode gerar quebras de sequência numérica na SEFAZ. Deseja prosseguir?", "LevelOS", MessageBoxButtons.YesNo, MessageBoxIcon.Stop) == DialogResult.Yes)
{
OnNovo();
}
}
protected override void OnLocalizar()
{
// Abre o Grid de cupons emitidos/pendentes
}
protected override void OnCancelar()
{
OnNovo();
}
}
}