$(function () { const itemsState = {}; const trackableTypes = [1, 2]; let rowIndex = 0; let activeRowIndex = null; const trackingLabels = window.stockEntryConfig?.trackingLabels || { 0: "Sem controle", 1: "Nº de Série", 2: "IMEI", 3: "Grade (cor/tamanho)", }; const $itemsTable = $("#items-table tbody"); const $imeiModal = $("#modal-imei"); const $imeiTable = $("#imei-table tbody"); addItemRow(); $("#btn-add-item").on("click", function () { addItemRow(); }); $("#btn-submit-entry").on("click", function () { submitEntry(); }); $("#modal-imei-add-row").on("click", function () { appendImeiRow(""); }); $("#btn-save-imei").on("click", function () { persistImeiModal(); }); $imeiTable.on("click", ".btn-remove-imei", function () { $(this).closest("tr").remove(); if ($imeiTable.find("tr").length === 0) { appendImeiRow(""); } }); $itemsTable.on("click", ".btn-remove-item", function () { const index = $(this).data("index"); delete itemsState[index]; $(this).closest("tr").remove(); if ($itemsTable.find("tr").length === 0) { addItemRow(); } }); $itemsTable.on("click", ".btn-manage-imei", function () { const index = $(this).data("index"); openImeiModal(index); }); $itemsTable.on("change", ".quantity-input", function () { const index = $(this).data("index"); const quantity = parseInt($(this).val(), 10) || 0; if (!itemsState[index]) return; const btn = getRow(index).find(".btn-manage-imei"); if ( requiresImei(itemsState[index].tracking_type) && itemsState[index].imeis.length !== quantity ) { btn.removeClass("btn-outline-secondary").addClass( "btn-outline-warning" ); } else { btn.removeClass("btn-outline-warning").addClass( "btn-outline-secondary" ); } updateImeiBadge(index); }); $itemsTable.on("select2:select", ".produto-select", function () { const index = $(this).data("index"); const productId = $(this).val(); fetchProductData(index, productId); }); $itemsTable.on("select2:clear", ".produto-select", function () { const index = $(this).data("index"); itemsState[index] = { imeis: [], tracking_type: null, product_id: null, }; const row = getRow(index); row.find(".btn-manage-imei").addClass("d-none"); row.find(".tracking-label").text(""); row.find(".count-badge").text("0"); }); function addItemRow() { const index = rowIndex++; itemsState[index] = { imeis: [], tracking_type: null, product_id: null, }; const row = `
`; $itemsTable.append(row); initProdutoSelect(index); } function initProdutoSelect(index) { const $select = getRow(index).find(".produto-select"); $select.select2({ minimumInputLength: 2, language: "pt-BR", placeholder: "Digite para buscar o produto", width: "100%", ajax: { cache: true, url: path_url + "api/produtos", dataType: "json", data: function (params) { return { pesquisa: params.term, empresa_id: $("#empresa_id").val(), usuario_id: $("#usuario_id").val(), }; }, processResults: function (response) { const results = []; $.each(response, function (_, item) { const option = { id: item.id, text: item.nome, }; if (item.codigo_variacao) { option.codigo_variacao = item.codigo_variacao; } results.push(option); }); return { results }; }, }, allowClear: true, }); } function fetchProductData(index, productId) { if (!productId) return; $.get(path_url + "api/produtos/find", { produto_id: productId, usuario_id: $("#usuario_id").val(), }) .done(function (product) { const trackingType = parseInt(product.tracking_type ?? 0, 10); const row = getRow(index); itemsState[index] = itemsState[index] || { imeis: [] }; itemsState[index].product_id = product.id; itemsState[index].tracking_type = trackingType; const requires = requiresImei(trackingType); const manageBtn = row.find(".btn-manage-imei"); row.find(".tracking-label").text( trackingLabels[trackingType] || "" ); if (requires) { manageBtn.removeClass("d-none"); } else { manageBtn.addClass("d-none"); itemsState[index].imeis = []; manageBtn .removeClass("btn-outline-warning") .addClass("btn-outline-secondary"); } updateImeiBadge(index); }) .fail(function () { swal( "Erro", "Não foi possível carregar o produto selecionado.", "error" ); }); } function requiresImei(trackingType) { return trackableTypes.includes(parseInt(trackingType, 10)); } function openImeiModal(index) { const state = itemsState[index]; if (!state || !requiresImei(state.tracking_type)) { swal( "Atenção", "Este item não requer controle por IMEI/Serial.", "info" ); return; } activeRowIndex = index; $imeiTable.empty(); const quantity = parseInt(getRow(index).find(".quantity-input").val(), 10) || 1; const currentImeis = state.imeis || []; const totalRows = Math.max(quantity, currentImeis.length || 1); for (let i = 0; i < totalRows; i++) { appendImeiRow(currentImeis[i] || ""); } $imeiModal.modal("show"); } function appendImeiRow(value) { const row = ` `; $imeiTable.append(row); } function persistImeiModal() { if (activeRowIndex === null) { $imeiModal.modal("hide"); return; } const inputs = $imeiTable.find(".imei-value"); const imeis = []; const seen = new Set(); let hasError = false; inputs.each(function () { const value = $(this).val().trim(); if (value.length === 0) { return; } if (seen.has(value)) { hasError = true; swal( "Atenção", "Existem IMEIs/Seriais duplicados no formulário.", "warning" ); return false; } seen.add(value); imeis.push(value); }); if (hasError) { return; } itemsState[activeRowIndex].imeis = imeis; updateImeiBadge(activeRowIndex); $imeiModal.modal("hide"); activeRowIndex = null; } function updateImeiBadge(index) { const row = getRow(index); const badge = row.find(".count-badge"); const state = itemsState[index]; const count = state?.imeis?.length || 0; badge.text(count); const quantity = parseInt(row.find(".quantity-input").val(), 10) || 0; const btn = row.find(".btn-manage-imei"); if (requiresImei(state?.tracking_type) && count !== quantity) { btn.removeClass("btn-outline-secondary").addClass( "btn-outline-warning" ); } else { btn.removeClass("btn-outline-warning").addClass( "btn-outline-secondary" ); } } function getRow(index) { return $itemsTable.find(`tr[data-index="${index}"]`); } function submitEntry() { const branchId = $("#branch_id").val(); const companyId = $("#empresa_id").val() || $("#company_fallback_id").val(); if (!branchId) { swal( "Atenção", "Selecione o local/filial para a entrada.", "warning" ); return; } const payload = { company_id: companyId, branch_id: branchId, items: [], }; if (!payload.company_id) { swal( "Atenção", "Não foi possível identificar a empresa ativa.", "warning" ); return; } let hasError = false; $itemsTable.find("tr").each(function (idx) { const index = $(this).data("index"); const productId = $(this).find(".produto-select").val(); const quantity = parseInt( $(this).find(".quantity-input").val(), 10 ); const state = itemsState[index]; if (!productId) { swal( "Atenção", `Selecione o produto na linha ${idx + 1}.`, "warning" ); hasError = true; return false; } if (!quantity || quantity < 1) { swal( "Atenção", `Informe uma quantidade válida na linha ${idx + 1}.`, "warning" ); hasError = true; return false; } const item = { product_id: productId, quantity: quantity, }; if (state && requiresImei(state.tracking_type)) { if (!state.imeis || state.imeis.length !== quantity) { swal( "Atenção", `A linha ${ idx + 1 } precisa ter ${quantity} IMEIs/Seriais cadastrados.`, "warning" ); hasError = true; return false; } item.imeis = state.imeis; } payload.items.push(item); }); if (hasError) { return; } if (payload.items.length === 0) { swal( "Atenção", "Informe ao menos um item para a entrada.", "warning" ); return; } $("#btn-submit-entry").prop("disabled", true); $.ajax({ url: path_url + "api/stock-entries", method: "POST", contentType: "application/json", data: JSON.stringify(payload), headers: { "X-CSRF-TOKEN": $('meta[name="csrf-token"]').attr("content"), }, }) .done(function (response) { swal( "Sucesso", response.message || "Entrada registrada com sucesso.", "success" ); resetForm(); }) .fail(function (xhr) { const errors = xhr.responseJSON?.errors; let message = xhr.responseJSON?.message || "Não foi possível registrar a entrada."; if (errors) { const firstKey = Object.keys(errors)[0]; if (errors[firstKey] && errors[firstKey].length > 0) { message = errors[firstKey][0]; } } swal("Erro", message, "error"); }) .always(function () { $("#btn-submit-entry").prop("disabled", false); }); } function resetForm() { $itemsTable.empty(); Object.keys(itemsState).forEach((key) => delete itemsState[key]); rowIndex = 0; addItemRow(); } });