resolvendo merge
This commit is contained in:
commit
407b4b4b17
10
.gitignore
vendored
10
.gitignore
vendored
@ -1,4 +1,5 @@
|
|||||||
.vs/
|
.vs/
|
||||||
|
<<<<<<< HEAD
|
||||||
**/.vs/
|
**/.vs/
|
||||||
bin/
|
bin/
|
||||||
obj/
|
obj/
|
||||||
@ -7,4 +8,11 @@ obj/
|
|||||||
*.pdb
|
*.pdb
|
||||||
*.cache
|
*.cache
|
||||||
*.user
|
*.user
|
||||||
*.suo
|
*.suo
|
||||||
|
=======
|
||||||
|
bin/
|
||||||
|
obj/
|
||||||
|
*.user
|
||||||
|
*.suo
|
||||||
|
*.cache
|
||||||
|
>>>>>>> 577e97245b8945b1bfd71ca7bb3971042d27d2a9
|
||||||
|
|||||||
108
ArquivosAuxiliares/DadosAuxiliaresTabelaPermissoes.sql
Normal file
108
ArquivosAuxiliares/DadosAuxiliaresTabelaPermissoes.sql
Normal file
@ -0,0 +1,108 @@
|
|||||||
|
INSERT INTO Permissoes (Nome, Descricao)
|
||||||
|
VALUES
|
||||||
|
|
||||||
|
-- ========================
|
||||||
|
-- EMPRESA
|
||||||
|
-- ========================
|
||||||
|
('EMPRESA_VER', 'Visualizar dados da empresa'),
|
||||||
|
('EMPRESA_EDITAR', 'Editar dados da empresa'),
|
||||||
|
|
||||||
|
-- ========================
|
||||||
|
-- CLIENTES
|
||||||
|
-- ========================
|
||||||
|
('CLIENTE_VER', 'Visualizar clientes'),
|
||||||
|
('CLIENTE_CADASTRAR', 'Cadastrar clientes'),
|
||||||
|
('CLIENTE_EDITAR', 'Editar clientes'),
|
||||||
|
('CLIENTE_EXCLUIR', 'Excluir clientes'),
|
||||||
|
|
||||||
|
-- ========================
|
||||||
|
-- FORNECEDORES
|
||||||
|
-- ========================
|
||||||
|
('FORNECEDOR_VER', 'Visualizar fornecedores'),
|
||||||
|
('FORNECEDOR_CADASTRAR', 'Cadastrar fornecedores'),
|
||||||
|
('FORNECEDOR_EDITAR', 'Editar fornecedores'),
|
||||||
|
('FORNECEDOR_EXCLUIR', 'Excluir fornecedores'),
|
||||||
|
|
||||||
|
-- ========================
|
||||||
|
-- FUNCIONARIOS
|
||||||
|
-- ========================
|
||||||
|
('FUNCIONARIO_VER', 'Visualizar funcionários'),
|
||||||
|
('FUNCIONARIO_CADASTRAR', 'Cadastrar funcionários'),
|
||||||
|
('FUNCIONARIO_EDITAR', 'Editar funcionários'),
|
||||||
|
('FUNCIONARIO_EXCLUIR', 'Excluir funcionários'),
|
||||||
|
|
||||||
|
-- ========================
|
||||||
|
-- USUARIOS / SEGURANÇA
|
||||||
|
-- ========================
|
||||||
|
('USUARIO_VER', 'Visualizar usuários'),
|
||||||
|
('USUARIO_CADASTRAR', 'Cadastrar usuários'),
|
||||||
|
('USUARIO_EDITAR', 'Editar usuários'),
|
||||||
|
('USUARIO_EXCLUIR', 'Excluir usuários'),
|
||||||
|
('PERMISSAO_GERENCIAR', 'Gerenciar permissões'),
|
||||||
|
|
||||||
|
-- ========================
|
||||||
|
-- SERVIÇOS
|
||||||
|
-- ========================
|
||||||
|
('SERVICO_VER', 'Visualizar serviços'),
|
||||||
|
('SERVICO_CADASTRAR', 'Cadastrar serviços'),
|
||||||
|
('SERVICO_EDITAR', 'Editar serviços'),
|
||||||
|
('SERVICO_EXCLUIR', 'Excluir serviços'),
|
||||||
|
|
||||||
|
-- ========================
|
||||||
|
-- CONTRATOS
|
||||||
|
-- ========================
|
||||||
|
('CONTRATO_VER', 'Visualizar contratos'),
|
||||||
|
('CONTRATO_CADASTRAR', 'Cadastrar contratos'),
|
||||||
|
('CONTRATO_EDITAR', 'Editar contratos'),
|
||||||
|
('CONTRATO_EXCLUIR', 'Excluir contratos'),
|
||||||
|
|
||||||
|
-- ========================
|
||||||
|
-- FINANCEIRO - RECEBER
|
||||||
|
-- ========================
|
||||||
|
('RECEBER_VER', 'Visualizar contas a receber'),
|
||||||
|
('RECEBER_CADASTRAR', 'Cadastrar contas a receber'),
|
||||||
|
('RECEBER_EDITAR', 'Editar contas a receber'),
|
||||||
|
('RECEBER_BAIXAR', 'Dar baixa em contas a receber'),
|
||||||
|
|
||||||
|
-- ========================
|
||||||
|
-- FINANCEIRO - PAGAR
|
||||||
|
-- ========================
|
||||||
|
('PAGAR_VER', 'Visualizar contas a pagar'),
|
||||||
|
('PAGAR_CADASTRAR', 'Cadastrar contas a pagar'),
|
||||||
|
('PAGAR_EDITAR', 'Editar contas a pagar'),
|
||||||
|
('PAGAR_BAIXAR', 'Dar baixa em contas a pagar'),
|
||||||
|
|
||||||
|
-- ========================
|
||||||
|
-- PLANO DE CONTAS
|
||||||
|
-- ========================
|
||||||
|
('PLANO_CONTAS_VER', 'Visualizar plano de contas'),
|
||||||
|
('PLANO_CONTAS_CADASTRAR', 'Cadastrar plano de contas'),
|
||||||
|
('PLANO_CONTAS_EDITAR', 'Editar plano de contas'),
|
||||||
|
('PLANO_CONTAS_EXCLUIR', 'Excluir plano de contas'),
|
||||||
|
|
||||||
|
-- ========================
|
||||||
|
-- TRANSPORTADORAS
|
||||||
|
-- ========================
|
||||||
|
('TRANSPORTADORA_VER', 'Visualizar transportadoras'),
|
||||||
|
('TRANSPORTADORA_CADASTRAR', 'Cadastrar transportadoras'),
|
||||||
|
('TRANSPORTADORA_EDITAR', 'Editar transportadoras'),
|
||||||
|
('TRANSPORTADORA_EXCLUIR', 'Excluir transportadoras'),
|
||||||
|
|
||||||
|
-- ========================
|
||||||
|
-- RELATORIOS
|
||||||
|
-- ========================
|
||||||
|
('RELATORIO_FINANCEIRO', 'Acessar relatórios financeiros'),
|
||||||
|
('RELATORIO_CLIENTES', 'Acessar relatórios de clientes'),
|
||||||
|
('RELATORIO_GERAL', 'Acessar relatórios gerais'),
|
||||||
|
|
||||||
|
-- ========================
|
||||||
|
-- SISTEMA
|
||||||
|
-- ========================
|
||||||
|
('SISTEMA_CONFIG', 'Alterar configurações do sistema'),
|
||||||
|
('SISTEMA_LOGS', 'Visualizar logs do sistema');
|
||||||
|
|
||||||
|
INSERT INTO Permissoes (Nome, Descricao)
|
||||||
|
SELECT 'CLIENTE_VER', 'Visualizar clientes'
|
||||||
|
WHERE NOT EXISTS (
|
||||||
|
SELECT 1 FROM Permissoes WHERE Nome = 'CLIENTE_VER'
|
||||||
|
);
|
||||||
74
ArquivosAuxiliares/DadosSistema.sql
Normal file
74
ArquivosAuxiliares/DadosSistema.sql
Normal file
@ -0,0 +1,74 @@
|
|||||||
|
-- =========================
|
||||||
|
-- PEGAR EMPRESA
|
||||||
|
-- =========================
|
||||||
|
DECLARE @EmpresaId INT;
|
||||||
|
SELECT TOP 1 @EmpresaId = Id FROM Empresa;
|
||||||
|
|
||||||
|
-- =========================
|
||||||
|
-- CRIAR USUARIO ADMIN
|
||||||
|
-- =========================
|
||||||
|
IF NOT EXISTS (SELECT 1 FROM Usuarios WHERE Usuario = 'admin' AND EmpresaId = @EmpresaId)
|
||||||
|
BEGIN
|
||||||
|
INSERT INTO Usuarios (
|
||||||
|
EmpresaId, Nome, Email, Usuario, SenhaHash, Ativo, CriadoEm
|
||||||
|
)
|
||||||
|
VALUES (
|
||||||
|
@EmpresaId,
|
||||||
|
'Administrador do Sistema',
|
||||||
|
'admin@levelcode.com.br',
|
||||||
|
'admin',
|
||||||
|
CONVERT(VARCHAR(255), HASHBYTES('SHA2_256', 'Nad310311*##'), 2),
|
||||||
|
1,
|
||||||
|
GETDATE()
|
||||||
|
);
|
||||||
|
END
|
||||||
|
|
||||||
|
-- =========================
|
||||||
|
-- CRIAR PERFIL ADMIN
|
||||||
|
-- =========================
|
||||||
|
IF NOT EXISTS (SELECT 1 FROM Perfis WHERE Nome = 'Administrador' AND EmpresaId = @EmpresaId)
|
||||||
|
BEGIN
|
||||||
|
INSERT INTO Perfis (
|
||||||
|
EmpresaId, Nome, Descricao, Ativo
|
||||||
|
)
|
||||||
|
VALUES (
|
||||||
|
@EmpresaId,
|
||||||
|
'Administrador',
|
||||||
|
'Acesso total ao sistema',
|
||||||
|
1
|
||||||
|
);
|
||||||
|
END
|
||||||
|
|
||||||
|
-- =========================
|
||||||
|
-- PEGAR IDS
|
||||||
|
-- =========================
|
||||||
|
DECLARE @UsuarioId INT;
|
||||||
|
DECLARE @PerfilId INT;
|
||||||
|
|
||||||
|
SELECT @UsuarioId = Id FROM Usuarios WHERE Usuario = 'admin' AND EmpresaId = @EmpresaId;
|
||||||
|
SELECT @PerfilId = Id FROM Perfis WHERE Nome = 'Administrador' AND EmpresaId = @EmpresaId;
|
||||||
|
|
||||||
|
-- =========================
|
||||||
|
-- VINCULAR USUARIO AO PERFIL
|
||||||
|
-- =========================
|
||||||
|
IF NOT EXISTS (
|
||||||
|
SELECT 1 FROM UsuarioPerfis
|
||||||
|
WHERE UsuarioId = @UsuarioId AND PerfilId = @PerfilId
|
||||||
|
)
|
||||||
|
BEGIN
|
||||||
|
INSERT INTO UsuarioPerfis (UsuarioId, PerfilId)
|
||||||
|
VALUES (@UsuarioId, @PerfilId);
|
||||||
|
END
|
||||||
|
|
||||||
|
-- =========================
|
||||||
|
-- DAR TODAS PERMISSÕES
|
||||||
|
-- =========================
|
||||||
|
INSERT INTO PerfilPermissoes (PerfilId, PermissaoId)
|
||||||
|
SELECT
|
||||||
|
@PerfilId,
|
||||||
|
Id
|
||||||
|
FROM Permissoes
|
||||||
|
WHERE NOT EXISTS (
|
||||||
|
SELECT 1 FROM PerfilPermissoes
|
||||||
|
WHERE PerfilId = @PerfilId AND PermissaoId = Permissoes.Id
|
||||||
|
);
|
||||||
674
ArquivosAuxiliares/Database.sql
Normal file
674
ArquivosAuxiliares/Database.sql
Normal file
@ -0,0 +1,674 @@
|
|||||||
|
-- ================================
|
||||||
|
-- CRIAR DATABASE
|
||||||
|
-- ================================
|
||||||
|
IF NOT EXISTS (SELECT name FROM sys.databases WHERE name = 'LevelOS')
|
||||||
|
BEGIN
|
||||||
|
CREATE DATABASE LevelOS;
|
||||||
|
END
|
||||||
|
GO
|
||||||
|
|
||||||
|
USE LevelOS;
|
||||||
|
GO
|
||||||
|
|
||||||
|
-- ================================
|
||||||
|
-- TABELA EMPRESA
|
||||||
|
-- ================================
|
||||||
|
CREATE TABLE Empresa (
|
||||||
|
Id INT IDENTITY(1,1) PRIMARY KEY,
|
||||||
|
|
||||||
|
-- Dados básicos
|
||||||
|
Nome VARCHAR(255) NOT NULL,
|
||||||
|
CNPJ VARCHAR(20) NOT NULL UNIQUE,
|
||||||
|
TipoEmpresa VARCHAR(20) NOT NULL,
|
||||||
|
RegimeTributario VARCHAR(30) NOT NULL,
|
||||||
|
CNAE VARCHAR(20) NOT NULL,
|
||||||
|
|
||||||
|
-- Endereço
|
||||||
|
Cep VARCHAR(15) NOT NULL,
|
||||||
|
Endereco VARCHAR(255) NOT NULL,
|
||||||
|
Numero INT NOT NULL,
|
||||||
|
Complemento VARCHAR(255),
|
||||||
|
Bairro VARCHAR(255) NOT NULL,
|
||||||
|
Cidade VARCHAR(255) NOT NULL,
|
||||||
|
UF CHAR(2) NOT NULL,
|
||||||
|
Pais VARCHAR(50),
|
||||||
|
|
||||||
|
-- Contatos
|
||||||
|
Telefone1 VARCHAR(20),
|
||||||
|
Telefone2 VARCHAR(20),
|
||||||
|
Celular VARCHAR(20),
|
||||||
|
Whatsapp VARCHAR(20),
|
||||||
|
Email VARCHAR(150) NOT NULL,
|
||||||
|
Site VARCHAR(255),
|
||||||
|
|
||||||
|
-- Fiscal
|
||||||
|
InscricaoEstadual VARCHAR(20) UNIQUE,
|
||||||
|
InscricaoMunicipal VARCHAR(20) UNIQUE,
|
||||||
|
|
||||||
|
-- Contador
|
||||||
|
CNPJCPF_Contador VARCHAR(20),
|
||||||
|
Nome_Contador VARCHAR(255),
|
||||||
|
|
||||||
|
-- Sistema
|
||||||
|
TextoParaRecibo VARCHAR(MAX),
|
||||||
|
|
||||||
|
-- Controle
|
||||||
|
Ativo BIT NOT NULL DEFAULT 1,
|
||||||
|
CriadoEm DATETIME DEFAULT GETDATE(),
|
||||||
|
AtualizadoEm DATETIME DEFAULT GETDATE()
|
||||||
|
);
|
||||||
|
GO
|
||||||
|
|
||||||
|
-- ================================
|
||||||
|
-- CONFIGURAÇÕES
|
||||||
|
-- ================================
|
||||||
|
CREATE TABLE Empresa_config (
|
||||||
|
Id INT IDENTITY(1,1) PRIMARY KEY,
|
||||||
|
EmpresaId INT NOT NULL,
|
||||||
|
|
||||||
|
-- Aparência
|
||||||
|
NomeSistema VARCHAR(255),
|
||||||
|
CorPrimaria VARCHAR(20),
|
||||||
|
CorSecundaria VARCHAR(20),
|
||||||
|
Logo VARCHAR(255),
|
||||||
|
Favicon VARCHAR(255),
|
||||||
|
|
||||||
|
-- OS
|
||||||
|
ExibirCPFCliente BIT DEFAULT 1,
|
||||||
|
ExibirTelefoneCliente BIT DEFAULT 1,
|
||||||
|
ExibirGarantia BIT DEFAULT 1,
|
||||||
|
DiasGarantiaPadrao INT DEFAULT 90,
|
||||||
|
|
||||||
|
-- Financeiro
|
||||||
|
GerarReciboAutomatico BIT DEFAULT 1,
|
||||||
|
ExibirValoresOS BIT DEFAULT 1,
|
||||||
|
|
||||||
|
-- Comunicação
|
||||||
|
EnviarEmailAutomatico BIT DEFAULT 0,
|
||||||
|
EnviarWhatsappAutomatico BIT DEFAULT 0,
|
||||||
|
|
||||||
|
-- Sistema
|
||||||
|
ModoEscuro BIT DEFAULT 0,
|
||||||
|
PermitirEdicaoOSFinalizada BIT DEFAULT 0,
|
||||||
|
|
||||||
|
-- Auditoria
|
||||||
|
CriadoEm DATETIME DEFAULT GETDATE(),
|
||||||
|
AtualizadoEm DATETIME DEFAULT GETDATE(),
|
||||||
|
|
||||||
|
CONSTRAINT FK_ConfigEmpresa
|
||||||
|
FOREIGN KEY (EmpresaId) REFERENCES Empresa(Id) ON DELETE CASCADE,
|
||||||
|
|
||||||
|
CONSTRAINT UQ_ConfigEmpresa UNIQUE (EmpresaId)
|
||||||
|
);
|
||||||
|
GO
|
||||||
|
|
||||||
|
-- ================================
|
||||||
|
-- FUNCIONÁRIOS
|
||||||
|
-- ================================
|
||||||
|
CREATE TABLE Funcionarios (
|
||||||
|
Id INT IDENTITY(1,1) PRIMARY KEY,
|
||||||
|
EmpresaId INT NOT NULL,
|
||||||
|
|
||||||
|
-- Dados pessoais
|
||||||
|
Nome VARCHAR(255) NOT NULL,
|
||||||
|
CPF VARCHAR(14),
|
||||||
|
DataNascimento DATE,
|
||||||
|
|
||||||
|
-- Contato
|
||||||
|
Telefone VARCHAR(20),
|
||||||
|
Celular VARCHAR(20),
|
||||||
|
Email VARCHAR(150) NOT NULL,
|
||||||
|
|
||||||
|
-- Login
|
||||||
|
Usuario VARCHAR(50) NOT NULL,
|
||||||
|
SenhaHash VARCHAR(255) NOT NULL,
|
||||||
|
|
||||||
|
-- Permissão
|
||||||
|
TipoConta VARCHAR(20) NOT NULL DEFAULT 'Atendente',
|
||||||
|
|
||||||
|
-- Controle
|
||||||
|
Ativo BIT NOT NULL DEFAULT 1,
|
||||||
|
UltimoLogin DATETIME,
|
||||||
|
|
||||||
|
-- Auditoria
|
||||||
|
CriadoEm DATETIME DEFAULT GETDATE(),
|
||||||
|
AtualizadoEm DATETIME DEFAULT GETDATE(),
|
||||||
|
|
||||||
|
-- Constraints
|
||||||
|
CONSTRAINT FK_FuncionarioEmpresa
|
||||||
|
FOREIGN KEY (EmpresaId) REFERENCES Empresa(Id) ON DELETE CASCADE,
|
||||||
|
|
||||||
|
CONSTRAINT UQ_LoginEmpresa UNIQUE (EmpresaId, Usuario)
|
||||||
|
);
|
||||||
|
GO
|
||||||
|
-- ================================
|
||||||
|
-- FORNECEDORES
|
||||||
|
-- ================================
|
||||||
|
|
||||||
|
CREATE TABLE Fornecedores (
|
||||||
|
Id INT IDENTITY(1,1) PRIMARY KEY,
|
||||||
|
EmpresaId INT NOT NULL,
|
||||||
|
|
||||||
|
-- Dados básicos
|
||||||
|
Nome VARCHAR(255) NOT NULL,
|
||||||
|
TipoPessoa VARCHAR(2) NOT NULL, -- PF ou PJ
|
||||||
|
Documento VARCHAR(20) NOT NULL, -- CPF ou CNPJ
|
||||||
|
|
||||||
|
-- Contato
|
||||||
|
Telefone VARCHAR(20),
|
||||||
|
Celular VARCHAR(20),
|
||||||
|
Whatsapp VARCHAR(20),
|
||||||
|
Email VARCHAR(150),
|
||||||
|
|
||||||
|
-- Endereço
|
||||||
|
Cep VARCHAR(15),
|
||||||
|
Endereco VARCHAR(255),
|
||||||
|
Numero INT,
|
||||||
|
Complemento VARCHAR(255),
|
||||||
|
Bairro VARCHAR(255),
|
||||||
|
Cidade VARCHAR(255),
|
||||||
|
UF CHAR(2),
|
||||||
|
|
||||||
|
-- Dados adicionais
|
||||||
|
NomeFantasia VARCHAR(255),
|
||||||
|
InscricaoEstadual VARCHAR(20),
|
||||||
|
Site VARCHAR(255),
|
||||||
|
Observacoes VARCHAR(MAX),
|
||||||
|
|
||||||
|
-- Controle
|
||||||
|
Ativo BIT NOT NULL DEFAULT 1,
|
||||||
|
|
||||||
|
-- Auditoria
|
||||||
|
CriadoEm DATETIME DEFAULT GETDATE(),
|
||||||
|
AtualizadoEm DATETIME DEFAULT GETDATE(),
|
||||||
|
|
||||||
|
-- Relacionamento
|
||||||
|
CONSTRAINT FK_FornecedorEmpresa
|
||||||
|
FOREIGN KEY (EmpresaId) REFERENCES Empresa(Id) ON DELETE CASCADE,
|
||||||
|
|
||||||
|
-- Evita duplicidade por empresa
|
||||||
|
CONSTRAINT UQ_Fornecedor_Doc UNIQUE (EmpresaId, Documento)
|
||||||
|
);
|
||||||
|
GO
|
||||||
|
|
||||||
|
-- ================================
|
||||||
|
-- TRANSPORTADORAS
|
||||||
|
-- ================================
|
||||||
|
CREATE TABLE Transportadoras (
|
||||||
|
Id INT IDENTITY(1,1) PRIMARY KEY,
|
||||||
|
EmpresaId INT NOT NULL,
|
||||||
|
|
||||||
|
-- Dados básicos
|
||||||
|
RazaoSocial VARCHAR(255) NOT NULL,
|
||||||
|
NomeFantasia VARCHAR(255),
|
||||||
|
CNPJ VARCHAR(20) NOT NULL,
|
||||||
|
|
||||||
|
-- Contato
|
||||||
|
Telefone VARCHAR(20),
|
||||||
|
Celular VARCHAR(20),
|
||||||
|
Whatsapp VARCHAR(20),
|
||||||
|
Email VARCHAR(150),
|
||||||
|
|
||||||
|
-- Endereço
|
||||||
|
Cep VARCHAR(15),
|
||||||
|
Endereco VARCHAR(255),
|
||||||
|
Numero INT,
|
||||||
|
Complemento VARCHAR(255),
|
||||||
|
Bairro VARCHAR(255),
|
||||||
|
Cidade VARCHAR(255),
|
||||||
|
UF CHAR(2),
|
||||||
|
|
||||||
|
-- Dados de transporte
|
||||||
|
TipoFrete VARCHAR(20), -- CIF / FOB / etc
|
||||||
|
PrazoEntrega INT, -- em dias
|
||||||
|
ValorFretePadrao DECIMAL(10,2),
|
||||||
|
|
||||||
|
-- Sistema
|
||||||
|
Observacoes VARCHAR(MAX),
|
||||||
|
|
||||||
|
-- Controle
|
||||||
|
Ativo BIT NOT NULL DEFAULT 1,
|
||||||
|
|
||||||
|
-- Auditoria
|
||||||
|
CriadoEm DATETIME DEFAULT GETDATE(),
|
||||||
|
AtualizadoEm DATETIME DEFAULT GETDATE(),
|
||||||
|
|
||||||
|
-- Relacionamento
|
||||||
|
CONSTRAINT FK_TransportadoraEmpresa
|
||||||
|
FOREIGN KEY (EmpresaId) REFERENCES Empresa(Id) ON DELETE CASCADE,
|
||||||
|
|
||||||
|
-- Evita duplicidade
|
||||||
|
CONSTRAINT UQ_Transportadora_CNPJ UNIQUE (EmpresaId, CNPJ)
|
||||||
|
);
|
||||||
|
GO
|
||||||
|
-- ================================
|
||||||
|
-- CLIENTES
|
||||||
|
-- ================================
|
||||||
|
CREATE TABLE Clientes (
|
||||||
|
Id INT IDENTITY(1,1) PRIMARY KEY,
|
||||||
|
EmpresaId INT NOT NULL,
|
||||||
|
|
||||||
|
-- Dados principais
|
||||||
|
Nome VARCHAR(255) NOT NULL,
|
||||||
|
NomeFantasia VARCHAR(255),
|
||||||
|
TipoPessoa VARCHAR(2) NOT NULL, -- PF / PJ
|
||||||
|
Documento VARCHAR(20) NOT NULL, -- CPF/CNPJ
|
||||||
|
RG VARCHAR(20),
|
||||||
|
InscricaoMunicipal VARCHAR(20),
|
||||||
|
DataNascimento DATE,
|
||||||
|
|
||||||
|
-- Contato
|
||||||
|
Contato VARCHAR(255),
|
||||||
|
Telefone1 VARCHAR(20),
|
||||||
|
Telefone2 VARCHAR(20),
|
||||||
|
Celular VARCHAR(20),
|
||||||
|
Whatsapp VARCHAR(20),
|
||||||
|
Email VARCHAR(150),
|
||||||
|
EmailNFe VARCHAR(150),
|
||||||
|
Site VARCHAR(255),
|
||||||
|
|
||||||
|
-- Classificação
|
||||||
|
Grupo VARCHAR(100),
|
||||||
|
|
||||||
|
-- Endereço
|
||||||
|
Cep VARCHAR(15),
|
||||||
|
Endereco VARCHAR(255),
|
||||||
|
Numero INT,
|
||||||
|
Complemento VARCHAR(255),
|
||||||
|
Bairro VARCHAR(255),
|
||||||
|
Cidade VARCHAR(255),
|
||||||
|
UF CHAR(2),
|
||||||
|
Pais VARCHAR(50),
|
||||||
|
|
||||||
|
-- Financeiro
|
||||||
|
LimiteCredito DECIMAL(10,2) DEFAULT 0,
|
||||||
|
Bloqueado BIT DEFAULT 0,
|
||||||
|
ObservacoesCobranca VARCHAR(MAX),
|
||||||
|
|
||||||
|
-- Vendas / OS
|
||||||
|
VendedorPadraoId INT NULL,
|
||||||
|
TipoConsumidor VARCHAR(50), -- Consumidor final, revenda etc
|
||||||
|
|
||||||
|
-- Sistema
|
||||||
|
Observacoes VARCHAR(MAX),
|
||||||
|
|
||||||
|
-- Extras (campos custom)
|
||||||
|
CampoExtra1 VARCHAR(255),
|
||||||
|
CampoExtra2 VARCHAR(255),
|
||||||
|
CampoExtra3 VARCHAR(255),
|
||||||
|
|
||||||
|
-- Carteiras virtuais
|
||||||
|
Bitcoin VARCHAR(255),
|
||||||
|
Ethereum VARCHAR(255),
|
||||||
|
Litecoin VARCHAR(255),
|
||||||
|
|
||||||
|
-- Controle
|
||||||
|
Ativo BIT NOT NULL DEFAULT 1,
|
||||||
|
UltimaCompra DATETIME,
|
||||||
|
|
||||||
|
-- Auditoria
|
||||||
|
CriadoEm DATETIME DEFAULT GETDATE(),
|
||||||
|
AtualizadoEm DATETIME DEFAULT GETDATE(),
|
||||||
|
|
||||||
|
-- Relacionamento
|
||||||
|
CONSTRAINT FK_ClienteEmpresa
|
||||||
|
FOREIGN KEY (EmpresaId) REFERENCES Empresa(Id) ON DELETE CASCADE,
|
||||||
|
|
||||||
|
-- Evita duplicidade
|
||||||
|
CONSTRAINT UQ_Cliente_Doc UNIQUE (EmpresaId, Documento)
|
||||||
|
);
|
||||||
|
GO
|
||||||
|
|
||||||
|
-- ================================
|
||||||
|
-- SERVIÇOS
|
||||||
|
-- ================================
|
||||||
|
CREATE TABLE Servicos (
|
||||||
|
Id INT IDENTITY(1,1) PRIMARY KEY,
|
||||||
|
EmpresaId INT NOT NULL,
|
||||||
|
|
||||||
|
-- Dados básicos
|
||||||
|
Nome VARCHAR(255) NOT NULL,
|
||||||
|
Descricao VARCHAR(MAX),
|
||||||
|
|
||||||
|
-- Valores
|
||||||
|
ValorPadrao DECIMAL(10,2) NOT NULL,
|
||||||
|
Custo DECIMAL(10,2),
|
||||||
|
|
||||||
|
-- Comissão
|
||||||
|
TipoComissao VARCHAR(10) NOT NULL DEFAULT 'Percentual', -- Percentual ou Fixo
|
||||||
|
ValorComissao DECIMAL(10,2) NOT NULL DEFAULT 0,
|
||||||
|
|
||||||
|
-- Tempo
|
||||||
|
TempoEstimado INT, -- em minutos
|
||||||
|
|
||||||
|
-- Controle
|
||||||
|
Ativo BIT NOT NULL DEFAULT 1,
|
||||||
|
|
||||||
|
-- Auditoria
|
||||||
|
CriadoEm DATETIME DEFAULT GETDATE(),
|
||||||
|
AtualizadoEm DATETIME DEFAULT GETDATE(),
|
||||||
|
|
||||||
|
-- Relacionamento
|
||||||
|
CONSTRAINT FK_ServicoEmpresa
|
||||||
|
FOREIGN KEY (EmpresaId) REFERENCES Empresa(Id) ON DELETE CASCADE
|
||||||
|
);
|
||||||
|
GO
|
||||||
|
-- ================================
|
||||||
|
-- Situação OS
|
||||||
|
-- ================================
|
||||||
|
CREATE TABLE SituacoesOS (
|
||||||
|
Id INT IDENTITY(1,1) PRIMARY KEY,
|
||||||
|
EmpresaId INT NOT NULL,
|
||||||
|
|
||||||
|
-- Identificação
|
||||||
|
Descricao VARCHAR(255) NOT NULL,
|
||||||
|
|
||||||
|
-- Classificação (os 3 grupos da tela)
|
||||||
|
Tipo VARCHAR(20) NOT NULL,
|
||||||
|
-- Entrada | Oficina | Saida
|
||||||
|
|
||||||
|
-- Regras da OS
|
||||||
|
ConsideraAberta BIT NOT NULL DEFAULT 1,
|
||||||
|
ConsideraFechada BIT NOT NULL DEFAULT 0,
|
||||||
|
MarcaComoPronto BIT NOT NULL DEFAULT 0,
|
||||||
|
|
||||||
|
-- Aparência (igual na tela)
|
||||||
|
CorFundo VARCHAR(20),
|
||||||
|
CorFonte VARCHAR(20),
|
||||||
|
|
||||||
|
-- Financeiro (opcional)
|
||||||
|
PlanoContasId INT NULL,
|
||||||
|
|
||||||
|
-- Controle
|
||||||
|
Ordem INT DEFAULT 0, -- ordem de exibição
|
||||||
|
Ativo BIT NOT NULL DEFAULT 1,
|
||||||
|
|
||||||
|
-- Auditoria
|
||||||
|
CriadoEm DATETIME DEFAULT GETDATE(),
|
||||||
|
AtualizadoEm DATETIME DEFAULT GETDATE(),
|
||||||
|
|
||||||
|
-- Relacionamento
|
||||||
|
CONSTRAINT FK_SituacaoEmpresa
|
||||||
|
FOREIGN KEY (EmpresaId) REFERENCES Empresa(Id) ON DELETE CASCADE
|
||||||
|
);
|
||||||
|
GO
|
||||||
|
-- ================================
|
||||||
|
-- CONTRATOS
|
||||||
|
-- ================================
|
||||||
|
CREATE TABLE Contratos (
|
||||||
|
Id INT IDENTITY(1,1) PRIMARY KEY,
|
||||||
|
EmpresaId INT NOT NULL,
|
||||||
|
ClienteId INT NOT NULL,
|
||||||
|
|
||||||
|
-- Dados principais
|
||||||
|
Descricao VARCHAR(255),
|
||||||
|
Observacoes VARCHAR(MAX),
|
||||||
|
|
||||||
|
Valor DECIMAL(10,2) NOT NULL,
|
||||||
|
DataInicio DATE,
|
||||||
|
DataValidade DATE,
|
||||||
|
|
||||||
|
-- Controle de franquia (ex: horas inclusas)
|
||||||
|
FranquiaTempo INT, -- minutos ou horas (você define padrão)
|
||||||
|
|
||||||
|
-- Controle
|
||||||
|
Ativo BIT NOT NULL DEFAULT 1,
|
||||||
|
|
||||||
|
-- Auditoria
|
||||||
|
CriadoEm DATETIME DEFAULT GETDATE(),
|
||||||
|
AtualizadoEm DATETIME DEFAULT GETDATE(),
|
||||||
|
|
||||||
|
-- Relacionamentos
|
||||||
|
CONSTRAINT FK_ContratoEmpresa
|
||||||
|
FOREIGN KEY (EmpresaId) REFERENCES Empresa(Id) ON DELETE CASCADE,
|
||||||
|
|
||||||
|
CONSTRAINT FK_ContratoCliente
|
||||||
|
FOREIGN KEY (ClienteId) REFERENCES Clientes(Id)
|
||||||
|
);
|
||||||
|
GO
|
||||||
|
-- ================================
|
||||||
|
-- CONTRATOS - EQUIPAMENTOS
|
||||||
|
-- ================================
|
||||||
|
CREATE TABLE ContratoEquipamentos (
|
||||||
|
Id INT IDENTITY(1,1) PRIMARY KEY,
|
||||||
|
ContratoId INT NOT NULL,
|
||||||
|
|
||||||
|
-- Dados do equipamento
|
||||||
|
Modelo VARCHAR(255),
|
||||||
|
Marca VARCHAR(255),
|
||||||
|
Operadora VARCHAR(100),
|
||||||
|
Serial VARCHAR(100),
|
||||||
|
NumeroPatrimonio VARCHAR(100),
|
||||||
|
|
||||||
|
Observacoes VARCHAR(MAX),
|
||||||
|
|
||||||
|
-- Relacionamento
|
||||||
|
CONSTRAINT FK_ContratoEquipamento
|
||||||
|
FOREIGN KEY (ContratoId) REFERENCES Contratos(Id) ON DELETE CASCADE
|
||||||
|
);
|
||||||
|
GO
|
||||||
|
-- ================================
|
||||||
|
-- PLANO DE CONTAS
|
||||||
|
-- ================================
|
||||||
|
CREATE TABLE PlanoDeContas (
|
||||||
|
Id INT IDENTITY(1,1) PRIMARY KEY,
|
||||||
|
EmpresaId INT NOT NULL,
|
||||||
|
|
||||||
|
-- Hierarquia
|
||||||
|
ContaPaiId INT NULL,
|
||||||
|
|
||||||
|
-- Identificação
|
||||||
|
Nome VARCHAR(255) NOT NULL,
|
||||||
|
Codigo VARCHAR(50), -- Ex: 1.01.02
|
||||||
|
Tipo VARCHAR(20) NOT NULL, -- Receita / Despesa
|
||||||
|
|
||||||
|
-- Controle
|
||||||
|
AceitaLancamento BIT NOT NULL DEFAULT 1, -- se pode lançar direto
|
||||||
|
Ativo BIT NOT NULL DEFAULT 1,
|
||||||
|
|
||||||
|
-- Auditoria
|
||||||
|
CriadoEm DATETIME DEFAULT GETDATE(),
|
||||||
|
AtualizadoEm DATETIME DEFAULT GETDATE(),
|
||||||
|
|
||||||
|
-- Relacionamentos
|
||||||
|
CONSTRAINT FK_PlanoContaEmpresa
|
||||||
|
FOREIGN KEY (EmpresaId) REFERENCES Empresa(Id) ON DELETE CASCADE,
|
||||||
|
|
||||||
|
CONSTRAINT FK_PlanoContaPai
|
||||||
|
FOREIGN KEY (ContaPaiId) REFERENCES PlanoDeContas(Id)
|
||||||
|
);
|
||||||
|
GO
|
||||||
|
-- ================================
|
||||||
|
-- CONTAS A PAGAR
|
||||||
|
-- ================================
|
||||||
|
CREATE TABLE ContasReceber (
|
||||||
|
Id INT IDENTITY(1,1) PRIMARY KEY,
|
||||||
|
EmpresaId INT NOT NULL,
|
||||||
|
ClienteId INT NOT NULL,
|
||||||
|
|
||||||
|
-- Classificação
|
||||||
|
PlanoContaId INT NOT NULL,
|
||||||
|
|
||||||
|
-- Origem (contrato, venda futura, etc)
|
||||||
|
ContratoId INT NULL,
|
||||||
|
|
||||||
|
-- Dados financeiros
|
||||||
|
Descricao VARCHAR(255),
|
||||||
|
Valor DECIMAL(10,2) NOT NULL,
|
||||||
|
DataEmissao DATE,
|
||||||
|
DataVencimento DATE NOT NULL,
|
||||||
|
DataPagamento DATE,
|
||||||
|
|
||||||
|
-- Controle
|
||||||
|
Status VARCHAR(20) NOT NULL DEFAULT 'Pendente',
|
||||||
|
-- Pendente / Pago / Cancelado / Atrasado
|
||||||
|
|
||||||
|
ValorPago DECIMAL(10,2),
|
||||||
|
Juros DECIMAL(10,2) DEFAULT 0,
|
||||||
|
Multa DECIMAL(10,2) DEFAULT 0,
|
||||||
|
Desconto DECIMAL(10,2) DEFAULT 0,
|
||||||
|
|
||||||
|
-- Observações
|
||||||
|
Observacoes VARCHAR(MAX),
|
||||||
|
|
||||||
|
-- Controle sistema
|
||||||
|
Ativo BIT NOT NULL DEFAULT 1,
|
||||||
|
|
||||||
|
-- Auditoria
|
||||||
|
CriadoEm DATETIME DEFAULT GETDATE(),
|
||||||
|
AtualizadoEm DATETIME DEFAULT GETDATE(),
|
||||||
|
|
||||||
|
-- Relacionamentos
|
||||||
|
CONSTRAINT FK_ReceberEmpresa
|
||||||
|
FOREIGN KEY (EmpresaId) REFERENCES Empresa(Id) ON DELETE CASCADE,
|
||||||
|
|
||||||
|
CONSTRAINT FK_ReceberCliente
|
||||||
|
FOREIGN KEY (ClienteId) REFERENCES Clientes(Id),
|
||||||
|
|
||||||
|
CONSTRAINT FK_ReceberPlano
|
||||||
|
FOREIGN KEY (PlanoContaId) REFERENCES PlanoDeContas(Id),
|
||||||
|
|
||||||
|
CONSTRAINT FK_ReceberContrato
|
||||||
|
FOREIGN KEY (ContratoId) REFERENCES Contratos(Id)
|
||||||
|
);
|
||||||
|
GO
|
||||||
|
-- ================================
|
||||||
|
-- CONTAS A PAGAR
|
||||||
|
-- ================================
|
||||||
|
CREATE TABLE ContasPagar (
|
||||||
|
Id INT IDENTITY(1,1) PRIMARY KEY,
|
||||||
|
EmpresaId INT NOT NULL,
|
||||||
|
FornecedorId INT NOT NULL,
|
||||||
|
|
||||||
|
-- Classificação
|
||||||
|
PlanoContaId INT NOT NULL,
|
||||||
|
|
||||||
|
-- Dados financeiros
|
||||||
|
Descricao VARCHAR(255),
|
||||||
|
Valor DECIMAL(10,2) NOT NULL,
|
||||||
|
DataEmissao DATE,
|
||||||
|
DataVencimento DATE NOT NULL,
|
||||||
|
DataPagamento DATE,
|
||||||
|
|
||||||
|
-- Controle
|
||||||
|
Status VARCHAR(20) NOT NULL DEFAULT 'Pendente',
|
||||||
|
|
||||||
|
ValorPago DECIMAL(10,2),
|
||||||
|
Juros DECIMAL(10,2) DEFAULT 0,
|
||||||
|
Multa DECIMAL(10,2) DEFAULT 0,
|
||||||
|
Desconto DECIMAL(10,2) DEFAULT 0,
|
||||||
|
|
||||||
|
-- Observações
|
||||||
|
Observacoes VARCHAR(MAX),
|
||||||
|
|
||||||
|
-- Controle sistema
|
||||||
|
Ativo BIT NOT NULL DEFAULT 1,
|
||||||
|
|
||||||
|
-- Auditoria
|
||||||
|
CriadoEm DATETIME DEFAULT GETDATE(),
|
||||||
|
AtualizadoEm DATETIME DEFAULT GETDATE(),
|
||||||
|
|
||||||
|
-- Relacionamentos
|
||||||
|
CONSTRAINT FK_PagarEmpresa
|
||||||
|
FOREIGN KEY (EmpresaId) REFERENCES Empresa(Id) ON DELETE CASCADE,
|
||||||
|
|
||||||
|
CONSTRAINT FK_PagarFornecedor
|
||||||
|
FOREIGN KEY (FornecedorId) REFERENCES Fornecedores(Id),
|
||||||
|
|
||||||
|
CONSTRAINT FK_PagarPlano
|
||||||
|
FOREIGN KEY (PlanoContaId) REFERENCES PlanoDeContas(Id)
|
||||||
|
);
|
||||||
|
GO
|
||||||
|
|
||||||
|
-- ================================
|
||||||
|
-- USUÁRIOS DO SISTEMA
|
||||||
|
-- ================================
|
||||||
|
CREATE TABLE Usuarios (
|
||||||
|
Id INT IDENTITY(1,1) PRIMARY KEY,
|
||||||
|
EmpresaId INT NOT NULL,
|
||||||
|
|
||||||
|
Nome VARCHAR(255) NOT NULL,
|
||||||
|
Email VARCHAR(150) NOT NULL,
|
||||||
|
Usuario VARCHAR(50) NOT NULL,
|
||||||
|
SenhaHash VARCHAR(255) NOT NULL,
|
||||||
|
|
||||||
|
-- Controle
|
||||||
|
Ativo BIT NOT NULL DEFAULT 1,
|
||||||
|
UltimoLogin DATETIME,
|
||||||
|
|
||||||
|
-- Auditoria
|
||||||
|
CriadoEm DATETIME DEFAULT GETDATE(),
|
||||||
|
AtualizadoEm DATETIME DEFAULT GETDATE(),
|
||||||
|
|
||||||
|
-- Relacionamento
|
||||||
|
CONSTRAINT FK_UsuarioEmpresa
|
||||||
|
FOREIGN KEY (EmpresaId) REFERENCES Empresa(Id) ON DELETE CASCADE,
|
||||||
|
|
||||||
|
-- Evita login duplicado por empresa
|
||||||
|
CONSTRAINT UQ_Usuario_Login UNIQUE (EmpresaId, Usuario)
|
||||||
|
);
|
||||||
|
GO
|
||||||
|
-- ================================
|
||||||
|
-- PERFIS DE USUÁRIO
|
||||||
|
-- ================================
|
||||||
|
CREATE TABLE Perfis (
|
||||||
|
Id INT IDENTITY(1,1) PRIMARY KEY,
|
||||||
|
EmpresaId INT NOT NULL,
|
||||||
|
|
||||||
|
Nome VARCHAR(100) NOT NULL, -- Admin, Técnico, etc
|
||||||
|
Descricao VARCHAR(255),
|
||||||
|
|
||||||
|
Ativo BIT NOT NULL DEFAULT 1,
|
||||||
|
|
||||||
|
CONSTRAINT FK_PerfilEmpresa
|
||||||
|
FOREIGN KEY (EmpresaId) REFERENCES Empresa(Id) ON DELETE CASCADE
|
||||||
|
);
|
||||||
|
GO
|
||||||
|
-- ================================
|
||||||
|
-- PERMISSÕES DE USUÁRIO
|
||||||
|
-- ================================
|
||||||
|
CREATE TABLE Permissoes (
|
||||||
|
Id INT IDENTITY(1,1) PRIMARY KEY,
|
||||||
|
|
||||||
|
Nome VARCHAR(100) NOT NULL, -- Ex: CLIENTE_CADASTRAR
|
||||||
|
Descricao VARCHAR(255)
|
||||||
|
);
|
||||||
|
GO
|
||||||
|
-- ================================
|
||||||
|
-- PERFIL - PERMISSÕES
|
||||||
|
-- ================================
|
||||||
|
CREATE TABLE PerfilPermissoes (
|
||||||
|
Id INT IDENTITY(1,1) PRIMARY KEY,
|
||||||
|
PerfilId INT NOT NULL,
|
||||||
|
PermissaoId INT NOT NULL,
|
||||||
|
|
||||||
|
CONSTRAINT FK_PerfilPermissao_Perfil
|
||||||
|
FOREIGN KEY (PerfilId) REFERENCES Perfis(Id) ON DELETE CASCADE,
|
||||||
|
|
||||||
|
CONSTRAINT FK_PerfilPermissao_Permissao
|
||||||
|
FOREIGN KEY (PermissaoId) REFERENCES Permissoes(Id) ON DELETE CASCADE,
|
||||||
|
|
||||||
|
CONSTRAINT UQ_PerfilPermissao UNIQUE (PerfilId, PermissaoId)
|
||||||
|
);
|
||||||
|
GO
|
||||||
|
-- ================================
|
||||||
|
-- USUÁRIO - PERFIL
|
||||||
|
-- ================================
|
||||||
|
CREATE TABLE UsuarioPerfis (
|
||||||
|
Id INT IDENTITY(1,1) PRIMARY KEY,
|
||||||
|
UsuarioId INT NOT NULL,
|
||||||
|
PerfilId INT NOT NULL,
|
||||||
|
|
||||||
|
CONSTRAINT FK_UsuarioPerfil_Usuario
|
||||||
|
FOREIGN KEY (UsuarioId)
|
||||||
|
REFERENCES Usuarios(Id)
|
||||||
|
ON DELETE CASCADE,
|
||||||
|
|
||||||
|
CONSTRAINT FK_UsuarioPerfil_Perfil
|
||||||
|
FOREIGN KEY (PerfilId)
|
||||||
|
REFERENCES Perfis(Id)
|
||||||
|
ON DELETE NO ACTION,
|
||||||
|
|
||||||
|
CONSTRAINT UQ_UsuarioPerfil UNIQUE (UsuarioId, PerfilId)
|
||||||
|
);
|
||||||
|
GO
|
||||||
95
ArquivosAuxiliares/ExemploUSO.txt
Normal file
95
ArquivosAuxiliares/ExemploUSO.txt
Normal file
@ -0,0 +1,95 @@
|
|||||||
|
using DALL;
|
||||||
|
using System.Data;
|
||||||
|
|
||||||
|
// =============================================
|
||||||
|
// Configuração da connection string
|
||||||
|
// =============================================
|
||||||
|
var connectionString = "Server=206.42.13.180;Database=Levelcode-LevelOS;User Id=sa;Password=suasenha;TrustServerCertificate=True;";
|
||||||
|
|
||||||
|
var backupService = new DALLBackupService(connectionString);
|
||||||
|
|
||||||
|
// =============================================
|
||||||
|
// Backup FULL
|
||||||
|
// =============================================
|
||||||
|
var resultadoFull = backupService.ExecutarBackupFull();
|
||||||
|
|
||||||
|
if (resultadoFull.Sucesso)
|
||||||
|
Console.WriteLine($"✅ Backup FULL concluído em {resultadoFull.Duracao.TotalSeconds:F1}s");
|
||||||
|
else
|
||||||
|
Console.WriteLine($"❌ Erro no Backup FULL: {resultadoFull.Erro}");
|
||||||
|
|
||||||
|
// =============================================
|
||||||
|
// Backup DIFERENCIAL
|
||||||
|
// =============================================
|
||||||
|
var resultadoDiff = backupService.ExecutarBackupDiferencial();
|
||||||
|
|
||||||
|
if (resultadoDiff.Sucesso)
|
||||||
|
Console.WriteLine($"✅ Backup DIFERENCIAL concluído em {resultadoDiff.Duracao.TotalSeconds:F1}s");
|
||||||
|
else
|
||||||
|
Console.WriteLine($"❌ Erro no Backup DIFERENCIAL: {resultadoDiff.Erro}");
|
||||||
|
|
||||||
|
// =============================================
|
||||||
|
// Limpeza de backups antigos
|
||||||
|
// =============================================
|
||||||
|
var resultadoLimpeza = backupService.ExecutarLimpeza();
|
||||||
|
|
||||||
|
if (resultadoLimpeza.Sucesso)
|
||||||
|
Console.WriteLine($"✅ Limpeza concluída em {resultadoLimpeza.Duracao.TotalSeconds:F1}s");
|
||||||
|
else
|
||||||
|
Console.WriteLine($"❌ Erro na Limpeza: {resultadoLimpeza.Erro}");
|
||||||
|
|
||||||
|
// =============================================
|
||||||
|
// Listar histórico de backups
|
||||||
|
// =============================================
|
||||||
|
var historico = backupService.ListarHistoricoBackups();
|
||||||
|
|
||||||
|
Console.WriteLine("\n📋 Histórico de Backups:");
|
||||||
|
Console.WriteLine($"{"Tipo",-15} {"TamanhoMB",-12} {"Inicio",-22} {"Arquivo"}");
|
||||||
|
Console.WriteLine(new string('-', 90));
|
||||||
|
|
||||||
|
foreach (DataRow row in historico.Rows)
|
||||||
|
{
|
||||||
|
Console.WriteLine($"{row["Tipo"],-15} {row["TamanhoMB"],-12} {row["Inicio"],-22} {row["Arquivo"]}");
|
||||||
|
}
|
||||||
|
|
||||||
|
// =============================================
|
||||||
|
// Restauração FULL + DIFERENCIAL
|
||||||
|
// =============================================
|
||||||
|
|
||||||
|
// Pega o arquivo mais recente do histórico automaticamente
|
||||||
|
string arquivoFull = "";
|
||||||
|
string arquivoDiff = "";
|
||||||
|
|
||||||
|
foreach (DataRow row in historico.Rows)
|
||||||
|
{
|
||||||
|
if (row["Tipo"].ToString() == "FULL" && string.IsNullOrEmpty(arquivoFull))
|
||||||
|
arquivoFull = row["Arquivo"].ToString()!;
|
||||||
|
|
||||||
|
if (row["Tipo"].ToString() == "DIFERENCIAL" && string.IsNullOrEmpty(arquivoDiff))
|
||||||
|
arquivoDiff = row["Arquivo"].ToString()!;
|
||||||
|
|
||||||
|
if (!string.IsNullOrEmpty(arquivoFull) && !string.IsNullOrEmpty(arquivoDiff))
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Restaura FULL
|
||||||
|
Console.WriteLine($"\n🔁 Restaurando FULL: {arquivoFull}");
|
||||||
|
var r1 = backupService.RestaurarBackup(arquivoFull, TipoRestauracao.Full);
|
||||||
|
|
||||||
|
if (r1.Sucesso)
|
||||||
|
{
|
||||||
|
Console.WriteLine($"✅ FULL restaurado em {r1.Duracao.TotalSeconds:F1}s");
|
||||||
|
|
||||||
|
// Aplica DIFERENCIAL após o FULL
|
||||||
|
Console.WriteLine($"🔁 Aplicando DIFERENCIAL: {arquivoDiff}");
|
||||||
|
var r2 = backupService.RestaurarBackup(arquivoDiff, TipoRestauracao.Diferencial);
|
||||||
|
|
||||||
|
if (r2.Sucesso)
|
||||||
|
Console.WriteLine($"✅ DIFERENCIAL aplicado em {r2.Duracao.TotalSeconds:F1}s — Banco online!");
|
||||||
|
else
|
||||||
|
Console.WriteLine($"❌ Erro no DIFERENCIAL: {r2.Erro}");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Console.WriteLine($"❌ Erro no FULL: {r1.Erro}");
|
||||||
|
}
|
||||||
157
ArquivosAuxiliares/InsertsLotes.sql
Normal file
157
ArquivosAuxiliares/InsertsLotes.sql
Normal file
@ -0,0 +1,157 @@
|
|||||||
|
INSERT INTO Bancos (NUMERO, NOME) VALUES
|
||||||
|
(1,'Banco do Brasil S/A'),
|
||||||
|
(2,'Banco Central do Brasil'),
|
||||||
|
(3,'Banco da Amazonia S/A'),
|
||||||
|
(4,'Banco do Nordeste do Brasil S/A'),
|
||||||
|
(8,'Banco Santander Meridional S/A'),
|
||||||
|
(21,'BANESTES S/A - Banco Est.Esp.Santo'),
|
||||||
|
(22,'CREDIREAL'),
|
||||||
|
(24,'Banco de Pernambuco S/A - BANDEPE'),
|
||||||
|
(25,'Banco Alfa S/A'),
|
||||||
|
(27,'Banco Estado Santa Catarina S/A'),
|
||||||
|
(28,'BANEB'),
|
||||||
|
(29,'Banco BANERJ S/A'),
|
||||||
|
(30,'PARAIBAN - Banco da Paraiba S/A'),
|
||||||
|
(31,'Banco BEG S/A'),
|
||||||
|
(33,'SANTANDER'),
|
||||||
|
(34,'Banco BEA S/A'),
|
||||||
|
(35,'Banco do Estado do Ceara S/A - BEC'),
|
||||||
|
(36,'Banco do Estado do Maranhao S/A'),
|
||||||
|
(37,'Banco do Estado do Para S/A'),
|
||||||
|
(38,'Banco BANESTADO S/A'),
|
||||||
|
(39,'Banco do Estado do Piaui S/A'),
|
||||||
|
(40,'Banco Cargill S/A'),
|
||||||
|
(41,'Banco Est. Rio Grande do Sul S/A'),
|
||||||
|
(44,'Banco BVA S/A'),
|
||||||
|
(45,'Banco OPPORTUNITY S/A'),
|
||||||
|
(47,'Banco Est. de Sergipe S/A'),
|
||||||
|
(48,'Banco BENGE S/A'),
|
||||||
|
(63,'IBIBANK S/A - Banco Multiplo'),
|
||||||
|
(65,'LEMON BANK Banco Multiplo S/A'),
|
||||||
|
(66,'Banco MORGAN S. D. Witter S/A'),
|
||||||
|
(67,'Banco BANEB S/A'),
|
||||||
|
(68,'Banco BEA S/A'),
|
||||||
|
(70,'BRB-Banco de Brasilia S/A'),
|
||||||
|
(89,'CREDISAN'),
|
||||||
|
(104,'Caixa Economica Federal'),
|
||||||
|
(106,'Banco Itabanco S/A'),
|
||||||
|
(107,'Banco BBM S/A'),
|
||||||
|
(109,'CREDIBANCO S/A'),
|
||||||
|
(116,'Banco BNL do Brasil S/A'),
|
||||||
|
(148,'Bank Of America Brasil S/A'),
|
||||||
|
(151,'Banco Nossa Caixa S/A'),
|
||||||
|
(175,'Banco Finasa S/A'),
|
||||||
|
(184,'Banco BBA Creditanstalt S/A'),
|
||||||
|
(204,'BCO Inter American Express S/A'),
|
||||||
|
(208,'Banco Pactual S/A'),
|
||||||
|
(210,'DRESDNER Bank Lateinamerika A.'),
|
||||||
|
(212,'Banco Matone S/A'),
|
||||||
|
(213,'Banco ARBI S/A'),
|
||||||
|
(214,'Banco DIBENS S/A'),
|
||||||
|
(215,'Banco Com e Invest Sudameris'),
|
||||||
|
(216,'Banco Regional MALCON S/A'),
|
||||||
|
(217,'Banco JOHN DEERE S/A'),
|
||||||
|
(218,'Banco Bonsucesso S/A'),
|
||||||
|
(219,'Banco ZOGBI S/A'),
|
||||||
|
(222,'BCO Credit Lyonnais Brasil S/A'),
|
||||||
|
(224,'Banco Fibra S/A'),
|
||||||
|
(225,'Banco Brascan S/A'),
|
||||||
|
(229,'Banco Cruzeiro do Sul S/A'),
|
||||||
|
(230,'Banco Bandeirantes S/A'),
|
||||||
|
(231,'Banco Boavista interatlantico S/A'),
|
||||||
|
(233,'Banco GE Capital S/A'),
|
||||||
|
(237,'Banco Bradesco S/A'),
|
||||||
|
(240,'Banco de Credito Real de M.G. S/A'),
|
||||||
|
(241,'Banco Classico S/A'),
|
||||||
|
(243,'Banco STOCK Maxima S/A'),
|
||||||
|
(244,'Banco Cidade S/A'),
|
||||||
|
(246,'Banco ABC-Brasil S/A'),
|
||||||
|
(247,'UBS WARBURG S/A'),
|
||||||
|
(249,'Banco Investcred UNIBANCO S/A'),
|
||||||
|
(250,'Banco SCHAHIN S/A'),
|
||||||
|
(252,'Banco FININVEST S/A'),
|
||||||
|
(254,'PARANA Banco S/A'),
|
||||||
|
(263,'Banco CACIQUE S/A'),
|
||||||
|
(265,'Banco Fator S/A'),
|
||||||
|
(266,'Banco Cedula S/A'),
|
||||||
|
(275,'Banco ABN AMRO Real S/A'),
|
||||||
|
(291,'Banco de Cred. Nacional S/A'),
|
||||||
|
(294,'BCR'),
|
||||||
|
(300,'Banco de LA Nacion Argentina'),
|
||||||
|
(318,'Banco BMG S/A'),
|
||||||
|
(320,'Banco Ind. e Com. S/A'),
|
||||||
|
(341,'Banco Itau S/A'),
|
||||||
|
(346,'Banco BFB'),
|
||||||
|
(347,'Banco Sudameris Brasil S/A'),
|
||||||
|
(351,'Banco Bozano Simonsen S/A'),
|
||||||
|
(353,'Banco Santander S/A'),
|
||||||
|
(356,'Banco ABN AMRO S/A'),
|
||||||
|
(366,'Banco Societe Generale Bras. S/A'),
|
||||||
|
(370,'Banco Westlb do Brasil S/A'),
|
||||||
|
(376,'Banco CHASE Manhattan S/A'),
|
||||||
|
(389,'Banco Mercantil do Brasil S/A'),
|
||||||
|
(392,'Banco Mercantil de Sao Paulo S/A'),
|
||||||
|
(394,'Banco BMC S/A'),
|
||||||
|
(399,'HSBC Bank Brasil S/A'),
|
||||||
|
(409,'Unibanco Uniao de Bancos Bras. S/A'),
|
||||||
|
(412,'Banco Capital S/A'),
|
||||||
|
(422,'Banco Safra S/A'),
|
||||||
|
(424,'Banco Santander Nordeste S/A'),
|
||||||
|
(453,'Banco Rural S/A'),
|
||||||
|
(456,'Banco de Tokio Mitsubishi BR S/A'),
|
||||||
|
(464,'Banco Sumitomo Mitsui Bras. S/A'),
|
||||||
|
(472,'LLOYDS Bank PLC'),
|
||||||
|
(473,'Banco Financial Portugues S/A'),
|
||||||
|
(477,'Banco Citibank N/A'),
|
||||||
|
(479,'Bankboston Banco Multiplo S/A'),
|
||||||
|
(487,'Deutsche Bank S/A'),
|
||||||
|
(488,'Morgan G. Trust Company of NY'),
|
||||||
|
(492,'ING Bank N.V.'),
|
||||||
|
(493,'Banco Union - Brasil S/A'),
|
||||||
|
(494,'Banco de La Rep. Or.Del Uruguai'),
|
||||||
|
(495,'Banco de La Provinc.Buenos Aires'),
|
||||||
|
(496,'Banco Uno-E Brasil S/A'),
|
||||||
|
(505,'Banco Credit S. F. Boston S/A'),
|
||||||
|
(600,'Banco Luso Brasileiro S/A'),
|
||||||
|
(604,'Banco Industrial Brasileiro S/A'),
|
||||||
|
(610,'Banco VR S/A'),
|
||||||
|
(611,'Banco Paulista S/A'),
|
||||||
|
(612,'Banco Guanabara S/A'),
|
||||||
|
(613,'Banco Pecunia S/A'),
|
||||||
|
(623,'Banco Panamericano S/A'),
|
||||||
|
(626,'Banco FICSA S/A'),
|
||||||
|
(630,'Banco Intercap S/A'),
|
||||||
|
(633,'Banco Rendimento S/A'),
|
||||||
|
(634,'Banco Triangulo S/A'),
|
||||||
|
(637,'Banco SOFISA S/A'),
|
||||||
|
(638,'Banco Prosper S/A'),
|
||||||
|
(641,'Banco Bilbao Vizcaya Argentaria Brasil S/A'),
|
||||||
|
(643,'Banco Pine S/A'),
|
||||||
|
(650,'Banco PEBB S/A'),
|
||||||
|
(652,'Banco Frances e Brasileiro S/A'),
|
||||||
|
(653,'Banco Indusval S/A'),
|
||||||
|
(654,'Banco A. J. RENNER S/A'),
|
||||||
|
(655,'Banco Votorantim S/A'),
|
||||||
|
(702,'Banco Santos S/A'),
|
||||||
|
(707,'Banco Daycoval S/A'),
|
||||||
|
(719,'Banco Banif Primus S/A'),
|
||||||
|
(721,'Banco Credibel S/A'),
|
||||||
|
(733,'Banco das Nacoes S/A'),
|
||||||
|
(734,'Banco Gerdau S/A'),
|
||||||
|
(735,'Banco Pottencial S/A'),
|
||||||
|
(738,'Banco Morada S/A'),
|
||||||
|
(739,'Banco BGN S/A'),
|
||||||
|
(740,'Banco BARCLAYS S/A'),
|
||||||
|
(741,'Banco Ribeirao Preto S/A'),
|
||||||
|
(743,'Banco Emblema S/A'),
|
||||||
|
(744,'Bankboston N.A.'),
|
||||||
|
(745,'Banco Citibank S/A'),
|
||||||
|
(746,'Banco Modal S/A'),
|
||||||
|
(747,'Banco Rabobank INT Brasil S/A'),
|
||||||
|
(748,'Banco Coop. Sic. S/A BANSICREDI'),
|
||||||
|
(749,'BR Banco Mercantil S/A'),
|
||||||
|
(751,'DRESDNER Bank Brasil S/A'),
|
||||||
|
(752,'Banco BNP Paribas Brasil S/A'),
|
||||||
|
(753,'Banco Comercial Uruguai S/A'),
|
||||||
|
(756,'Banco Cooperativo do Brasil S/A'),
|
||||||
|
(757,'Banco KEB do Brasil S/A');
|
||||||
44
ArquivosAuxiliares/ProcedureBKP-DIFF_AUTO.sql
Normal file
44
ArquivosAuxiliares/ProcedureBKP-DIFF_AUTO.sql
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
USE [msdb]
|
||||||
|
GO
|
||||||
|
|
||||||
|
-- =============================================
|
||||||
|
-- Job: Backup DIFERENCIAL - a cada 6 horas
|
||||||
|
-- =============================================
|
||||||
|
EXEC sp_add_job @job_name = N'Backup DIFERENCIAL - Levelcode-LevelOS';
|
||||||
|
|
||||||
|
EXEC sp_add_jobstep
|
||||||
|
@job_name = N'Backup DIFERENCIAL - Levelcode-LevelOS',
|
||||||
|
@step_name = N'Executar Backup DIFERENCIAL',
|
||||||
|
@command = N'EXEC [Levelcode-LevelOS].[dbo].[sp_BackupDiferencial]',
|
||||||
|
@database_name = N'Levelcode-LevelOS';
|
||||||
|
|
||||||
|
EXEC sp_add_schedule
|
||||||
|
@schedule_name = N'A cada 6 horas',
|
||||||
|
@freq_type = 4, -- diário
|
||||||
|
@freq_interval = 1,
|
||||||
|
@freq_subday_type = 8, -- a cada X horas
|
||||||
|
@freq_subday_interval = 6, -- 6 horas
|
||||||
|
@active_start_time = 080000; -- começa às 08:00
|
||||||
|
|
||||||
|
EXEC sp_attach_schedule
|
||||||
|
@job_name = N'Backup DIFERENCIAL - Levelcode-LevelOS',
|
||||||
|
@schedule_name = N'A cada 6 horas';
|
||||||
|
|
||||||
|
EXEC sp_add_jobserver
|
||||||
|
@job_name = N'Backup DIFERENCIAL - Levelcode-LevelOS';
|
||||||
|
GO
|
||||||
|
|
||||||
|
-- Confirma os jobs criados
|
||||||
|
SELECT
|
||||||
|
j.name AS Job,
|
||||||
|
s.name AS Schedule,
|
||||||
|
s.active_start_time,
|
||||||
|
CASE s.freq_subday_type
|
||||||
|
WHEN 8 THEN CAST(s.freq_subday_interval AS VARCHAR) + 'h em ' + CAST(s.freq_subday_interval AS VARCHAR) + 'h'
|
||||||
|
ELSE 'Diário fixo'
|
||||||
|
END AS Frequencia
|
||||||
|
FROM msdb.dbo.sysjobs j
|
||||||
|
JOIN msdb.dbo.sysjobschedules js ON j.job_id = js.job_id
|
||||||
|
JOIN msdb.dbo.sysschedules s ON js.schedule_id = s.schedule_id
|
||||||
|
WHERE j.name LIKE '%Levelcode%'
|
||||||
|
ORDER BY j.name;
|
||||||
25
ArquivosAuxiliares/ProcedureBKP-FULL_AUTO.sql
Normal file
25
ArquivosAuxiliares/ProcedureBKP-FULL_AUTO.sql
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
USE [msdb]
|
||||||
|
GO
|
||||||
|
|
||||||
|
-- Job: Backup FULL - toda madrugada às 02:00
|
||||||
|
EXEC sp_add_job @job_name = N'Backup FULL - Levelcode-LevelOS';
|
||||||
|
|
||||||
|
EXEC sp_add_jobstep
|
||||||
|
@job_name = N'Backup FULL - Levelcode-LevelOS',
|
||||||
|
@step_name = N'Executar Backup FULL',
|
||||||
|
@command = N'EXEC [Levelcode-LevelOS].[dbo].[sp_BackupFull]',
|
||||||
|
@database_name = N'Levelcode-LevelOS';
|
||||||
|
|
||||||
|
EXEC sp_add_schedule
|
||||||
|
@schedule_name = N'Diario 02:00',
|
||||||
|
@freq_type = 4, -- diário
|
||||||
|
@freq_interval = 1,
|
||||||
|
@active_start_time = 020000; -- 02:00:00
|
||||||
|
|
||||||
|
EXEC sp_attach_schedule
|
||||||
|
@job_name = N'Backup FULL - Levelcode-LevelOS',
|
||||||
|
@schedule_name = N'Diario 02:00';
|
||||||
|
|
||||||
|
EXEC sp_add_jobserver
|
||||||
|
@job_name = N'Backup FULL - Levelcode-LevelOS';
|
||||||
|
GO
|
||||||
61
ArquivosAuxiliares/ProcedureBackups.sql
Normal file
61
ArquivosAuxiliares/ProcedureBackups.sql
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
USE [Levelcode-LevelOS]
|
||||||
|
GO
|
||||||
|
|
||||||
|
DROP PROCEDURE IF EXISTS [dbo].[sp_BackupFull]
|
||||||
|
GO
|
||||||
|
|
||||||
|
CREATE PROCEDURE [dbo].[sp_BackupFull]
|
||||||
|
AS
|
||||||
|
BEGIN
|
||||||
|
SET NOCOUNT ON;
|
||||||
|
|
||||||
|
DECLARE @Caminho NVARCHAR(500);
|
||||||
|
|
||||||
|
SET @Caminho = '/var/opt/mssql/backups/Levelcode-LevelOS_FULL_'
|
||||||
|
+ FORMAT(GETDATE(), 'yyyyMMdd_HHmmss') + '.bak';
|
||||||
|
|
||||||
|
BACKUP DATABASE [Levelcode-LevelOS]
|
||||||
|
TO DISK = @Caminho
|
||||||
|
WITH FORMAT,
|
||||||
|
INIT,
|
||||||
|
NAME = 'Backup FULL - Levelcode-LevelOS',
|
||||||
|
STATS = 10;
|
||||||
|
END
|
||||||
|
GO
|
||||||
|
|
||||||
|
-- Confirma criação
|
||||||
|
SELECT name, create_date, modify_date
|
||||||
|
FROM sys.procedures
|
||||||
|
WHERE name = 'sp_BackupFull';
|
||||||
|
|
||||||
|
|
||||||
|
USE [Levelcode-LevelOS]
|
||||||
|
GO
|
||||||
|
|
||||||
|
DROP PROCEDURE IF EXISTS [dbo].[sp_BackupDiferencial]
|
||||||
|
GO
|
||||||
|
|
||||||
|
CREATE PROCEDURE [dbo].[sp_BackupDiferencial]
|
||||||
|
AS
|
||||||
|
BEGIN
|
||||||
|
SET NOCOUNT ON;
|
||||||
|
|
||||||
|
DECLARE @Caminho NVARCHAR(500);
|
||||||
|
|
||||||
|
SET @Caminho = '/var/opt/mssql/backups/Levelcode-LevelOS_DIFF_'
|
||||||
|
+ FORMAT(GETDATE(), 'yyyyMMdd_HHmmss') + '.bak';
|
||||||
|
|
||||||
|
BACKUP DATABASE [Levelcode-LevelOS]
|
||||||
|
TO DISK = @Caminho
|
||||||
|
WITH DIFFERENTIAL,
|
||||||
|
INIT,
|
||||||
|
NAME = 'Backup DIFERENCIAL - Levelcode-LevelOS',
|
||||||
|
STATS = 10;
|
||||||
|
END
|
||||||
|
GO
|
||||||
|
|
||||||
|
-- Confirma ambas criadas
|
||||||
|
SELECT name, create_date, modify_date
|
||||||
|
FROM sys.procedures
|
||||||
|
WHERE name IN ('sp_BackupFull', 'sp_BackupDiferencial')
|
||||||
|
ORDER BY name;
|
||||||
128
ArquivosAuxiliares/ProcedureRestaurarBanco.sql
Normal file
128
ArquivosAuxiliares/ProcedureRestaurarBanco.sql
Normal file
@ -0,0 +1,128 @@
|
|||||||
|
USE [master]
|
||||||
|
GO
|
||||||
|
|
||||||
|
DROP PROCEDURE IF EXISTS [dbo].[sp_RestaurarBackup]
|
||||||
|
GO
|
||||||
|
|
||||||
|
CREATE PROCEDURE [dbo].[sp_RestaurarBackup]
|
||||||
|
@Arquivo NVARCHAR(500) = NULL,
|
||||||
|
@Tipo CHAR(1) = 'F' -- 'F' = FULL | 'D' = DIFERENCIAL
|
||||||
|
AS
|
||||||
|
BEGIN
|
||||||
|
SET NOCOUNT ON;
|
||||||
|
|
||||||
|
-- =============================================
|
||||||
|
-- Se não informar arquivo, lista os disponíveis
|
||||||
|
-- =============================================
|
||||||
|
IF @Arquivo IS NULL
|
||||||
|
BEGIN
|
||||||
|
PRINT '>>> Backups disponíveis no histórico:';
|
||||||
|
|
||||||
|
SELECT
|
||||||
|
ROW_NUMBER() OVER (ORDER BY bs.backup_finish_date DESC) AS N,
|
||||||
|
CASE bs.type
|
||||||
|
WHEN 'D' THEN 'FULL'
|
||||||
|
WHEN 'I' THEN 'DIFERENCIAL'
|
||||||
|
END AS Tipo,
|
||||||
|
bmf.physical_device_name AS Arquivo,
|
||||||
|
bs.backup_start_date AS Inicio,
|
||||||
|
bs.backup_finish_date AS Fim,
|
||||||
|
CAST(bs.backup_size / 1024.0 / 1024.0 AS DECIMAL(10,2)) AS TamanhoMB
|
||||||
|
FROM msdb.dbo.backupset bs
|
||||||
|
JOIN msdb.dbo.backupmediafamily bmf
|
||||||
|
ON bs.media_set_id = bmf.media_set_id
|
||||||
|
WHERE bs.database_name = 'Levelcode-LevelOS'
|
||||||
|
ORDER BY bs.backup_finish_date DESC;
|
||||||
|
|
||||||
|
PRINT '>>> Copie o caminho do arquivo desejado e execute:';
|
||||||
|
PRINT '>>> EXEC sp_RestaurarBackup @Arquivo = ''caminho_aqui'', @Tipo = ''F''';
|
||||||
|
RETURN;
|
||||||
|
END
|
||||||
|
|
||||||
|
-- =============================================
|
||||||
|
-- Verifica o arquivo com RESTORE HEADERONLY
|
||||||
|
-- =============================================
|
||||||
|
BEGIN TRY
|
||||||
|
RESTORE HEADERONLY FROM DISK = @Arquivo;
|
||||||
|
END TRY
|
||||||
|
BEGIN CATCH
|
||||||
|
RAISERROR('Arquivo não encontrado ou inválido: %s', 16, 1, @Arquivo);
|
||||||
|
RETURN;
|
||||||
|
END CATCH
|
||||||
|
|
||||||
|
-- =============================================
|
||||||
|
-- Coloca o banco em SINGLE_USER
|
||||||
|
-- =============================================
|
||||||
|
PRINT '>>> Preparando banco para restauração...';
|
||||||
|
|
||||||
|
BEGIN TRY
|
||||||
|
ALTER DATABASE [Levelcode-LevelOS]
|
||||||
|
SET SINGLE_USER WITH ROLLBACK IMMEDIATE;
|
||||||
|
END TRY
|
||||||
|
BEGIN CATCH
|
||||||
|
PRINT '>>> Aviso: ' + ERROR_MESSAGE();
|
||||||
|
END CATCH
|
||||||
|
|
||||||
|
-- =============================================
|
||||||
|
-- Restauração FULL
|
||||||
|
-- =============================================
|
||||||
|
IF @Tipo = 'F'
|
||||||
|
BEGIN
|
||||||
|
PRINT '>>> Restaurando FULL: ' + @Arquivo;
|
||||||
|
|
||||||
|
RESTORE DATABASE [Levelcode-LevelOS]
|
||||||
|
FROM DISK = @Arquivo
|
||||||
|
WITH REPLACE,
|
||||||
|
NORECOVERY,
|
||||||
|
STATS = 10;
|
||||||
|
|
||||||
|
ALTER DATABASE [Levelcode-LevelOS] SET MULTI_USER;
|
||||||
|
|
||||||
|
PRINT '>>> FULL restaurado com sucesso!';
|
||||||
|
PRINT '>>> Se tiver diferencial execute: EXEC sp_RestaurarBackup @Arquivo = ''caminho_diff'', @Tipo = ''D''';
|
||||||
|
PRINT '>>> Se não tiver diferencial execute: RESTORE DATABASE [Levelcode-LevelOS] WITH RECOVERY;';
|
||||||
|
END
|
||||||
|
|
||||||
|
-- =============================================
|
||||||
|
-- Restauração DIFERENCIAL
|
||||||
|
-- =============================================
|
||||||
|
IF @Tipo = 'D'
|
||||||
|
BEGIN
|
||||||
|
PRINT '>>> Aplicando DIFERENCIAL: ' + @Arquivo;
|
||||||
|
|
||||||
|
RESTORE DATABASE [Levelcode-LevelOS]
|
||||||
|
FROM DISK = @Arquivo
|
||||||
|
WITH RECOVERY,
|
||||||
|
STATS = 10;
|
||||||
|
|
||||||
|
ALTER DATABASE [Levelcode-LevelOS] SET MULTI_USER;
|
||||||
|
|
||||||
|
PRINT '>>> Banco restaurado e online!';
|
||||||
|
END
|
||||||
|
END
|
||||||
|
GO
|
||||||
|
|
||||||
|
--Como usar --
|
||||||
|
-- 1. Lista os backups disponíveis
|
||||||
|
EXEC [master].[dbo].[sp_RestaurarBackup];
|
||||||
|
|
||||||
|
-- 2. Restaura apenas o FULL (sem diferencial)
|
||||||
|
EXEC [master].[dbo].[sp_RestaurarBackup]
|
||||||
|
@Arquivo = '/var/opt/mssql/backups/Levelcode-LevelOS_FULL_20260413_020000.bak',
|
||||||
|
@Tipo = 'F';
|
||||||
|
|
||||||
|
-- Finaliza o banco após o FULL sem diferencial
|
||||||
|
RESTORE DATABASE [Levelcode-LevelOS] WITH RECOVERY;
|
||||||
|
|
||||||
|
-- 3. Restaura FULL + DIFERENCIAL (sequência completa)
|
||||||
|
EXEC [master].[dbo].[sp_RestaurarBackup]
|
||||||
|
@Arquivo = '/var/opt/mssql/backups/Levelcode-LevelOS_FULL_20260413_020000.bak',
|
||||||
|
@Tipo = 'F';
|
||||||
|
|
||||||
|
EXEC [master].[dbo].[sp_RestaurarBackup]
|
||||||
|
@Arquivo = '/var/opt/mssql/backups/Levelcode-LevelOS_DIFF_20260413_080000.bak',
|
||||||
|
@Tipo = 'D';
|
||||||
|
|
||||||
|
EXEC [master].[dbo].[sp_RestaurarBackup]
|
||||||
|
@Arquivo = '/var/opt/mssql/backups/Levelcode-LevelOS_FULL_20260413_072013.bak',
|
||||||
|
@Tipo = 'F';
|
||||||
77
ArquivosAuxiliares/Procedure_LIMPEZA15DIAS.sql
Normal file
77
ArquivosAuxiliares/Procedure_LIMPEZA15DIAS.sql
Normal file
@ -0,0 +1,77 @@
|
|||||||
|
USE [Levelcode-LevelOS]
|
||||||
|
GO
|
||||||
|
|
||||||
|
-- =============================================
|
||||||
|
-- Procedure: Limpeza de backups antigos (+15 dias)
|
||||||
|
-- =============================================
|
||||||
|
DROP PROCEDURE IF EXISTS [dbo].[sp_LimpezaBackups]
|
||||||
|
GO
|
||||||
|
|
||||||
|
CREATE PROCEDURE [dbo].[sp_LimpezaBackups]
|
||||||
|
AS
|
||||||
|
BEGIN
|
||||||
|
SET NOCOUNT ON;
|
||||||
|
|
||||||
|
DECLARE @DataCorte DATETIME = DATEADD(DAY, -15, GETDATE());
|
||||||
|
DECLARE @Comando NVARCHAR(500);
|
||||||
|
DECLARE @Arquivo NVARCHAR(500);
|
||||||
|
|
||||||
|
-- Cursor nos backups com mais de 15 dias
|
||||||
|
DECLARE cur CURSOR FOR
|
||||||
|
SELECT DISTINCT bmf.physical_device_name
|
||||||
|
FROM msdb.dbo.backupset bs
|
||||||
|
JOIN msdb.dbo.backupmediafamily bmf
|
||||||
|
ON bs.media_set_id = bmf.media_set_id
|
||||||
|
WHERE bs.database_name = 'Levelcode-LevelOS'
|
||||||
|
AND bs.backup_finish_date < @DataCorte
|
||||||
|
AND bmf.physical_device_name LIKE '/var/opt/mssql/backups/%';
|
||||||
|
|
||||||
|
OPEN cur;
|
||||||
|
FETCH NEXT FROM cur INTO @Arquivo;
|
||||||
|
|
||||||
|
WHILE @@FETCH_STATUS = 0
|
||||||
|
BEGIN
|
||||||
|
-- Deleta o arquivo físico no Linux
|
||||||
|
SET @Comando = 'rm -f ' + @Arquivo;
|
||||||
|
EXEC xp_cmdshell @Comando;
|
||||||
|
|
||||||
|
-- Remove o histórico do msdb
|
||||||
|
PRINT 'Removido: ' + @Arquivo;
|
||||||
|
|
||||||
|
FETCH NEXT FROM cur INTO @Arquivo;
|
||||||
|
END
|
||||||
|
|
||||||
|
CLOSE cur;
|
||||||
|
DEALLOCATE cur;
|
||||||
|
|
||||||
|
-- Limpa o histórico do msdb também
|
||||||
|
EXEC msdb.dbo.sp_delete_backuphistory @oldest_date = @DataCorte;
|
||||||
|
|
||||||
|
PRINT 'Limpeza concluída. Backups anteriores a '
|
||||||
|
+ CONVERT(NVARCHAR(20), @DataCorte, 120) + ' removidos.';
|
||||||
|
END
|
||||||
|
GO
|
||||||
|
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
|
USE [Levelcode-LevelOS]
|
||||||
|
GO
|
||||||
|
|
||||||
|
-- =============================================
|
||||||
|
-- Procedure: Limpeza do HISTÓRICO (msdb) +15 dias
|
||||||
|
-- =============================================
|
||||||
|
DROP PROCEDURE IF EXISTS [dbo].[sp_LimpezaBackups]
|
||||||
|
GO
|
||||||
|
|
||||||
|
CREATE PROCEDURE [dbo].[sp_LimpezaBackups]
|
||||||
|
AS
|
||||||
|
BEGIN
|
||||||
|
SET NOCOUNT ON;
|
||||||
|
|
||||||
|
DECLARE @DataCorte DATETIME = DATEADD(DAY, -15, GETDATE());
|
||||||
|
|
||||||
|
-- Limpa apenas o histórico do msdb (não precisa de xp_cmdshell)
|
||||||
|
EXEC msdb.dbo.sp_delete_backuphistory @oldest_date = @DataCorte;
|
||||||
|
|
||||||
|
PRINT 'Histórico de backups anteriores a '
|
||||||
|
+ CONVERT(NVARCHAR(20), @DataCorte, 120) + ' removido do msdb.';
|
||||||
|
END
|
||||||
|
GO
|
||||||
32
ArquivosAuxiliares/ScriptLimpezaServidor.sh
Normal file
32
ArquivosAuxiliares/ScriptLimpezaServidor.sh
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
# Cria o script de limpeza
|
||||||
|
cat > /var/opt/mssql/backups/limpar_backups.sh << 'EOF'
|
||||||
|
#!/bin/bash
|
||||||
|
# Deleta arquivos .bak com mais de 15 dias
|
||||||
|
find /var/opt/mssql/backups/ -name "*.bak" -mtime +15 -delete
|
||||||
|
echo "[$(date)] Limpeza concluída." >> /var/opt/mssql/backups/limpeza.log
|
||||||
|
EOF
|
||||||
|
|
||||||
|
# Dá permissão de execução
|
||||||
|
chmod +x /var/opt/mssql/backups/limpar_backups.sh
|
||||||
|
|
||||||
|
# Agenda no cron todo domingo às 03:00
|
||||||
|
(crontab -l 2>/dev/null; echo "0 3 * * 0 /var/opt/mssql/backups/limpar_backups.sh") | crontab -
|
||||||
|
|
||||||
|
# Confirma o cron
|
||||||
|
crontab -l
|
||||||
|
|
||||||
|
#-------------------------------------------------------------------------------------------------
|
||||||
|
cat > /var/opt/mssql/backups/limpar_backups.sh << 'EOF'
|
||||||
|
#!/bin/bash
|
||||||
|
find /var/opt/mssql/backups/ -name "*.bak" -mtime +15 -delete
|
||||||
|
echo "[$(date)] Limpeza concluída." >> /var/opt/mssql/backups/limpeza.log
|
||||||
|
EOF
|
||||||
|
|
||||||
|
#Dar permissão
|
||||||
|
chmod +x /var/opt/mssql/backups/limpar_backups.sh
|
||||||
|
# Executar script
|
||||||
|
/var/opt/mssql/backups/limpar_backups.sh && cat /var/opt/mssql/backups/limpeza.log
|
||||||
|
# Agendar JOB
|
||||||
|
(crontab -l 2>/dev/null; echo "0 3 * * 0 /var/opt/mssql/backups/limpar_backups.sh") | crontab -
|
||||||
|
# confirmar agendamento
|
||||||
|
crontab -l
|
||||||
14
ArquivosAuxiliares/TriggerFuncionarios.sql
Normal file
14
ArquivosAuxiliares/TriggerFuncionarios.sql
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
--Gatilhos para a tabela funcionarios--
|
||||||
|
CREATE OR ALTER TRIGGER TR_Funcionarios_GerarCodigo
|
||||||
|
ON Funcionarios
|
||||||
|
AFTER INSERT
|
||||||
|
AS
|
||||||
|
BEGIN
|
||||||
|
SET NOCOUNT ON;
|
||||||
|
|
||||||
|
UPDATE F
|
||||||
|
SET CODIGO = CAST(100 + ((F.ID_FUNCIONARIO - 1) * 100) AS VARCHAR)
|
||||||
|
FROM Funcionarios F
|
||||||
|
INNER JOIN inserted I ON F.ID_FUNCIONARIO = I.ID_FUNCIONARIO;
|
||||||
|
END
|
||||||
|
GO
|
||||||
13
ArquivosAuxiliares/Trigger_AgendaCodigoAuto.sql
Normal file
13
ArquivosAuxiliares/Trigger_AgendaCodigoAuto.sql
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
CREATE OR ALTER TRIGGER TR_Agenda_GerarCodigo
|
||||||
|
ON Agenda
|
||||||
|
AFTER INSERT
|
||||||
|
AS
|
||||||
|
BEGIN
|
||||||
|
SET NOCOUNT ON;
|
||||||
|
|
||||||
|
UPDATE A
|
||||||
|
SET CODIGO = 'AG' + RIGHT('0000' + CAST(A.ID_AGENDA AS VARCHAR), 4)
|
||||||
|
FROM Agenda A
|
||||||
|
INNER JOIN inserted I ON A.ID_AGENDA = I.ID_AGENDA;
|
||||||
|
END
|
||||||
|
GO
|
||||||
151
ControlesCustom.cs
Normal file
151
ControlesCustom.cs
Normal file
@ -0,0 +1,151 @@
|
|||||||
|
using System.Drawing;
|
||||||
|
using System.Drawing.Drawing2D;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
using System.Windows.Forms;
|
||||||
|
|
||||||
|
namespace UI
|
||||||
|
{
|
||||||
|
public class RoundTextBox : UserControl
|
||||||
|
{
|
||||||
|
private TextBox _textBox = null!;
|
||||||
|
public int Radius { get; set; } = 4;
|
||||||
|
public Color BorderColor { get; set; } = Color.LightGray;
|
||||||
|
public Color FocusColor { get; set; } = Color.Blue;
|
||||||
|
private bool _focused;
|
||||||
|
|
||||||
|
public bool ReadOnly
|
||||||
|
{
|
||||||
|
get => _textBox.ReadOnly;
|
||||||
|
set => _textBox.ReadOnly = value;
|
||||||
|
}
|
||||||
|
public char PasswordChar
|
||||||
|
{
|
||||||
|
get => _textBox.PasswordChar;
|
||||||
|
set => _textBox.PasswordChar = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ── Adiciona isso aqui ──
|
||||||
|
public int SelectionStart
|
||||||
|
{
|
||||||
|
get => _textBox.SelectionStart;
|
||||||
|
set => _textBox.SelectionStart = value;
|
||||||
|
}
|
||||||
|
public new event KeyEventHandler? KeyDown
|
||||||
|
{
|
||||||
|
add => _textBox.KeyDown += value;
|
||||||
|
remove => _textBox.KeyDown -= value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool Multiline
|
||||||
|
{
|
||||||
|
get => _textBox.Multiline;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
_textBox.Multiline = value;
|
||||||
|
_textBox.ScrollBars = value ? ScrollBars.Vertical : ScrollBars.None;
|
||||||
|
AjustarTextBox();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string Text
|
||||||
|
{
|
||||||
|
get => _textBox.Text;
|
||||||
|
set => _textBox.Text = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public new Color BackColor
|
||||||
|
{
|
||||||
|
get => base.BackColor;
|
||||||
|
set { base.BackColor = value; if (_textBox != null) _textBox.BackColor = value; }
|
||||||
|
}
|
||||||
|
|
||||||
|
//public RoundTextBox()
|
||||||
|
//{
|
||||||
|
// DoubleBuffered = true;
|
||||||
|
// base.BackColor = Color.White;
|
||||||
|
// _textBox = new TextBox
|
||||||
|
// {
|
||||||
|
// BorderStyle = BorderStyle.None,
|
||||||
|
// Font = new Font("Segoe UI", 9f),
|
||||||
|
// Location = new Point(6, 6),
|
||||||
|
// Width = Width - 12,
|
||||||
|
// Height = Height - 12,
|
||||||
|
// BackColor = Color.White
|
||||||
|
// };
|
||||||
|
// _textBox.GotFocus += (s, e) => { _focused = true; Invalidate(); };
|
||||||
|
// _textBox.LostFocus += (s, e) => { _focused = false; Invalidate(); };
|
||||||
|
// Controls.Add(_textBox);
|
||||||
|
// SizeChanged += (s, e) => AjustarTextBox();
|
||||||
|
//}
|
||||||
|
public RoundTextBox()
|
||||||
|
{
|
||||||
|
DoubleBuffered = true;
|
||||||
|
base.BackColor = Color.White;
|
||||||
|
_textBox = new TextBox
|
||||||
|
{
|
||||||
|
BorderStyle = BorderStyle.None,
|
||||||
|
Font = new Font("Segoe UI", 9f),
|
||||||
|
Location = new Point(6, 6),
|
||||||
|
Width = Width - 12,
|
||||||
|
Height = Height - 12,
|
||||||
|
BackColor = Color.White
|
||||||
|
};
|
||||||
|
|
||||||
|
_textBox.GotFocus += (s, e) => { _focused = true; Invalidate(); };
|
||||||
|
_textBox.LostFocus += (s, e) => { _focused = false; Invalidate(); };
|
||||||
|
_textBox.TextChanged += (s, e) => OnTextChanged(e); // ← adiciona essa
|
||||||
|
_textBox.Leave += (s, e) => OnLeave(e); // ← e essa
|
||||||
|
|
||||||
|
Controls.Add(_textBox);
|
||||||
|
SizeChanged += (s, e) => AjustarTextBox();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ajusta largura e altura do TextBox interno conforme Multiline
|
||||||
|
private void AjustarTextBox()
|
||||||
|
{
|
||||||
|
_textBox.Width = Width - 12;
|
||||||
|
_textBox.Height = _textBox.Multiline ? Height - 12 : _textBox.PreferredHeight;
|
||||||
|
// Recentraliza verticalmente quando não é multiline
|
||||||
|
if (!_textBox.Multiline)
|
||||||
|
_textBox.Location = new Point(6, (Height - _textBox.PreferredHeight) / 2);
|
||||||
|
else
|
||||||
|
_textBox.Location = new Point(6, 6);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void OnPaint(PaintEventArgs e)
|
||||||
|
{
|
||||||
|
e.Graphics.SmoothingMode = SmoothingMode.AntiAlias;
|
||||||
|
using var path = GetPath(new Rectangle(0, 0, Width - 1, Height - 1), Radius);
|
||||||
|
using var brush = new SolidBrush(BackColor);
|
||||||
|
e.Graphics.FillPath(brush, path);
|
||||||
|
using var pen = new Pen(_focused ? FocusColor : BorderColor, _focused ? 1.5f : 1f);
|
||||||
|
e.Graphics.DrawPath(pen, path);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static GraphicsPath GetPath(Rectangle r, int rad)
|
||||||
|
{
|
||||||
|
var path = new GraphicsPath();
|
||||||
|
int d = rad * 2;
|
||||||
|
path.AddArc(r.X, r.Y, d, d, 180, 90);
|
||||||
|
path.AddArc(r.Right - d, r.Y, d, d, 270, 90);
|
||||||
|
path.AddArc(r.Right - d, r.Bottom - d, d, d, 0, 90);
|
||||||
|
path.AddArc(r.X, r.Bottom - d, d, d, 90, 90);
|
||||||
|
path.CloseFigure();
|
||||||
|
return path;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class RoundButton : Button
|
||||||
|
{
|
||||||
|
[DllImport("Gdi32.dll", EntryPoint = "CreateRoundRectRgn")]
|
||||||
|
private static extern IntPtr CreateRoundRectRgn(int nL, int nT, int nR, int nB, int nW, int nH);
|
||||||
|
|
||||||
|
protected override void OnPaint(PaintEventArgs e)
|
||||||
|
{
|
||||||
|
base.OnPaint(e);
|
||||||
|
Region = Region.FromHrgn(CreateRoundRectRgn(0, 0, Width, Height, 8, 8));
|
||||||
|
FlatStyle = FlatStyle.Flat;
|
||||||
|
FlatAppearance.BorderSize = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
120
ControlesCustom.resx
Normal file
120
ControlesCustom.resx
Normal file
@ -0,0 +1,120 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<root>
|
||||||
|
<!--
|
||||||
|
Microsoft ResX Schema
|
||||||
|
|
||||||
|
Version 2.0
|
||||||
|
|
||||||
|
The primary goals of this format is to allow a simple XML format
|
||||||
|
that is mostly human readable. The generation and parsing of the
|
||||||
|
various data types are done through the TypeConverter classes
|
||||||
|
associated with the data types.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
... ado.net/XML headers & schema ...
|
||||||
|
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||||
|
<resheader name="version">2.0</resheader>
|
||||||
|
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||||
|
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||||
|
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
||||||
|
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||||
|
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||||
|
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
||||||
|
</data>
|
||||||
|
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||||
|
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||||
|
<comment>This is a comment</comment>
|
||||||
|
</data>
|
||||||
|
|
||||||
|
There are any number of "resheader" rows that contain simple
|
||||||
|
name/value pairs.
|
||||||
|
|
||||||
|
Each data row contains a name, and value. The row also contains a
|
||||||
|
type or mimetype. Type corresponds to a .NET class that support
|
||||||
|
text/value conversion through the TypeConverter architecture.
|
||||||
|
Classes that don't support this are serialized and stored with the
|
||||||
|
mimetype set.
|
||||||
|
|
||||||
|
The mimetype is used for serialized objects, and tells the
|
||||||
|
ResXResourceReader how to depersist the object. This is currently not
|
||||||
|
extensible. For a given mimetype the value must be set accordingly:
|
||||||
|
|
||||||
|
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||||
|
that the ResXResourceWriter will generate, however the reader can
|
||||||
|
read any of the formats listed below.
|
||||||
|
|
||||||
|
mimetype: application/x-microsoft.net.object.binary.base64
|
||||||
|
value : The object must be serialized with
|
||||||
|
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
|
||||||
|
: and then encoded with base64 encoding.
|
||||||
|
|
||||||
|
mimetype: application/x-microsoft.net.object.soap.base64
|
||||||
|
value : The object must be serialized with
|
||||||
|
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||||
|
: and then encoded with base64 encoding.
|
||||||
|
|
||||||
|
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||||
|
value : The object must be serialized into a byte array
|
||||||
|
: using a System.ComponentModel.TypeConverter
|
||||||
|
: and then encoded with base64 encoding.
|
||||||
|
-->
|
||||||
|
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||||
|
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
||||||
|
<xsd:element name="root" msdata:IsDataSet="true">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:choice maxOccurs="unbounded">
|
||||||
|
<xsd:element name="metadata">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:sequence>
|
||||||
|
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||||
|
</xsd:sequence>
|
||||||
|
<xsd:attribute name="name" use="required" type="xsd:string" />
|
||||||
|
<xsd:attribute name="type" type="xsd:string" />
|
||||||
|
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||||
|
<xsd:attribute ref="xml:space" />
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
<xsd:element name="assembly">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:attribute name="alias" type="xsd:string" />
|
||||||
|
<xsd:attribute name="name" type="xsd:string" />
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
<xsd:element name="data">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:sequence>
|
||||||
|
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||||
|
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||||
|
</xsd:sequence>
|
||||||
|
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
|
||||||
|
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||||
|
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||||
|
<xsd:attribute ref="xml:space" />
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
<xsd:element name="resheader">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:sequence>
|
||||||
|
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||||
|
</xsd:sequence>
|
||||||
|
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
</xsd:choice>
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
</xsd:schema>
|
||||||
|
<resheader name="resmimetype">
|
||||||
|
<value>text/microsoft-resx</value>
|
||||||
|
</resheader>
|
||||||
|
<resheader name="version">
|
||||||
|
<value>2.0</value>
|
||||||
|
</resheader>
|
||||||
|
<resheader name="reader">
|
||||||
|
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||||
|
</resheader>
|
||||||
|
<resheader name="writer">
|
||||||
|
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||||
|
</resheader>
|
||||||
|
</root>
|
||||||
887
Dashboards/Cadastros/AgendaCadastroPanel.cs
Normal file
887
Dashboards/Cadastros/AgendaCadastroPanel.cs
Normal file
@ -0,0 +1,887 @@
|
|||||||
|
using BLL;
|
||||||
|
using CustomMessageBox;
|
||||||
|
using DAL;
|
||||||
|
using MLL;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Drawing;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Windows.Forms;
|
||||||
|
|
||||||
|
namespace UI
|
||||||
|
{
|
||||||
|
public class AgendaCadastroPanel : UserControl
|
||||||
|
{
|
||||||
|
string _cx = DadosDaConexao.ObterConexao();
|
||||||
|
// ── CORES ─────────────────────────────────────────────────────────────
|
||||||
|
private readonly Color AccentBlue = Color.FromArgb(37, 99, 235);
|
||||||
|
private readonly Color TextDark = Color.FromArgb(30, 41, 59);
|
||||||
|
private readonly Color BorderColor = Color.FromArgb(226, 232, 240);
|
||||||
|
private readonly Color GreenColor = Color.FromArgb(34, 197, 94);
|
||||||
|
private readonly Color AmberColor = Color.FromArgb(245, 158, 11);
|
||||||
|
private readonly Color RedColor = Color.FromArgb(239, 68, 68);
|
||||||
|
private readonly Color MutedGray = Color.FromArgb(148, 163, 184);
|
||||||
|
private readonly Color SurfaceColor = Color.FromArgb(248, 250, 252);
|
||||||
|
private readonly Color DisabledBack = Color.FromArgb(241, 245, 249);
|
||||||
|
|
||||||
|
// ── LAYOUT ────────────────────────────────────────────────────────────
|
||||||
|
private Panel pnlToolbar = null!;
|
||||||
|
private Panel pnlLeft = null!;
|
||||||
|
private Panel pnlRight = null!;
|
||||||
|
private Panel pnlEventList = null!;
|
||||||
|
private Panel pnlSplit = null!;
|
||||||
|
private Panel pnlDias = null!;
|
||||||
|
|
||||||
|
// ── TOOLBAR ───────────────────────────────────────────────────────────
|
||||||
|
private RoundButton btnNovo = null!;
|
||||||
|
private RoundButton btnAlterar = null!;
|
||||||
|
private RoundButton btnExcluir = null!;
|
||||||
|
private RoundButton btnLocalizar = null!;
|
||||||
|
private RoundButton btnSalvar = null!;
|
||||||
|
private RoundButton btnCancelar = null!;
|
||||||
|
|
||||||
|
// ── CAMPOS DO FORMULÁRIO ──────────────────────────────────────────────
|
||||||
|
private RoundTextBox txtId = null!;
|
||||||
|
private RoundTextBox txtCodigo = null!;
|
||||||
|
private RoundTextBox txtCompromisso = null!;
|
||||||
|
private RoundTextBox txtData = null!;
|
||||||
|
private RoundTextBox txtDia = null!;
|
||||||
|
private RoundTextBox txtHora = null!;
|
||||||
|
private RoundTextBox txtFunc = null!;
|
||||||
|
private RoundTextBox txtAvisar = null!;
|
||||||
|
private RoundTextBox txtOsVinc = null!;
|
||||||
|
private CheckBox chkRealizado = null!;
|
||||||
|
|
||||||
|
// ── INFO (readonly) ───────────────────────────────────────────────────
|
||||||
|
private RoundTextBox txtCriadoEm = null!;
|
||||||
|
private RoundTextBox txtAtualizadoEm = null!;
|
||||||
|
|
||||||
|
// ── CALENDÁRIO ────────────────────────────────────────────────────────
|
||||||
|
private Label lblMesAno = null!;
|
||||||
|
private Button btnPrev = null!;
|
||||||
|
private Button btnNext = null!;
|
||||||
|
|
||||||
|
// ── ESTADO ────────────────────────────────────────────────────────────
|
||||||
|
private DateTime _currentMonth = new DateTime(DateTime.Today.Year, DateTime.Today.Month, 1);
|
||||||
|
private DateTime? _selectedDate = null;
|
||||||
|
private List<MLL.ModeloAgenda> _eventos = new();
|
||||||
|
private int _nextId = 1;
|
||||||
|
|
||||||
|
// ── CONSTRUTOR ────────────────────────────────────────────────────────
|
||||||
|
public AgendaCadastroPanel()
|
||||||
|
{
|
||||||
|
Dock = DockStyle.Fill;
|
||||||
|
BackColor = Color.White;
|
||||||
|
DoubleBuffered = true;
|
||||||
|
|
||||||
|
InitializeLayout();
|
||||||
|
SetCampos(false);
|
||||||
|
//CarregarDadosFake();
|
||||||
|
CarregarDadosDoBanco();
|
||||||
|
RenderCalendario();
|
||||||
|
RenderListaEventos();
|
||||||
|
}
|
||||||
|
|
||||||
|
// ══════════════════════════════════════════════════════════════════════
|
||||||
|
// LAYOUT
|
||||||
|
// ══════════════════════════════════════════════════════════════════════
|
||||||
|
private void InitializeLayout()
|
||||||
|
{
|
||||||
|
Controls.Clear();
|
||||||
|
|
||||||
|
// ── TOOLBAR ───────────────────────────────────────────────────────
|
||||||
|
pnlToolbar = new Panel
|
||||||
|
{
|
||||||
|
Dock = DockStyle.Top,
|
||||||
|
Height = 55,
|
||||||
|
BackColor = SurfaceColor
|
||||||
|
};
|
||||||
|
|
||||||
|
var flow = new FlowLayoutPanel
|
||||||
|
{
|
||||||
|
Dock = DockStyle.Fill,
|
||||||
|
Padding = new Padding(12, 10, 0, 0),
|
||||||
|
BackColor = Color.Transparent
|
||||||
|
};
|
||||||
|
|
||||||
|
btnNovo = CreateToolbarButton("Novo", GreenColor);
|
||||||
|
btnAlterar = CreateToolbarButton("Alterar", AmberColor);
|
||||||
|
btnExcluir = CreateToolbarButton("Excluir", RedColor);
|
||||||
|
btnLocalizar = CreateToolbarButton("Localizar", AccentBlue);
|
||||||
|
btnSalvar = CreateToolbarButton("Salvar", AccentBlue);
|
||||||
|
btnCancelar = CreateToolbarButton("Cancelar", MutedGray);
|
||||||
|
|
||||||
|
btnNovo.Click += (_, _) => BtnNovo_Click();
|
||||||
|
btnAlterar.Click += (_, _) => BtnAlterar_Click();
|
||||||
|
btnExcluir.Click += (_, _) => BtnExcluir_Click();
|
||||||
|
btnLocalizar.Click += (_, _) => BtnLocalizar_Click();
|
||||||
|
btnSalvar.Click += (_, _) => BtnSalvar_Click();
|
||||||
|
btnCancelar.Click += (_, _) => BtnCancelar_Click();
|
||||||
|
|
||||||
|
flow.Controls.AddRange(new Control[]
|
||||||
|
{ btnNovo, btnAlterar, btnExcluir, btnLocalizar, btnSalvar, btnCancelar });
|
||||||
|
|
||||||
|
pnlToolbar.Controls.Add(flow);
|
||||||
|
Controls.Add(pnlToolbar);
|
||||||
|
|
||||||
|
// ── SPLIT ─────────────────────────────────────────────────────────
|
||||||
|
pnlSplit = new Panel { Dock = DockStyle.Fill, BackColor = Color.White };
|
||||||
|
Controls.Add(pnlSplit);
|
||||||
|
pnlSplit.BringToFront();
|
||||||
|
|
||||||
|
// RIGHT ─ calendário + lista
|
||||||
|
pnlRight = new Panel
|
||||||
|
{
|
||||||
|
Dock = DockStyle.Right,
|
||||||
|
Width = 340,
|
||||||
|
BackColor = Color.White,
|
||||||
|
Padding = new Padding(10, 10, 10, 10)
|
||||||
|
};
|
||||||
|
pnlSplit.Controls.Add(pnlRight);
|
||||||
|
BuildCalendario(); // preenche pnlRight
|
||||||
|
|
||||||
|
// Divider
|
||||||
|
var divider = new Panel
|
||||||
|
{
|
||||||
|
Dock = DockStyle.Right,
|
||||||
|
Width = 1,
|
||||||
|
BackColor = BorderColor
|
||||||
|
};
|
||||||
|
pnlSplit.Controls.Add(divider);
|
||||||
|
|
||||||
|
// LEFT ─ formulário
|
||||||
|
pnlLeft = new Panel
|
||||||
|
{
|
||||||
|
Dock = DockStyle.Fill,
|
||||||
|
AutoScroll = true,
|
||||||
|
BackColor = Color.White
|
||||||
|
};
|
||||||
|
pnlSplit.Controls.Add(pnlLeft);
|
||||||
|
BuildFormulario();
|
||||||
|
}
|
||||||
|
|
||||||
|
// ── FORMULÁRIO ────────────────────────────────────────────────────────
|
||||||
|
private void BuildFormulario()
|
||||||
|
{
|
||||||
|
var content = new Panel { Width = 800, BackColor = Color.White };
|
||||||
|
pnlLeft.Controls.Add(content);
|
||||||
|
|
||||||
|
const int rowH = 52;
|
||||||
|
const int secH = 28;
|
||||||
|
const int secGap = 10;
|
||||||
|
const int inputH = 28;
|
||||||
|
int y = 10;
|
||||||
|
|
||||||
|
// IDENTIFICAÇÃO
|
||||||
|
content.Controls.Add(CreateSectionHeader("IDENTIFICAÇÃO", y));
|
||||||
|
y += secH + 4;
|
||||||
|
|
||||||
|
txtId = AddInput(content, "ID", 20, y, 60, inputH, readOnly: true);
|
||||||
|
txtCodigo = AddInput(content, "Código", 90, y, 120, inputH);
|
||||||
|
txtCompromisso = AddInput(content, "Compromisso", 220, y, 520, inputH);
|
||||||
|
y += rowH;
|
||||||
|
|
||||||
|
// DATA E HORA
|
||||||
|
y += secGap;
|
||||||
|
content.Controls.Add(CreateSectionHeader("DATA E HORA", y));
|
||||||
|
y += secH + 4;
|
||||||
|
|
||||||
|
txtData = AddInput(content, "Data", 20, y, 130, inputH, readOnly: true);
|
||||||
|
txtDia = AddInput(content, "Dia", 160, y, 150, inputH, readOnly: true);
|
||||||
|
txtHora = AddInput(content, "Hora", 320, y, 100, inputH);
|
||||||
|
y += rowH;
|
||||||
|
|
||||||
|
// RESPONSÁVEL E AVISO
|
||||||
|
y += secGap;
|
||||||
|
content.Controls.Add(CreateSectionHeader("RESPONSÁVEL E AVISO", y));
|
||||||
|
y += secH + 4;
|
||||||
|
|
||||||
|
txtFunc = AddInput(content, "Funcionário", 20, y, 280, inputH);
|
||||||
|
txtAvisar = AddInput(content, "Avisar", 310, y, 180, inputH);
|
||||||
|
txtOsVinc = AddInput(content, "OS Vinculada", 500, y, 140, inputH);
|
||||||
|
y += rowH;
|
||||||
|
|
||||||
|
// SITUAÇÃO
|
||||||
|
y += secGap;
|
||||||
|
content.Controls.Add(CreateSectionHeader("SITUAÇÃO", y));
|
||||||
|
y += secH + 4;
|
||||||
|
|
||||||
|
chkRealizado = new CheckBox
|
||||||
|
{
|
||||||
|
Text = "Realizado",
|
||||||
|
Location = new Point(20, y + 4),
|
||||||
|
Font = new Font("Segoe UI", 8.5f, FontStyle.Bold),
|
||||||
|
ForeColor = TextDark,
|
||||||
|
AutoSize = true
|
||||||
|
};
|
||||||
|
content.Controls.Add(chkRealizado);
|
||||||
|
y += rowH;
|
||||||
|
|
||||||
|
// INFORMAÇÕES DO REGISTRO
|
||||||
|
y += secGap;
|
||||||
|
content.Controls.Add(CreateSectionHeader("INFORMAÇÕES DO REGISTRO", y));
|
||||||
|
y += secH + 4;
|
||||||
|
|
||||||
|
txtCriadoEm = AddInput(content, "Criado Em", 20, y, 175, inputH, readOnly: true);
|
||||||
|
txtAtualizadoEm = AddInput(content, "Atualizado Em", 205, y, 175, inputH, readOnly: true);
|
||||||
|
y += rowH;
|
||||||
|
|
||||||
|
content.Height = y + 10;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ── CALENDÁRIO ────────────────────────────────────────────────────────
|
||||||
|
// ATENÇÃO: No WinForms, DockStyle.Fill deve ser adicionado ANTES dos
|
||||||
|
// DockStyle.Top — a ordem de inserção em Controls é invertida visualmente.
|
||||||
|
private void BuildCalendario()
|
||||||
|
{
|
||||||
|
// 1º — Lista de eventos (Fill) → adicionada PRIMEIRO
|
||||||
|
pnlEventList = new Panel
|
||||||
|
{
|
||||||
|
Dock = DockStyle.Fill,
|
||||||
|
AutoScroll = true,
|
||||||
|
BackColor = Color.White,
|
||||||
|
Padding = new Padding(0, 4, 0, 0)
|
||||||
|
};
|
||||||
|
pnlRight.Controls.Add(pnlEventList); // ← PRIMEIRO
|
||||||
|
|
||||||
|
// 2º — Grid dos dias (Top) → adicionado DEPOIS do Fill
|
||||||
|
pnlDias = new Panel
|
||||||
|
{
|
||||||
|
Dock = DockStyle.Top,
|
||||||
|
Height = 215,
|
||||||
|
BackColor = Color.White
|
||||||
|
};
|
||||||
|
pnlRight.Controls.Add(pnlDias); // ← SEGUNDO
|
||||||
|
|
||||||
|
// 3º — Cabeçalho mês/ano (Top) → adicionado POR ÚLTIMO (aparece no topo)
|
||||||
|
var pnlCalHeader = new Panel
|
||||||
|
{
|
||||||
|
Dock = DockStyle.Top,
|
||||||
|
Height = 38,
|
||||||
|
BackColor = Color.White
|
||||||
|
};
|
||||||
|
|
||||||
|
btnPrev = new Button
|
||||||
|
{
|
||||||
|
Text = "‹",
|
||||||
|
Size = new Size(28, 26),
|
||||||
|
Location = new Point(0, 6),
|
||||||
|
FlatStyle = FlatStyle.Flat,
|
||||||
|
Font = new Font("Segoe UI", 13f),
|
||||||
|
ForeColor = AccentBlue,
|
||||||
|
BackColor = Color.White,
|
||||||
|
Cursor = Cursors.Hand
|
||||||
|
};
|
||||||
|
btnPrev.FlatAppearance.BorderColor = BorderColor;
|
||||||
|
btnPrev.Click += (_, _) =>
|
||||||
|
{
|
||||||
|
_currentMonth = _currentMonth.AddMonths(-1);
|
||||||
|
RenderCalendario();
|
||||||
|
RenderListaEventos();
|
||||||
|
};
|
||||||
|
|
||||||
|
btnNext = new Button
|
||||||
|
{
|
||||||
|
Text = "›",
|
||||||
|
Size = new Size(28, 26),
|
||||||
|
Location = new Point(290, 6),
|
||||||
|
FlatStyle = FlatStyle.Flat,
|
||||||
|
Font = new Font("Segoe UI", 13f),
|
||||||
|
ForeColor = AccentBlue,
|
||||||
|
BackColor = Color.White,
|
||||||
|
Cursor = Cursors.Hand
|
||||||
|
};
|
||||||
|
btnNext.FlatAppearance.BorderColor = BorderColor;
|
||||||
|
btnNext.Click += (_, _) =>
|
||||||
|
{
|
||||||
|
_currentMonth = _currentMonth.AddMonths(1);
|
||||||
|
RenderCalendario();
|
||||||
|
RenderListaEventos();
|
||||||
|
};
|
||||||
|
|
||||||
|
lblMesAno = new Label
|
||||||
|
{
|
||||||
|
AutoSize = false,
|
||||||
|
TextAlign = ContentAlignment.MiddleCenter,
|
||||||
|
Font = new Font("Segoe UI", 10f, FontStyle.Bold),
|
||||||
|
ForeColor = TextDark,
|
||||||
|
Size = new Size(256, 26),
|
||||||
|
Location = new Point(32, 6)
|
||||||
|
};
|
||||||
|
|
||||||
|
pnlCalHeader.Controls.AddRange(new Control[] { btnPrev, lblMesAno, btnNext });
|
||||||
|
pnlRight.Controls.Add(pnlCalHeader); // ← ÚLTIMO (fica no topo visualmente)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ══════════════════════════════════════════════════════════════════════
|
||||||
|
// RENDER CALENDÁRIO
|
||||||
|
// ══════════════════════════════════════════════════════════════════════
|
||||||
|
private void RenderCalendario()
|
||||||
|
{
|
||||||
|
pnlDias.Controls.Clear();
|
||||||
|
|
||||||
|
lblMesAno.Text = _currentMonth.ToString("MMMM yyyy",
|
||||||
|
new System.Globalization.CultureInfo("pt-BR")).ToUpper();
|
||||||
|
|
||||||
|
string[] dowLabels = { "Dom", "Seg", "Ter", "Qua", "Qui", "Sex", "Sáb" };
|
||||||
|
int cellW = 44;
|
||||||
|
int cellH = 26;
|
||||||
|
int startX = 2;
|
||||||
|
|
||||||
|
// Cabeçalho dias da semana
|
||||||
|
for (int i = 0; i < 7; i++)
|
||||||
|
{
|
||||||
|
pnlDias.Controls.Add(new Label
|
||||||
|
{
|
||||||
|
Text = dowLabels[i],
|
||||||
|
Size = new Size(cellW, 18),
|
||||||
|
Location = new Point(startX + i * cellW, 0),
|
||||||
|
TextAlign = ContentAlignment.MiddleCenter,
|
||||||
|
Font = new Font("Segoe UI", 7.5f, FontStyle.Bold),
|
||||||
|
ForeColor = MutedGray
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
int firstDow = (int)new DateTime(_currentMonth.Year, _currentMonth.Month, 1).DayOfWeek;
|
||||||
|
int daysInMonth = DateTime.DaysInMonth(_currentMonth.Year, _currentMonth.Month);
|
||||||
|
var datesWithEvts = GetDatesWithEvents();
|
||||||
|
DateTime today = DateTime.Today;
|
||||||
|
int col = firstDow, row = 0;
|
||||||
|
|
||||||
|
for (int d = 1; d <= daysInMonth; d++)
|
||||||
|
{
|
||||||
|
var date = new DateTime(_currentMonth.Year, _currentMonth.Month, d);
|
||||||
|
bool isToday = date == today;
|
||||||
|
bool isSelected = _selectedDate.HasValue && date == _selectedDate.Value;
|
||||||
|
bool hasEvent = datesWithEvts.Contains(date.Date);
|
||||||
|
|
||||||
|
var btn = new Button
|
||||||
|
{
|
||||||
|
Text = hasEvent ? $"{d} •" : d.ToString(),
|
||||||
|
Size = new Size(cellW - 2, cellH),
|
||||||
|
Location = new Point(startX + col * cellW, 22 + row * (cellH + 2)),
|
||||||
|
FlatStyle = FlatStyle.Flat,
|
||||||
|
Font = new Font("Segoe UI", 8f,
|
||||||
|
isToday || isSelected ? FontStyle.Bold : FontStyle.Regular),
|
||||||
|
Cursor = Cursors.Hand,
|
||||||
|
Tag = date
|
||||||
|
};
|
||||||
|
|
||||||
|
if (isSelected)
|
||||||
|
{
|
||||||
|
btn.BackColor = AccentBlue;
|
||||||
|
btn.ForeColor = Color.White;
|
||||||
|
btn.FlatAppearance.BorderColor = AccentBlue;
|
||||||
|
}
|
||||||
|
else if (isToday)
|
||||||
|
{
|
||||||
|
btn.BackColor = Color.White;
|
||||||
|
btn.ForeColor = AccentBlue;
|
||||||
|
btn.FlatAppearance.BorderColor = AccentBlue;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
btn.BackColor = Color.White;
|
||||||
|
btn.ForeColor = TextDark;
|
||||||
|
btn.FlatAppearance.BorderColor = BorderColor;
|
||||||
|
}
|
||||||
|
|
||||||
|
btn.Click += (s, _) =>
|
||||||
|
{
|
||||||
|
if (s is Button b && b.Tag is DateTime dt)
|
||||||
|
{
|
||||||
|
_selectedDate = dt;
|
||||||
|
if (txtData.Enabled)
|
||||||
|
{
|
||||||
|
txtData.Text = dt.ToString("dd/MM/yyyy");
|
||||||
|
txtDia.Text = new System.Globalization.CultureInfo("pt-BR")
|
||||||
|
.DateTimeFormat.GetDayName(dt.DayOfWeek);
|
||||||
|
}
|
||||||
|
RenderCalendario();
|
||||||
|
RenderListaEventos();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
pnlDias.Controls.Add(btn);
|
||||||
|
|
||||||
|
col++;
|
||||||
|
if (col == 7) { col = 0; row++; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ══════════════════════════════════════════════════════════════════════
|
||||||
|
// RENDER LISTA DE EVENTOS
|
||||||
|
// ══════════════════════════════════════════════════════════════════════
|
||||||
|
private void RenderListaEventos()
|
||||||
|
{
|
||||||
|
pnlEventList.Controls.Clear();
|
||||||
|
|
||||||
|
var filtrados = _selectedDate.HasValue
|
||||||
|
? _eventos.Where(e => ParseData(e.dDATA).Date == _selectedDate.Value.Date).ToList()
|
||||||
|
: _eventos.Where(e => ParseData(e.dDATA).Month == _currentMonth.Month
|
||||||
|
&& ParseData(e.dDATA).Year == _currentMonth.Year).ToList();
|
||||||
|
|
||||||
|
filtrados = filtrados.OrderBy(e => e.HORA).ToList();
|
||||||
|
|
||||||
|
// Largura real do painel (com fallback para evitar 0)
|
||||||
|
int listW = pnlEventList.ClientSize.Width > 0
|
||||||
|
? pnlEventList.ClientSize.Width
|
||||||
|
: pnlRight.Width - pnlRight.Padding.Horizontal - 20;
|
||||||
|
|
||||||
|
int y = 0;
|
||||||
|
|
||||||
|
// ── Título ────────────────────────────────────────────────────────
|
||||||
|
string titulo = _selectedDate.HasValue
|
||||||
|
? $"COMPROMISSOS — {_selectedDate.Value:dd/MM/yyyy}"
|
||||||
|
: $"COMPROMISSOS — {_currentMonth.ToString("MMMM/yyyy", new System.Globalization.CultureInfo("pt-BR")).ToUpper()}";
|
||||||
|
|
||||||
|
pnlEventList.Controls.Add(new Label
|
||||||
|
{
|
||||||
|
Text = titulo,
|
||||||
|
AutoSize = false,
|
||||||
|
Width = listW,
|
||||||
|
Height = 18,
|
||||||
|
Location = new Point(0, y),
|
||||||
|
Font = new Font("Segoe UI", 7.5f, FontStyle.Bold),
|
||||||
|
ForeColor = MutedGray
|
||||||
|
});
|
||||||
|
y += 6;
|
||||||
|
|
||||||
|
// Linha separadora
|
||||||
|
pnlEventList.Controls.Add(new Panel
|
||||||
|
{
|
||||||
|
Location = new Point(0, y + 14),
|
||||||
|
Size = new Size(listW, 1),
|
||||||
|
BackColor = BorderColor
|
||||||
|
});
|
||||||
|
y += 22;
|
||||||
|
|
||||||
|
// ── Vazio ─────────────────────────────────────────────────────────
|
||||||
|
if (!filtrados.Any())
|
||||||
|
{
|
||||||
|
pnlEventList.Controls.Add(new Label
|
||||||
|
{
|
||||||
|
Text = "Nenhum compromisso encontrado.",
|
||||||
|
Location = new Point(0, y + 8),
|
||||||
|
AutoSize = true,
|
||||||
|
Font = new Font("Segoe UI", 8.5f),
|
||||||
|
ForeColor = MutedGray
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ── Cards ─────────────────────────────────────────────────────────
|
||||||
|
foreach (var ev in filtrados)
|
||||||
|
{
|
||||||
|
bool realizado = ev.REALIZADO?.ToUpper() == "S";
|
||||||
|
|
||||||
|
var card = new Panel
|
||||||
|
{
|
||||||
|
Location = new Point(0, y),
|
||||||
|
Width = listW,
|
||||||
|
Height = 72,
|
||||||
|
BackColor = Color.White,
|
||||||
|
BorderStyle = BorderStyle.None,
|
||||||
|
Cursor = Cursors.Hand,
|
||||||
|
Tag = ev
|
||||||
|
};
|
||||||
|
|
||||||
|
// Borda esquerda colorida
|
||||||
|
card.Controls.Add(new Panel
|
||||||
|
{
|
||||||
|
Location = new Point(0, 0),
|
||||||
|
Size = new Size(3, 72),
|
||||||
|
BackColor = realizado ? GreenColor : AmberColor
|
||||||
|
});
|
||||||
|
|
||||||
|
card.Controls.Add(new Label
|
||||||
|
{
|
||||||
|
Text = $"{ev.HORA} — {ev.dDATA}",
|
||||||
|
Location = new Point(10, 5),
|
||||||
|
AutoSize = true,
|
||||||
|
Font = new Font("Segoe UI", 7.5f, FontStyle.Bold),
|
||||||
|
ForeColor = AccentBlue
|
||||||
|
});
|
||||||
|
card.Controls.Add(new Label
|
||||||
|
{
|
||||||
|
Text = ev.COMPROMISSO,
|
||||||
|
Location = new Point(10, 21),
|
||||||
|
AutoSize = true,
|
||||||
|
Font = new Font("Segoe UI", 8.5f, FontStyle.Bold),
|
||||||
|
ForeColor = TextDark
|
||||||
|
});
|
||||||
|
card.Controls.Add(new Label
|
||||||
|
{
|
||||||
|
Text = string.IsNullOrWhiteSpace(ev.FUNC) ? "—" : ev.FUNC,
|
||||||
|
Location = new Point(10, 39),
|
||||||
|
AutoSize = true,
|
||||||
|
Font = new Font("Segoe UI", 8f),
|
||||||
|
ForeColor = MutedGray
|
||||||
|
});
|
||||||
|
card.Controls.Add(new Label
|
||||||
|
{
|
||||||
|
Text = realizado ? "✔ Realizado" : "⏳ Pendente",
|
||||||
|
Location = new Point(10, 55),
|
||||||
|
AutoSize = true,
|
||||||
|
Font = new Font("Segoe UI", 7.5f, FontStyle.Bold),
|
||||||
|
ForeColor = realizado
|
||||||
|
? Color.FromArgb(22, 101, 52)
|
||||||
|
: Color.FromArgb(146, 64, 14)
|
||||||
|
});
|
||||||
|
|
||||||
|
// Borda do card via Paint
|
||||||
|
card.Paint += (_, pe) =>
|
||||||
|
{
|
||||||
|
using var pen = new Pen(BorderColor);
|
||||||
|
pe.Graphics.DrawRectangle(pen, 0, 0, card.Width - 1, card.Height - 1);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Clique em qualquer parte do card (inclusive labels filhos)
|
||||||
|
var evLocal = ev;
|
||||||
|
EventHandler clickHandler = (_, _) => CarregarEvento(evLocal);
|
||||||
|
card.Click += clickHandler;
|
||||||
|
foreach (Control child in card.Controls)
|
||||||
|
child.Click += clickHandler;
|
||||||
|
|
||||||
|
pnlEventList.Controls.Add(card);
|
||||||
|
y += 78;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ══════════════════════════════════════════════════════════════════════
|
||||||
|
// EVENTOS DOS BOTÕES
|
||||||
|
// ══════════════════════════════════════════════════════════════════════
|
||||||
|
private void BtnNovo_Click()
|
||||||
|
{
|
||||||
|
|
||||||
|
LimparCampos();
|
||||||
|
SetCampos(true);
|
||||||
|
txtCriadoEm.Text = DateTime.Now.ToString("dd/MM/yyyy");
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void BtnExcluir_Click()
|
||||||
|
{
|
||||||
|
BLLAgenda _agendaBLL = new BLLAgenda(this._cx);
|
||||||
|
if (string.IsNullOrWhiteSpace(txtId.Text))
|
||||||
|
{
|
||||||
|
NT_MessageBox.Show("Nenhum registro selecionado para excluir.",
|
||||||
|
"Atenção", MessageBoxButtons.OK, MessageBoxIcon.Warning);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var confirm = NT_MessageBox.Show("Confirma a exclusão deste registro?",
|
||||||
|
"Confirmar Exclusão", MessageBoxButtons.YesNo, MessageBoxIcon.Question);
|
||||||
|
|
||||||
|
if (confirm == DialogResult.Yes)
|
||||||
|
{
|
||||||
|
int id = int.Parse(txtId.Text);
|
||||||
|
|
||||||
|
bool sucesso = _agendaBLL.Excluir(id);
|
||||||
|
|
||||||
|
if (!sucesso)
|
||||||
|
{
|
||||||
|
NT_MessageBox.Show("Erro ao excluir o registro.",
|
||||||
|
"Erro", MessageBoxButtons.OK, MessageBoxIcon.Error);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 🔹 Atualiza lista do banco
|
||||||
|
_eventos.Clear();
|
||||||
|
_eventos.AddRange(_agendaBLL.Listar());
|
||||||
|
|
||||||
|
LimparCampos();
|
||||||
|
SetCampos(false);
|
||||||
|
RenderCalendario();
|
||||||
|
RenderListaEventos();
|
||||||
|
|
||||||
|
NT_MessageBox.Show("Registro excluído com sucesso!",
|
||||||
|
"Sucesso", MessageBoxButtons.OK, MessageBoxIcon.Information);
|
||||||
|
}
|
||||||
|
}//Excluir registro selecionado
|
||||||
|
|
||||||
|
private void BtnLocalizar_Click()
|
||||||
|
{
|
||||||
|
FormHelper.Show<AgendaConsultaPanel>("Agenda de Compromissos");
|
||||||
|
}
|
||||||
|
|
||||||
|
private void BtnSalvar_Click()
|
||||||
|
{
|
||||||
|
//if (string.IsNullOrWhiteSpace(txtData.Text) ||
|
||||||
|
// string.IsNullOrWhiteSpace(txtCompromisso.Text))
|
||||||
|
//{
|
||||||
|
// MessageBox.Show("Preencha ao menos Data e Compromisso.",
|
||||||
|
// "Atenção", MessageBoxButtons.OK, MessageBoxIcon.Warning);
|
||||||
|
// return;
|
||||||
|
//}
|
||||||
|
|
||||||
|
//bool isNew = string.IsNullOrWhiteSpace(txtId.Text);
|
||||||
|
//int id = isNew ? _nextId++ : int.Parse(txtId.Text);
|
||||||
|
|
||||||
|
//var agenda = new MLL.ModeloAgenda(
|
||||||
|
// iD_AGENDA: id,
|
||||||
|
// cODIGO: txtCodigo.Text,
|
||||||
|
// cOMPROMISSO: txtCompromisso.Text,
|
||||||
|
// dDATA: txtData.Text,
|
||||||
|
// aVISAR: txtAvisar.Text,
|
||||||
|
// fUNC: txtFunc.Text,
|
||||||
|
// dIA: txtDia.Text,
|
||||||
|
// hORA: txtHora.Text,
|
||||||
|
// rEALIZADO: chkRealizado.Checked ? "S" : "N",
|
||||||
|
// oS_VINC: txtOsVinc.Text
|
||||||
|
//);
|
||||||
|
|
||||||
|
//if (isNew)
|
||||||
|
//{
|
||||||
|
// _eventos.Add(agenda);
|
||||||
|
// txtId.Text = id.ToString();
|
||||||
|
//}
|
||||||
|
//else
|
||||||
|
//{
|
||||||
|
// int idx = _eventos.FindIndex(e => e.ID_AGENDA == id);
|
||||||
|
// if (idx >= 0) _eventos[idx] = agenda;
|
||||||
|
//}
|
||||||
|
|
||||||
|
//txtAtualizadoEm.Text = DateTime.Now.ToString("dd/MM/yyyy");
|
||||||
|
//SetCampos(false);
|
||||||
|
//RenderCalendario();
|
||||||
|
//RenderListaEventos();
|
||||||
|
|
||||||
|
//MessageBox.Show("Registro salvo com sucesso!", "Sucesso",
|
||||||
|
// MessageBoxButtons.OK, MessageBoxIcon.Information);
|
||||||
|
BLLAgenda _agendaBLL = new BLLAgenda(_cx);
|
||||||
|
if (string.IsNullOrWhiteSpace(txtData.Text) ||
|
||||||
|
string.IsNullOrWhiteSpace(txtCompromisso.Text))
|
||||||
|
{
|
||||||
|
MessageBox.Show("Preencha ao menos Data e Compromisso.",
|
||||||
|
"Atenção", MessageBoxButtons.OK, MessageBoxIcon.Warning);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool isNew = string.IsNullOrWhiteSpace(txtId.Text);
|
||||||
|
|
||||||
|
var agenda = new MLL.ModeloAgenda(
|
||||||
|
iD_AGENDA: isNew ? 0 : int.Parse(txtId.Text),
|
||||||
|
cODIGO: txtCodigo.Text,
|
||||||
|
cOMPROMISSO: txtCompromisso.Text,
|
||||||
|
dDATA: txtData.Text,
|
||||||
|
aVISAR: txtAvisar.Text,
|
||||||
|
fUNC: txtFunc.Text,
|
||||||
|
dIA: txtDia.Text,
|
||||||
|
hORA: txtHora.Text,
|
||||||
|
rEALIZADO: chkRealizado.Checked ? "S" : "N",
|
||||||
|
oS_VINC: txtOsVinc.Text
|
||||||
|
);
|
||||||
|
|
||||||
|
bool sucesso;
|
||||||
|
|
||||||
|
if (isNew)
|
||||||
|
{
|
||||||
|
sucesso = _agendaBLL.Inserir(agenda);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
sucesso = _agendaBLL.Alterar(agenda);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!sucesso)
|
||||||
|
{
|
||||||
|
MessageBox.Show("Erro ao salvar no banco de dados.",
|
||||||
|
"Erro", MessageBoxButtons.OK, MessageBoxIcon.Error);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 🔹 Recarrega dados do banco
|
||||||
|
_eventos = _agendaBLL.Listar();
|
||||||
|
|
||||||
|
// 🔹 Atualiza UI
|
||||||
|
txtAtualizadoEm.Text = DateTime.Now.ToString("dd/MM/yyyy");
|
||||||
|
SetCampos(false);
|
||||||
|
RenderCalendario();
|
||||||
|
RenderListaEventos();
|
||||||
|
|
||||||
|
MessageBox.Show("Registro salvo com sucesso!", "Sucesso",
|
||||||
|
MessageBoxButtons.OK, MessageBoxIcon.Information);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void BtnCancelar_Click()
|
||||||
|
{
|
||||||
|
LimparCampos();
|
||||||
|
SetCampos(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ══════════════════════════════════════════════════════════════════════
|
||||||
|
// HELPERS
|
||||||
|
// ══════════════════════════════════════════════════════════════════════
|
||||||
|
private void SetCampos(bool enabled)
|
||||||
|
{
|
||||||
|
var campos = new[] { txtCodigo, txtCompromisso, txtHora, txtFunc, txtAvisar, txtOsVinc };
|
||||||
|
foreach (var c in campos)
|
||||||
|
{
|
||||||
|
c.Enabled = enabled;
|
||||||
|
c.BackColor = enabled ? Color.White : DisabledBack;
|
||||||
|
}
|
||||||
|
chkRealizado.Enabled = enabled;
|
||||||
|
txtData.BackColor = enabled ? Color.FromArgb(239, 246, 255) : DisabledBack;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void LimparCampos()
|
||||||
|
{
|
||||||
|
txtId.Text = txtCodigo.Text = txtCompromisso.Text = string.Empty;
|
||||||
|
txtData.Text = txtDia.Text = txtHora.Text = string.Empty;
|
||||||
|
txtFunc.Text = txtAvisar.Text = txtOsVinc.Text = string.Empty;
|
||||||
|
txtCriadoEm.Text = txtAtualizadoEm.Text = string.Empty;
|
||||||
|
chkRealizado.Checked = false;
|
||||||
|
_selectedDate = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void CarregarEvento(MLL.ModeloAgenda ev)
|
||||||
|
{
|
||||||
|
txtId.Text = ev.ID_AGENDA.ToString();
|
||||||
|
txtCodigo.Text = ev.CODIGO;
|
||||||
|
txtCompromisso.Text = ev.COMPROMISSO;
|
||||||
|
txtData.Text = ev.dDATA;
|
||||||
|
txtDia.Text = ev.DIA;
|
||||||
|
txtHora.Text = ev.HORA;
|
||||||
|
txtFunc.Text = ev.FUNC;
|
||||||
|
txtAvisar.Text = ev.AVISAR;
|
||||||
|
txtOsVinc.Text = ev.OS_VINC;
|
||||||
|
txtCriadoEm.Text = ev.dDATA;
|
||||||
|
txtAtualizadoEm.Text = DateTime.Now.ToString("dd/MM/yyyy");
|
||||||
|
chkRealizado.Checked = ev.REALIZADO?.ToUpper() == "S";
|
||||||
|
|
||||||
|
var dt = ParseData(ev.dDATA);
|
||||||
|
if (dt != DateTime.MinValue)
|
||||||
|
{
|
||||||
|
_selectedDate = dt;
|
||||||
|
_currentMonth = new DateTime(dt.Year, dt.Month, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
SetCampos(false);
|
||||||
|
RenderCalendario();
|
||||||
|
RenderListaEventos();
|
||||||
|
}
|
||||||
|
|
||||||
|
private HashSet<DateTime> GetDatesWithEvents()
|
||||||
|
{
|
||||||
|
var set = new HashSet<DateTime>();
|
||||||
|
foreach (var ev in _eventos)
|
||||||
|
{
|
||||||
|
var dt = ParseData(ev.dDATA);
|
||||||
|
if (dt != DateTime.MinValue) set.Add(dt.Date);
|
||||||
|
}
|
||||||
|
return set;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static DateTime ParseData(string? value)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrWhiteSpace(value)) return DateTime.MinValue;
|
||||||
|
if (DateTime.TryParseExact(value, "dd/MM/yyyy",
|
||||||
|
System.Globalization.CultureInfo.InvariantCulture,
|
||||||
|
System.Globalization.DateTimeStyles.None, out var dt))
|
||||||
|
return dt;
|
||||||
|
if (DateTime.TryParse(value, out dt)) return dt;
|
||||||
|
return DateTime.MinValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void CarregarDadosFake()
|
||||||
|
{
|
||||||
|
var hoje = DateTime.Today;
|
||||||
|
_eventos.AddRange(new[]
|
||||||
|
{
|
||||||
|
new MLL.ModeloAgenda(1, "AG001", "Reunião com cliente",
|
||||||
|
hoje.ToString("dd/MM/yyyy"), "30 minutos antes",
|
||||||
|
"Carlos Silva", DiaSemana(hoje), "09:00", "S", "OS-1042"),
|
||||||
|
|
||||||
|
new MLL.ModeloAgenda(2, "AG002", "Visita técnica",
|
||||||
|
hoje.ToString("dd/MM/yyyy"), "1 hora antes",
|
||||||
|
"Ana Souza", DiaSemana(hoje), "14:00", "N", "OS-1055"),
|
||||||
|
|
||||||
|
new MLL.ModeloAgenda(3, "AG003", "Entrega de equipamento",
|
||||||
|
hoje.AddDays(4).ToString("dd/MM/yyyy"), "1 dia antes",
|
||||||
|
"Pedro Lima", DiaSemana(hoje.AddDays(4)), "10:30", "N", ""),
|
||||||
|
});
|
||||||
|
_nextId = 4;
|
||||||
|
}//Carregar dados fake (Não usa mais)
|
||||||
|
private void CarregarDadosDoBanco()
|
||||||
|
{
|
||||||
|
BLLAgenda _agendaBLL = new BLLAgenda(_cx);
|
||||||
|
_eventos.Clear();
|
||||||
|
_eventos.AddRange(_agendaBLL.Listar());
|
||||||
|
}// Método auxiliar para obter os dados da agenda no banco de dados e preencher a lista de eventos.
|
||||||
|
|
||||||
|
private static string DiaSemana(DateTime d) =>
|
||||||
|
new System.Globalization.CultureInfo("pt-BR").DateTimeFormat.GetDayName(d.DayOfWeek);
|
||||||
|
|
||||||
|
// ── UI HELPERS ────────────────────────────────────────────────────────
|
||||||
|
private Panel CreateSectionHeader(string title, int y)
|
||||||
|
{
|
||||||
|
var pnl = new Panel { Location = new Point(20, y), Width = 760, Height = 26 };
|
||||||
|
pnl.Controls.Add(new Label
|
||||||
|
{
|
||||||
|
Text = title,
|
||||||
|
Font = new Font("Segoe UI", 8.5f, FontStyle.Bold),
|
||||||
|
ForeColor = AccentBlue,
|
||||||
|
AutoSize = true,
|
||||||
|
Location = new Point(0, 0)
|
||||||
|
});
|
||||||
|
pnl.Controls.Add(new Panel
|
||||||
|
{
|
||||||
|
BackColor = BorderColor,
|
||||||
|
Height = 1,
|
||||||
|
Width = 740,
|
||||||
|
Location = new Point(0, 20)
|
||||||
|
});
|
||||||
|
return pnl;
|
||||||
|
}
|
||||||
|
|
||||||
|
private RoundTextBox AddInput(Control parent, string label,
|
||||||
|
int x, int y, int width, int height,
|
||||||
|
bool readOnly = false)
|
||||||
|
{
|
||||||
|
parent.Controls.Add(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 ? DisabledBack : Color.White
|
||||||
|
};
|
||||||
|
parent.Controls.Add(txt);
|
||||||
|
return txt;
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
120
Dashboards/Cadastros/AgendaCadastroPanel.resx
Normal file
120
Dashboards/Cadastros/AgendaCadastroPanel.resx
Normal file
@ -0,0 +1,120 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<root>
|
||||||
|
<!--
|
||||||
|
Microsoft ResX Schema
|
||||||
|
|
||||||
|
Version 2.0
|
||||||
|
|
||||||
|
The primary goals of this format is to allow a simple XML format
|
||||||
|
that is mostly human readable. The generation and parsing of the
|
||||||
|
various data types are done through the TypeConverter classes
|
||||||
|
associated with the data types.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
... ado.net/XML headers & schema ...
|
||||||
|
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||||
|
<resheader name="version">2.0</resheader>
|
||||||
|
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||||
|
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||||
|
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
||||||
|
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||||
|
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||||
|
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
||||||
|
</data>
|
||||||
|
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||||
|
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||||
|
<comment>This is a comment</comment>
|
||||||
|
</data>
|
||||||
|
|
||||||
|
There are any number of "resheader" rows that contain simple
|
||||||
|
name/value pairs.
|
||||||
|
|
||||||
|
Each data row contains a name, and value. The row also contains a
|
||||||
|
type or mimetype. Type corresponds to a .NET class that support
|
||||||
|
text/value conversion through the TypeConverter architecture.
|
||||||
|
Classes that don't support this are serialized and stored with the
|
||||||
|
mimetype set.
|
||||||
|
|
||||||
|
The mimetype is used for serialized objects, and tells the
|
||||||
|
ResXResourceReader how to depersist the object. This is currently not
|
||||||
|
extensible. For a given mimetype the value must be set accordingly:
|
||||||
|
|
||||||
|
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||||
|
that the ResXResourceWriter will generate, however the reader can
|
||||||
|
read any of the formats listed below.
|
||||||
|
|
||||||
|
mimetype: application/x-microsoft.net.object.binary.base64
|
||||||
|
value : The object must be serialized with
|
||||||
|
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
|
||||||
|
: and then encoded with base64 encoding.
|
||||||
|
|
||||||
|
mimetype: application/x-microsoft.net.object.soap.base64
|
||||||
|
value : The object must be serialized with
|
||||||
|
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||||
|
: and then encoded with base64 encoding.
|
||||||
|
|
||||||
|
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||||
|
value : The object must be serialized into a byte array
|
||||||
|
: using a System.ComponentModel.TypeConverter
|
||||||
|
: and then encoded with base64 encoding.
|
||||||
|
-->
|
||||||
|
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||||
|
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
||||||
|
<xsd:element name="root" msdata:IsDataSet="true">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:choice maxOccurs="unbounded">
|
||||||
|
<xsd:element name="metadata">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:sequence>
|
||||||
|
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||||
|
</xsd:sequence>
|
||||||
|
<xsd:attribute name="name" use="required" type="xsd:string" />
|
||||||
|
<xsd:attribute name="type" type="xsd:string" />
|
||||||
|
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||||
|
<xsd:attribute ref="xml:space" />
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
<xsd:element name="assembly">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:attribute name="alias" type="xsd:string" />
|
||||||
|
<xsd:attribute name="name" type="xsd:string" />
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
<xsd:element name="data">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:sequence>
|
||||||
|
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||||
|
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||||
|
</xsd:sequence>
|
||||||
|
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
|
||||||
|
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||||
|
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||||
|
<xsd:attribute ref="xml:space" />
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
<xsd:element name="resheader">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:sequence>
|
||||||
|
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||||
|
</xsd:sequence>
|
||||||
|
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
</xsd:choice>
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
</xsd:schema>
|
||||||
|
<resheader name="resmimetype">
|
||||||
|
<value>text/microsoft-resx</value>
|
||||||
|
</resheader>
|
||||||
|
<resheader name="version">
|
||||||
|
<value>2.0</value>
|
||||||
|
</resheader>
|
||||||
|
<resheader name="reader">
|
||||||
|
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||||
|
</resheader>
|
||||||
|
<resheader name="writer">
|
||||||
|
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||||
|
</resheader>
|
||||||
|
</root>
|
||||||
530
Dashboards/Cadastros/ClienteCadastroPanel.cs
Normal file
530
Dashboards/Cadastros/ClienteCadastroPanel.cs
Normal file
@ -0,0 +1,530 @@
|
|||||||
|
using BLL;
|
||||||
|
using CustomMessageBox;
|
||||||
|
using DAL;
|
||||||
|
using System.Drawing;
|
||||||
|
using System.Windows.Forms;
|
||||||
|
|
||||||
|
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
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
120
Dashboards/Cadastros/ClienteCadastroPanel.resx
Normal file
120
Dashboards/Cadastros/ClienteCadastroPanel.resx
Normal file
@ -0,0 +1,120 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<root>
|
||||||
|
<!--
|
||||||
|
Microsoft ResX Schema
|
||||||
|
|
||||||
|
Version 2.0
|
||||||
|
|
||||||
|
The primary goals of this format is to allow a simple XML format
|
||||||
|
that is mostly human readable. The generation and parsing of the
|
||||||
|
various data types are done through the TypeConverter classes
|
||||||
|
associated with the data types.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
... ado.net/XML headers & schema ...
|
||||||
|
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||||
|
<resheader name="version">2.0</resheader>
|
||||||
|
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||||
|
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||||
|
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
||||||
|
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||||
|
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||||
|
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
||||||
|
</data>
|
||||||
|
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||||
|
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||||
|
<comment>This is a comment</comment>
|
||||||
|
</data>
|
||||||
|
|
||||||
|
There are any number of "resheader" rows that contain simple
|
||||||
|
name/value pairs.
|
||||||
|
|
||||||
|
Each data row contains a name, and value. The row also contains a
|
||||||
|
type or mimetype. Type corresponds to a .NET class that support
|
||||||
|
text/value conversion through the TypeConverter architecture.
|
||||||
|
Classes that don't support this are serialized and stored with the
|
||||||
|
mimetype set.
|
||||||
|
|
||||||
|
The mimetype is used for serialized objects, and tells the
|
||||||
|
ResXResourceReader how to depersist the object. This is currently not
|
||||||
|
extensible. For a given mimetype the value must be set accordingly:
|
||||||
|
|
||||||
|
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||||
|
that the ResXResourceWriter will generate, however the reader can
|
||||||
|
read any of the formats listed below.
|
||||||
|
|
||||||
|
mimetype: application/x-microsoft.net.object.binary.base64
|
||||||
|
value : The object must be serialized with
|
||||||
|
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
|
||||||
|
: and then encoded with base64 encoding.
|
||||||
|
|
||||||
|
mimetype: application/x-microsoft.net.object.soap.base64
|
||||||
|
value : The object must be serialized with
|
||||||
|
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||||
|
: and then encoded with base64 encoding.
|
||||||
|
|
||||||
|
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||||
|
value : The object must be serialized into a byte array
|
||||||
|
: using a System.ComponentModel.TypeConverter
|
||||||
|
: and then encoded with base64 encoding.
|
||||||
|
-->
|
||||||
|
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||||
|
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
||||||
|
<xsd:element name="root" msdata:IsDataSet="true">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:choice maxOccurs="unbounded">
|
||||||
|
<xsd:element name="metadata">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:sequence>
|
||||||
|
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||||
|
</xsd:sequence>
|
||||||
|
<xsd:attribute name="name" use="required" type="xsd:string" />
|
||||||
|
<xsd:attribute name="type" type="xsd:string" />
|
||||||
|
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||||
|
<xsd:attribute ref="xml:space" />
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
<xsd:element name="assembly">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:attribute name="alias" type="xsd:string" />
|
||||||
|
<xsd:attribute name="name" type="xsd:string" />
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
<xsd:element name="data">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:sequence>
|
||||||
|
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||||
|
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||||
|
</xsd:sequence>
|
||||||
|
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
|
||||||
|
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||||
|
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||||
|
<xsd:attribute ref="xml:space" />
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
<xsd:element name="resheader">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:sequence>
|
||||||
|
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||||
|
</xsd:sequence>
|
||||||
|
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
</xsd:choice>
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
</xsd:schema>
|
||||||
|
<resheader name="resmimetype">
|
||||||
|
<value>text/microsoft-resx</value>
|
||||||
|
</resheader>
|
||||||
|
<resheader name="version">
|
||||||
|
<value>2.0</value>
|
||||||
|
</resheader>
|
||||||
|
<resheader name="reader">
|
||||||
|
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||||
|
</resheader>
|
||||||
|
<resheader name="writer">
|
||||||
|
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||||
|
</resheader>
|
||||||
|
</root>
|
||||||
526
Dashboards/Cadastros/EmpresaCadastroPanel.cs
Normal file
526
Dashboards/Cadastros/EmpresaCadastroPanel.cs
Normal file
@ -0,0 +1,526 @@
|
|||||||
|
using BLL;
|
||||||
|
using CustomMessageBox;
|
||||||
|
using DAL;
|
||||||
|
using MLL;
|
||||||
|
using System.Drawing;
|
||||||
|
using System.Windows.Forms;
|
||||||
|
|
||||||
|
namespace UI
|
||||||
|
{
|
||||||
|
public class EmpresaCadastroPanel : UserControl
|
||||||
|
{
|
||||||
|
private string _cx = 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!, txtNome = null!, txtCNPJ = null!;
|
||||||
|
private RoundTextBox txtTipoEmpresa = null!, txtRegimeTributario = null!, txtCNAE = null!;
|
||||||
|
|
||||||
|
// Endereço
|
||||||
|
private RoundTextBox txtCep = null!, txtEndereco = null!, txtNumero = null!, txtComplemento = null!;
|
||||||
|
private RoundTextBox txtBairro = null!, txtCidade = null!, txtUF = null!, txtPais = null!;
|
||||||
|
|
||||||
|
// Contatos
|
||||||
|
private RoundTextBox txtTelefone1 = null!, txtTelefone2 = null!, txtCelular = null!, txtWhatsapp = null!;
|
||||||
|
private RoundTextBox txtEmail = null!, txtSite = null!;
|
||||||
|
|
||||||
|
// Fiscal
|
||||||
|
private RoundTextBox txtInscricaoEstadual = null!, txtInscricaoMunicipal = null!;
|
||||||
|
|
||||||
|
// Contador
|
||||||
|
private RoundTextBox txtCNPJCPF_Contador = null!, txtNome_Contador = null!;
|
||||||
|
|
||||||
|
// Outros
|
||||||
|
private RoundTextBox txtTextoParaRecibo = null!;
|
||||||
|
private CheckBox chkAtivo = null!;
|
||||||
|
|
||||||
|
// Info (readonly)
|
||||||
|
private RoundTextBox txtCriadoEm = null!, txtAtualizadoEm = null!;
|
||||||
|
|
||||||
|
//Carregar dados da empresa atual, se houver no banco de dados
|
||||||
|
private void CarregarEmpresaAtiva()
|
||||||
|
{
|
||||||
|
var bll = new BLLEmpresa(_cx);
|
||||||
|
var empresa = bll.CarregarEmpresaAtiva();
|
||||||
|
|
||||||
|
if (empresa == null)
|
||||||
|
{
|
||||||
|
MessageBox.Show("Nenhuma empresa ativa encontrada.",
|
||||||
|
"Atenção", MessageBoxButtons.OK, MessageBoxIcon.Warning);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Preenche todos os campos do formulário
|
||||||
|
txtId.Text = empresa.Id.ToString();
|
||||||
|
txtNome.Text = empresa.Nome;
|
||||||
|
txtCNPJ.Text = empresa.CNPJ;
|
||||||
|
txtTipoEmpresa.Text = empresa.TipoEmpresa;
|
||||||
|
txtRegimeTributario.Text = empresa.RegimeTributario;
|
||||||
|
txtCNAE.Text = empresa.CNAE;
|
||||||
|
txtInscricaoEstadual.Text = empresa.InscricaoEstadual;
|
||||||
|
txtInscricaoMunicipal.Text = empresa.InscricaoMunicipal;
|
||||||
|
txtCep.Text = empresa.Cep;
|
||||||
|
txtEndereco.Text = empresa.Endereco;
|
||||||
|
txtNumero.Text = empresa.Numero.ToString();
|
||||||
|
txtComplemento.Text = empresa.Complemento;
|
||||||
|
txtBairro.Text = empresa.Bairro;
|
||||||
|
txtCidade.Text = empresa.Cidade;
|
||||||
|
txtUF.Text = empresa.UF;
|
||||||
|
txtPais.Text = empresa.Pais;
|
||||||
|
txtTelefone1.Text = empresa.Telefone1;
|
||||||
|
txtTelefone2.Text = empresa.Telefone2;
|
||||||
|
txtCelular.Text = empresa.Celular;
|
||||||
|
txtWhatsapp.Text = empresa.Whatsapp;
|
||||||
|
txtEmail.Text = empresa.Email;
|
||||||
|
txtSite.Text = empresa.Site;
|
||||||
|
txtCNPJCPF_Contador.Text = empresa.CNPJCPF_Contador;
|
||||||
|
txtNome_Contador.Text = empresa.Nome_Contador;
|
||||||
|
txtTextoParaRecibo.Text = empresa.TextoParaRecibo;
|
||||||
|
chkAtivo.Checked = empresa.Ativo;
|
||||||
|
txtCriadoEm.Text = empresa.CriadoEm.ToString("dd/MM/yyyy");
|
||||||
|
txtAtualizadoEm.Text = empresa.AtualizadoEm.ToString("dd/MM/yyyy");
|
||||||
|
}
|
||||||
|
public EmpresaCadastroPanel()
|
||||||
|
{
|
||||||
|
Dock = DockStyle.Fill;
|
||||||
|
BackColor = Color.White;
|
||||||
|
DoubleBuffered = true;
|
||||||
|
InitializeLayout();
|
||||||
|
// Carregar dados da empresa atual, se houver
|
||||||
|
CarregarEmpresaAtiva();
|
||||||
|
}
|
||||||
|
|
||||||
|
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));
|
||||||
|
var btnCriarCert = CreateToolbarButton("Certificado", Color.FromArgb(148, 160, 184));
|
||||||
|
var btnGerarFichaPDF = CreateToolbarButton("Ficha Tecnica", Color.FromArgb(255, 0, 0));
|
||||||
|
|
||||||
|
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();
|
||||||
|
btnCriarCert.Click += (s, e) => BtnGerarCertificado_Click();
|
||||||
|
btnGerarFichaPDF.Click += (s, e) => BtnFicha_Click();
|
||||||
|
|
||||||
|
flowButtons.Controls.AddRange(new Control[]
|
||||||
|
{ btnNovo, btnAlterar, btnExcluir, btnLocalizar, btnSalvar, btnCancelar,btnCriarCert,btnGerarFichaPDF });
|
||||||
|
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 DA EMPRESA ───────────────────────────────────
|
||||||
|
content.Controls.Add(CreateSectionHeader("IDENTIFICAÇÃO DA EMPRESA", y));
|
||||||
|
y += secH + 4;
|
||||||
|
|
||||||
|
txtId = AddInput(content, "ID", 20, y, 60, inputH, readOnly: true);
|
||||||
|
txtNome = AddInput(content, "Nome / Razão Social", 90, y, 450, inputH);
|
||||||
|
txtCNPJ = AddInput(content, "CNPJ", 550, y, 180, inputH);
|
||||||
|
DocumentoHelper.Registrar(txtCNPJ);
|
||||||
|
txtTipoEmpresa = AddInput(content, "Tipo Empresa", 740, y, 200, inputH);
|
||||||
|
y += rowH;
|
||||||
|
|
||||||
|
txtRegimeTributario = AddInput(content, "Regime Tributário", 20, y, 200, inputH);
|
||||||
|
txtCNAE = AddInput(content, "CNAE", 230, y, 150, inputH);
|
||||||
|
txtInscricaoEstadual = AddInput(content, "Inscrição Estadual", 390, y, 200, inputH);
|
||||||
|
txtInscricaoMunicipal = AddInput(content, "Inscrição Municipal", 600, y, 200, inputH);
|
||||||
|
|
||||||
|
// ── 2. ENDEREÇO COMPLETO ──────────────────────────────────────────
|
||||||
|
y += rowH + secGap;
|
||||||
|
content.Controls.Add(CreateSectionHeader("ENDEREÇO COMPLETO", y));
|
||||||
|
y += secH + 4;
|
||||||
|
|
||||||
|
txtCep = AddInput(content, "CEP", 20, y, 95, inputH);
|
||||||
|
// No InitializeLayout(), após criar o txtCep
|
||||||
|
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;
|
||||||
|
txtPais.Text = "Brasil";
|
||||||
|
|
||||||
|
// 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);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
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);
|
||||||
|
|
||||||
|
// ── 3. CONTATOS E COMUNICAÇÃO ─────────────────────────────────────
|
||||||
|
y += rowH + secGap;
|
||||||
|
content.Controls.Add(CreateSectionHeader("CONTATOS E COMUNICAÇÃO", y));
|
||||||
|
y += secH + 4;
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
txtEmail = AddInput(content, "E-mail", 20, y, 350, inputH);
|
||||||
|
txtSite = AddInput(content, "Site", 380, y, 290, inputH);
|
||||||
|
|
||||||
|
// ── 4. DADOS DO CONTADOR ──────────────────────────────────────────
|
||||||
|
y += rowH + secGap;
|
||||||
|
content.Controls.Add(CreateSectionHeader("DADOS DO CONTADOR", y));
|
||||||
|
y += secH + 4;
|
||||||
|
|
||||||
|
txtCNPJCPF_Contador = AddInput(content, "CPF/CNPJ do Contador", 20, y, 200, inputH);
|
||||||
|
DocumentoHelper.Registrar(txtCNPJCPF_Contador);
|
||||||
|
txtNome_Contador = AddInput(content, "Nome do Contador", 230, y, 400, inputH);
|
||||||
|
|
||||||
|
// ── 5. OUTROS ─────────────────────────────────────────────────────
|
||||||
|
y += rowH + secGap;
|
||||||
|
content.Controls.Add(CreateSectionHeader("OUTROS", y));
|
||||||
|
y += secH + 4;
|
||||||
|
|
||||||
|
txtTextoParaRecibo = AddInput(content, "Texto para Recibo", 20, y, 920, inputH);
|
||||||
|
y += rowH;
|
||||||
|
txtTextoParaRecibo.Multiline = true;
|
||||||
|
|
||||||
|
|
||||||
|
chkAtivo = CreateCheckBox("Ativo", 20, y);
|
||||||
|
content.Controls.Add(chkAtivo);
|
||||||
|
|
||||||
|
// ── 6. INFORMAÇÕES DO REGISTRO ────────────────────────────────────
|
||||||
|
y += 35 + secGap;
|
||||||
|
content.Controls.Add(CreateSectionHeader("INFORMAÇÕES DO REGISTRO", y));
|
||||||
|
y += secH + 4;
|
||||||
|
|
||||||
|
txtCriadoEm = AddInput(content, "Criado Em", 20, y, 175, inputH, readOnly: true);
|
||||||
|
txtAtualizadoEm = AddInput(content, "Atualizado Em", 205, y, 175, inputH, readOnly: true);
|
||||||
|
y += rowH;
|
||||||
|
|
||||||
|
content.Height = y + 10;
|
||||||
|
|
||||||
|
SetCampos(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ── CAMPOS ────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
private RoundTextBox[] TodosOsCampos() => new[]
|
||||||
|
{
|
||||||
|
txtNome, txtCNPJ, txtTipoEmpresa, txtRegimeTributario, txtCNAE,
|
||||||
|
txtInscricaoEstadual, txtInscricaoMunicipal,
|
||||||
|
txtCep, txtEndereco, txtNumero, txtComplemento,
|
||||||
|
txtBairro, txtCidade, txtUF, txtPais,
|
||||||
|
txtTelefone1, txtTelefone2, txtCelular, txtWhatsapp,
|
||||||
|
txtEmail, txtSite,
|
||||||
|
txtCNPJCPF_Contador, txtNome_Contador,
|
||||||
|
txtTextoParaRecibo
|
||||||
|
};
|
||||||
|
|
||||||
|
private void SetCampos(bool enabled)
|
||||||
|
{
|
||||||
|
foreach (var campo in TodosOsCampos())
|
||||||
|
{
|
||||||
|
campo.Enabled = enabled;
|
||||||
|
campo.BackColor = enabled ? Color.White : Color.FromArgb(241, 245, 249);
|
||||||
|
}
|
||||||
|
chkAtivo.Enabled = enabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ── EVENTOS ───────────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
private void BtnNovo_Click()
|
||||||
|
{
|
||||||
|
foreach (var campo in TodosOsCampos())
|
||||||
|
campo.Text = string.Empty;
|
||||||
|
|
||||||
|
chkAtivo.Checked = true;
|
||||||
|
SetCampos(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
// Evento
|
||||||
|
private void BtnFicha_Click()
|
||||||
|
{
|
||||||
|
var bll = new BLLEmpresa(_cx);
|
||||||
|
var empresa = bll.CarregarEmpresaAtiva();
|
||||||
|
|
||||||
|
if (empresa == null)
|
||||||
|
{
|
||||||
|
MessageBox.Show("Nenhuma empresa ativa encontrada.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var resultado = TLL.FichaEmpresaPDF.GerarEAbrir(empresa);
|
||||||
|
|
||||||
|
if (!resultado.Sucesso)
|
||||||
|
MessageBox.Show(resultado.Mensagem, "Erro",
|
||||||
|
MessageBoxButtons.OK, MessageBoxIcon.Error);
|
||||||
|
}
|
||||||
|
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 BtnGerarCertificado_Click()
|
||||||
|
{
|
||||||
|
ModeloEmpresa empresa = new ModeloEmpresa();
|
||||||
|
// Após salvar a empresa com sucesso...
|
||||||
|
var resultado = TLL.CertificadoHelper.Gerar(empresa, "Nike12122020*##");
|
||||||
|
|
||||||
|
if (resultado.Sucesso)
|
||||||
|
NT_MessageBox.Show(
|
||||||
|
$"Certificado gerado!\nVálido até: {resultado.ValidoAte:dd/MM/yyyy}\n" +
|
||||||
|
$"Thumbprint: {resultado.Thumbprint}",
|
||||||
|
"Certificado", MessageBoxButtons.OK, MessageBoxIcon.Information);
|
||||||
|
else
|
||||||
|
NT_MessageBox.Show(resultado.Mensagem, "Erro",
|
||||||
|
MessageBoxButtons.OK, MessageBoxIcon.Error);
|
||||||
|
}
|
||||||
|
private void BtnVerificarCert_Click()
|
||||||
|
{
|
||||||
|
ModeloEmpresa empresa = new ModeloEmpresa();
|
||||||
|
var status = TLL.CertificadoHelper.VerificarStatus(empresa.CNPJ, "Nike12122020*##");
|
||||||
|
|
||||||
|
if (!status.Valido)
|
||||||
|
NT_MessageBox.Show("Certificado expirado! Gere um novo.",
|
||||||
|
"Atenção", MessageBoxButtons.OK, MessageBoxIcon.Warning);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void BtnSalvar_Click()
|
||||||
|
{
|
||||||
|
BLLEmpresa _empresaBLL = new BLLEmpresa(_cx);
|
||||||
|
|
||||||
|
if (string.IsNullOrWhiteSpace(txtNome.Text) ||
|
||||||
|
string.IsNullOrWhiteSpace(txtCNPJ.Text) ||
|
||||||
|
string.IsNullOrWhiteSpace(txtEmail.Text))
|
||||||
|
{
|
||||||
|
NT_MessageBox.Show("Preencha ao menos Nome, CNPJ e Email.",
|
||||||
|
"Atenção", MessageBoxButtons.OK, MessageBoxIcon.Warning);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool isNew = string.IsNullOrWhiteSpace(txtId.Text);
|
||||||
|
|
||||||
|
var empresa = new MLL.ModeloEmpresa(
|
||||||
|
id: isNew ? 0 : int.Parse(txtId.Text),
|
||||||
|
nome: txtNome.Text,
|
||||||
|
cNPJ: txtCNPJ.Text,
|
||||||
|
tipoEmpresa: txtTipoEmpresa.Text,
|
||||||
|
regimeTributario: txtRegimeTributario.Text,
|
||||||
|
cNAE: txtCNAE.Text,
|
||||||
|
cep: txtCep.Text,
|
||||||
|
endereco: txtEndereco.Text,
|
||||||
|
numero: string.IsNullOrWhiteSpace(txtNumero.Text) ? 0 : int.Parse(txtNumero.Text),
|
||||||
|
complemento: txtComplemento.Text,
|
||||||
|
bairro: txtBairro.Text,
|
||||||
|
cidade: txtCidade.Text,
|
||||||
|
uF: txtUF.Text,
|
||||||
|
pais: txtPais.Text,
|
||||||
|
telefone1: txtTelefone1.Text,
|
||||||
|
telefone2: txtTelefone2.Text,
|
||||||
|
celular: txtCelular.Text,
|
||||||
|
whatsapp: txtWhatsapp.Text,
|
||||||
|
email: txtEmail.Text,
|
||||||
|
site: txtSite.Text,
|
||||||
|
inscricaoEstadual: txtInscricaoEstadual.Text,
|
||||||
|
inscricaoMunicipal: txtInscricaoMunicipal.Text,
|
||||||
|
cNPJCPF_Contador: txtCNPJCPF_Contador.Text,
|
||||||
|
nome_Contador: txtNome_Contador.Text,
|
||||||
|
textoParaRecibo: txtTextoParaRecibo.Text,
|
||||||
|
ativo: chkAtivo.Checked,
|
||||||
|
criadoEm: DateTime.Now,
|
||||||
|
atualizadoEm: DateTime.Now
|
||||||
|
);
|
||||||
|
|
||||||
|
bool sucesso;
|
||||||
|
|
||||||
|
if (isNew)
|
||||||
|
sucesso = _empresaBLL.Inserir(empresa);
|
||||||
|
else
|
||||||
|
sucesso = _empresaBLL.Alterar(empresa);
|
||||||
|
|
||||||
|
if (!sucesso)
|
||||||
|
{
|
||||||
|
NT_MessageBox.Show("Erro ao salvar empresa.",
|
||||||
|
"Erro", MessageBoxButtons.OK, MessageBoxIcon.Error);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 🔹 Atualiza UI
|
||||||
|
txtAtualizadoEm.Text = DateTime.Now.ToString("dd/MM/yyyy");
|
||||||
|
SetCampos(false);
|
||||||
|
|
||||||
|
NT_MessageBox.Show("Empresa salva com sucesso!", "Sucesso",
|
||||||
|
MessageBoxButtons.OK, MessageBoxIcon.Information);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void BtnCancelar_Click()
|
||||||
|
{
|
||||||
|
foreach (var campo in TodosOsCampos())
|
||||||
|
campo.Text = string.Empty;
|
||||||
|
|
||||||
|
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
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
120
Dashboards/Cadastros/EmpresaCadastroPanel.resx
Normal file
120
Dashboards/Cadastros/EmpresaCadastroPanel.resx
Normal file
@ -0,0 +1,120 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<root>
|
||||||
|
<!--
|
||||||
|
Microsoft ResX Schema
|
||||||
|
|
||||||
|
Version 2.0
|
||||||
|
|
||||||
|
The primary goals of this format is to allow a simple XML format
|
||||||
|
that is mostly human readable. The generation and parsing of the
|
||||||
|
various data types are done through the TypeConverter classes
|
||||||
|
associated with the data types.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
... ado.net/XML headers & schema ...
|
||||||
|
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||||
|
<resheader name="version">2.0</resheader>
|
||||||
|
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||||
|
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||||
|
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
||||||
|
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||||
|
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||||
|
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
||||||
|
</data>
|
||||||
|
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||||
|
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||||
|
<comment>This is a comment</comment>
|
||||||
|
</data>
|
||||||
|
|
||||||
|
There are any number of "resheader" rows that contain simple
|
||||||
|
name/value pairs.
|
||||||
|
|
||||||
|
Each data row contains a name, and value. The row also contains a
|
||||||
|
type or mimetype. Type corresponds to a .NET class that support
|
||||||
|
text/value conversion through the TypeConverter architecture.
|
||||||
|
Classes that don't support this are serialized and stored with the
|
||||||
|
mimetype set.
|
||||||
|
|
||||||
|
The mimetype is used for serialized objects, and tells the
|
||||||
|
ResXResourceReader how to depersist the object. This is currently not
|
||||||
|
extensible. For a given mimetype the value must be set accordingly:
|
||||||
|
|
||||||
|
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||||
|
that the ResXResourceWriter will generate, however the reader can
|
||||||
|
read any of the formats listed below.
|
||||||
|
|
||||||
|
mimetype: application/x-microsoft.net.object.binary.base64
|
||||||
|
value : The object must be serialized with
|
||||||
|
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
|
||||||
|
: and then encoded with base64 encoding.
|
||||||
|
|
||||||
|
mimetype: application/x-microsoft.net.object.soap.base64
|
||||||
|
value : The object must be serialized with
|
||||||
|
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||||
|
: and then encoded with base64 encoding.
|
||||||
|
|
||||||
|
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||||
|
value : The object must be serialized into a byte array
|
||||||
|
: using a System.ComponentModel.TypeConverter
|
||||||
|
: and then encoded with base64 encoding.
|
||||||
|
-->
|
||||||
|
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||||
|
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
||||||
|
<xsd:element name="root" msdata:IsDataSet="true">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:choice maxOccurs="unbounded">
|
||||||
|
<xsd:element name="metadata">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:sequence>
|
||||||
|
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||||
|
</xsd:sequence>
|
||||||
|
<xsd:attribute name="name" use="required" type="xsd:string" />
|
||||||
|
<xsd:attribute name="type" type="xsd:string" />
|
||||||
|
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||||
|
<xsd:attribute ref="xml:space" />
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
<xsd:element name="assembly">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:attribute name="alias" type="xsd:string" />
|
||||||
|
<xsd:attribute name="name" type="xsd:string" />
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
<xsd:element name="data">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:sequence>
|
||||||
|
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||||
|
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||||
|
</xsd:sequence>
|
||||||
|
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
|
||||||
|
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||||
|
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||||
|
<xsd:attribute ref="xml:space" />
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
<xsd:element name="resheader">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:sequence>
|
||||||
|
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||||
|
</xsd:sequence>
|
||||||
|
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
</xsd:choice>
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
</xsd:schema>
|
||||||
|
<resheader name="resmimetype">
|
||||||
|
<value>text/microsoft-resx</value>
|
||||||
|
</resheader>
|
||||||
|
<resheader name="version">
|
||||||
|
<value>2.0</value>
|
||||||
|
</resheader>
|
||||||
|
<resheader name="reader">
|
||||||
|
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||||
|
</resheader>
|
||||||
|
<resheader name="writer">
|
||||||
|
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||||
|
</resheader>
|
||||||
|
</root>
|
||||||
591
Dashboards/Cadastros/EmpresaConfiguracoesPanel.cs
Normal file
591
Dashboards/Cadastros/EmpresaConfiguracoesPanel.cs
Normal file
@ -0,0 +1,591 @@
|
|||||||
|
using BLL;
|
||||||
|
using CCH;
|
||||||
|
using CustomMessageBox;
|
||||||
|
using DAL;
|
||||||
|
using System.Drawing;
|
||||||
|
using System.IO;
|
||||||
|
using System.Windows.Forms;
|
||||||
|
|
||||||
|
namespace UI
|
||||||
|
{
|
||||||
|
public class EmpresaConfiguracoesPanel : UserControl
|
||||||
|
{
|
||||||
|
//Variaveis de ambiente
|
||||||
|
private int _idEmpresa;
|
||||||
|
private int _idConfig;
|
||||||
|
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!;
|
||||||
|
|
||||||
|
private RoundTextBox txtId = null!, txtEmpresaId = null!, txtNomeSistema = null!;
|
||||||
|
private RoundTextBox txtCorPrimaria = null!, txtCorSecundaria = null!;
|
||||||
|
private RoundTextBox txtLogo = null!, txtFavicon = null!;
|
||||||
|
private RoundTextBox txtDiasGarantiaPadrao = null!;
|
||||||
|
|
||||||
|
private CheckBox chkExibirCPF = null!, chkExibirTelefone = null!, chkExibirGarantia = null!;
|
||||||
|
private CheckBox chkGerarRecibo = null!, chkExibirValoresOS = null!;
|
||||||
|
private CheckBox chkEmailAuto = null!, chkWhatsAuto = null!, chkModoEscuro = null!;
|
||||||
|
private CheckBox chkPermitirEdicaoOS = null!;
|
||||||
|
|
||||||
|
private RoundTextBox txtCriadoEm = null!, txtAtualizadoEm = null!;
|
||||||
|
|
||||||
|
public EmpresaConfiguracoesPanel()
|
||||||
|
{
|
||||||
|
Dock = DockStyle.Fill;
|
||||||
|
BackColor = Color.White;
|
||||||
|
DoubleBuffered = true;
|
||||||
|
InitializeLayout();
|
||||||
|
this.CarregarConfig();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private void InitializeLayout()
|
||||||
|
{
|
||||||
|
this.Controls.Clear();
|
||||||
|
|
||||||
|
// ── TOOLBAR ───────────────────────────────────────────────────────
|
||||||
|
pnlToolbar = new Panel
|
||||||
|
{
|
||||||
|
Dock = DockStyle.Top,
|
||||||
|
Height = 55,
|
||||||
|
BackColor = Color.FromArgb(248, 250, 252)
|
||||||
|
};
|
||||||
|
var flowButtons = new FlowLayoutPanel
|
||||||
|
{
|
||||||
|
Dock = DockStyle.Fill,
|
||||||
|
Padding = new Padding(12, 10, 0, 0)
|
||||||
|
};
|
||||||
|
|
||||||
|
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));
|
||||||
|
var btnConfigEmpresa = CreateToolbarButton("Gerar Config", 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();
|
||||||
|
btnConfigEmpresa.Click += (s, e) => BtnGerarConfig_Click();
|
||||||
|
|
||||||
|
flowButtons.Controls.AddRange(new Control[]
|
||||||
|
{ btnNovo, btnAlterar, btnExcluir, btnLocalizar, btnSalvar,btnConfigEmpresa,btnCancelar });
|
||||||
|
pnlToolbar.Controls.Add(flowButtons);
|
||||||
|
this.Controls.Add(pnlToolbar);
|
||||||
|
|
||||||
|
// ── SCROLL + CONTENT ──────────────────────────────────────────────
|
||||||
|
mainScroll = new Panel { Dock = DockStyle.Fill, AutoScroll = true };
|
||||||
|
this.Controls.Add(mainScroll);
|
||||||
|
mainScroll.BringToFront();
|
||||||
|
|
||||||
|
content = new Panel { Width = 1100, Height = 850, Location = new Point(0, 0) };
|
||||||
|
mainScroll.Controls.Add(content);
|
||||||
|
|
||||||
|
int y = 10;
|
||||||
|
const int rowH = 52;
|
||||||
|
|
||||||
|
// ── 1. IDENTIDADE DO SISTEMA ──────────────────────────────────────
|
||||||
|
content.Controls.Add(CreateSectionHeader("IDENTIDADE DO SISTEMA", y));
|
||||||
|
y += 32;
|
||||||
|
|
||||||
|
txtId = AddInput(content, "ID", 20, y, 60, 28, readOnly: true);
|
||||||
|
txtEmpresaId = AddInput(content, "Empresa ID", 90, y, 80, 28);
|
||||||
|
txtNomeSistema = AddInput(content, "Nome Personalizado do Sistema", 180, y, 350, 28);
|
||||||
|
y += rowH;
|
||||||
|
|
||||||
|
txtCorPrimaria = AddInput(content, "Cor Primária (Hex)", 20, y, 150, 28);
|
||||||
|
txtCorSecundaria = AddInput(content, "Cor Secundária (Hex)", 180, y, 150, 28);
|
||||||
|
|
||||||
|
// Logo com botão lupa
|
||||||
|
txtLogo = AddInput(content, "Caminho da Logo", 340, y, 260, 28);
|
||||||
|
var btnLogo = CreateIconButton("🔍", 608, y + 16);
|
||||||
|
btnLogo.Click += (s, e) => SelecionarImagem(txtLogo, "Logo");
|
||||||
|
content.Controls.Add(btnLogo);
|
||||||
|
|
||||||
|
// Favicon com botão lupa
|
||||||
|
txtFavicon = AddInput(content, "Caminho do Favicon", 650, y, 240, 28);
|
||||||
|
var btnFavicon = CreateIconButton("🔍", 898, y + 16);
|
||||||
|
btnFavicon.Click += (s, e) => SelecionarImagem(txtFavicon, "Favicon");
|
||||||
|
content.Controls.Add(btnFavicon);
|
||||||
|
|
||||||
|
// ── 2. REGRAS DE NEGÓCIO E EXIBIÇÃO ──────────────────────────────
|
||||||
|
y += rowH + 15;
|
||||||
|
content.Controls.Add(CreateSectionHeader("REGRAS DE NEGÓCIO E EXIBIÇÃO", y));
|
||||||
|
y += 32;
|
||||||
|
|
||||||
|
chkExibirCPF = CreateCheckBox("Exibir CPF Cliente na OS", 20, y + 15);
|
||||||
|
chkExibirTelefone = CreateCheckBox("Exibir Telefone na OS", 230, y + 15);
|
||||||
|
chkExibirValoresOS = CreateCheckBox("Exibir Valores na OS", 460, y + 15);
|
||||||
|
content.Controls.AddRange(new Control[] { chkExibirCPF, chkExibirTelefone, chkExibirValoresOS });
|
||||||
|
y += rowH;
|
||||||
|
|
||||||
|
chkExibirGarantia = CreateCheckBox("Utilizar Garantia", 20, y + 15);
|
||||||
|
txtDiasGarantiaPadrao = AddInput(content, "Dias Garantia (Padrão)", 180, y, 120, 28);
|
||||||
|
content.Controls.Add(chkExibirGarantia);
|
||||||
|
|
||||||
|
// ── 3. AUTOMAÇÕES E COMUNICAÇÃO ───────────────────────────────────
|
||||||
|
y += rowH + 15;
|
||||||
|
content.Controls.Add(CreateSectionHeader("AUTOMAÇÕES E COMUNICAÇÃO", y));
|
||||||
|
y += 32;
|
||||||
|
|
||||||
|
chkGerarRecibo = CreateCheckBox("Gerar Recibo Automático", 20, y + 15);
|
||||||
|
chkEmailAuto = CreateCheckBox("Enviar E-mail Automático", 230, y + 15);
|
||||||
|
chkWhatsAuto = CreateCheckBox("Enviar WhatsApp Automático", 460, y + 15);
|
||||||
|
content.Controls.AddRange(new Control[] { chkGerarRecibo, chkEmailAuto, chkWhatsAuto });
|
||||||
|
|
||||||
|
// ── 4. PREFERÊNCIAS TÉCNICAS ──────────────────────────────────────
|
||||||
|
y += rowH + 15;
|
||||||
|
content.Controls.Add(CreateSectionHeader("PREFERÊNCIAS TÉCNICAS", y));
|
||||||
|
y += 32;
|
||||||
|
|
||||||
|
chkModoEscuro = CreateCheckBox("Habilitar Modo Escuro", 20, y + 15);
|
||||||
|
chkPermitirEdicaoOS = CreateCheckBox("Permitir Edição de OS Finalizada", 230, y + 15);
|
||||||
|
content.Controls.AddRange(new Control[] { chkModoEscuro, chkPermitirEdicaoOS });
|
||||||
|
|
||||||
|
// ── 5. INFORMAÇÕES DO REGISTRO ────────────────────────────────────
|
||||||
|
y += rowH + 15;
|
||||||
|
content.Controls.Add(CreateSectionHeader("INFORMAÇÕES DO REGISTRO", y));
|
||||||
|
y += 32;
|
||||||
|
|
||||||
|
txtCriadoEm = AddInput(content, "Criado Em", 20, y, 180, 28, readOnly: true);
|
||||||
|
txtAtualizadoEm = AddInput(content, "Atualizado Em", 210, y, 180, 28, readOnly: true);
|
||||||
|
y += rowH;
|
||||||
|
|
||||||
|
content.Height = y + 20;
|
||||||
|
|
||||||
|
SetCamposStatus(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ── SELEÇÃO DE IMAGEM ─────────────────────────────────────────────────
|
||||||
|
|
||||||
|
//private void SelecionarImagem(RoundTextBox destino, string tipo)
|
||||||
|
//{
|
||||||
|
// using var dlg = new OpenFileDialog
|
||||||
|
// {
|
||||||
|
// Title = $"Selecionar {tipo}",
|
||||||
|
// Filter = "Imagens|*.png;*.jpg;*.jpeg;*.bmp;*.ico;*.gif|Todos os arquivos|*.*"
|
||||||
|
// };
|
||||||
|
|
||||||
|
// if (dlg.ShowDialog() == DialogResult.OK)
|
||||||
|
// {
|
||||||
|
// var arquivo = dlg.FileName;
|
||||||
|
// destino.Text = arquivo;
|
||||||
|
|
||||||
|
// // Valida tamanho máximo (2MB)
|
||||||
|
// var info = new FileInfo(arquivo);
|
||||||
|
// if (info.Length > 2 * 1024 * 1024)
|
||||||
|
// {
|
||||||
|
// MessageBox.Show(
|
||||||
|
// $"O arquivo selecionado para {tipo} é maior que 2MB.\nRecomendamos imagens menores para melhor desempenho.",
|
||||||
|
// "Atenção",
|
||||||
|
// MessageBoxButtons.OK,
|
||||||
|
// MessageBoxIcon.Warning);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
//}
|
||||||
|
private void SelecionarImagem(RoundTextBox destino, string tipo)
|
||||||
|
{
|
||||||
|
using var dlg = new OpenFileDialog
|
||||||
|
{
|
||||||
|
Title = $"Selecionar {tipo}",
|
||||||
|
Filter = "Imagens|*.png;*.jpg;*.jpeg;*.bmp;*.ico;*.gif|Todos os arquivos|*.*"
|
||||||
|
};
|
||||||
|
|
||||||
|
if (dlg.ShowDialog() == DialogResult.OK)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var arquivoOriginal = dlg.FileName;
|
||||||
|
|
||||||
|
// 📁 Pasta destino fixa
|
||||||
|
string pastaDestino = @"C:\Levelcode\LevelOS\Uploads\Images";
|
||||||
|
|
||||||
|
// Cria a pasta se não existir
|
||||||
|
if (!Directory.Exists(pastaDestino))
|
||||||
|
Directory.CreateDirectory(pastaDestino);
|
||||||
|
|
||||||
|
// 🔥 Gera nome único (evita sobrescrever)
|
||||||
|
string extensao = Path.GetExtension(arquivoOriginal);
|
||||||
|
string nomeNovo = $"{tipo}_{Guid.NewGuid()}{extensao}";
|
||||||
|
string caminhoFinal = Path.Combine(pastaDestino, nomeNovo);
|
||||||
|
|
||||||
|
// Copia o arquivo
|
||||||
|
File.Copy(arquivoOriginal, caminhoFinal, false);
|
||||||
|
|
||||||
|
// Atualiza o campo
|
||||||
|
destino.Text = caminhoFinal;
|
||||||
|
|
||||||
|
// ⚠️ Valida tamanho (2MB)
|
||||||
|
var info = new FileInfo(caminhoFinal);
|
||||||
|
if (info.Length > 2 * 1024 * 1024)
|
||||||
|
{
|
||||||
|
MessageBox.Show(
|
||||||
|
$"O arquivo selecionado para {tipo} é maior que 2MB.\nRecomendamos imagens menores para melhor desempenho.",
|
||||||
|
"Atenção",
|
||||||
|
MessageBoxButtons.OK,
|
||||||
|
MessageBoxIcon.Warning);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
MessageBox.Show(
|
||||||
|
"Erro ao copiar imagem: " + ex.Message,
|
||||||
|
"Erro",
|
||||||
|
MessageBoxButtons.OK,
|
||||||
|
MessageBoxIcon.Error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}//Copiar com mais precisão
|
||||||
|
|
||||||
|
// ── EVENTOS DOS BOTÕES ────────────────────────────────────────────────
|
||||||
|
|
||||||
|
private void BtnNovo_Click()
|
||||||
|
{
|
||||||
|
LimparFormulario();
|
||||||
|
SetCamposStatus(true);
|
||||||
|
txtNomeSistema.Focus();
|
||||||
|
BLLEmpresaConfig empresaConfig = new BLLEmpresaConfig(_connectionString);
|
||||||
|
this.txtEmpresaId.Text = empresaConfig.ObterEmpresaAtivaId().ToString();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void BtnAlterar_Click()
|
||||||
|
{
|
||||||
|
if (string.IsNullOrWhiteSpace(txtId.Text))
|
||||||
|
{
|
||||||
|
MessageBox.Show(
|
||||||
|
"Nenhum registro selecionado para alterar.",
|
||||||
|
"Atenção",
|
||||||
|
MessageBoxButtons.OK,
|
||||||
|
MessageBoxIcon.Warning);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
SetCamposStatus(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void BtnExcluir_Click()
|
||||||
|
{
|
||||||
|
// Solicita confirmação e exclui o registro
|
||||||
|
}
|
||||||
|
|
||||||
|
private void BtnLocalizar_Click()
|
||||||
|
{
|
||||||
|
// Abre tela de busca e preenche os campos
|
||||||
|
}
|
||||||
|
private void BtnGerarConfig_Click()
|
||||||
|
{
|
||||||
|
var config = new ModeloEmpresaConfig
|
||||||
|
{
|
||||||
|
IdEmpresaConfig = Convert.ToInt32(txtId.Text), // você precisa ter isso carregado
|
||||||
|
IdEmpresa = Convert.ToInt32(txtEmpresaId.Text), // idem (empresa logada)
|
||||||
|
|
||||||
|
NomeSistema = txtNomeSistema.Text,
|
||||||
|
CorPrimaria = txtCorPrimaria.Text,
|
||||||
|
CorSecundaria = txtCorSecundaria.Text,
|
||||||
|
Logo = txtLogo.Text,
|
||||||
|
Favicon = txtFavicon.Text,
|
||||||
|
|
||||||
|
ExibirCPFCliente = chkExibirCPF.Checked,
|
||||||
|
ExibirTelefoneCliente = chkExibirTelefone.Checked,
|
||||||
|
ExibirGarantia = chkExibirGarantia.Checked,
|
||||||
|
DiasGarantiaPadrao = Convert.ToInt32(txtDiasGarantiaPadrao.Text),
|
||||||
|
|
||||||
|
GerarReciboAutomatico = chkGerarRecibo.Checked,
|
||||||
|
ExibirValoresOS = chkExibirValoresOS.Checked,
|
||||||
|
|
||||||
|
EnviarEmailAutomatico = chkEmailAuto.Checked,
|
||||||
|
EnviarWhatsappAutomatico = chkWhatsAuto.Checked,
|
||||||
|
|
||||||
|
ModoEscuro = chkModoEscuro.Checked,
|
||||||
|
PermitirEdicaoOSFinalizada = chkPermitirEdicaoOS.Checked
|
||||||
|
};
|
||||||
|
bool result = JsonHelper.SalvarBoolean(config, AppFileSystem.AppFileConfigEmpresa);
|
||||||
|
if (result)
|
||||||
|
{
|
||||||
|
NT_MessageBox.Show("Arquivo de configuração gerado com sucesso.","Arquivo gerado",MessageBoxButtons.OK, MessageBoxIcon.Warning);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
NT_MessageBox.Show("Não foi possivel gerar o arquivo de configuração", "falha ao gerar arquivo", MessageBoxButtons.OK, MessageBoxIcon.Error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void BtnSalvar_Click()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// Valida campos obrigatórios
|
||||||
|
if (string.IsNullOrWhiteSpace(txtNomeSistema.Text))
|
||||||
|
{
|
||||||
|
MessageBox.Show(
|
||||||
|
"O campo 'Nome do Sistema' é obrigatório.",
|
||||||
|
"Atenção",
|
||||||
|
MessageBoxButtons.OK,
|
||||||
|
MessageBoxIcon.Warning);
|
||||||
|
txtNomeSistema.Focus();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Valida cores HEX
|
||||||
|
if (!string.IsNullOrWhiteSpace(txtCorPrimaria.Text) && !ValidarHex(txtCorPrimaria.Text))
|
||||||
|
{
|
||||||
|
MessageBox.Show("Cor Primária inválida. Ex: #3B82F6", "Atenção");
|
||||||
|
txtCorPrimaria.Focus();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!string.IsNullOrWhiteSpace(txtCorSecundaria.Text) && !ValidarHex(txtCorSecundaria.Text))
|
||||||
|
{
|
||||||
|
MessageBox.Show("Cor Secundária inválida. Ex: #64748B", "Atenção");
|
||||||
|
txtCorSecundaria.Focus();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Valida arquivos
|
||||||
|
if (!string.IsNullOrWhiteSpace(txtLogo.Text) && !File.Exists(txtLogo.Text))
|
||||||
|
{
|
||||||
|
MessageBox.Show("Logo não encontrada.", "Atenção");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!string.IsNullOrWhiteSpace(txtFavicon.Text) && !File.Exists(txtFavicon.Text))
|
||||||
|
{
|
||||||
|
MessageBox.Show("Favicon não encontrado.", "Atenção");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 🔥 Monta o modelo
|
||||||
|
var config = new ModeloEmpresaConfig
|
||||||
|
{
|
||||||
|
IdEmpresaConfig = Convert.ToInt32(txtId.Text), // você precisa ter isso carregado
|
||||||
|
IdEmpresa = Convert.ToInt32(txtEmpresaId.Text), // idem (empresa logada)
|
||||||
|
|
||||||
|
NomeSistema = txtNomeSistema.Text,
|
||||||
|
CorPrimaria = txtCorPrimaria.Text,
|
||||||
|
CorSecundaria = txtCorSecundaria.Text,
|
||||||
|
Logo = txtLogo.Text,
|
||||||
|
Favicon = txtFavicon.Text,
|
||||||
|
|
||||||
|
ExibirCPFCliente = chkExibirCPF.Checked,
|
||||||
|
ExibirTelefoneCliente = chkExibirTelefone.Checked,
|
||||||
|
ExibirGarantia = chkExibirGarantia.Checked,
|
||||||
|
DiasGarantiaPadrao =Convert.ToInt32(txtDiasGarantiaPadrao.Text),
|
||||||
|
|
||||||
|
GerarReciboAutomatico = chkGerarRecibo.Checked,
|
||||||
|
ExibirValoresOS = chkExibirValoresOS.Checked,
|
||||||
|
|
||||||
|
EnviarEmailAutomatico = chkEmailAuto.Checked,
|
||||||
|
EnviarWhatsappAutomatico = chkWhatsAuto.Checked,
|
||||||
|
|
||||||
|
ModoEscuro = chkModoEscuro.Checked,
|
||||||
|
PermitirEdicaoOSFinalizada = chkPermitirEdicaoOS.Checked
|
||||||
|
};
|
||||||
|
|
||||||
|
var bll = new BLLEmpresaConfig(_connectionString);
|
||||||
|
|
||||||
|
// 🔥 Decide se cria ou atualiza
|
||||||
|
_idConfig = Convert.ToInt32(txtId.Text);
|
||||||
|
if (_idConfig == 0 || _idConfig == null)
|
||||||
|
{
|
||||||
|
bll.Inserir(config);
|
||||||
|
JsonHelper.Salvar(config, AppFileSystem.AppFileConfigEmpresa);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
|
||||||
|
bll.Alterar(config);
|
||||||
|
JsonHelper.Salvar(config, AppFileSystem.AppFileConfigEmpresa);
|
||||||
|
}
|
||||||
|
|
||||||
|
MessageBox.Show(
|
||||||
|
"Configurações salvas com sucesso!",
|
||||||
|
"LevelOS",
|
||||||
|
MessageBoxButtons.OK,
|
||||||
|
MessageBoxIcon.Information);
|
||||||
|
|
||||||
|
SetCamposStatus(false);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
MessageBox.Show(
|
||||||
|
ex.Message,
|
||||||
|
"Erro",
|
||||||
|
MessageBoxButtons.OK,
|
||||||
|
MessageBoxIcon.Error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void BtnCancelar_Click()
|
||||||
|
{
|
||||||
|
LimparFormulario();
|
||||||
|
SetCamposStatus(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ── HELPERS DE ESTADO ─────────────────────────────────────────────────
|
||||||
|
|
||||||
|
private void SetCamposStatus(bool active)
|
||||||
|
{
|
||||||
|
var campos = new Control[]
|
||||||
|
{
|
||||||
|
txtEmpresaId, txtNomeSistema, txtCorPrimaria, txtCorSecundaria,
|
||||||
|
txtLogo, txtFavicon, txtDiasGarantiaPadrao,
|
||||||
|
chkExibirCPF, chkExibirTelefone, chkExibirGarantia, chkGerarRecibo,
|
||||||
|
chkExibirValoresOS, chkEmailAuto, chkWhatsAuto, chkModoEscuro, chkPermitirEdicaoOS
|
||||||
|
};
|
||||||
|
|
||||||
|
foreach (var c in campos)
|
||||||
|
{
|
||||||
|
c.Enabled = active;
|
||||||
|
if (c is RoundTextBox r)
|
||||||
|
r.BackColor = active ? Color.White : Color.FromArgb(241, 245, 249);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ID e datas nunca editáveis
|
||||||
|
txtId.Enabled = false;
|
||||||
|
txtId.BackColor = Color.FromArgb(241, 245, 249);
|
||||||
|
txtCriadoEm.Enabled = false;
|
||||||
|
txtAtualizadoEm.Enabled = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void LimparFormulario()
|
||||||
|
{
|
||||||
|
var todos = new RoundTextBox[]
|
||||||
|
{
|
||||||
|
txtId, txtEmpresaId, txtNomeSistema, txtCorPrimaria, txtCorSecundaria,
|
||||||
|
txtLogo, txtFavicon, txtDiasGarantiaPadrao, txtCriadoEm, txtAtualizadoEm
|
||||||
|
};
|
||||||
|
foreach (var t in todos) t.Text = string.Empty;
|
||||||
|
|
||||||
|
foreach (Control c in content.Controls)
|
||||||
|
if (c is CheckBox chk) chk.Checked = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static bool ValidarHex(string valor)
|
||||||
|
{
|
||||||
|
var v = valor.TrimStart('#');
|
||||||
|
return v.Length == 6 && System.Text.RegularExpressions.Regex.IsMatch(v, @"^[0-9A-Fa-f]{6}$");
|
||||||
|
}
|
||||||
|
|
||||||
|
// ── HELPERS DE UI ─────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
private Panel CreateSectionHeader(string title, int y)
|
||||||
|
{
|
||||||
|
var pnl = new Panel { Location = new Point(20, y), Width = 1000, Height = 26 };
|
||||||
|
pnl.Controls.Add(new Label
|
||||||
|
{
|
||||||
|
Text = title,
|
||||||
|
Font = new Font("Segoe UI", 8.5f, FontStyle.Bold),
|
||||||
|
ForeColor = AccentBlue,
|
||||||
|
AutoSize = true
|
||||||
|
});
|
||||||
|
pnl.Controls.Add(new Panel
|
||||||
|
{
|
||||||
|
BackColor = BorderColor,
|
||||||
|
Height = 1,
|
||||||
|
Width = 980,
|
||||||
|
Location = new Point(0, 20)
|
||||||
|
});
|
||||||
|
return pnl;
|
||||||
|
}
|
||||||
|
|
||||||
|
private RoundTextBox AddInput(Control parent, string label,
|
||||||
|
int x, int y, int w, int h,
|
||||||
|
bool readOnly = false)
|
||||||
|
{
|
||||||
|
parent.Controls.Add(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(w, h),
|
||||||
|
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(txt);
|
||||||
|
return txt;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Button CreateIconButton(string icon, int x, int y) => new Button
|
||||||
|
{
|
||||||
|
Text = icon,
|
||||||
|
Location = new Point(x, y),
|
||||||
|
Size = new Size(28, 28),
|
||||||
|
FlatStyle = FlatStyle.Flat,
|
||||||
|
Font = new Font("Segoe UI", 10f),
|
||||||
|
Cursor = Cursors.Hand,
|
||||||
|
FlatAppearance = { BorderColor = BorderColor, BorderSize = 1 },
|
||||||
|
BackColor = Color.FromArgb(241, 245, 249)
|
||||||
|
};
|
||||||
|
|
||||||
|
private CheckBox CreateCheckBox(string text, int x, int y) => new CheckBox
|
||||||
|
{
|
||||||
|
Text = text,
|
||||||
|
Location = new Point(x, y),
|
||||||
|
Font = new Font("Segoe UI", 8.25f, 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
|
||||||
|
};
|
||||||
|
|
||||||
|
private void CarregarConfig()
|
||||||
|
{
|
||||||
|
BLLEmpresaConfig empresaConfig = new BLLEmpresaConfig(_connectionString);
|
||||||
|
int codEmpresa = empresaConfig.ObterEmpresaAtivaId();
|
||||||
|
if (codEmpresa > 0)
|
||||||
|
{
|
||||||
|
ModeloEmpresaConfig modelo = empresaConfig.ObterPorEmpresa(codEmpresa);
|
||||||
|
this.txtId.Text = modelo.IdEmpresaConfig.ToString();
|
||||||
|
this.txtEmpresaId.Text = modelo.IdEmpresa.ToString();
|
||||||
|
this.txtNomeSistema.Text = modelo.NomeSistema;
|
||||||
|
this.txtCorPrimaria.Text = modelo.CorPrimaria;
|
||||||
|
this.txtCorSecundaria.Text = modelo.CorSecundaria;
|
||||||
|
this.txtLogo.Text = modelo.Logo;
|
||||||
|
this.txtFavicon.Text = modelo.Favicon;
|
||||||
|
this.txtDiasGarantiaPadrao.Text = modelo.DiasGarantiaPadrao.ToString();
|
||||||
|
this.chkExibirCPF.Checked = modelo.ExibirCPFCliente;
|
||||||
|
this.chkExibirTelefone.Checked = modelo.ExibirTelefoneCliente;
|
||||||
|
this.chkExibirGarantia.Checked = modelo.ExibirGarantia;
|
||||||
|
this.chkGerarRecibo.Checked = modelo.GerarReciboAutomatico;
|
||||||
|
this.chkExibirValoresOS.Checked = modelo.ExibirValoresOS;
|
||||||
|
this.chkEmailAuto.Checked = modelo.EnviarEmailAutomatico;
|
||||||
|
this.chkWhatsAuto.Checked = modelo.EnviarWhatsappAutomatico;
|
||||||
|
this.chkModoEscuro.Checked = modelo.ModoEscuro;
|
||||||
|
this.chkPermitirEdicaoOS.Checked = modelo.PermitirEdicaoOSFinalizada;
|
||||||
|
this.txtCriadoEm.Text = modelo.CriadoEm.ToString();
|
||||||
|
this.txtAtualizadoEm.Text = modelo.AtualizadoEm.ToString();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
NT_MessageBox.Show("Erro ao recuperar configuração da empresa, por favor contacte o administrador do sistema","Erro",MessageBoxButtons.OK,MessageBoxIcon.Error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
120
Dashboards/Cadastros/EmpresaConfiguracoesPanel.resx
Normal file
120
Dashboards/Cadastros/EmpresaConfiguracoesPanel.resx
Normal file
@ -0,0 +1,120 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<root>
|
||||||
|
<!--
|
||||||
|
Microsoft ResX Schema
|
||||||
|
|
||||||
|
Version 2.0
|
||||||
|
|
||||||
|
The primary goals of this format is to allow a simple XML format
|
||||||
|
that is mostly human readable. The generation and parsing of the
|
||||||
|
various data types are done through the TypeConverter classes
|
||||||
|
associated with the data types.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
... ado.net/XML headers & schema ...
|
||||||
|
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||||
|
<resheader name="version">2.0</resheader>
|
||||||
|
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||||
|
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||||
|
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
||||||
|
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||||
|
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||||
|
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
||||||
|
</data>
|
||||||
|
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||||
|
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||||
|
<comment>This is a comment</comment>
|
||||||
|
</data>
|
||||||
|
|
||||||
|
There are any number of "resheader" rows that contain simple
|
||||||
|
name/value pairs.
|
||||||
|
|
||||||
|
Each data row contains a name, and value. The row also contains a
|
||||||
|
type or mimetype. Type corresponds to a .NET class that support
|
||||||
|
text/value conversion through the TypeConverter architecture.
|
||||||
|
Classes that don't support this are serialized and stored with the
|
||||||
|
mimetype set.
|
||||||
|
|
||||||
|
The mimetype is used for serialized objects, and tells the
|
||||||
|
ResXResourceReader how to depersist the object. This is currently not
|
||||||
|
extensible. For a given mimetype the value must be set accordingly:
|
||||||
|
|
||||||
|
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||||
|
that the ResXResourceWriter will generate, however the reader can
|
||||||
|
read any of the formats listed below.
|
||||||
|
|
||||||
|
mimetype: application/x-microsoft.net.object.binary.base64
|
||||||
|
value : The object must be serialized with
|
||||||
|
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
|
||||||
|
: and then encoded with base64 encoding.
|
||||||
|
|
||||||
|
mimetype: application/x-microsoft.net.object.soap.base64
|
||||||
|
value : The object must be serialized with
|
||||||
|
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||||
|
: and then encoded with base64 encoding.
|
||||||
|
|
||||||
|
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||||
|
value : The object must be serialized into a byte array
|
||||||
|
: using a System.ComponentModel.TypeConverter
|
||||||
|
: and then encoded with base64 encoding.
|
||||||
|
-->
|
||||||
|
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||||
|
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
||||||
|
<xsd:element name="root" msdata:IsDataSet="true">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:choice maxOccurs="unbounded">
|
||||||
|
<xsd:element name="metadata">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:sequence>
|
||||||
|
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||||
|
</xsd:sequence>
|
||||||
|
<xsd:attribute name="name" use="required" type="xsd:string" />
|
||||||
|
<xsd:attribute name="type" type="xsd:string" />
|
||||||
|
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||||
|
<xsd:attribute ref="xml:space" />
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
<xsd:element name="assembly">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:attribute name="alias" type="xsd:string" />
|
||||||
|
<xsd:attribute name="name" type="xsd:string" />
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
<xsd:element name="data">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:sequence>
|
||||||
|
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||||
|
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||||
|
</xsd:sequence>
|
||||||
|
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
|
||||||
|
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||||
|
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||||
|
<xsd:attribute ref="xml:space" />
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
<xsd:element name="resheader">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:sequence>
|
||||||
|
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||||
|
</xsd:sequence>
|
||||||
|
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
</xsd:choice>
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
</xsd:schema>
|
||||||
|
<resheader name="resmimetype">
|
||||||
|
<value>text/microsoft-resx</value>
|
||||||
|
</resheader>
|
||||||
|
<resheader name="version">
|
||||||
|
<value>2.0</value>
|
||||||
|
</resheader>
|
||||||
|
<resheader name="reader">
|
||||||
|
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||||
|
</resheader>
|
||||||
|
<resheader name="writer">
|
||||||
|
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||||
|
</resheader>
|
||||||
|
</root>
|
||||||
947
Dashboards/Cadastros/FuncionariosCadastroPanel.cs
Normal file
947
Dashboards/Cadastros/FuncionariosCadastroPanel.cs
Normal file
@ -0,0 +1,947 @@
|
|||||||
|
using BLL;
|
||||||
|
using CustomMessageBox;
|
||||||
|
using DAL;
|
||||||
|
using MLL;
|
||||||
|
using System;
|
||||||
|
using System.Drawing;
|
||||||
|
using System.Drawing.Imaging;
|
||||||
|
using System.IO;
|
||||||
|
using System.Windows.Forms;
|
||||||
|
using AForge.Video;
|
||||||
|
using AForge.Video.DirectShow;
|
||||||
|
|
||||||
|
namespace UI
|
||||||
|
{
|
||||||
|
public class FuncionariosCadastroPanel : UserControl
|
||||||
|
{
|
||||||
|
private int idBanco = 0;
|
||||||
|
private string _cx = 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!, txtCodigo = null!, txtNome = null!;
|
||||||
|
private RoundTextBox txtCPF = null!, txtCI = null!, txtCTPS = null!;
|
||||||
|
private RoundTextBox txtCNH = null!, txtCatCNH = null!;
|
||||||
|
private RoundTextBox txtECivil = null!, txtRegime = null!;
|
||||||
|
|
||||||
|
// Filiação
|
||||||
|
private RoundTextBox txtPai = null!, txtMae = null!;
|
||||||
|
|
||||||
|
// Endereço
|
||||||
|
private RoundTextBox txtcep=null!, txtEndereco = null!,txtEndNumero=null!, txtBairro = null!, txtCidade = null!, txtUF = null!;
|
||||||
|
|
||||||
|
// Dados Bancários
|
||||||
|
private RoundTextBox txtBanco = null!, txtAgencia = null!, txtConta = null!;
|
||||||
|
private RoundComboBox cbBanco = null!;
|
||||||
|
|
||||||
|
// Contato
|
||||||
|
private RoundTextBox txtTelefone = null!;
|
||||||
|
|
||||||
|
// Acesso
|
||||||
|
private RoundTextBox txtPass = null!;
|
||||||
|
private CheckBox chkMasterUser = null!, chkVendedor = null!, chkTecnico = null!;
|
||||||
|
private CheckBox chkDemitido = null!, chkContador = null!, chkOutros = null!;
|
||||||
|
|
||||||
|
// Outros
|
||||||
|
private RoundTextBox txtFPath = null!, txtObserv = null!;
|
||||||
|
|
||||||
|
// Datas
|
||||||
|
private RoundTextBox txtDataAdm = null!, txtDataDem = null!, txtAniver = null!;
|
||||||
|
|
||||||
|
// ── CARREGAR FUNCIONÁRIO ──────────────────────────────────────────────
|
||||||
|
|
||||||
|
private void CarregarFuncionario(int id)
|
||||||
|
{
|
||||||
|
//var bll = new BLLFuncionarios(_cx);
|
||||||
|
//var f = bll.CarregarPorId(id);
|
||||||
|
|
||||||
|
//if (f == null)
|
||||||
|
//{
|
||||||
|
// NT_MessageBox.Show("Funcionário não encontrado.",
|
||||||
|
// "Atenção", MessageBoxButtons.OK, MessageBoxIcon.Warning);
|
||||||
|
// return;
|
||||||
|
//}
|
||||||
|
|
||||||
|
//PreencherCampos(f);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void PreencherCampos(ModeloFuncionarios f)
|
||||||
|
{
|
||||||
|
txtId.Text = f.ID_FUNCIONARIO.ToString();
|
||||||
|
txtCodigo.Text = f.CODIGO;
|
||||||
|
txtNome.Text = f.NOME;
|
||||||
|
txtPai.Text = f.PAI;
|
||||||
|
txtMae.Text = f.MAE;
|
||||||
|
txtCPF.Text = f.CPF;
|
||||||
|
txtCI.Text = f.CI;
|
||||||
|
txtCTPS.Text = f.CTPS;
|
||||||
|
txtCNH.Text = f.CNH;
|
||||||
|
txtCatCNH.Text = f.CAT_CNH;
|
||||||
|
txtECivil.Text = f.ECIVIL;
|
||||||
|
txtRegime.Text = f.REGIME;
|
||||||
|
txtEndereco.Text = f.ENDERECO;
|
||||||
|
txtBairro.Text = f.BAIRRO;
|
||||||
|
txtCidade.Text = f.CIDADE;
|
||||||
|
txtUF.Text = f.UF;
|
||||||
|
txtBanco.Text = f.BANCO;
|
||||||
|
txtAgencia.Text = f.AGENCIA;
|
||||||
|
txtConta.Text = f.CONTA;
|
||||||
|
txtTelefone.Text = f.TELEFONE;
|
||||||
|
txtPass.Text = f.PASS;
|
||||||
|
txtFPath.Text = f.FPATH;
|
||||||
|
txtObserv.Text = f.OBSERV;
|
||||||
|
//txtDataAdm.Text = f.DATA_ADM;
|
||||||
|
//txtDataDem.Text = f.DATA_DEM;
|
||||||
|
//txtAniver.Text = f.ANIVER;
|
||||||
|
|
||||||
|
//chkMasterUser.Checked = f.MASTERUSER == "S";
|
||||||
|
//chkVendedor.Checked = f.VENDEDOR == "S";
|
||||||
|
//chkTecnico.Checked = f.TECNICO == "S";
|
||||||
|
//chkDemitido.Checked = f.DEMITIDO == "S";
|
||||||
|
//chkContador.Checked = f.FTECNICO == "S";
|
||||||
|
//chkOutros.Checked = f.FVENDEDOR == "S";
|
||||||
|
}
|
||||||
|
private Control[] TodosOsControles() => new Control[]{
|
||||||
|
txtCodigo, txtNome,
|
||||||
|
txtCPF, txtCI, txtCTPS, txtCNH, txtCatCNH,
|
||||||
|
txtECivil, txtRegime,
|
||||||
|
txtPai, txtMae,
|
||||||
|
txtcep, txtEndereco, txtEndNumero, txtBairro, txtCidade, txtUF,
|
||||||
|
|
||||||
|
// 👇 ComboBox entra aqui
|
||||||
|
cbBanco,
|
||||||
|
|
||||||
|
txtAgencia, txtConta,
|
||||||
|
txtTelefone,
|
||||||
|
txtPass,
|
||||||
|
txtFPath, txtObserv,
|
||||||
|
txtDataAdm, txtDataDem, txtAniver
|
||||||
|
};//todos os controles
|
||||||
|
private void SetCamposAtulizado(bool enabled)
|
||||||
|
{
|
||||||
|
foreach (var ctrl in TodosOsControles())
|
||||||
|
{
|
||||||
|
ctrl.Enabled = enabled;
|
||||||
|
|
||||||
|
// 🎨 Se for TextBox
|
||||||
|
if (ctrl is RoundTextBox txt)
|
||||||
|
{
|
||||||
|
txt.BackColor = enabled
|
||||||
|
? Color.White
|
||||||
|
: Color.FromArgb(241, 245, 249);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 🎨 Se for ComboBox
|
||||||
|
else if (ctrl is RoundComboBox cmb)
|
||||||
|
{
|
||||||
|
cmb.BackColor = enabled
|
||||||
|
? Color.White
|
||||||
|
: Color.FromArgb(241, 245, 249);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (var chk in TodosOsChecks())
|
||||||
|
chk.Enabled = enabled;
|
||||||
|
}//SetCampos
|
||||||
|
private void CarregarComboBoxAtualizada()
|
||||||
|
{
|
||||||
|
BLLBancos bLLBancos = new BLLBancos(_cx);
|
||||||
|
|
||||||
|
var tabela = bLLBancos.LocalizarTodos();
|
||||||
|
|
||||||
|
// 🔥 cria coluna personalizada
|
||||||
|
tabela.Columns.Add("EXIBICAO", typeof(string), "NUMERO + ' - ' + NOME");
|
||||||
|
|
||||||
|
cbBanco.DataSource = tabela;
|
||||||
|
cbBanco.DisplayMember = "EXIBICAO"; // 👈 aqui
|
||||||
|
cbBanco.ValueMember = "ID_BANCOS";
|
||||||
|
|
||||||
|
if (cbBanco.SelectedValue != null)
|
||||||
|
this.idBanco = Convert.ToInt32(cbBanco.SelectedValue);
|
||||||
|
}//CarregarComboBoxAtualizada
|
||||||
|
private DateTime? ConverterData(string texto)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrWhiteSpace(texto))
|
||||||
|
return null;
|
||||||
|
|
||||||
|
if (DateTime.TryParse(texto, out DateTime data))
|
||||||
|
return data;
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}//ConverterData
|
||||||
|
|
||||||
|
public FuncionariosCadastroPanel()
|
||||||
|
{
|
||||||
|
Dock = DockStyle.Fill;
|
||||||
|
BackColor = Color.White;
|
||||||
|
DoubleBuffered = true;
|
||||||
|
InitializeLayout();
|
||||||
|
this.CarregarComboBoxAtualizada();
|
||||||
|
}
|
||||||
|
|
||||||
|
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 btnGerarFicha = CreateToolbarButton("Gerar Ficha", Color.FromArgb(255,0,0));
|
||||||
|
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();
|
||||||
|
btnGerarFicha.Click += (s, e) => BtnFichaFuncionario_Click();
|
||||||
|
flowButtons.Controls.AddRange(new Control[]
|
||||||
|
{ btnNovo, btnAlterar, btnExcluir, btnLocalizar, btnSalvar,btnGerarFicha,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 FUNCIONÁRIO ───────────────────────────────
|
||||||
|
content.Controls.Add(CreateSectionHeader("IDENTIFICAÇÃO DO FUNCIONÁRIO", y));
|
||||||
|
y += secH + 4;
|
||||||
|
|
||||||
|
txtId = AddInput(content, "ID", 20, y, 60, inputH, readOnly: true);
|
||||||
|
txtCodigo = AddInput(content, "Código", 90, y, 100, inputH, readOnly: true);
|
||||||
|
txtNome = AddInput(content, "Nome", 200, y, 450, inputH);
|
||||||
|
y += rowH;
|
||||||
|
|
||||||
|
txtCPF = AddInput(content, "CPF", 20, y, 160, inputH);
|
||||||
|
DocumentoHelper.Registrar(txtCPF);
|
||||||
|
txtCI = AddInput(content, "RG / CI", 190, y, 160, inputH);
|
||||||
|
txtCTPS = AddInput(content, "CTPS", 360, y, 140, inputH);
|
||||||
|
txtCNH = AddInput(content, "CNH", 510, y, 160, inputH);
|
||||||
|
txtCatCNH = AddInput(content, "Cat. CNH", 680, y, 90, inputH);
|
||||||
|
y += rowH;
|
||||||
|
|
||||||
|
txtECivil = AddInput(content, "Estado Civil", 20, y, 160, inputH);
|
||||||
|
txtRegime = AddInput(content, "Regime", 190, y, 160, inputH);
|
||||||
|
|
||||||
|
// ── 2. FILIAÇÃO ───────────────────────────────────────────────────
|
||||||
|
y += rowH + secGap;
|
||||||
|
content.Controls.Add(CreateSectionHeader("FILIAÇÃO", y));
|
||||||
|
y += secH + 4;
|
||||||
|
|
||||||
|
txtPai = AddInput(content, "Nome do Pai", 20, y, 400, inputH);
|
||||||
|
txtMae = AddInput(content, "Nome da Mãe", 430, y, 400, inputH);
|
||||||
|
|
||||||
|
|
||||||
|
// ── 3. ENDEREÇO ─────────────────────────────────────────────
|
||||||
|
y += rowH + secGap;
|
||||||
|
content.Controls.Add(CreateSectionHeader("ENDEREÇO", y));
|
||||||
|
y += secH + 4;
|
||||||
|
|
||||||
|
// LINHA ÚNICA
|
||||||
|
txtcep = AddInput(content, "CEP", 20, y, 80, 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", 110, y, 260, inputH);
|
||||||
|
txtEndNumero = AddInput(content, "Nº", 380, y, 70, inputH);
|
||||||
|
txtBairro = AddInput(content, "Bairro", 460, y, 150, inputH);
|
||||||
|
txtCidade = AddInput(content, "Cidade", 620, y, 150, inputH);
|
||||||
|
txtUF = AddInput(content, "UF", 780, y, 60, inputH);
|
||||||
|
|
||||||
|
// ── 4. DADOS BANCÁRIOS ────────────────────────────────────────────
|
||||||
|
y += rowH + secGap;
|
||||||
|
content.Controls.Add(CreateSectionHeader("DADOS BANCÁRIOS", y));
|
||||||
|
y += secH + 4;
|
||||||
|
|
||||||
|
//txtBanco = AddInput(content, "Banco", 20, y, 280, inputH);
|
||||||
|
cbBanco = AddComboBox(content, "Banco", 20, y, 200, inputH);
|
||||||
|
txtAgencia = AddInput(content, "Agência", 310, y, 160, inputH);
|
||||||
|
txtConta = AddInput(content, "Conta", 480, y, 160, inputH);
|
||||||
|
|
||||||
|
// ── 5. CONTATO ────────────────────────────────────────────────────
|
||||||
|
y += rowH + secGap;
|
||||||
|
content.Controls.Add(CreateSectionHeader("CONTATO", y));
|
||||||
|
y += secH + 4;
|
||||||
|
|
||||||
|
txtTelefone = AddInput(content, "Telefone", 20, y, 200, inputH);
|
||||||
|
|
||||||
|
// ── 6. ACESSO AO SISTEMA ──────────────────────────────────────────
|
||||||
|
y += rowH + secGap;
|
||||||
|
content.Controls.Add(CreateSectionHeader("ACESSO AO SISTEMA", y));
|
||||||
|
y += secH + 4;
|
||||||
|
|
||||||
|
txtPass = AddInput(content, "Senha", 20, y, 200, inputH);
|
||||||
|
txtPass.PasswordChar = '*';
|
||||||
|
y += rowH;
|
||||||
|
|
||||||
|
chkMasterUser = CreateCheckBox("Master User", 20, y);
|
||||||
|
chkVendedor = CreateCheckBox("Vendedor", 160, y);
|
||||||
|
chkTecnico = CreateCheckBox("Técnico", 290, y);
|
||||||
|
chkOutros = CreateCheckBox("Outros", 420, y);
|
||||||
|
chkContador = CreateCheckBox("Contador", 560, y);
|
||||||
|
chkDemitido = CreateCheckBox("Demitido", 690, y);
|
||||||
|
|
||||||
|
content.Controls.AddRange(new Control[]
|
||||||
|
{ chkMasterUser, chkVendedor, chkTecnico, chkOutros, chkContador, chkDemitido });
|
||||||
|
|
||||||
|
// ── 7. OUTROS ─────────────────────────────────────────────────────
|
||||||
|
y += 35 + secGap;
|
||||||
|
content.Controls.Add(CreateSectionHeader("OUTROS", y));
|
||||||
|
y += secH + 4;
|
||||||
|
|
||||||
|
// Label da foto
|
||||||
|
var lblFoto = new Label
|
||||||
|
{
|
||||||
|
Text = "Caminho da Foto (FPATH)",
|
||||||
|
Location = new Point(20, y),
|
||||||
|
Font = new Font("Segoe UI", 7.5f, FontStyle.Bold),
|
||||||
|
ForeColor = TextDark,
|
||||||
|
AutoSize = true
|
||||||
|
};
|
||||||
|
content.Controls.Add(lblFoto);
|
||||||
|
|
||||||
|
// Campo de texto da foto (menor para dar espaço ao botão lupa)
|
||||||
|
txtFPath = new RoundTextBox
|
||||||
|
{
|
||||||
|
Location = new Point(20, y + 16),
|
||||||
|
Size = new Size(560, inputH),
|
||||||
|
Radius = 4,
|
||||||
|
BorderColor = BorderColor,
|
||||||
|
FocusColor = AccentBlue,
|
||||||
|
BackColor = Color.White
|
||||||
|
};
|
||||||
|
content.Controls.Add(txtFPath);
|
||||||
|
|
||||||
|
// Botão lupa 🔍
|
||||||
|
var btnFoto = new Button
|
||||||
|
{
|
||||||
|
Text = "🔍",
|
||||||
|
Location = new Point(588, y + 16),
|
||||||
|
Size = new Size(36, inputH),
|
||||||
|
FlatStyle = FlatStyle.Flat,
|
||||||
|
BackColor = Color.FromArgb(37, 99, 235),
|
||||||
|
ForeColor = Color.White,
|
||||||
|
Font = new Font("Segoe UI", 11f),
|
||||||
|
Cursor = Cursors.Hand,
|
||||||
|
TabStop = false
|
||||||
|
};
|
||||||
|
btnFoto.FlatAppearance.BorderSize = 0;
|
||||||
|
btnFoto.Click += (s, e) => BtnFoto_Click();
|
||||||
|
content.Controls.Add(btnFoto);
|
||||||
|
|
||||||
|
y += rowH;
|
||||||
|
|
||||||
|
txtObserv = AddInput(content, "Observações", 20, y, 920, inputH);
|
||||||
|
txtObserv.Multiline = true;
|
||||||
|
txtObserv.Height = 60;
|
||||||
|
|
||||||
|
// ── 8. DATAS ──────────────────────────────────────────────────────
|
||||||
|
y += 70 + secGap;
|
||||||
|
content.Controls.Add(CreateSectionHeader("DATAS", y));
|
||||||
|
y += secH + 4;
|
||||||
|
|
||||||
|
txtDataAdm = AddInput(content, "Data de Admissão", 20, y, 175, inputH);
|
||||||
|
txtDataDem = AddInput(content, "Data de Demissão", 205, y, 175, inputH);
|
||||||
|
txtAniver = AddInput(content, "Aniversário", 390, y, 175, inputH);
|
||||||
|
y += rowH;
|
||||||
|
|
||||||
|
content.Height = y + 10;
|
||||||
|
|
||||||
|
//SetCampos(false);
|
||||||
|
SetCamposAtulizado(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ── FOTO: LUPA ────────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
private void BtnFoto_Click()
|
||||||
|
{
|
||||||
|
using var dlg = new FotoOrigemDialog();
|
||||||
|
if (dlg.ShowDialog() != DialogResult.OK) return;
|
||||||
|
|
||||||
|
string? caminhoSalvo = dlg.UsarWebcam
|
||||||
|
? CapturarDaWebcam()
|
||||||
|
: SelecionarDoComputador();
|
||||||
|
|
||||||
|
if (!string.IsNullOrEmpty(caminhoSalvo))
|
||||||
|
txtFPath.Text = caminhoSalvo;
|
||||||
|
}
|
||||||
|
|
||||||
|
private string? SelecionarDoComputador()
|
||||||
|
{
|
||||||
|
using var ofd = new OpenFileDialog
|
||||||
|
{
|
||||||
|
Title = "Selecionar Foto do Funcionário",
|
||||||
|
Filter = "Imagens|*.jpg;*.jpeg;*.png;*.bmp|Todos os arquivos|*.*"
|
||||||
|
};
|
||||||
|
|
||||||
|
if (ofd.ShowDialog() != DialogResult.OK) return null;
|
||||||
|
|
||||||
|
return SalvarFoto(ofd.FileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
private string? CapturarDaWebcam()
|
||||||
|
{
|
||||||
|
using var webcamForm = new WebcamCaptureForm();
|
||||||
|
if (webcamForm.ShowDialog() != DialogResult.OK) return null;
|
||||||
|
if (webcamForm.ImagemCapturada == null) return null;
|
||||||
|
|
||||||
|
string temp = Path.Combine(Path.GetTempPath(), $"webcam_{Guid.NewGuid()}.jpg");
|
||||||
|
webcamForm.ImagemCapturada.Save(temp, ImageFormat.Jpeg);
|
||||||
|
return SalvarFoto(temp);
|
||||||
|
}
|
||||||
|
|
||||||
|
private string SalvarFoto(string origem)
|
||||||
|
{
|
||||||
|
const string pasta = @"C:\Levelcode\LevelOS\Uploads\Images\Funcionarios";
|
||||||
|
Directory.CreateDirectory(pasta);
|
||||||
|
|
||||||
|
// Nome: NomeFuncionario_yyyyMMdd_HHmmss.jpg
|
||||||
|
string nomeBase = string.IsNullOrWhiteSpace(txtNome.Text)
|
||||||
|
? "Funcionario"
|
||||||
|
: txtNome.Text.Trim().Replace(" ", "_");
|
||||||
|
|
||||||
|
string nomeArq = $"{nomeBase}_{DateTime.Now:yyyyMMdd_HHmmss}.jpg";
|
||||||
|
string destino = Path.Combine(pasta, nomeArq);
|
||||||
|
|
||||||
|
File.Copy(origem, destino, overwrite: true);
|
||||||
|
return destino;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ── CAMPOS ────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
private RoundTextBox[] TodosOsCampos() => new[]
|
||||||
|
{
|
||||||
|
txtCodigo, txtNome,
|
||||||
|
txtCPF, txtCI, txtCTPS, txtCNH, txtCatCNH,
|
||||||
|
txtECivil, txtRegime,
|
||||||
|
txtPai, txtMae,
|
||||||
|
txtcep,txtEndereco,txtEndNumero, txtBairro, txtCidade, txtUF,
|
||||||
|
/*txtBanco,*/ txtAgencia, txtConta,
|
||||||
|
txtTelefone,
|
||||||
|
txtPass,
|
||||||
|
txtFPath, txtObserv,
|
||||||
|
txtDataAdm, txtDataDem, txtAniver
|
||||||
|
};
|
||||||
|
|
||||||
|
private CheckBox[] TodosOsChecks() => new[]
|
||||||
|
{
|
||||||
|
chkMasterUser, chkVendedor, chkTecnico,
|
||||||
|
chkDemitido, chkContador, chkOutros
|
||||||
|
};
|
||||||
|
|
||||||
|
private void SetCampos(bool enabled)
|
||||||
|
{
|
||||||
|
foreach (var campo in TodosOsCampos())
|
||||||
|
{
|
||||||
|
campo.Enabled = enabled;
|
||||||
|
campo.BackColor = enabled ? Color.White : Color.FromArgb(241, 245, 249);
|
||||||
|
}
|
||||||
|
foreach (var chk in TodosOsChecks())
|
||||||
|
chk.Enabled = enabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ── EVENTOS ───────────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
private void BtnNovo_Click()
|
||||||
|
{
|
||||||
|
foreach (var campo in TodosOsCampos())
|
||||||
|
campo.Text = string.Empty;
|
||||||
|
|
||||||
|
foreach (var chk in TodosOsChecks())
|
||||||
|
chk.Checked = false;
|
||||||
|
|
||||||
|
//SetCampos(true);
|
||||||
|
SetCamposAtulizado(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void BtnAlterar_Click()
|
||||||
|
{
|
||||||
|
if (string.IsNullOrWhiteSpace(txtId.Text))
|
||||||
|
{
|
||||||
|
NT_MessageBox.Show(
|
||||||
|
"Nenhum registro selecionado para alterar.",
|
||||||
|
"Atenção", MessageBoxButtons.OK, MessageBoxIcon.Warning);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
//SetCampos(true);
|
||||||
|
SetCamposAtulizado(true);
|
||||||
|
txtId.Enabled = false;
|
||||||
|
txtId.BackColor = Color.FromArgb(241, 245, 249);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void BtnExcluir_Click()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private void BtnLocalizar_Click()
|
||||||
|
{
|
||||||
|
// Abre tela/diálogo de busca e preenche os campos
|
||||||
|
}
|
||||||
|
|
||||||
|
private void BtnSalvar_Click()
|
||||||
|
{
|
||||||
|
var bll = new BLLFuncionarios(_cx);
|
||||||
|
|
||||||
|
if (string.IsNullOrWhiteSpace(txtNome.Text) ||
|
||||||
|
string.IsNullOrWhiteSpace(txtCPF.Text))
|
||||||
|
{
|
||||||
|
NT_MessageBox.Show("Preencha ao menos Nome e CPF.",
|
||||||
|
"Atenção", MessageBoxButtons.OK, MessageBoxIcon.Warning);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool isNew = string.IsNullOrWhiteSpace(txtId.Text);
|
||||||
|
|
||||||
|
var funcionario = new ModeloFuncionarios
|
||||||
|
{
|
||||||
|
ID_FUNCIONARIO = isNew ? 0 : int.Parse(txtId.Text),
|
||||||
|
|
||||||
|
CODIGO = txtCodigo.Text,
|
||||||
|
NOME = txtNome.Text,
|
||||||
|
PAI = txtPai.Text,
|
||||||
|
MAE = txtMae.Text,
|
||||||
|
CPF = txtCPF.Text,
|
||||||
|
CI = txtCI.Text,
|
||||||
|
CTPS = txtCTPS.Text,
|
||||||
|
CNH = txtCNH.Text,
|
||||||
|
CAT_CNH = txtCatCNH.Text,
|
||||||
|
ECIVIL = txtECivil.Text,
|
||||||
|
REGIME = txtRegime.Text,
|
||||||
|
|
||||||
|
CEP = txtcep.Text,
|
||||||
|
ENDERECO = txtEndereco.Text,
|
||||||
|
ENDNUMERO = txtEndNumero.Text,
|
||||||
|
BAIRRO = txtBairro.Text,
|
||||||
|
CIDADE = txtCidade.Text,
|
||||||
|
UF = txtUF.Text,
|
||||||
|
|
||||||
|
// 🔥 BANCO vindo do ComboBox
|
||||||
|
BANCO = cbBanco.SelectedValue?.ToString(),
|
||||||
|
|
||||||
|
AGENCIA = txtAgencia.Text,
|
||||||
|
CONTA = txtConta.Text,
|
||||||
|
TELEFONE = txtTelefone.Text,
|
||||||
|
PASS = txtPass.Text,
|
||||||
|
|
||||||
|
// 🔥 BOOL correto
|
||||||
|
MASTERUSER = chkMasterUser.Checked,
|
||||||
|
VENDEDOR = chkVendedor.Checked,
|
||||||
|
TECNICO = chkTecnico.Checked,
|
||||||
|
DEMITIDO = chkDemitido.Checked,
|
||||||
|
|
||||||
|
FTECNICO = chkContador.Checked ? "1" : null,
|
||||||
|
FVENDEDOR = chkOutros.Checked ? "1" : null,
|
||||||
|
|
||||||
|
FPATH = txtFPath.Text,
|
||||||
|
OBSERV = txtObserv.Text,
|
||||||
|
|
||||||
|
// 🔥 DATAS
|
||||||
|
DATA_ADM = ConverterData(txtDataAdm.Text),
|
||||||
|
DATA_DEM = ConverterData(txtDataDem.Text),
|
||||||
|
ANIVER = ConverterData(txtAniver.Text)
|
||||||
|
};
|
||||||
|
|
||||||
|
bool sucesso = isNew
|
||||||
|
? bll.Inserir(funcionario)
|
||||||
|
: bll.Alterar(funcionario);
|
||||||
|
|
||||||
|
if (!sucesso)
|
||||||
|
{
|
||||||
|
NT_MessageBox.Show("Erro ao salvar funcionário.",
|
||||||
|
"Erro", MessageBoxButtons.OK, MessageBoxIcon.Error);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
SetCampos(false);
|
||||||
|
|
||||||
|
NT_MessageBox.Show("Funcionário salvo com sucesso!", "Sucesso",
|
||||||
|
MessageBoxButtons.OK, MessageBoxIcon.Information);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void BtnFichaFuncionario_Click()
|
||||||
|
{
|
||||||
|
var bll = new BLLFuncionarios(_cx);
|
||||||
|
|
||||||
|
var funcionario = bll.CarregarPorCodigo("100");
|
||||||
|
|
||||||
|
if (funcionario == null)
|
||||||
|
{
|
||||||
|
MessageBox.Show("Funcionário não encontrado.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var resultado = TLL.FichaFuncionarioPDF.GerarEAbrir(funcionario);
|
||||||
|
|
||||||
|
if (!resultado.Sucesso)
|
||||||
|
MessageBox.Show(resultado.Mensagem, "Erro",
|
||||||
|
MessageBoxButtons.OK, MessageBoxIcon.Error);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void BtnCancelar_Click()
|
||||||
|
{
|
||||||
|
foreach (var campo in TodosOsCampos())
|
||||||
|
campo.Text = string.Empty;
|
||||||
|
|
||||||
|
foreach (var chk in TodosOsChecks())
|
||||||
|
chk.Checked = false;
|
||||||
|
|
||||||
|
//SetCampos(false);
|
||||||
|
SetCamposAtulizado(false);
|
||||||
|
//this.cbBanco.Enabled = 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 RoundComboBox AddComboBox(Control parent, string label,
|
||||||
|
int x, int y, int width, int height)
|
||||||
|
{
|
||||||
|
var lbl = new Label
|
||||||
|
{
|
||||||
|
Text = label,
|
||||||
|
Location = new Point(x, y),
|
||||||
|
Font = new Font("Segoe UI", 7.5f, FontStyle.Bold),
|
||||||
|
ForeColor = TextDark,
|
||||||
|
AutoSize = true
|
||||||
|
};
|
||||||
|
var cb = new RoundComboBox
|
||||||
|
{
|
||||||
|
Location = new Point(x, y + 16),
|
||||||
|
Size = new Size(width, height),
|
||||||
|
Radius = 4,
|
||||||
|
BorderColor = BorderColor,
|
||||||
|
FocusColor = AccentBlue,
|
||||||
|
BackColor = Color.White
|
||||||
|
};
|
||||||
|
parent.Controls.Add(lbl);
|
||||||
|
parent.Controls.Add(cb);
|
||||||
|
return cb;
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// ══════════════════════════════════════════════════════════════════════════
|
||||||
|
// DIALOG: Escolher origem da foto (Computador ou Webcam)
|
||||||
|
// ══════════════════════════════════════════════════════════════════════════
|
||||||
|
|
||||||
|
public class FotoOrigemDialog : Form
|
||||||
|
{
|
||||||
|
public bool UsarWebcam { get; private set; }
|
||||||
|
|
||||||
|
public FotoOrigemDialog()
|
||||||
|
{
|
||||||
|
Text = "Selecionar Foto";
|
||||||
|
Size = new Size(340, 160);
|
||||||
|
StartPosition = FormStartPosition.CenterParent;
|
||||||
|
FormBorderStyle = FormBorderStyle.FixedDialog;
|
||||||
|
MaximizeBox = false;
|
||||||
|
MinimizeBox = false;
|
||||||
|
BackColor = Color.White;
|
||||||
|
|
||||||
|
var lbl = new Label
|
||||||
|
{
|
||||||
|
Text = "Como deseja adicionar a foto?",
|
||||||
|
Font = new Font("Segoe UI", 9.5f),
|
||||||
|
Location = new Point(20, 18),
|
||||||
|
AutoSize = true
|
||||||
|
};
|
||||||
|
|
||||||
|
var btnComputador = new Button
|
||||||
|
{
|
||||||
|
Text = "📁 Do Computador",
|
||||||
|
Location = new Point(20, 55),
|
||||||
|
Size = new Size(140, 38),
|
||||||
|
FlatStyle = FlatStyle.Flat,
|
||||||
|
BackColor = Color.FromArgb(37, 99, 235),
|
||||||
|
ForeColor = Color.White,
|
||||||
|
Font = new Font("Segoe UI", 9f),
|
||||||
|
Cursor = Cursors.Hand
|
||||||
|
};
|
||||||
|
btnComputador.FlatAppearance.BorderSize = 0;
|
||||||
|
btnComputador.Click += (s, e) =>
|
||||||
|
{
|
||||||
|
UsarWebcam = false;
|
||||||
|
DialogResult = DialogResult.OK;
|
||||||
|
Close();
|
||||||
|
};
|
||||||
|
|
||||||
|
var btnWebcam = new Button
|
||||||
|
{
|
||||||
|
Text = "📷 Webcam",
|
||||||
|
Location = new Point(172, 55),
|
||||||
|
Size = new Size(140, 38),
|
||||||
|
FlatStyle = FlatStyle.Flat,
|
||||||
|
BackColor = Color.FromArgb(16, 185, 129),
|
||||||
|
ForeColor = Color.White,
|
||||||
|
Font = new Font("Segoe UI", 9f),
|
||||||
|
Cursor = Cursors.Hand
|
||||||
|
};
|
||||||
|
btnWebcam.FlatAppearance.BorderSize = 0;
|
||||||
|
btnWebcam.Click += (s, e) =>
|
||||||
|
{
|
||||||
|
UsarWebcam = true;
|
||||||
|
DialogResult = DialogResult.OK;
|
||||||
|
Close();
|
||||||
|
};
|
||||||
|
|
||||||
|
Controls.AddRange(new Control[] { lbl, btnComputador, btnWebcam });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ══════════════════════════════════════════════════════════════════════════
|
||||||
|
// FORM: Captura pela Webcam usando AForge
|
||||||
|
// ══════════════════════════════════════════════════════════════════════════
|
||||||
|
|
||||||
|
public class WebcamCaptureForm : Form
|
||||||
|
{
|
||||||
|
public Bitmap? ImagemCapturada { get; private set; }
|
||||||
|
|
||||||
|
private PictureBox picPreview = null!;
|
||||||
|
private VideoCaptureDevice? _camera;
|
||||||
|
private Bitmap? _frameAtual;
|
||||||
|
|
||||||
|
public WebcamCaptureForm()
|
||||||
|
{
|
||||||
|
Text = "Capturar Foto pela Webcam";
|
||||||
|
Size = new Size(680, 560);
|
||||||
|
StartPosition = FormStartPosition.CenterParent;
|
||||||
|
FormBorderStyle = FormBorderStyle.FixedDialog;
|
||||||
|
MaximizeBox = false;
|
||||||
|
BackColor = Color.FromArgb(15, 23, 42);
|
||||||
|
|
||||||
|
picPreview = new PictureBox
|
||||||
|
{
|
||||||
|
Location = new Point(20, 20),
|
||||||
|
Size = new Size(628, 440),
|
||||||
|
SizeMode = PictureBoxSizeMode.Zoom,
|
||||||
|
BackColor = Color.Black
|
||||||
|
};
|
||||||
|
Controls.Add(picPreview);
|
||||||
|
|
||||||
|
var btnCapturar = new Button
|
||||||
|
{
|
||||||
|
Text = "📷 Capturar",
|
||||||
|
Location = new Point(20, 475),
|
||||||
|
Size = new Size(200, 38),
|
||||||
|
FlatStyle = FlatStyle.Flat,
|
||||||
|
BackColor = Color.FromArgb(37, 99, 235),
|
||||||
|
ForeColor = Color.White,
|
||||||
|
Font = new Font("Segoe UI", 9.5f),
|
||||||
|
Cursor = Cursors.Hand
|
||||||
|
};
|
||||||
|
btnCapturar.FlatAppearance.BorderSize = 0;
|
||||||
|
btnCapturar.Click += BtnCapturar_Click;
|
||||||
|
Controls.Add(btnCapturar);
|
||||||
|
|
||||||
|
var btnCancelar = new Button
|
||||||
|
{
|
||||||
|
Text = "Cancelar",
|
||||||
|
Location = new Point(234, 475),
|
||||||
|
Size = new Size(120, 38),
|
||||||
|
FlatStyle = FlatStyle.Flat,
|
||||||
|
BackColor = Color.FromArgb(100, 116, 139),
|
||||||
|
ForeColor = Color.White,
|
||||||
|
Font = new Font("Segoe UI", 9.5f),
|
||||||
|
Cursor = Cursors.Hand
|
||||||
|
};
|
||||||
|
btnCancelar.FlatAppearance.BorderSize = 0;
|
||||||
|
btnCancelar.Click += (s, e) => { PararCamera(); DialogResult = DialogResult.Cancel; Close(); };
|
||||||
|
Controls.Add(btnCancelar);
|
||||||
|
|
||||||
|
FormClosing += (s, e) => PararCamera();
|
||||||
|
|
||||||
|
IniciarCamera();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void IniciarCamera()
|
||||||
|
{
|
||||||
|
var cameras = new FilterInfoCollection(FilterCategory.VideoInputDevice);
|
||||||
|
|
||||||
|
if (cameras.Count == 0)
|
||||||
|
{
|
||||||
|
MessageBox.Show("Nenhuma webcam encontrada.", "Webcam",
|
||||||
|
MessageBoxButtons.OK, MessageBoxIcon.Warning);
|
||||||
|
DialogResult = DialogResult.Cancel;
|
||||||
|
Close();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
_camera = new VideoCaptureDevice(cameras[0].MonikerString);
|
||||||
|
_camera.NewFrame += Camera_NewFrame;
|
||||||
|
_camera.Start();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Camera_NewFrame(object sender, NewFrameEventArgs e)
|
||||||
|
{
|
||||||
|
_frameAtual?.Dispose();
|
||||||
|
_frameAtual = (Bitmap)e.Frame.Clone();
|
||||||
|
|
||||||
|
picPreview.Invoke((MethodInvoker)(() =>
|
||||||
|
{
|
||||||
|
picPreview.Image?.Dispose();
|
||||||
|
picPreview.Image = (Bitmap)_frameAtual.Clone();
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void BtnCapturar_Click(object? sender, EventArgs e)
|
||||||
|
{
|
||||||
|
if (_frameAtual == null)
|
||||||
|
{
|
||||||
|
MessageBox.Show("Aguarde a câmera inicializar.", "Atenção",
|
||||||
|
MessageBoxButtons.OK, MessageBoxIcon.Warning);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ImagemCapturada = (Bitmap)_frameAtual.Clone();
|
||||||
|
PararCamera();
|
||||||
|
DialogResult = DialogResult.OK;
|
||||||
|
Close();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void PararCamera()
|
||||||
|
{
|
||||||
|
if (_camera != null && _camera.IsRunning)
|
||||||
|
{
|
||||||
|
_camera.SignalToStop();
|
||||||
|
_camera.WaitForStop();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
120
Dashboards/Cadastros/FuncionariosCadastroPanel.resx
Normal file
120
Dashboards/Cadastros/FuncionariosCadastroPanel.resx
Normal file
@ -0,0 +1,120 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<root>
|
||||||
|
<!--
|
||||||
|
Microsoft ResX Schema
|
||||||
|
|
||||||
|
Version 2.0
|
||||||
|
|
||||||
|
The primary goals of this format is to allow a simple XML format
|
||||||
|
that is mostly human readable. The generation and parsing of the
|
||||||
|
various data types are done through the TypeConverter classes
|
||||||
|
associated with the data types.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
... ado.net/XML headers & schema ...
|
||||||
|
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||||
|
<resheader name="version">2.0</resheader>
|
||||||
|
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||||
|
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||||
|
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
||||||
|
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||||
|
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||||
|
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
||||||
|
</data>
|
||||||
|
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||||
|
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||||
|
<comment>This is a comment</comment>
|
||||||
|
</data>
|
||||||
|
|
||||||
|
There are any number of "resheader" rows that contain simple
|
||||||
|
name/value pairs.
|
||||||
|
|
||||||
|
Each data row contains a name, and value. The row also contains a
|
||||||
|
type or mimetype. Type corresponds to a .NET class that support
|
||||||
|
text/value conversion through the TypeConverter architecture.
|
||||||
|
Classes that don't support this are serialized and stored with the
|
||||||
|
mimetype set.
|
||||||
|
|
||||||
|
The mimetype is used for serialized objects, and tells the
|
||||||
|
ResXResourceReader how to depersist the object. This is currently not
|
||||||
|
extensible. For a given mimetype the value must be set accordingly:
|
||||||
|
|
||||||
|
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||||
|
that the ResXResourceWriter will generate, however the reader can
|
||||||
|
read any of the formats listed below.
|
||||||
|
|
||||||
|
mimetype: application/x-microsoft.net.object.binary.base64
|
||||||
|
value : The object must be serialized with
|
||||||
|
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
|
||||||
|
: and then encoded with base64 encoding.
|
||||||
|
|
||||||
|
mimetype: application/x-microsoft.net.object.soap.base64
|
||||||
|
value : The object must be serialized with
|
||||||
|
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||||
|
: and then encoded with base64 encoding.
|
||||||
|
|
||||||
|
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||||
|
value : The object must be serialized into a byte array
|
||||||
|
: using a System.ComponentModel.TypeConverter
|
||||||
|
: and then encoded with base64 encoding.
|
||||||
|
-->
|
||||||
|
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||||
|
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
||||||
|
<xsd:element name="root" msdata:IsDataSet="true">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:choice maxOccurs="unbounded">
|
||||||
|
<xsd:element name="metadata">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:sequence>
|
||||||
|
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||||
|
</xsd:sequence>
|
||||||
|
<xsd:attribute name="name" use="required" type="xsd:string" />
|
||||||
|
<xsd:attribute name="type" type="xsd:string" />
|
||||||
|
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||||
|
<xsd:attribute ref="xml:space" />
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
<xsd:element name="assembly">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:attribute name="alias" type="xsd:string" />
|
||||||
|
<xsd:attribute name="name" type="xsd:string" />
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
<xsd:element name="data">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:sequence>
|
||||||
|
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||||
|
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||||
|
</xsd:sequence>
|
||||||
|
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
|
||||||
|
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||||
|
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||||
|
<xsd:attribute ref="xml:space" />
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
<xsd:element name="resheader">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:sequence>
|
||||||
|
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||||
|
</xsd:sequence>
|
||||||
|
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
</xsd:choice>
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
</xsd:schema>
|
||||||
|
<resheader name="resmimetype">
|
||||||
|
<value>text/microsoft-resx</value>
|
||||||
|
</resheader>
|
||||||
|
<resheader name="version">
|
||||||
|
<value>2.0</value>
|
||||||
|
</resheader>
|
||||||
|
<resheader name="reader">
|
||||||
|
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||||
|
</resheader>
|
||||||
|
<resheader name="writer">
|
||||||
|
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||||
|
</resheader>
|
||||||
|
</root>
|
||||||
338
Dashboards/Configurações/Database/FrmConfigBanco.cs
Normal file
338
Dashboards/Configurações/Database/FrmConfigBanco.cs
Normal file
@ -0,0 +1,338 @@
|
|||||||
|
using CCH;
|
||||||
|
using CustomMessageBox;
|
||||||
|
using DAL;
|
||||||
|
using Microsoft.Data.SqlClient; // Certifique-se de ter este pacote NuGet instalado
|
||||||
|
using System;
|
||||||
|
using System.Drawing;
|
||||||
|
using System.Drawing.Drawing2D;
|
||||||
|
using System.Windows.Forms;
|
||||||
|
using TLL;
|
||||||
|
|
||||||
|
namespace UI
|
||||||
|
{
|
||||||
|
public class FrmConfigBanco : Form
|
||||||
|
{
|
||||||
|
// ── Cores LevelOS ──────────────────────────────────────────────────
|
||||||
|
private static readonly Color Surface = Color.White;
|
||||||
|
private static readonly Color Surface2 = Color.FromArgb(241, 245, 249);
|
||||||
|
private static readonly Color BorderCol = Color.FromArgb(226, 232, 240);
|
||||||
|
private static readonly Color TextPri = Color.FromArgb(15, 23, 42);
|
||||||
|
private static readonly Color TextSec = Color.FromArgb(71, 85, 105);
|
||||||
|
private static readonly Color TextMuted = Color.FromArgb(148, 163, 184);
|
||||||
|
private static readonly Color Blue = Color.FromArgb(37, 99, 235);
|
||||||
|
private static readonly Color Green = Color.FromArgb(22, 163, 74);
|
||||||
|
private static readonly Color Red = Color.FromArgb(220, 38, 38);
|
||||||
|
private static readonly Color NavyDark = Color.FromArgb(15, 30, 60);
|
||||||
|
|
||||||
|
// ── Controles ──────────────────────────────────────────────────────
|
||||||
|
private readonly TextBox txtHost = new();
|
||||||
|
private readonly TextBox txtPort = new();
|
||||||
|
private readonly TextBox txtBanco = new();
|
||||||
|
private readonly TextBox txtUsuario = new();
|
||||||
|
private readonly TextBox txtSenha = new();
|
||||||
|
private readonly TextBox txtTimeout = new();
|
||||||
|
private readonly CheckBox chkEncrypt = new();
|
||||||
|
private readonly CheckBox chkTrust = new();
|
||||||
|
private readonly Button btnSalvar = new();
|
||||||
|
private readonly Button btnTestar = new();
|
||||||
|
private readonly Button btnCancelar = new();
|
||||||
|
private readonly Label lblStatus = new();
|
||||||
|
|
||||||
|
public FrmConfigBanco()
|
||||||
|
{
|
||||||
|
Text = "LevelOS — Configuração do Banco de Dados";
|
||||||
|
Size = new Size(660, 680);
|
||||||
|
StartPosition = FormStartPosition.CenterScreen;
|
||||||
|
BackColor = Surface2;
|
||||||
|
FormBorderStyle = FormBorderStyle.FixedDialog;
|
||||||
|
MaximizeBox = false;
|
||||||
|
|
||||||
|
BuildLayout();
|
||||||
|
CarregarValores();
|
||||||
|
|
||||||
|
// ── Eventos ──────────────────────────────────────────────────
|
||||||
|
btnSalvar.Click += BtnSalvar_Click;
|
||||||
|
btnTestar.Click += BtnTestar_Click;
|
||||||
|
btnCancelar.Click += (s, e) => Close();
|
||||||
|
|
||||||
|
//Carregar dados
|
||||||
|
if (!File.Exists(AppFileSystem.AppFileDBSystem))
|
||||||
|
{
|
||||||
|
NT_MessageBox.Show("Arquivo de configuração do banco de dados ausente, por favor contacte o administrador do sistema para solucionar o problema", "Erro de SQL:101",
|
||||||
|
MessageBoxButtons.OK,MessageBoxIcon.Error);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
DatabaseHelper.Carregar(AppFileSystem.AppFileDBSystem, AppInfoSystem.AppKeyMasterCrip);
|
||||||
|
this.txtHost.Text = DadosDaConexao.Host;
|
||||||
|
this.txtPort.Text = DadosDaConexao.Port.ToString();
|
||||||
|
this.txtBanco.Text = DadosDaConexao.Banco;
|
||||||
|
this.txtUsuario.Text = DadosDaConexao.Usuario;
|
||||||
|
this.txtSenha.Text = DadosDaConexao.Senha;
|
||||||
|
this.chkEncrypt.Checked = DadosDaConexao.Encrypt;
|
||||||
|
this.txtTimeout.Text = DadosDaConexao.ConnectTimeout.ToString();
|
||||||
|
this.chkTrust.Checked = DadosDaConexao.TrustServerCertificate;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void BuildLayout()
|
||||||
|
{
|
||||||
|
// 1. TOPBAR
|
||||||
|
var topbar = new Panel { Dock = DockStyle.Top, Height = 75, BackColor = NavyDark };
|
||||||
|
topbar.Paint += DrawTopbar;
|
||||||
|
Controls.Add(topbar);
|
||||||
|
|
||||||
|
// 2. RODAPÉ
|
||||||
|
var footer = new Panel { Dock = DockStyle.Bottom, Height = 65, BackColor = Surface };
|
||||||
|
footer.Paint += (s, e) => e.Graphics.DrawLine(new Pen(BorderCol), 0, 0, footer.Width, 0);
|
||||||
|
Controls.Add(footer);
|
||||||
|
|
||||||
|
StyleButton(btnCancelar, "Cancelar", Surface, TextSec, BorderCol);
|
||||||
|
btnCancelar.SetBounds(20, 15, 100, 35);
|
||||||
|
btnCancelar.Anchor = AnchorStyles.Left;
|
||||||
|
footer.Controls.Add(btnCancelar);
|
||||||
|
|
||||||
|
StyleButton(btnSalvar, "✔ Salvar", Blue, Color.White);
|
||||||
|
btnSalvar.SetBounds(footer.Width - 120, 15, 100, 35);
|
||||||
|
btnSalvar.Anchor = AnchorStyles.Right;
|
||||||
|
footer.Controls.Add(btnSalvar);
|
||||||
|
|
||||||
|
StyleButton(btnTestar, "Testar conexão", Surface, TextPri, BorderCol);
|
||||||
|
btnTestar.SetBounds(btnSalvar.Left - 145, 15, 135, 35);
|
||||||
|
btnTestar.Anchor = AnchorStyles.Right;
|
||||||
|
footer.Controls.Add(btnTestar);
|
||||||
|
|
||||||
|
lblStatus.SetBounds(130, 15, 250, 35);
|
||||||
|
lblStatus.TextAlign = ContentAlignment.MiddleLeft;
|
||||||
|
lblStatus.Font = new Font("Segoe UI", 9f);
|
||||||
|
lblStatus.Anchor = AnchorStyles.Left | AnchorStyles.Right;
|
||||||
|
footer.Controls.Add(lblStatus);
|
||||||
|
|
||||||
|
// 3. CONTAINER DE CONTEÚDO
|
||||||
|
var pnlContainer = new Panel { Dock = DockStyle.Fill, AutoScroll = true, Padding = new Padding(0, 10, 0, 20) };
|
||||||
|
Controls.Add(pnlContainer);
|
||||||
|
pnlContainer.BringToFront();
|
||||||
|
|
||||||
|
// 4. CARD BRANCO
|
||||||
|
var card = new Panel { BackColor = Surface, Width = 560, Left = 40, Top = 20 };
|
||||||
|
pnlContainer.Controls.Add(card);
|
||||||
|
|
||||||
|
int cy = 30;
|
||||||
|
|
||||||
|
cy = AddSection(card, "SERVIDOR", cy);
|
||||||
|
AddLabel(card, "Host / IP", 30, cy);
|
||||||
|
AddLabel(card, "Porta", 430, cy);
|
||||||
|
cy += 20;
|
||||||
|
StyleInput(txtHost, "ex: localhost ou 192.168.0.1");
|
||||||
|
txtHost.SetBounds(30, cy, 385, 30); card.Controls.Add(txtHost);
|
||||||
|
StyleInput(txtPort, "1433");
|
||||||
|
txtPort.SetBounds(430, cy, 100, 30); card.Controls.Add(txtPort);
|
||||||
|
cy += 45;
|
||||||
|
|
||||||
|
cy = AddSection(card, "BANCO DE DADOS", cy);
|
||||||
|
AddLabel(card, "Nome do Banco", 30, cy);
|
||||||
|
cy += 20;
|
||||||
|
StyleInput(txtBanco, "ex: LevelOS_DB");
|
||||||
|
txtBanco.SetBounds(30, cy, 500, 30); card.Controls.Add(txtBanco);
|
||||||
|
cy += 45;
|
||||||
|
|
||||||
|
cy = AddSection(card, "AUTENTICAÇÃO", cy);
|
||||||
|
AddLabel(card, "Usuário", 30, cy);
|
||||||
|
AddLabel(card, "Senha", 285, cy);
|
||||||
|
cy += 20;
|
||||||
|
StyleInput(txtUsuario, "sa");
|
||||||
|
txtUsuario.SetBounds(30, cy, 245, 30); card.Controls.Add(txtUsuario);
|
||||||
|
StyleInput(txtSenha, "••••••••");
|
||||||
|
txtSenha.SetBounds(285, cy, 245, 30); txtSenha.PasswordChar = '●'; card.Controls.Add(txtSenha);
|
||||||
|
cy += 45;
|
||||||
|
|
||||||
|
cy = AddSection(card, "AVANÇADO", cy);
|
||||||
|
AddLabel(card, "Timeout de conexão (segundos)", 30, cy);
|
||||||
|
cy += 20;
|
||||||
|
StyleInput(txtTimeout, "3");
|
||||||
|
txtTimeout.SetBounds(30, cy, 100, 30); card.Controls.Add(txtTimeout);
|
||||||
|
cy += 40;
|
||||||
|
|
||||||
|
StyleCheckbox(chkEncrypt, "Encrypt Connection");
|
||||||
|
chkEncrypt.SetBounds(30, cy, 250, 25); card.Controls.Add(chkEncrypt);
|
||||||
|
cy += 30;
|
||||||
|
StyleCheckbox(chkTrust, "Trust Server Certificate");
|
||||||
|
chkTrust.SetBounds(30, cy, 250, 25); card.Controls.Add(chkTrust);
|
||||||
|
cy += 40;
|
||||||
|
|
||||||
|
card.Height = cy;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ── Lógica de Negócio ──────────────────────────────────────────────
|
||||||
|
|
||||||
|
private void CarregarValores()
|
||||||
|
{
|
||||||
|
txtHost.Text = DbConfig.Host;
|
||||||
|
txtPort.Text = DbConfig.Port.ToString();
|
||||||
|
txtBanco.Text = DbConfig.Banco;
|
||||||
|
txtUsuario.Text = DbConfig.Usuario;
|
||||||
|
txtSenha.Text = DbConfig.Senha;
|
||||||
|
txtTimeout.Text = DbConfig.ConnectTimeout.ToString();
|
||||||
|
chkEncrypt.Checked = DbConfig.Encrypt;
|
||||||
|
chkTrust.Checked = DbConfig.TrustServerCertificate;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void BtnSalvar_Click(object? sender, EventArgs e)
|
||||||
|
{
|
||||||
|
if (!Validar()) return;
|
||||||
|
|
||||||
|
DbConfig.Host = txtHost.Text.Trim();
|
||||||
|
DbConfig.Port = int.TryParse(txtPort.Text, out int p) ? p : 1433;
|
||||||
|
DbConfig.Banco = txtBanco.Text.Trim();
|
||||||
|
DbConfig.Usuario = txtUsuario.Text.Trim();
|
||||||
|
DbConfig.Senha = txtSenha.Text;
|
||||||
|
DbConfig.ConnectTimeout = int.TryParse(txtTimeout.Text, out int t) ? t : 3;
|
||||||
|
DbConfig.Encrypt = chkEncrypt.Checked;
|
||||||
|
DbConfig.TrustServerCertificate = chkTrust.Checked;
|
||||||
|
|
||||||
|
//Preenchendo dados da conexao
|
||||||
|
DadosDaConexao.Host = DbConfig.Host;
|
||||||
|
DadosDaConexao.Port = DbConfig.Port;
|
||||||
|
DadosDaConexao.Banco =DbConfig.Banco;
|
||||||
|
DadosDaConexao.Usuario = DbConfig.Usuario;
|
||||||
|
DadosDaConexao.Senha = DbConfig.Senha;
|
||||||
|
DadosDaConexao.ConnectTimeout = DbConfig.ConnectTimeout;
|
||||||
|
DadosDaConexao.Encrypt = chkEncrypt.Checked;
|
||||||
|
DadosDaConexao.TrustServerCertificate = chkTrust.Checked;
|
||||||
|
//salvar em arquivo criptografado
|
||||||
|
DatabaseHelper.Salvar(AppFileSystem.AppFileDBSystem, AppInfoSystem.AppKeyMasterCrip);
|
||||||
|
|
||||||
|
|
||||||
|
SetStatus("✔ Configurações salvas!", Green);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void BtnTestar_Click(object? sender, EventArgs e)
|
||||||
|
{
|
||||||
|
if (!Validar()) return;
|
||||||
|
|
||||||
|
SetStatus("⏳ Testando...", TextMuted);
|
||||||
|
btnTestar.Enabled = false;
|
||||||
|
Application.DoEvents(); // Força a interface a atualizar o status
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
using var conn = new SqlConnection(BuildConnStr());
|
||||||
|
conn.Open();
|
||||||
|
SetStatus($"✔ Conectado! SQL {conn.ServerVersion}", Green);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
SetStatus($"✖ Erro: {ex.Message}", Red);
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
btnTestar.Enabled = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private string BuildConnStr()
|
||||||
|
{
|
||||||
|
SqlConnectionStringBuilder builder = new()
|
||||||
|
{
|
||||||
|
DataSource = $"{txtHost.Text.Trim()},{txtPort.Text.Trim()}",
|
||||||
|
InitialCatalog = txtBanco.Text.Trim(),
|
||||||
|
UserID = txtUsuario.Text.Trim(),
|
||||||
|
Password = txtSenha.Text,
|
||||||
|
ConnectTimeout = int.TryParse(txtTimeout.Text, out int t) ? t : 3,
|
||||||
|
Encrypt = chkEncrypt.Checked,
|
||||||
|
TrustServerCertificate = chkTrust.Checked
|
||||||
|
};
|
||||||
|
return builder.ConnectionString;
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool Validar()
|
||||||
|
{
|
||||||
|
if (string.IsNullOrWhiteSpace(txtHost.Text)) { SetStatus("✖ Informe o Host.", Red); txtHost.Focus(); return false; }
|
||||||
|
if (string.IsNullOrWhiteSpace(txtBanco.Text)) { SetStatus("✖ Informe o Banco.", Red); txtBanco.Focus(); return false; }
|
||||||
|
if (string.IsNullOrWhiteSpace(txtUsuario.Text)) { SetStatus("✖ Informe o Usuário.", Red); txtUsuario.Focus(); return false; }
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void SetStatus(string msg, Color color)
|
||||||
|
{
|
||||||
|
lblStatus.Text = msg;
|
||||||
|
lblStatus.ForeColor = color;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ── Helpers de UI ──────────────────────────────────────────────────
|
||||||
|
|
||||||
|
private void DrawTopbar(object sender, PaintEventArgs e)
|
||||||
|
{
|
||||||
|
var g = e.Graphics;
|
||||||
|
g.SmoothingMode = SmoothingMode.AntiAlias;
|
||||||
|
var rect = new Rectangle(25, 20, 34, 34);
|
||||||
|
using var path = RoundRectPath(rect, 8);
|
||||||
|
g.FillPath(new SolidBrush(Blue), path);
|
||||||
|
g.DrawString("S", new Font("Segoe UI", 14, FontStyle.Bold), Brushes.White, rect, new StringFormat { Alignment = StringAlignment.Center, LineAlignment = StringAlignment.Center });
|
||||||
|
g.DrawString("Configuração do Banco", new Font("Segoe UI Semibold", 12.5f), Brushes.White, 70, 18);
|
||||||
|
g.DrawString("Defina os parâmetros de conexão com o SQL Server", new Font("Segoe UI", 9), new SolidBrush(Color.FromArgb(148, 163, 184)), 70, 40);
|
||||||
|
}
|
||||||
|
|
||||||
|
private int AddSection(Panel p, string title, int y)
|
||||||
|
{
|
||||||
|
var line = new Panel { BackColor = BorderCol, Height = 1, Width = p.Width - 60, Left = 30, Top = y };
|
||||||
|
p.Controls.Add(line);
|
||||||
|
var lbl = new Label { Text = title, Font = new Font("Segoe UI", 7, FontStyle.Bold), ForeColor = TextMuted, Top = y - 7, Left = 35, AutoSize = true, BackColor = Surface };
|
||||||
|
p.Controls.Add(lbl);
|
||||||
|
lbl.BringToFront();
|
||||||
|
return y + 20;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void AddLabel(Panel p, string txt, int x, int y)
|
||||||
|
{
|
||||||
|
p.Controls.Add(new Label { Text = txt, Font = new Font("Segoe UI Semibold", 9), ForeColor = TextSec, Left = x, Top = y, AutoSize = true });
|
||||||
|
}
|
||||||
|
|
||||||
|
private void StyleInput(TextBox t, string placeholder)
|
||||||
|
{
|
||||||
|
t.BorderStyle = BorderStyle.FixedSingle;
|
||||||
|
t.Font = new Font("Segoe UI", 10);
|
||||||
|
t.PlaceholderText = placeholder;
|
||||||
|
t.BackColor = Color.FromArgb(250, 251, 253);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void StyleCheckbox(CheckBox chk, string text)
|
||||||
|
{
|
||||||
|
chk.Text = text; chk.Font = new Font("Segoe UI", 9.5f);
|
||||||
|
chk.ForeColor = TextSec; chk.Cursor = Cursors.Hand;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void StyleButton(Button b, string txt, Color bg, Color fg, Color? borda = null)
|
||||||
|
{
|
||||||
|
b.Text = txt; b.FlatStyle = FlatStyle.Flat; b.BackColor = bg; b.ForeColor = fg; b.Cursor = Cursors.Hand;
|
||||||
|
b.Font = new Font("Segoe UI Semibold", 9.5f);
|
||||||
|
b.FlatAppearance.BorderSize = borda.HasValue ? 1 : 0;
|
||||||
|
if (borda.HasValue) b.FlatAppearance.BorderColor = borda.Value;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static GraphicsPath RoundRectPath(Rectangle r, int radius)
|
||||||
|
{
|
||||||
|
var path = new GraphicsPath();
|
||||||
|
int d = radius * 2;
|
||||||
|
path.AddArc(r.X, r.Y, d, d, 180, 90);
|
||||||
|
path.AddArc(r.Right - d, r.Y, d, d, 270, 90);
|
||||||
|
path.AddArc(r.Right - d, r.Bottom - d, d, d, 0, 90);
|
||||||
|
path.AddArc(r.X, r.Bottom - d, d, d, 90, 90);
|
||||||
|
path.CloseFigure();
|
||||||
|
return path;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ── Dados (DbConfig) ──────────────────────────────────────────────────
|
||||||
|
public static class DbConfig
|
||||||
|
{
|
||||||
|
public static string Host { get; set; } = "localhost";
|
||||||
|
public static int Port { get; set; } = 1433;
|
||||||
|
public static string Banco { get; set; } = "";
|
||||||
|
public static string Usuario { get; set; } = "sa";
|
||||||
|
public static string Senha { get; set; } = "";
|
||||||
|
public static int ConnectTimeout { get; set; } = 3;
|
||||||
|
public static bool Encrypt { get; set; } = true;
|
||||||
|
public static bool TrustServerCertificate { get; set; } = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
120
Dashboards/Configurações/Database/FrmConfigBanco.resx
Normal file
120
Dashboards/Configurações/Database/FrmConfigBanco.resx
Normal file
@ -0,0 +1,120 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<root>
|
||||||
|
<!--
|
||||||
|
Microsoft ResX Schema
|
||||||
|
|
||||||
|
Version 2.0
|
||||||
|
|
||||||
|
The primary goals of this format is to allow a simple XML format
|
||||||
|
that is mostly human readable. The generation and parsing of the
|
||||||
|
various data types are done through the TypeConverter classes
|
||||||
|
associated with the data types.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
... ado.net/XML headers & schema ...
|
||||||
|
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||||
|
<resheader name="version">2.0</resheader>
|
||||||
|
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||||
|
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||||
|
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
||||||
|
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||||
|
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||||
|
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
||||||
|
</data>
|
||||||
|
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||||
|
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||||
|
<comment>This is a comment</comment>
|
||||||
|
</data>
|
||||||
|
|
||||||
|
There are any number of "resheader" rows that contain simple
|
||||||
|
name/value pairs.
|
||||||
|
|
||||||
|
Each data row contains a name, and value. The row also contains a
|
||||||
|
type or mimetype. Type corresponds to a .NET class that support
|
||||||
|
text/value conversion through the TypeConverter architecture.
|
||||||
|
Classes that don't support this are serialized and stored with the
|
||||||
|
mimetype set.
|
||||||
|
|
||||||
|
The mimetype is used for serialized objects, and tells the
|
||||||
|
ResXResourceReader how to depersist the object. This is currently not
|
||||||
|
extensible. For a given mimetype the value must be set accordingly:
|
||||||
|
|
||||||
|
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||||
|
that the ResXResourceWriter will generate, however the reader can
|
||||||
|
read any of the formats listed below.
|
||||||
|
|
||||||
|
mimetype: application/x-microsoft.net.object.binary.base64
|
||||||
|
value : The object must be serialized with
|
||||||
|
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
|
||||||
|
: and then encoded with base64 encoding.
|
||||||
|
|
||||||
|
mimetype: application/x-microsoft.net.object.soap.base64
|
||||||
|
value : The object must be serialized with
|
||||||
|
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||||
|
: and then encoded with base64 encoding.
|
||||||
|
|
||||||
|
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||||
|
value : The object must be serialized into a byte array
|
||||||
|
: using a System.ComponentModel.TypeConverter
|
||||||
|
: and then encoded with base64 encoding.
|
||||||
|
-->
|
||||||
|
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||||
|
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
||||||
|
<xsd:element name="root" msdata:IsDataSet="true">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:choice maxOccurs="unbounded">
|
||||||
|
<xsd:element name="metadata">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:sequence>
|
||||||
|
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||||
|
</xsd:sequence>
|
||||||
|
<xsd:attribute name="name" use="required" type="xsd:string" />
|
||||||
|
<xsd:attribute name="type" type="xsd:string" />
|
||||||
|
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||||
|
<xsd:attribute ref="xml:space" />
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
<xsd:element name="assembly">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:attribute name="alias" type="xsd:string" />
|
||||||
|
<xsd:attribute name="name" type="xsd:string" />
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
<xsd:element name="data">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:sequence>
|
||||||
|
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||||
|
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||||
|
</xsd:sequence>
|
||||||
|
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
|
||||||
|
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||||
|
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||||
|
<xsd:attribute ref="xml:space" />
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
<xsd:element name="resheader">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:sequence>
|
||||||
|
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||||
|
</xsd:sequence>
|
||||||
|
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
</xsd:choice>
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
</xsd:schema>
|
||||||
|
<resheader name="resmimetype">
|
||||||
|
<value>text/microsoft-resx</value>
|
||||||
|
</resheader>
|
||||||
|
<resheader name="version">
|
||||||
|
<value>2.0</value>
|
||||||
|
</resheader>
|
||||||
|
<resheader name="reader">
|
||||||
|
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||||
|
</resheader>
|
||||||
|
<resheader name="writer">
|
||||||
|
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||||
|
</resheader>
|
||||||
|
</root>
|
||||||
431
Dashboards/Consultas/AgendaConsultaPanel.cs
Normal file
431
Dashboards/Consultas/AgendaConsultaPanel.cs
Normal file
@ -0,0 +1,431 @@
|
|||||||
|
using BLL;
|
||||||
|
using DAL;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Drawing;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Windows.Forms;
|
||||||
|
|
||||||
|
namespace UI
|
||||||
|
{
|
||||||
|
public class AgendaConsultaPanel : UserControl
|
||||||
|
{
|
||||||
|
// ── CORES ─────────────────────────────────────────────────────────────
|
||||||
|
private readonly Color AccentBlue = Color.FromArgb(37, 99, 235);
|
||||||
|
private readonly Color TextDark = Color.FromArgb(30, 41, 59);
|
||||||
|
private readonly Color BorderColor = Color.FromArgb(226, 232, 240);
|
||||||
|
private readonly Color GreenColor = Color.FromArgb(34, 197, 94);
|
||||||
|
private readonly Color MutedGray = Color.FromArgb(148, 163, 184);
|
||||||
|
private readonly Color SurfaceColor = Color.FromArgb(248, 250, 252);
|
||||||
|
|
||||||
|
// ── CONTROLES ─────────────────────────────────────────────────────────
|
||||||
|
private Panel pnlToolbar = null!;
|
||||||
|
private Panel pnlFiltros = null!;
|
||||||
|
private Panel pnlRodape = null!;
|
||||||
|
private DataGridView dgvAgenda = null!;
|
||||||
|
private Label lblTotal = null!;
|
||||||
|
|
||||||
|
// ── FILTROS ───────────────────────────────────────────────────────────
|
||||||
|
private RoundTextBox txtFiltroCompromisso = null!;
|
||||||
|
private RoundTextBox txtFiltroFunc = null!;
|
||||||
|
private RoundTextBox txtFiltroOsVinc = null!;
|
||||||
|
private RoundTextBox txtDataInicio = null!;
|
||||||
|
private RoundTextBox txtDataFim = null!;
|
||||||
|
private ComboBox cmbSituacao = null!;
|
||||||
|
|
||||||
|
// ── DADOS ─────────────────────────────────────────────────────────────
|
||||||
|
private List<MLL.ModeloAgenda> _todos = new();
|
||||||
|
private List<MLL.ModeloAgenda> _filtrados = new();
|
||||||
|
|
||||||
|
// ── EVENTO: abre cadastro com o registro selecionado ──────────────────
|
||||||
|
public event Action<MLL.ModeloAgenda>? OnAbrirCadastro;
|
||||||
|
|
||||||
|
//Carrega a string conexao com o banco de dados, para ser usada no repositório
|
||||||
|
private string _conexao = DadosDaConexao.ObterConexao();
|
||||||
|
|
||||||
|
// ── CONSTRUTOR ────────────────────────────────────────────────────────
|
||||||
|
public AgendaConsultaPanel()
|
||||||
|
{
|
||||||
|
Dock = DockStyle.Fill;
|
||||||
|
BackColor = Color.White;
|
||||||
|
DoubleBuffered = true;
|
||||||
|
|
||||||
|
InitializeLayout();
|
||||||
|
//CarregarDadosFake();
|
||||||
|
CarregarDadosDoBanco();
|
||||||
|
AplicarFiltros();
|
||||||
|
}
|
||||||
|
|
||||||
|
// ══════════════════════════════════════════════════════════════════════
|
||||||
|
// LAYOUT
|
||||||
|
//
|
||||||
|
// REGRA WINFORMS — ordem de adição ao Controls é INVERSA à exibição:
|
||||||
|
// 1º adicionar → Fill (ocupa o centro)
|
||||||
|
// 2º adicionar → Bottom
|
||||||
|
// 3º adicionar → Top (empurra o Fill para baixo; último = mais alto)
|
||||||
|
//
|
||||||
|
// ══════════════════════════════════════════════════════════════════════
|
||||||
|
private void InitializeLayout()
|
||||||
|
{
|
||||||
|
Controls.Clear();
|
||||||
|
|
||||||
|
// ── 1º: GRID (Fill) ───────────────────────────────────────────────
|
||||||
|
BuildGrid();
|
||||||
|
Controls.Add(dgvAgenda);
|
||||||
|
|
||||||
|
// ── 2º: RODAPÉ (Bottom) ───────────────────────────────────────────
|
||||||
|
pnlRodape = new Panel
|
||||||
|
{
|
||||||
|
Dock = DockStyle.Bottom,
|
||||||
|
Height = 30,
|
||||||
|
BackColor = SurfaceColor
|
||||||
|
};
|
||||||
|
lblTotal = new Label
|
||||||
|
{
|
||||||
|
AutoSize = true,
|
||||||
|
Location = new Point(16, 7),
|
||||||
|
Font = new Font("Segoe UI", 8.5f, FontStyle.Bold),
|
||||||
|
ForeColor = MutedGray,
|
||||||
|
Text = "0 registros encontrados"
|
||||||
|
};
|
||||||
|
pnlRodape.Controls.Add(lblTotal);
|
||||||
|
Controls.Add(pnlRodape);
|
||||||
|
|
||||||
|
// ── 3º: FILTROS (Top) ─────────────────────────────────────────────
|
||||||
|
pnlFiltros = new Panel
|
||||||
|
{
|
||||||
|
Dock = DockStyle.Top,
|
||||||
|
Height = 95,
|
||||||
|
BackColor = SurfaceColor,
|
||||||
|
Padding = new Padding(16, 8, 16, 8)
|
||||||
|
};
|
||||||
|
BuildFiltros();
|
||||||
|
Controls.Add(pnlFiltros);
|
||||||
|
|
||||||
|
// ── 4º: TOOLBAR (Top) — por último = fica acima dos filtros ───────
|
||||||
|
pnlToolbar = new Panel
|
||||||
|
{
|
||||||
|
Dock = DockStyle.Top,
|
||||||
|
Height = 55,
|
||||||
|
BackColor = SurfaceColor
|
||||||
|
};
|
||||||
|
|
||||||
|
var flow = new FlowLayoutPanel
|
||||||
|
{
|
||||||
|
Dock = DockStyle.Fill,
|
||||||
|
Padding = new Padding(12, 10, 0, 0),
|
||||||
|
BackColor = Color.Transparent
|
||||||
|
};
|
||||||
|
|
||||||
|
var btnPesquisar = CreateToolbarButton("Pesquisar", AccentBlue);
|
||||||
|
var btnLimpar = CreateToolbarButton("Limpar", MutedGray);
|
||||||
|
var btnAbrir = CreateToolbarButton("Abrir", GreenColor);
|
||||||
|
var btnExportar = CreateToolbarButton("Exportar", Color.FromArgb(99, 102, 241));
|
||||||
|
|
||||||
|
btnPesquisar.Click += (_, _) => AplicarFiltros();
|
||||||
|
btnLimpar.Click += (_, _) => LimparFiltros();
|
||||||
|
btnAbrir.Click += (_, _) => AbrirRegistroSelecionado();
|
||||||
|
btnExportar.Click += (_, _) => ExportarCSV();
|
||||||
|
|
||||||
|
flow.Controls.AddRange(new Control[] { btnPesquisar, btnLimpar, btnAbrir, btnExportar });
|
||||||
|
pnlToolbar.Controls.Add(flow);
|
||||||
|
Controls.Add(pnlToolbar); // ← último Top = aparece no topo
|
||||||
|
}
|
||||||
|
|
||||||
|
// ── FILTROS ───────────────────────────────────────────────────────────
|
||||||
|
private void BuildFiltros()
|
||||||
|
{
|
||||||
|
// Linha 1
|
||||||
|
txtFiltroCompromisso = AddFiltroInput(pnlFiltros, "Compromisso", 0, 8, 260);
|
||||||
|
txtFiltroFunc = AddFiltroInput(pnlFiltros, "Funcionário", 270, 8, 200);
|
||||||
|
txtFiltroOsVinc = AddFiltroInput(pnlFiltros, "OS Vinculada", 480, 8, 130);
|
||||||
|
|
||||||
|
// Linha 2
|
||||||
|
txtDataInicio = AddFiltroInput(pnlFiltros, "Data Início", 0, 50, 130);
|
||||||
|
txtDataFim = AddFiltroInput(pnlFiltros, "Data Fim", 140, 50, 130);
|
||||||
|
|
||||||
|
pnlFiltros.Controls.Add(new Label
|
||||||
|
{
|
||||||
|
Text = "Situação",
|
||||||
|
Location = new Point(280, 50),
|
||||||
|
Font = new Font("Segoe UI", 7.5f, FontStyle.Bold),
|
||||||
|
ForeColor = TextDark,
|
||||||
|
AutoSize = true
|
||||||
|
});
|
||||||
|
|
||||||
|
cmbSituacao = new ComboBox
|
||||||
|
{
|
||||||
|
Location = new Point(280, 66),
|
||||||
|
Size = new Size(160, 26),
|
||||||
|
DropDownStyle = ComboBoxStyle.DropDownList,
|
||||||
|
Font = new Font("Segoe UI", 8.5f),
|
||||||
|
FlatStyle = FlatStyle.Flat
|
||||||
|
};
|
||||||
|
cmbSituacao.Items.AddRange(new object[] { "Todos", "Pendente", "Realizado" });
|
||||||
|
cmbSituacao.SelectedIndex = 0;
|
||||||
|
pnlFiltros.Controls.Add(cmbSituacao);
|
||||||
|
|
||||||
|
foreach (var txt in new[] { txtFiltroCompromisso, txtFiltroFunc, txtFiltroOsVinc, txtDataInicio, txtDataFim })
|
||||||
|
txt.KeyDown += (_, e) => { if (e.KeyCode == Keys.Enter) AplicarFiltros(); };
|
||||||
|
}
|
||||||
|
|
||||||
|
private RoundTextBox AddFiltroInput(Control parent, string label, int x, int y, int width)
|
||||||
|
{
|
||||||
|
parent.Controls.Add(new Label
|
||||||
|
{
|
||||||
|
Text = label,
|
||||||
|
Location = new Point(x, y),
|
||||||
|
Font = new Font("Segoe UI", 7.5f, FontStyle.Bold),
|
||||||
|
ForeColor = TextDark,
|
||||||
|
AutoSize = true
|
||||||
|
});
|
||||||
|
var txt = new RoundTextBox
|
||||||
|
{
|
||||||
|
Location = new Point(x, y + 16),
|
||||||
|
Size = new Size(width, 26),
|
||||||
|
Radius = 4,
|
||||||
|
BorderColor = BorderColor,
|
||||||
|
FocusColor = AccentBlue,
|
||||||
|
BackColor = Color.White
|
||||||
|
};
|
||||||
|
parent.Controls.Add(txt);
|
||||||
|
return txt;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ── GRID ──────────────────────────────────────────────────────────────
|
||||||
|
private void BuildGrid()
|
||||||
|
{
|
||||||
|
dgvAgenda = new DataGridView
|
||||||
|
{
|
||||||
|
Dock = DockStyle.Fill,
|
||||||
|
BackgroundColor = Color.White,
|
||||||
|
BorderStyle = BorderStyle.None,
|
||||||
|
CellBorderStyle = DataGridViewCellBorderStyle.SingleHorizontal,
|
||||||
|
ColumnHeadersBorderStyle = DataGridViewHeaderBorderStyle.Single,
|
||||||
|
GridColor = BorderColor,
|
||||||
|
RowHeadersVisible = false,
|
||||||
|
AllowUserToAddRows = false,
|
||||||
|
AllowUserToDeleteRows = false,
|
||||||
|
ReadOnly = true,
|
||||||
|
SelectionMode = DataGridViewSelectionMode.FullRowSelect,
|
||||||
|
MultiSelect = false,
|
||||||
|
Font = new Font("Segoe UI", 8.5f),
|
||||||
|
AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.Fill,
|
||||||
|
ColumnHeadersHeight = 36,
|
||||||
|
ColumnHeadersHeightSizeMode = DataGridViewColumnHeadersHeightSizeMode.DisableResizing,
|
||||||
|
RowTemplate = { Height = 32 }
|
||||||
|
};
|
||||||
|
|
||||||
|
dgvAgenda.ColumnHeadersDefaultCellStyle = new DataGridViewCellStyle
|
||||||
|
{
|
||||||
|
BackColor = SurfaceColor,
|
||||||
|
ForeColor = TextDark,
|
||||||
|
Font = new Font("Segoe UI", 8.5f, FontStyle.Bold),
|
||||||
|
Alignment = DataGridViewContentAlignment.MiddleLeft,
|
||||||
|
Padding = new Padding(8, 0, 0, 0),
|
||||||
|
SelectionBackColor = SurfaceColor,
|
||||||
|
SelectionForeColor = TextDark
|
||||||
|
};
|
||||||
|
|
||||||
|
dgvAgenda.DefaultCellStyle = new DataGridViewCellStyle
|
||||||
|
{
|
||||||
|
ForeColor = TextDark,
|
||||||
|
BackColor = Color.White,
|
||||||
|
SelectionBackColor = Color.FromArgb(239, 246, 255),
|
||||||
|
SelectionForeColor = AccentBlue,
|
||||||
|
Padding = new Padding(8, 0, 0, 0)
|
||||||
|
};
|
||||||
|
|
||||||
|
dgvAgenda.AlternatingRowsDefaultCellStyle = new DataGridViewCellStyle
|
||||||
|
{
|
||||||
|
BackColor = SurfaceColor,
|
||||||
|
SelectionBackColor = Color.FromArgb(239, 246, 255),
|
||||||
|
SelectionForeColor = AccentBlue
|
||||||
|
};
|
||||||
|
|
||||||
|
dgvAgenda.Columns.AddRange(new DataGridViewColumn[]
|
||||||
|
{
|
||||||
|
new DataGridViewTextBoxColumn { Name = "colId", HeaderText = "ID", FillWeight = 5 },
|
||||||
|
new DataGridViewTextBoxColumn { Name = "colCodigo", HeaderText = "Código", FillWeight = 8 },
|
||||||
|
new DataGridViewTextBoxColumn { Name = "colCompromisso", HeaderText = "Compromisso", FillWeight = 26 },
|
||||||
|
new DataGridViewTextBoxColumn { Name = "colData", HeaderText = "Data", FillWeight = 10 },
|
||||||
|
new DataGridViewTextBoxColumn { Name = "colHora", HeaderText = "Hora", FillWeight = 7 },
|
||||||
|
new DataGridViewTextBoxColumn { Name = "colDia", HeaderText = "Dia", FillWeight = 10 },
|
||||||
|
new DataGridViewTextBoxColumn { Name = "colFunc", HeaderText = "Funcionário", FillWeight = 16 },
|
||||||
|
new DataGridViewTextBoxColumn { Name = "colAvisar", HeaderText = "Avisar", FillWeight = 12 },
|
||||||
|
new DataGridViewTextBoxColumn { Name = "colOs", HeaderText = "OS Vinc.", FillWeight = 8 },
|
||||||
|
new DataGridViewTextBoxColumn { Name = "colSituacao", HeaderText = "Situação", FillWeight = 10 },
|
||||||
|
});
|
||||||
|
|
||||||
|
dgvAgenda.CellDoubleClick += (_, e) =>
|
||||||
|
{
|
||||||
|
if (e.RowIndex >= 0) AbrirRegistroSelecionado();
|
||||||
|
};
|
||||||
|
|
||||||
|
dgvAgenda.CellFormatting += (_, e) =>
|
||||||
|
{
|
||||||
|
if (e.RowIndex < 0 || e.ColumnIndex < 0) return;
|
||||||
|
if (dgvAgenda.Columns[e.ColumnIndex].Name != "colSituacao") return;
|
||||||
|
|
||||||
|
bool realizado = e.Value?.ToString() == "Realizado";
|
||||||
|
e.CellStyle.ForeColor = realizado ? Color.FromArgb(22, 101, 52) : Color.FromArgb(146, 64, 14);
|
||||||
|
e.CellStyle.Font = new Font("Segoe UI", 8f, FontStyle.Bold);
|
||||||
|
e.CellStyle.SelectionForeColor = e.CellStyle.ForeColor;
|
||||||
|
e.FormattingApplied = true;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// ══════════════════════════════════════════════════════════════════════
|
||||||
|
// LÓGICA
|
||||||
|
// ══════════════════════════════════════════════════════════════════════
|
||||||
|
private void AplicarFiltros()
|
||||||
|
{
|
||||||
|
_filtrados = _todos.ToList();
|
||||||
|
|
||||||
|
var termComp = txtFiltroCompromisso.Text.Trim().ToLower();
|
||||||
|
if (!string.IsNullOrEmpty(termComp))
|
||||||
|
_filtrados = _filtrados.Where(e => e.COMPROMISSO?.ToLower().Contains(termComp) == true).ToList();
|
||||||
|
|
||||||
|
var termFunc = txtFiltroFunc.Text.Trim().ToLower();
|
||||||
|
if (!string.IsNullOrEmpty(termFunc))
|
||||||
|
_filtrados = _filtrados.Where(e => e.FUNC?.ToLower().Contains(termFunc) == true).ToList();
|
||||||
|
|
||||||
|
var termOs = txtFiltroOsVinc.Text.Trim().ToLower();
|
||||||
|
if (!string.IsNullOrEmpty(termOs))
|
||||||
|
_filtrados = _filtrados.Where(e => e.OS_VINC?.ToLower().Contains(termOs) == true).ToList();
|
||||||
|
|
||||||
|
if (DateTime.TryParseExact(txtDataInicio.Text.Trim(), "dd/MM/yyyy",
|
||||||
|
System.Globalization.CultureInfo.InvariantCulture,
|
||||||
|
System.Globalization.DateTimeStyles.None, out var dtIni))
|
||||||
|
_filtrados = _filtrados.Where(e => ParseData(e.dDATA) >= dtIni).ToList();
|
||||||
|
|
||||||
|
if (DateTime.TryParseExact(txtDataFim.Text.Trim(), "dd/MM/yyyy",
|
||||||
|
System.Globalization.CultureInfo.InvariantCulture,
|
||||||
|
System.Globalization.DateTimeStyles.None, out var dtFim))
|
||||||
|
_filtrados = _filtrados.Where(e => ParseData(e.dDATA) <= dtFim).ToList();
|
||||||
|
|
||||||
|
var sit = cmbSituacao.SelectedItem?.ToString();
|
||||||
|
if (sit == "Realizado") _filtrados = _filtrados.Where(e => e.REALIZADO?.ToUpper() == "S").ToList();
|
||||||
|
else if (sit == "Pendente") _filtrados = _filtrados.Where(e => e.REALIZADO?.ToUpper() != "S").ToList();
|
||||||
|
|
||||||
|
PreencherGrid();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void LimparFiltros()
|
||||||
|
{
|
||||||
|
txtFiltroCompromisso.Text = string.Empty;
|
||||||
|
txtFiltroFunc.Text = string.Empty;
|
||||||
|
txtFiltroOsVinc.Text = string.Empty;
|
||||||
|
txtDataInicio.Text = string.Empty;
|
||||||
|
txtDataFim.Text = string.Empty;
|
||||||
|
cmbSituacao.SelectedIndex = 0;
|
||||||
|
AplicarFiltros();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void PreencherGrid()
|
||||||
|
{
|
||||||
|
dgvAgenda.Rows.Clear();
|
||||||
|
|
||||||
|
foreach (var ev in _filtrados.OrderBy(e => ParseData(e.dDATA)).ThenBy(e => e.HORA))
|
||||||
|
{
|
||||||
|
dgvAgenda.Rows.Add(
|
||||||
|
ev.ID_AGENDA, ev.CODIGO, ev.COMPROMISSO,
|
||||||
|
ev.dDATA, ev.HORA, ev.DIA, ev.FUNC, ev.AVISAR, ev.OS_VINC,
|
||||||
|
ev.REALIZADO?.ToUpper() == "S" ? "Realizado" : "Pendente"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
int total = _filtrados.Count;
|
||||||
|
lblTotal.Text = total == 1 ? "1 registro encontrado" : $"{total} registros encontrados";
|
||||||
|
}
|
||||||
|
|
||||||
|
private void AbrirRegistroSelecionado()
|
||||||
|
{
|
||||||
|
if (dgvAgenda.SelectedRows.Count == 0)
|
||||||
|
{
|
||||||
|
MessageBox.Show("Selecione um registro na lista.",
|
||||||
|
"Atenção", MessageBoxButtons.OK, MessageBoxIcon.Warning);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var row = dgvAgenda.SelectedRows[0];
|
||||||
|
if (row.Cells["colId"].Value is int id)
|
||||||
|
{
|
||||||
|
var ev = _filtrados.FirstOrDefault(e => e.ID_AGENDA == id);
|
||||||
|
if (ev != null) OnAbrirCadastro?.Invoke(ev);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ExportarCSV()
|
||||||
|
{
|
||||||
|
if (!_filtrados.Any())
|
||||||
|
{
|
||||||
|
MessageBox.Show("Nenhum registro para exportar.",
|
||||||
|
"Atenção", MessageBoxButtons.OK, MessageBoxIcon.Warning);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
using var dlg = new SaveFileDialog
|
||||||
|
{
|
||||||
|
Filter = "CSV (*.csv)|*.csv",
|
||||||
|
FileName = $"Agenda_{DateTime.Today:yyyyMMdd}.csv"
|
||||||
|
};
|
||||||
|
if (dlg.ShowDialog() != DialogResult.OK) return;
|
||||||
|
|
||||||
|
var sb = new System.Text.StringBuilder();
|
||||||
|
sb.AppendLine("ID;Código;Compromisso;Data;Hora;Dia;Funcionário;Avisar;OS Vinculada;Situação");
|
||||||
|
foreach (var ev in _filtrados.OrderBy(e => ParseData(e.dDATA)).ThenBy(e => e.HORA))
|
||||||
|
sb.AppendLine($"{ev.ID_AGENDA};{ev.CODIGO};{ev.COMPROMISSO};{ev.dDATA};" +
|
||||||
|
$"{ev.HORA};{ev.DIA};{ev.FUNC};{ev.AVISAR};{ev.OS_VINC};" +
|
||||||
|
$"{(ev.REALIZADO?.ToUpper() == "S" ? "Realizado" : "Pendente")}");
|
||||||
|
|
||||||
|
System.IO.File.WriteAllText(dlg.FileName, sb.ToString(), System.Text.Encoding.UTF8);
|
||||||
|
MessageBox.Show($"Exportado com sucesso!\n{dlg.FileName}", "Exportar",
|
||||||
|
MessageBoxButtons.OK, MessageBoxIcon.Information);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ── DADOS FAKE — substituir pelo repositório ──────────────────────────
|
||||||
|
private void CarregarDadosFake()
|
||||||
|
{
|
||||||
|
var hoje = DateTime.Today;
|
||||||
|
_todos = new List<MLL.ModeloAgenda>
|
||||||
|
{
|
||||||
|
new(1, "AG001", "Reunião com cliente", hoje.ToString("dd/MM/yyyy"), "30 minutos antes", "Carlos Silva", DiaSemana(hoje), "09:00", "S", "OS-1042"),
|
||||||
|
new(2, "AG002", "Visita técnica", hoje.ToString("dd/MM/yyyy"), "1 hora antes", "Ana Souza", DiaSemana(hoje), "14:00", "N", "OS-1055"),
|
||||||
|
new(3, "AG003", "Entrega de equipamento", hoje.AddDays(4).ToString("dd/MM/yyyy"), "1 dia antes", "Pedro Lima", DiaSemana(hoje.AddDays(4)), "10:30", "N", ""),
|
||||||
|
new(4, "AG004", "Manutenção preventiva", hoje.AddDays(-2).ToString("dd/MM/yyyy"), "30 minutos antes", "Carlos Silva", DiaSemana(hoje.AddDays(-2)), "08:00", "S", "OS-1030"),
|
||||||
|
new(5, "AG005", "Treinamento equipe", hoje.AddDays(7).ToString("dd/MM/yyyy"), "1 dia antes", "Ana Souza", DiaSemana(hoje.AddDays(7)), "13:00", "N", ""),
|
||||||
|
};
|
||||||
|
}//Carregar dados fakes para ixibição
|
||||||
|
private void CarregarDadosDoBanco()
|
||||||
|
{
|
||||||
|
BLLAgenda _agendaBLL = new BLLAgenda(_conexao);
|
||||||
|
_todos.Clear();
|
||||||
|
_todos.AddRange(_agendaBLL.Listar());
|
||||||
|
}//Carregar dados reais do banco de dados usando o repositório
|
||||||
|
|
||||||
|
private static DateTime ParseData(string? value)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrWhiteSpace(value)) return DateTime.MinValue;
|
||||||
|
if (DateTime.TryParseExact(value, "dd/MM/yyyy",
|
||||||
|
System.Globalization.CultureInfo.InvariantCulture,
|
||||||
|
System.Globalization.DateTimeStyles.None, out var dt)) return dt;
|
||||||
|
if (DateTime.TryParse(value, out dt)) return dt;
|
||||||
|
return DateTime.MinValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static string DiaSemana(DateTime d) =>
|
||||||
|
new System.Globalization.CultureInfo("pt-BR").DateTimeFormat.GetDayName(d.DayOfWeek);
|
||||||
|
|
||||||
|
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
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
120
Dashboards/Consultas/AgendaConsultaPanel.resx
Normal file
120
Dashboards/Consultas/AgendaConsultaPanel.resx
Normal file
@ -0,0 +1,120 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<root>
|
||||||
|
<!--
|
||||||
|
Microsoft ResX Schema
|
||||||
|
|
||||||
|
Version 2.0
|
||||||
|
|
||||||
|
The primary goals of this format is to allow a simple XML format
|
||||||
|
that is mostly human readable. The generation and parsing of the
|
||||||
|
various data types are done through the TypeConverter classes
|
||||||
|
associated with the data types.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
... ado.net/XML headers & schema ...
|
||||||
|
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||||
|
<resheader name="version">2.0</resheader>
|
||||||
|
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||||
|
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||||
|
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
||||||
|
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||||
|
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||||
|
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
||||||
|
</data>
|
||||||
|
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||||
|
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||||
|
<comment>This is a comment</comment>
|
||||||
|
</data>
|
||||||
|
|
||||||
|
There are any number of "resheader" rows that contain simple
|
||||||
|
name/value pairs.
|
||||||
|
|
||||||
|
Each data row contains a name, and value. The row also contains a
|
||||||
|
type or mimetype. Type corresponds to a .NET class that support
|
||||||
|
text/value conversion through the TypeConverter architecture.
|
||||||
|
Classes that don't support this are serialized and stored with the
|
||||||
|
mimetype set.
|
||||||
|
|
||||||
|
The mimetype is used for serialized objects, and tells the
|
||||||
|
ResXResourceReader how to depersist the object. This is currently not
|
||||||
|
extensible. For a given mimetype the value must be set accordingly:
|
||||||
|
|
||||||
|
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||||
|
that the ResXResourceWriter will generate, however the reader can
|
||||||
|
read any of the formats listed below.
|
||||||
|
|
||||||
|
mimetype: application/x-microsoft.net.object.binary.base64
|
||||||
|
value : The object must be serialized with
|
||||||
|
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
|
||||||
|
: and then encoded with base64 encoding.
|
||||||
|
|
||||||
|
mimetype: application/x-microsoft.net.object.soap.base64
|
||||||
|
value : The object must be serialized with
|
||||||
|
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||||
|
: and then encoded with base64 encoding.
|
||||||
|
|
||||||
|
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||||
|
value : The object must be serialized into a byte array
|
||||||
|
: using a System.ComponentModel.TypeConverter
|
||||||
|
: and then encoded with base64 encoding.
|
||||||
|
-->
|
||||||
|
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||||
|
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
||||||
|
<xsd:element name="root" msdata:IsDataSet="true">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:choice maxOccurs="unbounded">
|
||||||
|
<xsd:element name="metadata">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:sequence>
|
||||||
|
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||||
|
</xsd:sequence>
|
||||||
|
<xsd:attribute name="name" use="required" type="xsd:string" />
|
||||||
|
<xsd:attribute name="type" type="xsd:string" />
|
||||||
|
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||||
|
<xsd:attribute ref="xml:space" />
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
<xsd:element name="assembly">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:attribute name="alias" type="xsd:string" />
|
||||||
|
<xsd:attribute name="name" type="xsd:string" />
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
<xsd:element name="data">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:sequence>
|
||||||
|
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||||
|
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||||
|
</xsd:sequence>
|
||||||
|
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
|
||||||
|
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||||
|
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||||
|
<xsd:attribute ref="xml:space" />
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
<xsd:element name="resheader">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:sequence>
|
||||||
|
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||||
|
</xsd:sequence>
|
||||||
|
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
</xsd:choice>
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
</xsd:schema>
|
||||||
|
<resheader name="resmimetype">
|
||||||
|
<value>text/microsoft-resx</value>
|
||||||
|
</resheader>
|
||||||
|
<resheader name="version">
|
||||||
|
<value>2.0</value>
|
||||||
|
</resheader>
|
||||||
|
<resheader name="reader">
|
||||||
|
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||||
|
</resheader>
|
||||||
|
<resheader name="writer">
|
||||||
|
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||||
|
</resheader>
|
||||||
|
</root>
|
||||||
368
Dashboards/Dashmain/DashboardPanel.cs
Normal file
368
Dashboards/Dashmain/DashboardPanel.cs
Normal file
@ -0,0 +1,368 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Drawing;
|
||||||
|
using System.Drawing.Drawing2D;
|
||||||
|
using System.Windows.Forms;
|
||||||
|
using System.Globalization;
|
||||||
|
namespace UI
|
||||||
|
{
|
||||||
|
// ═══════════════════════════════════════════════════════════════════════
|
||||||
|
// DashboardPanel — painel principal com KPI cards + tabela de OS
|
||||||
|
// ═══════════════════════════════════════════════════════════════════════
|
||||||
|
public class DashboardPanel : UserControl
|
||||||
|
{
|
||||||
|
// ── Paleta ─────────────────────────────────────────────────────────
|
||||||
|
private static readonly Color Surface = Color.FromArgb(255, 255, 255);
|
||||||
|
private static readonly Color Surface2 = Color.FromArgb(248, 250, 252);
|
||||||
|
private static readonly Color Border = Color.FromArgb(226, 232, 240);
|
||||||
|
private static readonly Color TextPri = Color.FromArgb(15, 23, 42);
|
||||||
|
private static readonly Color TextSec = Color.FromArgb(71, 85, 105);
|
||||||
|
private static readonly Color TextMuted = Color.FromArgb(148, 163, 184);
|
||||||
|
|
||||||
|
private static readonly Color Blue = Color.FromArgb(37, 99, 235);
|
||||||
|
private static readonly Color BlueLight = Color.FromArgb(219, 234, 254);
|
||||||
|
private static readonly Color Green = Color.FromArgb(22, 163, 74);
|
||||||
|
private static readonly Color GreenL = Color.FromArgb(220, 252, 231);
|
||||||
|
private static readonly Color Amber = Color.FromArgb(217, 119, 6);
|
||||||
|
private static readonly Color AmberL = Color.FromArgb(254, 243, 199);
|
||||||
|
private static readonly Color Red = Color.FromArgb(220, 38, 38);
|
||||||
|
private static readonly Color RedL = Color.FromArgb(254, 226, 226);
|
||||||
|
private static readonly Color Orange = Color.FromArgb(234, 88, 12);
|
||||||
|
private static readonly Color OrangeL = Color.FromArgb(255, 237, 213);
|
||||||
|
|
||||||
|
// ── Dados de OS ────────────────────────────────────────────────────
|
||||||
|
private readonly List<OsRow> _ordens = new()
|
||||||
|
{
|
||||||
|
new OsRow("#0001", "João Silva", "Notebook Dell", OsStatus.EmAndamento, "07/04"),
|
||||||
|
new OsRow("#0002", "Maria Souza", "PC Gamer", OsStatus.Concluida, "07/04"),
|
||||||
|
new OsRow("#0003", "Carlos Mota", "Impressora HP", OsStatus.Aguardando, "08/04"),
|
||||||
|
new OsRow("#0004", "Ana Lima", "iPhone 14", OsStatus.EmAndamento, "08/04"),
|
||||||
|
new OsRow("#0005", "Pedro Rocha", "Monitor LG", OsStatus.Pendente, "09/04"),
|
||||||
|
};
|
||||||
|
|
||||||
|
// ── KPI cards ──────────────────────────────────────────────────────
|
||||||
|
// CORRIGIDO: instanciação posicional explícita (sem parâmetros nomeados)
|
||||||
|
private readonly KpiCard[] _kpis;
|
||||||
|
|
||||||
|
// ── Layout ─────────────────────────────────────────────────────────
|
||||||
|
private const int Pad = 24;
|
||||||
|
private const int KpiH = 110;
|
||||||
|
private const int KpiGap = 14;
|
||||||
|
private const int CardRad = 10;
|
||||||
|
private const int TopbarH = 56;
|
||||||
|
private const int RowH = 38;
|
||||||
|
|
||||||
|
private readonly Font _fLabel;
|
||||||
|
private readonly Font _fValue;
|
||||||
|
private readonly Font _fDelta;
|
||||||
|
private readonly Font _fHead;
|
||||||
|
private readonly Font _fCell;
|
||||||
|
private readonly Font _fColHead;
|
||||||
|
private readonly Font _fMono;
|
||||||
|
private readonly Font _fBtn;
|
||||||
|
private readonly Font _fTopTitle;
|
||||||
|
private readonly Font _fTopSub;
|
||||||
|
|
||||||
|
private Rectangle _btnNovaOS;
|
||||||
|
private int _hoverRow = -1;
|
||||||
|
|
||||||
|
public DashboardPanel()
|
||||||
|
{
|
||||||
|
// CORRIGIDO: inicialização dos campos Font no construtor
|
||||||
|
// (evita o aviso "campo não anulável precisa conter valor não nulo")
|
||||||
|
_fLabel = new Font("Segoe UI", 8.5f);
|
||||||
|
_fValue = new Font("Segoe UI Semibold", 18f);
|
||||||
|
_fDelta = new Font("Segoe UI", 9f);
|
||||||
|
_fHead = new Font("Segoe UI Semibold", 10.5f);
|
||||||
|
_fCell = new Font("Segoe UI", 10f);
|
||||||
|
_fColHead = new Font("Segoe UI", 8f);
|
||||||
|
_fMono = new Font("Consolas", 9.5f);
|
||||||
|
_fBtn = new Font("Segoe UI Semibold", 10f);
|
||||||
|
_fTopTitle = new Font("Segoe UI Semibold", 13f);
|
||||||
|
_fTopSub = new Font("Segoe UI", 9f);
|
||||||
|
|
||||||
|
// CORRIGIDO: KpiCard instanciado com construtor posicional explícito
|
||||||
|
_kpis = new[]
|
||||||
|
{
|
||||||
|
new KpiCard("OS Abertas", "12", "↑ 4 essa semana", true, BlueLight, Blue),
|
||||||
|
new KpiCard("OS Concluídas", "45", "↑ 12% vs mês", true, GreenL, Green),
|
||||||
|
new KpiCard("Faturamento", "22.5k", "↑ R$ 2.100", true, AmberL, Amber),
|
||||||
|
new KpiCard("Pendências", "3", "↓ aguardando", false, RedL, Red),
|
||||||
|
};
|
||||||
|
|
||||||
|
BackColor = Surface2;
|
||||||
|
DoubleBuffered = true;
|
||||||
|
SetStyle(ControlStyles.AllPaintingInWmPaint |
|
||||||
|
ControlStyles.OptimizedDoubleBuffer |
|
||||||
|
ControlStyles.ResizeRedraw, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void Dispose(bool disposing)
|
||||||
|
{
|
||||||
|
if (disposing)
|
||||||
|
{
|
||||||
|
_fLabel.Dispose(); _fValue.Dispose(); _fDelta.Dispose();
|
||||||
|
_fHead.Dispose(); _fCell.Dispose(); _fColHead.Dispose();
|
||||||
|
_fMono.Dispose(); _fBtn.Dispose(); _fTopTitle.Dispose();
|
||||||
|
_fTopSub.Dispose();
|
||||||
|
}
|
||||||
|
base.Dispose(disposing);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ── Paint ──────────────────────────────────────────────────────────
|
||||||
|
protected override void OnPaint(PaintEventArgs e)
|
||||||
|
{
|
||||||
|
var g = e.Graphics;
|
||||||
|
g.SmoothingMode = SmoothingMode.AntiAlias;
|
||||||
|
g.TextRenderingHint = System.Drawing.Text.TextRenderingHint.ClearTypeGridFit;
|
||||||
|
|
||||||
|
DrawTopbar(g);
|
||||||
|
int y = TopbarH + Pad;
|
||||||
|
DrawKpiRow(g, y);
|
||||||
|
y += KpiH + 20;
|
||||||
|
DrawOsCard(g, y);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ── Topbar ─────────────────────────────────────────────────────────
|
||||||
|
private void DrawTopbar(Graphics g)
|
||||||
|
{
|
||||||
|
g.FillRectangle(new SolidBrush(Surface), 0, 0, Width, TopbarH);
|
||||||
|
g.DrawLine(new Pen(Border, 1), 0, TopbarH, Width, TopbarH);
|
||||||
|
|
||||||
|
g.DrawString("Home", _fTopTitle, new SolidBrush(TextPri), Pad, 12);
|
||||||
|
//g.DrawString("Quinta, 09 de abril de 2026", _fTopSub,
|
||||||
|
g.DrawString(
|
||||||
|
DateTime.Now.ToString("dd 'de' MMMM 'de' yyyy", new CultureInfo("pt-BR")), _fTopSub,
|
||||||
|
new SolidBrush(TextMuted), Pad, 32);
|
||||||
|
|
||||||
|
int bw = 110, bh = 32;
|
||||||
|
int bx = Width - Pad - bw;
|
||||||
|
int by = (TopbarH - bh) / 2;
|
||||||
|
_btnNovaOS = new Rectangle(bx, by, bw, bh);
|
||||||
|
FillRoundRect(g, new SolidBrush(Blue), _btnNovaOS, 6);
|
||||||
|
|
||||||
|
var sf = new StringFormat
|
||||||
|
{
|
||||||
|
Alignment = StringAlignment.Center,
|
||||||
|
LineAlignment = StringAlignment.Center
|
||||||
|
};
|
||||||
|
g.DrawString("+ Nova OS", _fBtn, new SolidBrush(Color.White), _btnNovaOS, sf);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ── KPI Row ────────────────────────────────────────────────────────
|
||||||
|
private void DrawKpiRow(Graphics g, int y)
|
||||||
|
{
|
||||||
|
int totalGap = KpiGap * (_kpis.Length - 1);
|
||||||
|
int kpiW = (Width - Pad * 2 - totalGap) / _kpis.Length;
|
||||||
|
|
||||||
|
for (int i = 0; i < _kpis.Length; i++)
|
||||||
|
{
|
||||||
|
int x = Pad + i * (kpiW + KpiGap);
|
||||||
|
DrawKpiCard(g, _kpis[i], new Rectangle(x, y, kpiW, KpiH));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void DrawKpiCard(Graphics g, KpiCard kpi, Rectangle r)
|
||||||
|
{
|
||||||
|
FillRoundRect(g, new SolidBrush(Surface), r, CardRad);
|
||||||
|
DrawRoundBorder(g, r, CardRad, Border);
|
||||||
|
|
||||||
|
int dotSize = 36;
|
||||||
|
var dotRect = new Rectangle(r.Right - 16 - dotSize, r.Y + 16, dotSize, dotSize);
|
||||||
|
FillRoundRect(g, new SolidBrush(kpi.DotBg), dotRect, 8);
|
||||||
|
|
||||||
|
g.DrawString(kpi.Label, _fLabel, new SolidBrush(TextMuted), r.X + 16, r.Y + 18);
|
||||||
|
g.DrawString(kpi.Value, _fValue, new SolidBrush(TextPri), r.X + 14, r.Y + 36);
|
||||||
|
|
||||||
|
var deltaColor = kpi.DeltaUp ? Green : Red;
|
||||||
|
g.DrawString(kpi.Delta, _fDelta, new SolidBrush(deltaColor), r.X + 16, r.Y + 76);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ── OS Card ────────────────────────────────────────────────────────
|
||||||
|
private void DrawOsCard(Graphics g, int y)
|
||||||
|
{
|
||||||
|
string[] cols = { "OS", "Cliente", "Equipamento", "Status", "Data" };
|
||||||
|
float[] colW = { 0.08f, 0.22f, 0.28f, 0.22f, 0.10f };
|
||||||
|
|
||||||
|
int cardH = 28 + RowH + RowH * _ordens.Count + 16;
|
||||||
|
var card = new Rectangle(Pad, y, Width - Pad * 2, cardH);
|
||||||
|
|
||||||
|
FillRoundRect(g, new SolidBrush(Surface), card, CardRad);
|
||||||
|
DrawRoundBorder(g, card, CardRad, Border);
|
||||||
|
|
||||||
|
g.DrawString("Ordens de Serviço Recentes", _fHead,
|
||||||
|
new SolidBrush(TextPri), card.X + 18, card.Y + 16);
|
||||||
|
|
||||||
|
int tableY = card.Y + 44;
|
||||||
|
g.DrawLine(new Pen(Border, 0.5f), card.X, tableY, card.Right, tableY);
|
||||||
|
|
||||||
|
int cx = card.X;
|
||||||
|
for (int c = 0; c < cols.Length; c++)
|
||||||
|
{
|
||||||
|
int cw = (int)(card.Width * colW[c]);
|
||||||
|
var sf = new StringFormat { LineAlignment = StringAlignment.Center };
|
||||||
|
g.DrawString(cols[c].ToUpperInvariant(), _fColHead,
|
||||||
|
new SolidBrush(TextMuted), cx + 10, tableY + 2, sf);
|
||||||
|
cx += cw;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < _ordens.Count; i++)
|
||||||
|
{
|
||||||
|
int ry = tableY + RowH + i * RowH;
|
||||||
|
var row = _ordens[i];
|
||||||
|
|
||||||
|
if (i == _hoverRow)
|
||||||
|
g.FillRectangle(new SolidBrush(Surface2),
|
||||||
|
card.X + 1, ry, card.Width - 2, RowH);
|
||||||
|
|
||||||
|
g.DrawLine(new Pen(Border, 0.5f), card.X, ry, card.Right, ry);
|
||||||
|
|
||||||
|
cx = card.X;
|
||||||
|
int[] cws = GetColWidths(card.Width, colW);
|
||||||
|
|
||||||
|
g.DrawString(row.OS, _fMono,
|
||||||
|
new SolidBrush(TextMuted), cx + 10, ry + (RowH - 14) / 2);
|
||||||
|
cx += cws[0];
|
||||||
|
|
||||||
|
g.DrawString(row.Cliente, _fCell,
|
||||||
|
new SolidBrush(TextPri), cx + 8, ry + (RowH - 14) / 2);
|
||||||
|
cx += cws[1];
|
||||||
|
|
||||||
|
g.DrawString(row.Equipamento, _fCell,
|
||||||
|
new SolidBrush(TextSec), cx + 8, ry + (RowH - 14) / 2);
|
||||||
|
cx += cws[2];
|
||||||
|
|
||||||
|
DrawBadge(g, row.Status, cx + 8, ry + (RowH - 20) / 2);
|
||||||
|
cx += cws[3];
|
||||||
|
|
||||||
|
g.DrawString(row.Data, _fCell,
|
||||||
|
new SolidBrush(TextMuted), cx + 8, ry + (RowH - 14) / 2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static int[] GetColWidths(int total, float[] ratios)
|
||||||
|
{
|
||||||
|
var ws = new int[ratios.Length];
|
||||||
|
for (int i = 0; i < ratios.Length; i++)
|
||||||
|
ws[i] = (int)(total * ratios[i]);
|
||||||
|
return ws;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void DrawBadge(Graphics g, OsStatus status, int x, int y)
|
||||||
|
{
|
||||||
|
var (label, bg, fg) = status switch
|
||||||
|
{
|
||||||
|
OsStatus.Concluida => ("Concluída", GreenL, Color.FromArgb(22, 101, 52)),
|
||||||
|
OsStatus.EmAndamento => ("Em andamento", AmberL, Color.FromArgb(146, 64, 14)),
|
||||||
|
OsStatus.Aguardando => ("Aguardando", BlueLight, Color.FromArgb(30, 64, 175)),
|
||||||
|
OsStatus.Pendente => ("Pendente", RedL, Color.FromArgb(153, 27, 27)),
|
||||||
|
_ => ("—", Border, TextMuted)
|
||||||
|
};
|
||||||
|
|
||||||
|
var sz = g.MeasureString(label, _fDelta);
|
||||||
|
int bw = (int)sz.Width + 16;
|
||||||
|
int bh = 20;
|
||||||
|
var badge = new Rectangle(x, y, bw, bh);
|
||||||
|
FillRoundRect(g, new SolidBrush(bg), badge, 10);
|
||||||
|
|
||||||
|
var sf = new StringFormat
|
||||||
|
{
|
||||||
|
Alignment = StringAlignment.Center,
|
||||||
|
LineAlignment = StringAlignment.Center
|
||||||
|
};
|
||||||
|
g.DrawString(label, _fDelta, new SolidBrush(fg), badge, sf);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ── Mouse ──────────────────────────────────────────────────────────
|
||||||
|
protected override void OnMouseMove(MouseEventArgs e)
|
||||||
|
{
|
||||||
|
int row = HitTestRow(e.Y);
|
||||||
|
if (row != _hoverRow) { _hoverRow = row; Invalidate(); }
|
||||||
|
Cursor = _btnNovaOS.Contains(e.Location) ? Cursors.Hand : Cursors.Default;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void OnMouseLeave(EventArgs e)
|
||||||
|
{
|
||||||
|
_hoverRow = -1;
|
||||||
|
Invalidate();
|
||||||
|
}
|
||||||
|
|
||||||
|
private int HitTestRow(int mouseY)
|
||||||
|
{
|
||||||
|
int tableY = TopbarH + Pad + KpiH + 20 + 44 + RowH;
|
||||||
|
for (int i = 0; i < _ordens.Count; i++)
|
||||||
|
{
|
||||||
|
int ry = tableY + i * RowH;
|
||||||
|
if (mouseY >= ry && mouseY < ry + RowH) return i;
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ── GDI Helpers ────────────────────────────────────────────────────
|
||||||
|
private static void FillRoundRect(Graphics g, Brush brush, Rectangle r, int radius)
|
||||||
|
{
|
||||||
|
using var path = RoundRectPath(r, radius);
|
||||||
|
g.FillPath(brush, path);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void DrawRoundBorder(Graphics g, Rectangle r, int radius, Color color)
|
||||||
|
{
|
||||||
|
using var path = RoundRectPath(r, radius);
|
||||||
|
g.DrawPath(new Pen(color, 0.5f), path);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static GraphicsPath RoundRectPath(Rectangle r, int radius)
|
||||||
|
{
|
||||||
|
var path = new GraphicsPath();
|
||||||
|
path.AddArc(r.X, r.Y, radius * 2, radius * 2, 180, 90);
|
||||||
|
path.AddArc(r.Right - radius * 2, r.Y, radius * 2, radius * 2, 270, 90);
|
||||||
|
path.AddArc(r.Right - radius * 2, r.Bottom - radius * 2, radius * 2, radius * 2, 0, 90);
|
||||||
|
path.AddArc(r.X, r.Bottom - radius * 2, radius * 2, radius * 2, 90, 90);
|
||||||
|
path.CloseFigure();
|
||||||
|
return path;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ── Modelos ────────────────────────────────────────────────────────
|
||||||
|
// CORRIGIDO: usando classes simples em vez de records posicionais
|
||||||
|
// para compatibilidade com qualquer versão do compilador .NET 6+.
|
||||||
|
private class OsRow
|
||||||
|
{
|
||||||
|
public string OS { get; }
|
||||||
|
public string Cliente { get; }
|
||||||
|
public string Equipamento { get; }
|
||||||
|
public OsStatus Status { get; }
|
||||||
|
public string Data { get; }
|
||||||
|
|
||||||
|
public OsRow(string os, string cliente, string equipamento, OsStatus status, string data)
|
||||||
|
{
|
||||||
|
OS = os;
|
||||||
|
Cliente = cliente;
|
||||||
|
Equipamento = equipamento;
|
||||||
|
Status = status;
|
||||||
|
Data = data;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private class KpiCard
|
||||||
|
{
|
||||||
|
public string Label { get; }
|
||||||
|
public string Value { get; }
|
||||||
|
public string Delta { get; }
|
||||||
|
public bool DeltaUp { get; }
|
||||||
|
public Color DotBg { get; }
|
||||||
|
public Color DotFg { get; }
|
||||||
|
|
||||||
|
public KpiCard(string label, string value, string delta, bool deltaUp, Color dotBg, Color dotFg)
|
||||||
|
{
|
||||||
|
Label = label;
|
||||||
|
Value = value;
|
||||||
|
Delta = delta;
|
||||||
|
DeltaUp = deltaUp;
|
||||||
|
DotBg = dotBg;
|
||||||
|
DotFg = dotFg;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private enum OsStatus { Concluida, EmAndamento, Aguardando, Pendente }
|
||||||
|
}
|
||||||
|
}
|
||||||
120
Dashboards/Dashmain/DashboardPanel.resx
Normal file
120
Dashboards/Dashmain/DashboardPanel.resx
Normal file
@ -0,0 +1,120 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<root>
|
||||||
|
<!--
|
||||||
|
Microsoft ResX Schema
|
||||||
|
|
||||||
|
Version 2.0
|
||||||
|
|
||||||
|
The primary goals of this format is to allow a simple XML format
|
||||||
|
that is mostly human readable. The generation and parsing of the
|
||||||
|
various data types are done through the TypeConverter classes
|
||||||
|
associated with the data types.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
... ado.net/XML headers & schema ...
|
||||||
|
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||||
|
<resheader name="version">2.0</resheader>
|
||||||
|
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||||
|
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||||
|
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
||||||
|
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||||
|
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||||
|
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
||||||
|
</data>
|
||||||
|
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||||
|
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||||
|
<comment>This is a comment</comment>
|
||||||
|
</data>
|
||||||
|
|
||||||
|
There are any number of "resheader" rows that contain simple
|
||||||
|
name/value pairs.
|
||||||
|
|
||||||
|
Each data row contains a name, and value. The row also contains a
|
||||||
|
type or mimetype. Type corresponds to a .NET class that support
|
||||||
|
text/value conversion through the TypeConverter architecture.
|
||||||
|
Classes that don't support this are serialized and stored with the
|
||||||
|
mimetype set.
|
||||||
|
|
||||||
|
The mimetype is used for serialized objects, and tells the
|
||||||
|
ResXResourceReader how to depersist the object. This is currently not
|
||||||
|
extensible. For a given mimetype the value must be set accordingly:
|
||||||
|
|
||||||
|
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||||
|
that the ResXResourceWriter will generate, however the reader can
|
||||||
|
read any of the formats listed below.
|
||||||
|
|
||||||
|
mimetype: application/x-microsoft.net.object.binary.base64
|
||||||
|
value : The object must be serialized with
|
||||||
|
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
|
||||||
|
: and then encoded with base64 encoding.
|
||||||
|
|
||||||
|
mimetype: application/x-microsoft.net.object.soap.base64
|
||||||
|
value : The object must be serialized with
|
||||||
|
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||||
|
: and then encoded with base64 encoding.
|
||||||
|
|
||||||
|
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||||
|
value : The object must be serialized into a byte array
|
||||||
|
: using a System.ComponentModel.TypeConverter
|
||||||
|
: and then encoded with base64 encoding.
|
||||||
|
-->
|
||||||
|
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||||
|
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
||||||
|
<xsd:element name="root" msdata:IsDataSet="true">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:choice maxOccurs="unbounded">
|
||||||
|
<xsd:element name="metadata">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:sequence>
|
||||||
|
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||||
|
</xsd:sequence>
|
||||||
|
<xsd:attribute name="name" use="required" type="xsd:string" />
|
||||||
|
<xsd:attribute name="type" type="xsd:string" />
|
||||||
|
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||||
|
<xsd:attribute ref="xml:space" />
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
<xsd:element name="assembly">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:attribute name="alias" type="xsd:string" />
|
||||||
|
<xsd:attribute name="name" type="xsd:string" />
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
<xsd:element name="data">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:sequence>
|
||||||
|
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||||
|
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||||
|
</xsd:sequence>
|
||||||
|
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
|
||||||
|
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||||
|
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||||
|
<xsd:attribute ref="xml:space" />
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
<xsd:element name="resheader">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:sequence>
|
||||||
|
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||||
|
</xsd:sequence>
|
||||||
|
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
</xsd:choice>
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
</xsd:schema>
|
||||||
|
<resheader name="resmimetype">
|
||||||
|
<value>text/microsoft-resx</value>
|
||||||
|
</resheader>
|
||||||
|
<resheader name="version">
|
||||||
|
<value>2.0</value>
|
||||||
|
</resheader>
|
||||||
|
<resheader name="reader">
|
||||||
|
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||||
|
</resheader>
|
||||||
|
<resheader name="writer">
|
||||||
|
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||||
|
</resheader>
|
||||||
|
</root>
|
||||||
147
Dashboards/Dashmain/MainForm.cs
Normal file
147
Dashboards/Dashmain/MainForm.cs
Normal file
@ -0,0 +1,147 @@
|
|||||||
|
using CCH;
|
||||||
|
using CustomMessageBox;
|
||||||
|
using DAL;
|
||||||
|
using System;
|
||||||
|
using System.Drawing;
|
||||||
|
using System.Windows.Forms;
|
||||||
|
using TLL;
|
||||||
|
namespace UI
|
||||||
|
{
|
||||||
|
public class MainForm : Form
|
||||||
|
{
|
||||||
|
private readonly SidebarControl _sidebar;
|
||||||
|
private readonly DashboardPanel _dashboard;
|
||||||
|
|
||||||
|
private readonly ClienteCadastroPanel _pClientes;
|
||||||
|
private readonly EmpresaCadastroPanel _pEmpresa;
|
||||||
|
private readonly EmpresaConfiguracoesPanel _pEmpresaConfig;
|
||||||
|
private readonly AgendaCadastroPanel _pAgendaCadastro;
|
||||||
|
private readonly AgendaConsultaPanel _pAgendaConsulta;
|
||||||
|
private readonly FuncionariosCadastroPanel _pfuncionariosCadastro ;
|
||||||
|
private readonly Panel _pOrdens;
|
||||||
|
private readonly Panel _pProdutos;
|
||||||
|
private readonly Panel _pEstoque;
|
||||||
|
private readonly Panel _pFinanceiro;
|
||||||
|
|
||||||
|
public MainForm()
|
||||||
|
{
|
||||||
|
Text = "LevelOS — Sistema ERP";
|
||||||
|
this.WindowState = FormWindowState.Maximized;
|
||||||
|
this.MinimumSize = new Size(1100, 750);
|
||||||
|
this.BackColor = Color.FromArgb(248, 250, 252);
|
||||||
|
|
||||||
|
_sidebar = new SidebarControl { Dock = DockStyle.Left };
|
||||||
|
_sidebar.NavItemClicked += OnNavItemClicked;
|
||||||
|
|
||||||
|
_dashboard = new DashboardPanel { Dock = DockStyle.Fill };
|
||||||
|
|
||||||
|
_pClientes = new ClienteCadastroPanel { Dock = DockStyle.Fill, Visible = false };
|
||||||
|
_pEmpresa = new EmpresaCadastroPanel { Dock = DockStyle.Fill, Visible = false };
|
||||||
|
_pEmpresaConfig = new EmpresaConfiguracoesPanel { Dock = DockStyle.Fill, Visible = false };
|
||||||
|
_pAgendaCadastro = new AgendaCadastroPanel { Dock = DockStyle.Fill, Visible = false };
|
||||||
|
_pAgendaConsulta = new AgendaConsultaPanel { Dock = DockStyle.Fill, Visible = false };
|
||||||
|
_pfuncionariosCadastro = new FuncionariosCadastroPanel { Dock = DockStyle.Fill, Visible = false };
|
||||||
|
_pOrdens = PlaceholderPanel("Ordens de Serviço", Color.FromArgb(22, 163, 74));
|
||||||
|
_pProdutos = PlaceholderPanel("Catálogo de Produtos", Color.FromArgb(217, 119, 6));
|
||||||
|
_pEstoque = PlaceholderPanel("Controle de Estoque", Color.FromArgb(234, 88, 12));
|
||||||
|
_pFinanceiro = PlaceholderPanel("Fluxo Financeiro", Color.FromArgb(124, 58, 237));
|
||||||
|
|
||||||
|
var mainContainer = new Panel { Dock = DockStyle.Fill };
|
||||||
|
mainContainer.Controls.Add(_pFinanceiro);
|
||||||
|
mainContainer.Controls.Add(_pAgendaCadastro);
|
||||||
|
mainContainer.Controls.Add(_pAgendaConsulta);
|
||||||
|
mainContainer.Controls.Add(_pEstoque);
|
||||||
|
mainContainer.Controls.Add(_pProdutos);
|
||||||
|
mainContainer.Controls.Add(_pOrdens);
|
||||||
|
mainContainer.Controls.Add(_pEmpresa);
|
||||||
|
mainContainer.Controls.Add(_pEmpresaConfig);
|
||||||
|
mainContainer.Controls.Add(_pClientes);
|
||||||
|
mainContainer.Controls.Add(_dashboard);
|
||||||
|
mainContainer.Controls.Add(_pfuncionariosCadastro);
|
||||||
|
|
||||||
|
Controls.Add(mainContainer);
|
||||||
|
Controls.Add(_sidebar);
|
||||||
|
|
||||||
|
ShowPanel(_dashboard);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnNavItemClicked(object? sender, int index)
|
||||||
|
{
|
||||||
|
/* Índices:
|
||||||
|
0 = Dashboard
|
||||||
|
2 = Ordens de Serviço
|
||||||
|
4 = Produtos
|
||||||
|
5 = Estoque
|
||||||
|
9 = Financeiro
|
||||||
|
99 = Submenu → Clientes
|
||||||
|
98 = Submenu → Empresa
|
||||||
|
*/
|
||||||
|
switch (index)
|
||||||
|
{
|
||||||
|
case 0: ShowPanel(_dashboard); break;
|
||||||
|
case 2: ShowPanel(_pOrdens); break;
|
||||||
|
case 4: ShowPanel(_pProdutos); break;
|
||||||
|
case 5: ShowPanel(_pEstoque); break;
|
||||||
|
case 9: ShowPanel(_pFinanceiro); break;
|
||||||
|
case 99: ShowPanel(_pClientes); break;
|
||||||
|
case 103: ShowPanel(_pfuncionariosCadastro); break;
|
||||||
|
case 106: ShowPanel(_pEmpresa); break;
|
||||||
|
|
||||||
|
|
||||||
|
case 202: ShowPanel(_pEmpresaConfig); break;
|
||||||
|
case 300: ShowPanel(_pAgendaCadastro); break;
|
||||||
|
case 301: ShowPanel(_pAgendaConsulta); break;
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ShowPanel(Control panelToShow)
|
||||||
|
{
|
||||||
|
_dashboard.Visible = (panelToShow == _dashboard);
|
||||||
|
_pClientes.Visible = (panelToShow == _pClientes);
|
||||||
|
_pEmpresa.Visible = (panelToShow == _pEmpresa);
|
||||||
|
_pEmpresaConfig.Visible = (panelToShow == _pEmpresaConfig);
|
||||||
|
_pOrdens.Visible = (panelToShow == _pOrdens);
|
||||||
|
_pProdutos.Visible = (panelToShow == _pProdutos);
|
||||||
|
_pEstoque.Visible = (panelToShow == _pEstoque);
|
||||||
|
_pFinanceiro.Visible = (panelToShow == _pFinanceiro);
|
||||||
|
_pAgendaCadastro.Visible = (panelToShow == _pAgendaCadastro);
|
||||||
|
_pAgendaConsulta.Visible = (panelToShow == _pAgendaConsulta);
|
||||||
|
_pfuncionariosCadastro.Visible = (panelToShow == _pfuncionariosCadastro);
|
||||||
|
|
||||||
|
if (panelToShow.Visible)
|
||||||
|
{
|
||||||
|
panelToShow.BringToFront();
|
||||||
|
panelToShow.Focus();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Panel PlaceholderPanel(string titulo, Color cor)
|
||||||
|
{
|
||||||
|
var p = new Panel { Dock = DockStyle.Fill, Visible = false };
|
||||||
|
p.Paint += (s, e) =>
|
||||||
|
{
|
||||||
|
var g = e.Graphics;
|
||||||
|
g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;
|
||||||
|
var r = p.ClientRectangle;
|
||||||
|
g.Clear(Color.FromArgb(248, 250, 252));
|
||||||
|
|
||||||
|
var circle = new Rectangle(r.Width / 2 - 40, r.Height / 2 - 80, 80, 80);
|
||||||
|
g.FillEllipse(new SolidBrush(Color.FromArgb(20, cor)), circle);
|
||||||
|
|
||||||
|
using var f1 = new Font("Segoe UI Semibold", 16f);
|
||||||
|
using var f2 = new Font("Segoe UI", 10f);
|
||||||
|
var sf = new StringFormat { Alignment = StringAlignment.Center, LineAlignment = StringAlignment.Center };
|
||||||
|
|
||||||
|
g.DrawString(titulo, f1, new SolidBrush(Color.FromArgb(30, 41, 59)),
|
||||||
|
new RectangleF(0, r.Height / 2f - 10, r.Width, 40), sf);
|
||||||
|
|
||||||
|
g.DrawString("Este módulo está sendo integrado ao LevelOS", f2, new SolidBrush(Color.FromArgb(148, 163, 184)),
|
||||||
|
new RectangleF(0, r.Height / 2f + 25, r.Width, 30), sf);
|
||||||
|
};
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
120
Dashboards/Dashmain/MainForm.resx
Normal file
120
Dashboards/Dashmain/MainForm.resx
Normal file
@ -0,0 +1,120 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<root>
|
||||||
|
<!--
|
||||||
|
Microsoft ResX Schema
|
||||||
|
|
||||||
|
Version 2.0
|
||||||
|
|
||||||
|
The primary goals of this format is to allow a simple XML format
|
||||||
|
that is mostly human readable. The generation and parsing of the
|
||||||
|
various data types are done through the TypeConverter classes
|
||||||
|
associated with the data types.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
... ado.net/XML headers & schema ...
|
||||||
|
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||||
|
<resheader name="version">2.0</resheader>
|
||||||
|
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||||
|
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||||
|
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
||||||
|
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||||
|
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||||
|
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
||||||
|
</data>
|
||||||
|
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||||
|
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||||
|
<comment>This is a comment</comment>
|
||||||
|
</data>
|
||||||
|
|
||||||
|
There are any number of "resheader" rows that contain simple
|
||||||
|
name/value pairs.
|
||||||
|
|
||||||
|
Each data row contains a name, and value. The row also contains a
|
||||||
|
type or mimetype. Type corresponds to a .NET class that support
|
||||||
|
text/value conversion through the TypeConverter architecture.
|
||||||
|
Classes that don't support this are serialized and stored with the
|
||||||
|
mimetype set.
|
||||||
|
|
||||||
|
The mimetype is used for serialized objects, and tells the
|
||||||
|
ResXResourceReader how to depersist the object. This is currently not
|
||||||
|
extensible. For a given mimetype the value must be set accordingly:
|
||||||
|
|
||||||
|
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||||
|
that the ResXResourceWriter will generate, however the reader can
|
||||||
|
read any of the formats listed below.
|
||||||
|
|
||||||
|
mimetype: application/x-microsoft.net.object.binary.base64
|
||||||
|
value : The object must be serialized with
|
||||||
|
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
|
||||||
|
: and then encoded with base64 encoding.
|
||||||
|
|
||||||
|
mimetype: application/x-microsoft.net.object.soap.base64
|
||||||
|
value : The object must be serialized with
|
||||||
|
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||||
|
: and then encoded with base64 encoding.
|
||||||
|
|
||||||
|
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||||
|
value : The object must be serialized into a byte array
|
||||||
|
: using a System.ComponentModel.TypeConverter
|
||||||
|
: and then encoded with base64 encoding.
|
||||||
|
-->
|
||||||
|
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||||
|
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
||||||
|
<xsd:element name="root" msdata:IsDataSet="true">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:choice maxOccurs="unbounded">
|
||||||
|
<xsd:element name="metadata">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:sequence>
|
||||||
|
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||||
|
</xsd:sequence>
|
||||||
|
<xsd:attribute name="name" use="required" type="xsd:string" />
|
||||||
|
<xsd:attribute name="type" type="xsd:string" />
|
||||||
|
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||||
|
<xsd:attribute ref="xml:space" />
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
<xsd:element name="assembly">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:attribute name="alias" type="xsd:string" />
|
||||||
|
<xsd:attribute name="name" type="xsd:string" />
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
<xsd:element name="data">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:sequence>
|
||||||
|
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||||
|
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||||
|
</xsd:sequence>
|
||||||
|
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
|
||||||
|
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||||
|
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||||
|
<xsd:attribute ref="xml:space" />
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
<xsd:element name="resheader">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:sequence>
|
||||||
|
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||||
|
</xsd:sequence>
|
||||||
|
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
</xsd:choice>
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
</xsd:schema>
|
||||||
|
<resheader name="resmimetype">
|
||||||
|
<value>text/microsoft-resx</value>
|
||||||
|
</resheader>
|
||||||
|
<resheader name="version">
|
||||||
|
<value>2.0</value>
|
||||||
|
</resheader>
|
||||||
|
<resheader name="reader">
|
||||||
|
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||||
|
</resheader>
|
||||||
|
<resheader name="writer">
|
||||||
|
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||||
|
</resheader>
|
||||||
|
</root>
|
||||||
423
Dashboards/Dashmain/SidebarControl.cs
Normal file
423
Dashboards/Dashmain/SidebarControl.cs
Normal file
@ -0,0 +1,423 @@
|
|||||||
|
using CustomMessageBox;
|
||||||
|
using DAL;
|
||||||
|
using DALL;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Drawing;
|
||||||
|
using System.Drawing.Drawing2D;
|
||||||
|
using System.Windows.Forms;
|
||||||
|
|
||||||
|
namespace UI
|
||||||
|
{
|
||||||
|
public class SidebarControl : UserControl
|
||||||
|
{
|
||||||
|
//Recebendo a conexao
|
||||||
|
string _cx = DadosDaConexao.ObterConexao();
|
||||||
|
|
||||||
|
// ── Cores do Tema LevelOS ──────────────────────────────────────────
|
||||||
|
private static readonly Color NavyDark = Color.FromArgb(15, 30, 60);
|
||||||
|
private static readonly Color NavyMid = Color.FromArgb(26, 45, 80);
|
||||||
|
private static readonly Color AccentBlue = Color.FromArgb(37, 99, 235);
|
||||||
|
private static readonly Color TextLight = Color.FromArgb(255, 255, 255);
|
||||||
|
private static readonly Color TextMuted = Color.FromArgb(148, 163, 184);
|
||||||
|
private static readonly Color Divider = Color.FromArgb(40, 255, 255, 255);
|
||||||
|
|
||||||
|
// ── Estado e Escalonamento (DPI) ───────────────────────────────────
|
||||||
|
private float _scale = 1.0f;
|
||||||
|
private int _activeIndex = 0;
|
||||||
|
private int _hoverIndex = -1;
|
||||||
|
|
||||||
|
// Propriedades Scaled (Ajustam-se ao monitor)
|
||||||
|
private int ScaledWidth => (int)(220 * _scale);
|
||||||
|
private int ScaledLogoH => (int)(55 * _scale);
|
||||||
|
private int ScaledSectionH => (int)(32 * _scale);
|
||||||
|
private int ScaledItemH => (int)(40 * _scale);
|
||||||
|
private int ScaledItemPadX => (int)(12 * _scale);
|
||||||
|
private int ScaledFooterH => (int)(50 * _scale);
|
||||||
|
private int ScaledIconSize => (int)(16 * _scale);
|
||||||
|
|
||||||
|
// ── Submenus ───────────────────────────────────────────────────────
|
||||||
|
private ContextMenuStrip _subMenuBanco, _subMenuConfiguracao,
|
||||||
|
_subMenuAjuda, _subMenuOrdemServico, _subMenuFinanceiro,_subMenuCadastro, _subMenuAgenda;
|
||||||
|
|
||||||
|
public string UserName = "Levelcode", UserFunction = "Administrador";
|
||||||
|
public event EventHandler<int>? NavItemClicked;
|
||||||
|
|
||||||
|
private readonly List<NavItem> _items = new()
|
||||||
|
{
|
||||||
|
new NavItem("Dashboard", SvgIcon.Grid, "Principal", null),
|
||||||
|
new NavItem("Cadastro", SvgIcon.UserPlus, null, "3"),
|
||||||
|
new NavItem("Ordens de Serviço", SvgIcon.FileText, null, "12"),
|
||||||
|
new NavItem("Agenda", SvgIcon.Calendar, null, null),
|
||||||
|
new NavItem("Produtos", SvgIcon.Package, "Gestão", null),
|
||||||
|
new NavItem("Estoque", SvgIcon.Inventory, null, null),
|
||||||
|
//new NavItem("Serviços", SvgIcon.Briefcase, null, null),
|
||||||
|
//new NavItem("Transportadoras", SvgIcon.Truck, null, null),
|
||||||
|
new NavItem("Financeiro", SvgIcon.DollarSign, null, null),
|
||||||
|
new NavItem("Banco de Dados", SvgIcon.Database, "Sistema", null),
|
||||||
|
new NavItem("Configurações", SvgIcon.Settings, null, null),
|
||||||
|
new NavItem("Suporte Técnico", SvgIcon.Support, "Ajuda", null),
|
||||||
|
};
|
||||||
|
|
||||||
|
public void backupFull(string conexao)
|
||||||
|
{
|
||||||
|
var backupService = new DALLBackupService(conexao);
|
||||||
|
var resultadoFull = backupService.ExecutarBackupFull();
|
||||||
|
|
||||||
|
if (resultadoFull.Sucesso)
|
||||||
|
NT_MessageBox.Show($"✅ Backup FULL concluído em {resultadoFull.Duracao.TotalSeconds:F1}s","Backup do banco de dados",MessageBoxButtons.OK, MessageBoxIcon.Information);
|
||||||
|
else
|
||||||
|
NT_MessageBox.Show($"❌ Erro no Backup FULL: {resultadoFull.Erro}","Erro ao tentar executar backup do sistema.",MessageBoxButtons.OK,MessageBoxIcon.Error);
|
||||||
|
}//Criar backup full
|
||||||
|
|
||||||
|
public void backupDifrencial(string conexao)
|
||||||
|
{
|
||||||
|
var backupService = new DALLBackupService(conexao);
|
||||||
|
var resultadoDiff = backupService.ExecutarBackupDiferencial();
|
||||||
|
|
||||||
|
if (resultadoDiff.Sucesso)
|
||||||
|
NT_MessageBox.Show($"✅ Backup DIFERENCIAL concluído em {resultadoDiff.Duracao.TotalSeconds:F1}s","Backup diferencial concluido", MessageBoxButtons.OK, MessageBoxIcon.Information);
|
||||||
|
else
|
||||||
|
NT_MessageBox.Show($"❌ Erro no Backup DIFERENCIAL: {resultadoDiff.Erro}","Erro ao tentar executar backup diferencial no sistema", MessageBoxButtons.OK, MessageBoxIcon.Error);
|
||||||
|
}//Criar backup diferencial
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public SidebarControl()
|
||||||
|
{
|
||||||
|
BackColor = NavyDark;
|
||||||
|
DoubleBuffered = true;
|
||||||
|
this.SetStyle(ControlStyles.ResizeRedraw, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void OnHandleCreated(EventArgs e)
|
||||||
|
{
|
||||||
|
base.OnHandleCreated(e);
|
||||||
|
using (Graphics g = this.CreateGraphics()) { _scale = g.DpiX / 96f; }
|
||||||
|
this.Width = ScaledWidth;
|
||||||
|
SetupSubMenus();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void SetupSubMenus()
|
||||||
|
{
|
||||||
|
//Submenu Cadastro
|
||||||
|
_subMenuCadastro = CreateStyledMenu();
|
||||||
|
_subMenuCadastro.Items.Add("👤 Clientes", null, (s, e) => {NavItemClicked?.Invoke(this, 99);});
|
||||||
|
_subMenuCadastro.Items.Add("💻 Equipamentos", null, (s, e) => { NavItemClicked?.Invoke(this, 100); });
|
||||||
|
_subMenuCadastro.Items.Add("📜 Contratos", null, (s, e) => { NavItemClicked?.Invoke(this, 101); });
|
||||||
|
_subMenuCadastro.Items.Add("🏭 Fornecedores", null, (s, e) => { NavItemClicked?.Invoke(this, 102); });
|
||||||
|
_subMenuCadastro.Items.Add("👔 Funcionários", null, (s, e) => { NavItemClicked?.Invoke(this, 103); });
|
||||||
|
_subMenuCadastro.Items.Add("🚚 Transportadoras", null, (s, e) => { NavItemClicked?.Invoke(this, 104); });
|
||||||
|
_subMenuCadastro.Items.Add("🛠️ Serviços", null, (s, e) => { NavItemClicked?.Invoke(this, 105); });
|
||||||
|
_subMenuCadastro.Items.Add("🏢 Empresa", null, (s, e) => { NavItemClicked?.Invoke(this, 106); });
|
||||||
|
_subMenuCadastro.Items.Add("🔑 Usuários do Sistema", null, (s, e) => { NavItemClicked?.Invoke(this, 107); });
|
||||||
|
|
||||||
|
_subMenuBanco = CreateStyledMenu();
|
||||||
|
_subMenuBanco.Items.Add("⚙️ Configuração Database", null, (s, e) => showForms<Form>()); // Substitua pelo seu Form
|
||||||
|
_subMenuBanco.Items.Add("💾 Backup de Dados (FULL)", null, (s, e) => backupFull(this._cx));
|
||||||
|
_subMenuBanco.Items.Add("⚡ Backup de Dados (DIFF)", null, (s, e) => backupDifrencial(this._cx));
|
||||||
|
_subMenuBanco.Items.Add("🔄 Restaurar Banco");
|
||||||
|
|
||||||
|
|
||||||
|
//submenu Configurações
|
||||||
|
_subMenuConfiguracao = CreateStyledMenu();
|
||||||
|
_subMenuConfiguracao.Items.Add("🖼️ Personalização de OS");
|
||||||
|
_subMenuConfiguracao.Items.Add("🖥️ Personalização de Sistema");
|
||||||
|
_subMenuConfiguracao.Items.Add(" Configuração Empresa", null, (s, e) => { NavItemClicked?.Invoke(this, 202); });
|
||||||
|
_subMenuConfiguracao.Items.Add(new ToolStripSeparator());
|
||||||
|
_subMenuConfiguracao.Items.Add("📂 FTP-Cliente"); // Pasta para arquivos
|
||||||
|
_subMenuConfiguracao.Items.Add("💬 Telegram-Cliente"); // Balão de conversa
|
||||||
|
_subMenuConfiguracao.Items.Add("📩 SMTP-Cliente"); // Envelope de saída
|
||||||
|
_subMenuConfiguracao.Items.Add(new ToolStripSeparator());
|
||||||
|
// Automação
|
||||||
|
_subMenuConfiguracao.Items.Add("⏰ Backups Automáticos"); // Relógio para agendamento
|
||||||
|
_subMenuConfiguracao.Items.Add("☁️ Backup em Nuvem");
|
||||||
|
|
||||||
|
_subMenuAjuda = CreateStyledMenu();
|
||||||
|
_subMenuAjuda.Items.Add("💬 Atendimento Online");
|
||||||
|
_subMenuAjuda.Items.Add("📖 Manual do Sistema");
|
||||||
|
|
||||||
|
_subMenuOrdemServico = CreateStyledMenu();
|
||||||
|
|
||||||
|
_subMenuOrdemServico.Items.Add("✚ Abrir nova O.S", null, (s, e) => { /* Lógica */ });
|
||||||
|
_subMenuOrdemServico.Items.Add("✎ Alterar O.S", null, (s, e) => { /* Lógica */ });
|
||||||
|
_subMenuOrdemServico.Items.Add("🔒 Encerrar O.S", null, (s, e) => { /* Lógica */ });
|
||||||
|
_subMenuOrdemServico.Items.Add("🔍 Localizar O.S", null, (s, e) => { /* Lógica */ });
|
||||||
|
_subMenuOrdemServico.Items.Add("📋 Orçamento de O.S", null, (s, e) => { /* Lógica */ });
|
||||||
|
_subMenuOrdemServico.Items.Add("📜 Histórico de O.S", null, (s, e) => { /* Lógica */ });
|
||||||
|
_subMenuOrdemServico.Items.Add("📊 Relatório de O.S", null, (s, e) => { /* Lógica */ });
|
||||||
|
_subMenuOrdemServico.Items.Add("🖨 Imprimir", null, (s, e) => { /* Lógica */ });
|
||||||
|
_subMenuOrdemServico.Items.Add("⚠️ Chamado Técnico", null, (s, e) => { /* Lógica */ });
|
||||||
|
_subMenuOrdemServico.Items.Add("🌐 OS WEB", null, (s, e) => { /* Lógica */ });
|
||||||
|
_subMenuOrdemServico.Items.Add("🔓 Reabrir OS", null, (s, e) => { /* Lógica */ });
|
||||||
|
|
||||||
|
_subMenuFinanceiro = CreateStyledMenu();
|
||||||
|
|
||||||
|
_subMenuFinanceiro.Items.Add("💳 Contas", null, (s, e) => { /* Lógica */ });
|
||||||
|
_subMenuFinanceiro.Items.Add("📈 Contas a receber", null, (s, e) => { /* Lógica */ });
|
||||||
|
_subMenuFinanceiro.Items.Add("📉 Contas a pagar", null, (s, e) => { /* Lógica */ });
|
||||||
|
_subMenuFinanceiro.Items.Add(new ToolStripSeparator()); // Linha divisória
|
||||||
|
_subMenuFinanceiro.Items.Add("🛒 Compras", null, (s, e) => { /* Lógica */ });
|
||||||
|
_subMenuFinanceiro.Items.Add("💰 Vendas", null, (s, e) => { /* Lógica */ });
|
||||||
|
_subMenuFinanceiro.Items.Add("🧾 Notas Fiscais", null, (s, e) => { /* Lógica */ });
|
||||||
|
_subMenuFinanceiro.Items.Add(new ToolStripSeparator()); // Linha divisória
|
||||||
|
_subMenuFinanceiro.Items.Add("📂 Arquivo Contador", null, (s, e) => { /* Lógica */ });
|
||||||
|
_subMenuFinanceiro.Items.Add("🏦 Dados Bancários", null, (s, e) => { /* Lógica */ });
|
||||||
|
_subMenuFinanceiro.Items.Add("🕒 Histórico Financeiro", null, (s, e) => { /* Lógica */ });
|
||||||
|
|
||||||
|
|
||||||
|
// private ContextMenuStrip _subMenuAgenda;
|
||||||
|
_subMenuAgenda = CreateStyledMenu();
|
||||||
|
//_subMenuAgenda.Items.Add("➕ Novo compromisso", null, (s, e) => {showForms<AgendaForm>();});
|
||||||
|
_subMenuAgenda.Items.Add("➕ Novo compromisso", null, (s, e) => { NavItemClicked?.Invoke(this, 300); });
|
||||||
|
_subMenuAgenda.Items.Add("🔍 Consultar compromissos", null, (s, e) => { NavItemClicked?.Invoke(this, 301); });
|
||||||
|
_subMenuAgenda.Items.Add("✏️ Alterar compromisso", null, (s, e) => { /* Lógica de edição */ });
|
||||||
|
_subMenuAgenda.Items.Add("🖨️ Imprimir", null, (s, e) => { /* Lógica de relatório */ });
|
||||||
|
}
|
||||||
|
|
||||||
|
private ContextMenuStrip CreateStyledMenu()
|
||||||
|
{
|
||||||
|
return new ContextMenuStrip
|
||||||
|
{
|
||||||
|
BackColor = NavyMid,
|
||||||
|
ForeColor = TextLight,
|
||||||
|
ShowImageMargin = false,
|
||||||
|
Font = new Font("Segoe UI", 10f * _scale),
|
||||||
|
Renderer = new ToolStripProfessionalRenderer(new SubMenuColorTable())
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private void showForms<T>() where T : Form, new()
|
||||||
|
{
|
||||||
|
using (T form = new T())
|
||||||
|
{
|
||||||
|
form.StartPosition = FormStartPosition.CenterScreen;
|
||||||
|
form.ShowDialog();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//Abrir agenda
|
||||||
|
// AgendaForm.cs
|
||||||
|
public class AgendaForm : Form
|
||||||
|
{
|
||||||
|
public AgendaForm()
|
||||||
|
{
|
||||||
|
Text = "Agenda de Compromissos";
|
||||||
|
Size = new Size(1150, 780);
|
||||||
|
StartPosition = FormStartPosition.CenterScreen;
|
||||||
|
BackColor = Color.White;
|
||||||
|
|
||||||
|
var panel = new AgendaCadastroPanel();
|
||||||
|
Controls.Add(panel);
|
||||||
|
}
|
||||||
|
}//abrir agenda de compromissos
|
||||||
|
|
||||||
|
protected override void OnPaint(PaintEventArgs e)
|
||||||
|
{
|
||||||
|
var g = e.Graphics;
|
||||||
|
g.SmoothingMode = SmoothingMode.AntiAlias;
|
||||||
|
g.TextRenderingHint = System.Drawing.Text.TextRenderingHint.ClearTypeGridFit;
|
||||||
|
|
||||||
|
DrawLogo(g);
|
||||||
|
DrawNavItems(g, ScaledLogoH + (int)(8 * _scale));
|
||||||
|
DrawFooter(g);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void DrawNavItems(Graphics g, int startY)
|
||||||
|
{
|
||||||
|
int y = startY;
|
||||||
|
using var fSection = new Font("Segoe UI", 8f * _scale, FontStyle.Bold);
|
||||||
|
using var fItem = new Font("Segoe UI", 10f * _scale);
|
||||||
|
using var fItemSel = new Font("Segoe UI Semibold", 10f * _scale);
|
||||||
|
|
||||||
|
for (int i = 0; i < _items.Count; i++)
|
||||||
|
{
|
||||||
|
var item = _items[i];
|
||||||
|
if (item.Section != null)
|
||||||
|
{
|
||||||
|
y += (int)(10 * _scale);
|
||||||
|
g.DrawString(item.Section.ToUpper(), fSection, new SolidBrush(Color.FromArgb(120, TextMuted)), ScaledItemPadX + (int)(8 * _scale), y);
|
||||||
|
y += ScaledSectionH;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool isActive = (i == _activeIndex);
|
||||||
|
bool isHover = (i == _hoverIndex && !isActive);
|
||||||
|
var itemRect = new Rectangle(ScaledItemPadX, y, Width - ScaledItemPadX * 2, ScaledItemH);
|
||||||
|
|
||||||
|
if (isActive) FillRoundRect(g, new SolidBrush(AccentBlue), itemRect, (int)(6 * _scale));
|
||||||
|
else if (isHover) FillRoundRect(g, new SolidBrush(Color.FromArgb(20, 255, 255, 255)), itemRect, (int)(6 * _scale));
|
||||||
|
|
||||||
|
var color = isActive ? TextLight : Color.FromArgb(200, TextLight);
|
||||||
|
DrawIcon(g, item.Icon, ScaledItemPadX + (int)(10 * _scale), y + (ScaledItemH - ScaledIconSize) / 2, ScaledIconSize, color);
|
||||||
|
g.DrawString(item.Label, isActive ? fItemSel : fItem, new SolidBrush(color), ScaledItemPadX + (int)(36 * _scale), y + (ScaledItemH - (int)(16 * _scale)) / 2);
|
||||||
|
|
||||||
|
if (HasSubMenu(item.Label))
|
||||||
|
g.DrawString("›", fItem, new SolidBrush(Color.FromArgb(100, TextLight)), Width - (int)(30 * _scale), y + (ScaledItemH - (int)(18 * _scale)) / 2);
|
||||||
|
|
||||||
|
y += ScaledItemH + (int)(2 * _scale);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Adicione "Cadastro" na verificação
|
||||||
|
private bool HasSubMenu(string label) =>
|
||||||
|
label == "Cadastro" || // <-- Adicionado aqui
|
||||||
|
label == "Banco de Dados" ||
|
||||||
|
label == "Financeiro" ||
|
||||||
|
label == "Ordens de Serviço" ||
|
||||||
|
label == "Configurações" ||
|
||||||
|
label == "Suporte Técnico" ||
|
||||||
|
label == "Agenda"
|
||||||
|
;
|
||||||
|
|
||||||
|
protected override void OnMouseClick(MouseEventArgs e)
|
||||||
|
{
|
||||||
|
int hit = HitTest(e.Y);
|
||||||
|
if (hit >= 0)
|
||||||
|
{
|
||||||
|
_activeIndex = hit; Invalidate();
|
||||||
|
string label = _items[hit].Label;
|
||||||
|
Point menuPos = new Point(Width + 2, e.Y - (int)(15 * _scale));
|
||||||
|
|
||||||
|
if (label == "Banco de Dados") _subMenuBanco.Show(this, menuPos);
|
||||||
|
else if (label == "Financeiro") _subMenuFinanceiro.Show(this, menuPos);
|
||||||
|
else if(label == "Agenda") _subMenuAgenda.Show(this, menuPos);
|
||||||
|
else if (label == "Ordens de Serviço") _subMenuOrdemServico.Show(this, menuPos);
|
||||||
|
else if (label == "Configurações") _subMenuConfiguracao.Show(this, menuPos);
|
||||||
|
else if (label == "Suporte Técnico") _subMenuAjuda.Show(this, menuPos);
|
||||||
|
else if (label == "Cadastro") _subMenuCadastro.Show(this, menuPos);
|
||||||
|
else NavItemClicked?.Invoke(this, hit);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private int HitTest(int mouseY)
|
||||||
|
{
|
||||||
|
int y = ScaledLogoH + (int)(8 * _scale);
|
||||||
|
for (int i = 0; i < _items.Count; i++)
|
||||||
|
{
|
||||||
|
if (_items[i].Section != null) y += (int)(10 * _scale) + ScaledSectionH;
|
||||||
|
if (mouseY >= y && mouseY < y + ScaledItemH) return i;
|
||||||
|
y += ScaledItemH + (int)(2 * _scale);
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void OnMouseMove(MouseEventArgs e) { int hit = HitTest(e.Y); if (hit != _hoverIndex) { _hoverIndex = hit; Invalidate(); } }
|
||||||
|
protected override void OnMouseLeave(EventArgs e) { _hoverIndex = -1; Invalidate(); }
|
||||||
|
|
||||||
|
private void DrawLogo(Graphics g)
|
||||||
|
{
|
||||||
|
var iconRect = new Rectangle((int)(16 * _scale), (int)(18 * _scale), (int)(34 * _scale), (int)(34 * _scale));
|
||||||
|
FillRoundRect(g, new SolidBrush(AccentBlue), iconRect, (int)(8 * _scale));
|
||||||
|
using var fIcon = new Font("Segoe UI", 14f * _scale, FontStyle.Bold);
|
||||||
|
DrawCenteredString(g, "S", fIcon, TextLight, iconRect);
|
||||||
|
g.DrawString("LevelOS", new Font("Segoe UI Semibold", 13f * _scale), new SolidBrush(TextLight), 58 * _scale, 20 * _scale);
|
||||||
|
g.DrawString("SISTEMA ERP", new Font("Segoe UI", 8f * _scale), new SolidBrush(TextMuted), 59 * _scale, 38 * _scale);
|
||||||
|
g.DrawLine(new Pen(Divider), 0, ScaledLogoH, Width, ScaledLogoH);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void DrawFooter(Graphics g)
|
||||||
|
{
|
||||||
|
int fy = Height - ScaledFooterH;
|
||||||
|
g.DrawLine(new Pen(Divider), 0, fy, Width, fy);
|
||||||
|
var avRect = new Rectangle((int)(16 * _scale), fy + (int)(14 * _scale), (int)(32 * _scale), (int)(32 * _scale));
|
||||||
|
g.FillEllipse(new SolidBrush(AccentBlue), avRect);
|
||||||
|
DrawCenteredString(g, "AD", new Font("Segoe UI Semibold", 10f * _scale), TextLight, avRect);
|
||||||
|
g.DrawString(UserName, new Font("Segoe UI Semibold", 11f * _scale), new SolidBrush(TextLight), 56 * _scale, fy + (14 * _scale));
|
||||||
|
g.DrawString(UserFunction, new Font("Segoe UI", 9f * _scale), new SolidBrush(TextMuted), 57 * _scale, fy + (30 * _scale));
|
||||||
|
}
|
||||||
|
|
||||||
|
// ── MOTOR DE ÍCONES COMPLETO (GDI+) ────────────────────────────────
|
||||||
|
private void DrawIcon(Graphics g, SvgIcon icon, int x, int y, int size, Color color)
|
||||||
|
{
|
||||||
|
using var p = new Pen(color, 1.6f * _scale) { StartCap = LineCap.Round, EndCap = LineCap.Round, LineJoin = LineJoin.Round };
|
||||||
|
float s = size / 24f;
|
||||||
|
g.TranslateTransform(x, y); g.ScaleTransform(s, s);
|
||||||
|
|
||||||
|
switch (icon)
|
||||||
|
{
|
||||||
|
case SvgIcon.Grid:
|
||||||
|
g.DrawRectangle(p, 3, 3, 7, 7); g.DrawRectangle(p, 14, 3, 7, 7); g.DrawRectangle(p, 3, 14, 7, 7); g.DrawRectangle(p, 14, 14, 7, 7); break;
|
||||||
|
case SvgIcon.Users:
|
||||||
|
g.DrawEllipse(p, 5, 3, 8, 8); g.DrawArc(p, 2, 13, 14, 8, 180, 180); g.DrawArc(p, 15, 8, 6, 6, 270, 180); break;
|
||||||
|
case SvgIcon.FileText:
|
||||||
|
g.DrawLines(p, new PointF[] { new(6, 2), new(6, 22), new(18, 22), new(18, 8), new(14, 2), new(6, 2) }); g.DrawLine(p, 14, 2, 14, 8); g.DrawLine(p, 14, 8, 18, 8); break;
|
||||||
|
case SvgIcon.Package:
|
||||||
|
g.DrawLines(p, new PointF[] { new(12, 2), new(2, 7), new(12, 12), new(22, 7), new(12, 2) }); g.DrawLine(p, 2, 7, 2, 17); g.DrawLine(p, 22, 7, 22, 17); g.DrawLine(p, 12, 12, 12, 22); break;
|
||||||
|
case SvgIcon.DollarSign:
|
||||||
|
g.DrawLine(p, 12, 2, 12, 22); g.DrawArc(p, 7, 5, 10, 7, 110, 250); g.DrawArc(p, 7, 12, 10, 7, 270, 250); break;
|
||||||
|
case SvgIcon.Database:
|
||||||
|
g.DrawEllipse(p, 4, 3, 16, 6); g.DrawLine(p, 4, 6, 4, 18); g.DrawLine(p, 20, 6, 20, 18); g.DrawArc(p, 4, 15, 16, 6, 0, 180); break;
|
||||||
|
case SvgIcon.Calendar:
|
||||||
|
g.DrawRectangle(p, 3, 4, 18, 17); g.DrawLine(p, 3, 9, 21, 9); g.DrawLine(p, 8, 2, 8, 6); g.DrawLine(p, 16, 2, 16, 6); break;
|
||||||
|
case SvgIcon.Truck:
|
||||||
|
g.DrawRectangle(p, 1, 5, 13, 11); g.DrawLines(p, new PointF[] { new(14, 16), new(14, 8), new(19, 8), new(23, 12), new(23, 16) });
|
||||||
|
g.DrawEllipse(p, 3, 15, 4, 4); g.DrawEllipse(p, 17, 15, 4, 4); break;
|
||||||
|
case SvgIcon.Factory:
|
||||||
|
g.DrawRectangle(p, 2, 10, 20, 11); g.DrawLines(p, new PointF[] { new(2, 10), new(2, 5), new(8, 10), new(8, 5), new(14, 10) }); break;
|
||||||
|
case SvgIcon.Briefcase:
|
||||||
|
g.DrawRectangle(p, 3, 7, 18, 13); g.DrawArc(p, 9, 3, 6, 8, 180, 180); break;
|
||||||
|
case SvgIcon.Support:
|
||||||
|
g.DrawArc(p, 4, 4, 16, 16, 180, 180); g.DrawRectangle(p, 3, 13, 3, 5); g.DrawRectangle(p, 18, 13, 3, 5); break;
|
||||||
|
case SvgIcon.Inventory:
|
||||||
|
g.DrawRectangle(p, 3, 3, 18, 8); g.DrawRectangle(p, 3, 13, 18, 8); break;
|
||||||
|
case SvgIcon.Settings:
|
||||||
|
g.DrawEllipse(p, 9, 9, 6, 6);
|
||||||
|
for (int a = 0; a < 360; a += 45)
|
||||||
|
{
|
||||||
|
float r = a * (float)Math.PI / 180f;
|
||||||
|
g.DrawLine(p, 12 + (float)Math.Cos(r) * 8, 12 + (float)Math.Sin(r) * 8, 12 + (float)Math.Cos(r) * 11, 12 + (float)Math.Sin(r) * 11);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case SvgIcon.User: g.DrawEllipse(p, 8, 2, 8, 8); g.DrawArc(p, 3, 14, 18, 8, 180, 180); break;
|
||||||
|
case SvgIcon.UserCheck: g.DrawEllipse(p, 8, 3, 8, 8); g.DrawArc(p, 3, 14, 18, 8, 180, 180); g.DrawRectangle(p, 10, 15, 4, 3); break;
|
||||||
|
case SvgIcon.UserPlus:
|
||||||
|
// Desenha o corpo do usuário (círculo e arco)
|
||||||
|
g.DrawEllipse(p, 4, 4, 8, 8); // Cabeça
|
||||||
|
g.DrawArc(p, 1, 14, 14, 8, 180, 180); // Ombros
|
||||||
|
|
||||||
|
// Desenha o sinal de "+" ao lado
|
||||||
|
// Vertical
|
||||||
|
g.DrawLine(p, 19, 7, 19, 15);
|
||||||
|
// Horizontal
|
||||||
|
g.DrawLine(p, 15, 11, 23, 11);
|
||||||
|
break;
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
g.ResetTransform();
|
||||||
|
}
|
||||||
|
|
||||||
|
// ── Helpers ──
|
||||||
|
private static void FillRoundRect(Graphics g, Brush b, Rectangle r, int rad) { using var path = RoundRectPath(r, rad); g.FillPath(b, path); }
|
||||||
|
private static GraphicsPath RoundRectPath(Rectangle r, int rad)
|
||||||
|
{
|
||||||
|
var path = new GraphicsPath(); int d = Math.Max(rad * 2, 1);
|
||||||
|
path.AddArc(r.X, r.Y, d, d, 180, 90); path.AddArc(r.Right - d, r.Y, d, d, 270, 90);
|
||||||
|
path.AddArc(r.Right - d, r.Bottom - d, d, d, 0, 90); path.AddArc(r.X, r.Bottom - d, d, d, 90, 90);
|
||||||
|
path.CloseFigure(); return path;
|
||||||
|
}
|
||||||
|
private static void DrawCenteredString(Graphics g, string t, Font f, Color c, Rectangle r)
|
||||||
|
{
|
||||||
|
var sf = new StringFormat { Alignment = StringAlignment.Center, LineAlignment = StringAlignment.Center };
|
||||||
|
g.DrawString(t, f, new SolidBrush(c), r, sf);
|
||||||
|
}
|
||||||
|
|
||||||
|
private class NavItem
|
||||||
|
{
|
||||||
|
public string Label { get; }
|
||||||
|
public SvgIcon Icon { get; }
|
||||||
|
public string? Section { get; }
|
||||||
|
public string? Badge { get; }
|
||||||
|
public NavItem(string l, SvgIcon i, string? s, string? b) { Label = l; Icon = i; Section = s; Badge = b; }
|
||||||
|
}
|
||||||
|
private class SubMenuColorTable : ProfessionalColorTable
|
||||||
|
{
|
||||||
|
public override Color ToolStripDropDownBackground => NavyMid;
|
||||||
|
public override Color MenuItemSelected => AccentBlue;
|
||||||
|
public override Color MenuItemBorder => Color.Transparent;
|
||||||
|
public override Color MenuItemSelectedGradientBegin => AccentBlue;
|
||||||
|
public override Color MenuItemSelectedGradientEnd => AccentBlue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum SvgIcon { Grid, Users, FileText, Package, DollarSign, User, Settings, Database, Truck, Factory, UserCheck, Briefcase, Support, Inventory, Wallet, ShoppingCart, ShoppingBag, Calendar , UserPlus}
|
||||||
|
}
|
||||||
120
Dashboards/Dashmain/SidebarControl.resx
Normal file
120
Dashboards/Dashmain/SidebarControl.resx
Normal file
@ -0,0 +1,120 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<root>
|
||||||
|
<!--
|
||||||
|
Microsoft ResX Schema
|
||||||
|
|
||||||
|
Version 2.0
|
||||||
|
|
||||||
|
The primary goals of this format is to allow a simple XML format
|
||||||
|
that is mostly human readable. The generation and parsing of the
|
||||||
|
various data types are done through the TypeConverter classes
|
||||||
|
associated with the data types.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
... ado.net/XML headers & schema ...
|
||||||
|
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||||
|
<resheader name="version">2.0</resheader>
|
||||||
|
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||||
|
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||||
|
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
||||||
|
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||||
|
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||||
|
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
||||||
|
</data>
|
||||||
|
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||||
|
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||||
|
<comment>This is a comment</comment>
|
||||||
|
</data>
|
||||||
|
|
||||||
|
There are any number of "resheader" rows that contain simple
|
||||||
|
name/value pairs.
|
||||||
|
|
||||||
|
Each data row contains a name, and value. The row also contains a
|
||||||
|
type or mimetype. Type corresponds to a .NET class that support
|
||||||
|
text/value conversion through the TypeConverter architecture.
|
||||||
|
Classes that don't support this are serialized and stored with the
|
||||||
|
mimetype set.
|
||||||
|
|
||||||
|
The mimetype is used for serialized objects, and tells the
|
||||||
|
ResXResourceReader how to depersist the object. This is currently not
|
||||||
|
extensible. For a given mimetype the value must be set accordingly:
|
||||||
|
|
||||||
|
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||||
|
that the ResXResourceWriter will generate, however the reader can
|
||||||
|
read any of the formats listed below.
|
||||||
|
|
||||||
|
mimetype: application/x-microsoft.net.object.binary.base64
|
||||||
|
value : The object must be serialized with
|
||||||
|
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
|
||||||
|
: and then encoded with base64 encoding.
|
||||||
|
|
||||||
|
mimetype: application/x-microsoft.net.object.soap.base64
|
||||||
|
value : The object must be serialized with
|
||||||
|
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||||
|
: and then encoded with base64 encoding.
|
||||||
|
|
||||||
|
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||||
|
value : The object must be serialized into a byte array
|
||||||
|
: using a System.ComponentModel.TypeConverter
|
||||||
|
: and then encoded with base64 encoding.
|
||||||
|
-->
|
||||||
|
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||||
|
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
||||||
|
<xsd:element name="root" msdata:IsDataSet="true">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:choice maxOccurs="unbounded">
|
||||||
|
<xsd:element name="metadata">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:sequence>
|
||||||
|
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||||
|
</xsd:sequence>
|
||||||
|
<xsd:attribute name="name" use="required" type="xsd:string" />
|
||||||
|
<xsd:attribute name="type" type="xsd:string" />
|
||||||
|
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||||
|
<xsd:attribute ref="xml:space" />
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
<xsd:element name="assembly">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:attribute name="alias" type="xsd:string" />
|
||||||
|
<xsd:attribute name="name" type="xsd:string" />
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
<xsd:element name="data">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:sequence>
|
||||||
|
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||||
|
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||||
|
</xsd:sequence>
|
||||||
|
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
|
||||||
|
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||||
|
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||||
|
<xsd:attribute ref="xml:space" />
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
<xsd:element name="resheader">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:sequence>
|
||||||
|
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||||
|
</xsd:sequence>
|
||||||
|
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
</xsd:choice>
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
</xsd:schema>
|
||||||
|
<resheader name="resmimetype">
|
||||||
|
<value>text/microsoft-resx</value>
|
||||||
|
</resheader>
|
||||||
|
<resheader name="version">
|
||||||
|
<value>2.0</value>
|
||||||
|
</resheader>
|
||||||
|
<resheader name="reader">
|
||||||
|
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||||
|
</resheader>
|
||||||
|
<resheader name="writer">
|
||||||
|
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||||
|
</resheader>
|
||||||
|
</root>
|
||||||
132
Dashboards/Main/Dash_main.Designer.cs
generated
Normal file
132
Dashboards/Main/Dash_main.Designer.cs
generated
Normal file
@ -0,0 +1,132 @@
|
|||||||
|
namespace UI
|
||||||
|
{
|
||||||
|
partial class Form1
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Required designer variable.
|
||||||
|
/// </summary>
|
||||||
|
private System.ComponentModel.IContainer components = null;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Clean up any resources being used.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
|
||||||
|
protected override void Dispose(bool disposing)
|
||||||
|
{
|
||||||
|
if (disposing && (components != null))
|
||||||
|
{
|
||||||
|
components.Dispose();
|
||||||
|
}
|
||||||
|
base.Dispose(disposing);
|
||||||
|
}
|
||||||
|
|
||||||
|
#region Windows Form Designer generated code
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Required method for Designer support - do not modify
|
||||||
|
/// the contents of this method with the code editor.
|
||||||
|
/// </summary>
|
||||||
|
private void InitializeComponent()
|
||||||
|
{
|
||||||
|
lbltest = new Label();
|
||||||
|
lV_button1 = new CPM.LV_BUTTON();
|
||||||
|
lV_button2 = new CPM.LV_BUTTON();
|
||||||
|
lV_button3 = new CPM.LV_BUTTON();
|
||||||
|
SuspendLayout();
|
||||||
|
//
|
||||||
|
// lbltest
|
||||||
|
//
|
||||||
|
lbltest.AutoSize = true;
|
||||||
|
lbltest.Location = new Point(12, 9);
|
||||||
|
lbltest.Name = "lbltest";
|
||||||
|
lbltest.Size = new Size(38, 15);
|
||||||
|
lbltest.TabIndex = 0;
|
||||||
|
lbltest.Text = "label1";
|
||||||
|
//
|
||||||
|
// lV_button1
|
||||||
|
//
|
||||||
|
lV_button1.BackColor = Color.MediumSlateBlue;
|
||||||
|
lV_button1.BackgroundColor = Color.MediumSlateBlue;
|
||||||
|
lV_button1.BorderColor = Color.PaleVioletRed;
|
||||||
|
lV_button1.BorderRadius = 0;
|
||||||
|
lV_button1.BorderSize = 0;
|
||||||
|
lV_button1.ClickColor = Color.DarkBlue;
|
||||||
|
lV_button1.FlatAppearance.BorderSize = 0;
|
||||||
|
lV_button1.FlatStyle = FlatStyle.Flat;
|
||||||
|
lV_button1.ForeColor = Color.White;
|
||||||
|
lV_button1.HoverColor = Color.LightBlue;
|
||||||
|
lV_button1.Location = new Point(734, 12);
|
||||||
|
lV_button1.Name = "lV_button1";
|
||||||
|
lV_button1.Size = new Size(148, 32);
|
||||||
|
lV_button1.TabIndex = 1;
|
||||||
|
lV_button1.Text = "FrmConfigDB";
|
||||||
|
lV_button1.TextColor = Color.White;
|
||||||
|
lV_button1.UseVisualStyleBackColor = false;
|
||||||
|
lV_button1.Click += lV_button1_Click;
|
||||||
|
//
|
||||||
|
// lV_button2
|
||||||
|
//
|
||||||
|
lV_button2.BackColor = Color.MediumSlateBlue;
|
||||||
|
lV_button2.BackgroundColor = Color.MediumSlateBlue;
|
||||||
|
lV_button2.BorderColor = Color.PaleVioletRed;
|
||||||
|
lV_button2.BorderRadius = 0;
|
||||||
|
lV_button2.BorderSize = 0;
|
||||||
|
lV_button2.ClickColor = Color.DarkBlue;
|
||||||
|
lV_button2.FlatAppearance.BorderSize = 0;
|
||||||
|
lV_button2.FlatStyle = FlatStyle.Flat;
|
||||||
|
lV_button2.ForeColor = Color.White;
|
||||||
|
lV_button2.HoverColor = Color.LightBlue;
|
||||||
|
lV_button2.Location = new Point(734, 50);
|
||||||
|
lV_button2.Name = "lV_button2";
|
||||||
|
lV_button2.Size = new Size(148, 32);
|
||||||
|
lV_button2.TabIndex = 2;
|
||||||
|
lV_button2.Text = "Dashmain";
|
||||||
|
lV_button2.TextColor = Color.White;
|
||||||
|
lV_button2.UseVisualStyleBackColor = false;
|
||||||
|
lV_button2.Click += lV_button2_Click;
|
||||||
|
//
|
||||||
|
// lV_button3
|
||||||
|
//
|
||||||
|
lV_button3.BackColor = Color.MediumSlateBlue;
|
||||||
|
lV_button3.BackgroundColor = Color.MediumSlateBlue;
|
||||||
|
lV_button3.BorderColor = Color.PaleVioletRed;
|
||||||
|
lV_button3.BorderRadius = 0;
|
||||||
|
lV_button3.BorderSize = 0;
|
||||||
|
lV_button3.ClickColor = Color.DarkBlue;
|
||||||
|
lV_button3.FlatAppearance.BorderSize = 0;
|
||||||
|
lV_button3.FlatStyle = FlatStyle.Flat;
|
||||||
|
lV_button3.ForeColor = Color.White;
|
||||||
|
lV_button3.HoverColor = Color.LightBlue;
|
||||||
|
lV_button3.Location = new Point(734, 88);
|
||||||
|
lV_button3.Name = "lV_button3";
|
||||||
|
lV_button3.Size = new Size(148, 32);
|
||||||
|
lV_button3.TabIndex = 3;
|
||||||
|
lV_button3.Text = "Arquivo Encryptado";
|
||||||
|
lV_button3.TextColor = Color.White;
|
||||||
|
lV_button3.UseVisualStyleBackColor = false;
|
||||||
|
lV_button3.Click += lV_button3_Click;
|
||||||
|
//
|
||||||
|
// Form1
|
||||||
|
//
|
||||||
|
AutoScaleDimensions = new SizeF(7F, 15F);
|
||||||
|
AutoScaleMode = AutoScaleMode.Font;
|
||||||
|
ClientSize = new Size(894, 474);
|
||||||
|
Controls.Add(lV_button3);
|
||||||
|
Controls.Add(lV_button2);
|
||||||
|
Controls.Add(lV_button1);
|
||||||
|
Controls.Add(lbltest);
|
||||||
|
Name = "Form1";
|
||||||
|
Text = "Form1";
|
||||||
|
Load += Form1_Load;
|
||||||
|
ResumeLayout(false);
|
||||||
|
PerformLayout();
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
private Label lbltest;
|
||||||
|
private CPM.LV_BUTTON lV_button1;
|
||||||
|
private CPM.LV_BUTTON lV_button2;
|
||||||
|
private CPM.LV_BUTTON lV_button3;
|
||||||
|
}
|
||||||
|
}
|
||||||
75
Dashboards/Main/Dash_main.cs
Normal file
75
Dashboards/Main/Dash_main.cs
Normal file
@ -0,0 +1,75 @@
|
|||||||
|
using CAB;
|
||||||
|
using CCH;
|
||||||
|
using CPM;
|
||||||
|
using CPT;
|
||||||
|
using CustomMessageBox;
|
||||||
|
using DAL;
|
||||||
|
using TLL;
|
||||||
|
using static CPT.SecurityManager;
|
||||||
|
|
||||||
|
namespace UI
|
||||||
|
{
|
||||||
|
public partial class Form1 : Form
|
||||||
|
{
|
||||||
|
public Form1()
|
||||||
|
{
|
||||||
|
InitializeComponent();
|
||||||
|
string caminhoIcone = AppFileSystem.AppFileIconSystem;
|
||||||
|
|
||||||
|
if (File.Exists(caminhoIcone))
|
||||||
|
{
|
||||||
|
this.Icon = new Icon(caminhoIcone);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Form1_Load(object sender, EventArgs e)
|
||||||
|
{
|
||||||
|
DadosDaConexao.Host = "206.42.13.180";
|
||||||
|
DadosDaConexao.Port = 1433;
|
||||||
|
DadosDaConexao.Banco = "Levelcode-LevelOS";
|
||||||
|
DadosDaConexao.Usuario = "nicolas";
|
||||||
|
DadosDaConexao.Senha = "Nike12122020*##";
|
||||||
|
DadosDaConexao.ConnectTimeout = 1000;
|
||||||
|
DadosDaConexao.Encrypt = false;
|
||||||
|
DadosDaConexao.TrustServerCertificate = false;
|
||||||
|
|
||||||
|
DatabaseHelper.Salvar(AppFileSystem.AppFileDBSystem, AppInfoSystem.AppKeyMasterCrip);
|
||||||
|
DatabaseHelper.Carregar(AppFileSystem.AppFileDBSystem, AppInfoSystem.AppKeyMasterCrip);
|
||||||
|
this.lbltest.Text = DadosDaConexao.Host;
|
||||||
|
if (DadosDaConexao.TestarConexao())
|
||||||
|
{
|
||||||
|
NT_MessageBox.Show("Conexão com o banco de dados concluida com sucesso!", "Teste de conexão");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void lV_button1_Click(object sender, EventArgs e)
|
||||||
|
{
|
||||||
|
FrmConfigBanco f = new FrmConfigBanco();
|
||||||
|
f.ShowDialog();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void lV_button2_Click(object sender, EventArgs e)
|
||||||
|
{
|
||||||
|
MainForm main = new MainForm();
|
||||||
|
main.ShowDialog();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void lV_button3_Click(object sender, EventArgs e)
|
||||||
|
{
|
||||||
|
string caminhoKey = @"C:\Levelcode\LevelOS\Config\config.json";
|
||||||
|
DadosDaConexao.Host = "206.42.13.180";
|
||||||
|
DadosDaConexao.Port = 1433;
|
||||||
|
DadosDaConexao.Banco = "Levelcode-LevelOS";
|
||||||
|
DadosDaConexao.Usuario = "nicolas";
|
||||||
|
DadosDaConexao.Senha = "Nike12122020*##";
|
||||||
|
DadosDaConexao.ConnectTimeout = 1000;
|
||||||
|
DadosDaConexao.Encrypt = false;
|
||||||
|
DadosDaConexao.TrustServerCertificate = false;
|
||||||
|
DatabaseHelperCPT.Salvar(caminhoKey);
|
||||||
|
string conectionString = DatabaseHelperCPT.Carregar(caminhoKey);
|
||||||
|
NT_MessageBox.Show(conectionString);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
120
Dashboards/Main/Dash_main.resx
Normal file
120
Dashboards/Main/Dash_main.resx
Normal file
@ -0,0 +1,120 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<root>
|
||||||
|
<!--
|
||||||
|
Microsoft ResX Schema
|
||||||
|
|
||||||
|
Version 2.0
|
||||||
|
|
||||||
|
The primary goals of this format is to allow a simple XML format
|
||||||
|
that is mostly human readable. The generation and parsing of the
|
||||||
|
various data types are done through the TypeConverter classes
|
||||||
|
associated with the data types.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
... ado.net/XML headers & schema ...
|
||||||
|
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||||
|
<resheader name="version">2.0</resheader>
|
||||||
|
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||||
|
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||||
|
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
||||||
|
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||||
|
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||||
|
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
||||||
|
</data>
|
||||||
|
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||||
|
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||||
|
<comment>This is a comment</comment>
|
||||||
|
</data>
|
||||||
|
|
||||||
|
There are any number of "resheader" rows that contain simple
|
||||||
|
name/value pairs.
|
||||||
|
|
||||||
|
Each data row contains a name, and value. The row also contains a
|
||||||
|
type or mimetype. Type corresponds to a .NET class that support
|
||||||
|
text/value conversion through the TypeConverter architecture.
|
||||||
|
Classes that don't support this are serialized and stored with the
|
||||||
|
mimetype set.
|
||||||
|
|
||||||
|
The mimetype is used for serialized objects, and tells the
|
||||||
|
ResXResourceReader how to depersist the object. This is currently not
|
||||||
|
extensible. For a given mimetype the value must be set accordingly:
|
||||||
|
|
||||||
|
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||||
|
that the ResXResourceWriter will generate, however the reader can
|
||||||
|
read any of the formats listed below.
|
||||||
|
|
||||||
|
mimetype: application/x-microsoft.net.object.binary.base64
|
||||||
|
value : The object must be serialized with
|
||||||
|
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
|
||||||
|
: and then encoded with base64 encoding.
|
||||||
|
|
||||||
|
mimetype: application/x-microsoft.net.object.soap.base64
|
||||||
|
value : The object must be serialized with
|
||||||
|
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||||
|
: and then encoded with base64 encoding.
|
||||||
|
|
||||||
|
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||||
|
value : The object must be serialized into a byte array
|
||||||
|
: using a System.ComponentModel.TypeConverter
|
||||||
|
: and then encoded with base64 encoding.
|
||||||
|
-->
|
||||||
|
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||||
|
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
||||||
|
<xsd:element name="root" msdata:IsDataSet="true">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:choice maxOccurs="unbounded">
|
||||||
|
<xsd:element name="metadata">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:sequence>
|
||||||
|
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||||
|
</xsd:sequence>
|
||||||
|
<xsd:attribute name="name" use="required" type="xsd:string" />
|
||||||
|
<xsd:attribute name="type" type="xsd:string" />
|
||||||
|
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||||
|
<xsd:attribute ref="xml:space" />
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
<xsd:element name="assembly">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:attribute name="alias" type="xsd:string" />
|
||||||
|
<xsd:attribute name="name" type="xsd:string" />
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
<xsd:element name="data">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:sequence>
|
||||||
|
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||||
|
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||||
|
</xsd:sequence>
|
||||||
|
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
|
||||||
|
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||||
|
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||||
|
<xsd:attribute ref="xml:space" />
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
<xsd:element name="resheader">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:sequence>
|
||||||
|
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||||
|
</xsd:sequence>
|
||||||
|
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
</xsd:choice>
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
</xsd:schema>
|
||||||
|
<resheader name="resmimetype">
|
||||||
|
<value>text/microsoft-resx</value>
|
||||||
|
</resheader>
|
||||||
|
<resheader name="version">
|
||||||
|
<value>2.0</value>
|
||||||
|
</resheader>
|
||||||
|
<resheader name="reader">
|
||||||
|
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||||
|
</resheader>
|
||||||
|
<resheader name="writer">
|
||||||
|
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||||
|
</resheader>
|
||||||
|
</root>
|
||||||
67
Documentohelper.cs
Normal file
67
Documentohelper.cs
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
using System.Windows.Forms;
|
||||||
|
|
||||||
|
namespace UI
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Formata CPF ou CNPJ automaticamente enquanto o usuário digita.
|
||||||
|
/// Uso: DocumentoHelper.Registrar(txtDocumento);
|
||||||
|
/// </summary>
|
||||||
|
public static class DocumentoHelper
|
||||||
|
{
|
||||||
|
public static void Registrar(RoundTextBox txt)
|
||||||
|
{
|
||||||
|
bool formatando = false;
|
||||||
|
|
||||||
|
txt.TextChanged += (_, _) =>
|
||||||
|
{
|
||||||
|
// Evita loop: TextChanged → altera Text → TextChanged → ...
|
||||||
|
if (formatando) return;
|
||||||
|
formatando = true;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// 1. Extrai só os dígitos
|
||||||
|
string digits = new string(txt.Text.Where(char.IsDigit).ToArray());
|
||||||
|
|
||||||
|
// 2. Limita ao tamanho máximo do CNPJ
|
||||||
|
if (digits.Length > 14) digits = digits[..14];
|
||||||
|
|
||||||
|
// 3. Formata conforme o tamanho
|
||||||
|
string formatado = digits.Length <= 11
|
||||||
|
? FormatarCPF(digits)
|
||||||
|
: FormatarCNPJ(digits);
|
||||||
|
|
||||||
|
// 4. Só atualiza se realmente mudou
|
||||||
|
if (txt.Text != formatado)
|
||||||
|
{
|
||||||
|
txt.Text = formatado;
|
||||||
|
txt.SelectionStart = formatado.Length; // cursor no final
|
||||||
|
}
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
formatando = false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// CPF: 000.000.000-00
|
||||||
|
private static string FormatarCPF(string d) => d.Length switch
|
||||||
|
{
|
||||||
|
<= 3 => d,
|
||||||
|
<= 6 => $"{d[..3]}.{d[3..]}",
|
||||||
|
<= 9 => $"{d[..3]}.{d[3..6]}.{d[6..]}",
|
||||||
|
_ => $"{d[..3]}.{d[3..6]}.{d[6..9]}-{d[9..]}"
|
||||||
|
};
|
||||||
|
|
||||||
|
// CNPJ: 00.000.000/0000-00
|
||||||
|
private static string FormatarCNPJ(string d) => d.Length switch
|
||||||
|
{
|
||||||
|
<= 2 => d,
|
||||||
|
<= 5 => $"{d[..2]}.{d[2..]}",
|
||||||
|
<= 8 => $"{d[..2]}.{d[2..5]}.{d[5..]}",
|
||||||
|
<= 12 => $"{d[..2]}.{d[2..5]}.{d[5..8]}/{d[8..]}",
|
||||||
|
_ => $"{d[..2]}.{d[2..5]}.{d[5..8]}/{d[8..12]}-{d[12..]}"
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
20
Program.cs
Normal file
20
Program.cs
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
using CCH;
|
||||||
|
|
||||||
|
namespace UI
|
||||||
|
{
|
||||||
|
internal static class Program
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// The main entry point for the application.
|
||||||
|
/// </summary>
|
||||||
|
[STAThread]
|
||||||
|
static void Main()
|
||||||
|
{
|
||||||
|
// To customize application configuration such as set high DPI settings or default font,
|
||||||
|
// see https://aka.ms/applicationconfiguration.
|
||||||
|
ApplicationConfiguration.Initialize();
|
||||||
|
AppFolderSystem.CriarEstruturaPastas();
|
||||||
|
Application.Run(new Form1());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
125
RoundComboBox.cs
Normal file
125
RoundComboBox.cs
Normal file
@ -0,0 +1,125 @@
|
|||||||
|
using System.Drawing.Drawing2D;
|
||||||
|
|
||||||
|
namespace UI
|
||||||
|
{
|
||||||
|
public class RoundComboBox : UserControl
|
||||||
|
{
|
||||||
|
private ComboBox _comboBox = null!;
|
||||||
|
public int Radius { get; set; } = 4;
|
||||||
|
public Color BorderColor { get; set; } = Color.LightGray;
|
||||||
|
public Color FocusColor { get; set; } = Color.Blue;
|
||||||
|
private bool _focused;
|
||||||
|
|
||||||
|
public ComboBoxStyle DropDownStyle
|
||||||
|
{
|
||||||
|
get => _comboBox.DropDownStyle;
|
||||||
|
set => _comboBox.DropDownStyle = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ComboBox.ObjectCollection Items => _comboBox.Items;
|
||||||
|
|
||||||
|
public object? SelectedItem
|
||||||
|
{
|
||||||
|
get => _comboBox.SelectedItem;
|
||||||
|
set => _comboBox.SelectedItem = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int SelectedIndex
|
||||||
|
{
|
||||||
|
get => _comboBox.SelectedIndex;
|
||||||
|
set => _comboBox.SelectedIndex = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string Text
|
||||||
|
{
|
||||||
|
get => _comboBox.Text;
|
||||||
|
set => _comboBox.Text = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public new Color BackColor
|
||||||
|
{
|
||||||
|
get => base.BackColor;
|
||||||
|
set { base.BackColor = value; if (_comboBox != null) _comboBox.BackColor = value; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public new event EventHandler? SelectedIndexChanged
|
||||||
|
{
|
||||||
|
add => _comboBox.SelectedIndexChanged += value;
|
||||||
|
remove => _comboBox.SelectedIndexChanged -= value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public RoundComboBox()
|
||||||
|
{
|
||||||
|
DoubleBuffered = true;
|
||||||
|
base.BackColor = Color.White;
|
||||||
|
|
||||||
|
_comboBox = new ComboBox
|
||||||
|
{
|
||||||
|
//BorderStyle = BorderStyle.None,
|
||||||
|
Font = new Font("Segoe UI", 9f),
|
||||||
|
BackColor = Color.White,
|
||||||
|
DropDownStyle = ComboBoxStyle.DropDownList,
|
||||||
|
FlatStyle = FlatStyle.Flat
|
||||||
|
};
|
||||||
|
|
||||||
|
_comboBox.GotFocus += (s, e) => { _focused = true; Invalidate(); };
|
||||||
|
_comboBox.LostFocus += (s, e) => { _focused = false; Invalidate(); };
|
||||||
|
_comboBox.TextChanged += (s, e) => OnTextChanged(e);
|
||||||
|
_comboBox.Leave += (s, e) => OnLeave(e);
|
||||||
|
|
||||||
|
Controls.Add(_comboBox);
|
||||||
|
SizeChanged += (s, e) => AjustarComboBox();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void AjustarComboBox()
|
||||||
|
{
|
||||||
|
_comboBox.Width = Width - 12;
|
||||||
|
_comboBox.Location = new Point(6, (Height - _comboBox.PreferredHeight) / 2);
|
||||||
|
}
|
||||||
|
public object? DataSource
|
||||||
|
{
|
||||||
|
get => _comboBox.DataSource;
|
||||||
|
set => _comboBox.DataSource = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public string DisplayMember
|
||||||
|
{
|
||||||
|
get => _comboBox.DisplayMember;
|
||||||
|
set => _comboBox.DisplayMember = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public string ValueMember
|
||||||
|
{
|
||||||
|
get => _comboBox.ValueMember;
|
||||||
|
set => _comboBox.ValueMember = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public object? SelectedValue
|
||||||
|
{
|
||||||
|
get => _comboBox.SelectedValue;
|
||||||
|
set => _comboBox.SelectedValue = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void OnPaint(PaintEventArgs e)
|
||||||
|
{
|
||||||
|
e.Graphics.SmoothingMode = SmoothingMode.AntiAlias;
|
||||||
|
using var path = GetPath(new Rectangle(0, 0, Width - 1, Height - 1), Radius);
|
||||||
|
using var brush = new SolidBrush(BackColor);
|
||||||
|
e.Graphics.FillPath(brush, path);
|
||||||
|
using var pen = new Pen(_focused ? FocusColor : BorderColor, _focused ? 1.5f : 1f);
|
||||||
|
e.Graphics.DrawPath(pen, path);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static GraphicsPath GetPath(Rectangle r, int rad)
|
||||||
|
{
|
||||||
|
var path = new GraphicsPath();
|
||||||
|
int d = rad * 2;
|
||||||
|
path.AddArc(r.X, r.Y, d, d, 180, 90);
|
||||||
|
path.AddArc(r.Right - d, r.Y, d, d, 270, 90);
|
||||||
|
path.AddArc(r.Right - d, r.Bottom - d, d, d, 0, 90);
|
||||||
|
path.AddArc(r.X, r.Bottom - d, d, d, 90, 90);
|
||||||
|
path.CloseFigure();
|
||||||
|
return path;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
28
UI.csproj
Normal file
28
UI.csproj
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<OutputType>WinExe</OutputType>
|
||||||
|
<TargetFramework>net8.0-windows</TargetFramework>
|
||||||
|
<Nullable>enable</Nullable>
|
||||||
|
<UseWindowsForms>true</UseWindowsForms>
|
||||||
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\BLL\BLL.csproj" />
|
||||||
|
<ProjectReference Include="..\CAB\CAB.csproj" />
|
||||||
|
<ProjectReference Include="..\CCH\CCH.csproj" />
|
||||||
|
<ProjectReference Include="..\CMB\CMB.csproj" />
|
||||||
|
<ProjectReference Include="..\CPM\CPM.csproj" />
|
||||||
|
<ProjectReference Include="..\CPT\CPT.csproj" />
|
||||||
|
<ProjectReference Include="..\DAL\DAL.csproj" />
|
||||||
|
<ProjectReference Include="..\MLL\MLL.csproj" />
|
||||||
|
<ProjectReference Include="..\TLL\TLL.csproj" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="AForge.Video" Version="2.2.5" />
|
||||||
|
<PackageReference Include="AForge.Video.DirectShow" Version="2.2.5" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
||||||
79
UI.sln
Normal file
79
UI.sln
Normal file
@ -0,0 +1,79 @@
|
|||||||
|
|
||||||
|
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||||
|
# Visual Studio Version 18
|
||||||
|
VisualStudioVersion = 18.4.11626.88
|
||||||
|
MinimumVisualStudioVersion = 10.0.40219.1
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UI", "UI.csproj", "{344A1172-B978-A3CB-44BF-B15E6902C6C7}"
|
||||||
|
EndProject
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MLL", "..\MLL\MLL.csproj", "{BD112D2C-C31D-4DC4-A3C8-2C5808C17D53}"
|
||||||
|
EndProject
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CCH", "..\CCH\CCH.csproj", "{AD6AD8F1-7AE1-4BFC-A7EB-5F5B37EFE4C0}"
|
||||||
|
EndProject
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TLL", "..\TLL\TLL.csproj", "{A5F3E468-7A97-4C71-8E75-CD2CAF8B477C}"
|
||||||
|
EndProject
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CPT", "..\CPT\CPT.csproj", "{970FFDEE-6F66-49FD-B41F-EBC8F50C547C}"
|
||||||
|
EndProject
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DAL", "..\DAL\DAL.csproj", "{9696C45A-97A2-445E-BE10-BB3EE320BFDF}"
|
||||||
|
EndProject
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BLL", "..\BLL\BLL.csproj", "{68B73E29-9E25-4BCA-B077-400F6B2B450B}"
|
||||||
|
EndProject
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CPM", "..\CPM\CPM.csproj", "{20B46C82-119A-F5E9-8B57-A756A827F265}"
|
||||||
|
EndProject
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CAB", "..\CAB\CAB.csproj", "{19039AC1-EE08-460B-821B-0277442D04D1}"
|
||||||
|
EndProject
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CMB", "..\CMB\CMB.csproj", "{766E76F2-BAFF-4352-B376-15F6DE8BE4D9}"
|
||||||
|
EndProject
|
||||||
|
Global
|
||||||
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
|
Debug|Any CPU = Debug|Any CPU
|
||||||
|
Release|Any CPU = Release|Any CPU
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||||
|
{344A1172-B978-A3CB-44BF-B15E6902C6C7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{344A1172-B978-A3CB-44BF-B15E6902C6C7}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{344A1172-B978-A3CB-44BF-B15E6902C6C7}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{344A1172-B978-A3CB-44BF-B15E6902C6C7}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{BD112D2C-C31D-4DC4-A3C8-2C5808C17D53}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{BD112D2C-C31D-4DC4-A3C8-2C5808C17D53}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{BD112D2C-C31D-4DC4-A3C8-2C5808C17D53}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{BD112D2C-C31D-4DC4-A3C8-2C5808C17D53}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{AD6AD8F1-7AE1-4BFC-A7EB-5F5B37EFE4C0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{AD6AD8F1-7AE1-4BFC-A7EB-5F5B37EFE4C0}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{AD6AD8F1-7AE1-4BFC-A7EB-5F5B37EFE4C0}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{AD6AD8F1-7AE1-4BFC-A7EB-5F5B37EFE4C0}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{A5F3E468-7A97-4C71-8E75-CD2CAF8B477C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{A5F3E468-7A97-4C71-8E75-CD2CAF8B477C}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{A5F3E468-7A97-4C71-8E75-CD2CAF8B477C}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{A5F3E468-7A97-4C71-8E75-CD2CAF8B477C}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{970FFDEE-6F66-49FD-B41F-EBC8F50C547C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{970FFDEE-6F66-49FD-B41F-EBC8F50C547C}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{970FFDEE-6F66-49FD-B41F-EBC8F50C547C}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{970FFDEE-6F66-49FD-B41F-EBC8F50C547C}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{9696C45A-97A2-445E-BE10-BB3EE320BFDF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{9696C45A-97A2-445E-BE10-BB3EE320BFDF}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{9696C45A-97A2-445E-BE10-BB3EE320BFDF}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{9696C45A-97A2-445E-BE10-BB3EE320BFDF}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{68B73E29-9E25-4BCA-B077-400F6B2B450B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{68B73E29-9E25-4BCA-B077-400F6B2B450B}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{68B73E29-9E25-4BCA-B077-400F6B2B450B}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{68B73E29-9E25-4BCA-B077-400F6B2B450B}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{20B46C82-119A-F5E9-8B57-A756A827F265}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{20B46C82-119A-F5E9-8B57-A756A827F265}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{20B46C82-119A-F5E9-8B57-A756A827F265}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{20B46C82-119A-F5E9-8B57-A756A827F265}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{19039AC1-EE08-460B-821B-0277442D04D1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{19039AC1-EE08-460B-821B-0277442D04D1}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{19039AC1-EE08-460B-821B-0277442D04D1}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{19039AC1-EE08-460B-821B-0277442D04D1}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{766E76F2-BAFF-4352-B376-15F6DE8BE4D9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{766E76F2-BAFF-4352-B376-15F6DE8BE4D9}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{766E76F2-BAFF-4352-B376-15F6DE8BE4D9}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{766E76F2-BAFF-4352-B376-15F6DE8BE4D9}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
|
HideSolutionNode = FALSE
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||||
|
SolutionGuid = {15E7E724-DCEE-49C0-90C5-A55F1E2F06BD}
|
||||||
|
EndGlobalSection
|
||||||
|
EndGlobal
|
||||||
Loading…
Reference in New Issue
Block a user