Primeiro commit fluig
This commit is contained in:
Binary file not shown.
@@ -0,0 +1,236 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Criar Solicitação de Compras</title>
|
||||
|
||||
<!-- Fluig SG + deps -->
|
||||
<link rel="stylesheet" href="/style-guide/css/fluig-style-guide.min.css">
|
||||
<link rel="stylesheet" href="/style-guide/css/fluig-style-guide-filter.min.css"> <!-- ADICIONE -->
|
||||
<script src="/portal/resources/js/jquery/jquery.js"></script>
|
||||
<script src="/portal/resources/js/jquery/jquery-ui.min.js"></script>
|
||||
<script src="/style-guide/js/fluig-style-guide.min.js"></script>
|
||||
<script src="/style-guide/js/fluig-style-guide-filter.min.js"></script> <!-- ADICIONE -->
|
||||
|
||||
<!-- seu JS/CSS -->
|
||||
<link rel="stylesheet" href="form.css">
|
||||
<script src="compras.js"></script>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div class="fluig-style-guide">
|
||||
<form name="form" role="form">
|
||||
|
||||
<div class="fs-display-block">
|
||||
|
||||
<!-- PAINEL: Dados da solicitação -->
|
||||
<div class="panel panel-info">
|
||||
<div class="panel-heading"><strong>Dados da Solicitação</strong></div>
|
||||
<div class="panel-body">
|
||||
|
||||
<div class="row">
|
||||
<div class="col-sm-6">
|
||||
<label>Empresa</label>
|
||||
<span class="required text-danger"><strong> * </strong></span>
|
||||
<input type="zoom" class="form-control requiredInput" name="estabelecimento" id="estabelecimento"
|
||||
data-zoom="{
|
||||
'displayKey':'LOJA',
|
||||
'datasetId':'dsSysCompany',
|
||||
'placeholder': 'Pesquisar por nome do estabelecimento.',
|
||||
'fields':[
|
||||
{
|
||||
'field':'BPCS',
|
||||
'label':'Filial',
|
||||
'standard':'true',
|
||||
'search':'true'
|
||||
},
|
||||
{
|
||||
'field':'DESCRICAO',
|
||||
'label':'estabelecimento',
|
||||
'search':'true'
|
||||
}
|
||||
]
|
||||
}" />
|
||||
<p class="text-danger text-error">
|
||||
Preenchimento obrigatório.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="col-sm-2">
|
||||
<label>Filial Entrega</label>
|
||||
<input type="text" name="filialDesc" id="filialDesc" class="form-control zoom"
|
||||
placeholder="Selecione..." readonly>
|
||||
</div>
|
||||
|
||||
<div class="col-sm-4">
|
||||
<label>Tipo de Solicitação <span class="text-danger">*</span></label>
|
||||
<select name="tipoSolicitacao" id="tipoSolicitacao" class="form-control" required>
|
||||
<option value="">Selecione</option>
|
||||
<option>Material</option>
|
||||
<option>Serviço</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row m-t-15">
|
||||
|
||||
<div class="col-sm-6">
|
||||
<label>Produto/Serviço <span class="text-danger">*</span></label>
|
||||
<div class="input-group">
|
||||
<input type="hidden" name="produtoCod" id="produtoCod">
|
||||
<input type="text" name="produtoDesc" id="produtoDesc" class="form-control zoom" data-zoom="produto"
|
||||
placeholder="Buscar..." readonly required>
|
||||
<span class="input-group-btn">
|
||||
<button class="btn btn-default" 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>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-sm-2">
|
||||
<label>Último Preço</label>
|
||||
<input type="text" name="ultimoPreco" id="ultimoPreco" class="form-control text-right" value="0,00"
|
||||
readonly>
|
||||
</div>
|
||||
<div class="col-sm-2">
|
||||
<label>Quantidade <span class="text-danger">*</span></label>
|
||||
<div class="input-group">
|
||||
<span class="input-group-btn">
|
||||
<button type="button" class="btn btn-default" 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-default" id="qtdMais">+</button>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-sm-2">
|
||||
<label>Data da Necessidade <span class="text-danger">*</span></label>
|
||||
<input type="text" name="dataNec" id="dataNec" class="form-control" placeholder="dd/mm/aaaa" required>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="row m-t-10">
|
||||
<div class="col-sm-6">
|
||||
<label>Centro de Custo <span class="text-danger">*</span></label>
|
||||
<input type="zoom" name="ccDesc" id="ccDesc" class="form-control" data-zoom="{
|
||||
'displayKey':'centroCusto',
|
||||
'datasetId':'ds_centroCusto',
|
||||
'placeholder': 'Pesquisar número ou nome do centro de custo.',
|
||||
'fields':[
|
||||
{
|
||||
'field':'codigoCentroCusto',
|
||||
'label':'Código',
|
||||
'standard':'true',
|
||||
'search':'true'
|
||||
},
|
||||
{
|
||||
'field':'centroCusto',
|
||||
'label':'Centro de custo',
|
||||
'search':'true'
|
||||
},
|
||||
{
|
||||
'field': 'gestorCentroCusto',
|
||||
'label': 'Gestor',
|
||||
'visible': 'false'
|
||||
},
|
||||
{
|
||||
'field': 'emailGestor',
|
||||
'label': 'Email do gestor',
|
||||
'visible': 'false'
|
||||
},
|
||||
{
|
||||
'field': 'idGestor',
|
||||
'label': 'Id do gestor',
|
||||
'visible': 'false'
|
||||
}
|
||||
]
|
||||
}" />
|
||||
</div>
|
||||
|
||||
<div class="col-sm-3">
|
||||
<label>Compra Emergencial?</label>
|
||||
<select name="emergencial" id="emergencial" class="form-control">
|
||||
<option>Não</option>
|
||||
<option>Sim</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="col-sm-3">
|
||||
<label>Total</label>
|
||||
<input type="text" name="total" id="total" class="form-control text-right" value="R$ 0,00" readonly>
|
||||
</div>
|
||||
</div> <!-- aqui sim fecha corretamente a row -->
|
||||
|
||||
<div class="row m-t-20">
|
||||
<div class="col-sm-12">
|
||||
<button type="button" class="btn btn-success" id="btnAddAnexo">
|
||||
<span class="fluigicon fluigicon-upload"></span> Adicionar Anexo
|
||||
</button>
|
||||
</div>
|
||||
<div class="col-sm-12">
|
||||
<label>Observação do Item</label>
|
||||
<textarea name="obs" id="obs" class="form-control" rows="2"></textarea>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="text-center m-t-15">
|
||||
<button type="button" id="btnAddItem" class="btn btn-primary">
|
||||
<span class="fluigicon fluigicon-add"></span> Adicionar Item
|
||||
</button>
|
||||
</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">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Produto</th>
|
||||
<th>Centro de Custo</th>
|
||||
<th>Qtd</th>
|
||||
<th>Preço Ref.</th>
|
||||
<th>Total</th>
|
||||
<th>Ação</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<!-- LINHA MODELO (detail=true) -->
|
||||
<tr class="tableRow" detail="true">
|
||||
<td>
|
||||
<input type="hidden" name="CodProd" class="form-control">
|
||||
<input type="text" name="DescProd" class="form-control" readonly>
|
||||
</td>
|
||||
<td>
|
||||
<input type="hidden" name="Codcc" class="form-control">
|
||||
<input type="text" name="Desccc" class="form-control" readonly>
|
||||
</td>
|
||||
<td><input type="number" name="qtd" class="form-control text-right" min="0" step="1" value="0"></td>
|
||||
<td><input type="text" name="Refpreco" class="form-control text-right" value="0,00"></td>
|
||||
<td><input type="text" name="totalProd" class="form-control text-right" value="R$ 0,00" readonly></td>
|
||||
<td class="text-center">
|
||||
<button type="button" class="btn btn-link" onclick="fnWdkRemoveChild(this)">
|
||||
<span class="fluigicon fluigicon-trash"></span>
|
||||
</button>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
@@ -0,0 +1,203 @@
|
||||
// ======== DATASETS (troque aqui se o id for diferente) ========
|
||||
const DS_EMPRESAS = 'dsSyscompany';
|
||||
const DS_FILIAIS = 'dsFiliais'; // se o seu for outro, troque aqui
|
||||
const DS_CC = 'ds_centroCusto';
|
||||
const DS_PRODUTOS = 'ProdutoTI'; // se o id for "ProdutosTI", troque aqui
|
||||
|
||||
// ======== MAPEAMENTO DE CAMPOS (ajuste se seus datasets usam nomes diferentes) ========
|
||||
// Empresas / Filiais / Centro de Custo
|
||||
const EMP_FIELDS = { code: 'codigo', desc: 'descricao' };
|
||||
const FIL_FIELDS = { code: 'codigo', desc: 'descricao' };
|
||||
const CC_FIELDS = { code: 'codigo', desc: 'descricao' };
|
||||
|
||||
// Produtos (inclui alternativas típicas do Protheus)
|
||||
const PROD_FIELDS = {
|
||||
code: ['codigo','B1_COD','CODIGO'],
|
||||
desc: ['descricao','B1_DESC','DESCRICAO'],
|
||||
um: ['um','B1_UM','UM'],
|
||||
lastPrice: ['ultimoPreco','ULTIMO_PRECO','ULT_PRECO','ULTIMOPRECO']
|
||||
};
|
||||
|
||||
// ======== INIT ========
|
||||
$(document).ready(function () {
|
||||
FLUIGC.calendar('#dataNec');
|
||||
|
||||
// qty/preço
|
||||
$('#precoRef').on('blur', recalcTotal);
|
||||
$('#quantidade').on('input', recalcTotal);
|
||||
$('#qtdMais').on('click', () => stepQtd(1));
|
||||
$('#qtdMenos').on('click', () => stepQtd(-1));
|
||||
|
||||
// produto
|
||||
$('#btnBuscaProd').on('click', openZoomProduto);
|
||||
$('#btnLimpaProd').on('click', () => {
|
||||
$('#produtoCod,#produtoDesc').val('');
|
||||
$('#ultimoPreco').val('0,00');
|
||||
recalcTotal();
|
||||
});
|
||||
|
||||
// zooms
|
||||
bindZoom($('#empresaDesc'), DS_EMPRESAS, EMP_FIELDS, 'empresaCodigo','empresaDesc');
|
||||
bindZoom($('#filialDesc'), DS_FILIAIS, FIL_FIELDS, 'filialCodigo','filialDesc');
|
||||
bindZoom($('#ccDesc'), DS_CC, CC_FIELDS, 'ccCod','ccDesc');
|
||||
|
||||
// itens
|
||||
$('#btnAddItem').on('click', addItem);
|
||||
});
|
||||
|
||||
// ======== HELPERS ========
|
||||
function stepQtd(n){
|
||||
const $q = $('#quantidade');
|
||||
let v = parseInt($q.val()||'0',10)+n;
|
||||
if (v < 0) v = 0;
|
||||
$q.val(v);
|
||||
recalcTotal();
|
||||
}
|
||||
|
||||
function parseMoneyBR(s){
|
||||
if(!s) return 0;
|
||||
s = (''+s).replace(/[^\d,,-]/g,'').replace(/\./g,'').replace(',', '.');
|
||||
const v = Number(s);
|
||||
return isNaN(v) ? 0 : v;
|
||||
}
|
||||
function formatMoneyBR(v){
|
||||
return v.toLocaleString('pt-BR',{style:'currency',currency:'BRL'});
|
||||
}
|
||||
function recalcTotal(){
|
||||
const qtd = parseFloat($('#quantidade').val()||'0');
|
||||
const preco = parseMoneyBR($('#precoRef').val());
|
||||
const tot = (qtd * preco) || 0;
|
||||
$('#total').val(formatMoneyBR(tot));
|
||||
}
|
||||
|
||||
// Compat: usa filtermodal OU filterModal, dependendo da versão do SG
|
||||
function openFilterModalCompat(opts){
|
||||
var fn = (FLUIGC && (FLUIGC.filtermodal || FLUIGC.filterModal));
|
||||
if (!fn) {
|
||||
FLUIGC.toast({
|
||||
title: 'Erro: ',
|
||||
message: 'Plugin de filtro (filtermodal) não está carregado. Verifique os includes do Style Guide.',
|
||||
type: 'danger'
|
||||
});
|
||||
return { onSelected: function(){} };
|
||||
}
|
||||
return fn(opts);
|
||||
}
|
||||
|
||||
// pega a primeira chave existente no item
|
||||
function pick(obj, keys){
|
||||
if (!Array.isArray(keys)) return obj[keys];
|
||||
for (const k of keys) if (obj[k] !== undefined && obj[k] !== null) return obj[k];
|
||||
return '';
|
||||
}
|
||||
function firstKey(keys){ return Array.isArray(keys) ? keys[0] : keys; }
|
||||
|
||||
// ======== ZOOMS GENÉRICOS (empresa, filial, centro de custo) ========
|
||||
function bindZoom($input, datasetId, fieldsMap, hiddenIdFld, displayFld){
|
||||
const codeK = fieldsMap.code, descK = fieldsMap.desc;
|
||||
|
||||
$input.on('click', function(){
|
||||
openFilterModalCompat({
|
||||
title: 'Selecionar',
|
||||
size: 'large',
|
||||
filterFields: codeK + ', ' + descK,
|
||||
source: {
|
||||
url: '/api/public/ecm/dataset/search',
|
||||
contentType: 'application/json',
|
||||
root: 'content',
|
||||
limit: 50,
|
||||
pattern: '',
|
||||
param: { datasetId: datasetId }
|
||||
},
|
||||
columns: [
|
||||
{ title: 'Código', data: codeK },
|
||||
{ title: 'Descrição', data: descK }
|
||||
],
|
||||
onSelected: function(data){
|
||||
$('#'+hiddenIdFld).val(data[codeK]);
|
||||
$('#'+displayFld).val(data[codeK] + ' - ' + data[descK]);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// ======== ZOOM DE PRODUTO ========
|
||||
function openZoomProduto(){
|
||||
openFilterModalCompat({
|
||||
title: 'Buscar Produto/Serviço',
|
||||
size: 'large',
|
||||
filterFields: firstKey(PROD_FIELDS.code) + ', ' + firstKey(PROD_FIELDS.desc),
|
||||
source: {
|
||||
url: '/api/public/ecm/dataset/search',
|
||||
contentType: 'application/json',
|
||||
root: 'content',
|
||||
limit: 50,
|
||||
param:{ datasetId: DS_PRODUTOS }
|
||||
},
|
||||
columns: [
|
||||
{ title: 'Código', data: firstKey(PROD_FIELDS.code) },
|
||||
{ title: 'Descrição', data: firstKey(PROD_FIELDS.desc) },
|
||||
{ title: 'UM', data: firstKey(PROD_FIELDS.um) },
|
||||
{ title: 'Último Preço', data: firstKey(PROD_FIELDS.lastPrice) }
|
||||
],
|
||||
onSelected: function(item){
|
||||
const cod = pick(item, PROD_FIELDS.code);
|
||||
const desc = pick(item, PROD_FIELDS.desc);
|
||||
const ult = pick(item, PROD_FIELDS.lastPrice);
|
||||
|
||||
$('#produtoCod').val(cod);
|
||||
$('#produtoDesc').val(cod + ' - ' + desc);
|
||||
$('#ultimoPreco').val(ult || '0,00');
|
||||
recalcTotal();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// ======== ITENS (tabela filha) ========
|
||||
function addItem(){
|
||||
if(!$('#produtoCod').val()){
|
||||
FLUIGC.toast({title:'Atenção: ', message:'Selecione um produto.', type:'warning'}); return;
|
||||
}
|
||||
if(!$('#ccCod').val()){
|
||||
FLUIGC.toast({title:'Atenção: ', message:'Selecione o centro de custo.', type:'warning'}); return;
|
||||
}
|
||||
const qtd = parseFloat($('#quantidade').val()||'0');
|
||||
if(qtd <= 0){
|
||||
FLUIGC.toast({title:'Atenção: ', message:'Quantidade deve ser > 0.', type:'warning'}); return;
|
||||
}
|
||||
|
||||
const row = wdkAddChild('tbItens');
|
||||
$('#produtoCod___'+row).val($('#produtoCod').val());
|
||||
$('#produtoDesc___'+row).val($('#produtoDesc').val());
|
||||
$('#ccCod___'+row).val($('#ccCod').val());
|
||||
$('#ccDesc___'+row).val($('#ccDesc').val());
|
||||
$('#qtd___'+row).val(qtd);
|
||||
$('#precoRef___'+row).val($('#precoRef').val());
|
||||
$('#total___'+row).val($('#total').val());
|
||||
}
|
||||
|
||||
// ======== VALIDAÇÃO (se usar o hook validateForm) ========
|
||||
function validateForm(form){
|
||||
var msgs = [];
|
||||
function req(id, label){ if(!form.getValue(id)) msgs.push('Preencha "'+label+'".'); }
|
||||
req('tipoSolicitacao','Tipo de Solicitação');
|
||||
req('produtoCod','Produto/Serviço');
|
||||
req('quantidade','Quantidade');
|
||||
req('dataNec','Data da Necessidade');
|
||||
req('ccCod','Centro de Custo');
|
||||
if(msgs.length){ throw msgs.join('\n'); }
|
||||
}
|
||||
|
||||
function setSelectedZoomItem(selectedItem) {
|
||||
var name_item = selectedItem.inputId;
|
||||
var ehItem = name_item.indexOf("___") >= 0;
|
||||
var indice = "";
|
||||
if (ehItem){
|
||||
var valores = name_item.split("___");
|
||||
name_item = valores[0];
|
||||
indice = valores[1];
|
||||
}
|
||||
|
||||
if (name_item == "estabelecimento")
|
||||
{ $("#filialDesc").val(selectedItem["CODIGO"]); }
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
.m-t-10 { margin-top: 10px; }
|
||||
.m-t-15 { margin-top: 15px; }
|
||||
.text-right { text-align: right; }
|
||||
Reference in New Issue
Block a user