Nueva partida cambios - edición
This commit is contained in:
@@ -440,56 +440,70 @@ function editar() {
|
|||||||
if (!($_SESSION['usuario_id'] ?? false)) {
|
if (!($_SESSION['usuario_id'] ?? false)) {
|
||||||
header('Location: /IMPORTADORES/login'); exit;
|
header('Location: /IMPORTADORES/login'); exit;
|
||||||
}
|
}
|
||||||
$id_solicitud = $_GET['id']??null;
|
|
||||||
if(!$id_solicitud||!is_numeric($id_solicitud)) die("❌ ID inválido.");
|
|
||||||
$id_importador=$_SESSION['usuario_id'];
|
|
||||||
$conn=getConnection();
|
|
||||||
|
|
||||||
$stmt=sqlsrv_query($conn,
|
$id_solicitud = $_GET['id']??null;
|
||||||
"SELECT * FROM dbo.solicitud_importacion_factura WHERE id_solicitud=? AND id_importador=?",
|
if(!$id_solicitud || !is_numeric($id_solicitud)) {
|
||||||
[(int)$id_solicitud,$id_importador]
|
die("❌ ID inválido.");
|
||||||
);
|
}
|
||||||
if($stmt===false) die(print_r(sqlsrv_errors(),true));
|
$id_importador = $_SESSION['usuario_id'];
|
||||||
$factura=sqlsrv_fetch_array($stmt,SQLSRV_FETCH_ASSOC);
|
$conn = getConnection();
|
||||||
if(!$factura) die("❌ No autorizado.");
|
|
||||||
if($factura['fecha_factura'] instanceof DateTime)
|
$stmt = sqlsrv_query($conn,"SELECT * FROM dbo.solicitud_importacion_factura WHERE id_solicitud=? AND id_importador=?",[(int)$id_solicitud,$id_importador]);
|
||||||
$factura['fecha_factura']=$factura['fecha_factura']->format('Y-m-d');
|
if($stmt === false) {
|
||||||
|
die(print_r(sqlsrv_errors(),true));
|
||||||
|
}
|
||||||
|
$factura = sqlsrv_fetch_array($stmt,SQLSRV_FETCH_ASSOC);
|
||||||
|
if(!$factura) {
|
||||||
|
die("❌ No autorizado.");
|
||||||
|
}
|
||||||
|
if($factura['fecha_factura'] instanceof DateTime) {
|
||||||
|
$factura['fecha_factura'] = $factura['fecha_factura']->format('Y-m-d');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Solo necesitamos la clave del proveedor actual para JavaScript
|
||||||
|
$proveedor_clave_actual = $factura['proveedor_clave'] ?? '';
|
||||||
|
|
||||||
// Carga selects (igual que crear)
|
// Carga selects (igual que crear)
|
||||||
// Transportistas
|
// Transportistas
|
||||||
$transportistas=[]; $stmtT=sqlsrv_query($conn,"SELECT id_transportista,nombre FROM dbo.transportistas WHERE id_usuario=? AND activo=1 ORDER BY nombre",[$id_importador]);
|
$transportistas = []; $stmtT = sqlsrv_query($conn,"SELECT id_transportista, nombre FROM dbo.transportistas WHERE id_usuario=? AND activo=1 ORDER BY nombre",[$id_importador]);
|
||||||
while($r=sqlsrv_fetch_array($stmtT,SQLSRV_FETCH_ASSOC)) $transportistas[]=$r;
|
while($r = sqlsrv_fetch_array($stmtT,SQLSRV_FETCH_ASSOC)) {
|
||||||
|
$transportistas[] = $r;
|
||||||
|
}
|
||||||
// Choferes
|
// Choferes
|
||||||
$choferes=[]; $stmtC=sqlsrv_query($conn,"SELECT c.id_chofer,c.nombre+' '+c.apellido AS nombre FROM dbo.choferes c JOIN dbo.transportistas t ON c.transportista_id=t.id_transportista WHERE t.id_usuario=? AND c.status=1 ORDER BY c.nombre",[$id_importador]);
|
$choferes = []; $stmtC = sqlsrv_query($conn,"SELECT c.id_chofer, c.nombre+' '+c.apellido AS nombre FROM dbo.choferes c JOIN dbo.transportistas t ON c.transportista_id=t.id_transportista
|
||||||
while($r=sqlsrv_fetch_array($stmtC,SQLSRV_FETCH_ASSOC)) $choferes[]=$r;
|
WHERE t.id_usuario=? AND c.status=1 ORDER BY c.nombre",[$id_importador]);
|
||||||
|
while($r=sqlsrv_fetch_array($stmtC,SQLSRV_FETCH_ASSOC)) {
|
||||||
|
$choferes[] = $r;
|
||||||
|
}
|
||||||
// Paises
|
// Paises
|
||||||
$paises=[]; $stmtP=sqlsrv_query($conn,"SELECT id_pais,nombre FROM dbo.paises ORDER BY nombre");
|
$paises = []; $stmtP = sqlsrv_query($conn,"SELECT id_pais, nombre FROM dbo.paises ORDER BY nombre");
|
||||||
while($r=sqlsrv_fetch_array($stmtP,SQLSRV_FETCH_ASSOC)) $paises[]=$r;
|
while($r=sqlsrv_fetch_array($stmtP,SQLSRV_FETCH_ASSOC)) {
|
||||||
|
$paises[] = $r;
|
||||||
|
}
|
||||||
// Aduanas
|
// Aduanas
|
||||||
$aduanas=[]; $stmtA=sqlsrv_query($conn,"SELECT aduana_seccion,nombre FROM dbo.aduanas ORDER BY aduana_seccion");
|
$aduanas = []; $stmtA = sqlsrv_query($conn,"SELECT DISTINCT RIGHT(REPLICATE('0', 3) + CAST(aduana_seccion AS VARCHAR), 3) AS aduana_seccion, nombre FROM dbo.aduanas ORDER BY aduana_seccion");
|
||||||
while($r=sqlsrv_fetch_array($stmtA,SQLSRV_FETCH_ASSOC)) $aduanas[]=$r;
|
while($r = sqlsrv_fetch_array($stmtA,SQLSRV_FETCH_ASSOC)) {
|
||||||
|
$aduanas[] = $r;
|
||||||
|
}
|
||||||
// Incoterms
|
// Incoterms
|
||||||
$incoterms=[]; $stmtI=sqlsrv_query($conn,"SELECT INCOTERM,DESCESPANOL FROM dbo.gIncoterms ORDER BY INCOTERM");
|
$incoterms = []; $stmtI = sqlsrv_query($conn,"SELECT INCOTERM,DESCESPANOL FROM dbo.gIncoterms ORDER BY INCOTERM");
|
||||||
while($r=sqlsrv_fetch_array($stmtI,SQLSRV_FETCH_ASSOC)) $incoterms[]=$r;
|
while($r = sqlsrv_fetch_array($stmtI,SQLSRV_FETCH_ASSOC)) {
|
||||||
|
$incoterms[] = $r;
|
||||||
|
}
|
||||||
|
// Unidades de Medida
|
||||||
|
$unidades_medida = []; $stmtU = sqlsrv_query($conn, "SELECT id, descripcion FROM dbo.unidades_medida_apendice7 ORDER BY id");
|
||||||
|
while ($r = sqlsrv_fetch_array($stmtU, SQLSRV_FETCH_ASSOC)) {
|
||||||
|
$unidades_medida[] = $r;
|
||||||
|
}
|
||||||
|
|
||||||
// Partidas existentes
|
// Partidas existentes
|
||||||
$partidas=[];
|
$partidas = [];
|
||||||
$stmtPar = sqlsrv_query($conn,
|
$stmtPar = sqlsrv_query($conn,
|
||||||
"SELECT
|
"SELECT id_partida, descripcion, cantidad_comercial, cantidad_tarifa, valor_factura, peso_bruto, unidad_comercial_id, tasa_preferencial
|
||||||
id_partida,
|
FROM dbo.solicitud_importacion_partidas WHERE id_solicitud=? ORDER BY id_partida", [(int)$id_solicitud]);
|
||||||
descripcion,
|
while($r=sqlsrv_fetch_array($stmtPar,SQLSRV_FETCH_ASSOC)) {
|
||||||
cantidad_comercial,
|
$partidas[]=$r;
|
||||||
cantidad_tarifa,
|
}
|
||||||
valor_factura,
|
|
||||||
peso_bruto,
|
|
||||||
unidad_comercial_id,
|
|
||||||
tasa_preferencial
|
|
||||||
FROM dbo.solicitud_importacion_partidas
|
|
||||||
WHERE id_solicitud=?
|
|
||||||
ORDER BY id_partida",
|
|
||||||
[(int)$id_solicitud]
|
|
||||||
);
|
|
||||||
while($r=sqlsrv_fetch_array($stmtPar,SQLSRV_FETCH_ASSOC)) $partidas[]=$r;
|
|
||||||
|
|
||||||
include __DIR__ . '/../../views/solicitud_importacion/editar.php';
|
include __DIR__ . '/../../views/solicitud_importacion/editar.php';
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
<?php include __DIR__ . '/../partials/sidebar_importador.php'; ?>
|
||||||
|
|
||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html lang="es">
|
<html lang="es">
|
||||||
<head>
|
<head>
|
||||||
@@ -48,8 +50,7 @@
|
|||||||
</style>
|
</style>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<?php include __DIR__ . '/../partials/sidebar_importador.php'; ?>
|
|
||||||
<br><br>
|
|
||||||
<div class="content">
|
<div class="content">
|
||||||
<h4>➕ Nueva Solicitud de Importación</h4>
|
<h4>➕ Nueva Solicitud de Importación</h4>
|
||||||
<div class="card p-4 bg-white shadow-sm">
|
<div class="card p-4 bg-white shadow-sm">
|
||||||
@@ -239,33 +240,70 @@
|
|||||||
<script src="https://cdn.jsdelivr.net/npm/select2@4.1.0/dist/js/select2.min.js"></script>
|
<script src="https://cdn.jsdelivr.net/npm/select2@4.1.0/dist/js/select2.min.js"></script>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
// add-partida & validation script
|
// 1) Inicializar Choices para todos los selects excepto proveedor_id
|
||||||
|
document.querySelectorAll('.searchable:not(#proveedor_id)').forEach(el => {
|
||||||
|
new Choices(el, { searchEnabled: true, itemSelectText: '', shouldSort: false });
|
||||||
|
});
|
||||||
|
|
||||||
|
// 2) Cargar proveedores dinámicamente
|
||||||
|
const proveedorEl = document.getElementById('proveedor_id');
|
||||||
|
let proveedorChoices = null;
|
||||||
|
|
||||||
|
fetch('/IMPORTADORES/solicitud_importacion/ajax_proveedores')
|
||||||
|
.then(res => res.ok ? res.json() : Promise.reject(res.status))
|
||||||
|
.then(json => {
|
||||||
|
proveedorEl.innerHTML = '<option value="">-- Selecciona Proveedor --</option>';
|
||||||
|
json.results.forEach(item => {
|
||||||
|
const opt = document.createElement('option');
|
||||||
|
opt.value = item.id;
|
||||||
|
opt.text = item.text;
|
||||||
|
proveedorEl.add(opt);
|
||||||
|
});
|
||||||
|
// destruir instancia previa si existe
|
||||||
|
if (proveedorChoices) proveedorChoices.destroy();
|
||||||
|
proveedorChoices = new Choices(proveedorEl, {
|
||||||
|
searchEnabled: true,
|
||||||
|
itemSelectText: '',
|
||||||
|
shouldSort: false
|
||||||
|
});
|
||||||
|
// seleccionar valor actual
|
||||||
|
const current = '<?= htmlspecialchars($factura['proveedor_id'], ENT_QUOTES) ?>';
|
||||||
|
if (current) {
|
||||||
|
proveedorChoices.setChoiceByValue(current);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch(err => {
|
||||||
|
console.error('Error cargando proveedores:', err);
|
||||||
|
proveedorEl.innerHTML = '<option value="">No fue posible cargar proveedores</option>';
|
||||||
|
});
|
||||||
|
|
||||||
|
// 3) Agregar partida dinámica
|
||||||
document.getElementById('add-partida').addEventListener('click', () => {
|
document.getElementById('add-partida').addEventListener('click', () => {
|
||||||
const tbody = document.querySelector('#tabla-partidas tbody');
|
const tbody = document.querySelector('#tabla-partidas tbody');
|
||||||
const idx = tbody.querySelectorAll('tr').length;
|
const idx = tbody.querySelectorAll('tr').length;
|
||||||
const row = document.createElement('tr');
|
const row = document.createElement('tr');
|
||||||
row.innerHTML = `
|
row.innerHTML = `
|
||||||
<td><input name="partidas[${idx}][descripcion]" class="form-control"></td>
|
<td><input name="partidas[\${idx}][descripcion]" class="form-control"></td>
|
||||||
<td><input name="partidas[${idx}][cantidad_comercial]" type="number" step="0.0001" class="form-control"></td>
|
<td><input name="partidas[\${idx}][cantidad_comercial]" type="number" step="0.0001" class="form-control"></td>
|
||||||
<td><input name="partidas[${idx}][cantidad_tarifa]" type="number" step="0.0001" class="form-control"></td>
|
<td><input name="partidas[\${idx}][cantidad_tarifa]" type="number" step="0.0001" class="form-control"></td>
|
||||||
<td>
|
<td>
|
||||||
<select name="partidas[${idx}][unidad_comercial_id]" class="form-select searchable">
|
<select name="partidas[\${idx}][unidad_comercial_id]" class="form-select searchable">
|
||||||
<option value="">-- Unidad --</option>
|
<option value="">-- Unidad --</option>
|
||||||
<?php foreach($unidades_medida as $um): ?>
|
<?php foreach($unidades_medida as $um): ?>
|
||||||
<option value="<?= htmlspecialchars($um['id']) ?>"><?= htmlspecialchars($um['descripcion']) ?></option>
|
<option value="<?= htmlspecialchars($um['id']) ?>"><?= htmlspecialchars($um['descripcion']) ?></option>
|
||||||
<?php endforeach; ?>
|
<?php endforeach; ?>
|
||||||
</select>
|
</select>
|
||||||
</td>
|
</td>
|
||||||
<td><input name="partidas[${idx}][valor_factura]" type="number" step="0.01" class="form-control valor-partida"></td>
|
<td><input name="partidas[\${idx}][valor_factura]" type="number" step="0.01" class="form-control valor-partida"></td>
|
||||||
<td><input name="partidas[${idx}][peso_bruto]" type="number" step="0.0001" class="form-control"></td>
|
<td><input name="partidas[\${idx}][peso_bruto]" type="number" step="0.0001" class="form-control"></td>
|
||||||
<td>
|
<td>
|
||||||
<select name="partidas[${idx}][tasa_preferencial]" class="form-select searchable">
|
<select name="partidas[\${idx}][tasa_preferencial]" class="form-select searchable">
|
||||||
<option value="">-- Selecciona --</option>
|
<option value="">-- Selecciona --</option>
|
||||||
<option>General</option><option>TLC</option><option>PROSEC</option><option>ALADI</option><option>COMERCIALIZADORA</option>
|
<option>General</option><option>TLC</option><option>PROSEC</option><option>ALADI</option><option>COMERCIALIZADORA</option>
|
||||||
</select>
|
</select>
|
||||||
</td>
|
</td>
|
||||||
<td class="hide"><input name="partidas[${idx}][precio_unitario]" type="number" class="form-control"></td>
|
<td class="hide"><input name="partidas[\${idx}][precio_unitario]" type="number" class="form-control"></td>
|
||||||
<td class="hide"><input name="partidas[${idx}][oma_factura]" class="form-control"></td>
|
<td class="hide"><input name="partidas[\${idx}][oma_factura]" class="form-control"></td>
|
||||||
<td><button type="button" class="btn btn-danger btn-sm remove-row">✖️</button></td>
|
<td><button type="button" class="btn btn-danger btn-sm remove-row">✖️</button></td>
|
||||||
`;
|
`;
|
||||||
tbody.appendChild(row);
|
tbody.appendChild(row);
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
<?php include __DIR__ . '/../partials/sidebar_importador.php'; ?>
|
||||||
|
|
||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html lang="es">
|
<html lang="es">
|
||||||
<head>
|
<head>
|
||||||
@@ -27,8 +29,7 @@
|
|||||||
</style>
|
</style>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<?php include __DIR__ . '/../partials/sidebar_importador.php'; ?>
|
|
||||||
<br><br>
|
|
||||||
<div class="content">
|
<div class="content">
|
||||||
<h4>✏️ Editar Solicitud #<?= (int)$factura['id_solicitud'] ?></h4>
|
<h4>✏️ Editar Solicitud #<?= (int)$factura['id_solicitud'] ?></h4>
|
||||||
<div class="card p-4 bg-white shadow-sm">
|
<div class="card p-4 bg-white shadow-sm">
|
||||||
@@ -50,7 +51,7 @@
|
|||||||
<div class="col-md-3 mb-3">
|
<div class="col-md-3 mb-3">
|
||||||
<label for="proveedor_id" class="form-label">Proveedor</label>
|
<label for="proveedor_id" class="form-label">Proveedor</label>
|
||||||
<select id="proveedor_id" name="proveedor_id" class="form-select searchable" required>
|
<select id="proveedor_id" name="proveedor_id" class="form-select searchable" required>
|
||||||
<option value="">Cargando proveedores…</option>
|
<option value="">Cargando proveedores...</option>
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-md-3 mb-3">
|
<div class="col-md-3 mb-3">
|
||||||
@@ -232,8 +233,8 @@
|
|||||||
|
|
||||||
<!-- Activo -->
|
<!-- Activo -->
|
||||||
<div class="form-check mb-4">
|
<div class="form-check mb-4">
|
||||||
<input id="status" name="status" type="checkbox" class="form-check-input" <?= $factura['status']==1?'checked':'' ?>>
|
<input id="status" name="status" type="checkbox" class="hide form-check-input" <?= $factura['status']==1?'checked':'' ?>>
|
||||||
<label for="status" class="form-check-label">Activo</label>
|
<label for="status" class="hide form-check-label">Activo</label>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<button type="submit" class="btn btn-success">Actualizar</button>
|
<button type="submit" class="btn btn-success">Actualizar</button>
|
||||||
@@ -250,118 +251,148 @@
|
|||||||
<script src="https://cdn.jsdelivr.net/npm/select2@4.1.0/dist/js/select2.min.js"></script>
|
<script src="https://cdn.jsdelivr.net/npm/select2@4.1.0/dist/js/select2.min.js"></script>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
// add-partida & validation script
|
// ✅ 1. INICIALIZACIÓN PRINCIPAL
|
||||||
document.getElementById('add-partida').addEventListener('click', () => {
|
document.addEventListener('DOMContentLoaded', function() {
|
||||||
const tbody = document.querySelector('#tabla-partidas tbody');
|
// Primero cargar proveedores, después inicializar otros selects
|
||||||
const idx = tbody.querySelectorAll('tr').length;
|
cargarProveedores().then(() => {
|
||||||
const row = document.createElement('tr');
|
// Inicializar Choices.js en todos los selects searchable DESPUÉS de cargar proveedores
|
||||||
row.innerHTML = `
|
document.querySelectorAll('.searchable').forEach(el => {
|
||||||
<td><input name="partidas[${idx}][descripcion]" class="form-control"></td>
|
new Choices(el, {
|
||||||
<td><input name="partidas[${idx}][cantidad_comercial]" type="number" step="0.0001" class="form-control"></td>
|
searchEnabled: true,
|
||||||
<td><input name="partidas[${idx}][cantidad_tarifa]" type="number" step="0.0001" class="form-control"></td>
|
itemSelectText: '',
|
||||||
<td>
|
shouldSort: false
|
||||||
<select name="partidas[${idx}][unidad_comercial_id]" class="form-select searchable">
|
});
|
||||||
<option value="">-- Unidad --</option>
|
|
||||||
<?php foreach($unidades_medida as $um): ?>
|
|
||||||
<option value="<?= htmlspecialchars($um['id']) ?>"><?= htmlspecialchars($um['descripcion']) ?></option>
|
|
||||||
<?php endforeach; ?>
|
|
||||||
</select>
|
|
||||||
</td>
|
|
||||||
<td><input name="partidas[${idx}][valor_factura]" type="number" step="0.01" class="form-control valor-partida"></td>
|
|
||||||
<td><input name="partidas[${idx}][peso_bruto]" type="number" step="0.0001" class="form-control"></td>
|
|
||||||
<td>
|
|
||||||
<select name="partidas[${idx}][tasa_preferencial]" class="form-select searchable">
|
|
||||||
<option value="">-- Selecciona --</option>
|
|
||||||
<option>General</option><option>TLC</option><option>PROSEC</option><option>ALADI</option><option>COMERCIALIZADORA</option>
|
|
||||||
</select>
|
|
||||||
</td>
|
|
||||||
<td class="hide"><input name="partidas[${idx}][precio_unitario]" type="number" class="form-control"></td>
|
|
||||||
<td class="hide"><input name="partidas[${idx}][oma_factura]" class="form-control"></td>
|
|
||||||
<td><button type="button" class="btn btn-danger btn-sm remove-row">✖️</button></td>
|
|
||||||
`;
|
|
||||||
tbody.appendChild(row);
|
|
||||||
// Re-inicializar Choices.js en los nuevos selects
|
|
||||||
row.querySelectorAll('.searchable').forEach(el => {
|
|
||||||
new Choices(el, { searchEnabled: true, itemSelectText: '', shouldSort: false });
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
});
|
||||||
|
|
||||||
// Manejador para controlar el overflow al abrir dropdowns
|
// ✅ 2. FUNCIÓN PARA CARGAR PROVEEDORES (CON PROMESA)
|
||||||
document.addEventListener('click', function(e) {
|
function cargarProveedores() {
|
||||||
const tableContainer = document.querySelector('.table-responsive');
|
const proveedorEl = document.getElementById('proveedor_id');
|
||||||
if (!tableContainer) return;
|
const proveedorActual = '<?= htmlspecialchars($proveedor_clave_actual ?? '') ?>';
|
||||||
|
|
||||||
|
return fetch('/IMPORTADORES/solicitud_importacion/ajax_proveedores')
|
||||||
|
.then(res => {
|
||||||
|
if (!res.ok) throw new Error(`HTTP ${res.status}`);
|
||||||
|
return res.json();
|
||||||
|
})
|
||||||
|
.then(json => {
|
||||||
|
// Limpiar el select
|
||||||
|
proveedorEl.innerHTML = '<option value="">-- Selecciona Proveedor --</option>';
|
||||||
|
|
||||||
|
// Agregar todas las opciones
|
||||||
|
if (json.results && json.results.length > 0) {
|
||||||
|
json.results.forEach(item => {
|
||||||
|
const opt = document.createElement('option');
|
||||||
|
opt.value = item.id;
|
||||||
|
opt.textContent = item.text;
|
||||||
|
|
||||||
|
// ✅ Pre-seleccionar si coincide con el proveedor actual
|
||||||
|
if (item.id === proveedorActual && proveedorActual !== '') {
|
||||||
|
opt.selected = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
proveedorEl.appendChild(opt);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log('✅ Proveedores cargados. Proveedor actual:', proveedorActual);
|
||||||
|
})
|
||||||
|
.catch(err => {
|
||||||
|
console.error('❌ Error cargando proveedores:', err);
|
||||||
|
proveedorEl.innerHTML = '<option value="">Error cargando proveedores</option>';
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
if (e.target.closest('.choices__inner')) {
|
// ✅ 3. AGREGAR PARTIDAS
|
||||||
tableContainer.style.overflow = 'visible';
|
document.getElementById('add-partida').addEventListener('click', () => {
|
||||||
} else {
|
const tbody = document.querySelector('#tabla-partidas tbody');
|
||||||
tableContainer.style.overflow = 'auto';
|
const idx = tbody.querySelectorAll('tr').length;
|
||||||
}
|
const row = document.createElement('tr');
|
||||||
|
|
||||||
|
row.innerHTML = `
|
||||||
|
<td><input name="partidas[${idx}][descripcion]" class="form-control"></td>
|
||||||
|
<td><input name="partidas[${idx}][cantidad_comercial]" type="number" step="0.0001" class="form-control"></td>
|
||||||
|
<td><input name="partidas[${idx}][cantidad_tarifa]" type="number" step="0.0001" class="form-control"></td>
|
||||||
|
<td>
|
||||||
|
<select name="partidas[${idx}][unidad_comercial_id]" class="form-select searchable">
|
||||||
|
<option value="">-- Unidad --</option>
|
||||||
|
<?php foreach($unidades_medida as $um): ?>
|
||||||
|
<option value="<?= htmlspecialchars($um['id']) ?>"><?= htmlspecialchars($um['descripcion']) ?></option>
|
||||||
|
<?php endforeach; ?>
|
||||||
|
</select>
|
||||||
|
</td>
|
||||||
|
<td><input name="partidas[${idx}][valor_factura]" type="number" step="0.01" class="form-control valor-partida"></td>
|
||||||
|
<td><input name="partidas[${idx}][peso_bruto]" type="number" step="0.0001" class="form-control"></td>
|
||||||
|
<td>
|
||||||
|
<select name="partidas[${idx}][tasa_preferencial]" class="form-select searchable">
|
||||||
|
<option value="">-- Selecciona --</option>
|
||||||
|
<option>General</option><option>TLC</option><option>PROSEC</option><option>ALADI</option><option>COMERCIALIZADORA</option>
|
||||||
|
</select>
|
||||||
|
</td>
|
||||||
|
<td class="hide"><input name="partidas[${idx}][precio_unitario]" type="number" class="form-control"></td>
|
||||||
|
<td class="hide"><input name="partidas[${idx}][oma_factura]" class="form-control"></td>
|
||||||
|
<td><button type="button" class="btn btn-danger btn-sm remove-row">✖️</button></td>
|
||||||
|
`;
|
||||||
|
|
||||||
|
tbody.appendChild(row);
|
||||||
|
|
||||||
|
// Inicializar Choices.js en los nuevos selects
|
||||||
|
row.querySelectorAll('.searchable').forEach(el => {
|
||||||
|
new Choices(el, {
|
||||||
|
searchEnabled: true,
|
||||||
|
itemSelectText: '',
|
||||||
|
shouldSort: false
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
});
|
||||||
|
|
||||||
document.querySelector('#tabla-partidas tbody').addEventListener('click', e => {
|
// ✅ 4. REMOVER PARTIDAS
|
||||||
if (e.target.matches('.remove-row')) e.target.closest('tr').remove();
|
document.querySelector('#tabla-partidas tbody').addEventListener('click', e => {
|
||||||
});
|
if (e.target.matches('.remove-row')) {
|
||||||
|
// Destruir instancia de Choices.js antes de remover la fila
|
||||||
|
const row = e.target.closest('tr');
|
||||||
|
row.querySelectorAll('.searchable').forEach(el => {
|
||||||
|
if (el.choicesInstance) {
|
||||||
|
el.choicesInstance.destroy();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
row.remove();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
// validate suma partidas == valor_factura
|
// ✅ 5. CONTROLAR OVERFLOW DE LA TABLA
|
||||||
|
document.addEventListener('click', function(e) {
|
||||||
|
const tableContainer = document.querySelector('.table-responsive');
|
||||||
|
if (!tableContainer) return;
|
||||||
|
|
||||||
|
if (e.target.closest('.choices__inner')) {
|
||||||
|
tableContainer.style.overflow = 'visible';
|
||||||
|
} else {
|
||||||
|
tableContainer.style.overflow = 'auto';
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// ✅ 6. VALIDACIÓN DEL FORMULARIO
|
||||||
|
$(document).ready(function() {
|
||||||
$('#solicitudForm').submit(function(e){
|
$('#solicitudForm').submit(function(e){
|
||||||
const total = parseFloat($('#valor_factura').val())||0;
|
const total = parseFloat($('#valor_factura').val()) || 0;
|
||||||
let sum = 0;
|
let sum = 0;
|
||||||
$('.valor-partida').each(function(){ sum += parseFloat($(this).val())||0; });
|
$('.valor-partida').each(function(){
|
||||||
|
sum += parseFloat($(this).val()) || 0;
|
||||||
|
});
|
||||||
|
|
||||||
if(Math.abs(sum - total) > 0.001){
|
if(Math.abs(sum - total) > 0.001){
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
Swal.fire({
|
Swal.fire({
|
||||||
icon:'error',
|
icon: 'error',
|
||||||
title:'Error de validación',
|
title: 'Error de validación',
|
||||||
text:`La suma de partidas (${sum.toFixed(2)}) no coincide con Valor Factura (${total.toFixed(2)}).`
|
text: `La suma de partidas (${sum.toFixed(2)}) no coincide con Valor Factura (${total.toFixed(2)}).`
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<script>
|
|
||||||
// ✅ DIFERENCIA PRINCIPAL: Inicializar Choices.js en partidas existentes
|
|
||||||
document.addEventListener('DOMContentLoaded', function() {
|
|
||||||
// Inicializar Choices.js en selects existentes de partidas (para edición)
|
|
||||||
document.querySelectorAll('#tabla-partidas .searchable').forEach(el => {
|
|
||||||
if (el.id !== 'proveedor_id') {
|
|
||||||
new Choices(el, { searchEnabled: true, itemSelectText: '', shouldSort: false });
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// Inicializar otros selects searchable (excepto proveedor_id que se maneja aparte)
|
|
||||||
document.querySelectorAll('.searchable').forEach(el => {
|
|
||||||
if (el.id !== 'proveedor_id' && !el.closest('#tabla-partidas')) {
|
|
||||||
new Choices(el, { searchEnabled: true, itemSelectText: '', shouldSort: false });
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
// proveedores script - ✅ DIFERENCIA: Pre-seleccionar proveedor existente
|
|
||||||
const proveedorEl = document.getElementById('proveedor_id');
|
|
||||||
const proveedorActual = '<?= htmlspecialchars($factura['proveedor_clave'] ?? '') ?>'; // ← Proveedor actual
|
|
||||||
|
|
||||||
fetch('/IMPORTADORES/solicitud_importacion/ajax_proveedores')
|
|
||||||
.then(res => { if (!res.ok) throw new Error(`HTTP ${res.status}`); return res.json(); })
|
|
||||||
.then(json => {
|
|
||||||
proveedorEl.innerHTML = '<option value="">-- Selecciona Proveedor --</option>';
|
|
||||||
json.results.forEach(item => {
|
|
||||||
const opt = document.createElement('option');
|
|
||||||
opt.value = item.id;
|
|
||||||
opt.text = item.text;
|
|
||||||
// ✅ Pre-seleccionar si coincide con el proveedor actual
|
|
||||||
if (item.id === proveedorActual) {
|
|
||||||
opt.selected = true;
|
|
||||||
}
|
|
||||||
proveedorEl.add(opt);
|
|
||||||
});
|
|
||||||
if (proveedorEl._choice) proveedorEl._choice.destroy();
|
|
||||||
new Choices(proveedorEl, { searchEnabled: true, itemSelectText: '', shouldSort: false });
|
|
||||||
})
|
|
||||||
.catch(err => {
|
|
||||||
console.error('Error cargando proveedores:', err);
|
|
||||||
proveedorEl.innerHTML = '<option value="">No fue posible cargar proveedores</option>';
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
|
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
Reference in New Issue
Block a user