531 lines
22 KiB
C#
531 lines
22 KiB
C#
using BLL;
|
|
using CustomMessageBox;
|
|
using DAL;
|
|
using System.Drawing;
|
|
using System.Windows.Forms;
|
|
using MLL;
|
|
|
|
namespace UI
|
|
{
|
|
public class ClienteCadastroPanel : UserControl
|
|
{
|
|
private string _connectionString = DadosDaConexao.ObterConexao();
|
|
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 Panel pnlToolbar = null!;
|
|
private Panel mainScroll = null!;
|
|
private Panel content = null!;
|
|
|
|
// Identificação
|
|
private RoundTextBox txtId = null!, txtEmpresaId = null!, txtNome = null!, txtNomeFantasia = null!;
|
|
private RoundTextBox txtTipoPessoa = null!, txtDocumento = null!, txtRG = null!;
|
|
private RoundTextBox txtInscricaoMunicipal = null!, txtDataNascimento = null!;
|
|
private RoundTextBox txtGrupo = null!, txtTipoConsumidor = null!;
|
|
|
|
// Contatos
|
|
private RoundTextBox txtContato = null!, txtTelefone1 = null!, txtTelefone2 = null!;
|
|
private RoundTextBox txtCelular = null!, txtWhatsapp = null!, txtEmail = null!, txtEmailNFe = null!, txtSite = null!;
|
|
|
|
// Endereço
|
|
private RoundTextBox txtCep = null!, txtEndereco = null!, txtNumero = null!, txtComplemento = null!;
|
|
private RoundTextBox txtBairro = null!, txtCidade = null!, txtUF = null!, txtPais = null!;
|
|
|
|
// Financeiro
|
|
private RoundTextBox txtLimiteCredito = null!, txtVendedorPadraoId = null!, txtObservacoesCobranca = null!;
|
|
private CheckBox chkBloqueado = null!, chkAtivo = null!;
|
|
|
|
// Carteiras
|
|
private RoundTextBox txtBitcoin = null!, txtEthereum = null!, txtLitecoin = null!;
|
|
|
|
// Extras
|
|
private RoundTextBox txtObservacoes = null!;
|
|
private RoundTextBox txtCampoExtra1 = null!, txtCampoExtra2 = null!, txtCampoExtra3 = null!;
|
|
|
|
// Info (readonly)
|
|
private RoundTextBox txtUltimaCompra = null!, txtCriadoEm = null!, txtAtualizadoEm = null!;
|
|
|
|
//Funções Auxiliares
|
|
private void CarregarConfiguracoesSistema()
|
|
{
|
|
BLLEmpresaConfig empresaConfig = new BLLEmpresaConfig(_connectionString);
|
|
int codEmpresa = empresaConfig.ObterEmpresaAtivaId();
|
|
|
|
this.txtEmpresaId.Text = codEmpresa.ToString();
|
|
}
|
|
private DateTime? ConverterData(string texto)
|
|
{
|
|
if (string.IsNullOrWhiteSpace(texto))
|
|
return null;
|
|
|
|
if (DateTime.TryParse(texto, out DateTime data))
|
|
return data;
|
|
|
|
return null;
|
|
}
|
|
private RoundTextBox[] TodosOsCampos() => new[]
|
|
{
|
|
txtId, txtEmpresaId, txtNome, txtNomeFantasia,
|
|
txtTipoPessoa, txtDocumento, txtRG,
|
|
txtInscricaoMunicipal, txtDataNascimento,
|
|
txtGrupo, txtTipoConsumidor,
|
|
txtContato, txtTelefone1, txtTelefone2,
|
|
txtCelular, txtWhatsapp, txtEmail, txtEmailNFe, txtSite,
|
|
txtCep, txtEndereco, txtNumero, txtComplemento,
|
|
txtBairro, txtCidade, txtUF, txtPais,
|
|
txtLimiteCredito, txtVendedorPadraoId, txtObservacoesCobranca,
|
|
txtBitcoin, txtEthereum, txtLitecoin,
|
|
txtObservacoes, txtCampoExtra1, txtCampoExtra2, txtCampoExtra3
|
|
};
|
|
|
|
private void SetCampos(bool enabled)
|
|
{
|
|
foreach (var campo in TodosOsCampos())
|
|
{
|
|
campo.Enabled = enabled;
|
|
campo.BackColor = enabled ? Color.White : Color.FromArgb(241, 245, 249);
|
|
}
|
|
chkBloqueado.Enabled = enabled;
|
|
chkAtivo.Enabled = enabled;
|
|
}
|
|
|
|
public ClienteCadastroPanel()
|
|
{
|
|
Dock = DockStyle.Fill;
|
|
BackColor = Color.White;
|
|
DoubleBuffered = true;
|
|
InitializeLayout();
|
|
SetCampos(false);
|
|
}
|
|
|
|
private void InitializeLayout()
|
|
{
|
|
this.Controls.Clear();
|
|
|
|
// ── TOOLBAR ───────────────────────────────────────────────────────
|
|
pnlToolbar = new Panel
|
|
{
|
|
Dock = DockStyle.Top,
|
|
Height = 55,
|
|
BackColor = Color.FromArgb(248, 250, 252),
|
|
BorderStyle = BorderStyle.None
|
|
};
|
|
|
|
var flowButtons = new FlowLayoutPanel
|
|
{
|
|
Dock = DockStyle.Fill,
|
|
Padding = new Padding(12, 10, 0, 0),
|
|
BackColor = Color.Transparent
|
|
};
|
|
|
|
var btnNovo = CreateToolbarButton("Novo", Color.FromArgb(34, 197, 94));
|
|
var btnAlterar = CreateToolbarButton("Alterar", Color.FromArgb(245, 158, 11));
|
|
var btnExcluir = CreateToolbarButton("Excluir", Color.FromArgb(239, 68, 68));
|
|
var btnLocalizar = CreateToolbarButton("Localizar", AccentBlue);
|
|
var btnSalvar = CreateToolbarButton("Salvar", AccentBlue);
|
|
var btnCancelar = CreateToolbarButton("Cancelar", Color.FromArgb(148, 163, 184));
|
|
|
|
btnNovo.Click += (s, e) => BtnNovo_Click();
|
|
btnAlterar.Click += (s, e) => BtnAlterar_Click();
|
|
btnExcluir.Click += (s, e) => BtnExcluir_Click();
|
|
btnLocalizar.Click += (s, e) => BtnLocalizar_Click();
|
|
btnSalvar.Click += (s, e) => BtnSalvar_Click();
|
|
btnCancelar.Click += (s, e) => BtnCancelar_Click();
|
|
|
|
flowButtons.Controls.AddRange(new Control[]
|
|
{ btnNovo, btnAlterar, btnExcluir, btnLocalizar, btnSalvar, btnCancelar });
|
|
pnlToolbar.Controls.Add(flowButtons);
|
|
this.Controls.Add(pnlToolbar);
|
|
|
|
// ── SCROLL + CONTENT ──────────────────────────────────────────────
|
|
mainScroll = new Panel
|
|
{
|
|
Dock = DockStyle.Fill,
|
|
AutoScroll = true,
|
|
BackColor = Color.White
|
|
};
|
|
this.Controls.Add(mainScroll);
|
|
mainScroll.BringToFront();
|
|
|
|
content = new Panel
|
|
{
|
|
Width = 1100,
|
|
Height = 900,
|
|
Location = new Point(0, 0),
|
|
BackColor = Color.White
|
|
};
|
|
mainScroll.Controls.Add(content);
|
|
|
|
const int rowH = 52;
|
|
const int secGap = 10;
|
|
const int secH = 28;
|
|
const int inputH = 28;
|
|
|
|
int y = 10;
|
|
|
|
// ── 1. IDENTIFICAÇÃO DO CLIENTE ───────────────────────────────────
|
|
content.Controls.Add(CreateSectionHeader("IDENTIFICAÇÃO DO CLIENTE", y));
|
|
y += secH + 4;
|
|
|
|
txtId = AddInput(content, "ID", 20, y, 60, inputH);
|
|
txtEmpresaId = AddInput(content, "Empresa ID", 90, y, 80, inputH);
|
|
txtNome = AddInput(content, "Nome / Razão Social", 180, y, 390, inputH);
|
|
txtNomeFantasia = AddInput(content, "Nome Fantasia", 580, y, 360, inputH);
|
|
y += rowH;
|
|
|
|
txtDocumento = AddInput(content, "CPF/CNPJ", 20, y, 170, inputH);
|
|
DocumentoHelper.Registrar(txtDocumento);
|
|
txtRG = AddInput(content, "RG / Insc. Estadual", 200, y, 170, inputH);
|
|
txtInscricaoMunicipal = AddInput(content, "Insc. Municipal", 380, y, 130, inputH);
|
|
txtDataNascimento = AddInput(content, "Dt. Nascimento", 520, y, 130, inputH);
|
|
txtTipoPessoa = AddInput(content, "Tipo Pessoa", 660, y, 110, inputH);
|
|
txtGrupo = AddInput(content, "Grupo", 780, y, 110, inputH);
|
|
txtTipoConsumidor = AddInput(content, "Tipo Consumidor", 900, y, 140, inputH);
|
|
y += rowH;
|
|
|
|
// ── 2. CONTATOS E COMUNICAÇÃO ─────────────────────────────────────
|
|
y += secGap;
|
|
content.Controls.Add(CreateSectionHeader("CONTATOS E COMUNICAÇÃO", y));
|
|
y += secH + 4;
|
|
|
|
txtContato = AddInput(content, "Contato", 20, y, 180, inputH);
|
|
txtEmail = AddInput(content, "E-mail", 210, y, 230, inputH);
|
|
txtEmailNFe = AddInput(content, "E-mail XML/NFe", 450, y, 230, inputH);
|
|
txtSite = AddInput(content, "Site", 690, y, 250, inputH);
|
|
y += rowH;
|
|
|
|
txtTelefone1 = AddInput(content, "Telefone 1", 20, y, 155, inputH);
|
|
txtTelefone2 = AddInput(content, "Telefone 2", 185, y, 155, inputH);
|
|
txtCelular = AddInput(content, "Celular", 350, y, 155, inputH);
|
|
txtWhatsapp = AddInput(content, "WhatsApp", 515, y, 155, inputH);
|
|
y += rowH;
|
|
|
|
// ── 3. ENDEREÇO COMPLETO ──────────────────────────────────────────
|
|
y += secGap;
|
|
content.Controls.Add(CreateSectionHeader("ENDEREÇO COMPLETO", y));
|
|
y += secH + 4;
|
|
|
|
txtCep = AddInput(content, "CEP", 20, y, 95, inputH);
|
|
txtCep.Leave += (s, e) =>
|
|
{
|
|
string cep = txtCep.Text.Trim().Replace("-", "");
|
|
|
|
if (cep.Length != 8) return;
|
|
|
|
if (TLL.VerifyCep.verificaCEP(cep))
|
|
{
|
|
txtEndereco.Text = TLL.VerifyCep.endereco;
|
|
txtBairro.Text = TLL.VerifyCep.bairro;
|
|
txtCidade.Text = TLL.VerifyCep.cidade;
|
|
txtUF.Text = TLL.VerifyCep.estado;
|
|
|
|
// Formata o CEP com hífen
|
|
txtCep.Text = $"{cep[..5]}-{cep[5..]}";
|
|
}
|
|
else
|
|
{
|
|
NT_MessageBox.Show("CEP não encontrado.", "CEP",
|
|
MessageBoxButtons.OK, MessageBoxIcon.Warning);
|
|
}
|
|
};//cep
|
|
txtEndereco = AddInput(content, "Logradouro", 125, y, 370, inputH);
|
|
txtNumero = AddInput(content, "Nº", 505, y, 60, inputH);
|
|
txtComplemento = AddInput(content, "Complemento", 575, y, 175, inputH);
|
|
txtBairro = AddInput(content, "Bairro", 760, y, 180, inputH);
|
|
y += rowH;
|
|
|
|
txtCidade = AddInput(content, "Cidade", 20, y, 280, inputH);
|
|
txtUF = AddInput(content, "UF", 310, y, 55, inputH);
|
|
txtPais = AddInput(content, "País", 375, y, 150, inputH);
|
|
y += rowH;
|
|
|
|
// ── 4. FINANCEIRO ─────────────────────────────────────────────────
|
|
y += secGap;
|
|
content.Controls.Add(CreateSectionHeader("FINANCEIRO", y));
|
|
y += secH + 4;
|
|
|
|
txtLimiteCredito = AddInput(content, "Limite de Crédito", 20, y, 150, inputH);
|
|
txtVendedorPadraoId = AddInput(content, "Vendedor Padrão ID", 180, y, 120, inputH);
|
|
txtObservacoesCobranca = AddInput(content, "Obs. de Cobrança", 310, y, 380, inputH);
|
|
|
|
chkBloqueado = CreateCheckBox("Bloqueado", 705, y + 18);
|
|
chkAtivo = CreateCheckBox("Ativo", 805, y + 18);
|
|
content.Controls.Add(chkBloqueado);
|
|
content.Controls.Add(chkAtivo);
|
|
y += rowH;
|
|
|
|
// ── 5. CARTEIRAS DIGITAIS ─────────────────────────────────────────
|
|
y += secGap;
|
|
content.Controls.Add(CreateSectionHeader("CARTEIRAS DIGITAIS", y));
|
|
y += secH + 4;
|
|
|
|
txtBitcoin = AddInput(content, "Bitcoin (BTC)", 20, y, 290, inputH);
|
|
txtEthereum = AddInput(content, "Ethereum (ETH)", 320, y, 290, inputH);
|
|
txtLitecoin = AddInput(content, "Litecoin (LTC)", 620, y, 290, inputH);
|
|
y += rowH;
|
|
|
|
// ── 6. CAMPOS EXTRAS ──────────────────────────────────────────────
|
|
y += secGap;
|
|
content.Controls.Add(CreateSectionHeader("CAMPOS EXTRAS", y));
|
|
y += secH + 4;
|
|
|
|
txtCampoExtra1 = AddInput(content, "Campo Extra 1", 20, y, 290, inputH);
|
|
txtCampoExtra2 = AddInput(content, "Campo Extra 2", 320, y, 290, inputH);
|
|
txtCampoExtra3 = AddInput(content, "Campo Extra 3", 620, y, 290, inputH);
|
|
y += rowH;
|
|
|
|
// ── 7. OBSERVAÇÕES ────────────────────────────────────────────────
|
|
y += secGap;
|
|
content.Controls.Add(CreateSectionHeader("OBSERVAÇÕES", y));
|
|
y += secH + 4;
|
|
|
|
txtObservacoes = AddInput(content, "Observações Internas", 20, y, 920, inputH);
|
|
y += rowH;
|
|
|
|
// ── 8. INFORMAÇÕES DO REGISTRO ────────────────────────────────────
|
|
y += secGap;
|
|
content.Controls.Add(CreateSectionHeader("INFORMAÇÕES DO REGISTRO", y));
|
|
y += secH + 4;
|
|
|
|
txtUltimaCompra = AddInput(content, "Última Compra", 20, y, 175, inputH, readOnly: true);
|
|
txtCriadoEm = AddInput(content, "Criado Em", 205, y, 175, inputH, readOnly: true);
|
|
txtAtualizadoEm = AddInput(content, "Atualizado Em", 390, y, 175, inputH, readOnly: true);
|
|
y += rowH;
|
|
|
|
content.Height = y + 10;
|
|
}
|
|
|
|
// ── EVENTOS ───────────────────────────────────────────────────────────
|
|
|
|
private void BtnNovo_Click()
|
|
{
|
|
foreach (var campo in TodosOsCampos())
|
|
campo.Text = string.Empty;
|
|
|
|
chkBloqueado.Checked = false;
|
|
chkAtivo.Checked = true;
|
|
|
|
SetCampos(true);
|
|
txtId.Enabled = false;
|
|
txtId.BackColor = Color.FromArgb(241, 245, 249);
|
|
this.CarregarConfiguracoesSistema();
|
|
txtEmpresaId.Enabled = false;
|
|
txtEmpresaId.BackColor = Color.FromArgb(241, 245, 249);
|
|
}
|
|
|
|
private void BtnAlterar_Click()
|
|
{
|
|
if (string.IsNullOrWhiteSpace(txtId.Text))
|
|
{
|
|
MessageBox.Show(
|
|
"Nenhum registro selecionado para alterar.",
|
|
"Atenção",
|
|
MessageBoxButtons.OK,
|
|
MessageBoxIcon.Warning);
|
|
return;
|
|
}
|
|
|
|
SetCampos(true);
|
|
txtId.Enabled = false;
|
|
txtId.BackColor = Color.FromArgb(241, 245, 249);
|
|
txtEmpresaId.Enabled = false;
|
|
txtEmpresaId.BackColor = Color.FromArgb(241, 245, 249);
|
|
}
|
|
|
|
private void BtnExcluir_Click()
|
|
{
|
|
// Solicita confirmação e exclui o registro atual
|
|
}
|
|
|
|
private void BtnLocalizar_Click()
|
|
{
|
|
// Abre tela/diálogo de busca e preenche os campos
|
|
}
|
|
|
|
private void BtnSalvar_Click()
|
|
{
|
|
var bll = new BLLClientes(_connectionString);
|
|
|
|
// 🔒 validação básica front
|
|
if (string.IsNullOrWhiteSpace(txtNome.Text) ||
|
|
string.IsNullOrWhiteSpace(txtDocumento.Text))
|
|
{
|
|
NT_MessageBox.Show("Preencha ao menos Nome e Documento.",
|
|
"Atenção", MessageBoxButtons.OK, MessageBoxIcon.Warning);
|
|
return;
|
|
}
|
|
|
|
bool isNew = string.IsNullOrWhiteSpace(txtId.Text);
|
|
|
|
var cliente = new ModeloCliente
|
|
{
|
|
Id = isNew ? 0 : int.Parse(txtId.Text),
|
|
EmpresaId = int.TryParse(txtEmpresaId.Text, out var emp) ? emp : 0,
|
|
|
|
Nome = txtNome.Text,
|
|
NomeFantasia = txtNomeFantasia.Text,
|
|
TipoPessoa = txtTipoPessoa.Text,
|
|
Documento = txtDocumento.Text,
|
|
|
|
RG = txtRG.Text,
|
|
InscricaoMunicipal = txtInscricaoMunicipal.Text,
|
|
DataNascimento = ConverterData(txtDataNascimento.Text),
|
|
|
|
Contato = txtContato.Text,
|
|
Telefone1 = txtTelefone1.Text,
|
|
Telefone2 = txtTelefone2.Text,
|
|
Celular = txtCelular.Text,
|
|
Whatsapp = txtWhatsapp.Text,
|
|
Email = txtEmail.Text,
|
|
EmailNFe = txtEmailNFe.Text,
|
|
Site = txtSite.Text,
|
|
|
|
Grupo = txtGrupo.Text,
|
|
|
|
Cep = txtCep.Text,
|
|
Endereco = txtEndereco.Text,
|
|
Numero = int.TryParse(txtNumero.Text, out var num) ? num : null,
|
|
Complemento = txtComplemento.Text,
|
|
Bairro = txtBairro.Text,
|
|
Cidade = txtCidade.Text,
|
|
UF = txtUF.Text,
|
|
Pais = txtPais.Text,
|
|
|
|
LimiteCredito = decimal.TryParse(txtLimiteCredito.Text, out var lim) ? lim : 0,
|
|
Bloqueado = chkBloqueado.Checked,
|
|
ObservacoesCobranca = txtObservacoesCobranca.Text,
|
|
|
|
VendedorPadraoId = int.TryParse(txtVendedorPadraoId.Text, out var vend) ? vend : null,
|
|
TipoConsumidor = txtTipoConsumidor.Text,
|
|
|
|
Observacoes = txtObservacoes.Text,
|
|
|
|
CampoExtra1 = txtCampoExtra1.Text,
|
|
CampoExtra2 = txtCampoExtra2.Text,
|
|
CampoExtra3 = txtCampoExtra3.Text,
|
|
|
|
Bitcoin = txtBitcoin.Text,
|
|
Ethereum = txtEthereum.Text,
|
|
Litecoin = txtLitecoin.Text,
|
|
|
|
Ativo = chkAtivo.Checked,
|
|
UltimaCompra = ConverterData(txtUltimaCompra.Text),
|
|
|
|
// 🔥 esses o banco já gera, mas mantém compatível
|
|
CriadoEm = DateTime.Now,
|
|
AtualizadoEm = DateTime.Now
|
|
};
|
|
|
|
bool sucesso = false;
|
|
|
|
try
|
|
{
|
|
sucesso = isNew
|
|
? bll.Inserir(cliente)
|
|
: bll.Alterar(cliente);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
NT_MessageBox.Show(ex.Message,
|
|
"Erro", MessageBoxButtons.OK, MessageBoxIcon.Error);
|
|
return;
|
|
}
|
|
|
|
if (!sucesso)
|
|
{
|
|
NT_MessageBox.Show("Erro ao salvar cliente.",
|
|
"Erro", MessageBoxButtons.OK, MessageBoxIcon.Error);
|
|
return;
|
|
}
|
|
|
|
SetCampos(false);
|
|
|
|
NT_MessageBox.Show("Cliente salvo com sucesso!",
|
|
"Sucesso", MessageBoxButtons.OK, MessageBoxIcon.Information);
|
|
}
|
|
|
|
private void BtnCancelar_Click()
|
|
{
|
|
foreach (var campo in TodosOsCampos())
|
|
campo.Text = string.Empty;
|
|
|
|
chkBloqueado.Checked = false;
|
|
chkAtivo.Checked = false;
|
|
|
|
SetCampos(false);
|
|
}
|
|
|
|
// ── HELPERS ───────────────────────────────────────────────────────────
|
|
|
|
private Panel CreateSectionHeader(string title, int y)
|
|
{
|
|
var pnl = new Panel { Location = new Point(20, y), Width = 1000, Height = 26 };
|
|
var lbl = new Label
|
|
{
|
|
Text = title,
|
|
Font = new Font("Segoe UI", 8.5f, FontStyle.Bold),
|
|
ForeColor = AccentBlue,
|
|
AutoSize = true,
|
|
Location = new Point(0, 0)
|
|
};
|
|
var line = new Panel
|
|
{
|
|
BackColor = BorderColor,
|
|
Height = 1,
|
|
Width = 980,
|
|
Location = new Point(0, 20)
|
|
};
|
|
pnl.Controls.Add(lbl);
|
|
pnl.Controls.Add(line);
|
|
return pnl;
|
|
}
|
|
|
|
private RoundTextBox AddInput(Control parent, string label,
|
|
int x, int y, int width, int height,
|
|
bool readOnly = false)
|
|
{
|
|
var lbl = new Label
|
|
{
|
|
Text = label,
|
|
Location = new Point(x, y),
|
|
Font = new Font("Segoe UI", 7.5f, FontStyle.Bold),
|
|
ForeColor = readOnly ? Color.Gray : TextDark,
|
|
AutoSize = true
|
|
};
|
|
var txt = new RoundTextBox
|
|
{
|
|
Location = new Point(x, y + 16),
|
|
Size = new Size(width, height),
|
|
Radius = 4,
|
|
BorderColor = readOnly ? Color.FromArgb(203, 213, 225) : BorderColor,
|
|
FocusColor = AccentBlue,
|
|
ReadOnly = readOnly,
|
|
BackColor = readOnly ? Color.FromArgb(241, 245, 249) : Color.White
|
|
};
|
|
parent.Controls.Add(lbl);
|
|
parent.Controls.Add(txt);
|
|
return txt;
|
|
}
|
|
|
|
private CheckBox CreateCheckBox(string text, int x, int y) => new CheckBox
|
|
{
|
|
Text = text,
|
|
Location = new Point(x, y),
|
|
Font = new Font("Segoe UI", 8.5f, FontStyle.Bold),
|
|
ForeColor = TextDark,
|
|
AutoSize = true
|
|
};
|
|
|
|
private RoundButton CreateToolbarButton(string text, Color color) => new RoundButton
|
|
{
|
|
Text = text,
|
|
Size = new Size(95, 32),
|
|
BackColor = color,
|
|
ForeColor = Color.White,
|
|
Font = new Font("Segoe UI Semibold", 8.5f),
|
|
Margin = new Padding(0, 0, 6, 0),
|
|
Cursor = Cursors.Hand
|
|
};
|
|
}
|
|
} |