feat: importar csv y auditar ediciones
This commit is contained in:
@@ -2,6 +2,10 @@
|
||||
<div>
|
||||
<h1 class="text-h4 mb-4">Inventario y Productos</h1>
|
||||
<v-alert v-if="mensaje" :type="tipoMensaje" variant="tonal" class="mb-4">{{ mensaje }}</v-alert>
|
||||
<v-card class="mb-4" variant="tonal" color="info">
|
||||
<v-card-title><v-icon icon="mdi-file-delimited" class="mr-2" />Importar inventario inicial</v-card-title>
|
||||
<v-card-text><div class="text-body-2 mb-3">CSV con: Nombre de producto, Nombre Productor, precio unitario y cantidad.</div><v-file-input v-model="csvFile" accept=".csv,text/csv" label="Seleccionar CSV" density="compact" prepend-icon="mdi-paperclip" @update:model-value="previsualizarCsv" /><v-alert v-if="previewRows.length" variant="outlined" density="compact" class="mb-3"><div class="text-caption font-weight-bold mb-1">Previsualización</div><div v-for="(row, index) in previewRows" :key="index" class="text-caption text-truncate">{{ row }}</div></v-alert><v-btn :disabled="!csvFile || !previewRows.length" color="info" @click="importarCsv" prepend-icon="mdi-upload">Confirmar importación</v-btn></v-card-text>
|
||||
</v-card>
|
||||
|
||||
<v-row>
|
||||
<v-col cols="12" md="6">
|
||||
@@ -17,7 +21,7 @@
|
||||
</v-col>
|
||||
</v-row>
|
||||
<v-list>
|
||||
<v-list-item v-for="p in productores" :key="p.id" :title="p.nombre"></v-list-item>
|
||||
<v-list-item v-for="p in productores" :key="p.id" :title="p.nombre"><template #append><v-btn icon="mdi-pencil" variant="text" size="small" :aria-label="`Editar ${p.nombre}`" @click="editarProductor(p)" /></template></v-list-item>
|
||||
</v-list>
|
||||
</v-card-text>
|
||||
</v-card>
|
||||
@@ -32,7 +36,7 @@
|
||||
<v-text-field v-model.number="precioProd" label="Precio unitario" type="number" density="compact" class="mb-2"></v-text-field>
|
||||
<v-btn @click="crearProducto" color="primary" block>Agregar Producto</v-btn>
|
||||
<v-list class="mt-3">
|
||||
<v-list-item v-for="prod in productos" :key="prod.id" :title="prod.nombrePresentacion" :subtitle="'$' + prod.precioUnitario"></v-list-item>
|
||||
<v-list-item v-for="prod in productos" :key="prod.id" :title="prod.nombrePresentacion" :subtitle="'$' + prod.precioUnitario"><template #append><v-btn icon="mdi-pencil" variant="text" size="small" :aria-label="`Editar ${prod.nombrePresentacion}`" @click="editarProducto(prod)" /></template></v-list-item>
|
||||
</v-list>
|
||||
</v-card-text>
|
||||
</v-card>
|
||||
@@ -63,13 +67,14 @@
|
||||
</v-card>
|
||||
</v-col>
|
||||
</v-row>
|
||||
<v-dialog v-model="dialogoEdicion" max-width="520"><v-card><v-card-title>Editar {{ entidadEdicion === 'PRODUCTOR' ? 'productor' : 'producto' }}</v-card-title><v-card-text><v-text-field v-if="entidadEdicion === 'PRODUCTOR'" v-model="edicionProductor.nombre" label="Nombre" /><template v-else><v-text-field v-model="edicionProducto.nombrePresentacion" label="Nombre / presentación" /><v-text-field v-model.number="edicionProducto.precioUnitario" type="number" label="Precio unitario" /></template><v-divider class="my-3" /><v-text-field v-model="actor" label="Quién realiza el cambio" /><v-textarea v-model="motivo" label="Motivo del cambio" rows="2" /></v-card-text><v-card-actions><v-spacer /><v-btn variant="text" @click="dialogoEdicion = false">Cancelar</v-btn><v-btn color="primary" @click="guardarEdicion">Guardar cambio</v-btn></v-card-actions></v-card></v-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, onMounted } from 'vue';
|
||||
import { db } from '@toldo/data';
|
||||
import { InventarioService } from '@toldo/services';
|
||||
import { InventarioService, ImportInventarioCsvService, EdicionService } from '@toldo/services';
|
||||
|
||||
const invService = new InventarioService();
|
||||
const productores = ref<any[]>([]);
|
||||
@@ -85,7 +90,37 @@ const cantInv2 = ref(0);
|
||||
const recibidoPor = ref('');
|
||||
const mensaje = ref('');
|
||||
const tipoMensaje = ref<'success' | 'error'>('success');
|
||||
const csvFile = ref<File | File[] | null>(null);
|
||||
const previewRows = ref<string[]>([]);
|
||||
const csvService = new ImportInventarioCsvService();
|
||||
const edicionService = new EdicionService();
|
||||
const dialogoEdicion = ref(false);
|
||||
const entidadEdicion = ref<'PRODUCTOR' | 'PRODUCTO'>('PRODUCTOR');
|
||||
const edicionProductor = ref<any>({});
|
||||
const edicionProducto = ref<any>({});
|
||||
const originalEdicion = ref<any>({});
|
||||
const actor = ref('');
|
||||
const motivo = ref('');
|
||||
function avisar(texto: string, tipo: 'success' | 'error' = 'error') { mensaje.value = texto; tipoMensaje.value = tipo; }
|
||||
function editarProductor(productor: any) { entidadEdicion.value = 'PRODUCTOR'; originalEdicion.value = { ...productor }; edicionProductor.value = { ...productor }; actor.value = ''; motivo.value = ''; dialogoEdicion.value = true; }
|
||||
function editarProducto(producto: any) { entidadEdicion.value = 'PRODUCTO'; originalEdicion.value = { ...producto }; edicionProducto.value = { ...producto }; actor.value = ''; motivo.value = ''; dialogoEdicion.value = true; }
|
||||
async function guardarEdicion() {
|
||||
try {
|
||||
if (entidadEdicion.value === 'PRODUCTOR') await edicionService.editarProductor(edicionProductor.value, originalEdicion.value, { modificadoPor: actor.value, motivo: motivo.value });
|
||||
else await edicionService.editarProducto(edicionProducto.value, originalEdicion.value, { modificadoPor: actor.value, motivo: motivo.value });
|
||||
dialogoEdicion.value = false; await cargar(); avisar('Cambio guardado y auditado.', 'success');
|
||||
} catch (error: any) { avisar(error.message); }
|
||||
}
|
||||
async function importarCsv() {
|
||||
const archivo = Array.isArray(csvFile.value) ? csvFile.value[0] : csvFile.value;
|
||||
if (!archivo) return;
|
||||
try { const resultado = await csvService.importar(await archivo.text()); csvFile.value = null; await cargar(); avisar(`Importación finalizada: ${resultado.creados} creados, ${resultado.movimientos} movimientos, ${resultado.errores.length} errores.`, resultado.errores.length ? 'error' : 'success'); }
|
||||
catch (error: any) { avisar(error.message); }
|
||||
}
|
||||
async function previsualizarCsv() {
|
||||
const archivo = Array.isArray(csvFile.value) ? csvFile.value[0] : csvFile.value;
|
||||
previewRows.value = archivo ? (await archivo.text()).split(/\r?\n/).filter((linea) => linea.trim()).slice(0, 6) : [];
|
||||
}
|
||||
|
||||
async function cargar() {
|
||||
productores.value = await db.productores.toArray();
|
||||
|
||||
Reference in New Issue
Block a user