20/07/2026 - DAL (ITENSLOTES) concluida.

This commit is contained in:
levelcode developed 2026-07-20 19:20:44 -03:00
parent a2268913b2
commit 92273602d4
3 changed files with 711 additions and 137 deletions

View File

@ -14,4 +14,8 @@
<ProjectReference Include="..\MLL\MLL.csproj" />
</ItemGroup>
<ItemGroup>
<Folder Include="Docs\" />
</ItemGroup>
</Project>

View File

@ -1388,75 +1388,72 @@ namespace DAL
public DataTable ListarTodos()
{
DataTable tabela = new DataTable();
DataTable tabela = new();
using SqlConnection conexao = new(connectionString);
using (SqlConnection conexao = new SqlConnection(DadosDaConexao.ObjetoStringConexao))
{
conexao.Open();
SqlDataAdapter da = new SqlDataAdapter(@"
SqlDataAdapter da = new(@"
SELECT *
FROM Itens_Lotes
ORDER BY COD_ITEM, DATA_VALIDADE", conexao);
da.Fill(tabela);
}
return tabela;
}//ListarTodos
public DataTable ListarPorProduto(string codItem)
public DataTable RelatorioPorProduto(string codItem)
{
DataTable tabela = new DataTable();
DataTable tabela = new();
using SqlConnection conexao = new(connectionString);
using (SqlConnection conexao = new SqlConnection(connectionString))
{
conexao.Open();
SqlDataAdapter da = new SqlDataAdapter(@"
SqlDataAdapter da = new(@"
SELECT *
FROM Itens_Lotes
WHERE COD_ITEM=@COD_ITEM
ORDER BY DATA_VALIDADE", conexao);
da.SelectCommand.Parameters.AddWithValue("@COD_ITEM", codItem);
da.SelectCommand.Parameters.AddWithValue(
"@COD_ITEM", codItem);
da.Fill(tabela);
}
return tabela;
}
public DataTable ListarPorFornecedor(string fornecedor)
}//RelatorioPorProduto
public DataTable RelatorioPorFornecedor(string fornecedor)
{
DataTable tabela = new DataTable();
DataTable tabela = new();
using SqlConnection conexao = new(connectionString);
using (SqlConnection conexao = new SqlConnection(DadosDaConexao.StringDeConexao))
{
conexao.Open();
SqlDataAdapter da = new SqlDataAdapter(@"
SqlDataAdapter da = new(@"
SELECT *
FROM Itens_Lotes
WHERE FORNECEDOR=@FORNECEDOR
ORDER BY COD_ITEM", conexao);
da.SelectCommand.Parameters.AddWithValue("@FORNECEDOR", fornecedor);
da.SelectCommand.Parameters.AddWithValue(
"@FORNECEDOR", fornecedor);
da.Fill(tabela);
}
return tabela;
}
public DataTable ListarVencidos()
}//RelatorioPorFornecedor
public DataTable RelatorioVencidos()
{
DataTable tabela = new DataTable();
DataTable tabela = new();
using SqlConnection conexao = new(connectionString);
using (SqlConnection conexao = new SqlConnection(DadosDaConexao.StringDeConexao))
{
conexao.Open();
SqlDataAdapter da = new SqlDataAdapter(@"
SqlDataAdapter da = new(@"
SELECT *
FROM Itens_Lotes
WHERE DATA_VALIDADE < GETDATE()
@ -1464,126 +1461,500 @@ namespace DAL
ORDER BY DATA_VALIDADE", conexao);
da.Fill(tabela);
}
return tabela;
}
public DataTable ListarAVencer(int dias)
}//RelatorioVencidos
public DataTable RelatorioAVencer(int dias)
{
DataTable tabela = new DataTable();
DataTable tabela = new();
using SqlConnection conexao = new(connectionString);
using (SqlConnection conexao = new SqlConnection(DadosDaConexao.StringDeConexao))
{
conexao.Open();
SqlDataAdapter da = new SqlDataAdapter(@"
SqlDataAdapter da = new(@"
SELECT *
FROM Itens_Lotes
WHERE DATA_VALIDADE BETWEEN GETDATE() AND DATEADD(DAY,@DIAS,GETDATE())
WHERE DATA_VALIDADE BETWEEN
GETDATE()
AND DATEADD(DAY,@DIAS,GETDATE())
AND ATIVO = 1
ORDER BY DATA_VALIDADE", conexao);
da.SelectCommand.Parameters.AddWithValue("@DIAS", dias);
da.SelectCommand.Parameters.AddWithValue(
"@DIAS", dias);
da.Fill(tabela);
}
return tabela;
}
public DataTable ListarSemValidade()
}//RelatorioAVencer
public DataTable RelatorioSemValidade()
{
DataTable tabela = new DataTable();
DataTable tabela = new();
using SqlConnection conexao = new(connectionString);
using (SqlConnection conexao = new SqlConnection(DadosDaConexao.StringDeConexao))
{
conexao.Open();
SqlDataAdapter da = new SqlDataAdapter(@"
SqlDataAdapter da = new(@"
SELECT *
FROM Itens_Lotes
WHERE DATA_VALIDADE IS NULL", conexao);
da.Fill(tabela);
}
return tabela;
}
public DataTable ListarEstoqueZero()
}//RelatorioSemValidade
public DataTable RelatorioEstoqueZero()
{
DataTable tabela = new DataTable();
DataTable tabela = new();
using SqlConnection conexao = new(connectionString);
using (SqlConnection conexao = new SqlConnection(DadosDaConexao.StringDeConexao))
{
conexao.Open();
SqlDataAdapter da = new SqlDataAdapter(@"
SqlDataAdapter da = new(@"
SELECT *
FROM Itens_Lotes
WHERE QUANTIDADE <= 0
ORDER BY COD_ITEM", conexao);
da.Fill(tabela);
}
return tabela;
}
public DataTable ListarAtivos()
}//RelatorioEstoqueZero
public DataTable RelatorioAtivos()
{
DataTable tabela = new DataTable();
DataTable tabela = new();
using SqlConnection conexao = new(connectionString);
using (SqlConnection conexao = new SqlConnection(DadosDaConexao.StringDeConexao))
{
conexao.Open();
SqlDataAdapter da = new SqlDataAdapter(@"
SqlDataAdapter da = new(@"
SELECT *
FROM Itens_Lotes
WHERE ATIVO = 1
ORDER BY COD_ITEM", conexao);
da.Fill(tabela);
}
return tabela;
}
public DataTable ListarInativos()
}//RelatorioAtivos
public DataTable RelatorioInativos()
{
DataTable tabela = new DataTable();
DataTable tabela = new();
using SqlConnection conexao = new(connectionString);
using (SqlConnection conexao = new SqlConnection(DadosDaConexao.StringDeConexao))
{
conexao.Open();
SqlDataAdapter da = new SqlDataAdapter(@"
SqlDataAdapter da = new(@"
SELECT *
FROM Itens_Lotes
WHERE ATIVO = 0
ORDER BY COD_ITEM", conexao);
da.Fill(tabela);
}
return tabela;
}//RelatorioInativos
public DataTable RelatorioComReserva()
{
DataTable tabela = new();
using SqlConnection conexao = new(connectionString);
conexao.Open();
SqlDataAdapter da = new(@"
SELECT *
FROM Itens_Lotes
WHERE QUANTIDADE_RESERVADA > 0
ORDER BY COD_ITEM", conexao);
da.Fill(tabela);
return tabela;
}//RelatorioComReserva
public DataTable RelatorioSemSaldo()
{
DataTable tabela = new();
using SqlConnection conexao = new(connectionString);
conexao.Open();
SqlDataAdapter da = new(@"
SELECT *
FROM Itens_Lotes
WHERE QUANTIDADE = 0
ORDER BY COD_ITEM", conexao);
da.Fill(tabela);
return tabela;
}//RelatorioSemSaldo
public DataTable RelatorioDisponiveis()
{
DataTable tabela = new();
using SqlConnection conexao = new(connectionString);
conexao.Open();
SqlDataAdapter da = new(@"
SELECT *
FROM Itens_Lotes
WHERE QUANTIDADE_DISPONIVEL > 0
ORDER BY COD_ITEM,
DATA_VALIDADE", conexao);
da.Fill(tabela);
return tabela;
}//RelatorioDisponiveis
#endregion
#region Integração - Integration
public bool AtualizarSaldoItem(string codigoItem)
{
decimal saldo = SaldoProduto(codigoItem);
using SqlConnection conn = new(connectionString);
string sql = @"
UPDATE Itens
SET ESTOQUE_DISP = @ESTOQUE
WHERE CODIGO = @CODIGO";
using SqlCommand cmd = new(sql, conn);
cmd.Parameters.AddWithValue("@ESTOQUE", saldo.ToString());
cmd.Parameters.AddWithValue("@CODIGO", codigoItem);
conn.Open();
return cmd.ExecuteNonQuery() > 0;
}//AtualizarSaldoItem
public bool AtualizarUltimaCompra(string codigoItem,DateTime dataCompra)
{
using SqlConnection conn = new(connectionString);
string sql = @"
UPDATE Itens
SET ULTIMA_COMPRA = @DATA
WHERE CODIGO = @CODIGO";
using SqlCommand cmd = new(sql, conn);
cmd.Parameters.AddWithValue(
"@DATA",
dataCompra.ToString("dd/MM/yyyy"));
cmd.Parameters.AddWithValue(
"@CODIGO",
codigoItem);
conn.Open();
return cmd.ExecuteNonQuery() > 0;
}//AtualizarUltimaCompra
public bool AtualizarFornecedorPrincipal(string codigoItem)
{
using SqlConnection conn = new(connectionString);
string sqlFornecedor = @"
SELECT TOP 1 FORNECEDOR
FROM Itens_Lotes
WHERE COD_ITEM=@COD_ITEM
GROUP BY FORNECEDOR
ORDER BY COUNT(*) DESC";
using SqlCommand cmd = new(sqlFornecedor, conn);
cmd.Parameters.AddWithValue(
"@COD_ITEM",
codigoItem);
conn.Open();
string fornecedor =
Convert.ToString(cmd.ExecuteScalar()) ??
string.Empty;
conn.Close();
sqlFornecedor = @"
UPDATE Itens
SET FORNECEDOR=@FORNECEDOR
WHERE CODIGO=@CODIGO";
cmd.CommandText = sqlFornecedor;
cmd.Parameters.Clear();
cmd.Parameters.AddWithValue(
"@FORNECEDOR",
fornecedor);
cmd.Parameters.AddWithValue(
"@CODIGO",
codigoItem);
conn.Open();
return cmd.ExecuteNonQuery() > 0;
}//AtualizarFornecedorPrincipal
public bool AtualizarValidadeProduto(string codigoItem)
{
DateTime? validade =
PrimeiroVencimento(codigoItem);
if (!validade.HasValue)
return false;
using SqlConnection conn = new(connectionString);
string sql = @"
UPDATE Itens
SET VALIDADE=@VALIDADE
WHERE CODIGO=@CODIGO";
using SqlCommand cmd = new(sql, conn);
cmd.Parameters.AddWithValue(
"@VALIDADE",
validade.Value.ToString("dd/MM/yyyy"));
cmd.Parameters.AddWithValue(
"@CODIGO",
codigoItem);
conn.Open();
return cmd.ExecuteNonQuery() > 0;
}//AtualizarValidadeProduto
public void RecalcularEstoqueProduto(string codigoItem)
{
AtualizarSaldoItem(codigoItem);
AtualizarFornecedorPrincipal(
codigoItem);
AtualizarValidadeProduto(
codigoItem);
}//RecalcularEstoqueProduto
#endregion
#region Inteligencia de Negócios - Business Intelligence
public ModeloItensLotes? MelhorLoteVenda(string codigoProduto)
{
// Hoje utiliza FEFO.
// Futuramente poderá ler da configuração da empresa.
return ObterFEFO(codigoProduto);
}//MelhorLoteVenda
public bool SugestaoReposicao(string codigoProduto)
{
decimal saldo = SaldoProduto(
codigoProduto);
using SqlConnection conn =
new(connectionString);
string sql = @"
SELECT ESTOQUE_MIN
FROM Itens
WHERE CODIGO=@CODIGO";
using SqlCommand cmd =
new(sql, conn);
cmd.Parameters.AddWithValue(
"@CODIGO",
codigoProduto);
conn.Open();
decimal minimo =
Convert.ToDecimal(
cmd.ExecuteScalar() ?? 0);
return saldo <= minimo;
}//SugestaoReposicao
public decimal CapitalParado()
{
using SqlConnection conn =
new(connectionString);
string sql = @"
SELECT ISNULL(
SUM(
TRY_CONVERT(decimal(18,2),
QUANTIDADE)
),0)
FROM Itens_Lotes
WHERE QUANTIDADE > 0";
using SqlCommand cmd =
new(sql, conn);
conn.Open();
return Convert.ToDecimal(
cmd.ExecuteScalar());
}//CapitalParado
public decimal CapitalVencido()
{
using SqlConnection conn =
new(connectionString);
string sql = @"
SELECT ISNULL(
SUM(QUANTIDADE),0)
FROM Itens_Lotes
WHERE DATA_VALIDADE <
GETDATE()";
using SqlCommand cmd =
new(sql, conn);
conn.Open();
return Convert.ToDecimal(
cmd.ExecuteScalar());
}//CapitalVencido
public decimal CapitalAVencer(int dias)
{
using SqlConnection conn =
new(connectionString);
string sql = @"
SELECT ISNULL(
SUM(QUANTIDADE),0)
FROM Itens_Lotes
WHERE DATA_VALIDADE
BETWEEN GETDATE()
AND DATEADD(
DAY,
@DIAS,
GETDATE())";
using SqlCommand cmd =
new(sql, conn);
cmd.Parameters.AddWithValue(
"@DIAS",
dias);
conn.Open();
return Convert.ToDecimal(
cmd.ExecuteScalar());
}//CapitalAVencer
public List<string> ProdutosCriticos()
{
List<string> lista = [];
using SqlConnection conn =
new(connectionString);
string sql = @"
SELECT DISTINCT COD_ITEM
FROM Itens_Lotes
WHERE DATA_VALIDADE <
DATEADD(
DAY,
15,
GETDATE())";
using SqlCommand cmd =
new(sql, conn);
conn.Open();
using SqlDataReader dr =
cmd.ExecuteReader();
while (dr.Read())
{
lista.Add(
dr["COD_ITEM"]
.ToString()!);
}
return lista;
}//ProdutosCriticos
public List<ModeloItensLotes>LotesPrioritarios()
{
return Listar(validadeFinal:DateTime.Today.AddDays(15));
}//LotesPrioritarios
public bool ExisteRiscoPerda(string codigoProduto)
{
return ExisteLoteAVencer(
codigoProduto,
15);
}//ExisteRiscoPerda
public decimal SugestaoCompra(string codigoProduto)
{
using SqlConnection conn =
new(connectionString);
string sql = @"
SELECT ESTOQUE_IDEAL
FROM Itens
WHERE CODIGO=@CODIGO";
using SqlCommand cmd =
new(sql, conn);
cmd.Parameters.AddWithValue(
"@CODIGO",
codigoProduto);
conn.Open();
decimal ideal =
Convert.ToDecimal(
cmd.ExecuteScalar() ?? 0);
decimal atual =
SaldoProduto(
codigoProduto);
if (ideal <= atual)
return 0;
return ideal - atual;
}//SugestaoCompra
public bool PossuiLotes(string codigoProduto)
{
using SqlConnection conn =
new(connectionString);
string sql = @"
SELECT COUNT(*)
FROM Itens_Lotes
WHERE COD_ITEM=@COD_ITEM";
using SqlCommand cmd =
new(sql, conn);
cmd.Parameters.AddWithValue(
"@COD_ITEM",
codigoProduto);
conn.Open();
return Convert.ToInt32(
cmd.ExecuteScalar()) > 0;
}//PossuiLotes
#endregion
//Concluida em 2026-07-20
//Versão 1.0.2
//Parte 8.1 -> Concluida
//Parte 8.2 -> Concluida
//Parte 8.3 -> Concluida
//Parte 8.4 -> Concluida
//Parte 8.5 -> Concluida
//Parte 8.6 -> Concluida
//Parte 8.7 -> Concluida
//Parte 8.8
//Parte 8.9
//Parte 8.10
}
}

View File

@ -0,0 +1,199 @@
//Parte 8.1 -> Concluída
// CRUD (Create, Read, Update e Delete)
//
// Responsável pelas operações básicas da tabela Itens_Lotes.
// Implementa inserção, alteração, exclusão, carregamento,
// verificação de existência e preenchimento do modelo.
//
// Métodos:
// - Inserir()
// - Alterar()
// - Excluir()
// - Carregar()
// - CarregarPorCodigo()
// - CarregarPorLote()
// - ExisteCodigo()
// - ExisteLote()
// - PreencherModelo()
// - PreencherParametros()
//Parte 8.2 -> Concluída
// Pesquisas e Filtros
//
// Responsável pelas consultas avançadas do módulo,
// permitindo localizar lotes por diversos critérios.
//
// Métodos:
// - Listar()
// - ListarPorProduto()
// - ListarPorFornecedor()
// - ListarPorNF()
// - ListarPorLote()
// - ListarAtivos()
// - ListarInativos()
// - ListarVencidos()
// - ListarAVencer()
// - ListarPorPeriodoValidade()
// - ListarPorPeriodoFabricacao()
//Parte 8.3 -> Concluída
// Controle de Estoque
//
// Responsável pelas movimentações de estoque dos lotes,
// incluindo entradas, saídas, transferências e ajustes.
//
// Métodos:
// - Entrada()
// - Saida()
// - SomarQuantidade()
// - BaixarQuantidade()
// - AjustarQuantidade()
// - TransferirQuantidade()
// - SaldoLote()
// - SaldoProduto()
// - ExisteSaldo()
// - ZerarLote()
//Parte 8.4 -> Concluída
// Controle de Validade
//
// Responsável pela gestão das datas de validade dos lotes,
// identificação de produtos vencidos e monitoramento de risco.
//
// Métodos:
// - LotesVencidos()
// - LotesAVencer()
// - LotesValidos()
// - LotesSemValidade()
// - DiasParaVencer()
// - DiasVencido()
// - PrimeiroVencimento()
// - UltimoVencimento()
// - ExisteLoteVencido()
// - ExisteLoteAVencer()
// - QuantidadeVencida()
// - QuantidadeAVencer()
// - QuantidadeValida()
//Parte 8.5 -> Concluída
// FEFO / FIFO
//
// Responsável pela seleção automática do melhor lote para
// venda e reserva de estoque.
//
// Métodos:
// - ObterFEFO()
// - ObterFIFO()
// - ReservarLote()
// - LiberarLote()
// - ConsumirReserva()
// - MelhorLote()
// - QuantidadeDisponivel()
// - QuantidadeReservada()
// - PodeAtenderVenda()
//Parte 8.6 -> Concluída
// Dashboard
//
// Responsável pelos indicadores e métricas utilizadas em
// dashboards, telas gerenciais e painéis do sistema.
//
// Indicadores:
// - QuantidadeLotes()
// - QuantidadeProdutos()
// - QuantidadeLotesAtivos()
// - QuantidadeLotesInativos()
// - QuantidadeVencidos()
// - QuantidadeAVencer()
// - QuantidadeSemValidade()
// - QuantidadeTotalEstoque()
// - QuantidadeDisponivelEstoque()
// - QuantidadeReservadaEstoque()
// - MaiorQuantidade()
// - MenorQuantidade()
// - QuantidadeMedia()
// - PercentualReservado()
// - PercentualDisponivel()
//Parte 8.7 -> Concluída
// Estatísticas
//
// Responsável pela geração de estatísticas avançadas para
// análise de comportamento dos lotes.
//
// Estatísticas:
// - ProdutoComMaisLotes()
// - ProdutoComMenosLotes()
// - FornecedorComMaisLotes()
// - FornecedorComMenosLotes()
// - MediaQuantidadeLote()
// - MediaDiasValidade()
// - ProdutosSemLote()
// - LotesSemMovimento()
// - LotesComEstoqueZero()
// - LotesComEstoquePositivo()
// - QuantidadeMediaPorProduto()
// - QuantidadeProdutosComMaisDeUmLote()
//Parte 8.8 -> Concluída
// Relatórios
//
// Responsável pela geração de DataTables para impressão,
// exportação e visualização em grids.
//
// Relatórios:
// - ListarTodos()
// - RelatorioPorProduto()
// - RelatorioPorFornecedor()
// - RelatorioVencidos()
// - RelatorioAVencer()
// - RelatorioSemValidade()
// - RelatorioEstoqueZero()
// - RelatorioAtivos()
// - RelatorioInativos()
// - RelatorioComReserva()
// - RelatorioSemSaldo()
// - RelatorioDisponiveis()
//Parte 8.9 -> Concluída
// Integração
//
// Responsável pela sincronização do módulo de lotes com
// os demais módulos do ERP.
//
// Integrações:
// - AtualizarSaldoItem()
// - AtualizarUltimaCompra()
// - AtualizarFornecedorPrincipal()
// - AtualizarValidadeProduto()
// - RecalcularEstoqueProduto()
//
// Módulos Integrados:
// - Itens
// - Compras
// - Vendas
// - Estoque
// - Movimentações
//Parte 8.10 -> Concluída
// Inteligência
//
// Responsável pela camada de inteligência do módulo,
// oferecendo sugestões, análises e automações.
//
// Recursos:
// - MelhorLoteVenda()
// - SugestaoReposicao()
// - CapitalParado()
// - CapitalVencido()
// - CapitalAVencer()
// - ProdutosCriticos()
// - LotesPrioritarios()
// - ExisteRiscoPerda()
// - SugestaoCompra()
// - PossuiLotes()
//
// Esta camada utiliza todas as demais partes da DAL para
// fornecer recursos avançados de tomada de decisão,
// tornando o módulo Itens_Lotes comparável aos controles
// de rastreabilidade presentes em ERPs de médio e grande porte.