Subir saldos como csv
This commit is contained in:
parent
eee23082db
commit
665ab517fb
4 changed files with 154 additions and 1 deletions
|
@ -8,10 +8,14 @@ use App\Producto;
|
||||||
use Illuminate\Http\JsonResponse;
|
use Illuminate\Http\JsonResponse;
|
||||||
use Illuminate\Http\Request;
|
use Illuminate\Http\Request;
|
||||||
use Symfony\Component\HttpFoundation\BinaryFileResponse;
|
use Symfony\Component\HttpFoundation\BinaryFileResponse;
|
||||||
|
use League\Csv\Reader;
|
||||||
|
use DatabaseSeeder;
|
||||||
|
|
||||||
class ComisionesController
|
class ComisionesController
|
||||||
{
|
{
|
||||||
const CANASTAS_PATH = 'csv/canastas/';
|
const CANASTAS_PATH = 'csv/canastas/';
|
||||||
|
const BARRIO = "Barrio";
|
||||||
|
const SALDO = "Saldo";
|
||||||
|
|
||||||
public function show()
|
public function show()
|
||||||
{
|
{
|
||||||
|
@ -67,4 +71,36 @@ class ComisionesController
|
||||||
$file = storage_path('csv/productos.csv');
|
$file = storage_path('csv/productos.csv');
|
||||||
return response()->download($file);
|
return response()->download($file);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function cargarSaldos(Request $request): JsonResponse
|
||||||
|
{
|
||||||
|
$request->validate([
|
||||||
|
'data' => 'required|file|mimes:csv,txt|max:2048',
|
||||||
|
]);
|
||||||
|
|
||||||
|
$file = $request->file('data')->getPathname();
|
||||||
|
$csv = Reader::createFromPath($file, 'r');
|
||||||
|
try {
|
||||||
|
$csv->setDelimiter("|");
|
||||||
|
$csv->setEnclosure("'");
|
||||||
|
$csv->setHeaderOffset(0);
|
||||||
|
$records = $csv->getRecords();
|
||||||
|
} catch (InvalidArgument|Exception $e) {
|
||||||
|
Log::error($e->getMessage());
|
||||||
|
return response()->json([
|
||||||
|
'message' => 'No se pudo leer el csv',
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ($records as $record) {
|
||||||
|
$barrio = $record[self::BARRIO];
|
||||||
|
$saldo = $record[self::SALDO];
|
||||||
|
GrupoDeCompra::where('nombre', $barrio)
|
||||||
|
->update(['saldo' => $saldo]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return response()->json([
|
||||||
|
'message' => 'Saldos cargados exitosamente',
|
||||||
|
]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -46,7 +46,38 @@
|
||||||
:class="seccionActiva === 'saldos-comisiones-seccion' ? 'is-active' : 'is-hidden'"
|
:class="seccionActiva === 'saldos-comisiones-seccion' ? 'is-active' : 'is-hidden'"
|
||||||
>
|
>
|
||||||
<div class="block" id="saldos-comisiones-seccion">
|
<div class="block" id="saldos-comisiones-seccion">
|
||||||
<table class="table">
|
<article class="message is-warning">
|
||||||
|
<div class="message-header">
|
||||||
|
<p>
|
||||||
|
<button class="icon" aria-label="foldout" @click="toggleSaldosFileDialog">
|
||||||
|
<i class="fa" :class="show_saldos_file_dialog ? 'fa-arrow-up' : 'fa-arrow-down'"></i>
|
||||||
|
</button>
|
||||||
|
Cargar saldos
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<div class="message-body" v-if="show_saldos_file_dialog">
|
||||||
|
<div class="content">
|
||||||
|
La planilla de saldos tiene que tener el siguiente formato para que la aplicación la lea correctamente:
|
||||||
|
<ul>
|
||||||
|
<li>Los valores deben usar punto y no coma decimal</li>
|
||||||
|
<li>El nombre de las columnas deben ser "Barrio" y "Saldo"</li>
|
||||||
|
<li>Las celdas deben separarse con '|'</li>
|
||||||
|
<li>No puede haber "enters" en ninguna celda</li>
|
||||||
|
<li>El nombre de los barrios debe estar exactamente igual que como están configurados en esta aplicacaión</li>
|
||||||
|
</ul>
|
||||||
|
<article class="message is-danger mt-2">
|
||||||
|
<div class="message-body">
|
||||||
|
<div class="content">
|
||||||
|
Cargar un archivo de saldos sólo reemplazará los saldos de los barrios presentes en la tabla.
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</article>
|
||||||
|
</div>
|
||||||
|
<input-file-button text="Subir archivo" @archivo-subido="saldosSubido" />
|
||||||
|
</div>
|
||||||
|
</article>
|
||||||
|
|
||||||
|
<table class="table container">
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th>Barrio</th>
|
<th>Barrio</th>
|
||||||
|
@ -83,6 +114,7 @@
|
||||||
import TabsSecciones from "../comunes/TabsSecciones.vue";
|
import TabsSecciones from "../comunes/TabsSecciones.vue";
|
||||||
import DropdownDescargar from "./DropdownDescargar.vue";
|
import DropdownDescargar from "./DropdownDescargar.vue";
|
||||||
import CanastaInput from "./CanastaInput.vue";
|
import CanastaInput from "./CanastaInput.vue";
|
||||||
|
import InputFileButton from "../comunes/InputFileButton.vue";
|
||||||
import { mapActions, mapState } from "vuex";
|
import { mapActions, mapState } from "vuex";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
|
@ -104,6 +136,7 @@ export default {
|
||||||
seccionActiva: "pedidos-comisiones-seccion",
|
seccionActiva: "pedidos-comisiones-seccion",
|
||||||
archivo: undefined,
|
archivo: undefined,
|
||||||
saldo_modificado: {},
|
saldo_modificado: {},
|
||||||
|
show_saldos_file_dialog: false,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
@ -112,6 +145,7 @@ export default {
|
||||||
this.seccionActiva = tabId + "-seccion";
|
this.seccionActiva = tabId + "-seccion";
|
||||||
},
|
},
|
||||||
...mapActions('comisiones', ['getGruposDeCompra', 'setSaldo']),
|
...mapActions('comisiones', ['getGruposDeCompra', 'setSaldo']),
|
||||||
|
...mapActions('ui',["toast"]),
|
||||||
async confirmar_saldo(gdc_id) {
|
async confirmar_saldo(gdc_id) {
|
||||||
var saldo = this.getSaldo(gdc_id);
|
var saldo = this.getSaldo(gdc_id);
|
||||||
await this.setSaldo({
|
await this.setSaldo({
|
||||||
|
@ -135,6 +169,32 @@ export default {
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
},
|
},
|
||||||
|
async saldosSubido(event) {
|
||||||
|
var archivo = event.archivo;
|
||||||
|
if (archivo.type === "text/csv") {
|
||||||
|
const formData = new FormData();
|
||||||
|
formData.append("data", archivo);
|
||||||
|
try {
|
||||||
|
const response = await axios.post("/comisiones/saldos", formData, {
|
||||||
|
headers: {
|
||||||
|
"Content-Type": "multipart/form-data",
|
||||||
|
},
|
||||||
|
});
|
||||||
|
this.getGruposDeCompra();
|
||||||
|
this.toast({ mensaje: (response.data.message || "Canasta cargada exitosamente") });
|
||||||
|
} catch (error) {
|
||||||
|
console.log(error);
|
||||||
|
this.toast({ mensaje: (error.response?.data?.message || "Hubo errores.") });
|
||||||
|
}
|
||||||
|
event.component.cargando = false;
|
||||||
|
} else {
|
||||||
|
this.toast("El archivo debe ser .CSV");
|
||||||
|
event.component.cargando = false;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
toggleSaldosFileDialog() {
|
||||||
|
this.show_saldos_file_dialog = !this.show_saldos_file_dialog;
|
||||||
|
},
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
...mapState('comisiones', [
|
...mapState('comisiones', [
|
||||||
|
|
56
resources/js/components/comunes/InputFileButton.vue
Normal file
56
resources/js/components/comunes/InputFileButton.vue
Normal file
|
@ -0,0 +1,56 @@
|
||||||
|
<template>
|
||||||
|
<div class="file has-name">
|
||||||
|
<label class="file-label">
|
||||||
|
<input
|
||||||
|
class="file-input"
|
||||||
|
type="file"
|
||||||
|
name="canasta"
|
||||||
|
@change="archivoSubido"
|
||||||
|
/>
|
||||||
|
<span class="file-cta">
|
||||||
|
<span class="file-icon">
|
||||||
|
<i class="fas fa-cloud-upload-alt"></i>
|
||||||
|
</span>
|
||||||
|
<span class="file-label">{{ text }}</span>
|
||||||
|
</span>
|
||||||
|
<span class="file-name" v-if="cargando">
|
||||||
|
{{ 'Cargando ' + archivo.nombre }}
|
||||||
|
</span>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
name: "InputFileButton",
|
||||||
|
props: {
|
||||||
|
text: {
|
||||||
|
type: String,
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
archivo: null,
|
||||||
|
cargando: false,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
archivoSubido(event) {
|
||||||
|
const archivo = event.target.files[0];
|
||||||
|
if (archivo) {
|
||||||
|
this.archivo = { data: archivo, nombre: archivo.name };
|
||||||
|
this.$emit("archivo-subido", {
|
||||||
|
component: this,
|
||||||
|
archivo: archivo
|
||||||
|
});
|
||||||
|
this.cargando = true;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
|
||||||
|
</style>
|
|
@ -54,4 +54,5 @@ Route::middleware(['auth', 'role:comision'])->group( function() {
|
||||||
Route::get('/comisiones/pedidos/pdf', 'ComisionesController@pdf')->name('comisiones.pedidos.pdf');
|
Route::get('/comisiones/pedidos/pdf', 'ComisionesController@pdf')->name('comisiones.pedidos.pdf');
|
||||||
Route::get('/comisiones/canasta/ejemplo', 'ComisionesController@descargarCanastaEjemplo')->name('comisiones.canasta.ejemplo');
|
Route::get('/comisiones/canasta/ejemplo', 'ComisionesController@descargarCanastaEjemplo')->name('comisiones.canasta.ejemplo');
|
||||||
Route::post('/comisiones/canasta', 'ComisionesController@cargarCanasta')->name('comisiones.canasta');
|
Route::post('/comisiones/canasta', 'ComisionesController@cargarCanasta')->name('comisiones.canasta');
|
||||||
|
Route::post('/comisiones/saldos', 'ComisionesController@cargarSaldos')->name('comisiones.canasta');
|
||||||
});
|
});
|
||||||
|
|
Loading…
Add table
Reference in a new issue