Novo git da alteração

This commit is contained in:
2026-03-01 17:27:48 -03:00
parent 8b7a079235
commit 9ec8d6e70b
366 changed files with 50299 additions and 27325 deletions
Binary file not shown.
@@ -0,0 +1,729 @@
<!DOCTYPE html>
<html lang="pt-BR">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>Solicitação de compra</title>
<!-- CSS -->
<link rel="stylesheet" type="text/css" href="/style-guide/css/fluig-style-guide.min.css">
<link rel="stylesheet" type="text/css" href="comprasV2.css">
<link rel="stylesheet" type="text/css" href="style.css">
<!-- JS -->
<script src="/resources/js/jquery/jquery.js"></script>
<script src="/resources/js/jquery/jquery-ui.min.js"></script>
<script src="/resources/js/mustache/mustache-min.js"></script>
<script src="/style-guide/js/fluig-style-guide.min.js"></script>
<script type="text/javascript" src="/webdesk/vcXMLRPC.js"></script>
<script type="text/javascript" src="compras_digital.js"></script>
<script type="text/javascript" src="anexos.js"></script>
<style>
/* Ajuste de altura e alinhamento dos botões com inputs */
.input-group .form-control,
.input-group .btn {
height: 34px;
line-height: 1.42857143;
box-sizing: border-box;
}
.input-group .btn {
padding-top: 6px;
padding-bottom: 6px;
}
h6 { color: #AFB0B3 !important; font-weight: normal !important; }
h2 {
color: #04506b !important;
display: flex !important;
flex-direction: row !important;
align-items: center;
gap: .5rem;
}
h2:after {
content: "" !important;
flex: 1 1 auto !important;
border-bottom: 2px solid #04506b !important;
margin-left: .5rem !important;
}
.flaticon { color: #04506b !important; }
#rcorners {
height: 110px;
line-height: 110px;
color: #fff;
border-radius: 0 0 50px 50px;
background: linear-gradient(90deg, rgba(4,80,107,1) 0%, rgba(4,80,107,1) 50%, rgba(4,80,107,1) 100%);
text-align: center !important;
margin-bottom: 24px;
}
.change-weight { font-weight: 400 !important; }
</style>
</head>
<body>
<div class="fluig-style-guide" style="background-color:white;">
<h1 id="rcorners" style="margin:0;">Solicitação de compra</h1>
<ul id="wizard-steps" class="steps m-t-20">
<li class="step-item"><span class="step-bullet"></span><span class="step-label">Solicitação</span></li>
<li class="step-item"><span class="step-bullet"></span><span class="step-label">Validando necessidade</span></li>
<li class="step-item"><span class="step-bullet"></span><span class="step-label">Solicitando...</span></li>
<li class="step-item"><span class="step-bullet"></span><span class="step-label">Dados Adicionais</span></li>
<li class="step-item"><span class="step-bullet"></span><span class="step-label">Indicar Cotação</span></li>
<li class="step-item"><span class="step-bullet"></span><span class="step-label">Confirmação Cotação</span></li>
<li class="step-item"><span class="step-bullet"></span><span class="step-label">Aprovação Ccusto</span></li>
<li class="step-item"><span class="step-bullet"></span><span class="step-label">Aprovação GERF</span></li>
<li class="step-item"><span class="step-bullet"></span><span class="step-label">Aprovação CEO</span></li>
<li class="step-item"><span class="step-bullet"></span><span class="step-label">Receber Produto</span></li>
<li class="step-item"><span class="step-bullet"></span><span class="step-label">Problema</span></li>
<li class="step-item"><span class="step-bullet"></span><span class="step-label">Fim</span></li>
</ul>
<form name="form" role="form">
<!-- Campos ocultos -->
<input type="hidden" id="WKNumProces" name="WKNumProces">
<input type="hidden" id="activity" name="activity">
<input type="hidden" id="formMode" name="formMode">
<input type="hidden" id="empresa" name="empresa">
<input type="hidden" id="requesterMail" name="requesterMail">
<input type="hidden" id="requesterId" name="requesterId">
<input type="hidden" id="currentUserName" name="currentUserName">
<input type="hidden" id="currentUsermail" name="currentUsermail">
<input type="hidden" id="currentUserId" name="currentUserId">
<input type="hidden" id="moreInfo" name="moreInfo">
<input type="hidden" id="gestor_cc" name="gestor_cc">
<input type="hidden" id="filialest" name="filialest">
<input type="hidden" id="filialdest" name="filialdest">
<input type="hidden" id="filialprotheus" name="filialprotheus">
<input type="hidden" id="codigocentroCusto" name="codigocentroCusto">
<input type="hidden" name="numeroSCProtheus" id="numeroSCProtheus">
<input type="hidden" name="statusSCProtheus" id="statusSCProtheus">
<input type="hidden" name="solicitanteSCProtheus" id="solicitanteSCProtheus">
<input type="hidden" name="emissaoSCProtheus" id="emissaoSCProtheus">
<input type="hidden" name="qtdItensSCProtheus" id="qtdItensSCProtheus">
<input type="hidden" name="dataCadastroSCProtheus" id="dataCadastroSCProtheus">
<input type="hidden" name="horaCadastroSCProtheus" id="horaCadastroSCProtheus">
<input type="hidden" name="cotacaoSCProtheus" id="cotacaoSCProtheus">
<input type="hidden" name="pedidoSCProtheus" id="pedidoSCProtheus">
<input type="hidden" name="statusAtendimento" id="statusAtendimento">
<div class="container activity-all">
<!-- ACTIVITY 0 / 1 - Dados da solicitação -->
<div class="activity activity-0 activity-1">
<div class="row">
<div class="col-md-12">
<h2><i class="flaticon flaticon-tests-central icon-md" aria-hidden="true"></i>Dados da solicitação</h2>
<button type="button" class="btn btn-info btn-sm" id="btnHistorico"
style="background-color:#04506b; border-color:#04506b;">
<i class="fluigicon fluigicon-eye-open"></i> Ver Histórico
</button>
<h6>Dados referentes aos responsáveis pela abertura e pela solicitação do atual processo.</h6>
</div>
</div>
<!-- Linha 1 -->
<div class="row">
<div class="form-field">
<div class="form-input">
<div class="form-group col-md-2 col-xs-12">
<label>Tipo de Solicitação</label>
<select name="tipoSolicitacao" id="tipoSolicitacao" class="form-control" required>
<option value="">Selecione</option>
<option>Material</option>
<option>Serviço</option>
</select>
</div>
<div class="form-group col-md-3 col-xs-12">
<label>Usuário solicitante</label>
<input type="text" name="usuarioSolicitante" id="usuarioSolicitante" class="form-control"
placeholder="Inserir nome completo do solicitante. Ex: João da Silva"
data-protection="Usuário solicitante" data-protection-anonymizable data-protection-sensitive
data-protection-name data-protection-class-legitimate-interests="Dado coletado para o funcionamento do processo" />
</div>
<div class="form-group col-md-3 col-xs-12">
<label>E-mail do solicitante</label>
<input type="email" name="emailSolicitante" id="emailSolicitante" class="form-control"
placeholder="Inserir e-mail do solicitante. Ex: joaodasilva@mail.com"
data-protection="E-mail do solicitante" data-protection-anonymizable data-protection-sensitive
data-protection-mail data-protection-class-legitimate-interests="Dado coletado para o funcionamento do processo" />
</div>
<div class="form-group col-md-4 col-xs-12 divEstabelecimentoFilial alertaCampo">
<label for="zoom">Estabelecimento/Filial <span class="required text-danger"><strong>*</strong></span></label>
<input type="zoom" class="form-control" name="estabelecimento" id="estabelecimento" data-zoom="{
'displayKey':'LOJA',
'placeholder': 'Buscar nome do estabelecimento ou filial',
'datasetId':'dsSysCompan',
'fields':[
{'field':'LOJA','label':'Filial','standard':'true','search':'true'},
{'field':'CNPJ','label':'CNPJ','standard':'true'},
{'field':'ESTADO','label':'ESTADO','standard':'true'}
]
}">
<p class="help-block" id="estabelecimentoFilial" style="display:none;position:absolute;font-size:12px;">
Preenchimento obrigatório
</p>
</div>
<div class="form-group col-md-3 col-xs-12 divCentroCusto alertaCampo">
<label for="zoom">Centro de custo <span class="required text-danger"><strong>*</strong></span></label>
<input type="zoom" class="form-control" name="centro_custo" id="centro_custo" data-zoom="{
'displayKey':'centroCusto',
'placeholder': 'Buscar número ou nome do centro de custo',
'datasetId':'ds_centroCusto',
'fields':[
{'field':'codigoCentroCusto','label':'Código','standard':'true','search':'true'},
{'field':'centroCusto','label':'Nome','search':'true'},
{'field':'gestorCentroCusto','label':'gestorCentroCusto','visible':'false'},
{'field':'idGestor','label':'idGestor','visible':'false'},
{'field':'emailGestor','label':'emailGestor','visible':'false'}
]
}">
<p class="help-block" id="centroCusto" style="display:none;position:absolute;font-size:12px;">
Preenchimento obrigatório
</p>
</div>
<div class="form-group col-md-2 col-xs-12">
<label>Urgência</label>
<select name="urgencia" id="urgencia" class="form-control">
<option value="">Selecione</option>
<option>Normal</option>
<option>Urgente</option>
<option>Emergencial</option>
</select>
</div>
</div>
</div>
</div>
<!-- Linha 3 -->
<div class="row">
<div class="form-field">
<div class="form-input">
<div class="form-group col-md-4 col-xs-12">
<label for="descProduto">Produto/serviço</label>
<div class="input-group">
<input type="hidden" name="produtoCod" id="produtoCod">
<input type="text" name="descProduto" id="descProduto" class="form-control" placeholder="Buscar..." readonly>
<div class="input-group-btn">
<button class="btn btn-info" type="button" id="btnBuscaProd">
<span class="fluigicon fluigicon-search"></span>
</button>
<button class="btn btn-danger" type="button" id="btnLimpaProd">
<span class="fluigicon fluigicon-trash"></span>
</button>
</div>
</div>
</div>
<div class="form-group col-md-2 col-xs-12">
<label>Quantidade </label>
<div class="input-group">
<span class="input-group-btn"><button type="button" class="btn btn-danger" id="qtdMenos"></button></span>
<input type="number" min="0" step="1" name="quantidade" id="quantidade" class="form-control text-center" value="0" required>
<span class="input-group-btn"><button type="button" class="btn btn-success" id="qtdMais">+</button></span>
</div>
</div>
</div>
</div>
</div>
<!-- Botão adicionar item (oculto) -->
<div class="row">
<div class="form-field">
<div class="form-input">
<div class="form-group col-md-8 col-xs-12 text-center">
<button type="button" id="btnAddItem" class="btn btn-primary" style="display:none;">
<span class="fluigicon fluigicon-add"></span> Adicionar Item
</button>
</div>
</div>
</div>
</div>
<!-- Painel Itens -->
<div class="panel panel-default">
<div class="panel-heading"><strong>Itens</strong></div>
<div class="panel-body">
<table id="tbItens" tablename="tbItens" class="table table-bordered" noaddbutton="true" nodeletebutton="true">
<thead>
<tr>
<th>#</th>
<th>Código</th>
<th>Descrição</th>
<th>Qtd</th>
<th>Data Limite</th>
<th>*</th>
</tr>
</thead>
<tbody>
<!-- Linha modelo -->
<tr class="tableRow" detail="true">
<td><span class="tableIndex"></span></td>
<td><input type="text" name="Codproduto" class="form-control" readonly></td>
<td><input type="text" name="produtoDesc" class="form-control" readonly></td>
<td><input type="number" name="qtd" class="form-control text-right" min="0" step="1"></td>
<td><input type="date" name="dataNec" class="form-control" placeholder="dd/mm/aa"></td>
<td class="text-center">
<div class="btn-group">
<button type="button" class="btn btn-link" onclick="fnWdkRemoveChild(this)">
<span class="fluigicon fluigicon-trash"></span>
</button>
<button type="button" class="btn btn-link" onclick="handleProductLink(this)" data-link="">
<span class="fluigicon fluigicon-link"></span>
</button>
</div>
<!-- campo hidden que o Fluig vai gravar -->
<input type="hidden" name="produtoLink" class="produto-link">
</td>
</tr>
</tbody>
</table>
</div>
</div>
<!-- Linha 5 - Anexo + Observações -->
<div class="row">
<div class="form-field">
<div class="form-input">
<div class="form-group col-md-3 col-xs-12">
<label>Adicionar Anexo?</label>
<div class="componentAnexo">
<div class="input-group input-group-sm">
<input type="hidden" class="descAnexo" name="fdComprovante" value="Anexo" />
<input type="text" id="fnComprovante" name="fnComprovante" class="form-control inputAnexo input-sm" placeholder="Selecione um arquivo" readonly />
<span class="input-group-btn">
<button type="button" class="btnUpFile btn btn-success btn-sm" data-acao="upload" onclick="anexo(event)" title="Selecionar">
<i class="fluigicon fluigicon-file-upload icon-sm"></i>
</button>
<button style="display:none;" type="button" class="btnViewerFile btn btn-info btn-sm" data-acao="viewer" onclick="anexo(event)" title="Visualizar" disabled>
<i class="fluigicon fluigicon-eye-open icon-sm"></i>
</button>
<button style="display:none;" type="button" class="btnDownloadFile btn btn-info btn-sm" data-acao="download" onclick="anexo(event)" title="Download" disabled>
<i class="fluigicon fluigicon-download icon-sm"></i>
</button>
</span>
</div>
</div>
</div>
<div class="form-group col-md-8 col-xs-12">
<label>Motivo da compra<span class="required text-danger"><strong>*</strong></span></label>
<textarea class="form-control" rows="3" id="observacoes" name="observacoes"
placeholder="Descreva aqui alguma informação adicional que julgar importante."></textarea>
</div>
</div>
</div>
</div>
</div><!-- /activity-0/1 -->
<!-- ACTIVITY 4 - Análise da necessidade -->
<div class="activity activity-121">
<div class="row">
<div class="col-md-12">
<h2><i class="flaticon flaticon-check-circle" aria-hidden="true"></i>Análise da Necessidade</h2>
<h6>Informações complementares sobre a análise da solicitação pelo gestor responsável</h6>
</div>
</div>
<div class="row">
<div class="form-field">
<div class="form-input">
<div class="form-group col-md-6 col-xs-12">
<label>Responsável por aprovar a solicitação</label>
<input type="text" name="user_validacao_gestor" id="user_validacao_gestor" class="form-control" readonly
data-protection="Responsável por lançamento de documentos" data-protection-anonymizable
data-protection-sensitive data-protection-name
data-protection-class-legitimate-interests="Dado coletado para o funcionamento do processo" />
</div>
<div class="form-group col-md-3 col-xs-12">
<label>Data</label>
<input type="text" name="data_validacao_gestor" id="data_validacao_gestor" class="form-control" readonly />
</div>
</div>
</div>
</div>
<div class="row">
<div class="form-field">
<div class="form-input">
<div class="form-group col-md-12 divJustiDecisaoGestor alertaCampo">
<label for="justi_decisao_gestor">Justificativa</label>
<textarea class="form-control" name="justi_decisao_gestor" id="justi_decisao_gestor"></textarea>
<p class="help-block" id="justiDecisaoGestor" style="display:none;">Preenchimento obrigatório</p>
</div>
</div>
</div>
</div>
</div><!-- /activity-4 -->
<!-- DADOS DO DOCUMENTO -->
<div class="activity activity-114">
<div class="row">
<div class="col-md-12">
<h2><i class="flaticon flaticon-totvs-forms icon-md" aria-hidden="true"></i>Dados da Solicitação</h2>
<h6>Dados referentes a solicitação.</h6>
</div>
</div>
<div class="card" style="margin-top:15px; border-radius:8px; box-shadow:0 2px 5px rgba(0,0,0,0.1);">
<div class="card-body" style="padding:15px; background-color:#f9f9f9;">
<div class="row">
<div class="col-md-4">
<p><strong>Número:</strong> <span id="numeroSCProtheus_label">-</span></p>
</div>
<div class="col-md-4">
<p><strong>Status:</strong> <span id="statusSCProtheus_label" class="badge bg-secondary">-</span></p>
</div>
<div class="col-md-4">
<p><strong>Solicitante:</strong> <span id="solicitanteSCProtheus_label">-</span></p>
</div>
<div class="col-md-4">
<p><strong>Emissão:</strong> <span id="emissaoSCProtheus_label">-</span></p>
</div>
<div class="col-md-4">
<p><strong>Qtd. Itens:</strong> <span id="qtdItensSCProtheus_label">-</span></p>
</div>
<div class="col-md-4">
<p><strong>Data da aprovação:</strong> <span id="dataCadastroSCProtheus_label">-</span> às <span id="horaCadastroSCProtheus_label">-</span></p>
</div>
<div class="col-md-4">
<p><strong>Status:</strong> <span id="statusSC_label" class="badge bg-secondary">-</span></p>
</div>
<div class="col-md-4">
<p><strong>Cotação:</strong> <span id="cotacaoSC_label">-</span></p>
</div>
<div class="col-md-4">
<p><strong>Pedido:</strong> <span id="pedidoSC_label">-</span></p>
</div>
</div>
</div>
</div>
</div>
<!-- CONSULTA COTAÇÃO -->
<div class="activity activity-105">
<div class="row">
<div class="panel panel-default">
<div class="panel-heading"><strong>Consulta Cotação</strong></div>
<!-- Campo hidden para guardar o total -->
<input type="hidden" name="valorTotalCotacao" id="valorTotalCotacao" value="0"/>
<!-- Tabela Pai-Filho -->
<table tablename="tbCotacao" id="tbCotacao" class="table table-bordered" noaddbutton="true" nodeletebutton="true">
<thead>
<tr>
<th>Item</th>
<th>Produto</th>
<th>Qtd</th>
<th>Preço</th>
<th>Total</th>
<th>Selecionar</th>
</tr>
</thead>
<tbody>
<!-- O Fluig precisa de uma linha “modelo” -->
<tr>
<td><input type="text" name="item" id="item" readonly></td>
<td><input type="text" name="produto" id="produto" readonly></td>
<td><input type="text" name="qtdc" id="qtdc" readonly></td>
<td><input type="text" name="preco" id="preco" readonly></td>
<td><input type="text" name="total" id="total" readonly></td>
<td><input type="checkbox" name="selecionado" id="selecionado" value="S"></td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
<!-- ACTIVITY 137- Aprovar cotação Compras -->
<div class="activity activity-137">
<div class="row">
<div class="col-md-12">
<h2><i class="flaticon flaticon-check-circle" aria-hidden="true"></i>Aprovar cotação</h2>
<h6>Análise da cotação</h6>
</div>
</div>
<div class="row">
<div class="form-field">
<div class="form-input">
<div class="form-group col-md-6 col-xs-12">
<label>Usuário responsável da Cotação</label>
<input type="text" name="user_validacao_aprova" id="user_validacao_aprova" class="form-control" readonly
data-protection="Responsável por aprovar de documentos" data-protection-anonymizable
data-protection-sensitive data-protection-name
data-protection-class-legitimate-interests="Dado coletado para o funcionamento do processo" />
</div>
<div class="form-group col-md-3 col-xs-12">
<label>Data</label>
<input type="text" name="data_validacao_aprova" id="data_validacao_aprova" class="form-control" readonly />
</div>
</div>
</div>
</div>
<div class="row">
<div class="form-field">
<div class="form-input">
<div class="form-group col-md-12 divJustiDecisaoGestor alertaCampo">
<label for="justi_decisao_aprova">Justificativa</label>
<textarea class="form-control" name="justi_decisao_aprova" id="justi_decisao_aprova"></textarea>
<p class="help-block" id="justiDecisaoGestor" style="display:none;">Preenchimento obrigatório</p>
</div>
</div>
</div>
</div>
</div>
<!-- ACTIVITY 133- Aprovar cotação Compras -->
<div class="activity activity-133">
<div class="row">
<div class="col-md-12">
<h2><i class="flaticon flaticon-check-circle" aria-hidden="true"></i>Aprovação do Gestor do C.Custo</h2>
<h6>Aprovação da cotação</h6>
</div>
</div>
<div class="row">
<div class="form-field">
<div class="form-input">
<div class="form-group col-md-6 col-xs-12">
<label>Gestor responsável da Cotação</label>
<input type="text" name="gestor_validacao_aprova" id="gestor_validacao_aprova" class="form-control" readonly
data-protection="Responsável por aprovar de documentos" data-protection-anonymizable
data-protection-sensitive data-protection-name
data-protection-class-legitimate-interests="Dado coletado para o funcionamento do processo" />
</div>
<div class="form-group col-md-3 col-xs-12">
<label>Data</label>
<input type="text" name="data_validacao_aprova_gestor" id="data_validacao_aprova_gestor" class="form-control" readonly />
</div>
</div>
</div>
</div>
<div class="row">
<div class="form-field">
<div class="form-input">
<div class="form-group col-md-12 divJustiDecisaoGestor alertaCampo">
<label for="justi_decisao_aprova_gestor">Justificativa</label>
<textarea class="form-control" name="justi_decisao_aprova_gestor" id="justi_decisao_aprova_gestor"></textarea>
<p class="help-block" id="justi_decisao_aprova_gestor" style="display:none;">Preenchimento obrigatório</p>
</div>
<div class="form-group col-md-8 col-xs-12">
<label>Jusiticativa do solicitante <span class="required text-danger"><strong>*</strong></span></label>
<textarea class="form-control" rows="3" id="observacoesdosolicitante" name="observacoesdosolicitante" readonly
placeholder="Descreva aqui alguma informação adicional que julgar importante."></textarea>
</div>
</div>
</div>
</div>
</div><!-- /activity-131 -->
<!-- ACTIVITY 147- Aprovar cotação Compras -->
<div class="activity activity-147">
<div class="row">
<div class="col-md-12">
<h2><i class="flaticon flaticon-check-circle" aria-hidden="true"></i>Aprovação do Gerente Financeiro</h2>
<h6>Aprovação do Gerente Financeiro</h6>
</div>
</div>
<div class="row">
<div class="form-field">
<div class="form-input">
<div class="form-group col-md-6 col-xs-12">
<label>Ger. Financeiro responsável pela Aprovação</label>
<input type="text" name="gerf_validacao_aprova" id="gerf_validacao_aprova" class="form-control" readonly
data-protection="Responsável por aprovar de documentos" data-protection-anonymizable
data-protection-sensitive data-protection-name
data-protection-class-legitimate-interests="Dado coletado para o funcionamento do processo" />
</div>
<div class="form-group col-md-3 col-xs-12">
<label>Data</label>
<input type="text" name="data_validacao_aprova_gerf" id="data_validacao_aprova_gerf" class="form-control" readonly />
</div>
</div>
</div>
</div>
<div class="row">
<div class="form-field">
<div class="form-input">
<div class="form-group col-md-12 divJustiDecisaoGestor alertaCampo">
<label for="justi_decisao_aprova_gerente">Justificativa</label>
<textarea class="form-control" name="justi_decisao_aprova_gerente" id="justi_decisao_aprova_gerente" readonly></textarea>
<p class="help-block" id="justi_decisao_aprova_gerente" style="display:none;">Preenchimento obrigatório</p>
</div>
<div class="form-group col-md-12 divJustiDecisaoGestor alertaCampo">
<label for="justi_decisao_gc">Justificativa do Gestor do Centro de Custo</label>
<textarea class="form-control" name="justi_decisao_gc" id="justi_decisao_gc"readonly></textarea>
</div>
<div class="form-group col-md-12 divJustiDecisaoGestor alertaCampo">
<label for="justi_decisao__soli">Justificativa do Solicitante</label>
<textarea class="form-control" name="justi_decisao__soli" id="justi_decisao__soli" readonly></textarea>
</div>
</div>
</div>
</div>
</div><!-- /activity-131 -->
<!-- ACTIVITY 137- Aprovar cotação Compras -->
<div class="activity activity-158">
<div class="row">
<div class="col-md-12">
<h2><i class="flaticon flaticon-check-circle" aria-hidden="true"></i>Aprovação CEO</h2>
<h6> Aprovação do CEO</h6>
</div>
</div>
<div class="row">
<div class="form-field">
<div class="form-input">
<div class="form-group col-md-6 col-xs-12">
<label>Usuário responsável</label>
<input type="text" name="ceo_validacao_aprova" id="ceo_validacao_aprova" class="form-control" readonly
data-protection="Responsável por aprovar de documentos" data-protection-anonymizable
data-protection-sensitive data-protection-name
data-protection-class-legitimate-interests="Dado coletado para o funcionamento do processo" />
</div>
<div class="form-group col-md-3 col-xs-12">
<label>Data</label>
<input type="text" name="data_validacao_aprova_ceo" id="data_validacao_aprova_ceo" class="form-control" readonly />
</div>
</div>
</div>
</div>
<div class="row">
<div class="form-field">
<div class="form-input">
<div class="form-group col-md-12 divJustiDecisaoGestor alertaCampo">
<label for="justi_decisao_aprova_ceo">Justificativa</label>
<textarea class="form-control" name="justi_decisao_aprova_ceo" id="justi_decisao_aprova_ceo" readonly></textarea>
<p class="help-block" id="justi_decisao_aprova_ceo" style="display:none;">Preenchimento obrigatório</p>
</div>
<div class="form-group col-md-12 divJustiDecisaoGestor alertaCampo">
<label for="justi_decisao_aprova_ceo">Justificativa do Gerente Financeiro</label>
<textarea class="form-control" name="justi_decisao_gerf" id="justi_decisao_gerf" readonly></textarea>
</div>
<div class="form-group col-md-12 divJustiDecisaoGestor alertaCampo">
<label for="justi_decisaogc">Justificativa do Gestor do Centro de custo</label>
<textarea class="form-control" name="justi_decisaogc" id="justi_decisaogc" readonly></textarea>
</div>
<div class="form-group col-md-12 divJustiDecisaoGestor alertaCampo">
<label for="justi_decisao_solic">Justificativa do Solicitante</label>
<textarea class="form-control" name="justi_decisao_solic" id="justi_decisao_solic" readonly></textarea>
</div>
</div>
</div>
</div>
</div><!-- /activity-131 -->
<div class="activity activity-18">
<div>
<br />
<h2>
<i class="flaticon flaticon-check-circle" aria-hidden="true"></i>
&nbsp;Validação do pedido e entrega dos itens &nbsp;
</h2>
<br />
</div>
<div class="row">
<!-- Botão para consultar agora -->
<div id="espelhoPedido" style="margin-top:15px;">
⏳ Aguardando geração do pedido...
</div>
</div>
<div class="row">
<div class="form-field">
<div class="form-input">
<div class="form-group col-md-10 col-xs-6">
<label for="userValidacaoItens"> Solicitante </label>
<input type="text" name="userValidacaoItens" id="userValidacaoItens" class="form-control"
data-protection="Solicitante" data-protection-anonymizable data-protection-sensitive
data-protection-name
data-protection-class-legitimate-interests="Dado coletado para o funcionamento do processo"
readonly />
</div>
<div class="form-group col-md-2 col-xs-6">
<label for="dataValidacaoItens"> Data </label>
<input type="text" name="dataValidacaoItens" id="dataValidacaoItens" class="form-control" readonly />
</div>
</div>
</div>
</div>
<div class="row">
<div class="form-field">
<div class="form-input">
<div class="form-group col-md-12">
<label>Houve algum problema com a compra?</label>
<span class="text-danger"><strong>*</strong></span><br />
<div>
<label>
<input name="validacaoItens" id="validacaoItensEntregue" value="entregue" type="radio" />
<span class="change-weight">Não houve problema</span>
</label>
</div>
<div>
<label>
<input name="validacaoItens" id="validacaoItensNaoEntregue" value="naoEntregue" type="radio" />
<span class="change-weight">Pedido não entregue</span>
</label>
</div>
<div>
<label>
<input name="validacaoItens" id="validacaoItensIncorreto" value="incorreto" type="radio" />
<span class="change-weight">Entregue com inconsistência (qualidade, quantidade,
embalagem)</span>
</label>
</div>
</div>
</div>
</div>
</div>
<div class="row justificativaDecisaoItens">
<div class="form-field">
<div class="form-input">
<div class="form-group col-md-12">
<label for="justificativaDecisaoItens">Justificativa</label>
<span class="text-danger"><strong>*</strong></span>
<textarea class="form-control requiredInput"
placeholder="Insira a justificativa sobre a validação dos itens" name="justificativaDecisaoItens"
id="justificativaDecisaoItens"></textarea>
<p class="text-danger text-error">
Preenchimento obrigatório.
</p>
</div>
</div>
</div>
</div>
</div>
<div class="activity activity-24">
<div>
<br />
<h2>
<i class="flaticon flaticon-document-check" aria-hidden="true"></i>
&nbsp;Validar problema: considerações de compras &nbsp;
</h2>
<h6>Dados referentes às possíveis implicações desta compra.</h6>
<br />
</div>
<div class="row">
<div class="form-group col-md-12">
<label for="justificativaValidaProblema">Quais as suas considerações?</label>
<span class="text-danger"><strong>*</strong></span>
<textarea placeholder="Insira as considerções desta compra." class="form-control"
name="justificativaValidaProblema" id="justificativaValidaProblema"></textarea>
<p class="text-danger text-error">
Preenchimento obrigatório.
</p>
</div>
</div>
</div><!-- /activity-18 -->
<br><br>
<h6>Todos os campos com * são de preenchimento obrigatório.</h6>
</div><!-- /container -->
</form>
</div>
</body>
</html>
@@ -0,0 +1,437 @@
/**
* Toda a lógica para o correto funcionamento desse componente foi feito em cima das classes abaixo:
* .componentAnexo, .descAnexo, .inputAnexo, .btnUpFile, .btnViewerFile, .btnDownloadFile e o atributo data-acao
* Sem elas o código não irá funcionar, então se por acaso você quiser alterar os nomes dessas classes
* lembre-se de alterar nas funções desse arquivo e também no css
*/
/**
* Direciona para cada função correspondente ao valor que esta no atributo data-acao do botão
* @param {object} event Parâmetro obrigatório, o própio elemento que sofreu o evento click
* @return {void}
* @author Sérgio Machado
*/
function anexo(event){
console.log("event")
console.log(event)
try{
const acao = event.currentTarget.getAttribute("data-acao");
const inputFile = $(event.currentTarget).parent().parent().find(".inputAnexo")[0]
const fileDescription = $(event.currentTarget).parent().parent().find(".descAnexo").val()
if(acao == "upload"){
uploadFile(fileDescription, inputFile.id)
}
if(acao == "viewer"){
viewerFile(fileDescription)
}
if(acao == "download"){
downloadFile(fileDescription, inputFile.id)
}
if(acao == "delete"){
removeFileConfirm(fileDescription, inputFile.id)
}
}catch(e){
console.error("Houve um erro inesperado na função anexo")
console.error(e)
}
}
/**
* Envia arquivos para a aba Anexos do Fluig
* Função adaptada por Sérgio Machado
* @param {String} fileDescription Parâmetro obrigatório, Descrição do arquivo que ficará na aba anexos do Fluig
* @param {String} idInput Parâmetro obrigatório, Id do campo em que o nome do arquivo fisico é gravado
* @return {void}
*/
function uploadFile(fileDescription, idInput) {
try{
var tabAttachments = parent.document.getElementById("tab-attachments");
if (tabAttachments) {
//Verifica se o navegador é o Ie9 para realizar o devido tratamento
if (parent.WCMAPI.isIe9()) {
$(".ecm-navigation-silverlight", parent.document).show("fade").css("top", 0);
$("#ecm-navigation-silverlight", parent.document).attr({
"data-on-camera": "true", "data-file-name-camera": fileDescription, "data-inputNameFile": idInput
});
$(parent.document).on("keyup", this.actionKeyup)
} else {
var element = parent.document.getElementById("ecm-navigation-inputFile-clone");
if (element && document.createEvent) {
element.setAttribute("data-on-camera", "true");
if (fileDescription && idInput) {
element.setAttribute("data-file-name-camera", fileDescription)
element.setAttribute("data-inputNameFile", idInput)
}
//Realiza o click no botão "Carregar arquivos" que tem na aba de anexos
element.click();
}
}
}
}catch(e){
console.error("Houve um erro inesperado na função uploadFile")
console.error(e)
}
}
/**
* Função executada após a escolha do arquivo a ser enviado para o Fluig.
* Verifica se o anexo já existe, seta o valor do arquivo fisico no campo e altera o estado dos botões
* @return {void}
*/
$(function(){
try{
window.parent.$("#ecm-navigation-inputFile-clone").on('change', function(e) {
const inputNameFile = this.getAttribute("data-inputNameFile");
const fileDescription = this.getAttribute("data-file-name-camera");
const filePhisical = this.files[0].name;
if(fileDescription && fileDescription){
/**
* O trecho de código abaixo percorre os anexos do Fluig e caso já exista um anexo com a mesma descrição, ele será removido.
* Em seguida limpa o campo onde é armazenado o nome fisico do arquivo
*/
$.each(parent.ECM.attachmentTable.getData(), function(i, attachment) {
var descricao = attachment.description;
if (fileDescription == descricao) {
parent.WKFViewAttachment.removeAttach([i]);
setFilePhisicalName(inputNameFile, "");
}
});
setFilePhisicalName(inputNameFile, filePhisical)
if(getFormMode() == "ADD"){
btnState(inputNameFile, 'delete', 'download');
}
if(getFormMode() == "MOD"){
btnState(inputNameFile, 'delete', 'viewer');
}
if(getFormMode() == "VIEW"){
btnState(inputNameFile, 'download', 'viewer');
}
}
});
}catch(e){
console.error("Houve um erro inesperado ao selecionar o arquivo")
console.error(e)
}
});
/**
* Visualizar arquivos que esta na aba Anexos do Fluig
* @param {String} fileDescription Parâmetro obrigatório, Descrição do anexo
* @return {void}
*/
function viewerFile(fileDescription) {
try{
if(hasFileFluig(fileDescription)){
const anexos = parent.ECM.attachmentTable.getData();
for(let i = 0; i < anexos.length; i++){
var descricao = anexos[i].description;
if (fileDescription == descricao) {
parent.WKFViewAttachment.openAttachmentView('adm', anexos[i].documentId);
return
}
}
}else{
FLUIGC.toast({
title: "Atenção",
message: "Anexo não encontrado",
type: "warning"
});
}
}catch(e){
console.error("Houve um erro inesperado na função viewerFile")
console.error(e)
}
}
/**
* Realiza o download do arquivo que esta na aba Anexos do Fluig
* @param {String} idInput Parâmetro obrigatório, Id do campo em que o nome do arquivo fisico é gravado
* @param {String} fileDescription Parâmetro obrigatório, Descrição do arquivo que esta na aba anexos do Fluig
* @return {void}
*/
function downloadFile(fileDescription, idInput) {
try{
const filename = getFormMode() == "VIEW" ? $(`#${idInput}`).text() : $(`#${idInput}`).val()
FLUIGC.message.confirm({
message: `Deseja baixar o anexo <b>${filename}</b>?`,
title: 'Confirmação',
labelYes: 'Sim, quero baixar',
labelNo: 'Não, quero cancelar',
}, function(result) {
if (result) {
$.each(parent.ECM.attachmentTable.getData(), function(i, attachment) {
var descricao = attachment.description;
if (fileDescription == descricao) {
parent.WKFViewAttachment.downloadAttach([i]);
}
});
}
});
}catch(e){
console.error("Houve um erro inesperado na função downloadFile")
console.error(e)
}
}
/**
* Confirmação para Remove arquivo que esta na aba Anexos do Fluig
* @param {String} idInput Parâmetro obrigatório, Id do campo em que o nome do arquivo fisico é gravado
* @param {String} fileDescription Parâmetro obrigatório, Descrição do arquivo que esta na aba anexos do Fluig
* @return {void}
* @author Sérgio Machado
*/
function removeFileConfirm(fileDescription, idInput) {
try{
const filename = $(`#${idInput}`).val()
FLUIGC.message.confirm({
message: `Deseja remover o anexo <b>${filename}</b>?`,
title: 'Confirmação',
labelYes: 'Sim, quero remover',
labelNo: 'Não, quero cancelar',
}, function(result) {
if (result) {
removeFile(fileDescription)
setFilePhisicalName(idInput, "")
btnState(idInput, "upload", "download")
}
});
}catch(e){
console.error("Houve um erro inesperado na função removeFileConfirm")
console.error(e)
}
}
/**
* Remove arquivo que esta na aba Anexos do Fluig
* @param {String} fileDescription Parâmetro obrigatório, Descrição do arquivo que esta na aba anexos do Fluig
* @return {void}
* @author Sérgio Machado
*/
function removeFile(fileDescription) {
try{
$.each(parent.ECM.attachmentTable.getData(), function(i, attachment) {
if (attachment.description == fileDescription) {
parent.WKFViewAttachment.removeAttach([i]);
}
});
}catch(e){
console.error("Houve um erro inesperado na função removeFile")
console.error(e)
}
}
/**
* Seta o nome do arquivo fisico no campo e realiza tratativa caso o campo esteja bloqueado pelo enableFields
* @param {String} idInput Parâmetro obrigatório, Id do campo em que o nome do arquivo fisico é gravado
* @param {String} filePhisical Parâmetro obrigatório, nome do arquivo fisico
* @return {void}
* @author Sérgio Machado
*/
function setFilePhisicalName(idInput, filePhisical){
try{
if(idInput.indexOf("_") == 0){
$("#" + idInput.substring(1)).val(filePhisical);
}
$("#" + idInput).val(filePhisical);
}catch(e){
console.error("Houve um erro inesperado na função setFilePhisicalName")
console.error(e)
}
}
/**
* Altera o estado e visibilidade dos botões de anexos
* @param {String} idInput Parâmetro obrigatório, Id do campo em que o nome do arquivo fisico é gravado
* @param {String} acao Parâmetro obrigatório, ação para ser executada no momento do click, se é delete ou upload
* @param {String} btn Parâmetro obrigatório, botão secundário que deve sofrer ação de ficar visível ou não. Botão de Download ou Viewer
* @return {void}
* @author Sérgio Machado
*/
function btnState(idInput, acao, btn){
try{
let btnUpFile = $(`#${idInput}`).parent().parent().find(".btnUpFile");
let btnDownloadFile = $(`#${idInput}`).parent().parent().find(".btnDownloadFile");
let btnViewerFile = $(`#${idInput}`).parent().parent().find(".btnViewerFile");
if(acao == "delete"){
btnUpFile.removeClass("btn-success").addClass("btn-danger");
btnUpFile.attr({'data-acao': acao, 'title': 'Excluir'});
btnUpFile.find("i").removeClass("fluigicon-file-upload").addClass("fluigicon-trash");
if(btn == "download"){
btnDownloadFile.prop("disabled", false);
btnDownloadFile.show()
}
if(btn == "viewer"){
btnViewerFile.prop("disabled", false);
btnViewerFile.show()
}
}
if(acao == "upload"){
btnUpFile.removeClass("btn-danger").addClass("btn-success");
btnUpFile.attr({'data-acao': acao, 'title': 'Selecionar'});
btnUpFile.find("i").removeClass("fluigicon-trash").addClass("fluigicon-file-upload");
btnDownloadFile.prop("disabled", true);
btnDownloadFile.hide()
btnViewerFile.prop("disabled", true);
btnViewerFile.hide()
}
}catch(e){
console.error("Houve um erro inesperado na função btnState")
console.error(e)
}
}
/**
* Faz tratativa nos botões do anexos percorrente cada class .componentAnexo
* Em modo de visualização o botão de upload é removido, e caso tenha anexo, habilita o botão de visualização do anexo
* Se em modo de edição e conter anexo o botão de upload é alterado para o botão de deletar anexos e habilita o botão de visualização
* @return {void}
* @author Sérgio Machado
*/
function displayBtnFiles(){
try{
$('.componentAnexo').each(function(i, element) {
let inputFile = $(element).find(".inputAnexo")
let inputFileVew = $(element).find(".componentAnexo")
let btnUpFile = $(element).find(".btnUpFile");
let btnViewerFile = $(element).find(".btnViewerFile");
let btnDownloadFile = $(element).find(".btnDownloadFile");
if(getFormMode() == "VIEW"){
btnUpFile.remove();
if(inputFileVew.val() != ""){
btnViewerFile.prop("disabled", false);
btnViewerFile.show()
}
}
if(getFormMode() == "MOD" && inputFile.val() != ""){
btnUpFile.remove();
// btnState(inputFile[0].id, "delete", "viewer")
btnViewerFile.prop("disabled", false);
btnViewerFile.show()
btnDownloadFile.prop("disabled", false);
btnDownloadFile.show()
}
});
}catch(e){
console.error("Houve um erro inesperado na função displayBtnFiles")
console.error(e)
}
}
/**
* Remove o botão de upload/delete
* @param {String} inputFile Parâmetro obrigatório, Id do campo
* @return {void}
* @author Sérgio Machado
*/
function invisibleBtnUpload(inputFile){
try{
if(getFormMode() == "MOD" || getFormMode() == "VIEW"){
if($(`#_${inputFile}`).length){
let btnUpFile = $(`#_${inputFile}`).parent().parent().find(".btnUpFile");
btnUpFile.remove();
} else{
let btnUpFile = $(`#${inputFile}`).parent().parent().find(".btnUpFile");
btnUpFile.remove();
}
}
if($(`#_${inputFile}`).length){
if($(`#_${inputFile}`).val() == ""){
$(`#_${inputFile}`).attr({placeholder:"Nenhum anexo selecionado"});
}
} else{
if($(`#${inputFile}`).val() == ""){
$(`#${inputFile}`).attr({placeholder:"Nenhum anexo selecionado"});
}
}
}catch(e){
console.error("Houve um erro inesperado na função invisibleBtnUpload")
console.error(e)
}
}
/**
* Verifica se os campos do anexo de uma tabela pai e filho esta preenchido,
* caso esteja, ele verifica se o anexo esta presente na aba de anexos do Fluig
* @param {String} tablename Parâmetro obrigatório, tablename da tabela pai e filho.
* @param {String} idInput Parâmetro obrigatório, Id do campo de anexo que deseja verificar
* @return {String} - Retorna string de erros caso apresente erros
* @author Sérgio Machado
*/
function invalidFilesTable(tablename, idInput){
try {
let errors = "";
const countRows = $(`[tablename='${tablename}']`).find('tbody tr').not(':first');
for(let i = 0; i < countRows.length; i++){
let indice = getIndice(countRows.eq(i).find("input")[0].id);
let inputNameFile = $(`#_${idInput}___${indice}`).length ? $(`#_${idInput}___${indice}`) : $(`#${idInput}___${indice}`)
let fileDescription = inputNameFile.parent().find(".descAnexo").val()
if(inputNameFile.val() && !hasFileFluig(fileDescription)){
errors += `<li style='margin-bottom: 5px;'>O anexo <b>${inputNameFile.val()}</b> da linha <b>${i+1}</b> não foi encontrado</li>`
}
}
return errors
} catch (e) {
console.error('Houve um erro inesperado na função invalidFileTable')
console.error(e)
}
}
/**
* Verifica se o campo do anexo esta preenchido, caso esteja, ele verifica se o anexo esta válido
* @param {String} idInput Parâmetro obrigatório, Id do campo em que o nome do arquivo fisico é gravado
* @return {Boolean}
* @author Sérgio Machado
*/
function invalidFile(idInput){
try {
const inputNameFile = $(`#${idInput}`).val()
if(inputNameFile){
if($(`#_${idInput}`).length){
let fileDescription = $(`#_${idInput}`).parent().find(".descAnexo").val()
return !hasFileFluig(fileDescription)
} else{
let fileDescription = $(`#${idInput}`).parent().find(".descAnexo").val()
return !hasFileFluig(fileDescription)
}
}else{
return false
}
} catch (e) {
console.error('Houve um erro inesperado na função invalidFile')
console.error(e)
}
}
/**
* Verifica se o anexo existe na aba de anexos do Fluig
* @param {String} fileDescription Parâmetro obrigatório, Descrição do arquivo
* @return {Boolean} - Retorna verdadeiro caso o arquivo exista
* @author Sérgio Machado
*/
function hasFileFluig(fileDescription){
try {
const anexos = parent.ECM.attachmentTable.getData();
for(let i = 0; i < anexos.length; i++){
var descricao = anexos[i].description;
if (fileDescription == descricao) {
return true
}
}
return false
} catch (e) {
console.error('Houve um erro inesperado na função hasFileFluig')
console.error(e)
}
}
@@ -0,0 +1,424 @@
$(document).ready(function () {
if ($("#formMode").val() == "VIEW") {
showAndBlock(["all"]);
} else {
var activity = $("#activity").val();
var requestDate = getCurrentDate();
$(".activity").hide();
$(".activity-" + activity).show();
// Atividade 4: Abertura
if (activity == 4) {
$("#dataNec").val(requestDate[0]); // já coloca a data de hoje
toggleBotaoAddItem();
// Atividade 6: Validação do Centro de Custo
} else if (activity == 5) {
showAndBlock([4]); // bloqueia os campos da abertura
$("#userValidacaoGestor").val($("#currentUserName").val());
$("#dataValidacaoGestor").val(requestDate[0] + " - " + requestDate[1]);
if ($("#justificativaDecisaoGestor").val() == "") {
$(".justificativa-activity-4").hide();
}
}
}});
$(document).ready(function () {
try {
FLUIGC.calendar('#dataNec');
} catch (e) {
console.warn("Erro ao iniciar calendário:", e);
}
toggleBotaoAddItem(); // inicia escondido
/* ========= Eventos ========= */
$('#precoRef, #quantidade').on('input', recalcTotal);
$('#qtdMais').on('click', function () {
let v = parseInt($('#quantidade').val() || '0', 10);
$('#quantidade').val(v + 1);
recalcTotal();
});
$('#qtdMenos').on('click', function () {
let v = parseInt($('#quantidade').val() || '0', 10);
v = Math.max(0, v - 1);
$('#quantidade').val(v);
recalcTotal();
});
$('#btnBuscaProd').on('click', consultarProdutos);
$('#btnLimpaProd').on('click', limparCamposPrincipais);
$('#btnAddItem').on('click', adicionarItem);
});
function showAndBlock(activity) {
for (var i = 0; i < activity.length; i++) {
$(".activity-" + activity[i]).show();
$(".hideButton").hide();
$(".activity-" + activity[i] + " :input").each(function () {
$(this).attr("readonly", "readonly")
.css("background-color", "#eee")
.children("option:not(:selected)").prop("disabled", true);
if ($(this).is(":checkbox") || $(this).is(":radio")) {
$(this).attr("disabled", true);
}
});
}
}
function getCurrentDate() {
var newDate = new Date();
var h = newDate.getHours();
if (h < 10) {
h = "0" + h;
}
var m = newDate.getMinutes();
if (m < 10) {
m = "0" + m;
}
var hour = h + ":" + m; // + ":" + s;
var day = newDate.getDate();
if (day < 10) {
day = "0" + day;
}
var month = newDate.getMonth() + 1;
if (month < 10) {
month = "0" + month;
}
newDate = day + "/" + month + "/" + newDate.getFullYear();
var currentDate = [newDate, hour];
return currentDate;
}
function toggleBotaoAddItem() {
const temProduto = $('#produtoCod').val() || $('#DescoProduto').val();
if (temProduto && temProduto.trim() !== "") {
$('#btnAddItem').show();
} else {
$('#btnAddItem').hide();
}
}
function setSelectedZoomItem(selectedItem) {
if (selectedItem.inputId === "estabelecimento") {
// joga o código da filial (cnpj, etc.)
$("#filialDesc").val(selectedItem.CNPJ); // supondo que o dataset dsSysCompany devolva o campo CNPJ
$("#filialest").val(selectedItem.ESTADO); // supondo que o dataset dsSysCompany devolva o campo ESTADO
}
if (selectedItem.inputId === "centroCusto") {
// joga o nome do gestor
$("#gestorCentroCusto").val(selectedItem.gestorCentroCusto); // supondo que o dataset dsCentroCusto devolva o campo GestorCentroCusto
}
}
function removedZoomItem(removedItem) {
if (removedItem.inputId === "estabelecimento") {
// Quando remover a empresa, limpa os campos relacionados
$("#filialDesc").val('');
$("#filialest").val('');
}
}
/* ========= Config ========= */
const DATASET_PRODUTOS = "dsProd"; // dataset de produtos
let todosProdutos = [];
let paginaAtual = 1;
const itensPorPagina = 10;
/* ========= Utils ========= */
function escapeHTML(txt) {
return $('<div>').text(txt == null ? '' : String(txt)).html();
}
function brMoneyToFloat(v) {
if (!v) return 0;
return parseFloat(String(v).replace(/\./g, '').replace(',', '.')) || 0;
}
function floatToBRL(n) {
try {
return new Intl.NumberFormat('pt-BR', { style: 'currency', currency: 'BRL' }).format(n || 0);
} catch (_) {
return 'R$ ' + (n || 0).toFixed(2).replace('.', ',');
}
}
/* ========= Modal Consulta Produtos ========= */
function consultarProdutos() {
FLUIGC.modal({
title: 'Consulta de Produtos',
content:
'<div id="buscaProduto" style="margin-bottom:10px;">' +
'<input type="text" id="filtroDescricao" class="form-control" placeholder="Buscar por descrição..." onkeyup="filtrarProdutos()">' +
'</div>' +
'<div id="listaProdutos"></div>' +
'<div id="paginacaoProdutos" style="margin-top:10px; text-align:center;"></div>',
id: 'modalConsultaProdutos',
size: 'large',
actions: [{ 'label': 'Fechar', 'autoClose': true }]
}, function (err) {
if (!err) carregaListaProdutos();
});
}
function carregaListaProdutos(filtro) {
// Só chama o dataset se ainda não carregou nada
if (todosProdutos.length === 0) {
let dataset = DatasetFactory.getDataset(DATASET_PRODUTOS, null, null, null);
todosProdutos = dataset && dataset.values ? dataset.values : [];
console.log("Produtos carregados do dataset:", todosProdutos.length);
}
paginaAtual = 1;
renderizaProdutos(filtro);
}
function filtrarProdutos() {
paginaAtual = 1;
renderizaProdutos();
}
function renderizaProdutos(filtro) {
filtro = (filtro || $('#filtroDescricao').val() || '').toLowerCase();
// Agora filtra no cache (sem chamar dataset de novo)
const produtosFiltrados = todosProdutos.filter(p =>
(p.descricao || '').toLowerCase().includes(filtro) ||
(p.codigo || '').toLowerCase().includes(filtro) ||
(p.medida || '').toLowerCase().includes(filtro)
);
const inicio = (paginaAtual - 1) * itensPorPagina;
const fim = inicio + itensPorPagina;
const produtosPagina = produtosFiltrados.slice(inicio, fim);
let html = `
<table class="table table-striped">
<thead>
<tr>
<th>Codigo</th>
<th>Descricao</th>
<th>UM</th>
<th>Ultimo Preco</th>
<th>Acao</th>
</tr>
</thead>
<tbody>
`;
if (produtosPagina.length === 0) {
html += `
<tr>
<td colspan="5" class="text-center text-muted">
Nenhum produto encontrado
</td>
</tr>`;
} else {
produtosPagina.forEach(produto => {
const codigo = escapeHTML(produto['codigo']);
const descricao = escapeHTML(produto['descricao']);
const um = escapeHTML(produto['medida'] || '');
const preco = produto['ultimoPreco'] || '0,00';
html += `
<tr>
<td>${codigo}</td>
<td>${descricao}</td>
<td>${um}</td>
<td>${preco}</td>
<td>
<button class="btn btn-sm btn-success selecionar-produto"
data-codigo="${codigo}"
data-descricao="${descricao}"
data-preco="${preco}">
Selecionar
</button>
</td>
</tr>`;
});
}
html += `</tbody></table>`;
$('#listaProdutos').html(html);
renderizaPaginacao(produtosFiltrados.length);
}
function renderizaPaginacao(totalItens) {
const totalPaginas = Math.ceil(totalItens / itensPorPagina);
let html = '';
if (totalPaginas > 1) {
if (paginaAtual > 1) {
html += '<button class="btn btn-sm btn-default" onclick="mudarPagina(' + (paginaAtual - 1) + ')">Anterior</button> ';
}
html += ' Pagina ' + paginaAtual + ' de ' + totalPaginas + ' ';
if (paginaAtual < totalPaginas) {
html += '<button class="btn btn-sm btn-default" onclick="mudarPagina(' + (paginaAtual + 1) + ')">Proxima</button>';
}
}
$('#paginacaoProdutos').html(html);
}
function mudarPagina(n) {
paginaAtual = n;
renderizaProdutos();
}
/* ========= Seleção ========= */
function selecionarProduto(codigo, descricao, preco) {
$('#produtoCod').val(codigo);
$('#DescoProduto').val(codigo + ' - ' + descricao);
$('#ultimoPreco').val(preco);
FLUIGC.toast({ title: 'Produto', message: 'Selecionado: ' + descricao, type: 'success' });
$('#modalConsultaProdutos').modal('hide');
toggleBotaoAddItem(); // 👈 mostra botão
}
/* ========= Eventos delegados ========= */
$(document).on('click', '.selecionar-produto', function () {
const codigo = $(this).data('codigo');
const descricao = $(this).data('descricao');
const preco = $(this).data('preco');
selecionarProduto(codigo, descricao, preco);
});
// Digitação em Qtd ou Preço Ref → recalcula automaticamente
$(document).on('input', 'input[name^="qtd___"], input[name^="Refpreco___"]', function () {
recalcLinha(this);
});
/* ========= Total / Quantidade ========= */
function recalcTotal() {
const q = parseFloat($('#quantidade').val() || '0');
const p = brMoneyToFloat($('#precoRef').val());
const t = (q * p) || 0;
$('#total').val(floatToBRL(t));
}
/* ========= Index das linhas ========= */
function atualizarIndex() {
$('#tbItens tbody tr.tableRow').each(function (i) {
if (!$(this).is('[detail=true]')) {
$(this).find('.tableIndex').text(i);
}
});
}
/* ========= Totais da tabela ========= */
function atualizarTotais() {
let totalItens = 0;
let totalGeral = 0;
// Pega todos os valores da tabela
const dadosTabela = $('#tbItens').find('input').serializeArray();
// Transforma em objeto chave:valor para fácil acesso
const mapValores = {};
dadosTabela.forEach(item => {
mapValores[item.name] = item.value;
});
// Percorre por linha (cada linha tem um sufixo ___1, ___2...)
let idx = 1;
while (mapValores['qtd___' + idx] !== undefined) {
const qtd = parseFloat(mapValores['qtd___' + idx] || 0);
const preco = brMoneyToFloat(mapValores['Refpreco___' + idx] || "0");
const total = qtd * preco;
totalItens += qtd;
totalGeral += total;
// Atualiza campo total da linha
if ($(`#totalValor___${idx}`).length) {
$(`#totalValor___${idx}`).val(floatToBRL(total));
}
idx++;
}
// Atualiza rodapé
$('#totalItens').val(totalItens);
$('#totalGeral').val(floatToBRL(totalGeral));
}
/* ========= Recalcula uma linha ========= */
function recalcLinha(el) {
const $linha = $(el).closest('tr');
const qtd = parseFloat($linha.find('input[name^="qtd___"]').val() || '0');
const preco = brMoneyToFloat($linha.find('input[name^="Refpreco___"]').val() || '0');
const total = qtd * preco;
$linha.find('input[name^="totalValor___"]').val(floatToBRL(total));
atualizarTotais();
}
/* ========= Remover linha ========= */
function fnWdkRemoveChild(el) {
$(el).closest('tr').remove();
atualizarIndex();
atualizarTotais();
}
/* ========= Adicionar Item ========= */
function adicionarItem() {
const cod = $('#produtoCod').val();
const desc = $('#DescoProduto').val();
const ult = $('#ultimoPreco').val() || '0,00';
const qtd = $('#quantidade').val();
const prec = $('#precoRef').val();
const tot = $('#total').val();
const dataN = $('#dataNec').val();
if (!cod) {
FLUIGC.toast({ title: 'Atenção', message: 'Selecione um produto/serviço', type: 'warning' });
return;
}
const idx = wdkAddChild('tbItens');
setTimeout(() => {
$('input[name="Codproduto___' + idx + '"]').val(cod);
const somenteDesc = desc.includes('-') ? desc.split('-').slice(1).join('-').trim() : desc;
$('input[name="produtoDesc___' + idx + '"]').val(somenteDesc);
$('input[name="ultimoPrecoItem___' + idx + '"]').val(ult);
$('input[name="qtd___' + idx + '"]').val(qtd).on('input', function () { recalcLinha(this); });
$('input[name="Refpreco___' + idx + '"]').val(prec).on('input', function () { recalcLinha(this); });
$('input[name="totalValor___' + idx + '"]').val(tot);
$('input[name="dataNecItem___' + idx + '"]').val(dataN);
atualizarIndex();
atualizarTotais();
}, 0);
FLUIGC.toast({ title: 'Item', message: 'Adicionado à lista', type: 'success' });
limparCamposPrincipais();
}
/* ========= Limpar campos principais ========= */
function limparCamposPrincipais() {
$('#produtoCod, #DescoProduto').val('');
$('#ultimoPreco').val('0,00');
$('#quantidade').val('0');
$('#precoRef').val('0,00');
$('#total').val('R$ 0,00');
$('#fnComprovante').val('');
toggleBotaoAddItem(); // 👈 mostra botão
}
@@ -0,0 +1,73 @@
.painel-ginseng > .panel-heading {
background-color: #7a113a !important; /* azul do logo */
color: #fff !important; /* texto branco */
border-color: #0b556b !important;
}
.painel-ginseng {
border-color: #0b556b !important;
}
/* tabela ocupa 100% */
#tbItens {
table-layout: fixed; /* força obedecer larguras definidas */
width: 100%;
}
/* todas as células centralizam por padrão */
#tbItens td, #tbItens th {
vertical-align: middle;
text-align: center;
white-space: nowrap;
}
/* coluna # */
#tbItens th:nth-child(1),
#tbItens td:nth-child(1) {
width: 5%;
}
/* coluna Código (maior espaço) */
#tbItens th:nth-child(2),
#tbItens td:nth-child(2) {
width: 18%;
white-space: normal; /* deixa quebrar */
text-align: left;
}
/* Descrição */
#tbItens th:nth-child(3),
#tbItens td:nth-child(3) {
width: 27%;
}
/* Preço Ref. */
#tbItens th:nth-child(4),
#tbItens td:nth-child(4) {
width: 15%;
}
/* qtd */
#tbItens th:nth-child(5),
#tbItens td:nth-child(5) {
width: 18%;
}
/* Data limite */
#tbItens th:nth-child(6),
#tbItens td:nth-child(6) {
width: 8%;
}
/* Excluir */
#tbItens th:nth-child(7),
#tbItens td:nth-child(7) {
width: 6%;
}
td.text-center .btn-link {
margin: 0 2px; /* espaçamento horizontal */
}
@@ -0,0 +1,432 @@
$(document).ready(function () {
try {
FLUIGC.calendar('#dataNec');
} catch (e) {
console.warn("Erro ao iniciar calendário:", e);
}
toggleBotaoAddItem(); // inicia escondido
/* ========= Eventos ========= */
$('#precoRef, #quantidade').on('input', recalcTotal);
// formata o teto de preço só quando o usuário sair do campo
$('#precoRef').on('blur', function() {
const p = brMoneyToFloat($(this).val());
$(this).val(floatToBRL(p));
recalcTotal();
});
$('#qtdMais').on('click', function () {
let v = parseInt($('#quantidade').val() || '0', 10);
$('#quantidade').val(v + 1);
recalcTotal();
});
$('#qtdMenos').on('click', function () {
let v = parseInt($('#quantidade').val() || '0', 10);
v = Math.max(0, v - 1);
$('#quantidade').val(v);
recalcTotal();
});
$('#btnBuscaProd').on('click', consultarProdutos);
$('#btnLimpaProd').on('click', limparCamposPrincipais);
$('#btnAddItem').on('click', adicionarItem);
});
/* ========= Total / Quantidade ========= */
function recalcTotal() {
const q = parseFloat($('#quantidade').val() || '0');
const p = brMoneyToFloat($('#precoRef').val());
const t = (q * p) || 0;
$('#total').val(floatToBRL(t));
}
function setSelectedZoomItem(selectedItem) {
if (selectedItem.inputId === "estabelecimento") {
// joga o código da filial (cnpj, etc.)
$("#filialdest").val(selectedItem.CNPJ); // supondo que o dataset dsSysCompany devolva o campo CNPJ
$("#filialest").val(selectedItem.ESTADO); // supondo que o dataset dsSysCompany devolva o campo ESTADO
$("#filialprotheus").val(selectedItem.CODIGO); // supondo que o dataset dsSysCompany devolva o campo CODIGO
}
if (selectedItem.inputId === "centro_custo") {
// joga o código da filial (cnpj, etc.)
$("#gestor_cc").val(selectedItem.idGestor); // supondo que o dataset Centro_custo devolva o campo GestorCentroCusto
$("#codigocentroCusto").val(selectedItem.codigoCentroCusto); // supondo que o dataset Centro_custo devolva o campo GestorCentroCusto
}
}
function removedZoomItem(removedItem) {
if (removedItem.inputId === "estabelecimento") {
// Quando remover a empresa, limpa os campos relacionados
$("#filialDesc").val('');
$("#filialest").val('');
}
}
/* ========= Config ========= */
const DATASET_PRODUTOS = "dsProd"; // dataset de produtos
let todosProdutos = [];
let paginaAtual = 1;
const itensPorPagina = 10;
/* ========= Utils ========= */
function escapeHTML(txt) {
return $('<div>').text(txt == null ? '' : String(txt)).html();
}
function brMoneyToFloat(v) {
if (!v) return 0;
return parseFloat(
String(v)
.replace(/R\$/g, '') // remove "R$"
.replace(/\s/g, '') // remove espaços
.replace(/\./g, '') // remove pontos de milhar
.replace(',', '.') // troca vírgula por ponto
) || 0;
}
function floatToBRL(n) {
try {
return new Intl.NumberFormat('pt-BR', { style: 'currency', currency: 'BRL' }).format(n || 0);
} catch (_) {
return 'R$ ' + (n || 0).toFixed(2).replace('.', ',');
}
}
/* ========= Modal Consulta Produtos ========= */
function consultarProdutos() {
FLUIGC.modal({
title: 'Consulta de Produtos',
content:
'<div id="buscaProduto" style="margin-bottom:10px;">' +
'<input type="text" id="filtroDescricao" class="form-control" placeholder="Buscar por nome..." onkeyup="filtrarProdutos()">' +
'</div>' +
'<div id="listaProdutos"></div>' +
'<div id="paginacaoProdutos" style="margin-top:10px; text-align:center;"></div>',
id: 'modalConsultaProdutos',
size: 'large',
actions: [{ 'label': 'Fechar', 'autoClose': true }]
}, function (err) {
if (!err) carregaListaProdutos();
});
}
function carregaListaProdutos(filtro) {
// Só chama o dataset se ainda não carregou nada
if (todosProdutos.length === 0) {
let dataset = DatasetFactory.getDataset(DATASET_PRODUTOS, null, null, null);
todosProdutos = dataset && dataset.values ? dataset.values : [];
console.log("Produtos carregados do dataset:", todosProdutos.length);
}
paginaAtual = 1;
renderizaProdutos(filtro);
}
function filtrarProdutos() {
paginaAtual = 1;
renderizaProdutos();
}
function renderizaProdutos(filtro) {
filtro = (filtro || $('#filtroDescricao').val() || '').toLowerCase();
// Agora filtra no cache (sem chamar dataset de novo)
const produtosFiltrados = todosProdutos.filter(p =>
(p.descricao || '').toLowerCase().includes(filtro) ||
(p.codigo || '').toLowerCase().includes(filtro) ||
(p.medida || '').toLowerCase().includes(filtro)
);
const inicio = (paginaAtual - 1) * itensPorPagina;
const fim = inicio + itensPorPagina;
const produtosPagina = produtosFiltrados.slice(inicio, fim);
let html = `
<table class="table table-striped">
<thead>
<tr>
<th>Codigo</th>
<th>Descricao</th>
<th>UM</th>
<th>Ultimo Preco</th>
<th>Acao</th>
</tr>
</thead>
<tbody>
`;
if (produtosPagina.length === 0) {
html += `
<tr>
<td colspan="5" class="text-center text-muted">
Nenhum produto encontrado
</td>
</tr>`;
} else {
produtosPagina.forEach(produto => {
const codigo = escapeHTML(produto['codigo']);
const descricao = escapeHTML(produto['descricao']);
const um = escapeHTML(produto['medida'] || '');
const preco = produto['ultimo_preco'] || '0,00';
html += `
<tr>
<td>${codigo}</td>
<td>${descricao}</td>
<td>${um}</td>
<td>${preco}</td>
<td>
<button class="btn btn-sm btn-success selecionar-produto"
data-codigo="${codigo}"
data-descricao="${descricao}"
data-preco="${preco}">
Selecionar
</button>
</td>
</tr>`;
});
}
html += `</tbody></table>`;
$('#listaProdutos').html(html);
renderizaPaginacao(produtosFiltrados.length);
}
function renderizaPaginacao(totalItens) {
const totalPaginas = Math.ceil(totalItens / itensPorPagina);
let html = '';
if (totalPaginas > 1) {
if (paginaAtual > 1) {
html += '<button class="btn btn-sm btn-default" onclick="mudarPagina(' + (paginaAtual - 1) + ')">Anterior</button> ';
}
html += ' Pagina ' + paginaAtual + ' de ' + totalPaginas + ' ';
if (paginaAtual < totalPaginas) {
html += '<button class="btn btn-sm btn-default" onclick="mudarPagina(' + (paginaAtual + 1) + ')">Proxima</button>';
}
}
$('#paginacaoProdutos').html(html);
}
function mudarPagina(n) {
paginaAtual = n;
renderizaProdutos();
}
/* ========= Seleção ========= */
function selecionarProduto(codigo, descricao, preco) {
$('#produtoCod').val(codigo);
$('#descProduto').val(codigo + ' - ' + descricao);
$('#ultimoPreco').val(preco);
FLUIGC.toast({ title: 'Produto', message: 'Selecionado: ' + descricao, type: 'success' });
$('#modalConsultaProdutos').modal('hide');
toggleBotaoAddItem(); // 👈 mostra botão
}
function toggleBotaoAddItem() {
const temProduto = $('#produtoCod').val() || $('#descProduto').val();
if (temProduto && temProduto.trim() !== "") {
$('#btnAddItem').show();
} else {
$('#btnAddItem').hide();
}
}
/* ========= Adicionar Item ========= */
function adicionarItem() {
const cod = $('#produtoCod').val();
const desc = $('#descProduto').val();
const qtd = $('#quantidade').val();
if (!cod) {
FLUIGC.toast({ title: 'Atenção', message: 'Selecione um produto/serviço', type: 'warning' });
return;
}
const idx = wdkAddChild('tbItens');
setTimeout(() => {
$('input[name="Codproduto___' + idx + '"]').val(cod);
const somenteDesc = desc.includes('-') ? desc.split('-').slice(1).join('-').trim() : desc;
$('input[name="produtoDesc___' + idx + '"]').val(somenteDesc);
$('input[name="qtd___' + idx + '"]').val(qtd).on('input', function () { recalcLinha(this); });
$('input[name="ultimoPreco___' + idx + '"]').val(prec).on('input', function () { recalcLinha(this); });
atualizarIndex();
atualizarTotais();
}, 0);
FLUIGC.toast({ title: 'Item', message: 'Adicionado à lista', type: 'success' });
limparCamposPrincipais();
}
/* ========= Limpar campos principais ========= */
function limparCamposPrincipais() {
$('#produtoCod, #descProduto').val('');
$('#quantidade').val('0');
$('#precoRef').val('0,00');
$('#fnComprovante').val('');
toggleBotaoAddItem(); // 👈 mostra botão
}
/* ========= Eventos delegados ========= */
$(document).on('click', '.selecionar-produto', function () {
const codigo = $(this).data('codigo');
const descricao = $(this).data('descricao');
const preco = $(this).data('preco');
selecionarProduto(codigo, descricao, preco);
});
/* ========= Index das linhas ========= */
function atualizarIndex() {
$('#tbItens tbody tr.tableRow').each(function (i) {
if (!$(this).is('[detail=true]')) {
$(this).find('.tableIndex').text(i);
}
});
}
/* ========= Remover linha ========= */
function fnWdkRemoveChild(el) {
$(el).closest('tr').remove();
atualizarIndex();
atualizarTotais();
}
/* ========= Link do produto ========= */
function handleProductLink(el) {
const $row = $(el).closest("tr");
const $hidden = $row.find("input.produto-link");
let linkAtual = $hidden.val();
if (!linkAtual) {
// ainda não tem link → pedir ao usuário
let novoLink = prompt("Insira o link do produto:");
if (novoLink && novoLink.trim() !== "") {
$hidden.val(novoLink.trim()); // grava no hidden (vai persistir no Fluig)
}
} else {
// já existe link → abrir
window.open(linkAtual, "_blank");
}
}
$(function () {
var steps = [
{ state: 1, label: "Solicitação" },
{ state: 121, label: "Validando Necessidade" },
{ state: 82, label: "Enviando pedido" },
{ state: 114, label: "Cotação Iniciada" },
{ state: 105, label: "Indicar Cotação" },
{ state: 137, label: "Confirmação da cotação" },
{ state: 133, label: "Aprovação Gestor" },
{ state: 147, label: "Aprovação Ger. Financeiro" },
{ state: 158, label: "Aprovação CEO" },
{ state: 18, label: "Recebimento do Produto" },
{ state: 24, label: "Problema" },
{ state: 52, label: "Fim" }
];
var current = parseInt($("#activity").val() || "0", 10);
var idxAtual = steps.findIndex(function (s) { return s.state === current; });
if (idxAtual < 0) idxAtual = 0;
$("#wizard-steps .step-item").each(function (i) {
if (i < idxAtual) $(this).addClass("done");
if (i === idxAtual) $(this).addClass("active");
});
// clique nos steps
$("#wizard-steps .step-item").on("click", function () {
var index = $(this).index();
var step = steps[index];
if (!step) return;
// 👉 se já estava ativo, mostra tudo de novo
if ($(this).hasClass("active") && $(".activity:visible").length === 1) {
$(".activity").show();
$("#wizard-steps .step-item").removeClass("active");
return;
}
// senão, mostra só a activity clicada
$(".activity").hide();
$(".activity-" + step.state).show();
$("#wizard-steps .step-item").removeClass("active");
$(this).addClass("active");
});
});
$(document).ready(function () {
// Quando carregar a página, já pinta o status se tiver valor nos inputs
let status = $("#statusSCProtheus").val() || "";
let badgeClass = "badge bg-secondary";
if (status.toLowerCase().includes("sucesso")) badgeClass = "badge bg-success";
if (status.toLowerCase().includes("erro")) badgeClass = "badge bg-danger";
$("#statusSCProtheus_label")
.text(status || "-")
.removeClass()
.addClass(badgeClass);
});
function recalcularTotalCotacao() {
var soma = 0;
$("input[name^='selecionado___']").each(function() {
var idx = $(this).attr("id").split("___")[1];
// pega qtd e preço da linha
var qtd = parseFloat($("#qtdc___" + idx).val() || "0");
var preco = parseFloat($("#preco___" + idx).val() || "0");
// calcula total da linha
var total = qtd * preco;
// atualiza campo total da linha
$("#total___" + idx).val(total.toFixed(2));
// se marcado, acumula na soma
if ($(this).is(":checked")) {
soma += total;
}
});
// Atualiza o hidden e dispara change pro Fluig gravar
$("#valorTotalCotacao").val(soma.toFixed(2)).trigger("change");
}
// dispara sempre que marcar/desmarcar
$(document).on("change", "input[name^='selecionado___']", function() {
recalcularTotalCotacao();
});
// recalcula ao abrir a atividade
$(document).ready(function() {
recalcularTotalCotacao();
});
// garante que o total seja salvo antes de enviar a atividade
function beforeSendValidate(numState, nextState) {
console.log("Executando beforeSendValidate, recalculando total...");
recalcularTotalCotacao();
return true; // precisa retornar true senão bloqueia o envio
}
@@ -0,0 +1,283 @@
function displayFields(form, customHTML) {
var activity = getValue('WKNumState');
var userId = getValue('WKUser');
form.setShowDisabledFields(true);
form.setHidePrintLink(true);
form.setValue("WKNumProces", getValue('WKNumProces'));
form.setValue("activity", activity);
form.setValue("formMode", form.getFormMode());
form.setValue("empresa", getValue("WKCompany"));
var c1 = DatasetFactory.createConstraint("colleagueId", userId, userId, ConstraintType.MUST);
var filter = new Array(c1);
var fields = new Array("colleagueName");
var retorno = DatasetFactory.getDataset("colleague", fields, filter, null);
//requester
if (activity == 0) {
form.setValue("usuario_abertura", retorno.getValue(0, "colleagueName"));
form.setValue("requesterMail", retorno.getValue(0, "mail"));
form.setValue("requesterId", userId);
} else {
form.setValue("currentUserName", retorno.getValue(0, "colleagueName"));
form.setValue("currentUsermail", retorno.getValue(0, "mail"));
form.setValue("currentUserId", userId);
}
// ✅ Quando for atividade de aprovação do gestor
if (activity == 121) {
var hoje = new java.text.SimpleDateFormat("dd/MM/yyyy").format(new java.util.Date());
form.setValue("user_validacao_gestor", retorno.getValue(0, "colleagueName"));
form.setValue("data_validacao_gestor", hoje);
}
if (activity == 133) {
var hoje = new java.text.SimpleDateFormat("dd/MM/yyyy").format(new java.util.Date());
form.setValue("gestor_validacao_aprova", retorno.getValue(0, "colleagueName"));
form.setValue("data_validacao_aprova_gestor", hoje);
}
if (activity == 137) {
var hoje = new java.text.SimpleDateFormat("dd/MM/yyyy").format(new java.util.Date());
form.setValue("user_validacao_aprova", retorno.getValue(0, "colleagueName"));
form.setValue("data_validacao_aprova", hoje);
}
if (activity == 147) {
var hoje = new java.text.SimpleDateFormat("dd/MM/yyyy").format(new java.util.Date());
form.setValue("gerf_validacao_aprova", retorno.getValue(0, "colleagueName"));
form.setValue("data_validacao_aprova_gerf", hoje);
}
if (activity == 18) {
var hoje = new java.text.SimpleDateFormat("dd/MM/yyyy").format(new java.util.Date());
form.setValue("userValidacaoItens", retorno.getValue(0, "colleagueName"));
form.setValue("dataValidacaoItens", hoje);
}
// ✅ Injetar dados da SC do Protheus (se já tiverem sido preenchidos no servicetask)
var camposSC = [
"numeroSCProtheus",
"statusSCProtheus",
"solicitanteSCProtheus",
"emissaoSCProtheus",
"qtdItensSCProtheus",
"dataCadastroSCProtheus",
"horaCadastroSCProtheus"
];
camposSC.forEach(function(campo) {
var valor = form.getValue(campo);
if (valor) {
customHTML.append("<script>$('#" + campo + "_label').text('" + valor + "');</script>");
}
});
// cor no status
var status = form.getValue("statusSCProtheus");
if (status) {
var badgeClass = "badge bg-secondary";
if (status.toLowerCase().indexOf("sucesso") >= 0) badgeClass = "badge bg-success";
if (status.toLowerCase().indexOf("erro") >= 0) badgeClass = "badge bg-danger";
customHTML.append("<script>$('#statusSCProtheus_label').removeClass().addClass('" + badgeClass + "').text('" + status + "');</script>");
}
// Consultar informações adicionais da SC no Protheus
var numSC = form.getValue("numeroSCProtheus");
if (numSC) {
try {
var c1 = DatasetFactory.createConstraint("numeroSCProtheus", numSC, numSC, ConstraintType.MUST);
var ds = DatasetFactory.getDataset("ds_consultaSC", null, [c1], null);
if (ds && ds.rowsCount > 0) {
var status = ds.getValue(0, "STATUS") || "";
var cotacao = ds.getValue(0, "C1_COTACAO") || "";
var pedido = ds.getValue(0, "C1_PEDIDO") || "";
// grava nos hidden inputs
form.setValue("statusAtendimento", status);
form.setValue("cotacaoSCProtheus", cotacao);
form.setValue("pedidoSCProtheus", pedido);
// mostra nos cards (HTML)
customHTML.append("<script>$('#statusSC_label').text('" + status + "');</script>");
customHTML.append("<script>$('#cotacaoSC_label').text('" + cotacao + "');</script>");
customHTML.append("<script>$('#pedidoSC_label').text('" + pedido + "');</script>");
}
} catch (e) {
log.error("❌ Erro ao consultar dataset ds_consultaSC: " + e);
}
}
try {
var msgs = [];
var numeroSC = form.getValue("numeroSCProtheus");
var cotacaoSC = form.getValue("cotacaoSCProtheus");
var pedidoSC = form.getValue("pedidoSCProtheus");
if (numeroSC) msgs.push("📌 Gerou SC Protheus nº " + numeroSC);
if (cotacaoSC) msgs.push("📌 SC originou Cotação nº " + cotacaoSC);
if (pedidoSC) msgs.push("📌 Cotação finalizou → Pedido nº " + pedidoSC);
if (msgs.length === 0) {
msgs.push("️ Nenhum dado de integração Protheus encontrado no formulário");
}
// Monta conteúdo HTML do histórico
var htmlHistorico = "<ul class='hist-list'>";
for (var i = 0; i < msgs.length; i++) {
htmlHistorico += "<li class='hist-item'>" + msgs[i] + "</li>";
}
htmlHistorico += "</ul>";
// Script para abrir modal ao clicar no botão
customHTML.append("<script>");
customHTML.append("$('#btnHistorico').off('click').on('click', function(){");
customHTML.append(" var myModal = FLUIGC.modal({");
customHTML.append(" title: 'Histórico do Processo',");
customHTML.append(" content: `" + htmlHistorico + "`,");
customHTML.append(" id: 'modalHistorico',");
customHTML.append(" size: 'large'");
customHTML.append(" });");
customHTML.append("});");
customHTML.append("</script>");
} catch (e) {
log.error("[displayFields] Erro ao montar histórico: " + e);
}
var numCot = form.getValue("cotacaoSCProtheus");
var numSC = form.getValue("numeroSCProtheus"); // pega a SC atual
function formatCurrency(v) {
if (!v || isNaN(v)) return "R$ 0,00";
var num = parseFloat(v).toFixed(2);
return "R$ " + num.replace(".", ",").replace(/\B(?=(\d{3})+(?!\d))/g, ".");
}
function formatDate(v) {
if (!v || v.length !== 8) return v || "";
var y = v.substring(0,4);
var m = v.substring(4,6);
var d = v.substring(6,8);
return d + "/" + m + "/" + y;
}
function formatPrazo(v) {
if (!v) return "";
return v + " dias úteis";
}
if (!numCot) {
customHTML.append("<script>");
customHTML.append("$('#cotacaoContainer').html('<p>⚠️ Cotação não informada no formulário.</p>');");
customHTML.append("</script>");
return;
}
var c = DatasetFactory.createConstraint("numCotacao", numCot, numCot, ConstraintType.MUST);
var ds = DatasetFactory.getDataset("dsComprasCotacao", null, [c], null);
var precoFormatado = formatCurrency(preco);
var totalFormatado = formatCurrency(total);
if (ds && ds.rowsCount > 0) {
for (var i = 0; i < ds.rowsCount; i++) {
var item = ds.getValue(i, "C8_ITEM");
var desc = ds.getValue(i, "B1_DESC");
var qtd = ds.getValue(i, "C8_QUANT");
var preco = ds.getValue(i, "C8_PRECO");
var total = ds.getValue(i, "C8_TOTAL");
// adiciona linha na tabela pai-filho
customHTML.append("<script>");
customHTML.append("var idx = wdkAddChild('tbCotacao');");
customHTML.append("$('#item___'+idx).val('" + item + "');");
customHTML.append("$('#produto___'+idx).val('" + desc + "');");
customHTML.append("$('#qtdc___'+idx).val('" + qtd + "');");
customHTML.append("$('#preco___' + idx).val('" + precoFormatado + "');");
customHTML.append("$('#total___' + idx).val('" + totalFormatado + "');");
customHTML.append("</script>");
}
} else {
customHTML.append("<script>$('#tbCotacao tbody').html('<tr><td colspan=6>⏳ Nenhum item encontrado.</td></tr>');</script>");
}
try {
var numPedido = form.getValue("pedidoSCProtheus"); // hidden no formulário
if (!numPedido) {
customHTML.append("<script>");
customHTML.append("$('#espelhoPedido').html('<span class=\"badge bg-warning\">⏳ O pedido ainda não foi criado</span>');");
customHTML.append("</script>");
return;
}
var c = DatasetFactory.createConstraint("numeroPed", numPedido, numPedido, ConstraintType.MUST);
var ds = DatasetFactory.getDataset("dsComprasGateway", null, [c], null);
if (!ds || ds.rowsCount === 0) {
customHTML.append("<script>");
customHTML.append("$('#espelhoPedido').html('<span class=\"badge bg-warning\">⏳ O pedido ainda não foi criado</span>');");
customHTML.append("</script>");
return;
}
var html = "";
for (var i = 0; i < ds.rowsCount; i++) {
var rowNum = ds.getValue(i, "C7_NUM");
var desc = ds.getValue(i, "B1_DESC");
var qtd = ds.getValue(i, "C7_QUANT");
var valor = ds.getValue(i, "C7_TOTAL");
var un = ds.getValue(i, "B1_UM");
var pr = ds.getValue(i, "C7_DATPRF");
html += "<div class='pedido-card'>"
+ " <div class='pedido-header'>Pedido nº " + (rowNum || "-") + "</div>"
+ " <div class='pedido-grid'>"
+ " <div class='pedido-box'><b>Descrição</b><br>" + (desc || "-") + "</div>"
+ " <div class='pedido-box'><b>Quantidade</b><br>" + parseInt(qtd || 0) + " " + (un || "") + "</div>"
+ " <div class='pedido-box'><b>Valor</b><br>" + formatCurrency(valor) + "</div>"
+ " <div class='pedido-box'><b>Data de Entrega</b><br>" + formatDate(pr) + "</div>"
+ " </div>"
+ "</div>";
}
customHTML.append("<script>");
customHTML.append("$('#espelhoPedido').html(" + JSON.stringify(html) + ");");
customHTML.append("</script>");
} catch (e) {
var msg = "❌ Erro displayFields Pedido: " + (e && e.message ? e.message : e);
log.error(msg);
customHTML.append("<script>");
customHTML.append("console.error(" + JSON.stringify(msg) + ");"); // aparece no console do navegador
customHTML.append("$('#espelhoPedido').html('<span class=\"badge bg-danger\">" + msg + "</span>');");
customHTML.append("</script>");
}
// Se estou na atividade do Gestor do CC (ex: 133)
if (activity == 133) {
// Copia a justificativa do solicitante para o campo de exibição
form.setValue("observacoesdosolicitante", form.getValue("observacoes"));
}
// Se estou na atividade do GERF (ex: 147)
if (activity == 147) {
form.setValue("justi_decisao__soli", form.getValue("observacoes")); // solicitante
form.setValue("justi_decisao_gc", form.getValue("justi_decisao_aprova_gestor")); // gestor
}
// Se estou na atividade do CEO (ex: 158)
if (activity == 158) {
form.setValue("justi_decisao_solic", form.getValue("observacoes")); // solicitante
form.setValue("justi_decisaogc", form.getValue("justi_decisao_aprova_gestor")); // gestor
form.setValue("justi_decisao_gerf", form.getValue("justi_decisao_aprova_gerente")); // gerente financeiro
}
}
@@ -0,0 +1,12 @@
function enableFields(form) {
var atividade = getValue("WKNumState");
if (atividade != 0 && atividade != 4 && atividade != 9) {
form.setEnabled("emitido_por", false);
form.setEnabled("tipo_cadastro", false);
form.setEnabled("radio_ged", false);
form.setEnabled("radio_data_validade", false);
}
}
@@ -0,0 +1,15 @@
function validateForm(form){
var msg = "";
var activity = getValue("WKNumState");
// Só valida "Justificativa do Gestor" quando estiver na atividade do gestor (ex.: 5)
if (activity == 121) {
if (form.getValue("justi_decisao_gestor") == "") {
msg += "Campo Justificativa do Gestor não foi preenchido\n";
}
}
if (msg != "") {
throw msg;
}
}
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,161 @@
.componentAnexo{
display: flex;
align-items: center;
flex-wrap: nowrap;
}
.componentAnexo .input-group{
flex-grow: 1;
position: relative;
}
.componentAnexo .inputAnexo{
color: blue!important;
border-radius: 0!important;
}
.componentAnexo .icones{
display: flex;
align-items: center;
justify-content: flex-end;
}
.componentAnexo .icones .btn{
outline: none!important;
outline-offset: unset!important;
border-radius: 0;
padding-left: 7px;
padding-right: 7px;
margin-left: 3px;
}
.componentAnexo .icones .btn-default,
.componentAnexo .icones .btn-default:focus,
.componentAnexo .icones .btn-default:active,
.componentAnexo .icones .btn-default:hover{
border: solid 1px #58595b!important;
}
.componentAnexo .icones .btn-primary,
.componentAnexo .icones .btn-primary:focus,
.componentAnexo .icones .btn-primary:active,
.componentAnexo .icones .btn-primary:hover{
border: solid 1px #58595b!important;
}
.componentAnexo .icones .btn-success,
.componentAnexo .icones .btn-success:focus,
.componentAnexo .icones .btn-success:active,
.componentAnexo .icones .btn-success:hover{
border: solid 1px #1ab83f!important;
}
.componentAnexo .icones .btn-info,
.componentAnexo .icones .btn-info:focus,
.componentAnexo .icones .btn-info:active,
.componentAnexo .icones .btn-info:hover{
border: solid 1px #1eaad9!important;
}
.componentAnexo .icones .btn-warning,
.componentAnexo .icones .btn-warning:focus,
.componentAnexo .icones .btn-warning:active,
.componentAnexo .icones .btn-warning:hover{
border: solid 1px #e3b420!important;
}
.componentAnexo .icones .btn-danger,
.componentAnexo .icones .btn-danger:focus,
.componentAnexo .icones .btn-danger:active,
.componentAnexo .icones .btn-danger:hover{
border: solid 1px #cc3d3d!important;
}
/* Etapas concluídas */
#wizard-steps .step-item.done .step-bullet {
background-color: #28a745; /* verde */
border-color: #28a745;
color: white;
}
#wizard-steps .step-item.done .step-label {
color: #28a745;
font-weight: bold;
}
/* Etapa atual */
#wizard-steps .step-item.active .step-bullet {
background-color: #007bff; /* azul */
border-color: #007bff;
color: white;
}
#wizard-steps .step-item.active .step-label {
color: #007bff;
font-weight: bold;
}
/* Etapas futuras */
#wizard-steps .step-item .step-bullet {
background-color: #e9ecef; /* cinza claro */
border: 2px solid #ccc;
color: #6c757d;
}
#wizard-steps .step-item .step-label {
color: #6c757d;
}
/* Deixar as bolinhas maiores e destacadas */
#wizard-steps .step-bullet {
width: 24px;
height: 24px;
border-radius: 50%;
display: inline-flex;
align-items: center;
justify-content: center;
font-size: 14px;
margin-right: 8px;
}
.hist-list {
margin: 0;
padding-left: 20px;
list-style: none;
}
.hist-list .hist-item {
padding: 8px 0;
border-bottom: 1px dashed #ddd;
font-size: 14px;
line-height: 1.5;
}
.hist-list .hist-item:last-child { border-bottom: 0; }
.pedido-card {
border: 1px solid #ddd;
border-radius: 8px;
margin: 10px 0;
padding: 10px;
box-shadow: 2px 2px 5px rgba(0,0,0,0.05);
}
.pedido-header {
font-weight: bold;
margin-bottom: 8px;
background: #f5f5f5;
padding: 5px 10px;
border-radius: 5px;
}
.pedido-grid {
display: flex;
flex-wrap: wrap;
gap: 10px;
}
.pedido-box {
flex: 1 1 120px; /* mínimo 120px, ajusta conforme espaço */
background: #fafafa;
border: 1px solid #eee;
border-radius: 6px;
padding: 8px;
text-align: center;
font-size: 13px;
}