Merge pull request 'funcion/actualizar-canasta-desde-compras' (#39) from funcion/actualizar-canasta-desde-compras into master
Reviewed-on: #39
This commit is contained in:
commit
d4bffd1df8
|
@ -12,6 +12,7 @@ npm-debug.log
|
||||||
yarn-error.log
|
yarn-error.log
|
||||||
.idea
|
.idea
|
||||||
/resources/csv/exports/*.csv
|
/resources/csv/exports/*.csv
|
||||||
|
/resources/csv/canastas/*.csv
|
||||||
/public/css/
|
/public/css/
|
||||||
/public/js/
|
/public/js/
|
||||||
/public/mix-manifest.json
|
/public/mix-manifest.json
|
||||||
|
|
|
@ -0,0 +1,11 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App;
|
||||||
|
|
||||||
|
use Illuminate\Database\Eloquent\Model;
|
||||||
|
|
||||||
|
class CanastaLog extends Model
|
||||||
|
{
|
||||||
|
protected $fillable = ["path", "descripcion"];
|
||||||
|
protected $table = "carga_de_canastas";
|
||||||
|
}
|
|
@ -0,0 +1,151 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Helpers;
|
||||||
|
|
||||||
|
use App\Producto;
|
||||||
|
use App\Proveedor;
|
||||||
|
use App\CanastaLog;
|
||||||
|
use DatabaseSeeder;
|
||||||
|
use Illuminate\Support\Arr;
|
||||||
|
use Illuminate\Support\Facades\DB;
|
||||||
|
use Illuminate\Support\Str;
|
||||||
|
use League\Csv\Reader;
|
||||||
|
|
||||||
|
class CanastaHelper
|
||||||
|
{
|
||||||
|
const FILA_HEADER = "Tipo";
|
||||||
|
const ULTIMA_FILA = "TOTAL";
|
||||||
|
const ARCHIVO_SUBIDO = 'Archivo subido';
|
||||||
|
const CANASTA_CARGADA = 'Canasta cargada';
|
||||||
|
|
||||||
|
public static function guardarCanasta($data, $path): string {
|
||||||
|
$nombre = $data->getClientOriginalName();
|
||||||
|
|
||||||
|
$data->move(resource_path($path), $nombre);
|
||||||
|
|
||||||
|
self::log($path . $nombre, self::ARCHIVO_SUBIDO);
|
||||||
|
|
||||||
|
return $nombre;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function cargarCanasta($archivo) {
|
||||||
|
self::limpiarTablas();
|
||||||
|
|
||||||
|
$csv = Reader::createFromPath(resource_path($archivo), 'r');
|
||||||
|
$csv->setDelimiter("|");
|
||||||
|
$iHeader = self::obtenerIndiceDeHeader($csv);
|
||||||
|
$csv->setHeaderOffset($iHeader);
|
||||||
|
$registros = $csv->getRecords();
|
||||||
|
|
||||||
|
$toInsert = [];
|
||||||
|
$categoria = '';
|
||||||
|
foreach($registros as $i => $registro){
|
||||||
|
//filas que están arriba del header
|
||||||
|
if ($i <= $iHeader){
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
//finalizar
|
||||||
|
if ($registro[self::FILA_HEADER] == self::ULTIMA_FILA) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
//filas que no tienen tipo
|
||||||
|
if (!Arr::has($registro,self::FILA_HEADER)|| trim($registro[self::FILA_HEADER]) == ''){
|
||||||
|
var_dump("no hay tipo en la fila " . $i);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
//saltear bono de transporte
|
||||||
|
if ($registro[self::FILA_HEADER] == "T"){
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
//obtener categoria
|
||||||
|
if ($registro['Producto'] == '') {
|
||||||
|
//es la pregunta de la copa?
|
||||||
|
if (Str::contains($registro[self::FILA_HEADER],"¿")) { continue; }
|
||||||
|
$categoria = $registro[self::FILA_HEADER];
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
//completar producto
|
||||||
|
$toInsert[] = [
|
||||||
|
'fila' => $i,
|
||||||
|
'categoria' => $categoria,
|
||||||
|
'nombre' => trim(str_replace('*', ' ',$registro['Producto'])),
|
||||||
|
'precio' => $registro['Precio'],
|
||||||
|
'proveedor_id' => self::obtenerProveedor($registro['Producto']),
|
||||||
|
'bono' => $registro[self::FILA_HEADER] == "B",
|
||||||
|
'requiere_notas'=> $registro[self::FILA_HEADER] =="PTC",
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (array_chunk($toInsert,DatabaseSeeder::CHUNK_SIZE) as $chunk) {
|
||||||
|
DB::table('productos')->insert($chunk);
|
||||||
|
}
|
||||||
|
|
||||||
|
self::agregarBonoBarrial();
|
||||||
|
|
||||||
|
self::log($archivo, self::CANASTA_CARGADA);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static function obtenerIndiceDeHeader($csv){
|
||||||
|
$registros = $csv->getRecords();
|
||||||
|
$iheader = 0;
|
||||||
|
foreach ($registros as $i => $registro){
|
||||||
|
if (strtolower($registro[0]) == strtolower(self::FILA_HEADER)) {
|
||||||
|
$iheader = $i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return $iheader;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static function obtenerProveedor($nombre) {
|
||||||
|
$result = null;
|
||||||
|
if (Str::contains($nombre,"*")){
|
||||||
|
$result = Proveedor::firstOrCreate([
|
||||||
|
'nombre' => 'Proveedor de economía solidaria',
|
||||||
|
'economia_solidaria' => 1,
|
||||||
|
'nacional' => 1
|
||||||
|
])->id;
|
||||||
|
}
|
||||||
|
return $result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param $path
|
||||||
|
* @param $descripcion
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
private static function log($path, $descripcion): void
|
||||||
|
{
|
||||||
|
$log = new CanastaLog([
|
||||||
|
'path' => $path,
|
||||||
|
'descripcion' => $descripcion,
|
||||||
|
]);
|
||||||
|
$log->save();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static function limpiarTablas()
|
||||||
|
{
|
||||||
|
DB::delete('delete from producto_subpedido');
|
||||||
|
DB::delete('delete from productos');
|
||||||
|
DB::delete('delete from subpedidos');
|
||||||
|
}
|
||||||
|
|
||||||
|
private static function agregarBonoBarrial()
|
||||||
|
{
|
||||||
|
$categoria = Producto::all()->pluck('categoria')->unique()->flatten()->first(function ($c) { return Str::contains($c, 'BONO'); });
|
||||||
|
DB::table('productos')->insert([
|
||||||
|
'fila' => 420,
|
||||||
|
'nombre' => "Bono barrial",
|
||||||
|
'precio' => 20,
|
||||||
|
'categoria' => $categoria,
|
||||||
|
'bono' => 1,
|
||||||
|
'proveedor_id' => null,
|
||||||
|
'requiere_notas'=> false,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
|
@ -3,10 +3,14 @@
|
||||||
namespace App\Http\Controllers;
|
namespace App\Http\Controllers;
|
||||||
|
|
||||||
use App\GrupoDeCompra;
|
use App\GrupoDeCompra;
|
||||||
|
use App\Helpers\CanastaHelper;
|
||||||
use App\Producto;
|
use App\Producto;
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
|
||||||
class ComprasController
|
class ComprasController
|
||||||
{
|
{
|
||||||
|
const CANASTAS_PATH = 'csv/canastas/';
|
||||||
|
|
||||||
public function indexPedidos() {
|
public function indexPedidos() {
|
||||||
return view('compras_pedidos');
|
return view('compras_pedidos');
|
||||||
}
|
}
|
||||||
|
@ -33,4 +37,23 @@ class ComprasController
|
||||||
{
|
{
|
||||||
return view('auth/compras_login');
|
return view('auth/compras_login');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function cargarCanasta(Request $request)
|
||||||
|
{
|
||||||
|
$request->validate([
|
||||||
|
'data' => 'required|file|mimes:csv,txt|max:2048',
|
||||||
|
]);
|
||||||
|
|
||||||
|
$nombre = CanastaHelper::guardarCanasta($request->file('data'), self::CANASTAS_PATH);
|
||||||
|
CanastaHelper::cargarCanasta(self::CANASTAS_PATH . $nombre);
|
||||||
|
|
||||||
|
return response()->json([
|
||||||
|
'message' => 'Canasta cargada exitosamente',
|
||||||
|
], 200);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function descargarCanastaEjemplo() {
|
||||||
|
$file = resource_path('csv/productos.csv');
|
||||||
|
return response()->download($file);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,33 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
use Illuminate\Database\Migrations\Migration;
|
||||||
|
use Illuminate\Database\Schema\Blueprint;
|
||||||
|
use Illuminate\Support\Facades\Schema;
|
||||||
|
|
||||||
|
class CrearCargaDeCanastas extends Migration
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Run the migrations.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function up()
|
||||||
|
{
|
||||||
|
Schema::create('carga_de_canastas', function (Blueprint $table) {
|
||||||
|
$table->id();
|
||||||
|
$table->string('path');
|
||||||
|
$table->string('descripcion');
|
||||||
|
$table->timestamps();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reverse the migrations.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function down()
|
||||||
|
{
|
||||||
|
Schema::dropIfExists('carga_de_canastas');
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,13 +1,11 @@
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
|
use App\Helpers\CanastaHelper;
|
||||||
use Illuminate\Database\Seeder;
|
use Illuminate\Database\Seeder;
|
||||||
use League\Csv\Reader;
|
|
||||||
use App\Proveedor;
|
|
||||||
|
|
||||||
class CanastaSeeder extends Seeder
|
class CanastaSeeder extends Seeder
|
||||||
{
|
{
|
||||||
const FILA_HEADER = "Tipo";
|
const ARCHIVO_DEFAULT = 'csv/productos.csv';
|
||||||
const ULTIMA_FILA = "TOTAL";
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Run the database seeds.
|
* Run the database seeds.
|
||||||
|
@ -16,83 +14,6 @@ class CanastaSeeder extends Seeder
|
||||||
*/
|
*/
|
||||||
public function run()
|
public function run()
|
||||||
{
|
{
|
||||||
$csv = Reader::createFromPath(resource_path('csv/productos.csv'), 'r');
|
CanastaHelper::cargarCanasta(self::ARCHIVO_DEFAULT);
|
||||||
$csv->setDelimiter("|");
|
|
||||||
$iHeader = $this->obtenerIndiceDeHeader($csv);
|
|
||||||
$csv->setHeaderOffset($iHeader);
|
|
||||||
$registros = $csv->getRecords();
|
|
||||||
|
|
||||||
$toInsert = [];
|
|
||||||
$categoria = '';
|
|
||||||
foreach($registros as $i => $registro){
|
|
||||||
//filas que están arriba del header
|
|
||||||
if ($i <= $iHeader){
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
//finalizar
|
|
||||||
if ($registro[$this::FILA_HEADER] == $this::ULTIMA_FILA){
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
//filas que no tienen tipo
|
|
||||||
if (!Arr::has($registro,$this::FILA_HEADER)|| trim($registro[$this::FILA_HEADER]) == ''){
|
|
||||||
var_dump("no hay tipo en la fila " . $i);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
//saltear bono de transporte
|
|
||||||
if ($registro[$this::FILA_HEADER] == "T"){
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
//obtener categoria
|
|
||||||
if ($registro['Producto'] == '') {
|
|
||||||
//es la pregunta de la copa?
|
|
||||||
if (Str::contains($registro[$this::FILA_HEADER],"¿")) { continue; }
|
|
||||||
$categoria = $registro[$this::FILA_HEADER];
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
//completar producto
|
|
||||||
$toInsert[] = [
|
|
||||||
'fila' => $i,
|
|
||||||
'categoria' => $categoria,
|
|
||||||
'nombre' => trim(str_replace('*', ' ',$registro['Producto'])),
|
|
||||||
'precio' => $registro['Precio'],
|
|
||||||
'proveedor_id' => $this->obtenerProveedor($registro['Producto']),
|
|
||||||
'bono' => $registro[$this::FILA_HEADER] == "B",
|
|
||||||
'requiere_notas'=> $registro[$this::FILA_HEADER] =="PTC",
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach (array_chunk($toInsert,DatabaseSeeder::CHUNK_SIZE) as $chunk)
|
|
||||||
{
|
|
||||||
DB::table('productos')->insert($chunk);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private function obtenerIndiceDeHeader($csv){
|
|
||||||
$registros = $csv->getRecords();
|
|
||||||
$iheader = 0;
|
|
||||||
foreach ($registros as $i => $registro){
|
|
||||||
if (strtolower($registro[0]) == strtolower($this::FILA_HEADER)) {
|
|
||||||
$iheader = $i;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return $iheader;
|
|
||||||
}
|
|
||||||
|
|
||||||
private function obtenerProveedor($nombre) {
|
|
||||||
$result = null;
|
|
||||||
if (Str::contains($nombre,"*")){
|
|
||||||
$result = Proveedor::firstOrCreate([
|
|
||||||
'nombre' => 'Proveedor de economía solidaria',
|
|
||||||
'economia_solidaria' => 1,
|
|
||||||
'nacional' => 1
|
|
||||||
])->id;
|
|
||||||
}
|
|
||||||
return $result;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,7 +32,7 @@ Vue.prototype.$rootMiga = {
|
||||||
Vue.prototype.$settearProducto = function(cantidad, id) {
|
Vue.prototype.$settearProducto = function(cantidad, id) {
|
||||||
Event.$emit("sync-subpedido", this.cant, this.producto.id)
|
Event.$emit("sync-subpedido", this.cant, this.producto.id)
|
||||||
}
|
}
|
||||||
Vue.prototype.$toast = function(mensaje, duration = 1000) {
|
Vue.prototype.$toast = function(mensaje, duration = 2000) {
|
||||||
return window.bulmaToast.toast({
|
return window.bulmaToast.toast({
|
||||||
message: mensaje,
|
message: mensaje,
|
||||||
duration: duration,
|
duration: duration,
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="block ml-3 mr-3 is-max-widescreen is-max-desktop">
|
<div class="block ml-3 mr-3 is-max-widescreen is-max-desktop">
|
||||||
<admin-tabs-secciones></admin-tabs-secciones>
|
<comunes-tabs-secciones :tabs="tabs" :tabInicial="tabActiva"></comunes-tabs-secciones>
|
||||||
<div class="block" id="pedidos-seccion"
|
<div class="block" id="pedidos-seccion"
|
||||||
:class="seccionActiva === 'pedidos-seccion' ? 'is-active' : 'is-hidden'">
|
:class="seccionActiva === 'pedidos-seccion' ? 'is-active' : 'is-hidden'">
|
||||||
<div class="block pb-6" id="pedidos-tabla-y-dropdown" v-show="hayPedidos">
|
<div class="block pb-6" id="pedidos-tabla-y-dropdown" v-show="hayPedidos">
|
||||||
|
@ -34,7 +34,7 @@
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import CaracteristicasOpcionales from "./CaracteristicasOpcionales.vue";
|
import CaracteristicasOpcionales from "./CaracteristicasOpcionales.vue";
|
||||||
import TabsSecciones from "./TabsSecciones.vue";
|
import TabsSecciones from "../comunes/TabsSecciones.vue";
|
||||||
import DropdownDescargar from "./DropdownDescargar.vue";
|
import DropdownDescargar from "./DropdownDescargar.vue";
|
||||||
import TablaPedidos from "./TablaPedidos.vue";
|
import TablaPedidos from "./TablaPedidos.vue";
|
||||||
import TablaBonos from "./TablaBonos.vue";
|
import TablaBonos from "./TablaBonos.vue";
|
||||||
|
@ -52,6 +52,9 @@ export default {
|
||||||
pedidos: [],
|
pedidos: [],
|
||||||
bonosDeTransporte: 0,
|
bonosDeTransporte: 0,
|
||||||
totalBonosBarriales: 0,
|
totalBonosBarriales: 0,
|
||||||
|
tabs: [{ id: "pedidos", nombre: "Pedidos" },
|
||||||
|
{ id: "bonos", nombre: "Bonos" },
|
||||||
|
{ id: "caracteristicas", nombre: "Caracteristicas opcionales" }],
|
||||||
tabActiva: "pedidos",
|
tabActiva: "pedidos",
|
||||||
seccionActiva: "pedidos-seccion",
|
seccionActiva: "pedidos-seccion",
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,7 +6,9 @@ export default {
|
||||||
caracteristica: Object
|
caracteristica: Object
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
gdc: undefined
|
return {
|
||||||
|
gdc: undefined
|
||||||
|
}
|
||||||
},
|
},
|
||||||
watch: {
|
watch: {
|
||||||
'$root.gdc' : {
|
'$root.gdc' : {
|
||||||
|
|
|
@ -1,42 +1,75 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="container is-fluid has-text-centered">
|
<div class="block ml-3 mr-3 is-max-widescreen is-max-desktop">
|
||||||
<div class="block">
|
<comunes-tabs-secciones :tabs="tabs" :tabInicial="tabActiva"></comunes-tabs-secciones>
|
||||||
<div class="field">
|
<div class="block pb-6" id="pedidos-compras-seccion"
|
||||||
<p class="control">
|
:class="seccionActiva === 'pedidos-compras-seccion' ? 'is-active' : 'is-hidden'">
|
||||||
<a href="/compras/pedidos/descargar" class="button">
|
<div class="block" id="pedidos-compras-tabla-y-dropdown">
|
||||||
<span class="icon is-small">
|
<compras-dropdown-descargar>
|
||||||
<i class="fas fa-download"></i>
|
</compras-dropdown-descargar>
|
||||||
</span>
|
|
||||||
<span>Descargar planilla de totales</span>
|
|
||||||
</a>
|
|
||||||
</p>
|
|
||||||
</div>
|
</div>
|
||||||
<div class="field">
|
</div>
|
||||||
<p class="control">
|
<div class="block pb-6" id="canasta-compras-seccion"
|
||||||
<a href="/compras/pedidos/notas" class="button">
|
:class="seccionActiva === 'canasta-compras-seccion' ? 'is-active' : 'is-hidden'">
|
||||||
<span class="icon is-small">
|
<div class="block" id="canasta-compras-seccion">
|
||||||
<i class="fas fa-sticky-note"></i>
|
<article class="message is-warning">
|
||||||
</span>
|
<div class="message-header">
|
||||||
<span>Descargar planilla de notas</span>
|
<p>Formato de la canasta</p>
|
||||||
</a>
|
</div>
|
||||||
</p>
|
<div class="message-body">
|
||||||
</div>
|
<div class="content">
|
||||||
<div class="field">
|
La planilla de la canasta tiene que tener el siguiente formato para que la aplicación la lea correctamente:
|
||||||
<p class="control">
|
<ul>
|
||||||
<a href="/compras/pedidos/transporte" class="button">
|
<li> Los precios deben usar punto y no coma decimal </li>
|
||||||
<span class="icon is-small">
|
<li> El nombre de la columna de precios debe ser "Precio" </li>
|
||||||
<i class="fa fa-truck"></i>
|
<li> Las celdas deben separarse con '|' </li>
|
||||||
</span>
|
<li> No puede haber "enters" en ninguna celda </li>
|
||||||
<span>Descargar planilla de transporte</span>
|
<li> Todos los bonos deben tener tipo 'B' para evitar que paguen transporte </li>
|
||||||
</a>
|
<li> El bono de transporte debe tener tipo 'T' </li>
|
||||||
</p>
|
</ul>
|
||||||
|
<a class="has-text-info" href="/compras/canasta/ejemplo">Planilla de ejemplo.</a>
|
||||||
|
<article class="message is-danger mt-2">
|
||||||
|
<div class="message-body">
|
||||||
|
<div class="content">
|
||||||
|
Cuidado! Cargar una nueva canasta elimina todos los pedidos de la aplicación.
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</article>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</article>
|
||||||
|
<div class="buttons is-right">
|
||||||
|
<compras-canasta-input></compras-canasta-input>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
export default {
|
import TabsSecciones from "../comunes/TabsSecciones.vue";
|
||||||
|
import DropdownDescargar from "./DropdownDescargar.vue";
|
||||||
|
import CanastaInput from "./CanastaInput.vue";
|
||||||
|
|
||||||
|
export default {
|
||||||
|
components: {
|
||||||
|
TabsSecciones,
|
||||||
|
DropdownDescargar,
|
||||||
|
CanastaInput,
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
tabs: [{ id: "pedidos-compras", nombre: "Pedidos" },
|
||||||
|
{ id: "canasta-compras", nombre: "Canasta" }],
|
||||||
|
tabActiva: "pedidos-compras",
|
||||||
|
seccionActiva: "pedidos-compras-seccion",
|
||||||
|
archivo: undefined,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
setSeccionActiva(tabId) {
|
||||||
|
this.tabActiva = tabId;
|
||||||
|
this.seccionActiva = tabId + "-seccion";
|
||||||
|
},
|
||||||
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -0,0 +1,69 @@
|
||||||
|
<template>
|
||||||
|
<div class="block">
|
||||||
|
<div class="file has-name is-right">
|
||||||
|
<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">Subir canasta</span>
|
||||||
|
</span>
|
||||||
|
<span class="file-name" v-if="archivo">
|
||||||
|
{{ 'Cargando ' + archivo.nombre }}
|
||||||
|
</span>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import axios from "axios";
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: "CanastaInput",
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
archivo: null,
|
||||||
|
cargando: false,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
async archivoSubido(event) {
|
||||||
|
const archivo = event.target.files[0];
|
||||||
|
if (archivo && archivo.type === "text/csv") {
|
||||||
|
this.archivo = {data: archivo, nombre: archivo.name};
|
||||||
|
const formData = new FormData();
|
||||||
|
formData.append("data", this.archivo.data);
|
||||||
|
|
||||||
|
try {
|
||||||
|
this.cargando = true;
|
||||||
|
const response = await axios.post("/compras/canasta", formData, {
|
||||||
|
headers: {
|
||||||
|
"Content-Type": "multipart/form-data",
|
||||||
|
},
|
||||||
|
});
|
||||||
|
this.$root.$toast(response.data.message || "Canasta cargada exitosamente");
|
||||||
|
} catch (error) {
|
||||||
|
this.$root.$toast(error.response?.data?.message || "Hubo errores.");
|
||||||
|
} finally {
|
||||||
|
this.cargando = false;
|
||||||
|
this.archivo = null;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
this.$root.$toast("La canasta debe ser .CSV")
|
||||||
|
this.archivo = null;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
|
||||||
|
</style>
|
|
@ -0,0 +1,44 @@
|
||||||
|
<template>
|
||||||
|
<div class="buttons is-right">
|
||||||
|
<div class="dropdown" :class="{'is-active': dropdownActivo}" @mouseleave="dropdownActivo = false">
|
||||||
|
<div class="dropdown-trigger">
|
||||||
|
<button class="button" aria-haspopup="true" aria-controls="dropdown-menu" @click="dropdownActivo = !dropdownActivo">
|
||||||
|
<span class="icon is-small">
|
||||||
|
<i class="fas fa-download"></i>
|
||||||
|
</span>
|
||||||
|
<span>Descargar planillas</span>
|
||||||
|
<span class="icon is-small">
|
||||||
|
<i class="fas fa-angle-down" aria-hidden="true"></i>
|
||||||
|
</span>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<div class="dropdown-menu" id="dropdown-menu" role="menu">
|
||||||
|
<div class="dropdown-content">
|
||||||
|
<a href="/compras/pedidos/descargar" class="dropdown-item">
|
||||||
|
Pedidos por barrio
|
||||||
|
</a>
|
||||||
|
<a href="/compras/pedidos/notas" class="dropdown-item">
|
||||||
|
Notas por barrio
|
||||||
|
</a>
|
||||||
|
<a href="/compras/pedidos/transporte" class="dropdown-item">
|
||||||
|
Transporte por barrio
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
dropdownActivo: false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
|
||||||
|
</style>
|
|
@ -19,23 +19,13 @@
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
export default {
|
export default {
|
||||||
|
props: {
|
||||||
|
tabs: Array,
|
||||||
|
tabInicial: String,
|
||||||
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
tabActiva: "pedidos",
|
tabActiva: this.tabInicial,
|
||||||
tabs: [
|
|
||||||
{
|
|
||||||
id: "pedidos",
|
|
||||||
nombre: "Pedidos"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: "bonos",
|
|
||||||
nombre: "Bonos"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: "caracteristicas",
|
|
||||||
nombre: "Caracteristicas opcionales"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
|
@ -83,4 +83,6 @@ Route::middleware(['compras'])->group( function() {
|
||||||
Route::get('/compras/pedidos/descargar', 'ComprasController@descargarPedidos')->name('compras.pedidos.descargar');
|
Route::get('/compras/pedidos/descargar', 'ComprasController@descargarPedidos')->name('compras.pedidos.descargar');
|
||||||
Route::get('/compras/pedidos/notas', 'ComprasController@descargarNotas')->name('compras.pedidos.descargar');
|
Route::get('/compras/pedidos/notas', 'ComprasController@descargarNotas')->name('compras.pedidos.descargar');
|
||||||
Route::get('/compras/pedidos/transporte', 'ComprasController@descargarTransporte')->name('compras.pedidos.descargar');
|
Route::get('/compras/pedidos/transporte', 'ComprasController@descargarTransporte')->name('compras.pedidos.descargar');
|
||||||
|
Route::post('/compras/canasta', 'ComprasController@cargarCanasta')->name('compras.canasta');
|
||||||
|
Route::get('/compras/canasta/ejemplo', 'ComprasController@descargarCanastaEjemplo')->name('compras.canasta.ejemplo');
|
||||||
});
|
});
|
||||||
|
|
Loading…
Reference in New Issue