$(function () { const isPurchase = $('#is_compra').val() === '1'; if (isPurchase) { return; } const state = {}; const trackable = [1, 2]; let activeKey = null; const globalSelections = new Map(); const $modal = $('#modal-imei-sale'); const $table = $('#imei-sale-table tbody'); const $feedback = $('#imei-sale-feedback'); const $payloadInput = $('#sale_imeis_payload'); const $form = $('#form-nfe'); $('#inp-local_id').on('change', function () { Object.keys(state).forEach((key) => { releaseImeis(state[key].imeis || []); state[key].imeis = []; const row = getRowByKey(key); if (row) { updateBadge(row); } }); }); window.handleSaleProductSelection = function (row, product) { const key = getRowKey(row); ensureState(key); if (state[key].product_id && state[key].product_id !== product.id) { releaseImeis(state[key].imeis); state[key].imeis = []; } state[key].product_id = product.id; state[key].tracking = parseInt(product.tracking_type ?? 0, 10); if (requiresTracking(state[key].tracking)) { showButton(row); } else { hideButton(row); state[key].imeis = []; } updateBadge(row); }; syncRowKeys(); $(document).on('click', '.btn-add-tr-nfe', function () { setTimeout(syncRowKeys, 200); }); $(document).on('click', '.btn-remove-tr', function () { const row = $(this).closest('tr'); const key = getRowKey(row); releaseImeis(state[key]?.imeis || []); delete state[key]; setTimeout(syncRowKeys, 200); }); $(document).on('click', '.btn-manage-imei', function () { const row = $(this).closest('tr'); const key = getRowKey(row); ensureState(key); if (!state[key].product_id) { swal('Atenção', 'Selecione o produto antes de escolher os IMEIs/Seriais.', 'warning'); return; } if (!requiresTracking(state[key].tracking)) { swal('Atenção', 'Este produto não exige IMEI/Serial.', 'info'); return; } const branchId = $('#inp-local_id').val(); if (!branchId) { swal('Atenção', 'Selecione o local/filial da venda antes de continuar.', 'warning'); return; } activeKey = key; $table.empty(); $feedback.text('Carregando IMEIs disponíveis...'); $.get(path_url + 'api/imei-units/available', { product_id: state[key].product_id, branch_id: branchId, empresa_id: $('#empresa_id').val() }) .done(function (response) { if (!response.length) { $feedback.text('Nenhum IMEI/Serial disponível neste local.'); return; } renderAvailable(response, key); }) .fail(function () { $feedback.text('Não foi possível carregar os IMEIs disponíveis.'); }); $modal.modal('show'); }); $('#btn-save-imei-sale').on('click', function () { persistSaleSelection(); }); $(document).on('input blur', '.qtd', function () { updateBadge($(this).closest('tr')); }); $form.on('submit', function (e) { if (!validateBeforeSubmit()) { e.preventDefault(); return false; } const payload = buildPayload(); if (payload === null) { e.preventDefault(); return false; } if (payload.length) { $payloadInput.val(JSON.stringify(payload)); } else { $payloadInput.val(''); } return true; }); function renderAvailable(units, key) { $table.empty(); const selectedIds = new Set(state[key].imeis.map((item) => item.id)); units.forEach((unit) => { const isSelected = selectedIds.has(unit.id); const disabled = globalSelections.has(unit.id) && globalSelections.get(unit.id) !== key; const branchName = unit.branch ? unit.branch.descricao : ''; const row = ` ${unit.imei_or_serial} ${branchName} `; $table.append(row); }); $feedback.text('Selecione os IMEIs/Seriais desejados.'); } function persistSaleSelection() { if (activeKey === null) { $modal.modal('hide'); return; } const row = getRowByKey(activeKey); const requiredQty = getRowQuantity(row); const selections = []; let hasError = false; $table.find('.imei-sale-check:checked').each(function () { const id = parseInt($(this).val(), 10); const code = $(this).data('code'); selections.push({ id, code }); }); if (selections.length !== requiredQty) { swal('Atenção', `Selecione ${requiredQty} IMEIs/Seriais para este item.`, 'warning'); return; } selections.forEach((item) => { const other = globalSelections.get(item.id); if (other && other !== activeKey) { swal('Atenção', `O IMEI/Serial ${item.code} já foi utilizado em outro item.`, 'warning'); hasError = true; } }); if (hasError) { return; } releaseImeis(state[activeKey].imeis); state[activeKey].imeis = selections; selections.forEach((item) => { globalSelections.set(item.id, activeKey); }); updateBadge(row); activeKey = null; $modal.modal('hide'); } function releaseImeis(items) { items.forEach((item) => { if (globalSelections.get(item.id)) { globalSelections.delete(item.id); } }); } function buildPayload() { const payload = []; let hasError = false; const usedCodes = new Set(); $('.table-produtos tbody tr.dynamic-form').each(function (index) { const row = $(this); const key = getRowKey(row); const productId = row.find('.produto_id').val(); const quantity = getRowQuantity(row); if (!productId) { return; } ensureState(key); if (!requiresTracking(state[key].tracking)) { return; } if (!quantity || quantity < 1) { swal('Atenção', `Informe a quantidade do item ${index + 1}.`, 'warning'); hasError = true; return false; } if (state[key].imeis.length !== quantity) { swal('Atenção', `O item ${index + 1} precisa ter ${quantity} IMEIs/Seriais selecionados.`, 'warning'); hasError = true; return false; } state[key].imeis.forEach((item) => { if (usedCodes.has(item.id)) { swal('Atenção', `O IMEI/Serial ${item.code} foi associado a mais de um item.`, 'warning'); hasError = true; } usedCodes.add(item.id); }); payload.push({ product_id: productId, imei_unit_ids: state[key].imeis.map((item) => item.id), }); }); if (hasError) { return null; } return payload; } function validateBeforeSubmit() { if (!$('.btn-manage-imei').length) { return true; } if (!$('#inp-local_id').val()) { swal('Atenção', 'Selecione o local/filial da venda.', 'warning'); return false; } return true; } function syncRowKeys() { $('.table-produtos tbody tr.dynamic-form').each(function () { const row = $(this); const key = getRowKey(row); ensureState(key); row.attr('data-line', key); row.find('.btn-manage-imei').attr('data-line', key); const initialTracking = row.data('initial-tracking'); const initialProduct = row.data('initial-product'); if (typeof initialProduct !== 'undefined' && initialProduct && !state[key].product_id) { state[key].product_id = initialProduct; } if (typeof initialTracking !== 'undefined' && state[key].tracking === null) { state[key].tracking = parseInt(initialTracking, 10); if (requiresTracking(state[key].tracking)) { showButton(row); } } updateBadge(row); }); } function showButton(row) { row.find('.btn-manage-imei').removeClass('d-none'); } function hideButton(row) { row.find('.btn-manage-imei').addClass('d-none'); } function getRowKey(row) { return row.find('._key').val() ?? row.index(); } function getRowByKey(key) { let target = null; $('.table-produtos tbody tr.dynamic-form').each(function () { if (getRowKey($(this)) == key) { target = $(this); return false; } }); return target; } function updateBadge(row) { const key = getRowKey(row); ensureState(key); const badge = row.find('.count-badge'); const count = state[key].imeis.length; badge.text(count); if (!requiresTracking(state[key].tracking)) { return; } const quantity = getRowQuantity(row); const btn = row.find('.btn-manage-imei'); if (count === quantity && quantity > 0) { btn.removeClass('btn-outline-warning').addClass('btn-outline-secondary'); } else { btn.removeClass('btn-outline-secondary').addClass('btn-outline-warning'); } } function getRowQuantity(row) { const input = row.find('.qtd'); if (!input.length) { return 0; } const value = input.val(); if (!value) { return 0; } if (typeof convertMoedaToFloat === 'function') { return Math.trunc(convertMoedaToFloat(value)); } return parseInt(value.replace(/\D/g, ''), 10) || 0; } function ensureState(key) { if (!state[key]) { state[key] = { product_id: null, tracking: null, imeis: [], }; } } function requiresTracking(value) { return trackable.includes(parseInt(value, 10)); } });