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