forked from nathalie/pedi2
Merge pull request 'funcion/refactor-general' (#45) from funcion/refactor-general into master
Reviewed-on: nathalie/pedi2#45
This commit is contained in:
commit
78b9d682cc
123 changed files with 4017 additions and 2244 deletions
2
.gitignore
vendored
2
.gitignore
vendored
|
@ -13,6 +13,8 @@ yarn-error.log
|
||||||
.idea
|
.idea
|
||||||
/resources/csv/exports/*.csv
|
/resources/csv/exports/*.csv
|
||||||
/resources/csv/canastas/*.csv
|
/resources/csv/canastas/*.csv
|
||||||
|
/storage/csv/exports/*.csv
|
||||||
|
/storage/csv/canastas/*.csv
|
||||||
/public/css/
|
/public/css/
|
||||||
/public/js/
|
/public/js/
|
||||||
/public/mix-manifest.json
|
/public/mix-manifest.json
|
||||||
|
|
|
@ -11,13 +11,12 @@ use Illuminate\Database\Eloquent\Relations\HasMany;
|
||||||
use Illuminate\Support\Collection;
|
use Illuminate\Support\Collection;
|
||||||
use Illuminate\Support\Facades\DB;
|
use Illuminate\Support\Facades\DB;
|
||||||
use Illuminate\Support\Facades\Log;
|
use Illuminate\Support\Facades\Log;
|
||||||
|
use League\Csv\Exception;
|
||||||
|
|
||||||
class GrupoDeCompra extends Model
|
class GrupoDeCompra extends Model
|
||||||
{
|
{
|
||||||
public $timestamps = false;
|
protected $fillable = ["nombre", "region", "devoluciones_habilitadas", "saldo"];
|
||||||
protected $fillable = ["nombre", "region", "telefono", "correo", "referente_finanzas", "cantidad_de_nucleos", "fila", "devoluciones_habilitadas"];
|
|
||||||
protected $table = 'grupos_de_compra';
|
protected $table = 'grupos_de_compra';
|
||||||
protected $hidden = ['password'];
|
|
||||||
|
|
||||||
public function subpedidos(): HasMany
|
public function subpedidos(): HasMany
|
||||||
{
|
{
|
||||||
|
@ -45,6 +44,14 @@ class GrupoDeCompra extends Model
|
||||||
return $total;
|
return $total;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function totalSinDevoluciones() {
|
||||||
|
$total = 0;
|
||||||
|
foreach ($this->pedidosAprobados() as $subpedido) {
|
||||||
|
$total = $total + $subpedido->totalSinDevoluciones();
|
||||||
|
}
|
||||||
|
return $total;
|
||||||
|
}
|
||||||
|
|
||||||
public function totalBarrial()
|
public function totalBarrial()
|
||||||
{
|
{
|
||||||
$total = 0;
|
$total = 0;
|
||||||
|
@ -63,11 +70,17 @@ class GrupoDeCompra extends Model
|
||||||
return $total;
|
return $total;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function totalATransferir()
|
public function totalDePedido()
|
||||||
{
|
{
|
||||||
return $this->totalCentralesQueNoPaganTransporte()
|
return $this->totalCentralesQueNoPaganTransporte()
|
||||||
+ $this->totalCentralesQuePaganTransporte()
|
+ $this->totalCentralesQuePaganTransporte()
|
||||||
+ $this->totalTransporte();
|
+ $this->totalTransporte()
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function totalATransferir()
|
||||||
|
{
|
||||||
|
return $this->totalDePedido() - $this->saldo;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function totalCentralesQueNoPaganTransporte()
|
public function totalCentralesQueNoPaganTransporte()
|
||||||
|
@ -105,12 +118,13 @@ class GrupoDeCompra extends Model
|
||||||
public function exportarPedidosAPdf()
|
public function exportarPedidosAPdf()
|
||||||
{
|
{
|
||||||
$subpedidos = $this->pedidosAprobados();
|
$subpedidos = $this->pedidosAprobados();
|
||||||
PdfHelper::exportarPedidos($this->nombre . '.pdf', $subpedidos);
|
$fecha = now()->format('Y-m-d');
|
||||||
|
PdfHelper::exportarPedidos($this->nombre . '-' . $fecha . '.pdf', $subpedidos);
|
||||||
}
|
}
|
||||||
|
|
||||||
function pedidoParaPdf(): array
|
function pedidoParaPdf(): array
|
||||||
{
|
{
|
||||||
$productos = $this->productosPedidos(true, true, 'producto_id');
|
$productos = $this->productosPedidos(true, 'producto_id');
|
||||||
$pedido = [];
|
$pedido = [];
|
||||||
$pedido['productos'] = [];
|
$pedido['productos'] = [];
|
||||||
|
|
||||||
|
@ -138,7 +152,8 @@ class GrupoDeCompra extends Model
|
||||||
public static function exportarPedidosBarrialesAPdf()
|
public static function exportarPedidosBarrialesAPdf()
|
||||||
{
|
{
|
||||||
$barrios = GrupoDeCompra::barriosMenosPrueba()->get();
|
$barrios = GrupoDeCompra::barriosMenosPrueba()->get();
|
||||||
PdfHelper::exportarPedidos('pedidos_por_barrio.pdf', $barrios);
|
$fecha = now()->format('Y-m-d');
|
||||||
|
PdfHelper::exportarPedidos('pedidos_por_barrio-' . $fecha . '.pdf', $barrios);
|
||||||
}
|
}
|
||||||
|
|
||||||
static function filaVacia(string $product, int $columns): array
|
static function filaVacia(string $product, int $columns): array
|
||||||
|
@ -151,6 +166,10 @@ class GrupoDeCompra extends Model
|
||||||
}
|
}
|
||||||
|
|
||||||
//Asume que los productos están gruadados en orden de fila
|
//Asume que los productos están gruadados en orden de fila
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
public static function obtenerTemplateDeFilasVacias(int $columns): array
|
public static function obtenerTemplateDeFilasVacias(int $columns): array
|
||||||
{
|
{
|
||||||
$productosFilaID = Producto::productosFilaID();
|
$productosFilaID = Producto::productosFilaID();
|
||||||
|
@ -168,13 +187,20 @@ class GrupoDeCompra extends Model
|
||||||
return $template;
|
return $template;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
public function exportarPedidoEnCSV()
|
public function exportarPedidoEnCSV()
|
||||||
{
|
{
|
||||||
$records = $this->generarColumnaCantidades();
|
$records = $this->generarColumnaCantidades();
|
||||||
|
|
||||||
CsvHelper::generarCsv('csv/exports/' . $this->nombre . '.csv', $records);
|
$fecha = now()->format('Y-m-d');
|
||||||
|
CsvHelper::generarCsv('csv/exports/' . $this->nombre . '-' . $fecha . '.csv', $records);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
public function generarColumnaCantidades(): array
|
public function generarColumnaCantidades(): array
|
||||||
{
|
{
|
||||||
$productos_en_pedido = $this->productosPedidos();
|
$productos_en_pedido = $this->productosPedidos();
|
||||||
|
@ -197,6 +223,9 @@ class GrupoDeCompra extends Model
|
||||||
return $records;
|
return $records;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
public function exportarPedidoConNucleosEnCSV()
|
public function exportarPedidoConNucleosEnCSV()
|
||||||
{
|
{
|
||||||
$productos_en_pedido = $this->productosPedidos();
|
$productos_en_pedido = $this->productosPedidos();
|
||||||
|
@ -229,7 +258,8 @@ class GrupoDeCompra extends Model
|
||||||
}
|
}
|
||||||
array_splice($records, 0, 0, array($nucleos));
|
array_splice($records, 0, 0, array($nucleos));
|
||||||
|
|
||||||
CsvHelper::generarCsv('csv/exports/' . $this->nombre . '-completo.csv', $records);
|
$fecha = now()->format('Y-m-d');
|
||||||
|
CsvHelper::generarCsv('csv/exports/' . $this->nombre . '-completo-' . $fecha . '.csv', $records);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function agregarCantidad($pedido, $id, array $records, $fila, int $i): array
|
public function agregarCantidad($pedido, $id, array $records, $fila, int $i): array
|
||||||
|
@ -260,13 +290,12 @@ class GrupoDeCompra extends Model
|
||||||
return $result;
|
return $result;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function productosPedidos($excluirBarriales = false, $excluirBonos = false, $orderBy = 'producto_nombre'): Collection
|
public function productosPedidos($excluirBonos = false, $orderBy = 'producto_nombre'): Collection
|
||||||
{
|
{
|
||||||
$query = DB::table('pedidos_aprobados')
|
$query = DB::table('pedidos_aprobados')
|
||||||
->where('grupo_de_compra_id', $this->id);
|
->where('grupo_de_compra_id', $this->id)
|
||||||
|
->where('producto_nombre','NOT LIKE','%barrial%');
|
||||||
|
|
||||||
if ($excluirBarriales)
|
|
||||||
$query = $query->where('producto_nombre','NOT LIKE','%barrial%');
|
|
||||||
if ($excluirBonos)
|
if ($excluirBonos)
|
||||||
$query = $query->where('producto_es_bono',false);
|
$query = $query->where('producto_es_bono',false);
|
||||||
|
|
||||||
|
@ -275,4 +304,9 @@ class GrupoDeCompra extends Model
|
||||||
->get()
|
->get()
|
||||||
->keyBy('producto_id');
|
->keyBy('producto_id');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function setSaldo(float $saldo) {
|
||||||
|
$this->saldo = $saldo;
|
||||||
|
$this->save();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,13 +3,13 @@
|
||||||
namespace App\Helpers;
|
namespace App\Helpers;
|
||||||
|
|
||||||
use App\Producto;
|
use App\Producto;
|
||||||
use App\Proveedor;
|
|
||||||
use App\CanastaLog;
|
use App\CanastaLog;
|
||||||
use DatabaseSeeder;
|
use DatabaseSeeder;
|
||||||
use Illuminate\Support\Arr;
|
use Illuminate\Support\Arr;
|
||||||
use Illuminate\Support\Facades\DB;
|
use Illuminate\Support\Facades\DB;
|
||||||
|
use Illuminate\Support\Facades\File;
|
||||||
use Illuminate\Support\Str;
|
use Illuminate\Support\Str;
|
||||||
|
use League\Csv\Exception;
|
||||||
|
|
||||||
class CanastaHelper
|
class CanastaHelper
|
||||||
{
|
{
|
||||||
|
@ -21,76 +21,77 @@ class CanastaHelper
|
||||||
const CANASTA_CARGADA = 'Canasta cargada';
|
const CANASTA_CARGADA = 'Canasta cargada';
|
||||||
const PRODUCTO_TALLE_COLOR = "PTC";
|
const PRODUCTO_TALLE_COLOR = "PTC";
|
||||||
|
|
||||||
|
public static function canastaActual() {
|
||||||
|
$result = [];
|
||||||
|
$log = CanastaLog::where('descripcion', self::CANASTA_CARGADA)
|
||||||
|
->orderBy('created_at', 'desc')
|
||||||
|
->first();
|
||||||
|
$nombre = str_replace(storage_path(), "", $log->path);
|
||||||
|
$nombre = str_replace("/csv/canastas/", "", $nombre);
|
||||||
|
$result["nombre"] = str_replace(".csv", "", $nombre);
|
||||||
|
$result["fecha"] = $log->created_at;
|
||||||
|
return $result;
|
||||||
|
}
|
||||||
|
|
||||||
public static function guardarCanasta($data, $path): string {
|
public static function guardarCanasta($data, $path): string {
|
||||||
|
if (!File::exists(storage_path('csv/canastas'))) {
|
||||||
|
File::makeDirectory(storage_path('csv/canastas'), 0755, true);
|
||||||
|
}
|
||||||
|
|
||||||
$nombre = $data->getClientOriginalName();
|
$nombre = $data->getClientOriginalName();
|
||||||
|
|
||||||
$data->move(resource_path($path), $nombre);
|
$storage_path = storage_path($path);
|
||||||
|
$data->move($storage_path, $nombre);
|
||||||
|
|
||||||
self::log($path . $nombre, self::ARCHIVO_SUBIDO);
|
self::log($storage_path . $nombre, self::ARCHIVO_SUBIDO);
|
||||||
|
|
||||||
return $nombre;
|
return $nombre;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
public static function cargarCanasta($archivo) {
|
public static function cargarCanasta($archivo) {
|
||||||
self::limpiarTablas();
|
self::limpiarTablas();
|
||||||
|
|
||||||
$registros = CsvHelper::getRecords($archivo);
|
$registros = CsvHelper::getRecords($archivo, "No se pudo leer el archivo.");
|
||||||
|
|
||||||
$toInsert = [];
|
$toInsert = [];
|
||||||
$categoria = '';
|
$categoria = '';
|
||||||
|
|
||||||
foreach($registros as $i => $registro) {
|
foreach($registros as $i => $registro) {
|
||||||
// saltear filas que no tienen tipo
|
// saltear bono de transporte y filas que no tienen tipo
|
||||||
if (self::noTieneTipo($registro)) {
|
if (self::noTieneTipo($registro) || $registro[self::TIPO] == "T")
|
||||||
var_dump("no hay tipo en la fila " . $i);
|
|
||||||
continue;
|
continue;
|
||||||
}
|
|
||||||
|
|
||||||
// saltear bono de transporte
|
|
||||||
if ($registro[self::TIPO] == "T"){
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// obtener categoria si no hay producto
|
// obtener categoria si no hay producto
|
||||||
if ($registro[self::PRODUCTO] == '') {
|
if ($registro[self::PRODUCTO] == '') {
|
||||||
// no es la pregunta de la copa?
|
// no es la pregunta de la copa?
|
||||||
if (!Str::contains($registro[self::TIPO],"¿"))
|
if (!Str::contains($registro[self::TIPO],"¿"))
|
||||||
$categoria = $registro[self::TIPO];
|
$categoria = $registro[self::TIPO];
|
||||||
continue;
|
continue; // saltear si es la pregunta de la copa
|
||||||
}
|
}
|
||||||
|
|
||||||
// completar producto
|
// completar producto
|
||||||
$toInsert[] = [
|
$toInsert[] = DatabaseSeeder::addTimestamps([
|
||||||
'fila' => $i,
|
'fila' => $i,
|
||||||
'categoria' => $categoria,
|
'categoria' => $categoria,
|
||||||
'nombre' => trim(str_replace('*', '',$registro[self::PRODUCTO])),
|
'nombre' => trim(str_replace('*', '',$registro[self::PRODUCTO])),
|
||||||
'precio' => $registro[self::PRECIO],
|
'precio' => $registro[self::PRECIO],
|
||||||
'proveedor_id' => self::obtenerProveedor($registro[self::PRODUCTO]),
|
'es_solidario' => Str::contains($registro[self::PRODUCTO],"*"),
|
||||||
'bono' => preg_match(self::REGEX_BONO, $registro[self::TIPO]),
|
'bono' => preg_match(self::REGEX_BONO, $registro[self::TIPO]),
|
||||||
'requiere_notas'=> $registro[self::TIPO] == self::PRODUCTO_TALLE_COLOR,
|
'requiere_notas'=> $registro[self::TIPO] == self::PRODUCTO_TALLE_COLOR,
|
||||||
];
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach (array_chunk($toInsert,DatabaseSeeder::CHUNK_SIZE) as $chunk) {
|
foreach (array_chunk($toInsert,DatabaseSeeder::CHUNK_SIZE) as $chunk)
|
||||||
DB::table('productos')->insert($chunk);
|
Producto::insert($chunk);
|
||||||
}
|
|
||||||
|
|
||||||
self::agregarBonoBarrial();
|
self::agregarBonoBarrial();
|
||||||
|
|
||||||
self::log($archivo, self::CANASTA_CARGADA);
|
self::log($archivo, self::CANASTA_CARGADA);
|
||||||
}
|
}
|
||||||
|
|
||||||
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 $path
|
||||||
* @param $descripcion
|
* @param $descripcion
|
||||||
|
@ -122,13 +123,12 @@ class CanastaHelper
|
||||||
return Str::contains($c, 'BONO');
|
return Str::contains($c, 'BONO');
|
||||||
});
|
});
|
||||||
|
|
||||||
DB::table('productos')->insert([
|
Producto::create([
|
||||||
'fila' => 420,
|
|
||||||
'nombre' => "Bono barrial",
|
'nombre' => "Bono barrial",
|
||||||
'precio' => 20,
|
'precio' => 20,
|
||||||
'categoria' => $categoria,
|
'categoria' => $categoria,
|
||||||
'bono' => 1,
|
'bono' => 1,
|
||||||
'proveedor_id' => null,
|
'es_solidario' => 0,
|
||||||
'requiere_notas'=> false,
|
'requiere_notas'=> false,
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
|
|
||||||
namespace App\Helpers;
|
namespace App\Helpers;
|
||||||
|
|
||||||
|
use Illuminate\Support\Facades\File;
|
||||||
use Illuminate\Support\Facades\Log;
|
use Illuminate\Support\Facades\Log;
|
||||||
use Iterator;
|
use Iterator;
|
||||||
use League\Csv\CannotInsertRecord;
|
use League\Csv\CannotInsertRecord;
|
||||||
|
@ -12,8 +13,11 @@ use League\Csv\Writer;
|
||||||
|
|
||||||
class CsvHelper
|
class CsvHelper
|
||||||
{
|
{
|
||||||
public static function getRecords($filePath): Iterator {
|
/**
|
||||||
$csv = Reader::createFromPath(resource_path($filePath));
|
* @throws Exception
|
||||||
|
*/
|
||||||
|
public static function getRecords($filePath, $message): Iterator {
|
||||||
|
$csv = Reader::createFromPath($filePath);
|
||||||
try {
|
try {
|
||||||
$csv->setDelimiter("|");
|
$csv->setDelimiter("|");
|
||||||
$csv->setEnclosure("'");
|
$csv->setEnclosure("'");
|
||||||
|
@ -21,14 +25,18 @@ class CsvHelper
|
||||||
return $csv->getRecords();
|
return $csv->getRecords();
|
||||||
} catch (InvalidArgument|Exception $e) {
|
} catch (InvalidArgument|Exception $e) {
|
||||||
Log::error($e->getMessage());
|
Log::error($e->getMessage());
|
||||||
return null;
|
throw new Exception($message, $e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function generarCsv($filePath, $contenido, $headers = null): void
|
public static function generarCsv($filePath, $contenido, $headers = null): void
|
||||||
{
|
{
|
||||||
|
if (!File::exists(storage_path('csv/exports'))) {
|
||||||
|
File::makeDirectory(storage_path('csv/exports'), 0755, true);
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
$writer = Writer::createFromPath(resource_path($filePath), 'w');
|
$writer = Writer::createFromPath(storage_path($filePath), 'w');
|
||||||
if ($headers) {
|
if ($headers) {
|
||||||
$writer->insertOne($headers);
|
$writer->insertOne($headers);
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,6 +4,7 @@ namespace App\Helpers;
|
||||||
|
|
||||||
use App\CanastaLog;
|
use App\CanastaLog;
|
||||||
use Illuminate\Support\Facades\Log;
|
use Illuminate\Support\Facades\Log;
|
||||||
|
use League\Csv\Exception;
|
||||||
|
|
||||||
class TransporteHelper
|
class TransporteHelper
|
||||||
{
|
{
|
||||||
|
@ -20,6 +21,9 @@ class TransporteHelper
|
||||||
return self::cantidadTransporte($monto) * self::COSTO_TRANSPORTE;
|
return self::cantidadTransporte($monto) * self::COSTO_TRANSPORTE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
public static function filaTransporte()
|
public static function filaTransporte()
|
||||||
{
|
{
|
||||||
$ultimaCanasta = CanastaLog::where('descripcion', CanastaHelper::CANASTA_CARGADA)
|
$ultimaCanasta = CanastaLog::where('descripcion', CanastaHelper::CANASTA_CARGADA)
|
||||||
|
@ -27,12 +31,14 @@ class TransporteHelper
|
||||||
->pluck('path')
|
->pluck('path')
|
||||||
->first();
|
->first();
|
||||||
|
|
||||||
$registros = CsvHelper::getRecords($ultimaCanasta);
|
$registros = CsvHelper::getRecords($ultimaCanasta, "No se encontró la ultima canasta.");
|
||||||
|
$error = 'No hay fila de tipo T en la planilla: ' . $ultimaCanasta;
|
||||||
|
|
||||||
foreach ($registros as $key => $registro)
|
foreach ($registros as $key => $registro)
|
||||||
if ($registro[CanastaHelper::TIPO] == 'T') return $key;
|
if ($registro[CanastaHelper::TIPO] == 'T')
|
||||||
|
return $key;
|
||||||
|
|
||||||
Log::error('No hay fila de tipo T en la planilla: ' . $ultimaCanasta);
|
Log::error($error);
|
||||||
return null;
|
throw new Exception($error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,13 +3,13 @@
|
||||||
namespace App\Http\Controllers;
|
namespace App\Http\Controllers;
|
||||||
|
|
||||||
use App\GrupoDeCompra;
|
use App\GrupoDeCompra;
|
||||||
use Symfony\Component\HttpFoundation\BinaryFileResponse;
|
use League\Csv\Exception;
|
||||||
|
|
||||||
class AdminController extends Controller
|
class AdminController extends Controller
|
||||||
{
|
{
|
||||||
public function show()
|
public function show()
|
||||||
{
|
{
|
||||||
return view('auth/admin_login');
|
return view('auth/login');
|
||||||
}
|
}
|
||||||
|
|
||||||
public function index() {
|
public function index() {
|
||||||
|
@ -20,17 +20,37 @@ class AdminController extends Controller
|
||||||
$gdc->exportarPedidosAPdf();
|
$gdc->exportarPedidosAPdf();
|
||||||
}
|
}
|
||||||
|
|
||||||
public function exportarPedidoACSV(GrupoDeCompra $gdc): BinaryFileResponse
|
public function exportarPedidoACSV(GrupoDeCompra $gdc)
|
||||||
{
|
{
|
||||||
|
try {
|
||||||
$gdc->exportarPedidoEnCSV();
|
$gdc->exportarPedidoEnCSV();
|
||||||
$file = resource_path('csv/exports/'.$gdc->nombre.'.csv');
|
} catch (Exception $e) {
|
||||||
return response()->download($file);
|
return response()->json(['message' => $e->getMessage()]);
|
||||||
|
}
|
||||||
|
$pattern = storage_path('csv/exports/'. $gdc->nombre . '-*.csv');
|
||||||
|
$files = glob($pattern);
|
||||||
|
|
||||||
|
usort($files, function ($a, $b) {
|
||||||
|
return filemtime($b) <=> filemtime($a);
|
||||||
|
});
|
||||||
|
|
||||||
|
return response()->download($files[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function exportarPedidoConNucleosACSV(GrupoDeCompra $gdc): BinaryFileResponse
|
public function exportarPedidoConNucleosACSV(GrupoDeCompra $gdc)
|
||||||
{
|
{
|
||||||
|
try {
|
||||||
$gdc->exportarPedidoConNucleosEnCSV();
|
$gdc->exportarPedidoConNucleosEnCSV();
|
||||||
$file = resource_path('csv/exports/'.$gdc->nombre.'-completo.csv');
|
} catch (Exception $e) {
|
||||||
return response()->download($file);
|
return response()->json(['message' => $e->getMessage()]);
|
||||||
|
}
|
||||||
|
$pattern = storage_path('csv/exports/'.$gdc->nombre.'-completo-*.csv');
|
||||||
|
$files = glob($pattern);
|
||||||
|
|
||||||
|
usort($files, function ($a, $b) {
|
||||||
|
return filemtime($b) <=> filemtime($a);
|
||||||
|
});
|
||||||
|
|
||||||
|
return response()->download($files[0]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
13
app/Http/Controllers/Api/CanastaController.php
Normal file
13
app/Http/Controllers/Api/CanastaController.php
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Controllers\Api;
|
||||||
|
|
||||||
|
use App\Helpers\CanastaHelper;
|
||||||
|
use App\Http\Controllers\Controller;
|
||||||
|
|
||||||
|
class CanastaController extends Controller
|
||||||
|
{
|
||||||
|
public function canastaActual() {
|
||||||
|
return response()->json(CanastaHelper::canastaActual());
|
||||||
|
}
|
||||||
|
}
|
|
@ -4,6 +4,7 @@ namespace App\Http\Controllers\Api;
|
||||||
|
|
||||||
use App\GrupoDeCompra;
|
use App\GrupoDeCompra;
|
||||||
use App\Http\Controllers\Controller;
|
use App\Http\Controllers\Controller;
|
||||||
|
use App\Http\Resources\GrupoDeCompraComisionesResource;
|
||||||
use App\Http\Resources\GrupoDeCompraResource;
|
use App\Http\Resources\GrupoDeCompraResource;
|
||||||
|
|
||||||
class GrupoDeCompraController extends Controller
|
class GrupoDeCompraController extends Controller
|
||||||
|
@ -16,4 +17,32 @@ class GrupoDeCompraController extends Controller
|
||||||
{
|
{
|
||||||
return new GrupoDeCompraResource($grupoDeCompra);
|
return new GrupoDeCompraResource($grupoDeCompra);
|
||||||
}
|
}
|
||||||
|
public function regiones()
|
||||||
|
{
|
||||||
|
return GrupoDeCompra::all()->pluck('region')->unique()->flatten();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function region(string $region)
|
||||||
|
{
|
||||||
|
return GrupoDeCompra::where('region', $region)->get();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function toggleDevoluciones(int $gdc) {
|
||||||
|
GrupoDeCompra::find($gdc)->toggleDevoluciones();
|
||||||
|
return response()->noContent();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setSaldo(int $gdc) {
|
||||||
|
$valid = request()->validate([
|
||||||
|
'saldo' => ['required', 'min:0'],
|
||||||
|
]);
|
||||||
|
$grupoDeCompra = GrupoDeCompra::find($gdc);
|
||||||
|
$grupoDeCompra->setSaldo($valid['saldo']);
|
||||||
|
return response()->noContent();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function saldos()
|
||||||
|
{
|
||||||
|
return GrupoDeCompraComisionesResource::collection(GrupoDeCompra::all());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,8 +2,8 @@
|
||||||
|
|
||||||
namespace App\Http\Controllers\Api;
|
namespace App\Http\Controllers\Api;
|
||||||
|
|
||||||
use App\Http\Controllers\Controller;
|
|
||||||
use Illuminate\Http\Request;
|
use Illuminate\Http\Request;
|
||||||
|
use App\Http\Controllers\Controller;
|
||||||
use App\Filtros\FiltroDeProducto;
|
use App\Filtros\FiltroDeProducto;
|
||||||
use App\Http\Resources\ProductoResource;
|
use App\Http\Resources\ProductoResource;
|
||||||
use App\Producto;
|
use App\Producto;
|
||||||
|
@ -15,9 +15,8 @@ class ProductoController extends Controller
|
||||||
return ProductoResource::collection(Producto::filtrar($filtros)->paginate(Producto::getPaginar($request)));
|
return ProductoResource::collection(Producto::filtrar($filtros)->paginate(Producto::getPaginar($request)));
|
||||||
}
|
}
|
||||||
|
|
||||||
public function show(Producto $producto)
|
public function categorias()
|
||||||
{
|
{
|
||||||
return new ProductoResource($producto);
|
return Producto::all()->pluck('categoria')->unique()->flatten();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,7 +17,7 @@ class SubpedidoController extends Controller
|
||||||
{
|
{
|
||||||
public function index(FiltroDeSubpedido $filtros, Request $request)
|
public function index(FiltroDeSubpedido $filtros, Request $request)
|
||||||
{
|
{
|
||||||
return Subpedido::filtrar($filtros)->get();
|
return Subpedido::filtrar($filtros)->select('id','nombre')->get();
|
||||||
}
|
}
|
||||||
|
|
||||||
public function indexResources(FiltroDeSubpedido $filtros, Request $request)
|
public function indexResources(FiltroDeSubpedido $filtros, Request $request)
|
||||||
|
@ -35,7 +35,7 @@ class SubpedidoController extends Controller
|
||||||
$s->nombre = $validado["nombre"];
|
$s->nombre = $validado["nombre"];
|
||||||
$s->grupo_de_compra_id = $validado["grupo_de_compra_id"];
|
$s->grupo_de_compra_id = $validado["grupo_de_compra_id"];
|
||||||
$s->save();
|
$s->save();
|
||||||
return $s;
|
return $this->show($s);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function validateSubpedido(): array
|
protected function validateSubpedido(): array
|
||||||
|
@ -57,7 +57,7 @@ class SubpedidoController extends Controller
|
||||||
// recibe request, saca producto y cantidad, valida, y pasa a syncProducto en Subpedido
|
// recibe request, saca producto y cantidad, valida, y pasa a syncProducto en Subpedido
|
||||||
public function syncProductos(Subpedido $subpedido) {
|
public function syncProductos(Subpedido $subpedido) {
|
||||||
if ($subpedido->aprobado)
|
if ($subpedido->aprobado)
|
||||||
return new SubpedidoResource($subpedido);
|
abort(400, "No se puede modificar un pedido aprobado.");
|
||||||
|
|
||||||
$valid = request()->validate([
|
$valid = request()->validate([
|
||||||
'cantidad' => ['integer','required','min:0'],
|
'cantidad' => ['integer','required','min:0'],
|
||||||
|
@ -80,11 +80,12 @@ class SubpedidoController extends Controller
|
||||||
'aprobacion' => 'required | boolean'
|
'aprobacion' => 'required | boolean'
|
||||||
]);
|
]);
|
||||||
$subpedido->toggleAprobacion($valid['aprobacion']);
|
$subpedido->toggleAprobacion($valid['aprobacion']);
|
||||||
return new SubpedidoResource($subpedido);
|
return response()->noContent();
|
||||||
}
|
}
|
||||||
|
|
||||||
public function syncDevoluciones(Subpedido $subpedido) {
|
public function syncDevoluciones(Subpedido $subpedido) {
|
||||||
if ($subpedido->aprobado) return new SubpedidoResource($subpedido);
|
if ($subpedido->aprobado)
|
||||||
|
abort(400, "No se puede modificar un pedido aprobado.");
|
||||||
|
|
||||||
$valid = request()->validate([
|
$valid = request()->validate([
|
||||||
'total' => 'required|min:0',
|
'total' => 'required|min:0',
|
||||||
|
|
|
@ -6,7 +6,6 @@ use App\Http\Controllers\Controller;
|
||||||
use App\Providers\RouteServiceProvider;
|
use App\Providers\RouteServiceProvider;
|
||||||
use Illuminate\Foundation\Auth\AuthenticatesUsers;
|
use Illuminate\Foundation\Auth\AuthenticatesUsers;
|
||||||
use Illuminate\Http\Request;
|
use Illuminate\Http\Request;
|
||||||
use Illuminate\Support\Facades\Auth;
|
|
||||||
|
|
||||||
class LoginController extends Controller
|
class LoginController extends Controller
|
||||||
{
|
{
|
||||||
|
@ -31,15 +30,8 @@ class LoginController extends Controller
|
||||||
|
|
||||||
protected function authenticated(Request $request, $user)
|
protected function authenticated(Request $request, $user)
|
||||||
{
|
{
|
||||||
if ($user->is_compras) {
|
|
||||||
return redirect('compras/pedidos');
|
|
||||||
} else if ($user->is_admin) {
|
|
||||||
session(['admin_gdc' => $user->grupo_de_compra_id]);
|
|
||||||
return redirect('admin/pedidos');
|
|
||||||
} else {
|
|
||||||
return redirect('/');
|
return redirect('/');
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a new controller instance.
|
* Create a new controller instance.
|
||||||
|
|
107
app/Http/Controllers/ComisionesController.php
Normal file
107
app/Http/Controllers/ComisionesController.php
Normal file
|
@ -0,0 +1,107 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Controllers;
|
||||||
|
|
||||||
|
use App\GrupoDeCompra;
|
||||||
|
use App\Helpers\CanastaHelper;
|
||||||
|
use App\Helpers\CsvHelper;
|
||||||
|
use App\Http\Resources\GrupoDeCompraResource;
|
||||||
|
use App\Producto;
|
||||||
|
use Illuminate\Http\JsonResponse;
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
use League\Csv\Exception;
|
||||||
|
use Symfony\Component\HttpFoundation\BinaryFileResponse;
|
||||||
|
|
||||||
|
class ComisionesController
|
||||||
|
{
|
||||||
|
const CANASTAS_PATH = 'csv/canastas/';
|
||||||
|
const BARRIO = "Barrio";
|
||||||
|
const SALDO = "Saldo";
|
||||||
|
|
||||||
|
public function show()
|
||||||
|
{
|
||||||
|
return view('auth/login');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function descargarPedidos()
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
Producto::planillaTotales();
|
||||||
|
} catch (Exception $e) {
|
||||||
|
return response()->json(['message' => $e->getMessage()], 500);
|
||||||
|
}
|
||||||
|
$pattern = storage_path('csv/exports/pedidos-por-barrio-*.csv');
|
||||||
|
$files = glob($pattern);
|
||||||
|
|
||||||
|
usort($files, function ($a, $b) {
|
||||||
|
return filemtime($b) <=> filemtime($a);
|
||||||
|
});
|
||||||
|
|
||||||
|
return response()->download($files[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function descargarNotas(): BinaryFileResponse
|
||||||
|
{
|
||||||
|
Producto::planillaNotas();
|
||||||
|
$pattern = storage_path('csv/exports/notas-por-barrio-*.csv');
|
||||||
|
$files = glob($pattern);
|
||||||
|
|
||||||
|
usort($files, function ($a, $b) {
|
||||||
|
return filemtime($b) <=> filemtime($a);
|
||||||
|
});
|
||||||
|
|
||||||
|
return response()->download($files[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function pdf() {
|
||||||
|
GrupoDeCompra::exportarPedidosBarrialesAPdf();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function cargarCanasta(Request $request): JsonResponse
|
||||||
|
{
|
||||||
|
$request->validate([
|
||||||
|
'data' => 'required|file|mimes:csv,txt|max:2048',
|
||||||
|
]);
|
||||||
|
|
||||||
|
$nombre = CanastaHelper::guardarCanasta($request->file('data'), self::CANASTAS_PATH);
|
||||||
|
try {
|
||||||
|
CanastaHelper::cargarCanasta(storage_path(self::CANASTAS_PATH . $nombre));
|
||||||
|
} catch (Exception $e) {
|
||||||
|
return response()->json(['message' => $e->getMessage()], 500);
|
||||||
|
}
|
||||||
|
|
||||||
|
return response()->json([
|
||||||
|
'message' => 'Canasta cargada exitosamente',
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function descargarCanastaEjemplo(): BinaryFileResponse
|
||||||
|
{
|
||||||
|
$file = resource_path('csv/productos.csv');
|
||||||
|
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();
|
||||||
|
|
||||||
|
try {
|
||||||
|
$records = CsvHelper::getRecords($file, "No se pudo leer el archivo.");
|
||||||
|
} catch (Exception $e) {
|
||||||
|
return response()->json(['message' => $e->getMessage()], 500);
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ($records as $record) {
|
||||||
|
$barrio = $record[self::BARRIO];
|
||||||
|
$saldo = $record[self::SALDO];
|
||||||
|
GrupoDeCompra::where('nombre', $barrio)
|
||||||
|
->update(['saldo' => $saldo]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return response()->json(GrupoDeCompraResource::collection(GrupoDeCompra::all()));
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,62 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
namespace App\Http\Controllers;
|
|
||||||
|
|
||||||
use App\GrupoDeCompra;
|
|
||||||
use App\Helpers\CanastaHelper;
|
|
||||||
use App\Producto;
|
|
||||||
use Illuminate\Http\JsonResponse;
|
|
||||||
use Illuminate\Http\Request;
|
|
||||||
use Symfony\Component\HttpFoundation\BinaryFileResponse;
|
|
||||||
|
|
||||||
class ComprasController
|
|
||||||
{
|
|
||||||
const CANASTAS_PATH = 'csv/canastas/';
|
|
||||||
|
|
||||||
public function indexPedidos() {
|
|
||||||
return view('compras_pedidos');
|
|
||||||
}
|
|
||||||
|
|
||||||
public function descargarPedidos(): BinaryFileResponse
|
|
||||||
{
|
|
||||||
Producto::planillaTotales();
|
|
||||||
$file = resource_path('csv/exports/pedidos-por-barrio.csv');
|
|
||||||
return response()->download($file);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function descargarNotas(): BinaryFileResponse
|
|
||||||
{
|
|
||||||
Producto::planillaNotas();
|
|
||||||
$file = resource_path('csv/exports/notas-por-barrio.csv');
|
|
||||||
return response()->download($file);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function pdf() {
|
|
||||||
GrupoDeCompra::exportarPedidosBarrialesAPdf();
|
|
||||||
}
|
|
||||||
|
|
||||||
public function show()
|
|
||||||
{
|
|
||||||
return view('auth/compras_login');
|
|
||||||
}
|
|
||||||
|
|
||||||
public function cargarCanasta(Request $request): JsonResponse
|
|
||||||
{
|
|
||||||
$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',
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function descargarCanastaEjemplo(): BinaryFileResponse
|
|
||||||
{
|
|
||||||
$file = resource_path('csv/productos.csv');
|
|
||||||
return response()->download($file);
|
|
||||||
}
|
|
||||||
}
|
|
34
app/Http/Controllers/RouteController.php
Normal file
34
app/Http/Controllers/RouteController.php
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Controllers;
|
||||||
|
|
||||||
|
use App\UserRole;
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
use Illuminate\Support\Facades\Auth;
|
||||||
|
|
||||||
|
class RouteController extends Controller
|
||||||
|
{
|
||||||
|
function home(Request $request) {
|
||||||
|
if (!Auth::check())
|
||||||
|
return redirect('/login');
|
||||||
|
|
||||||
|
$barrio = UserRole::where('nombre', 'barrio')->first();
|
||||||
|
$admin = UserRole::where('nombre', 'admin_barrio')->first();
|
||||||
|
$comision = UserRole::where('nombre', 'comision')->first();
|
||||||
|
|
||||||
|
switch ($request->user()->role_id) {
|
||||||
|
case $barrio->id:
|
||||||
|
return redirect('/pedido');
|
||||||
|
case $admin->id:
|
||||||
|
return redirect('/admin');
|
||||||
|
case $comision->id:
|
||||||
|
return redirect('/comisiones');
|
||||||
|
default:
|
||||||
|
abort(400, 'Rol de usuario invalido');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function main(Request $request) {
|
||||||
|
return view('main');
|
||||||
|
}
|
||||||
|
}
|
35
app/Http/Controllers/SessionController.php
Normal file
35
app/Http/Controllers/SessionController.php
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Controllers;
|
||||||
|
|
||||||
|
use App\Subpedido;
|
||||||
|
use Illuminate\Http\JsonResponse;
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
use Illuminate\Http\Response;
|
||||||
|
use Illuminate\Support\Facades\Auth;
|
||||||
|
use Illuminate\Validation\Rule;
|
||||||
|
|
||||||
|
class SessionController extends Controller
|
||||||
|
{
|
||||||
|
public function store(Request $request): Response
|
||||||
|
{
|
||||||
|
$grupo_de_compra_id = Auth::user()->grupo_de_compra_id;
|
||||||
|
$validated = $request->validate([
|
||||||
|
'id' => 'required',
|
||||||
|
Rule::in(Subpedido::where('grupo_de_compra_id', $grupo_de_compra_id)->pluck('id')),
|
||||||
|
]);
|
||||||
|
session()->put('pedido_id', $validated["id"]);
|
||||||
|
return response()->noContent();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function fetch(): JsonResponse
|
||||||
|
{
|
||||||
|
return response()->json(['id' => session('pedido_id')]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function destroy(): Response
|
||||||
|
{
|
||||||
|
session()->forget('pedido_id');
|
||||||
|
return response()->noContent();
|
||||||
|
}
|
||||||
|
}
|
37
app/Http/Controllers/UserController.php
Normal file
37
app/Http/Controllers/UserController.php
Normal file
|
@ -0,0 +1,37 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Controllers;
|
||||||
|
|
||||||
|
use App\GrupoDeCompra;
|
||||||
|
use App\Http\Resources\GrupoDeCompraPedidoResource;
|
||||||
|
use App\Http\Resources\GrupoDeCompraResource;
|
||||||
|
use App\UserRole;
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
use Illuminate\Support\Facades\Auth;
|
||||||
|
|
||||||
|
class UserController extends Controller
|
||||||
|
{
|
||||||
|
public function rol(Request $request) {
|
||||||
|
return ["rol" => UserRole::find($request->user()->role_id)->nombre];
|
||||||
|
}
|
||||||
|
|
||||||
|
public function grupoDeCompra(Request $request)
|
||||||
|
{
|
||||||
|
$user = Auth::user();
|
||||||
|
$result = [ 'grupo_de_compra' => null, ];
|
||||||
|
$grupo_de_compra = GrupoDeCompra::find($user->grupo_de_compra_id);
|
||||||
|
switch (UserRole::findOrFail($user->role_id)->nombre) {
|
||||||
|
case 'barrio':
|
||||||
|
$result['grupo_de_compra'] = new GrupoDeCompraPedidoResource($grupo_de_compra);
|
||||||
|
break;
|
||||||
|
case 'admin_barrio':
|
||||||
|
$result['grupo_de_compra'] = new GrupoDeCompraResource($grupo_de_compra);
|
||||||
|
break;
|
||||||
|
case 'comision':
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
abort(400, 'Rol invalido.');
|
||||||
|
}
|
||||||
|
return $result;
|
||||||
|
}
|
||||||
|
}
|
|
@ -2,6 +2,7 @@
|
||||||
|
|
||||||
namespace App\Http;
|
namespace App\Http;
|
||||||
|
|
||||||
|
use App\Http\Middleware\CheckRole;
|
||||||
use Illuminate\Foundation\Http\Kernel as HttpKernel;
|
use Illuminate\Foundation\Http\Kernel as HttpKernel;
|
||||||
use Laravel\Sanctum\Http\Middleware\EnsureFrontendRequestsAreStateful;
|
use Laravel\Sanctum\Http\Middleware\EnsureFrontendRequestsAreStateful;
|
||||||
|
|
||||||
|
@ -56,8 +57,7 @@ class Kernel extends HttpKernel
|
||||||
*/
|
*/
|
||||||
protected $routeMiddleware = [
|
protected $routeMiddleware = [
|
||||||
'auth' => \App\Http\Middleware\Authenticate::class,
|
'auth' => \App\Http\Middleware\Authenticate::class,
|
||||||
'admin' => \App\Http\Middleware\Admin::class,
|
'role' => \App\Http\Middleware\CheckRole::class,
|
||||||
'compras' => \App\Http\Middleware\Compras::class,
|
|
||||||
'auth.basic' => \Illuminate\Auth\Middleware\AuthenticateWithBasicAuth::class,
|
'auth.basic' => \Illuminate\Auth\Middleware\AuthenticateWithBasicAuth::class,
|
||||||
'bindings' => \Illuminate\Routing\Middleware\SubstituteBindings::class,
|
'bindings' => \Illuminate\Routing\Middleware\SubstituteBindings::class,
|
||||||
'cache.headers' => \Illuminate\Http\Middleware\SetCacheHeaders::class,
|
'cache.headers' => \Illuminate\Http\Middleware\SetCacheHeaders::class,
|
||||||
|
|
|
@ -1,20 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
namespace App\Http\Middleware;
|
|
||||||
|
|
||||||
use Closure;
|
|
||||||
use Illuminate\Support\Facades\Auth;
|
|
||||||
use Illuminate\Http\Request;
|
|
||||||
|
|
||||||
class Admin
|
|
||||||
{
|
|
||||||
public function handle(Request $request, Closure $next)
|
|
||||||
{
|
|
||||||
$user = Auth::user();
|
|
||||||
if ($user->is_admin) {
|
|
||||||
return $next($request);
|
|
||||||
} else {
|
|
||||||
return response('Necesitás ser admin para hacer esto', 403);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -14,7 +14,12 @@ class Authenticate extends Middleware
|
||||||
*/
|
*/
|
||||||
protected function redirectTo($request)
|
protected function redirectTo($request)
|
||||||
{
|
{
|
||||||
if (! $request->expectsJson()) {
|
if (!$request->expectsJson()) {
|
||||||
|
$path = $request->path();
|
||||||
|
if (preg_match('~^admin.*~i', $path))
|
||||||
|
return route('admin.login');
|
||||||
|
if (preg_match('~^comisiones.*~i', $path))
|
||||||
|
return route('comisiones.login');
|
||||||
return route('login');
|
return route('login');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
25
app/Http/Middleware/CheckRole.php
Normal file
25
app/Http/Middleware/CheckRole.php
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Middleware;
|
||||||
|
|
||||||
|
use App\UserRole;
|
||||||
|
use Closure;
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
|
||||||
|
class CheckRole
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Handle the incoming request.
|
||||||
|
*
|
||||||
|
* @param Request $request
|
||||||
|
* @param Closure $next
|
||||||
|
* @param string $role
|
||||||
|
* @return mixed
|
||||||
|
*/
|
||||||
|
public function handle($request, Closure $next, $role)
|
||||||
|
{
|
||||||
|
$role_id = UserRole::where('nombre', $role)->first()->id;
|
||||||
|
return $request->user()->role_id == $role_id ? $next($request)
|
||||||
|
: response('No tenés permiso para esto.', 403);
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,29 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
namespace App\Http\Middleware;
|
|
||||||
|
|
||||||
use Closure;
|
|
||||||
use Illuminate\Http\Request;
|
|
||||||
use Illuminate\Support\Facades\Auth;
|
|
||||||
|
|
||||||
class Compras
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Handle an incoming request.
|
|
||||||
*
|
|
||||||
* @param Request $request
|
|
||||||
* @param Closure $next
|
|
||||||
* @return mixed
|
|
||||||
*/
|
|
||||||
public function handle(Request $request, Closure $next)
|
|
||||||
{
|
|
||||||
if (!Auth::check())
|
|
||||||
return redirect()->route('compras_login.show');
|
|
||||||
|
|
||||||
if (Auth::user()->is_compras) {
|
|
||||||
return $next($request);
|
|
||||||
} else {
|
|
||||||
return response('Necesitás ser de comisión compras para hacer esto', 403);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
22
app/Http/Resources/GrupoDeCompraComisionesResource.php
Normal file
22
app/Http/Resources/GrupoDeCompraComisionesResource.php
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Resources;
|
||||||
|
|
||||||
|
use Illuminate\Http\Resources\Json\JsonResource;
|
||||||
|
|
||||||
|
class GrupoDeCompraComisionesResource extends JsonResource
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Transform the resource into an array.
|
||||||
|
*
|
||||||
|
* @param \Illuminate\Http\Request $request
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function toArray($request): array {
|
||||||
|
return [
|
||||||
|
'id' => $this->id,
|
||||||
|
'nombre' => $this->nombre,
|
||||||
|
'saldo' => $this->saldo,
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
22
app/Http/Resources/GrupoDeCompraPedidoResource.php
Normal file
22
app/Http/Resources/GrupoDeCompraPedidoResource.php
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Resources;
|
||||||
|
|
||||||
|
use Illuminate\Http\Resources\Json\JsonResource;
|
||||||
|
|
||||||
|
class GrupoDeCompraPedidoResource extends JsonResource
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Transform the resource into an array.
|
||||||
|
*
|
||||||
|
* @param \Illuminate\Http\Request $request
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function toArray($request): array {
|
||||||
|
return [
|
||||||
|
'id' => $this->id,
|
||||||
|
'nombre' => $this->nombre,
|
||||||
|
'devoluciones_habilitadas' => $this->devoluciones_habilitadas,
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
|
@ -21,8 +21,11 @@ class GrupoDeCompraResource extends JsonResource
|
||||||
'devoluciones_habilitadas' => $this->devoluciones_habilitadas,
|
'devoluciones_habilitadas' => $this->devoluciones_habilitadas,
|
||||||
'pedidos' => SubpedidoResource::collection($this->subpedidos),
|
'pedidos' => SubpedidoResource::collection($this->subpedidos),
|
||||||
'total_a_recaudar' => number_format($this->totalARecaudar(),2),
|
'total_a_recaudar' => number_format($this->totalARecaudar(),2),
|
||||||
|
'saldo' => number_format($this->saldo, 2, ".", ""),
|
||||||
|
'total_sin_devoluciones' => number_format($this->totalSinDevoluciones(),2),
|
||||||
'total_barrial' => number_format($this->totalBarrial(),2),
|
'total_barrial' => number_format($this->totalBarrial(),2),
|
||||||
'total_devoluciones' => number_format($this->totalDevoluciones(),2),
|
'total_devoluciones' => number_format($this->totalDevoluciones(),2),
|
||||||
|
'total_de_pedido' => number_format($this->totalDePedido(),2),
|
||||||
'total_a_transferir' => number_format($this->totalATransferir(),2),
|
'total_a_transferir' => number_format($this->totalATransferir(),2),
|
||||||
'total_transporte' => number_format($this->totalTransporte()),
|
'total_transporte' => number_format($this->totalTransporte()),
|
||||||
'cantidad_transporte' => number_format($this->cantidadTransporte()),
|
'cantidad_transporte' => number_format($this->cantidadTransporte()),
|
||||||
|
|
|
@ -20,13 +20,8 @@ class ProductoResource extends JsonResource
|
||||||
'nombre' => $this->nombre,
|
'nombre' => $this->nombre,
|
||||||
'precio' => $this->precio,
|
'precio' => $this->precio,
|
||||||
'categoria' => $this->categoria,
|
'categoria' => $this->categoria,
|
||||||
'proveedor' => optional($this->proveedor)->nombre,
|
'economia_solidaria' => $this->es_solidario,
|
||||||
'economia_solidaria' => optional($this->proveedor)->economia_solidaria,
|
'nacional' => $this->es_solidario,
|
||||||
'nacional' => optional($this->proveedor)->nacional,
|
|
||||||
'imagen' => optional($this->poster)->url(),
|
|
||||||
'descripcion' => $this->descripcion,
|
|
||||||
'apto_veganxs' => $this->apto_veganxs,
|
|
||||||
'apto_celiacxs' => $this->apto_celiacxs,
|
|
||||||
'requiere_notas' => $this->requiere_notas,
|
'requiere_notas' => $this->requiere_notas,
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,11 +15,14 @@ class SubpedidoResource extends JsonResource
|
||||||
*/
|
*/
|
||||||
public function toArray($request): array
|
public function toArray($request): array
|
||||||
{
|
{
|
||||||
|
$productos = $this->productos;
|
||||||
|
foreach ($productos as $producto) {
|
||||||
|
$producto['pivot']['total'] = number_format($producto->pivot->cantidad * $producto->precio, 2);
|
||||||
|
}
|
||||||
return [
|
return [
|
||||||
'id' => $this->id,
|
'id' => $this->id,
|
||||||
'nombre' => $this->nombre,
|
'nombre' => $this->nombre,
|
||||||
'grupo_de_compra' => $this->grupoDeCompra,
|
'productos' => $productos,
|
||||||
'productos' => $this->productos,
|
|
||||||
'aprobado' => (bool) $this->aprobado,
|
'aprobado' => (bool) $this->aprobado,
|
||||||
'total' => number_format($this->total(),2),
|
'total' => number_format($this->total(),2),
|
||||||
'total_transporte' => number_format($this->totalTransporte()),
|
'total_transporte' => number_format($this->totalTransporte()),
|
||||||
|
|
|
@ -7,29 +7,27 @@ use App\Helpers\CsvHelper;
|
||||||
use App\Helpers\TransporteHelper;
|
use App\Helpers\TransporteHelper;
|
||||||
use Illuminate\Database\Eloquent\Builder;
|
use Illuminate\Database\Eloquent\Builder;
|
||||||
use Illuminate\Database\Eloquent\Model;
|
use Illuminate\Database\Eloquent\Model;
|
||||||
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
|
||||||
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
|
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
|
||||||
use Illuminate\Http\Request;
|
use Illuminate\Http\Request;
|
||||||
use Illuminate\Support\Collection;
|
use Illuminate\Support\Collection;
|
||||||
use Illuminate\Support\Facades\DB;
|
use Illuminate\Support\Facades\DB;
|
||||||
|
use League\Csv\Exception;
|
||||||
|
|
||||||
class Producto extends Model
|
class Producto extends Model
|
||||||
{
|
{
|
||||||
public $timestamps = false;
|
protected $fillable = ["nombre", "precio", "categoria", "bono", "es_solidario", "requiere_notas"];
|
||||||
protected $fillable = ["nombre", "precio", "presentacion", "stock", "categoria"];
|
|
||||||
static int $paginarPorDefecto = 10;
|
|
||||||
|
|
||||||
public function subpedidos(): BelongsToMany
|
public function subpedidos(): BelongsToMany
|
||||||
{
|
{
|
||||||
return $this->belongsToMany('App\Subpedido', 'productos_subpedidos')->withPivot(["cantidad", "notas"]);
|
return $this->belongsToMany(Subpedido::class, 'productos_subpedidos')->withPivot(["cantidad", "notas"]);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function proveedor(): BelongsTo
|
public static function noBarriales()
|
||||||
{
|
{
|
||||||
return $this->belongsTo('App\Proveedor');
|
return self::where('nombre', 'not like', '%barrial%');
|
||||||
}
|
}
|
||||||
|
|
||||||
//Este método permite que se apliquen los filtros al hacer una request (por ejemplo, de búsqueda)
|
// Este método permite que se apliquen los filtros al hacer una request (por ejemplo, de búsqueda)
|
||||||
public function scopeFiltrar($query, FiltroDeProducto $filtros): Builder
|
public function scopeFiltrar($query, FiltroDeProducto $filtros): Builder
|
||||||
{
|
{
|
||||||
return $filtros->aplicar($query);
|
return $filtros->aplicar($query);
|
||||||
|
@ -37,22 +35,22 @@ class Producto extends Model
|
||||||
|
|
||||||
public static function getPaginar(Request $request): int
|
public static function getPaginar(Request $request): int
|
||||||
{
|
{
|
||||||
return $request->has('paginar') && intval($request->input('paginar')) ? intval($request->input('paginar')) : self::$paginarPorDefecto;
|
return $request->has('paginar') && intval($request->input('paginar')) ? intval($request->input('paginar')) : self::all()->count();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function productosFilaID()
|
public static function productosFilaID()
|
||||||
{
|
{
|
||||||
return Producto::pluck('id', 'fila')->all();
|
return self::noBarriales()->pluck('id', 'fila')->all();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function productosIDFila()
|
public static function productosIDFila()
|
||||||
{
|
{
|
||||||
return Producto::pluck('fila', 'id')->all();
|
return self::noBarriales()->pluck('fila', 'id')->all();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function productosIDNombre()
|
public static function productosIDNombre()
|
||||||
{
|
{
|
||||||
return Producto::pluck('nombre', 'id')->all();
|
return self::noBarriales()->pluck('nombre', 'id')->all();
|
||||||
}
|
}
|
||||||
|
|
||||||
static public function cantidadesPorBarrio(): Collection
|
static public function cantidadesPorBarrio(): Collection
|
||||||
|
@ -78,6 +76,9 @@ class Producto extends Model
|
||||||
->get();
|
->get();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
static public function planillaTotales()
|
static public function planillaTotales()
|
||||||
{
|
{
|
||||||
$headers = ['Producto'];
|
$headers = ['Producto'];
|
||||||
|
@ -112,7 +113,8 @@ class Producto extends Model
|
||||||
$planilla[$filaTransporte][] = $cantidad;
|
$planilla[$filaTransporte][] = $cantidad;
|
||||||
}
|
}
|
||||||
|
|
||||||
CsvHelper::generarCsv('csv/exports/pedidos-por-barrio.csv', $planilla, $headers);
|
$fecha = now()->format('Y-m-d');
|
||||||
|
CsvHelper::generarCsv('csv/exports/pedidos-por-barrio- ' . $fecha . '.csv', $planilla, $headers);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function notasPorBarrio(): Collection
|
public static function notasPorBarrio(): Collection
|
||||||
|
@ -149,6 +151,7 @@ class Producto extends Model
|
||||||
$planilla[] = $fila;
|
$planilla[] = $fila;
|
||||||
}
|
}
|
||||||
|
|
||||||
CsvHelper::generarCsv('csv/exports/notas-por-barrio.csv', $planilla, $headers);
|
$fecha = now()->format('Y-m-d');
|
||||||
|
CsvHelper::generarCsv('csv/exports/notas-por-barrio-' . $fecha . '.csv', $planilla, $headers);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,18 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
namespace App;
|
|
||||||
|
|
||||||
use Illuminate\Database\Eloquent\Model;
|
|
||||||
use Illuminate\Database\Eloquent\Relations\HasMany;
|
|
||||||
|
|
||||||
class Proveedor extends Model
|
|
||||||
{
|
|
||||||
public $timestamps = false;
|
|
||||||
protected $fillable = [ "nombre","direccion","telefono","correo","comentario" ];
|
|
||||||
protected $table = 'proveedores';
|
|
||||||
|
|
||||||
public function productos(): HasMany
|
|
||||||
{
|
|
||||||
return $this->hasMany('App\Producto');
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -12,17 +12,16 @@ use App\Filtros\FiltroDeSubpedido;
|
||||||
|
|
||||||
class Subpedido extends Model
|
class Subpedido extends Model
|
||||||
{
|
{
|
||||||
public $timestamps = false;
|
|
||||||
protected $fillable = ['grupo_de_compra_id', 'aprobado', 'nombre', 'devoluciones_total', 'devoluciones_notas'];
|
protected $fillable = ['grupo_de_compra_id', 'aprobado', 'nombre', 'devoluciones_total', 'devoluciones_notas'];
|
||||||
|
|
||||||
public function productos(): BelongsToMany
|
public function productos(): BelongsToMany
|
||||||
{
|
{
|
||||||
return $this->belongsToMany('App\Producto')->withPivot(["cantidad", "total", "notas"]);
|
return $this->belongsToMany(Producto::class)->withPivot(["cantidad", "notas"]);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function grupoDeCompra(): BelongsTo
|
public function grupoDeCompra(): BelongsTo
|
||||||
{
|
{
|
||||||
return $this->belongsTo('App\GrupoDeCompra');
|
return $this->belongsTo(GrupoDeCompra::class);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Permite que se apliquen los filtros al hacer una request (por ejemplo, de búsqueda)
|
// Permite que se apliquen los filtros al hacer una request (por ejemplo, de búsqueda)
|
||||||
|
@ -92,7 +91,7 @@ class Subpedido extends Model
|
||||||
return TransporteHelper::cantidadTransporte($this->totalCentralesQuePaganTransporte());
|
return TransporteHelper::cantidadTransporte($this->totalCentralesQuePaganTransporte());
|
||||||
}
|
}
|
||||||
|
|
||||||
//Actualiza el pedido, agregando o quitando del subpedido según sea necesario. Debe ser llamado desde el controlador de subpedidos, luego de validar que los parámetros $producto y $cantidad son correctos. También calcula el subtotal por producto.
|
// Actualiza el pedido, agregando o quitando del subpedido según sea necesario. Debe ser llamado desde el controlador de subpedidos, luego de validar que los parámetros $producto y $cantidad son correctos. También calcula el subtotal por producto.
|
||||||
public function syncProducto(Producto $producto, int $cantidad, string $notas)
|
public function syncProducto(Producto $producto, int $cantidad, string $notas)
|
||||||
{
|
{
|
||||||
if ($cantidad) {
|
if ($cantidad) {
|
||||||
|
@ -100,7 +99,6 @@ class Subpedido extends Model
|
||||||
$this->productos()->syncWithoutDetaching([
|
$this->productos()->syncWithoutDetaching([
|
||||||
$producto->id => [
|
$producto->id => [
|
||||||
'cantidad' => $cantidad,
|
'cantidad' => $cantidad,
|
||||||
'total' => $cantidad * $producto->precio,
|
|
||||||
'notas' => $notas,
|
'notas' => $notas,
|
||||||
]
|
]
|
||||||
]);
|
]);
|
||||||
|
@ -108,11 +106,15 @@ class Subpedido extends Model
|
||||||
//si la cantidad es 0, se elimina el producto del subpedido
|
//si la cantidad es 0, se elimina el producto del subpedido
|
||||||
$this->productos()->detach($producto->id);
|
$this->productos()->detach($producto->id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$this->updated_at = now();
|
||||||
|
$this->save();
|
||||||
}
|
}
|
||||||
|
|
||||||
public function toggleAprobacion(bool $aprobacion)
|
public function toggleAprobacion(bool $aprobacion)
|
||||||
{
|
{
|
||||||
$this->aprobado = $aprobacion;
|
$this->aprobado = $aprobacion;
|
||||||
|
$this->update(['aprobado' => $aprobacion]);
|
||||||
$this->save();
|
$this->save();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -16,7 +16,7 @@ class User extends Authenticatable
|
||||||
* @var array
|
* @var array
|
||||||
*/
|
*/
|
||||||
protected $fillable = [
|
protected $fillable = [
|
||||||
'name', 'email', 'password',
|
'name', 'email', 'password', 'role_id',
|
||||||
];
|
];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -40,6 +40,6 @@ class User extends Authenticatable
|
||||||
|
|
||||||
public function grupoDeCompra(): BelongsTo
|
public function grupoDeCompra(): BelongsTo
|
||||||
{
|
{
|
||||||
return $this->belongsTo('App\GrupoDeCompra');
|
return $this->belongsTo(GrupoDeCompra::class);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,7 +4,7 @@ namespace App;
|
||||||
|
|
||||||
use Illuminate\Database\Eloquent\Model;
|
use Illuminate\Database\Eloquent\Model;
|
||||||
|
|
||||||
class Admin extends Model
|
class UserRole extends Model
|
||||||
{
|
{
|
||||||
//
|
protected $fillable = ["nombre"];
|
||||||
}
|
}
|
|
@ -9,6 +9,7 @@
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"require": {
|
"require": {
|
||||||
"php": "^7.4",
|
"php": "^7.4",
|
||||||
|
"doctrine/dbal": "^2.2.0",
|
||||||
"fideloper/proxy": "^4.4",
|
"fideloper/proxy": "^4.4",
|
||||||
"fruitcake/laravel-cors": "^2.0",
|
"fruitcake/laravel-cors": "^2.0",
|
||||||
"guzzlehttp/guzzle": "^6.3.1|^7.0.1",
|
"guzzlehttp/guzzle": "^6.3.1|^7.0.1",
|
||||||
|
|
809
composer.lock
generated
809
composer.lock
generated
File diff suppressed because it is too large
Load diff
|
@ -0,0 +1,41 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
use App\UserRole;
|
||||||
|
use Illuminate\Database\Migrations\Migration;
|
||||||
|
use Illuminate\Database\Schema\Blueprint;
|
||||||
|
use Illuminate\Support\Facades\DB;
|
||||||
|
use Illuminate\Support\Facades\Schema;
|
||||||
|
|
||||||
|
class CreateUserRolesTable extends Migration
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Run the migrations.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function up()
|
||||||
|
{
|
||||||
|
Schema::create('user_roles', function (Blueprint $table) {
|
||||||
|
$table->id();
|
||||||
|
$table->string('nombre');
|
||||||
|
$table->timestamps();
|
||||||
|
});
|
||||||
|
|
||||||
|
$tipos = ["barrio", "admin_barrio", "comision"];
|
||||||
|
foreach ($tipos as $tipo) {
|
||||||
|
UserRole::create([
|
||||||
|
"nombre" => $tipo,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reverse the migrations.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function down()
|
||||||
|
{
|
||||||
|
Schema::dropIfExists('user_roles');
|
||||||
|
}
|
||||||
|
}
|
43
database/migrations/2025_05_15_023829_agregar_rol_a_user.php
Normal file
43
database/migrations/2025_05_15_023829_agregar_rol_a_user.php
Normal file
|
@ -0,0 +1,43 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
use App\User;
|
||||||
|
use App\UserRole;
|
||||||
|
use Illuminate\Database\Migrations\Migration;
|
||||||
|
use Illuminate\Database\Schema\Blueprint;
|
||||||
|
use Illuminate\Support\Facades\Schema;
|
||||||
|
|
||||||
|
class AgregarRolAUser extends Migration
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Run the migrations.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function up()
|
||||||
|
{
|
||||||
|
Schema::table('users', function (Blueprint $table) {
|
||||||
|
$table->foreignId('role_id');
|
||||||
|
});
|
||||||
|
|
||||||
|
$barrio = UserRole::where('nombre', 'barrio')->first();
|
||||||
|
$admin_barrio = UserRole::where('nombre', 'admin_barrio')->first();
|
||||||
|
$comision = UserRole::where('nombre', 'comision')->first();
|
||||||
|
User::all()->each(function($user) use ($barrio, $comision, $admin_barrio) {
|
||||||
|
$user->role_id = $user->is_admin ? $admin_barrio->id :
|
||||||
|
($user->is_compras ? $comision->id : $barrio->id);
|
||||||
|
$user->save();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reverse the migrations.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function down()
|
||||||
|
{
|
||||||
|
Schema::table('user', function (Blueprint $table) {
|
||||||
|
$table->dropForeign('role_id');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
43
database/migrations/2025_05_15_033316_simplificar_users.php
Normal file
43
database/migrations/2025_05_15_033316_simplificar_users.php
Normal file
|
@ -0,0 +1,43 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
use App\User;
|
||||||
|
use App\UserRole;
|
||||||
|
use Illuminate\Database\Migrations\Migration;
|
||||||
|
use Illuminate\Database\Schema\Blueprint;
|
||||||
|
use Illuminate\Support\Facades\Schema;
|
||||||
|
|
||||||
|
class SimplificarUsers extends Migration
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Run the migrations.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function up()
|
||||||
|
{
|
||||||
|
Schema::table('users', function (Blueprint $table) {
|
||||||
|
$table->dropColumn(['is_admin', 'is_compras']);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reverse the migrations.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function down()
|
||||||
|
{
|
||||||
|
Schema::table('users', function (Blueprint $table) {
|
||||||
|
$table->boolean('is_admin')->default(false);
|
||||||
|
$table->boolean('is_compras')->default(false);
|
||||||
|
});
|
||||||
|
|
||||||
|
$admin_barrio = UserRole::where('nombre', 'admin_barrio')->first();
|
||||||
|
$comision = UserRole::where('nombre', 'comision')->first();
|
||||||
|
foreach (User::all() as $user) {
|
||||||
|
$user->is_admin = $user->role_id == $admin_barrio->id;
|
||||||
|
$user->is_compras = $user->role_id == $comision->id;
|
||||||
|
$user->save();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,40 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
use Illuminate\Database\Migrations\Migration;
|
||||||
|
use Illuminate\Database\Schema\Blueprint;
|
||||||
|
use Illuminate\Support\Facades\Schema;
|
||||||
|
|
||||||
|
class SimplificarBarrios extends Migration
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Run the migrations.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function up()
|
||||||
|
{
|
||||||
|
Schema::table('grupos_de_compra', function (Blueprint $table) {
|
||||||
|
$table->dropColumn([
|
||||||
|
'cantidad_de_nucleos',
|
||||||
|
'telefono',
|
||||||
|
'correo',
|
||||||
|
'referente_finanzas',
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reverse the migrations.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function down()
|
||||||
|
{
|
||||||
|
Schema::table('grupos_de_compra', function (Blueprint $table) {
|
||||||
|
$table->double('cantidad_de_nucleos');
|
||||||
|
$table->string('telefono');
|
||||||
|
$table->string('correo');
|
||||||
|
$table->string('referente_finanzas');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,44 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
use Illuminate\Database\Migrations\Migration;
|
||||||
|
use Illuminate\Database\Schema\Blueprint;
|
||||||
|
use Illuminate\Support\Facades\Schema;
|
||||||
|
|
||||||
|
class SimplificarProductos extends Migration
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Run the migrations.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function up()
|
||||||
|
{
|
||||||
|
Schema::table('productos', function (Blueprint $table) {
|
||||||
|
$table->dropColumn([
|
||||||
|
'presentacion',
|
||||||
|
'stock',
|
||||||
|
'imagen_id',
|
||||||
|
'descripcion',
|
||||||
|
'apto_veganxs',
|
||||||
|
'apto_celiacxs',
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reverse the migrations.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function down()
|
||||||
|
{
|
||||||
|
Schema::table('productos', function (Blueprint $table) {
|
||||||
|
$table->integer('presentacion')->nullable();
|
||||||
|
$table->integer('stock')->nullable();
|
||||||
|
$table->foreignId('imagen_id')->nullable();
|
||||||
|
$table->string('descripcion')->nullable();
|
||||||
|
$table->boolean('apto_veganxs')->nullable();
|
||||||
|
$table->boolean('apto_celiacxs')->nullable();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,32 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
use Illuminate\Database\Migrations\Migration;
|
||||||
|
use Illuminate\Database\Schema\Blueprint;
|
||||||
|
use Illuminate\Support\Facades\Schema;
|
||||||
|
|
||||||
|
class SimplificarProductoSubpedido extends Migration
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Run the migrations.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function up()
|
||||||
|
{
|
||||||
|
Schema::table('producto_subpedido', function (Blueprint $table) {
|
||||||
|
$table->dropColumn('total');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reverse the migrations.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function down()
|
||||||
|
{
|
||||||
|
Schema::table('producto_subpedido', function (Blueprint $table) {
|
||||||
|
$table->double('total');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,38 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
use App\Producto;
|
||||||
|
use Illuminate\Database\Migrations\Migration;
|
||||||
|
use Illuminate\Database\Schema\Blueprint;
|
||||||
|
use Illuminate\Support\Facades\Schema;
|
||||||
|
|
||||||
|
class AgregarEsSolidario extends Migration
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Run the migrations.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function up()
|
||||||
|
{
|
||||||
|
Schema::table('productos', function (Blueprint $table) {
|
||||||
|
$table->boolean('es_solidario')->default(false);
|
||||||
|
});
|
||||||
|
|
||||||
|
foreach (Producto::all() as $producto) {
|
||||||
|
$producto->es_solidario = $producto->proveedor_id != null;
|
||||||
|
$producto->save();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reverse the migrations.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function down()
|
||||||
|
{
|
||||||
|
Schema::table('productos', function (Blueprint $table) {
|
||||||
|
$table->dropColumn('es_solidario');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
59
database/migrations/2025_05_15_035807_eliminar_proveedor.php
Normal file
59
database/migrations/2025_05_15_035807_eliminar_proveedor.php
Normal file
|
@ -0,0 +1,59 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
use App\Producto;
|
||||||
|
use Illuminate\Database\Migrations\Migration;
|
||||||
|
use Illuminate\Database\Schema\Blueprint;
|
||||||
|
use Illuminate\Support\Facades\DB;
|
||||||
|
use Illuminate\Support\Facades\Schema;
|
||||||
|
|
||||||
|
class EliminarProveedor extends Migration
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Run the migrations.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function up()
|
||||||
|
{
|
||||||
|
Schema::table('productos', function (Blueprint $table) {
|
||||||
|
$table->dropColumn('proveedor_id');
|
||||||
|
});
|
||||||
|
Schema::dropIfExists('proveedores');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reverse the migrations.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function down()
|
||||||
|
{
|
||||||
|
Schema::create('proveedores', function (Blueprint $table) {
|
||||||
|
$table->id();
|
||||||
|
$table->string('nombre');
|
||||||
|
$table->string('direccion')->nullable();
|
||||||
|
$table->string('telefono')->nullable();
|
||||||
|
$table->string('correo')->nullable();
|
||||||
|
$table->boolean('economia_solidaria')->nullable();
|
||||||
|
$table->boolean('nacional')->nullable();
|
||||||
|
$table->text('detalles_de_pago')->nullable();
|
||||||
|
$table->text('comentario')->nullable();
|
||||||
|
$table->timestamps();
|
||||||
|
});
|
||||||
|
|
||||||
|
Schema::table('productos', function (Blueprint $table) {
|
||||||
|
$table->foreignId('proveedor_id')->nullable();
|
||||||
|
});
|
||||||
|
|
||||||
|
$proveedor_id = DB::table('proveedores')->insertGetId([
|
||||||
|
['nombre' => 'Proveedor de economía solidaria',
|
||||||
|
'economia_solidaria' => 1,
|
||||||
|
'nacional' => 1]
|
||||||
|
]);
|
||||||
|
|
||||||
|
foreach (Producto::all() as $producto) {
|
||||||
|
$producto->proveedor_id = $producto->es_solidario ? $proveedor_id : null;
|
||||||
|
$producto->save();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
35
database/migrations/2025_05_15_041404_eliminar_admin.php
Normal file
35
database/migrations/2025_05_15_041404_eliminar_admin.php
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
use Illuminate\Database\Migrations\Migration;
|
||||||
|
use Illuminate\Database\Schema\Blueprint;
|
||||||
|
use Illuminate\Support\Facades\Schema;
|
||||||
|
|
||||||
|
class EliminarAdmin extends Migration
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Run the migrations.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function up()
|
||||||
|
{
|
||||||
|
Schema::dropIfExists('admins');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reverse the migrations.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function down()
|
||||||
|
{
|
||||||
|
Schema::create('admins', function (Blueprint $table) {
|
||||||
|
$table->id();
|
||||||
|
$table->string('nombre');
|
||||||
|
$table->foreignId('grupo_de_compra_id');
|
||||||
|
$table->string('email');
|
||||||
|
$table->string('contrasena');
|
||||||
|
$table->timestamps();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,32 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
use Illuminate\Database\Migrations\Migration;
|
||||||
|
use Illuminate\Database\Schema\Blueprint;
|
||||||
|
use Illuminate\Support\Facades\Schema;
|
||||||
|
|
||||||
|
class HacerFilaNullable extends Migration
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Run the migrations.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function up()
|
||||||
|
{
|
||||||
|
Schema::table('productos', function (Blueprint $table) {
|
||||||
|
$table->integer('fila')->nullable()->change();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reverse the migrations.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function down()
|
||||||
|
{
|
||||||
|
Schema::table('productos', function (Blueprint $table) {
|
||||||
|
$table->integer('fila')->nullable(false)->change();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,32 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
use Illuminate\Database\Migrations\Migration;
|
||||||
|
use Illuminate\Database\Schema\Blueprint;
|
||||||
|
use Illuminate\Support\Facades\Schema;
|
||||||
|
|
||||||
|
class QuitarPasswordDeGrupoDeCompra extends Migration
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Run the migrations.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function up()
|
||||||
|
{
|
||||||
|
Schema::table('grupos_de_compra', function (Blueprint $table) {
|
||||||
|
$table->dropColumn('password');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reverse the migrations.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function down()
|
||||||
|
{
|
||||||
|
Schema::table('grupos_de_compra', function (Blueprint $table) {
|
||||||
|
$table->string('password')->nullable();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,34 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
use Illuminate\Database\Migrations\Migration;
|
||||||
|
use Illuminate\Database\Schema\Blueprint;
|
||||||
|
use Illuminate\Support\Facades\Schema;
|
||||||
|
|
||||||
|
class AgregarSaldosABarrios extends Migration
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Run the migrations.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function up()
|
||||||
|
{
|
||||||
|
// Agregar columna 'saldo' a la tabla 'grupos_de_compra'
|
||||||
|
Schema::table('grupos_de_compra', function (Blueprint $table) {
|
||||||
|
$table->double('saldo', 10, 2)->default(0);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reverse the migrations.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function down()
|
||||||
|
{
|
||||||
|
// Remover columna 'saldo' de la tabla 'grupos_de_compra'
|
||||||
|
Schema::table('grupos_de_compra', function (Blueprint $table) {
|
||||||
|
$table->dropColumn('saldo');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
|
@ -11,9 +11,10 @@ class CanastaSeeder extends Seeder
|
||||||
* Run the database seeds.
|
* Run the database seeds.
|
||||||
*
|
*
|
||||||
* @return void
|
* @return void
|
||||||
|
* @throws \League\Csv\Exception
|
||||||
*/
|
*/
|
||||||
public function run()
|
public function run()
|
||||||
{
|
{
|
||||||
CanastaHelper::cargarCanasta(self::ARCHIVO_DEFAULT);
|
CanastaHelper::cargarCanasta(resource_path(self::ARCHIVO_DEFAULT));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,10 +1,19 @@
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
use Illuminate\Database\Seeder;
|
use Illuminate\Database\Seeder;
|
||||||
|
use Illuminate\Support\Facades\DB;
|
||||||
|
|
||||||
class DatabaseSeeder extends Seeder
|
class DatabaseSeeder extends Seeder
|
||||||
{
|
{
|
||||||
const CHUNK_SIZE = 100;
|
const CHUNK_SIZE = 100;
|
||||||
|
|
||||||
|
static function addTimestamps($object) {
|
||||||
|
$now = DB::raw('CURRENT_TIMESTAMP');
|
||||||
|
$object['created_at'] = $now;
|
||||||
|
$object['updated_at'] = $now;
|
||||||
|
return $object;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Seed the application's database.
|
* Seed the application's database.
|
||||||
*
|
*
|
||||||
|
|
|
@ -1,8 +1,10 @@
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
use App\Helpers\CsvHelper as CsvHelperAlias;
|
use App\Helpers\CsvHelper;
|
||||||
|
use App\GrupoDeCompra;
|
||||||
|
use App\User;
|
||||||
|
use App\UserRole;
|
||||||
use Illuminate\Database\Seeder;
|
use Illuminate\Database\Seeder;
|
||||||
use Illuminate\Support\Facades\DB;
|
|
||||||
use Illuminate\Support\Facades\Hash;
|
use Illuminate\Support\Facades\Hash;
|
||||||
|
|
||||||
class GrupoDeCompraSeeder extends Seeder
|
class GrupoDeCompraSeeder extends Seeder
|
||||||
|
@ -11,45 +13,36 @@ class GrupoDeCompraSeeder extends Seeder
|
||||||
* Run the database seeds.
|
* Run the database seeds.
|
||||||
*
|
*
|
||||||
* @return void
|
* @return void
|
||||||
|
* @throws \League\Csv\Exception
|
||||||
*/
|
*/
|
||||||
public function run()
|
public function run()
|
||||||
{
|
{
|
||||||
$registros = CsvHelperAlias::getRecords('csv/barrios.csv');
|
$registros = CsvHelper::getRecords(resource_path('csv/barrios.csv'), 'No se pudo leer la planilla de barrios.');
|
||||||
$gdcToInsert = [];
|
$gdcToInsert = [];
|
||||||
$usersToInsert = [];
|
$usersToInsert = [];
|
||||||
|
$roles = UserRole::where('nombre', 'barrio')->orWhere('nombre', 'admin_barrio')->get();
|
||||||
|
|
||||||
foreach($registros as $key => $registro){
|
foreach($registros as $key => $registro){
|
||||||
$gdcToInsert[] = [
|
$gdcToInsert[] = DatabaseSeeder::addTimestamps([
|
||||||
'nombre' => $registro['barrio'],
|
'nombre' => $registro['barrio'],
|
||||||
'region' => $registro['region'],
|
'region' => $registro['region'],
|
||||||
'telefono' => $registro['telefono'],
|
]);
|
||||||
'correo' => $registro['correo'],
|
|
||||||
'referente_finanzas' => $registro['referente']
|
|
||||||
];
|
|
||||||
|
|
||||||
$usersToInsert[] = [
|
foreach($roles as $role) {
|
||||||
'name' => $registro['barrio'],
|
$nombre = $registro['barrio'] . ($role->nombre == 'barrio' ? '' : '_admin');
|
||||||
|
$usersToInsert[] = DatabaseSeeder::addTimestamps([
|
||||||
|
'name' => $nombre,
|
||||||
'password' => Hash::make("123"),
|
'password' => Hash::make("123"),
|
||||||
"is_admin" => 0,
|
'role_id' => $role->id,
|
||||||
'grupo_de_compra_id' => $key
|
'grupo_de_compra_id' => $key,
|
||||||
];
|
]);
|
||||||
|
}
|
||||||
$usersToInsert[] = [
|
|
||||||
'name' => $registro['barrio'] . "_admin",
|
|
||||||
'password' => Hash::make("123"),
|
|
||||||
"is_admin" => 1,
|
|
||||||
'grupo_de_compra_id' => $key
|
|
||||||
];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach (array_chunk($gdcToInsert,DatabaseSeeder::CHUNK_SIZE) as $chunk)
|
foreach (array_chunk($gdcToInsert,DatabaseSeeder::CHUNK_SIZE) as $chunk)
|
||||||
{
|
GrupoDeCompra::insert($chunk);
|
||||||
DB::table('grupos_de_compra')->insert($chunk);
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach (array_chunk($usersToInsert,DatabaseSeeder::CHUNK_SIZE) as $chunk)
|
foreach (array_chunk($usersToInsert,DatabaseSeeder::CHUNK_SIZE) as $chunk)
|
||||||
{
|
User::insert($chunk);
|
||||||
DB::table('users')->insert($chunk);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
|
use App\User;
|
||||||
|
use App\UserRole;
|
||||||
use Illuminate\Database\Seeder;
|
use Illuminate\Database\Seeder;
|
||||||
use Illuminate\Support\Facades\DB;
|
|
||||||
use Illuminate\Support\Facades\Hash;
|
use Illuminate\Support\Facades\Hash;
|
||||||
|
|
||||||
class UserSeeder extends Seeder
|
class UserSeeder extends Seeder
|
||||||
|
@ -15,17 +16,14 @@ class UserSeeder extends Seeder
|
||||||
{
|
{
|
||||||
$usersToInsert = [];
|
$usersToInsert = [];
|
||||||
|
|
||||||
$usersToInsert[] = [
|
$usersToInsert[] = DatabaseSeeder::addTimestamps([
|
||||||
'name' => 'compras',
|
'name' => 'comi',
|
||||||
'password' => Hash::make("123"),
|
'password' => Hash::make("123"),
|
||||||
'is_admin' => 0,
|
'role_id' => UserRole::where('nombre', 'comision')->first()->id,
|
||||||
'is_compras' => 1
|
]);
|
||||||
];
|
|
||||||
|
|
||||||
|
|
||||||
foreach (array_chunk($usersToInsert,DatabaseSeeder::CHUNK_SIZE) as $chunk)
|
foreach (array_chunk($usersToInsert,DatabaseSeeder::CHUNK_SIZE) as $chunk)
|
||||||
{
|
User::insert($chunk);
|
||||||
DB::table('users')->insert($chunk);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
121
package-lock.json
generated
121
package-lock.json
generated
|
@ -8,16 +8,13 @@
|
||||||
"animate.css": "^4.1.1",
|
"animate.css": "^4.1.1",
|
||||||
"bulma": "^0.9.4",
|
"bulma": "^0.9.4",
|
||||||
"bulma-switch": "^2.0.4",
|
"bulma-switch": "^2.0.4",
|
||||||
"bulma-toast": "^2.4.1"
|
"bulma-toast": "^2.4.1",
|
||||||
|
"vuex": "^3.6.2"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"axios": "^0.19.2",
|
"axios": "^0.19.2",
|
||||||
"bootstrap": "^4.0.0",
|
|
||||||
"cross-env": "^7.0.3",
|
"cross-env": "^7.0.3",
|
||||||
"jquery": "^3.2",
|
|
||||||
"laravel-mix": "^5.0.1",
|
"laravel-mix": "^5.0.1",
|
||||||
"lodash": "^4.17.19",
|
|
||||||
"popper.js": "^1.12",
|
|
||||||
"resolve-url-loader": "^2.3.1",
|
"resolve-url-loader": "^2.3.1",
|
||||||
"sass": "^1.20.1",
|
"sass": "^1.20.1",
|
||||||
"sass-loader": "^8.0.0",
|
"sass-loader": "^8.0.0",
|
||||||
|
@ -350,7 +347,6 @@
|
||||||
"version": "7.27.1",
|
"version": "7.27.1",
|
||||||
"resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz",
|
"resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz",
|
||||||
"integrity": "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==",
|
"integrity": "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==",
|
||||||
"dev": true,
|
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=6.9.0"
|
"node": ">=6.9.0"
|
||||||
}
|
}
|
||||||
|
@ -359,7 +355,6 @@
|
||||||
"version": "7.27.1",
|
"version": "7.27.1",
|
||||||
"resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.27.1.tgz",
|
"resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.27.1.tgz",
|
||||||
"integrity": "sha512-D2hP9eA+Sqx1kBZgzxZh0y1trbuU+JoDkiEwqhQ36nodYqJwyEIhPSdMNd7lOm/4io72luTPWH20Yda0xOuUow==",
|
"integrity": "sha512-D2hP9eA+Sqx1kBZgzxZh0y1trbuU+JoDkiEwqhQ36nodYqJwyEIhPSdMNd7lOm/4io72luTPWH20Yda0xOuUow==",
|
||||||
"dev": true,
|
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=6.9.0"
|
"node": ">=6.9.0"
|
||||||
}
|
}
|
||||||
|
@ -404,7 +399,6 @@
|
||||||
"version": "7.27.2",
|
"version": "7.27.2",
|
||||||
"resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.27.2.tgz",
|
"resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.27.2.tgz",
|
||||||
"integrity": "sha512-QYLs8299NA7WM/bZAdp+CviYYkVoYXlDW2rzliy3chxd1PQjej7JORuMJDJXJUb9g0TT+B99EwaVLKmX+sPXWw==",
|
"integrity": "sha512-QYLs8299NA7WM/bZAdp+CviYYkVoYXlDW2rzliy3chxd1PQjej7JORuMJDJXJUb9g0TT+B99EwaVLKmX+sPXWw==",
|
||||||
"dev": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/types": "^7.27.1"
|
"@babel/types": "^7.27.1"
|
||||||
},
|
},
|
||||||
|
@ -1568,7 +1562,6 @@
|
||||||
"version": "7.27.1",
|
"version": "7.27.1",
|
||||||
"resolved": "https://registry.npmjs.org/@babel/types/-/types-7.27.1.tgz",
|
"resolved": "https://registry.npmjs.org/@babel/types/-/types-7.27.1.tgz",
|
||||||
"integrity": "sha512-+EzkxvLNfiUeKMgy/3luqfsCWFRXLb7U6wNQTk60tovuckwB15B191tJWvpp4HjiQWdJkCxO3Wbvc6jlk3Xb2Q==",
|
"integrity": "sha512-+EzkxvLNfiUeKMgy/3luqfsCWFRXLb7U6wNQTk60tovuckwB15B191tJWvpp4HjiQWdJkCxO3Wbvc6jlk3Xb2Q==",
|
||||||
"dev": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/helper-string-parser": "^7.27.1",
|
"@babel/helper-string-parser": "^7.27.1",
|
||||||
"@babel/helper-validator-identifier": "^7.27.1"
|
"@babel/helper-validator-identifier": "^7.27.1"
|
||||||
|
@ -2060,7 +2053,6 @@
|
||||||
"version": "2.7.16",
|
"version": "2.7.16",
|
||||||
"resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-2.7.16.tgz",
|
"resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-2.7.16.tgz",
|
||||||
"integrity": "sha512-KWhJ9k5nXuNtygPU7+t1rX6baZeqOYLEforUPjgNDBnLicfHCoi48H87Q8XyLZOrNNsmhuwKqtpDQWjEFe6Ekg==",
|
"integrity": "sha512-KWhJ9k5nXuNtygPU7+t1rX6baZeqOYLEforUPjgNDBnLicfHCoi48H87Q8XyLZOrNNsmhuwKqtpDQWjEFe6Ekg==",
|
||||||
"dev": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/parser": "^7.23.5",
|
"@babel/parser": "^7.23.5",
|
||||||
"postcss": "^8.4.14",
|
"postcss": "^8.4.14",
|
||||||
|
@ -2075,7 +2067,6 @@
|
||||||
"version": "8.5.3",
|
"version": "8.5.3",
|
||||||
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.3.tgz",
|
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.3.tgz",
|
||||||
"integrity": "sha512-dle9A3yYxlBSrt8Fu+IpjGT8SY8hN0mlaA6GY8t0P5PjIOZemULz/E2Bnm/2dcUOena75OTNkHI76uZBNUUq3A==",
|
"integrity": "sha512-dle9A3yYxlBSrt8Fu+IpjGT8SY8hN0mlaA6GY8t0P5PjIOZemULz/E2Bnm/2dcUOena75OTNkHI76uZBNUUq3A==",
|
||||||
"dev": true,
|
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
"type": "opencollective",
|
"type": "opencollective",
|
||||||
|
@ -3095,26 +3086,6 @@
|
||||||
"integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==",
|
"integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"node_modules/bootstrap": {
|
|
||||||
"version": "4.6.2",
|
|
||||||
"resolved": "https://registry.npmjs.org/bootstrap/-/bootstrap-4.6.2.tgz",
|
|
||||||
"integrity": "sha512-51Bbp/Uxr9aTuy6ca/8FbFloBUJZLHwnhTcnjIeRn2suQWsWzcuJhGjKDB5eppVte/8oCdOL3VuwxvZDUggwGQ==",
|
|
||||||
"dev": true,
|
|
||||||
"funding": [
|
|
||||||
{
|
|
||||||
"type": "github",
|
|
||||||
"url": "https://github.com/sponsors/twbs"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "opencollective",
|
|
||||||
"url": "https://opencollective.com/bootstrap"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"peerDependencies": {
|
|
||||||
"jquery": "1.9.1 - 3",
|
|
||||||
"popper.js": "^1.16.1"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/brace-expansion": {
|
"node_modules/brace-expansion": {
|
||||||
"version": "1.1.11",
|
"version": "1.1.11",
|
||||||
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
|
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
|
||||||
|
@ -4609,8 +4580,7 @@
|
||||||
"node_modules/csstype": {
|
"node_modules/csstype": {
|
||||||
"version": "3.1.3",
|
"version": "3.1.3",
|
||||||
"resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz",
|
"resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz",
|
||||||
"integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==",
|
"integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw=="
|
||||||
"dev": true
|
|
||||||
},
|
},
|
||||||
"node_modules/cyclist": {
|
"node_modules/cyclist": {
|
||||||
"version": "1.0.2",
|
"version": "1.0.2",
|
||||||
|
@ -7945,12 +7915,6 @@
|
||||||
"node": ">=8"
|
"node": ">=8"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/jquery": {
|
|
||||||
"version": "3.7.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/jquery/-/jquery-3.7.1.tgz",
|
|
||||||
"integrity": "sha512-m4avr8yL8kmFN8psrbFFFmB/If14iN5o9nw/NgnnM+kybDJpRsAynV2BsfpTYrTRysYUdADVD7CkUUizgkpLfg==",
|
|
||||||
"dev": true
|
|
||||||
},
|
|
||||||
"node_modules/js-tokens": {
|
"node_modules/js-tokens": {
|
||||||
"version": "4.0.0",
|
"version": "4.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
|
||||||
|
@ -8717,7 +8681,6 @@
|
||||||
"version": "3.3.11",
|
"version": "3.3.11",
|
||||||
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz",
|
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz",
|
||||||
"integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==",
|
"integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==",
|
||||||
"dev": true,
|
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
"type": "github",
|
"type": "github",
|
||||||
|
@ -9555,8 +9518,7 @@
|
||||||
"node_modules/picocolors": {
|
"node_modules/picocolors": {
|
||||||
"version": "1.1.1",
|
"version": "1.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz",
|
||||||
"integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==",
|
"integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA=="
|
||||||
"dev": true
|
|
||||||
},
|
},
|
||||||
"node_modules/picomatch": {
|
"node_modules/picomatch": {
|
||||||
"version": "2.3.1",
|
"version": "2.3.1",
|
||||||
|
@ -9613,17 +9575,6 @@
|
||||||
"node": ">=8"
|
"node": ">=8"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/popper.js": {
|
|
||||||
"version": "1.16.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/popper.js/-/popper.js-1.16.1.tgz",
|
|
||||||
"integrity": "sha512-Wb4p1J4zyFTbM+u6WuO4XstYx4Ky9Cewe4DWrel7B0w6VVICvPwdOpotjzcf6eD8TsckVnIMNONQyPIUFOUbCQ==",
|
|
||||||
"deprecated": "You can find the new Popper v2 at @popperjs/core, this package is dedicated to the legacy v1",
|
|
||||||
"dev": true,
|
|
||||||
"funding": {
|
|
||||||
"type": "opencollective",
|
|
||||||
"url": "https://opencollective.com/popperjs"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/portfinder": {
|
"node_modules/portfinder": {
|
||||||
"version": "1.0.37",
|
"version": "1.0.37",
|
||||||
"resolved": "https://registry.npmjs.org/portfinder/-/portfinder-1.0.37.tgz",
|
"resolved": "https://registry.npmjs.org/portfinder/-/portfinder-1.0.37.tgz",
|
||||||
|
@ -10557,7 +10508,6 @@
|
||||||
"version": "2.8.8",
|
"version": "2.8.8",
|
||||||
"resolved": "https://registry.npmjs.org/prettier/-/prettier-2.8.8.tgz",
|
"resolved": "https://registry.npmjs.org/prettier/-/prettier-2.8.8.tgz",
|
||||||
"integrity": "sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==",
|
"integrity": "sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==",
|
||||||
"dev": true,
|
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"bin": {
|
"bin": {
|
||||||
"prettier": "bin-prettier.js"
|
"prettier": "bin-prettier.js"
|
||||||
|
@ -12085,7 +12035,6 @@
|
||||||
"version": "0.6.1",
|
"version": "0.6.1",
|
||||||
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
|
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
|
||||||
"integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
|
"integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
|
||||||
"dev": true,
|
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=0.10.0"
|
"node": ">=0.10.0"
|
||||||
}
|
}
|
||||||
|
@ -12094,7 +12043,6 @@
|
||||||
"version": "1.2.1",
|
"version": "1.2.1",
|
||||||
"resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz",
|
"resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz",
|
||||||
"integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==",
|
"integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==",
|
||||||
"dev": true,
|
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=0.10.0"
|
"node": ">=0.10.0"
|
||||||
}
|
}
|
||||||
|
@ -13345,7 +13293,6 @@
|
||||||
"resolved": "https://registry.npmjs.org/vue/-/vue-2.7.16.tgz",
|
"resolved": "https://registry.npmjs.org/vue/-/vue-2.7.16.tgz",
|
||||||
"integrity": "sha512-4gCtFXaAA3zYZdTp5s4Hl2sozuySsgz4jy1EnpBHNfpMa9dK1ZCG7viqBPCwXtmgc8nHqUsAu3G4gtmXkkY3Sw==",
|
"integrity": "sha512-4gCtFXaAA3zYZdTp5s4Hl2sozuySsgz4jy1EnpBHNfpMa9dK1ZCG7viqBPCwXtmgc8nHqUsAu3G4gtmXkkY3Sw==",
|
||||||
"deprecated": "Vue 2 has reached EOL and is no longer actively maintained. See https://v2.vuejs.org/eol/ for more details.",
|
"deprecated": "Vue 2 has reached EOL and is no longer actively maintained. See https://v2.vuejs.org/eol/ for more details.",
|
||||||
"dev": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@vue/compiler-sfc": "2.7.16",
|
"@vue/compiler-sfc": "2.7.16",
|
||||||
"csstype": "^3.1.0"
|
"csstype": "^3.1.0"
|
||||||
|
@ -13463,6 +13410,14 @@
|
||||||
"integrity": "sha512-4gDntzrifFnCEvyoO8PqyJDmguXgVPxKiIxrBKjIowvL9l+N66196+72XVYR8BBf1Uv1Fgt3bGevJ+sEmxfZzw==",
|
"integrity": "sha512-4gDntzrifFnCEvyoO8PqyJDmguXgVPxKiIxrBKjIowvL9l+N66196+72XVYR8BBf1Uv1Fgt3bGevJ+sEmxfZzw==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"node_modules/vuex": {
|
||||||
|
"version": "3.6.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/vuex/-/vuex-3.6.2.tgz",
|
||||||
|
"integrity": "sha512-ETW44IqCgBpVomy520DT5jf8n0zoCac+sxWnn+hMe/CzaSejb/eVw2YToiXYX+Ex/AuHHia28vWTq4goAexFbw==",
|
||||||
|
"peerDependencies": {
|
||||||
|
"vue": "^2.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/watchpack": {
|
"node_modules/watchpack": {
|
||||||
"version": "1.7.5",
|
"version": "1.7.5",
|
||||||
"resolved": "https://registry.npmjs.org/watchpack/-/watchpack-1.7.5.tgz",
|
"resolved": "https://registry.npmjs.org/watchpack/-/watchpack-1.7.5.tgz",
|
||||||
|
@ -15238,14 +15193,12 @@
|
||||||
"@babel/helper-string-parser": {
|
"@babel/helper-string-parser": {
|
||||||
"version": "7.27.1",
|
"version": "7.27.1",
|
||||||
"resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz",
|
"resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz",
|
||||||
"integrity": "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==",
|
"integrity": "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA=="
|
||||||
"dev": true
|
|
||||||
},
|
},
|
||||||
"@babel/helper-validator-identifier": {
|
"@babel/helper-validator-identifier": {
|
||||||
"version": "7.27.1",
|
"version": "7.27.1",
|
||||||
"resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.27.1.tgz",
|
"resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.27.1.tgz",
|
||||||
"integrity": "sha512-D2hP9eA+Sqx1kBZgzxZh0y1trbuU+JoDkiEwqhQ36nodYqJwyEIhPSdMNd7lOm/4io72luTPWH20Yda0xOuUow==",
|
"integrity": "sha512-D2hP9eA+Sqx1kBZgzxZh0y1trbuU+JoDkiEwqhQ36nodYqJwyEIhPSdMNd7lOm/4io72luTPWH20Yda0xOuUow=="
|
||||||
"dev": true
|
|
||||||
},
|
},
|
||||||
"@babel/helper-validator-option": {
|
"@babel/helper-validator-option": {
|
||||||
"version": "7.27.1",
|
"version": "7.27.1",
|
||||||
|
@ -15278,7 +15231,6 @@
|
||||||
"version": "7.27.2",
|
"version": "7.27.2",
|
||||||
"resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.27.2.tgz",
|
"resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.27.2.tgz",
|
||||||
"integrity": "sha512-QYLs8299NA7WM/bZAdp+CviYYkVoYXlDW2rzliy3chxd1PQjej7JORuMJDJXJUb9g0TT+B99EwaVLKmX+sPXWw==",
|
"integrity": "sha512-QYLs8299NA7WM/bZAdp+CviYYkVoYXlDW2rzliy3chxd1PQjej7JORuMJDJXJUb9g0TT+B99EwaVLKmX+sPXWw==",
|
||||||
"dev": true,
|
|
||||||
"requires": {
|
"requires": {
|
||||||
"@babel/types": "^7.27.1"
|
"@babel/types": "^7.27.1"
|
||||||
}
|
}
|
||||||
|
@ -16040,7 +15992,6 @@
|
||||||
"version": "7.27.1",
|
"version": "7.27.1",
|
||||||
"resolved": "https://registry.npmjs.org/@babel/types/-/types-7.27.1.tgz",
|
"resolved": "https://registry.npmjs.org/@babel/types/-/types-7.27.1.tgz",
|
||||||
"integrity": "sha512-+EzkxvLNfiUeKMgy/3luqfsCWFRXLb7U6wNQTk60tovuckwB15B191tJWvpp4HjiQWdJkCxO3Wbvc6jlk3Xb2Q==",
|
"integrity": "sha512-+EzkxvLNfiUeKMgy/3luqfsCWFRXLb7U6wNQTk60tovuckwB15B191tJWvpp4HjiQWdJkCxO3Wbvc6jlk3Xb2Q==",
|
||||||
"dev": true,
|
|
||||||
"requires": {
|
"requires": {
|
||||||
"@babel/helper-string-parser": "^7.27.1",
|
"@babel/helper-string-parser": "^7.27.1",
|
||||||
"@babel/helper-validator-identifier": "^7.27.1"
|
"@babel/helper-validator-identifier": "^7.27.1"
|
||||||
|
@ -16309,7 +16260,6 @@
|
||||||
"version": "2.7.16",
|
"version": "2.7.16",
|
||||||
"resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-2.7.16.tgz",
|
"resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-2.7.16.tgz",
|
||||||
"integrity": "sha512-KWhJ9k5nXuNtygPU7+t1rX6baZeqOYLEforUPjgNDBnLicfHCoi48H87Q8XyLZOrNNsmhuwKqtpDQWjEFe6Ekg==",
|
"integrity": "sha512-KWhJ9k5nXuNtygPU7+t1rX6baZeqOYLEforUPjgNDBnLicfHCoi48H87Q8XyLZOrNNsmhuwKqtpDQWjEFe6Ekg==",
|
||||||
"dev": true,
|
|
||||||
"requires": {
|
"requires": {
|
||||||
"@babel/parser": "^7.23.5",
|
"@babel/parser": "^7.23.5",
|
||||||
"postcss": "^8.4.14",
|
"postcss": "^8.4.14",
|
||||||
|
@ -16321,7 +16271,6 @@
|
||||||
"version": "8.5.3",
|
"version": "8.5.3",
|
||||||
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.3.tgz",
|
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.3.tgz",
|
||||||
"integrity": "sha512-dle9A3yYxlBSrt8Fu+IpjGT8SY8hN0mlaA6GY8t0P5PjIOZemULz/E2Bnm/2dcUOena75OTNkHI76uZBNUUq3A==",
|
"integrity": "sha512-dle9A3yYxlBSrt8Fu+IpjGT8SY8hN0mlaA6GY8t0P5PjIOZemULz/E2Bnm/2dcUOena75OTNkHI76uZBNUUq3A==",
|
||||||
"dev": true,
|
|
||||||
"requires": {
|
"requires": {
|
||||||
"nanoid": "^3.3.8",
|
"nanoid": "^3.3.8",
|
||||||
"picocolors": "^1.1.1",
|
"picocolors": "^1.1.1",
|
||||||
|
@ -17166,13 +17115,6 @@
|
||||||
"integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==",
|
"integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"bootstrap": {
|
|
||||||
"version": "4.6.2",
|
|
||||||
"resolved": "https://registry.npmjs.org/bootstrap/-/bootstrap-4.6.2.tgz",
|
|
||||||
"integrity": "sha512-51Bbp/Uxr9aTuy6ca/8FbFloBUJZLHwnhTcnjIeRn2suQWsWzcuJhGjKDB5eppVte/8oCdOL3VuwxvZDUggwGQ==",
|
|
||||||
"dev": true,
|
|
||||||
"requires": {}
|
|
||||||
},
|
|
||||||
"brace-expansion": {
|
"brace-expansion": {
|
||||||
"version": "1.1.11",
|
"version": "1.1.11",
|
||||||
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
|
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
|
||||||
|
@ -18344,8 +18286,7 @@
|
||||||
"csstype": {
|
"csstype": {
|
||||||
"version": "3.1.3",
|
"version": "3.1.3",
|
||||||
"resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz",
|
"resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz",
|
||||||
"integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==",
|
"integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw=="
|
||||||
"dev": true
|
|
||||||
},
|
},
|
||||||
"cyclist": {
|
"cyclist": {
|
||||||
"version": "1.0.2",
|
"version": "1.0.2",
|
||||||
|
@ -20905,12 +20846,6 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"jquery": {
|
|
||||||
"version": "3.7.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/jquery/-/jquery-3.7.1.tgz",
|
|
||||||
"integrity": "sha512-m4avr8yL8kmFN8psrbFFFmB/If14iN5o9nw/NgnnM+kybDJpRsAynV2BsfpTYrTRysYUdADVD7CkUUizgkpLfg==",
|
|
||||||
"dev": true
|
|
||||||
},
|
|
||||||
"js-tokens": {
|
"js-tokens": {
|
||||||
"version": "4.0.0",
|
"version": "4.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
|
||||||
|
@ -21555,8 +21490,7 @@
|
||||||
"nanoid": {
|
"nanoid": {
|
||||||
"version": "3.3.11",
|
"version": "3.3.11",
|
||||||
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz",
|
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz",
|
||||||
"integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==",
|
"integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w=="
|
||||||
"dev": true
|
|
||||||
},
|
},
|
||||||
"nanomatch": {
|
"nanomatch": {
|
||||||
"version": "1.2.13",
|
"version": "1.2.13",
|
||||||
|
@ -22207,8 +22141,7 @@
|
||||||
"picocolors": {
|
"picocolors": {
|
||||||
"version": "1.1.1",
|
"version": "1.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz",
|
||||||
"integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==",
|
"integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA=="
|
||||||
"dev": true
|
|
||||||
},
|
},
|
||||||
"picomatch": {
|
"picomatch": {
|
||||||
"version": "2.3.1",
|
"version": "2.3.1",
|
||||||
|
@ -22247,12 +22180,6 @@
|
||||||
"find-up": "^4.0.0"
|
"find-up": "^4.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"popper.js": {
|
|
||||||
"version": "1.16.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/popper.js/-/popper.js-1.16.1.tgz",
|
|
||||||
"integrity": "sha512-Wb4p1J4zyFTbM+u6WuO4XstYx4Ky9Cewe4DWrel7B0w6VVICvPwdOpotjzcf6eD8TsckVnIMNONQyPIUFOUbCQ==",
|
|
||||||
"dev": true
|
|
||||||
},
|
|
||||||
"portfinder": {
|
"portfinder": {
|
||||||
"version": "1.0.37",
|
"version": "1.0.37",
|
||||||
"resolved": "https://registry.npmjs.org/portfinder/-/portfinder-1.0.37.tgz",
|
"resolved": "https://registry.npmjs.org/portfinder/-/portfinder-1.0.37.tgz",
|
||||||
|
@ -23060,7 +22987,6 @@
|
||||||
"version": "2.8.8",
|
"version": "2.8.8",
|
||||||
"resolved": "https://registry.npmjs.org/prettier/-/prettier-2.8.8.tgz",
|
"resolved": "https://registry.npmjs.org/prettier/-/prettier-2.8.8.tgz",
|
||||||
"integrity": "sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==",
|
"integrity": "sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==",
|
||||||
"dev": true,
|
|
||||||
"optional": true
|
"optional": true
|
||||||
},
|
},
|
||||||
"private": {
|
"private": {
|
||||||
|
@ -24290,14 +24216,12 @@
|
||||||
"source-map": {
|
"source-map": {
|
||||||
"version": "0.6.1",
|
"version": "0.6.1",
|
||||||
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
|
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
|
||||||
"integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
|
"integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="
|
||||||
"dev": true
|
|
||||||
},
|
},
|
||||||
"source-map-js": {
|
"source-map-js": {
|
||||||
"version": "1.2.1",
|
"version": "1.2.1",
|
||||||
"resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz",
|
"resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz",
|
||||||
"integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==",
|
"integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA=="
|
||||||
"dev": true
|
|
||||||
},
|
},
|
||||||
"source-map-resolve": {
|
"source-map-resolve": {
|
||||||
"version": "0.5.3",
|
"version": "0.5.3",
|
||||||
|
@ -25287,7 +25211,6 @@
|
||||||
"version": "2.7.16",
|
"version": "2.7.16",
|
||||||
"resolved": "https://registry.npmjs.org/vue/-/vue-2.7.16.tgz",
|
"resolved": "https://registry.npmjs.org/vue/-/vue-2.7.16.tgz",
|
||||||
"integrity": "sha512-4gCtFXaAA3zYZdTp5s4Hl2sozuySsgz4jy1EnpBHNfpMa9dK1ZCG7viqBPCwXtmgc8nHqUsAu3G4gtmXkkY3Sw==",
|
"integrity": "sha512-4gCtFXaAA3zYZdTp5s4Hl2sozuySsgz4jy1EnpBHNfpMa9dK1ZCG7viqBPCwXtmgc8nHqUsAu3G4gtmXkkY3Sw==",
|
||||||
"dev": true,
|
|
||||||
"requires": {
|
"requires": {
|
||||||
"@vue/compiler-sfc": "2.7.16",
|
"@vue/compiler-sfc": "2.7.16",
|
||||||
"csstype": "^3.1.0"
|
"csstype": "^3.1.0"
|
||||||
|
@ -25382,6 +25305,12 @@
|
||||||
"integrity": "sha512-4gDntzrifFnCEvyoO8PqyJDmguXgVPxKiIxrBKjIowvL9l+N66196+72XVYR8BBf1Uv1Fgt3bGevJ+sEmxfZzw==",
|
"integrity": "sha512-4gDntzrifFnCEvyoO8PqyJDmguXgVPxKiIxrBKjIowvL9l+N66196+72XVYR8BBf1Uv1Fgt3bGevJ+sEmxfZzw==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"vuex": {
|
||||||
|
"version": "3.6.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/vuex/-/vuex-3.6.2.tgz",
|
||||||
|
"integrity": "sha512-ETW44IqCgBpVomy520DT5jf8n0zoCac+sxWnn+hMe/CzaSejb/eVw2YToiXYX+Ex/AuHHia28vWTq4goAexFbw==",
|
||||||
|
"requires": {}
|
||||||
|
},
|
||||||
"watchpack": {
|
"watchpack": {
|
||||||
"version": "1.7.5",
|
"version": "1.7.5",
|
||||||
"resolved": "https://registry.npmjs.org/watchpack/-/watchpack-1.7.5.tgz",
|
"resolved": "https://registry.npmjs.org/watchpack/-/watchpack-1.7.5.tgz",
|
||||||
|
|
|
@ -11,12 +11,8 @@
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"axios": "^0.19.2",
|
"axios": "^0.19.2",
|
||||||
"bootstrap": "^4.0.0",
|
|
||||||
"cross-env": "^7.0.3",
|
"cross-env": "^7.0.3",
|
||||||
"jquery": "^3.2",
|
|
||||||
"laravel-mix": "^5.0.1",
|
"laravel-mix": "^5.0.1",
|
||||||
"lodash": "^4.17.19",
|
|
||||||
"popper.js": "^1.12",
|
|
||||||
"resolve-url-loader": "^2.3.1",
|
"resolve-url-loader": "^2.3.1",
|
||||||
"sass": "^1.20.1",
|
"sass": "^1.20.1",
|
||||||
"sass-loader": "^8.0.0",
|
"sass-loader": "^8.0.0",
|
||||||
|
@ -27,6 +23,7 @@
|
||||||
"animate.css": "^4.1.1",
|
"animate.css": "^4.1.1",
|
||||||
"bulma": "^0.9.4",
|
"bulma": "^0.9.4",
|
||||||
"bulma-switch": "^2.0.4",
|
"bulma-switch": "^2.0.4",
|
||||||
"bulma-toast": "^2.4.1"
|
"bulma-toast": "^2.4.1",
|
||||||
|
"vuex": "^3.6.2"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
114
resources/js/app.js
vendored
114
resources/js/app.js
vendored
|
@ -5,6 +5,7 @@
|
||||||
*/
|
*/
|
||||||
import axios from 'axios';
|
import axios from 'axios';
|
||||||
import Vue from 'vue';
|
import Vue from 'vue';
|
||||||
|
|
||||||
window.Vue = require('vue');
|
window.Vue = require('vue');
|
||||||
window.Event = new Vue();
|
window.Event = new Vue();
|
||||||
window.axios = axios;
|
window.axios = axios;
|
||||||
|
@ -18,21 +19,12 @@ window.bulmaToast = require('bulma-toast');
|
||||||
* Eg. ./components/ExampleComponent.vue -> <example-component></example-component>
|
* Eg. ./components/ExampleComponent.vue -> <example-component></example-component>
|
||||||
*/
|
*/
|
||||||
import './components';
|
import './components';
|
||||||
|
import store from "./store";
|
||||||
|
|
||||||
/**
|
|
||||||
* Constants
|
|
||||||
*/
|
|
||||||
Vue.prototype.$rootMiga = {
|
|
||||||
nombre: "Categorías",
|
|
||||||
href: "/productos"
|
|
||||||
}
|
|
||||||
/**
|
/**
|
||||||
* Global methods
|
* Global methods
|
||||||
*/
|
*/
|
||||||
Vue.prototype.$settearProducto = function(cantidad, id) {
|
Vue.prototype.$toast = function (mensaje, duration = 2000) {
|
||||||
Event.$emit("sync-subpedido", this.cant, this.producto.id)
|
|
||||||
}
|
|
||||||
Vue.prototype.$toast = function(mensaje, duration = 2000) {
|
|
||||||
return window.bulmaToast.toast({
|
return window.bulmaToast.toast({
|
||||||
message: mensaje,
|
message: mensaje,
|
||||||
duration: duration,
|
duration: duration,
|
||||||
|
@ -40,110 +32,14 @@ Vue.prototype.$toast = function(mensaje, duration = 2000) {
|
||||||
position: 'bottom-center',
|
position: 'bottom-center',
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
Vue.prototype.$limpiarFloat = function(unFloat) {
|
|
||||||
return parseFloat(unFloat.replace(/,/g, ''))
|
|
||||||
}
|
|
||||||
Vue.prototype.$limpiarInt = function(unInt) {
|
|
||||||
return parseInt(unInt.replace(/,/g, ''))
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Next, we will create a fresh Vue application instance and attach it to
|
* Next, we will create a fresh Vue application instance and attach it to
|
||||||
* the page. Then, you may begin adding components to this application
|
* the page. Then, you may begin adding components to this application
|
||||||
* or customize the JavaScript scaffolding to fit your unique needs.
|
* or customize the JavaScript scaffolding to fit your unique needs.
|
||||||
*/
|
*/
|
||||||
const app = new Vue({
|
new Vue({
|
||||||
el: '#root',
|
el: '#root',
|
||||||
data() {
|
store,
|
||||||
return {
|
|
||||||
gdc: null,
|
|
||||||
pedido: null,
|
|
||||||
devoluciones: null,
|
|
||||||
}
|
|
||||||
},
|
|
||||||
computed: {
|
|
||||||
productos: function() {
|
|
||||||
return this.pedido.productos
|
|
||||||
}
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
cantidad(producto) {
|
|
||||||
let pedido = this.productos.some(p => p.id == producto.id)
|
|
||||||
return pedido ? this.productos.find(p => p.id == producto.id).pivot.cantidad : 0
|
|
||||||
},
|
|
||||||
notas(producto) {
|
|
||||||
let pedido = this.productos.some(p => p.id == producto.id);
|
|
||||||
return pedido ? this.productos.find(p => p.id == producto.id).pivot.notas : "";
|
|
||||||
},
|
|
||||||
settearDevoluciones() {
|
|
||||||
axios.get(`/api/grupos-de-compra/${this.gdc}/devoluciones`)
|
|
||||||
.then(response => {
|
|
||||||
this.devoluciones = response.data.devoluciones;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
},
|
|
||||||
mounted() {
|
|
||||||
Event.$on('obtener-sesion', () => {
|
|
||||||
axios.get('/subpedidos/obtener_sesion')
|
|
||||||
.then(response => {
|
|
||||||
if (response.data.subpedido.id) {
|
|
||||||
this.gdc = response.data.gdc;
|
|
||||||
this.settearDevoluciones();
|
|
||||||
this.pedido = response.data.subpedido.id;
|
|
||||||
axios.get('/api/subpedidos/' + this.pedido)
|
|
||||||
.then(response => {
|
|
||||||
this.pedido = response.data.data;
|
|
||||||
Event.$emit("pedido-actualizado");
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
axios.get('/admin/obtener_sesion')
|
|
||||||
.then(response => {
|
|
||||||
this.gdc = response.data.gdc
|
|
||||||
});
|
|
||||||
}
|
|
||||||
})
|
|
||||||
})
|
|
||||||
Event.$on('sync-subpedido', (cantidad, id, notas) => {
|
|
||||||
if (this.pedido.aprobado) {
|
|
||||||
this.$toast('No se puede modificar un pedido ya aprobado', 2000);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
axios.post("/api/subpedidos/" + this.pedido.id + "/sync", {
|
|
||||||
cantidad: cantidad,
|
|
||||||
producto_id: id,
|
|
||||||
notas: notas,
|
|
||||||
}).then((response) => {
|
|
||||||
this.pedido = response.data.data
|
|
||||||
this.$toast('Pedido actualizado exitosamente')
|
|
||||||
Event.$emit("pedido-actualizado");
|
|
||||||
});
|
|
||||||
});
|
|
||||||
// Actualizar monto y notas de devoluciones
|
|
||||||
Event.$on('sync-devoluciones', (total, notas) => {
|
|
||||||
if (this.pedido.aprobado) {
|
|
||||||
this.$toast('No se puede modificar un pedido ya aprobado', 2000);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
axios.post("api/subpedidos/" + this.pedido.id + "/sync_devoluciones", {
|
|
||||||
total: total,
|
|
||||||
notas: notas,
|
|
||||||
}).then((response) => {
|
|
||||||
this.pedido = response.data.data;
|
|
||||||
this.$toast('Pedido actualizado');
|
|
||||||
Event.$emit("pedido-actualizado");
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
Event.$on('aprobacion-subpedido', (subpedidoId, aprobado) => {
|
|
||||||
axios.post("/api/admin/subpedidos/" + subpedidoId + "/aprobacion", {
|
|
||||||
aprobacion: aprobado
|
|
||||||
}).then((response) => {
|
|
||||||
Event.$emit('sync-aprobacion', response.data.data);
|
|
||||||
this.$toast('Pedido ' + (aprobado ? 'aprobado' : 'desaprobado') + ' exitosamente')
|
|
||||||
})
|
|
||||||
})
|
|
||||||
Event.$emit('obtener-sesion')
|
|
||||||
},
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
41
resources/js/bootstrap.js
vendored
41
resources/js/bootstrap.js
vendored
|
@ -1,41 +0,0 @@
|
||||||
window._ = require('lodash');
|
|
||||||
|
|
||||||
/**
|
|
||||||
* We'll load jQuery and the Bootstrap jQuery plugin which provides support
|
|
||||||
* for JavaScript based Bootstrap features such as modals and tabs. This
|
|
||||||
* code may be modified to fit the specific needs of your application.
|
|
||||||
*/
|
|
||||||
|
|
||||||
try {
|
|
||||||
window.Popper = require('popper.js').default;
|
|
||||||
window.$ = window.jQuery = require('jquery');
|
|
||||||
|
|
||||||
require('bootstrap');
|
|
||||||
} catch (e) {}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* We'll load the axios HTTP library which allows us to easily issue requests
|
|
||||||
* to our Laravel back-end. This library automatically handles sending the
|
|
||||||
* CSRF token as a header based on the value of the "XSRF" token cookie.
|
|
||||||
*/
|
|
||||||
|
|
||||||
window.axios = require('axios');
|
|
||||||
|
|
||||||
window.axios.defaults.headers.common['X-Requested-With'] = 'XMLHttpRequest';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Echo exposes an expressive API for subscribing to channels and listening
|
|
||||||
* for events that are broadcast by Laravel. Echo and event broadcasting
|
|
||||||
* allows your team to easily build robust real-time web applications.
|
|
||||||
*/
|
|
||||||
|
|
||||||
// import Echo from 'laravel-echo';
|
|
||||||
|
|
||||||
// window.Pusher = require('pusher-js');
|
|
||||||
|
|
||||||
// window.Echo = new Echo({
|
|
||||||
// broadcaster: 'pusher',
|
|
||||||
// key: process.env.MIX_PUSHER_APP_KEY,
|
|
||||||
// cluster: process.env.MIX_PUSHER_APP_CLUSTER,
|
|
||||||
// forceTLS: true
|
|
||||||
// });
|
|
28
resources/js/components/AppLogin.vue
Normal file
28
resources/js/components/AppLogin.vue
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
<script>
|
||||||
|
import LoginInput from "./login/LoginInput.vue";
|
||||||
|
import LoginLoginTitulos from "./login/LoginTitulos.vue";
|
||||||
|
import { mapGetters } from "vuex";
|
||||||
|
import LoginDropdown from "./login/LoginDropdown.vue";
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'LoginForm',
|
||||||
|
components: { LoginDropdown, LoginTitulos: LoginLoginTitulos, LoginInput },
|
||||||
|
computed: {
|
||||||
|
...mapGetters("login", ["estilos"])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div id="login-form" :class="estilos.fondo">
|
||||||
|
<section class="section">
|
||||||
|
<login-dropdown class="is-hidden-tablet"/>
|
||||||
|
<login-titulos/>
|
||||||
|
<login-input/>
|
||||||
|
</section>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
|
||||||
|
</style>
|
35
resources/js/components/AppMain.vue
Normal file
35
resources/js/components/AppMain.vue
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
<script>
|
||||||
|
import NavBar from "./comunes/NavBar.vue";
|
||||||
|
import { mapActions, mapState } from "vuex";
|
||||||
|
import ComisionesBody from "./comisiones/Body.vue";
|
||||||
|
import AdminBody from "./admin/Body.vue";
|
||||||
|
import PedidosBody from "./pedidos/Body.vue";
|
||||||
|
import InfoTags from "./comunes/InfoTags.vue";
|
||||||
|
export default {
|
||||||
|
name: 'Main',
|
||||||
|
components: { InfoTags, ComisionesBody, AdminBody, PedidosBody, NavBar },
|
||||||
|
computed: {
|
||||||
|
...mapState("login", ["rol"]),
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
...mapActions("login", ["getRol"]),
|
||||||
|
},
|
||||||
|
async mounted() {
|
||||||
|
await this.getRol();
|
||||||
|
},
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div id="app-main">
|
||||||
|
<nav-bar/>
|
||||||
|
<pedidos-body v-if="rol === 'barrio'"/>
|
||||||
|
<admin-body v-else-if="rol === 'admin_barrio'"/>
|
||||||
|
<comisiones-body v-else-if="rol === 'comision'"/>
|
||||||
|
<info-tags/>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
|
||||||
|
</style>
|
|
@ -1,15 +1,11 @@
|
||||||
<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">
|
||||||
<comunes-tabs-secciones :tabs="tabs" :tabInicial="tabActiva"></comunes-tabs-secciones>
|
<tabs-secciones :tabs="tabs" :tabInicial="tabActiva"/>
|
||||||
<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-if="hayPedidos">
|
<div class="block pb-6" id="pedidos-tabla-y-dropdown" v-if="hayPedidos">
|
||||||
<admin-dropdown-descargar
|
<dropdown-descargar/>
|
||||||
:gdc_id="gdc.id">
|
<tabla-pedidos/>
|
||||||
</admin-dropdown-descargar>
|
|
||||||
<admin-tabla-pedidos
|
|
||||||
:gdc="this.gdc"
|
|
||||||
></admin-tabla-pedidos>
|
|
||||||
</div>
|
</div>
|
||||||
<p class="has-text-centered" v-else>
|
<p class="has-text-centered" v-else>
|
||||||
Todavía no hay ningún pedido para administrar.
|
Todavía no hay ningún pedido para administrar.
|
||||||
|
@ -17,8 +13,7 @@
|
||||||
</div>
|
</div>
|
||||||
<div class="block pb-6" id="caracteristicas-seccion"
|
<div class="block pb-6" id="caracteristicas-seccion"
|
||||||
:class="seccionActiva === 'caracteristicas-seccion' ? 'is-active' : 'is-hidden'">
|
:class="seccionActiva === 'caracteristicas-seccion' ? 'is-active' : 'is-hidden'">
|
||||||
<admin-caracteristicas-opcionales>
|
<caracteristicas-opcionales/>
|
||||||
</admin-caracteristicas-opcionales>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
@ -28,19 +23,17 @@ import CaracteristicasOpcionales from "./CaracteristicasOpcionales.vue";
|
||||||
import TabsSecciones from "../comunes/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 { mapActions, mapGetters } from "vuex";
|
||||||
import axios from "axios";
|
|
||||||
export default {
|
export default {
|
||||||
|
name: "AdminBody",
|
||||||
components: {
|
components: {
|
||||||
CaracteristicasOpcionales,
|
CaracteristicasOpcionales,
|
||||||
TabsSecciones,
|
TabsSecciones,
|
||||||
DropdownDescargar,
|
DropdownDescargar,
|
||||||
TablaPedidos,
|
TablaPedidos,
|
||||||
TablaBonos,
|
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
gdc: undefined,
|
|
||||||
tabs: [{ id: "pedidos", nombre: "Pedidos" },
|
tabs: [{ id: "pedidos", nombre: "Pedidos" },
|
||||||
{ id: "caracteristicas", nombre: "Caracteristicas opcionales" }],
|
{ id: "caracteristicas", nombre: "Caracteristicas opcionales" }],
|
||||||
tabActiva: "pedidos",
|
tabActiva: "pedidos",
|
||||||
|
@ -48,32 +41,17 @@ export default {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
hayPedidos: function() {
|
...mapGetters('admin', ['hayPedidos']),
|
||||||
return this.gdc && this.gdc.pedidos.length !== 0
|
|
||||||
},
|
|
||||||
hayAprobados: function() {
|
|
||||||
return this.gdc && this.gdc.pedidos.filter(p => p.aprobado).length > 0
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
...mapActions('admin', ['getGrupoDeCompra']),
|
||||||
setSeccionActiva(tabId) {
|
setSeccionActiva(tabId) {
|
||||||
this.tabActiva = tabId;
|
this.tabActiva = tabId;
|
||||||
this.seccionActiva = tabId + "-seccion";
|
this.seccionActiva = tabId + "-seccion";
|
||||||
},
|
},
|
||||||
actualizar() {
|
|
||||||
axios.get('/api/grupos-de-compra/' + this.$root.gdc)
|
|
||||||
.then(response => {
|
|
||||||
this.gdc = response.data.data;
|
|
||||||
console.log(this.gdc);
|
|
||||||
})
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
async mounted() {
|
async mounted() {
|
||||||
Event.$on('sync-aprobacion', (_) => {
|
await this.getGrupoDeCompra();
|
||||||
this.actualizar();
|
|
||||||
});
|
|
||||||
await new Promise(r => setTimeout(r, 1000));
|
|
||||||
this.actualizar();
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -1,12 +0,0 @@
|
||||||
<template>
|
|
||||||
<div class="buttons is-right">
|
|
||||||
<a class="button is-danger is-light is-small" href="/admin">
|
|
||||||
<span class="icon">
|
|
||||||
<i class="fa fa-solid fa-user-check"></i>
|
|
||||||
</span>
|
|
||||||
<span>
|
|
||||||
Admin
|
|
||||||
</span>
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
|
@ -8,8 +8,7 @@ export default {
|
||||||
caracteristicas: [
|
caracteristicas: [
|
||||||
{
|
{
|
||||||
id: "devoluciones",
|
id: "devoluciones",
|
||||||
nombre: "Devoluciones",
|
nombre: "Devoluciones"
|
||||||
habilitada: false
|
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
@ -27,16 +26,15 @@ export default {
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
<admin-fila-caracteristica
|
<fila-caracteristica
|
||||||
v-for="(c,i) in caracteristicas"
|
v-for="(c,i) in caracteristicas"
|
||||||
:key="i"
|
:key="i"
|
||||||
:caracteristica="c">
|
:caracteristica="c"
|
||||||
</admin-fila-caracteristica>
|
/>
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
|
|
||||||
</style>
|
</style>
|
||||||
|
|
|
@ -14,13 +14,13 @@
|
||||||
</div>
|
</div>
|
||||||
<div class="dropdown-menu" id="dropdown-menu" role="menu">
|
<div class="dropdown-menu" id="dropdown-menu" role="menu">
|
||||||
<div class="dropdown-content">
|
<div class="dropdown-content">
|
||||||
<a :href="'/admin/exportar-pedido-a-csv/' + gdc_id" class="dropdown-item has-background-primary">
|
<a :href="'/admin/exportar-pedido-a-csv/' + grupo_de_compra_id" class="dropdown-item has-background-primary">
|
||||||
Planilla para central (CSV)
|
Planilla para central (CSV)
|
||||||
</a>
|
</a>
|
||||||
<a :href="'/admin/exportar-planillas-a-pdf/' + gdc_id" class="dropdown-item">
|
<a :href="'/admin/exportar-planillas-a-pdf/' + grupo_de_compra_id" class="dropdown-item">
|
||||||
Planillas para armado (PDF)
|
Planillas para armado (PDF)
|
||||||
</a>
|
</a>
|
||||||
<a :href="'/admin/exportar-pedido-con-nucleos-a-csv/' + gdc_id" class="dropdown-item">
|
<a :href="'/admin/exportar-pedido-con-nucleos-a-csv/' + grupo_de_compra_id" class="dropdown-item">
|
||||||
Planilla completa de la canasta (CSV)
|
Planilla completa de la canasta (CSV)
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
|
@ -30,27 +30,18 @@
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
import { mapGetters, mapState } from "vuex";
|
||||||
export default {
|
export default {
|
||||||
props: {
|
|
||||||
gdc_id: {
|
|
||||||
type: Number,
|
|
||||||
required: true
|
|
||||||
},
|
|
||||||
},
|
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
dropdownActivo: false
|
dropdownActivo: false
|
||||||
}
|
};
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
hayAprobados: function() {
|
...mapState('admin', ["grupo_de_compra_id"]),
|
||||||
return this.$parent.hayAprobados;
|
...mapGetters('admin', ["hayAprobados"]),
|
||||||
}
|
|
||||||
},
|
},
|
||||||
|
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style>
|
<style></style>
|
||||||
|
|
||||||
</style>
|
|
||||||
|
|
|
@ -1,48 +1,19 @@
|
||||||
<script>
|
<script>
|
||||||
import axios from "axios";
|
import {mapActions, mapGetters, mapState} from "vuex";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
props: {
|
props: {
|
||||||
caracteristica: Object
|
caracteristica: Object
|
||||||
},
|
},
|
||||||
data() {
|
computed: {
|
||||||
return {
|
...mapState('admin',["grupo_de_compra_id"]),
|
||||||
gdc: undefined
|
...mapGetters('admin',["getCaracteristica"]),
|
||||||
|
habilitada() {
|
||||||
|
return this.getCaracteristica(this.caracteristica.id);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
watch: {
|
|
||||||
'$root.gdc' : {
|
|
||||||
handler(newValue) {
|
|
||||||
if (newValue) {
|
|
||||||
this.gdc = newValue;
|
|
||||||
this.obtenerValor();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
},
|
|
||||||
methods: {
|
methods: {
|
||||||
toggleActivacion() {
|
...mapActions('admin',["toggleCaracteristica"]),
|
||||||
const id = this.caracteristica.id;
|
|
||||||
axios.post(`/api/grupos-de-compra/${this.gdc}/${id}`)
|
|
||||||
.then(response => {
|
|
||||||
this.caracteristica.habilitada = response.data[id];
|
|
||||||
this.$root[id] = response.data[id];
|
|
||||||
});
|
|
||||||
},
|
|
||||||
obtenerValor() {
|
|
||||||
const id = this.caracteristica.id;
|
|
||||||
axios.get(`/api/grupos-de-compra/${this.gdc}/${id}`)
|
|
||||||
.then(response => {
|
|
||||||
this.caracteristica.habilitada = response.data[id];
|
|
||||||
this.$root[id] = response.data[id];
|
|
||||||
});
|
|
||||||
},
|
|
||||||
},
|
|
||||||
mounted() {
|
|
||||||
if (this.$root.gdc) {
|
|
||||||
this.gdc = this.$root.gdc;
|
|
||||||
this.obtenerValor();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
@ -53,17 +24,17 @@ export default {
|
||||||
<td>
|
<td>
|
||||||
<div class="field">
|
<div class="field">
|
||||||
<input type="checkbox" class="switch is-rounded is-success"
|
<input type="checkbox" class="switch is-rounded is-success"
|
||||||
:id="'switch-'+caracteristica.id"
|
:id="'switch-' + caracteristica.id"
|
||||||
:checked="caracteristica.habilitada"
|
:checked="habilitada"
|
||||||
@change="toggleActivacion(caracteristica)">
|
@change="toggleCaracteristica({ caracteristica_id: caracteristica.id })">
|
||||||
<label :for="'switch-'+caracteristica.id">
|
<label :for="'switch-' + caracteristica.id">
|
||||||
<span class="is-hidden-mobile">{{ caracteristica.habilitada ? 'Habilitada' : 'Deshabilitada' }}</span>
|
<span class="is-hidden-mobile">
|
||||||
|
{{ habilitada ? 'Habilitada' : 'Deshabilitada' }}
|
||||||
|
</span>
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped></style>
|
||||||
|
|
||||||
</style>
|
|
||||||
|
|
|
@ -1,36 +1,41 @@
|
||||||
<template>
|
<template>
|
||||||
<tr>
|
<tr>
|
||||||
<td>{{ pedido.nombre }}</td>
|
<td>{{ pedido.nombre }}</td>
|
||||||
<td v-if="$root.devoluciones" class="has-text-right" >{{ pedido.total_sin_devoluciones }}</td>
|
<td v-if="devoluciones_habilitadas" class="has-text-right" >
|
||||||
<td v-if="$root.devoluciones" class="has-text-right" ><abbr :title="pedido.devoluciones_notas">-{{ pedido.devoluciones_total }}</abbr></td>
|
{{ pedido.total_sin_devoluciones }}
|
||||||
<td class="has-text-right" >{{ $root.devoluciones ? pedido.total : pedido.total_sin_devoluciones }}</td>
|
</td>
|
||||||
|
<td v-if="devoluciones_habilitadas" class="has-text-right" >
|
||||||
|
<abbr :title="pedido.devoluciones_notas">
|
||||||
|
-{{ pedido.devoluciones_total }}
|
||||||
|
</abbr>
|
||||||
|
</td>
|
||||||
|
<td class="has-text-right" >
|
||||||
|
{{ devoluciones_habilitadas ? pedido.total : pedido.total_sin_devoluciones }}
|
||||||
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<admin-switch-aprobacion
|
<switch-aprobacion :pedido_id="pedido_id"/>
|
||||||
:pedido="pedido">
|
|
||||||
</admin-switch-aprobacion>
|
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import SwitchAprobacion from "./SwitchAprobacion.vue";
|
import SwitchAprobacion from "./SwitchAprobacion.vue";
|
||||||
|
import { mapGetters, mapState } from "vuex";
|
||||||
export default {
|
export default {
|
||||||
components: {
|
components: {
|
||||||
SwitchAprobacion
|
SwitchAprobacion
|
||||||
},
|
},
|
||||||
props: {
|
props: {
|
||||||
pedido: Object
|
pedido_id: Number
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
...mapState('admin',["devoluciones_habilitadas"]),
|
||||||
|
...mapGetters('admin',["getPedido"]),
|
||||||
|
pedido() {
|
||||||
|
return this.getPedido(this.pedido_id);
|
||||||
|
},
|
||||||
},
|
},
|
||||||
mounted() {
|
|
||||||
Event.$on('sync-aprobacion', (unPedido) => {
|
|
||||||
if (this.pedido.id === unPedido.id) {
|
|
||||||
this.pedido = unPedido
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped></style>
|
||||||
|
|
||||||
</style>
|
|
||||||
|
|
|
@ -1,56 +0,0 @@
|
||||||
<template>
|
|
||||||
<div v-show="visible" class="block">
|
|
||||||
<div class="field">
|
|
||||||
<label class="label has-text-white">Contraseña de administración del barrio</label>
|
|
||||||
<div class="field has-addons">
|
|
||||||
<div class="control">
|
|
||||||
<input required class="input" :type="this.passwordType" name="password" placeholder="Contraseña de admin del barrio">
|
|
||||||
</div>
|
|
||||||
<div class="control">
|
|
||||||
<a class="button is-warning" @click="togglePassword">
|
|
||||||
{{ (passwordVisible ? 'Ocultar' : 'Mostrar') + ' contraseña'}}
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<p class="help has-text-white">Si no la sabés, consultá a la comisión informática.</p>
|
|
||||||
</div>
|
|
||||||
<div class="field">
|
|
||||||
<div class="control">
|
|
||||||
<input type="submit" class="button is-warning" value="Ingresar"/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
export default {
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
visible: false,
|
|
||||||
gdc: null,
|
|
||||||
passwordVisible: false,
|
|
||||||
passwordType: "password",
|
|
||||||
}
|
|
||||||
},
|
|
||||||
mounted() {
|
|
||||||
Event.$on('gdc-seleccionado', (gdc) => {
|
|
||||||
this.gdc = gdc;
|
|
||||||
this.visible = true;
|
|
||||||
});
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
togglePassword() {
|
|
||||||
if (this.passwordVisible) this.passwordType = "password";
|
|
||||||
else this.passwordType = "text"
|
|
||||||
this.passwordVisible = !this.passwordVisible
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
|
|
||||||
<style>
|
|
||||||
.help {
|
|
||||||
font-size: 1rem;
|
|
||||||
}
|
|
||||||
</style>
|
|
|
@ -1,46 +1,34 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="field">
|
<div class="field">
|
||||||
<input type="checkbox" name="switchRoundedSuccess" class="switch is-rounded is-success"
|
<input type="checkbox" name="switchRoundedSuccess" class="switch is-rounded is-success"
|
||||||
:id="'switch'+this.pedido.id"
|
:id="'switch' + pedido_id"
|
||||||
:checked="pedido.aprobado"
|
:checked="aprobado"
|
||||||
@change="toggleAprobacion">
|
@change="setAprobacionPedido({ pedido_id: pedido_id, aprobacion: !aprobado })">
|
||||||
<label :for="'switch'+this.pedido.id">
|
<label :for="'switch' + pedido_id">
|
||||||
<span class="is-hidden-mobile">{{ mensaje }}</span>
|
<span class="is-hidden-mobile">{{ mensaje }}</span>
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
import { mapActions, mapGetters } from "vuex";
|
||||||
export default {
|
export default {
|
||||||
props: {
|
props: {
|
||||||
pedido: Object
|
pedido_id: Number
|
||||||
},
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
aprobado: this.pedido.aprobado
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
mensaje: function () {
|
...mapGetters('admin', ["getPedido"]),
|
||||||
return this.aprobado ? "Pagado" : "No pagado"
|
aprobado() {
|
||||||
|
return this.getPedido(this.pedido_id).aprobado;
|
||||||
|
},
|
||||||
|
mensaje() {
|
||||||
|
return this.aprobado ? "Aprobado" : "No aprobado";
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
toggleAprobacion() {
|
...mapActions('admin',["setAprobacionPedido"]),
|
||||||
Event.$emit('aprobacion-subpedido', this.pedido.id, !this.aprobado);
|
|
||||||
this.aprobado = !this.aprobado
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
mounted() {
|
|
||||||
Event.$on('sync-aprobacion', (unPedido) => {
|
|
||||||
if (this.pedido.id === unPedido.id) {
|
|
||||||
this.pedido = unPedido
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped></style>
|
||||||
|
|
||||||
</style>
|
|
||||||
|
|
|
@ -1,97 +0,0 @@
|
||||||
<template>
|
|
||||||
<div class="block">
|
|
||||||
<div class="block" v-show="!hayBonos">
|
|
||||||
<p class="has-text-centered">
|
|
||||||
Todavía no hay bonos pedidos.
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
<div class="block" v-show="hayBonos">
|
|
||||||
<table class="table is-bordered is-striped is-hoverable is-fullwidth">
|
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
<th><abbr title="Núcleo">Núcleo</abbr></th>
|
|
||||||
<td v-for="(bono,i) in bonos" :key="i" class="is-1">
|
|
||||||
{{ bono.nombre }}
|
|
||||||
</td>
|
|
||||||
<th><abbr title="Total a Pagar">Total $</abbr></th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
<tr v-for="(bp, i) in bonosPorPedido" :key="i">
|
|
||||||
<td> {{ bp.nucleo }} </td>
|
|
||||||
<td v-for="(bono,j) in bp.bonos" :key="j" class="has-text-right">
|
|
||||||
{{ bono.cantidad }}
|
|
||||||
</td>
|
|
||||||
<td class="has-text-right"> {{ bp.total }} </td>
|
|
||||||
</tr>
|
|
||||||
</tbody>
|
|
||||||
<tfoot>
|
|
||||||
<tr>
|
|
||||||
<th></th>
|
|
||||||
<th :colspan="bonos.length">Total bonos</th>
|
|
||||||
<th class="has-text-right">$ {{ totalBonos }}</th>
|
|
||||||
</tr>
|
|
||||||
</tfoot>
|
|
||||||
</table>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
export default {
|
|
||||||
props: {
|
|
||||||
pedidos: {
|
|
||||||
type: Array,
|
|
||||||
required: true
|
|
||||||
}
|
|
||||||
},
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
bonos: []
|
|
||||||
}
|
|
||||||
},
|
|
||||||
computed: {
|
|
||||||
pedidosAprobados: function() {
|
|
||||||
return this.pedidos.filter(p => p.aprobado)
|
|
||||||
},
|
|
||||||
hayBonos: function() {
|
|
||||||
return this.pedidosAprobados.filter(p => p.subtotal_bonos != 0).length !== 0
|
|
||||||
},
|
|
||||||
bonosPorPedido: function() {
|
|
||||||
let bonosPorPedido = this.pedidosAprobados.map(p => p = {"nucleo":p.nombre, "bonos":p.productos.filter(x => x.bono), "total":p.subtotal_bonos});
|
|
||||||
bonosPorPedido.forEach(bp => {
|
|
||||||
bp.bonos = bp.bonos.map(b => b = {"bono":b.nombre, "cantidad":b.pivot.cantidad, "total":b.pivot.total, "id":b.id})
|
|
||||||
})
|
|
||||||
return bonosPorPedido.map(bp => this.completarBonos(bp));
|
|
||||||
},
|
|
||||||
totalBonos: function() {
|
|
||||||
let total = 0
|
|
||||||
this.bonosPorPedido.map(bp => total += parseInt(bp.total))
|
|
||||||
return total
|
|
||||||
},
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
completarBonos(bonosPedido) {
|
|
||||||
this.bonos.map(b => {
|
|
||||||
if (!bonosPedido.bonos.map(x => x.id).includes(b.id))
|
|
||||||
bonosPedido.bonos.push({"bono":b.nombre, "cantidad":0, "total":0, "id":b.id})
|
|
||||||
})
|
|
||||||
bonosPedido.bonos = bonosPedido.bonos.sort((b1,b2) => b1.id - b2.id)
|
|
||||||
return bonosPedido
|
|
||||||
}
|
|
||||||
},
|
|
||||||
beforeMount() {
|
|
||||||
axios.get("../api/productos", {
|
|
||||||
params: {
|
|
||||||
categoria:'TRANSPORTE, BONOS Y FINANCIAMIENTO SORORO',
|
|
||||||
}
|
|
||||||
}).then(response => {
|
|
||||||
this.bonos = response.data.data;
|
|
||||||
});
|
|
||||||
},
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style>
|
|
||||||
|
|
||||||
</style>
|
|
|
@ -4,17 +4,18 @@
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th>Núcleo</th>
|
<th>Núcleo</th>
|
||||||
<th v-if="$root.devoluciones"><abbr title="Total sin tomar en cuenta las devoluciones">Total parcial $</abbr></th>
|
<th v-if="devoluciones_habilitadas"><abbr title="Total sin tomar en cuenta las devoluciones">Total parcial $</abbr></th>
|
||||||
<th v-if="$root.devoluciones"><abbr title="Devoluciones correspondientes al núcleo">Devoluciones $</abbr></th>
|
<th v-if="devoluciones_habilitadas"><abbr title="Devoluciones correspondientes al núcleo">Devoluciones $</abbr></th>
|
||||||
<th><abbr title="Total a Pagar por el núleo">{{ $root.devoluciones ? 'Total real' : 'Total' }} $</abbr></th>
|
<th><abbr title="Total a Pagar por el núleo">{{ devoluciones_habilitadas ? 'Total real' : 'Total' }} $</abbr></th>
|
||||||
<th class="is-1"><abbr title="Pagado">Pagado</abbr></th>
|
<th class="is-1"><abbr title="Aprobado">Aprobado</abbr></th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
<admin-fila-pedido
|
<fila-pedido
|
||||||
v-for="pedido in gdc.pedidos"
|
v-for="pedido in pedidos"
|
||||||
:pedido="pedido" :key="pedido.id">
|
:pedido_id="pedido.id"
|
||||||
</admin-fila-pedido>
|
:key="pedido.id"
|
||||||
|
/>
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
<table class="table is-striped is-bordered">
|
<table class="table is-striped is-bordered">
|
||||||
|
@ -23,27 +24,35 @@
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<th>Total a recaudar:</th>
|
<th>Total a recaudar:</th>
|
||||||
<td class="has-text-right">$ {{ gdc.total_a_recaudar }}</td>
|
<td class="has-text-right">$ {{ devoluciones_habilitadas ? total_a_recaudar : total_sin_devoluciones }}</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<th>Total bonos barriales:</th>
|
<th>Total bonos barriales:</th>
|
||||||
<td class="has-text-right">$ {{ gdc.total_barrial }}</td>
|
<td class="has-text-right">$ {{ total_barrial }}</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr v-if="$root.devoluciones">
|
<tr v-if="devoluciones_habilitadas">
|
||||||
<th>Total devoluciones:</th>
|
<th>Total devoluciones:</th>
|
||||||
<td class="has-text-right">- $ {{ gdc.total_devoluciones }}</td>
|
<td class="has-text-right">- $ {{ total_devoluciones }}</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<th>Cantidad bonos de transporte:</th>
|
<th>Cantidad bonos de transporte:</th>
|
||||||
<td class="has-text-right">{{ gdc.cantidad_transporte }}</td>
|
<td class="has-text-right">{{ cantidad_transporte }}</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<th>Total bonos de transporte:</th>
|
<th>Total bonos de transporte:</th>
|
||||||
<td class="has-text-right">$ {{ gdc.total_transporte }}</td>
|
<td class="has-text-right">$ {{ total_transporte }}</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<th>Total a depositar:</th>
|
<th>Total de pedido:</th>
|
||||||
<td class="has-text-right">$ {{ gdc.total_a_transferir }}</td>
|
<td class="has-text-right">$ {{ total_de_pedido }}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<th>Saldo a favor:</th>
|
||||||
|
<td class="has-text-right">- $ {{ saldo }}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<th>Total a transferir:</th>
|
||||||
|
<td class="has-text-right">$ {{ total_a_transferir }}</td>
|
||||||
</tr>
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
|
@ -51,19 +60,28 @@
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import FilaPedido from "./FilaPedido.vue";
|
import FilaPedido from "./FilaPedido.vue";
|
||||||
|
import { mapGetters, mapState } from "vuex";
|
||||||
export default {
|
export default {
|
||||||
components: {
|
components: {
|
||||||
FilaPedido
|
FilaPedido
|
||||||
},
|
},
|
||||||
props: {
|
computed: {
|
||||||
gdc: {
|
...mapState('admin', [
|
||||||
type: Object,
|
"devoluciones_habilitadas",
|
||||||
required: true
|
"pedidos",
|
||||||
}
|
"total_a_recaudar",
|
||||||
}
|
"total_sin_devoluciones",
|
||||||
|
"total_barrial",
|
||||||
|
"total_devoluciones",
|
||||||
|
"cantidad_transporte",
|
||||||
|
"total_transporte",
|
||||||
|
"total_de_pedido",
|
||||||
|
"total_a_transferir",
|
||||||
|
"saldo",
|
||||||
|
]),
|
||||||
|
...mapGetters('admin', ['pedidosAprobados']),
|
||||||
|
},
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style>
|
<style></style>
|
||||||
|
|
||||||
</style>
|
|
||||||
|
|
59
resources/js/components/comisiones/Body.vue
Normal file
59
resources/js/components/comisiones/Body.vue
Normal file
|
@ -0,0 +1,59 @@
|
||||||
|
<template>
|
||||||
|
<div class="block ml-3 mr-3 is-max-widescreen is-max-desktop">
|
||||||
|
<tabs-secciones :tabs="tabs" :tabInicial="tabActiva"/>
|
||||||
|
<div class="block pb-6"
|
||||||
|
id="pedidos-comisiones-seccion"
|
||||||
|
:class="seccionActiva === 'pedidos-comisiones-seccion' ? 'is-active' : 'is-hidden'">
|
||||||
|
<div class="block" id="pedidos-comisiones-tabla-y-dropdown">
|
||||||
|
<dropdown-descargar/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="block pb-6"
|
||||||
|
id="canasta-comisiones-seccion"
|
||||||
|
:class="seccionActiva === 'canasta-comisiones-seccion' ? 'is-active' : 'is-hidden'">
|
||||||
|
<canasta-seccion/>
|
||||||
|
</div>
|
||||||
|
<div class="block pb-6"
|
||||||
|
id="saldos-comisiones-seccion"
|
||||||
|
:class="seccionActiva === 'saldos-comisiones-seccion' ? 'is-active' : 'is-hidden'">
|
||||||
|
<saldos-seccion/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import TabsSecciones from "../comunes/TabsSecciones.vue";
|
||||||
|
import DropdownDescargar from "./DropdownDescargar.vue";
|
||||||
|
import InputFileButton from "../comunes/InputFileButton.vue";
|
||||||
|
import CanastaSeccion from "./canasta/CanastaSeccion.vue";
|
||||||
|
import SaldosSeccion from "./saldos/SaldosSeccion.vue";
|
||||||
|
import { mapActions } from "vuex";
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: "ComisionesBody",
|
||||||
|
components: {
|
||||||
|
SaldosSeccion,
|
||||||
|
CanastaSeccion,
|
||||||
|
TabsSecciones,
|
||||||
|
DropdownDescargar,
|
||||||
|
InputFileButton,
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
tabs: [
|
||||||
|
{ id: "pedidos-comisiones", nombre: "Pedidos" },
|
||||||
|
{ id: "canasta-comisiones", nombre: "Canasta" },
|
||||||
|
{ id: "saldos-comisiones", nombre: "Saldos" },
|
||||||
|
],
|
||||||
|
tabActiva: "pedidos-comisiones",
|
||||||
|
seccionActiva: "pedidos-comisiones-seccion",
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
setSeccionActiva(tabId) {
|
||||||
|
this.tabActiva = tabId;
|
||||||
|
this.seccionActiva = tabId + "-seccion";
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
</script>
|
|
@ -14,13 +14,13 @@
|
||||||
</div>
|
</div>
|
||||||
<div class="dropdown-menu" id="dropdown-menu" role="menu">
|
<div class="dropdown-menu" id="dropdown-menu" role="menu">
|
||||||
<div class="dropdown-content">
|
<div class="dropdown-content">
|
||||||
<a href="/compras/pedidos/descargar" class="dropdown-item">
|
<a href="/comisiones/pedidos/descargar" class="dropdown-item">
|
||||||
Pedidos por barrio
|
Pedidos por barrio
|
||||||
</a>
|
</a>
|
||||||
<a href="/compras/pedidos/notas" class="dropdown-item">
|
<a href="/comisiones/pedidos/notas" class="dropdown-item">
|
||||||
Notas por barrio
|
Notas por barrio
|
||||||
</a>
|
</a>
|
||||||
<a href="/compras/pedidos/pdf" class="dropdown-item">
|
<a href="/comisiones/pedidos/pdf" class="dropdown-item">
|
||||||
Pedidos por barrio en pdf
|
Pedidos por barrio en pdf
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
|
@ -14,7 +14,7 @@
|
||||||
</span>
|
</span>
|
||||||
<span class="file-label">Subir canasta</span>
|
<span class="file-label">Subir canasta</span>
|
||||||
</span>
|
</span>
|
||||||
<span class="file-name" v-if="archivo">
|
<span class="file-name" v-if="cargando">
|
||||||
{{ 'Cargando ' + archivo.nombre }}
|
{{ 'Cargando ' + archivo.nombre }}
|
||||||
</span>
|
</span>
|
||||||
</label>
|
</label>
|
||||||
|
@ -24,6 +24,7 @@
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import axios from "axios";
|
import axios from "axios";
|
||||||
|
import { mapActions } from "vuex";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: "CanastaInput",
|
name: "CanastaInput",
|
||||||
|
@ -34,29 +35,30 @@ export default {
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
...mapActions('ui',["toast"]),
|
||||||
async archivoSubido(event) {
|
async archivoSubido(event) {
|
||||||
const archivo = event.target.files[0];
|
const archivo = event.target.files[0];
|
||||||
if (archivo && archivo.type === "text/csv") {
|
if (archivo && archivo.type === "text/csv") {
|
||||||
this.archivo = {data: archivo, nombre: archivo.name};
|
this.archivo = { data: archivo, nombre: archivo.name };
|
||||||
const formData = new FormData();
|
const formData = new FormData();
|
||||||
formData.append("data", this.archivo.data);
|
formData.append("data", this.archivo.data);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
this.cargando = true;
|
this.cargando = true;
|
||||||
const response = await axios.post("/compras/canasta", formData, {
|
const response = await axios.post("/comisiones/canasta", formData, {
|
||||||
headers: {
|
headers: {
|
||||||
"Content-Type": "multipart/form-data",
|
"Content-Type": "multipart/form-data",
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
this.$root.$toast(response.data.message || "Canasta cargada exitosamente");
|
this.toast({ mensaje: (response.data.message || "Canasta cargada exitosamente") });
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
this.$root.$toast(error.response?.data?.message || "Hubo errores.");
|
this.toast({ mensaje: (error.response?.data?.message || "Hubo errores.") });
|
||||||
} finally {
|
} finally {
|
||||||
this.cargando = false;
|
this.cargando = false;
|
||||||
this.archivo = null;
|
this.archivo = null;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
this.$root.$toast("La canasta debe ser .CSV")
|
this.toast("La canasta debe ser .CSV")
|
||||||
this.archivo = null;
|
this.archivo = null;
|
||||||
}
|
}
|
||||||
},
|
},
|
|
@ -0,0 +1,46 @@
|
||||||
|
<script>
|
||||||
|
import { defineComponent } from "vue";
|
||||||
|
import CanastaInput from "./CanastaInput.vue";
|
||||||
|
|
||||||
|
export default defineComponent({
|
||||||
|
components: { CanastaInput },
|
||||||
|
name: "CanastaSeccion",
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<article class="message is-warning">
|
||||||
|
<div class="message-header">
|
||||||
|
<p>Formato de la canasta</p>
|
||||||
|
</div>
|
||||||
|
<div class="message-body">
|
||||||
|
<div class="content">
|
||||||
|
La planilla de la canasta tiene que tener el siguiente formato para que la aplicación la lea correctamente:
|
||||||
|
<ul>
|
||||||
|
<li> Los precios deben usar punto y no coma decimal </li>
|
||||||
|
<li> El nombre de las columnas deben ser "Tipo", "Producto", y "Precio" respectivamente </li>
|
||||||
|
<li> Las celdas deben separarse con '|' </li>
|
||||||
|
<li> No puede haber "enters" en ninguna celda </li>
|
||||||
|
<li> El bono de transporte debe tener tipo 'T' </li>
|
||||||
|
</ul>
|
||||||
|
<a class="has-text-info" href="/comisiones/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">
|
||||||
|
<canasta-input/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
|
||||||
|
</style>
|
71
resources/js/components/comisiones/saldos/SaldoRow.vue
Normal file
71
resources/js/components/comisiones/saldos/SaldoRow.vue
Normal file
|
@ -0,0 +1,71 @@
|
||||||
|
<script>
|
||||||
|
import { mapActions, mapGetters, mapState } from "vuex";
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: "SaldoRow",
|
||||||
|
props: {
|
||||||
|
grupo_de_compra: {
|
||||||
|
type: Object,
|
||||||
|
required: true,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
saldoControl: 0,
|
||||||
|
inputSaldoInteractuado: false,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
mounted() {
|
||||||
|
this.saldoControl = this.grupo_de_compra.saldo;
|
||||||
|
},
|
||||||
|
watch: {
|
||||||
|
lastFetch() {
|
||||||
|
this.saldoControl = this.grupo_de_compra.saldo;
|
||||||
|
},
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
...mapActions("comisiones", ["setSaldo"]),
|
||||||
|
async confirmarSaldo() {
|
||||||
|
await this.setSaldo({
|
||||||
|
gdc_id: this.grupo_de_compra.id,
|
||||||
|
saldo: this.saldoControl,
|
||||||
|
});
|
||||||
|
this.inputSaldoInteractuado = false;
|
||||||
|
},
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
...mapState("comisiones", ["lastFetch"]),
|
||||||
|
...mapGetters("comisiones", ["saldo"]),
|
||||||
|
saldoModificado() {
|
||||||
|
return Number.parseFloat(this.saldo(this.grupo_de_compra.id)) !== Number.parseFloat(this.saldoControl);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<tr>
|
||||||
|
<th>{{ grupo_de_compra.nombre }}</th>
|
||||||
|
<td>
|
||||||
|
<input :id="`saldo-input-${grupo_de_compra.id}`"
|
||||||
|
v-model="saldoControl"
|
||||||
|
class="input is-small"
|
||||||
|
type="number"
|
||||||
|
style="text-align: center"
|
||||||
|
@input="inputSaldoInteractuado = true">
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<button :disabled="!(inputSaldoInteractuado && saldoModificado)"
|
||||||
|
class="button is-small is-success ml-1"
|
||||||
|
@click="confirmarSaldo">
|
||||||
|
<span class="icon">
|
||||||
|
<i class="fas fa-check"/>
|
||||||
|
</span>
|
||||||
|
</button>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
|
||||||
|
</style>
|
76
resources/js/components/comisiones/saldos/SaldosSeccion.vue
Normal file
76
resources/js/components/comisiones/saldos/SaldosSeccion.vue
Normal file
|
@ -0,0 +1,76 @@
|
||||||
|
<script>
|
||||||
|
import InputFileButton from "../../comunes/InputFileButton.vue";
|
||||||
|
import { mapActions } from "vuex";
|
||||||
|
import TablaSaldos from "./TablaSaldos.vue";
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: "SaldosSeccion",
|
||||||
|
components: { TablaSaldos, InputFileButton },
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
archivo: undefined,
|
||||||
|
show_saldos_file_dialog: true,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
...mapActions('ui',["toast"]),
|
||||||
|
...mapActions('comisiones', ['cargarSaldos']),
|
||||||
|
async archivoSubido(event) {
|
||||||
|
event.component.cargando = true;
|
||||||
|
const formData = new FormData();
|
||||||
|
formData.append('data',event.archivo);
|
||||||
|
await this.cargarSaldos(formData);
|
||||||
|
event.component.cargando = false;
|
||||||
|
},
|
||||||
|
toggleSaldosFileDialog() {
|
||||||
|
this.show_saldos_file_dialog = !this.show_saldos_file_dialog;
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<div class="columns">
|
||||||
|
<div class="column">
|
||||||
|
<article class="message is-warning">
|
||||||
|
<div class="message-header">
|
||||||
|
<p>
|
||||||
|
<span class="icon is-small"
|
||||||
|
@click="toggleSaldosFileDialog">
|
||||||
|
<i :class="`fas ${!show_saldos_file_dialog ? 'fa-angle-down' : 'fa-angle-up'}`" aria-hidden="true"></i>
|
||||||
|
</span>
|
||||||
|
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">
|
||||||
|
Al cargar un archivo, se reemplazaran los saldos de los barrios que éste contenga, el resto quedará sin cambiar.
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</article>
|
||||||
|
</div>
|
||||||
|
<input-file-button text="Subir archivo" @archivo-subido="archivoSubido" />
|
||||||
|
</div>
|
||||||
|
</article>
|
||||||
|
</div>
|
||||||
|
<div class="column">
|
||||||
|
<tabla-saldos/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
</style>
|
38
resources/js/components/comisiones/saldos/TablaSaldos.vue
Normal file
38
resources/js/components/comisiones/saldos/TablaSaldos.vue
Normal file
|
@ -0,0 +1,38 @@
|
||||||
|
<script>
|
||||||
|
import { mapActions, mapState } from "vuex";
|
||||||
|
import SaldoRow from "./SaldoRow.vue";
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: "TablaSaldos",
|
||||||
|
components: { SaldoRow },
|
||||||
|
async mounted() {
|
||||||
|
await this.getGruposDeCompra();
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
...mapActions("comisiones", ["getGruposDeCompra"]),
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
...mapState("comisiones", ["grupos_de_compra"]),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<table class="table container">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>Barrio</th>
|
||||||
|
<th>Saldo</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<saldo-row v-for="(gdc,index) in grupos_de_compra"
|
||||||
|
:grupo_de_compra="gdc"
|
||||||
|
:key="index"/>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
|
||||||
|
</style>
|
|
@ -1,74 +0,0 @@
|
||||||
<template>
|
|
||||||
<div class="block ml-3 mr-3 is-max-widescreen is-max-desktop">
|
|
||||||
<comunes-tabs-secciones :tabs="tabs" :tabInicial="tabActiva"></comunes-tabs-secciones>
|
|
||||||
<div class="block pb-6" id="pedidos-compras-seccion"
|
|
||||||
:class="seccionActiva === 'pedidos-compras-seccion' ? 'is-active' : 'is-hidden'">
|
|
||||||
<div class="block" id="pedidos-compras-tabla-y-dropdown">
|
|
||||||
<compras-dropdown-descargar>
|
|
||||||
</compras-dropdown-descargar>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="block pb-6" id="canasta-compras-seccion"
|
|
||||||
:class="seccionActiva === 'canasta-compras-seccion' ? 'is-active' : 'is-hidden'">
|
|
||||||
<div class="block" id="canasta-compras-seccion">
|
|
||||||
<article class="message is-warning">
|
|
||||||
<div class="message-header">
|
|
||||||
<p>Formato de la canasta</p>
|
|
||||||
</div>
|
|
||||||
<div class="message-body">
|
|
||||||
<div class="content">
|
|
||||||
La planilla de la canasta tiene que tener el siguiente formato para que la aplicación la lea correctamente:
|
|
||||||
<ul>
|
|
||||||
<li> Los precios deben usar punto y no coma decimal </li>
|
|
||||||
<li> El nombre de las columnas deben ser "Tipo", "Producto", y "Precio" respectivamente </li>
|
|
||||||
<li> Las celdas deben separarse con '|' </li>
|
|
||||||
<li> No puede haber "enters" en ninguna celda </li>
|
|
||||||
<li> El bono de transporte debe tener tipo 'T' </li>
|
|
||||||
</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>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
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>
|
|
|
@ -1,52 +0,0 @@
|
||||||
<template>
|
|
||||||
<div class="block">
|
|
||||||
<div class="field">
|
|
||||||
<label class="label">Usuario</label>
|
|
||||||
<div class="field">
|
|
||||||
<div class="control">
|
|
||||||
<input required class="input" type="text" name="name" placeholder="Usuario">
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="field">
|
|
||||||
<label class="label">Contraseña</label>
|
|
||||||
<div class="field has-addons">
|
|
||||||
<div class="control">
|
|
||||||
<input required class="input" :type="this.passwordType" name="password" placeholder="Contraseña">
|
|
||||||
</div>
|
|
||||||
<div class="control">
|
|
||||||
<a class="button is-dark" @click="togglePassword">
|
|
||||||
{{ (passwordVisible ? 'Ocultar' : 'Mostrar') + ' contraseña'}}
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="field">
|
|
||||||
<div class="control">
|
|
||||||
<input type="submit" class="button is-dark" value="Ingresar"/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
export default {
|
|
||||||
name: "LoginAdmin",
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
passwordVisible: false,
|
|
||||||
passwordType: "password",
|
|
||||||
}
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
togglePassword() {
|
|
||||||
if (this.passwordVisible) this.passwordType = "password";
|
|
||||||
else this.passwordType = "text"
|
|
||||||
this.passwordVisible = !this.passwordVisible
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style>
|
|
||||||
</style>
|
|
|
@ -1,51 +0,0 @@
|
||||||
<template>
|
|
||||||
<div v-show="visible" class="block">
|
|
||||||
<div class="field">
|
|
||||||
<label class="label" :class="isAdmin ? 'has-text-white' : ''">Seleccioná tu barrio o grupo de compra</label>
|
|
||||||
<div class="control">
|
|
||||||
<div class="select">
|
|
||||||
<select @change="onGDCSelected" v-model="gdc" name="name">
|
|
||||||
<option :disabled="isDefaultDisabled==1" value=null>Seleccionar</option>
|
|
||||||
<option v-for="(gdc, index) in gdcs" :key="index" v-text="gdc.nombre + (isAdmin ? '_admin' : '')"
|
|
||||||
:name="gdc.nombre + (isAdmin ? '_admin' : '')">
|
|
||||||
</option>
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
export default {
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
visible: false,
|
|
||||||
region: null,
|
|
||||||
gdcs: [],
|
|
||||||
isDefaultDisabled: 0,
|
|
||||||
gdc: null,
|
|
||||||
isAdmin: this.admin == null ? false : this.admin
|
|
||||||
}
|
|
||||||
},
|
|
||||||
mounted() {
|
|
||||||
Event.$on('region-seleccionada', (region)=> {
|
|
||||||
this.region = region;
|
|
||||||
this.fillGDC(region);
|
|
||||||
this.visible = true;
|
|
||||||
});
|
|
||||||
},
|
|
||||||
methods : {
|
|
||||||
fillGDC(region) {
|
|
||||||
axios.get("/api/grupos-de-compra").then(response => {
|
|
||||||
this.gdcs = response.data[this.region];
|
|
||||||
});
|
|
||||||
},
|
|
||||||
onGDCSelected() {
|
|
||||||
this.isDefaultDisabled = 1;
|
|
||||||
Event.$emit("gdc-seleccionado",this.gdc);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
props: {'admin': Boolean}
|
|
||||||
}
|
|
||||||
</script>
|
|
90
resources/js/components/comunes/InfoTags.vue
Normal file
90
resources/js/components/comunes/InfoTags.vue
Normal file
|
@ -0,0 +1,90 @@
|
||||||
|
<script>
|
||||||
|
import { mapActions, mapMutations, mapState } from "vuex";
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: "InfoTags",
|
||||||
|
computed: {
|
||||||
|
...mapState("ui", ["canasta_actual", "show_tags"])
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
...mapActions("ui", ["getCanastaActual"]),
|
||||||
|
...mapMutations("ui", ["toggleTags"])
|
||||||
|
},
|
||||||
|
async mounted() {
|
||||||
|
await this.getCanastaActual();
|
||||||
|
this.fechaCanasta = new Date(this.canasta_actual.fecha)
|
||||||
|
.toLocaleDateString('es-UY');
|
||||||
|
this.nombreCanasta = this.canasta_actual.nombre;
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
nombreCanasta: "",
|
||||||
|
fechaCanasta: "",
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<div v-if="!show_tags" class="info-tab" @click="toggleTags(true)">
|
||||||
|
<button class="button is-borderless" type="button">
|
||||||
|
<span class="icon">
|
||||||
|
<i class="fas fa-info-circle"></i>
|
||||||
|
</span>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<div v-if="show_tags" class="box sticky-tags">
|
||||||
|
<div class="field is-grouped is-grouped-multiline">
|
||||||
|
<div class="control">
|
||||||
|
<div class="tags has-addons">
|
||||||
|
<span class="tag">Canasta</span>
|
||||||
|
<span class="tag is-danger">{{ nombreCanasta }}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="control">
|
||||||
|
<div class="tags has-addons">
|
||||||
|
<span class="tag">Actualizada</span>
|
||||||
|
<span class="tag is-danger">{{ fechaCanasta }}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<button class="delete" type="button" @click="toggleTags(true)"></button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.sticky-tags {
|
||||||
|
position: fixed;
|
||||||
|
bottom: 1rem;
|
||||||
|
right: 1rem;
|
||||||
|
z-index: 50;
|
||||||
|
padding: 0.75rem 1rem;
|
||||||
|
border-radius: 0.5rem;
|
||||||
|
max-width: 90vw;
|
||||||
|
}
|
||||||
|
|
||||||
|
.is-borderless {
|
||||||
|
border: 0;
|
||||||
|
background: none;
|
||||||
|
box-shadow: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.info-tab {
|
||||||
|
position: fixed;
|
||||||
|
right: -0.1rem;
|
||||||
|
bottom: 1rem;
|
||||||
|
z-index: 51;
|
||||||
|
transform: translateX(10%);
|
||||||
|
transition: transform 0.3s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.info-tab button {
|
||||||
|
border-top-left-radius: 9999px;
|
||||||
|
border-bottom-left-radius: 9999px;
|
||||||
|
background-color: white;
|
||||||
|
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
|
||||||
|
padding: 0.5rem 0.75rem;
|
||||||
|
}
|
||||||
|
</style>
|
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>
|
|
@ -4,15 +4,16 @@
|
||||||
<a class="navbar-item" href="https://mps.org.uy">
|
<a class="navbar-item" href="https://mps.org.uy">
|
||||||
<img src="/assets/logoMPS.png" height="28">
|
<img src="/assets/logoMPS.png" height="28">
|
||||||
</a>
|
</a>
|
||||||
<!-- Styles nombre del barrio-->
|
<div class="navbar-item hide-below-1024" v-if="pedidoDefinido">
|
||||||
<p class="navbar-item hide-below-1024">
|
<p>{{ `Barrio: ${grupo_de_compra.nombre} - Núcleo: ${nombre}` }}</p>
|
||||||
<slot name="gdc"></slot>
|
</div>
|
||||||
</p>
|
<chismosa-dropdown
|
||||||
<p class="navbar-item">
|
v-if="pedidoDefinido"
|
||||||
<slot name="subpedido"></slot>
|
class="hide-above-1023"
|
||||||
</p>
|
ariaControls="mobile"
|
||||||
<pedidos-chismosa-dropdown v-if="this.$root.pedido != null" class="hide-above-1023" id="mobile"></pedidos-chismosa-dropdown>
|
/>
|
||||||
<a role="button" class="navbar-burger" :class="{'is-active':burgerActiva}" aria-label="menu" aria-expanded="false" data-target="nav-bar" @click="toggleBurger">
|
<a role="button" class="navbar-burger" :class="{'is-active':burgerActiva}" aria-label="menu"
|
||||||
|
aria-expanded="false" data-target="nav-bar" @click="toggleBurger">
|
||||||
<span aria-hidden="true"></span>
|
<span aria-hidden="true"></span>
|
||||||
<span aria-hidden="true"></span>
|
<span aria-hidden="true"></span>
|
||||||
<span aria-hidden="true"></span>
|
<span aria-hidden="true"></span>
|
||||||
|
@ -20,20 +21,25 @@
|
||||||
</div>
|
</div>
|
||||||
<div class="navbar-menu" :class="{'is-active':burgerActiva}">
|
<div class="navbar-menu" :class="{'is-active':burgerActiva}">
|
||||||
<div class="navbar-end">
|
<div class="navbar-end">
|
||||||
<div v-if="this.$root.pedido != null" class="navbar-item field has-addons mt-2 mr-3">
|
<div v-if="pedidoDefinido" class="navbar-item field has-addons mt-1 mr-3 mb-1">
|
||||||
<a class="button is-small has-text-dark-grey" @click.capture="buscar">
|
<a class="button is-small has-text-dark-grey" @click.capture="buscar">
|
||||||
<span class="icon">
|
<span class="icon">
|
||||||
<i class="fas fa-search"></i>
|
<i class="fas fa-search"></i>
|
||||||
</span>
|
</span>
|
||||||
</a>
|
</a>
|
||||||
<input class="input is-small" type="text" placeholder="Harina" v-model="searchString" @keyup.enter="buscar" >
|
<input class="input is-small" type="text" placeholder="Harina" v-model="searchString"
|
||||||
|
@keyup.enter="buscar">
|
||||||
</div>
|
</div>
|
||||||
<pedidos-chismosa-dropdown v-if="this.$root.pedido != null" class="hide-below-1024" id="wide"></pedidos-chismosa-dropdown>
|
<chismosa-dropdown
|
||||||
|
v-if="pedidoDefinido"
|
||||||
|
class="hide-below-1024"
|
||||||
|
ariaControls="wide">
|
||||||
|
</chismosa-dropdown>
|
||||||
<div class="block navbar-item">
|
<div class="block navbar-item">
|
||||||
<a onclick="event.preventDefault(); document.getElementById('logout-form').submit();" class="text-a">
|
<a onclick="event.preventDefault(); document.getElementById('logout-form').submit();"
|
||||||
|
class="text-a">
|
||||||
Cerrar sesión
|
Cerrar sesión
|
||||||
</a>
|
</a>
|
||||||
<slot name="logout-form"></slot>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -42,22 +48,35 @@
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import ChismosaDropdown from '../pedidos/ChismosaDropdown.vue';
|
import ChismosaDropdown from '../pedidos/ChismosaDropdown.vue';
|
||||||
|
import { mapActions, mapGetters, mapMutations, mapState } from "vuex";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
components: { ChismosaDropdown },
|
components: { ChismosaDropdown },
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
burgerActiva: false,
|
burgerActiva: false,
|
||||||
searchString: "",
|
searchString: "",
|
||||||
|
nombreCanasta: "",
|
||||||
|
fechaCanasta: "",
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
computed: {
|
||||||
|
...mapGetters('pedido', ["pedidoDefinido"]),
|
||||||
|
...mapState('pedido', ["nombre"]),
|
||||||
|
...mapState('pedido', ["grupo_de_compra"]),
|
||||||
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
...mapActions('productos', ["filtrarProductos"]),
|
||||||
|
...mapMutations('ui', ["addMiga", "popUltimaBusqueda"]),
|
||||||
toggleBurger() {
|
toggleBurger() {
|
||||||
this.burgerActiva = !this.burgerActiva
|
this.burgerActiva = !this.burgerActiva
|
||||||
},
|
},
|
||||||
buscar() {
|
buscar() {
|
||||||
if (this.burgerActiva) this.toggleBurger()
|
if (this.burgerActiva)
|
||||||
Event.$emit("migas-setear-como-inicio", this.$rootMiga)
|
this.toggleBurger();
|
||||||
Event.$emit("filtrar-productos",'nombre',this.searchString)
|
this.filtrarProductos({ filtro: "nombre", valor: this.searchString });
|
||||||
|
this.popUltimaBusqueda();
|
||||||
|
this.addMiga({ nombre: this.searchString });
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,38 +0,0 @@
|
||||||
<template>
|
|
||||||
<div class="block">
|
|
||||||
<div class="field">
|
|
||||||
<label class="label" :class="whiteText ? 'has-text-white' : ''">Seleccioná tu región</label>
|
|
||||||
<div class="control">
|
|
||||||
<div class="select">
|
|
||||||
<select @change="onRegionSelected" v-model="region">
|
|
||||||
<option :disabled="isDefaultDisabled===1" value=null>Seleccionar</option>
|
|
||||||
<option v-for="(region, index) in regiones" :key="index" v-text="region" :name="region"></option>
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
export default {
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
regiones: [],
|
|
||||||
isDefaultDisabled: 0,
|
|
||||||
region: null,
|
|
||||||
whiteText: this.admin == null ? false : this.admin
|
|
||||||
}
|
|
||||||
},
|
|
||||||
mounted() {
|
|
||||||
axios.get("/api/regiones").then(response => this.regiones = response.data);
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
onRegionSelected() {
|
|
||||||
this.isDefaultDisabled = 1;
|
|
||||||
Event.$emit("region-seleccionada",this.region);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
props: {'admin': Boolean}
|
|
||||||
}
|
|
||||||
</script>
|
|
48
resources/js/components/login/LoginDropdown.vue
Normal file
48
resources/js/components/login/LoginDropdown.vue
Normal file
|
@ -0,0 +1,48 @@
|
||||||
|
<script>
|
||||||
|
import { mapGetters } from "vuex";
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: "LoginDropdown",
|
||||||
|
computed: {
|
||||||
|
...mapGetters("login", ["opcionesLogin", "estilos"])
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
dropdownActivo: false
|
||||||
|
};
|
||||||
|
},
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<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"
|
||||||
|
type="button"
|
||||||
|
@click="dropdownActivo = !dropdownActivo">
|
||||||
|
<span class="icon is-small">
|
||||||
|
<i class="fa fa-solid fa-user-check"></i>
|
||||||
|
</span>
|
||||||
|
<span>Cambiar login</span>
|
||||||
|
<span class="icon is-small">
|
||||||
|
<i class="fas fa-angle-down" aria-hidden="true"></i>
|
||||||
|
</span>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<div class="dropdown-menu" role="menu">
|
||||||
|
<div class="dropdown-content">
|
||||||
|
<a class="dropdown-item" v-for="opcion in opcionesLogin" :href="opcion.href">
|
||||||
|
{{ opcion.nombre }}
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
|
||||||
|
</style>
|
24
resources/js/components/login/LoginInput.vue
Normal file
24
resources/js/components/login/LoginInput.vue
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
<script>
|
||||||
|
import { mapGetters } from "vuex";
|
||||||
|
import BarrioLogin from "./input/BarrioLogin.vue";
|
||||||
|
import UserLogin from "./input/UserLogin.vue";
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: "LoginInput",
|
||||||
|
components: { UserLogin, BarrioLogin },
|
||||||
|
computed: {
|
||||||
|
...mapGetters("login", ["urlRol"]),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<user-login v-if="urlRol === 'comisiones'"/>
|
||||||
|
<barrio-login v-else/>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
|
||||||
|
</style>
|
33
resources/js/components/login/LoginTitulos.vue
Normal file
33
resources/js/components/login/LoginTitulos.vue
Normal file
|
@ -0,0 +1,33 @@
|
||||||
|
<script>
|
||||||
|
import { mapGetters } from "vuex";
|
||||||
|
import LoginDropdown from "./LoginDropdown.vue";
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: "LoginTitulos",
|
||||||
|
components: { LoginDropdown },
|
||||||
|
computed: {
|
||||||
|
...mapGetters("login", ["textos", "estilos"]),
|
||||||
|
}
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div class="columns">
|
||||||
|
<div class="column">
|
||||||
|
<div class="block">
|
||||||
|
<h1 class="title" :class="estilos.texto">{{ textos.titulo }}</h1>
|
||||||
|
<p class="subtitle" :class="estilos.texto">
|
||||||
|
{{ `Bienvenidx a la ${textos.subtitlo} del ` }}
|
||||||
|
<strong :class="estilos.texto">Mercado Popular de Subistencia</strong>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="column is-2 is-hidden-mobile">
|
||||||
|
<login-dropdown/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
|
||||||
|
</style>
|
26
resources/js/components/login/input/BarrioLogin.vue
Normal file
26
resources/js/components/login/input/BarrioLogin.vue
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
<script>
|
||||||
|
import { defineComponent } from "vue";
|
||||||
|
import RegionSelect from "./barrio/RegionSelect.vue";
|
||||||
|
import BarrioSelect from "./barrio/BarrioSelect.vue";
|
||||||
|
import { mapActions } from "vuex";
|
||||||
|
|
||||||
|
export default defineComponent({
|
||||||
|
components: { BarrioSelect, RegionSelect },
|
||||||
|
methods: {
|
||||||
|
...mapActions("login", ["getRegiones"]),
|
||||||
|
},
|
||||||
|
async mounted() {
|
||||||
|
await this.getRegiones();
|
||||||
|
},
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div class="block">
|
||||||
|
<region-select/>
|
||||||
|
<barrio-select/>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
</style>
|
65
resources/js/components/login/input/PasswordInput.vue
Normal file
65
resources/js/components/login/input/PasswordInput.vue
Normal file
|
@ -0,0 +1,65 @@
|
||||||
|
<template>
|
||||||
|
<div class="block">
|
||||||
|
<div class="field">
|
||||||
|
<label class="label" :class="estilos.texto">
|
||||||
|
{{ textos.password }}
|
||||||
|
</label>
|
||||||
|
<div class="field has-addons">
|
||||||
|
<div class="control">
|
||||||
|
<input required
|
||||||
|
class="input"
|
||||||
|
:type="passwordType"
|
||||||
|
name="password"
|
||||||
|
:placeholder="textos.password">
|
||||||
|
</div>
|
||||||
|
<div class="control">
|
||||||
|
<a class="button" :class="estilos.botones" @click="togglePassword">
|
||||||
|
{{ textoBotonPassword }}
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<p class="help"
|
||||||
|
:class="estilos.texto">
|
||||||
|
{{ textos.ayuda }}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<div class="field">
|
||||||
|
<div class="control">
|
||||||
|
<input type="submit" class="button" :class="estilos.botones" value="Log in"/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import { mapGetters } from "vuex";
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'PasswordInput',
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
passwordVisible: false,
|
||||||
|
passwordType: "password",
|
||||||
|
}
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
...mapGetters("login", ["textos", "estilos"]),
|
||||||
|
textoBotonPassword() {
|
||||||
|
return `${this.passwordVisible ? "Ocultar" : "Mostrar"} contraseña`;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
togglePassword() {
|
||||||
|
this.passwordType = this.passwordVisible ? "password" : "text";
|
||||||
|
this.passwordVisible = !this.passwordVisible;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.help {
|
||||||
|
font-size: 1rem;
|
||||||
|
}
|
||||||
|
</style>
|
19
resources/js/components/login/input/UserLogin.vue
Normal file
19
resources/js/components/login/input/UserLogin.vue
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
<script>
|
||||||
|
import { defineComponent } from "vue";
|
||||||
|
import PasswordInput from "./PasswordInput.vue";
|
||||||
|
import UserInput from "./user/UserInput.vue";
|
||||||
|
|
||||||
|
export default defineComponent({
|
||||||
|
components: { UserInput, PasswordInput }
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div class="block">
|
||||||
|
<user-input/>
|
||||||
|
<password-input/>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
</style>
|
47
resources/js/components/login/input/barrio/BarrioSelect.vue
Normal file
47
resources/js/components/login/input/barrio/BarrioSelect.vue
Normal file
|
@ -0,0 +1,47 @@
|
||||||
|
<template>
|
||||||
|
<div v-if="region_elegida" class="block">
|
||||||
|
<div class="field">
|
||||||
|
<label class="label" :class="estilos.texto">
|
||||||
|
Seleccioná tu barrio o grupo de compra
|
||||||
|
</label>
|
||||||
|
<div class="control">
|
||||||
|
<div class="select">
|
||||||
|
<select v-model="barrio"
|
||||||
|
@change="selectGrupoDeCompra({ grupo_de_compra: barrio })">
|
||||||
|
<option :disabled="grupo_de_compra_elegido" value=null>
|
||||||
|
Seleccionar
|
||||||
|
</option>
|
||||||
|
<option v-for="(gdc, index) in grupos_de_compra"
|
||||||
|
:key="index"
|
||||||
|
v-text="gdc.nombre"
|
||||||
|
:name="gdc.nombre">
|
||||||
|
</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<password-input v-if="grupo_de_compra_elegido"/>
|
||||||
|
<input readonly v-model="nombre" type="hidden" name="name">
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import { mapGetters, mapMutations, mapState } from "vuex";
|
||||||
|
import PasswordInput from "../PasswordInput.vue";
|
||||||
|
export default {
|
||||||
|
name: 'BarrioSelect',
|
||||||
|
components: { PasswordInput },
|
||||||
|
methods: {
|
||||||
|
...mapMutations("login", ["selectGrupoDeCompra"]),
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
...mapState("login", ["region_elegida", "grupos_de_compra", "grupo_de_compra_elegido"]),
|
||||||
|
...mapGetters("login", ["urlRol", "estilos", "nombre"]),
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
barrio: null,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
}
|
||||||
|
</script>
|
43
resources/js/components/login/input/barrio/RegionSelect.vue
Normal file
43
resources/js/components/login/input/barrio/RegionSelect.vue
Normal file
|
@ -0,0 +1,43 @@
|
||||||
|
<template>
|
||||||
|
<div class="field">
|
||||||
|
<label class="label" :class="estilos.texto">
|
||||||
|
Seleccioná tu región
|
||||||
|
</label>
|
||||||
|
<div class="control">
|
||||||
|
<div class="select">
|
||||||
|
<select @change="selectRegion({ region })" v-model="region">
|
||||||
|
<option :disabled="region_elegida" value=null>
|
||||||
|
Seleccionar
|
||||||
|
</option>
|
||||||
|
<option v-for="(region, index) in regiones"
|
||||||
|
:key="index"
|
||||||
|
v-text="region"
|
||||||
|
:name="region">
|
||||||
|
</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import {mapActions, mapGetters, mapState} from "vuex";
|
||||||
|
export default {
|
||||||
|
name: 'RegionSelect',
|
||||||
|
async mounted() {
|
||||||
|
await this.getRegiones();
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
region: null,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
...mapActions("login", ["getRegiones", "selectRegion"])
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
...mapState("login", ["regiones", "region_elegida"]),
|
||||||
|
...mapGetters("login", ["estilos"]),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
20
resources/js/components/login/input/user/UserInput.vue
Normal file
20
resources/js/components/login/input/user/UserInput.vue
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
name: "UserInput",
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div class="field">
|
||||||
|
<label class="label">Usuario</label>
|
||||||
|
<div class="field has-addons">
|
||||||
|
<div class="control">
|
||||||
|
<input required class="input" type="text" name="name" placeholder="Usuario">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
|
||||||
|
</style>
|
|
@ -1,22 +1,41 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="columns ml-3 mr-3">
|
<div id="pedidos-body" class="pb-6 mb-6">
|
||||||
<pedidos-categorias-container :class="chismosaActiva ? 'hide-below-1024' : ''"></pedidos-categorias-container>
|
<pedido-select v-if="!pedidoDefinido"/>
|
||||||
<pedidos-productos-container :class="chismosaActiva ? 'hide-below-1024' : ''"></pedidos-productos-container>
|
<div v-else>
|
||||||
<pedidos-chismosa v-show="chismosaActiva"></pedidos-chismosa>
|
<nav-migas/>
|
||||||
|
<div class="columns">
|
||||||
|
<div class="column" :class="{ 'is-two-thirds-desktop is-hidden-touch': show_chismosa }">
|
||||||
|
<cartel-pedido-aprobado/>
|
||||||
|
<canasta/>
|
||||||
|
</div>
|
||||||
|
<div class="column is-full-touch" v-if="show_chismosa">
|
||||||
|
<chismosa/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
export default {
|
import { mapActions, mapGetters, mapState } from "vuex";
|
||||||
data() {
|
import CartelPedidoAprobado from "./CartelPedidoAprobado.vue";
|
||||||
return {
|
import PedidoSelect from "./PedidoSelect.vue";
|
||||||
chismosaActiva: false,
|
import Canasta from "./Canasta.vue";
|
||||||
}
|
import NavMigas from "./NavMigas.vue";
|
||||||
|
import Chismosa from "./Chismosa.vue";
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: "PedidosBody",
|
||||||
|
components: { Chismosa, NavMigas, CartelPedidoAprobado, PedidoSelect, Canasta },
|
||||||
|
computed: {
|
||||||
|
...mapGetters('pedido', ["pedidoDefinido"]),
|
||||||
|
...mapState('ui', ["show_chismosa"]),
|
||||||
},
|
},
|
||||||
mounted() {
|
methods: {
|
||||||
Event.$on('toggle-chismosa', (activa) => {
|
...mapActions('productos', ["init"]),
|
||||||
this.chismosaActiva = activa;
|
|
||||||
});
|
|
||||||
},
|
},
|
||||||
|
async mounted() {
|
||||||
|
await this.init();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
34
resources/js/components/pedidos/Canasta.vue
Normal file
34
resources/js/components/pedidos/Canasta.vue
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
<script >
|
||||||
|
import { defineComponent } from "vue";
|
||||||
|
import { mapMutations, mapState } from "vuex";
|
||||||
|
import CategoriasContainer from "./CategoriasContainer.vue";
|
||||||
|
import ProductosContainer from "./ProductosContainer.vue";
|
||||||
|
import Chismosa from "./Chismosa.vue";
|
||||||
|
import DevolucionesModal from "./DevolucionesModal.vue";
|
||||||
|
|
||||||
|
export default defineComponent({
|
||||||
|
components: { DevolucionesModal, CategoriasContainer, ProductosContainer, Chismosa },
|
||||||
|
computed: {
|
||||||
|
...mapState('ui', ["show_chismosa", "show_devoluciones", "tags_interactuada"])
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
...mapMutations("ui", ["toggleTags"]),
|
||||||
|
},
|
||||||
|
mounted() {
|
||||||
|
if (!this.tags_interactuada)
|
||||||
|
this.toggleTags(false);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div class="columns ml-3 mr-3" v-else>
|
||||||
|
<categorias-container :class="show_chismosa ? 'hide-below-1024' : ''"/>
|
||||||
|
<productos-container :class="show_chismosa ? 'hide-below-1024' : ''"/>
|
||||||
|
<devoluciones-modal v-show="show_devoluciones"/>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
|
||||||
|
</style>
|
|
@ -1,31 +1,18 @@
|
||||||
<template>
|
<template>
|
||||||
<div v-show="aprobado" class="notification is-warning has-text-centered">
|
<div v-if="aprobado" class="notification is-warning has-text-centered">
|
||||||
Tu pedido fue <strong>aprobado</strong>, por lo que no puede ser modificado
|
Tu pedido fue <strong>aprobado</strong>, por lo que no puede ser modificado
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
export default {
|
import { mapState } from "vuex";
|
||||||
data() {
|
|
||||||
return {
|
export default {
|
||||||
aprobado: false,
|
name: 'CartelPedidoAprobado',
|
||||||
}
|
computed: {
|
||||||
},
|
...mapState('pedido',["aprobado"]),
|
||||||
mounted() {
|
|
||||||
Event.$on('pedido-actualizado', this.actualizarEstado);
|
|
||||||
if (this.$root.pedido != null) {
|
|
||||||
this.actualizarEstado();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
pedidoAprobado: function() {
|
|
||||||
return this.$root.pedido.aprobado;
|
|
||||||
},
|
|
||||||
actualizarEstado: function() {
|
|
||||||
this.aprobado = this.pedidoAprobado();
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
|
|
|
@ -1,41 +1,92 @@
|
||||||
<template>
|
<template>
|
||||||
<div v-show="visible" class="column">
|
<div v-show="visible" class="column">
|
||||||
<div class="columns is-multiline is-mobile">
|
<div ref="categorias"
|
||||||
<div v-for="(categoria,i) in categorias" :key="i" class="block column is-one-quarter-desktop is-one-third-tablet is-half-mobile">
|
class="columns is-multiline is-mobile"
|
||||||
<div @click.capture="seleccionarCategoria(categoria)" class="card" style="height:100%" >
|
:class="{ 'align-last-left': isLastRowIncomplete }">
|
||||||
|
<div v-for="(categoria,i) in categorias" :key="i"
|
||||||
|
:class="{ 'is-3-desktop is-2-fullhd': !show_chismosa }"
|
||||||
|
class="column is-4-tablet is-6-mobile hover-dedito">
|
||||||
|
<div @click.capture="seleccionar(categoria)" class="card" style="height: 100%">
|
||||||
<div class="card-content">
|
<div class="card-content">
|
||||||
<div class="media">
|
<div class="media">
|
||||||
<div class="media-content" style="overflow:hidden">
|
<div class="media-content" style="overflow: hidden">
|
||||||
<p class="title is-6" v-text="categoria"></p>
|
<p class="title is-size-7-mobile is-size-6-tablet has-text-centered" v-text="categoria"></p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div><!-- END CARD -->
|
|
||||||
</div><!-- END BLOCK COLUMN -->
|
|
||||||
</div><!-- END COLUMNS -->
|
|
||||||
</div><!-- END CONTAINER -->
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
export default {
|
import { mapActions, mapMutations, mapState } from "vuex";
|
||||||
|
export default {
|
||||||
|
name: 'CategoriasContainer',
|
||||||
|
computed: {
|
||||||
|
...mapState('productos', ["categorias", "filtro"]),
|
||||||
|
...mapState('ui', ["show_chismosa"]),
|
||||||
|
visible() {
|
||||||
|
return this.filtro === null;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
...mapActions('productos', ["seleccionarCategoria"]),
|
||||||
|
...mapMutations('ui', ["addMiga"]),
|
||||||
|
seleccionar(categoria) {
|
||||||
|
this.seleccionarCategoria({ categoria: categoria });
|
||||||
|
this.addMiga({ nombre: categoria, action: "productos/seleccionarCategoria", arguments: { categoria: categoria }});
|
||||||
|
},
|
||||||
|
checkIfLastRowIncomplete() {
|
||||||
|
this.$nextTick(() => {
|
||||||
|
const wrapper = this.$refs.categorias;
|
||||||
|
if (!wrapper) return;
|
||||||
|
|
||||||
|
const columns = wrapper.querySelectorAll('.column');
|
||||||
|
if (columns.length === 0) {
|
||||||
|
this.isLastRowIncomplete = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const firstRowTop = columns[0].offsetTop;
|
||||||
|
let firstRowCount = 0;
|
||||||
|
columns.forEach(col => {
|
||||||
|
if (col.offsetTop === firstRowTop) firstRowCount++;
|
||||||
|
});
|
||||||
|
this.isLastRowIncomplete = this.categorias.length % firstRowCount !== 0;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
categorias: null,
|
isLastRowIncomplete: false
|
||||||
visible: true
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
axios.get("/api/categorias").then(response => {
|
this.checkIfLastRowIncomplete();
|
||||||
this.categorias = response.data;
|
window.addEventListener('resize', this.checkIfLastRowIncomplete);
|
||||||
});
|
|
||||||
Event.$emit("migas-setear-como-inicio", this.$rootMiga);
|
|
||||||
Event.$on("filtrar-productos", (_) => this.visible = false)
|
|
||||||
},
|
},
|
||||||
methods: {
|
beforeDestroy() {
|
||||||
seleccionarCategoria(categoria) {
|
window.removeEventListener('resize', this.checkIfLastRowIncomplete);
|
||||||
this.visible = false;
|
},
|
||||||
Event.$emit("filtrar-productos",'categoria',categoria);
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.hover-dedito {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
.columns.align-last-left {
|
||||||
|
justify-content: flex-start !important;
|
||||||
|
}
|
||||||
|
.columns.align-last-left > .column:last-child:nth-child(3n),
|
||||||
|
.columns.align-last-left > .column:last-child:nth-child(2n),
|
||||||
|
.columns.align-last-left > .column:last-child {
|
||||||
|
margin-right: auto;
|
||||||
|
}
|
||||||
|
.title {
|
||||||
|
word-break: keep-all;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="column is-one-third">
|
<div class="fixed-right mr-3 ml-3">
|
||||||
<div class="fixed-right">
|
|
||||||
<table v-show="mostrar_tabla" class="table is-striped is-bordered tabla-chismosa is-narrow">
|
<table v-show="mostrar_tabla" class="table is-striped is-bordered tabla-chismosa is-narrow">
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
|
@ -12,20 +11,20 @@
|
||||||
<tfoot>
|
<tfoot>
|
||||||
<tr>
|
<tr>
|
||||||
<th><abbr title="Bonos de Transporte">B. Transporte</abbr></th>
|
<th><abbr title="Bonos de Transporte">B. Transporte</abbr></th>
|
||||||
<th class="has-text-right">{{ cantidad_bonos_transporte }}</th>
|
<th class="has-text-right">{{ cantidad_transporte }}</th>
|
||||||
<th class="has-text-right">{{ total_bonos_transporte }}</th>
|
<th class="has-text-right">{{ total_transporte }}</th>
|
||||||
</tr>
|
</tr>
|
||||||
<tr v-if="this.$root.devoluciones">
|
<tr v-if="grupo_de_compra.devoluciones_habilitadas && !aprobado">
|
||||||
<th><p>Devoluciones</p></th>
|
<th><p>Devoluciones</p></th>
|
||||||
<td>
|
<td>
|
||||||
<abbr :title="notas_devoluciones">{{ notas_devoluciones_abbr }}</abbr>
|
<abbr :title="devoluciones_notas">{{ notas_abreviadas }}</abbr>
|
||||||
<button @click.capture="modificarDevoluciones()" class="button is-warning is-small">
|
<button @click.capture="toggleDevoluciones()" class="button is-warning is-small">
|
||||||
<span class="icon">
|
<span class="icon">
|
||||||
<i class="fas fa-edit"></i>
|
<i class="fas fa-edit"></i>
|
||||||
</span>
|
</span>
|
||||||
</button>
|
</button>
|
||||||
</td>
|
</td>
|
||||||
<th class="has-text-right">-{{ devoluciones }}</th>
|
<th class="has-text-right">-{{ devoluciones_total }}</th>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<th>Total total</th>
|
<th>Total total</th>
|
||||||
|
@ -34,69 +33,53 @@
|
||||||
</tr>
|
</tr>
|
||||||
</tfoot>
|
</tfoot>
|
||||||
<tbody>
|
<tbody>
|
||||||
<pedidos-producto-row v-for="producto in productos" :producto="producto" :key="producto.id"></pedidos-producto-row>
|
<producto-row v-for="producto in productos" :producto="producto" :key="producto.id"/>
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
<p class="has-text-centered" v-show="!mostrar_tabla">
|
<p class="has-text-centered" v-show="!mostrar_tabla">
|
||||||
Compa, todavía no agregaste nada a la chismosa.
|
Compa, todavía no agregaste nada a la chismosa.
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
export default {
|
import ProductoRow from "./ProductoRow.vue";
|
||||||
data() {
|
import { mapMutations, mapState } from "vuex";
|
||||||
return {
|
|
||||||
mostrar_tabla: false,
|
export default {
|
||||||
cantidad_bonos_transporte: 0,
|
components: { ProductoRow },
|
||||||
total_bonos_transporte: 0,
|
computed: {
|
||||||
devoluciones: 0,
|
...mapState('pedido',[
|
||||||
notas_devoluciones: "",
|
"grupo_de_compra",
|
||||||
notas_devoluciones_abbr: "",
|
"productos",
|
||||||
total: 0,
|
"total",
|
||||||
productos: [],
|
"total_transporte",
|
||||||
}
|
"cantidad_transporte",
|
||||||
|
"devoluciones_total",
|
||||||
|
"devoluciones_notas",
|
||||||
|
"aprobado"
|
||||||
|
]),
|
||||||
|
notas_abreviadas() {
|
||||||
|
return this.devoluciones_notas.substring(0, 15) + (this.devoluciones_notas.length > 15 ? "..." : "");
|
||||||
|
},
|
||||||
|
mostrar_tabla() {
|
||||||
|
return this.productos?.length !== 0;
|
||||||
},
|
},
|
||||||
mounted() {
|
|
||||||
Event.$on('pedido-actualizado', this.pedidoActualizado);
|
|
||||||
Event.$on('toggle-chismosa', this.pedidoActualizado);
|
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
pedidoActualizado: function() {
|
...mapMutations('ui',["toggleDevoluciones"]),
|
||||||
this.mostrar_tabla = this.$root.productos.length > 0;
|
|
||||||
this.cantidad_bonos_transporte = this.cantidadBonosDeTransporte();
|
|
||||||
this.total_bonos_transporte = this.totalBonosDeTransporte();
|
|
||||||
this.devoluciones = this.$root.pedido.devoluciones_total;
|
|
||||||
this.notas_devoluciones = this.$root.pedido.devoluciones_notas;
|
|
||||||
this.notas_devoluciones_abbr = this.notas_devoluciones.substring(0, 15);
|
|
||||||
if (this.notas_devoluciones.length > 15) {
|
|
||||||
this.notas_devoluciones_abbr += "...";
|
|
||||||
}
|
|
||||||
this.total = this.$root.pedido.total;
|
|
||||||
this.productos = this.$root.productos;
|
|
||||||
},
|
},
|
||||||
modificarDevoluciones: function() {
|
}
|
||||||
Event.$emit("modificar-devoluciones");
|
|
||||||
},
|
|
||||||
cantidadBonosDeTransporte: function() {
|
|
||||||
return this.$root.pedido.cantidad_transporte;
|
|
||||||
},
|
|
||||||
totalBonosDeTransporte: function() {
|
|
||||||
return this.$root.pedido.total_transporte
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
.tabla-chismosa {
|
.tabla-chismosa {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
.fixed-right {
|
|
||||||
|
.fixed-right {
|
||||||
position: fixed;
|
position: fixed;
|
||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
max-height: 81vh;
|
max-height: 81vh;
|
||||||
margin-right: 20px;
|
}
|
||||||
}
|
|
||||||
</style>
|
</style>
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="dropdown is-right navbar-item" :class="{'is-active':activa}">
|
<div class="dropdown is-right navbar-item" :class="{'is-active': show_chismosa}">
|
||||||
<div class="dropdown-trigger">
|
<div class="dropdown-trigger">
|
||||||
<a class="text-a" aria-haspopup="true" :aria-controls="id" @click.capture="toggle">
|
<a class="text-a" aria-haspopup="true" :aria-controls="ariaControls" @click.capture="toggleChismosa">
|
||||||
<span class="icon is-small mr-1">
|
<span class="icon is-small mr-1">
|
||||||
<img src="/assets/chismosa.png">
|
<img src="/assets/chismosa.png">
|
||||||
</span>
|
</span>
|
||||||
|
@ -13,33 +13,23 @@
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import Chismosa from './Chismosa.vue'
|
import Chismosa from './Chismosa.vue'
|
||||||
|
import { mapMutations, mapState } from "vuex";
|
||||||
export default {
|
export default {
|
||||||
components: {
|
components: {
|
||||||
Chismosa
|
Chismosa
|
||||||
},
|
},
|
||||||
props: {
|
props: {
|
||||||
id: {
|
ariaControls: {
|
||||||
type: String,
|
type: String,
|
||||||
required: true
|
required: true
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
data() {
|
computed: {
|
||||||
return {
|
...mapState('pedido',["total"]),
|
||||||
activa: false,
|
...mapState('ui',["show_chismosa"]),
|
||||||
total: 0,
|
|
||||||
}
|
|
||||||
},
|
|
||||||
mounted() {
|
|
||||||
Event.$on('pedido-actualizado', this.actualizar);
|
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
toggle() {
|
...mapMutations('ui',["toggleChismosa"]),
|
||||||
this.activa = !this.activa;
|
|
||||||
Event.$emit("toggle-chismosa", this.activa);
|
|
||||||
},
|
|
||||||
actualizar() {
|
|
||||||
this.total = this.$root.pedido.total;
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -1,67 +1,71 @@
|
||||||
<template>
|
<template>
|
||||||
<div v-bind:class="visible ? 'is-active modal' : 'modal'">
|
<div :class="show_devoluciones ? 'is-active modal' : 'modal'">
|
||||||
<div class="modal-background"></div>
|
<div class="modal-background"></div>
|
||||||
<div class="modal-card">
|
<div class="modal-card">
|
||||||
<header class="modal-card-head">
|
<header class="modal-card-head">
|
||||||
<p class="modal-card-title">Devoluciones</p>
|
<p class="modal-card-title">Devoluciones</p>
|
||||||
<button class="delete" aria-label="close" @click.capture="cerrar"></button>
|
<button class="delete" aria-label="close" @click.capture="toggleDevoluciones()"></button>
|
||||||
</header>
|
</header>
|
||||||
<section class="modal-card-body">
|
<section class="modal-card-body">
|
||||||
<div class="field has-addons is-centered is-thin-centered">
|
<div class="field has-addons is-centered is-thin-centered">
|
||||||
<p class="control">
|
<p class="control">
|
||||||
Total:
|
Total:
|
||||||
<input id="total" class="input" type="number" v-model="total" style="text-align: center">
|
<input id="totalControl" class="input" type="number" v-model="totalControl"
|
||||||
|
style="text-align: center">
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
<div class="field has-addons is-centered is-thin-centered">
|
<div class="field has-addons is-centered is-thin-centered">
|
||||||
<p class="control">
|
<p class="control">
|
||||||
Notas:
|
Notas:
|
||||||
<input id="notas" class="input" type="text" v-model.text="notas">
|
<input id="notasControl" class="input" type="text" v-model.text="notasControl">
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
<footer class="modal-card-foot">
|
<footer class="modal-card-foot">
|
||||||
<button class="button is-success" @click="modificar">Aceptar</button>
|
<button class="button is-success" @click="modificar">Aceptar</button>
|
||||||
<button class="button" @click.capture="cerrar">Cancelar</button>
|
<button class="button" @click.capture="toggleDevoluciones()">Cancelar</button>
|
||||||
</footer>
|
</footer>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
export default {
|
import { mapActions, mapMutations, mapState } from "vuex";
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'DevolucionesModal',
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
visible: false,
|
totalControl: 0,
|
||||||
total: 0,
|
notasControl: "",
|
||||||
notas: "",
|
|
||||||
}
|
|
||||||
},
|
|
||||||
computed: {
|
|
||||||
miga: function() {
|
|
||||||
return {
|
|
||||||
nombre: "Devoluciones",
|
|
||||||
href: "#devoluciones",
|
|
||||||
}
|
|
||||||
},
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
cerrar() {
|
|
||||||
this.visible = false;
|
|
||||||
Event.$emit("migas-pop");
|
|
||||||
},
|
|
||||||
modificar() {
|
|
||||||
Event.$emit('sync-devoluciones', this.total, this.notas);
|
|
||||||
this.cerrar();
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
Event.$on('modificar-devoluciones', () => {
|
this.actualizar();
|
||||||
this.visible = true;
|
|
||||||
this.total = this.$root.pedido.devoluciones_total;
|
|
||||||
this.notas = this.$root.pedido.devoluciones_notas;
|
|
||||||
Event.$emit("migas-agregar", this.miga);
|
|
||||||
});
|
|
||||||
},
|
},
|
||||||
|
watch: {
|
||||||
|
cantidadEnChismosa() {
|
||||||
|
this.actualizar();
|
||||||
|
},
|
||||||
|
notasEnChismosa() {
|
||||||
|
this.actualizar();
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
...mapState('ui', ["show_devoluciones"]),
|
||||||
|
...mapState('pedido', ["devoluciones_total", "devoluciones_notas"])
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
...mapMutations('ui', ["toggleDevoluciones"]),
|
||||||
|
...mapActions('pedido', ["modificarDevoluciones"]),
|
||||||
|
modificar() {
|
||||||
|
this.modificarDevoluciones({ monto: this.totalControl, notas: this.notasControl });
|
||||||
|
this.toggleDevoluciones();
|
||||||
|
},
|
||||||
|
actualizar() {
|
||||||
|
this.totalControl = this.devoluciones_total;
|
||||||
|
this.notasControl = this.devoluciones_notas;
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
</script>
|
</script>
|
|
@ -1,55 +0,0 @@
|
||||||
<template>
|
|
||||||
<div v-show="visible" class="block">
|
|
||||||
<div class="field">
|
|
||||||
<label class="label">Contraseña del barrio</label>
|
|
||||||
<div class="field has-addons">
|
|
||||||
<div class="control">
|
|
||||||
<input required class="input" :type="this.passwordType" name="password" placeholder="Contraseña del barrio">
|
|
||||||
</div>
|
|
||||||
<div class="control">
|
|
||||||
<a class="button is-info" @click="togglePassword">
|
|
||||||
{{ (passwordVisible ? 'Ocultar' : 'Mostrar') + ' contraseña'}}
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<p class="help">Si no la sabés, consultá a tus compañerxs.</p>
|
|
||||||
</div>
|
|
||||||
<div class="field">
|
|
||||||
<div class="control">
|
|
||||||
<input type="submit" class="button is-success" value="Ingresar"/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
export default {
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
visible: false,
|
|
||||||
gdc: this.$root.gdc,
|
|
||||||
passwordVisible: false,
|
|
||||||
passwordType: "password",
|
|
||||||
}
|
|
||||||
},
|
|
||||||
mounted() {
|
|
||||||
Event.$on('gdc-seleccionado', (gdc) => {
|
|
||||||
this.$root.gdc = gdc;
|
|
||||||
this.visible = true;
|
|
||||||
});
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
togglePassword() {
|
|
||||||
if (this.passwordVisible) this.passwordType = "password";
|
|
||||||
else this.passwordType = "text"
|
|
||||||
this.passwordVisible = !this.passwordVisible
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style>
|
|
||||||
.help {
|
|
||||||
font-size: 1rem;
|
|
||||||
}
|
|
||||||
</style>
|
|
|
@ -1,45 +1,39 @@
|
||||||
<template>
|
<template>
|
||||||
<nav class="breadcrumb is-centered has-background-danger-light is-fixed-top" aria-label="breadcrumbs" v-show="visible">
|
<nav class="breadcrumb is-centered has-background-danger-light is-fixed-top"
|
||||||
|
aria-label="breadcrumbs" v-show="visible">
|
||||||
<ul class="mt-4">
|
<ul class="mt-4">
|
||||||
<li v-for="(miga, i) in migas" :key="i" :class="{'is-active': i == migaActiva}">
|
<li v-for="(miga, i) in migas" :key="i" :class="{'is-active': i === migaActiva}">
|
||||||
<a :href="miga.href" v-text="miga.nombre"
|
<a @click="clickMiga({ miga: miga })"
|
||||||
:class="{'has-text-danger': i != migaActiva}"></a>
|
v-text="miga.nombre"
|
||||||
|
:class="{'has-text-danger': i !== migaActiva}">
|
||||||
|
</a>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</nav>
|
</nav>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
export default {
|
import { mapActions, mapMutations, mapState } from "vuex";
|
||||||
data() {
|
|
||||||
return {
|
export default {
|
||||||
migas: []
|
methods: {
|
||||||
}
|
...mapActions('productos', ["getProductos"]),
|
||||||
|
...mapActions('ui', ["clickMiga"]),
|
||||||
|
...mapMutations('ui', ["addMiga"]),
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
visible: function() {
|
...mapState('ui', ["migas"]),
|
||||||
return this.migas.length > 0
|
visible() {
|
||||||
|
return this.migas.length > 0;
|
||||||
|
},
|
||||||
|
migaActiva() {
|
||||||
|
return this.migas.length - 1;
|
||||||
},
|
},
|
||||||
migaActiva: function() {
|
|
||||||
return this.migas.length-1
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
Event.$on('migas-setear-como-inicio', (miga) => {
|
this.addMiga({ nombre: 'Categorias', action: 'productos/getProductos' });
|
||||||
this.migas = [];
|
},
|
||||||
this.migas.push(miga);
|
}
|
||||||
});
|
|
||||||
Event.$on('migas-agregar', (miga) => {
|
|
||||||
this.migas.push(miga);
|
|
||||||
});
|
|
||||||
Event.$on('migas-reset', () => {
|
|
||||||
this.migas = [];
|
|
||||||
});
|
|
||||||
Event.$on('migas-pop', () => {
|
|
||||||
this.migas.pop();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
|
@ -47,8 +41,8 @@ nav.breadcrumb.is-fixed-top {
|
||||||
position: fixed;
|
position: fixed;
|
||||||
left: 0;
|
left: 0;
|
||||||
right: 0;
|
right: 0;
|
||||||
top: 3.25rem;
|
top: 2.25rem;
|
||||||
height: 2.75rem;
|
|
||||||
z-index: 5;
|
z-index: 5;
|
||||||
|
padding: 0.5rem;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
121
resources/js/components/pedidos/PedidoSelect.vue
Normal file
121
resources/js/components/pedidos/PedidoSelect.vue
Normal file
|
@ -0,0 +1,121 @@
|
||||||
|
<template>
|
||||||
|
<section class="section">
|
||||||
|
<div id="root" class="container">
|
||||||
|
<h1 class="title">
|
||||||
|
Pedidos MPS
|
||||||
|
</h1>
|
||||||
|
<p class="subtitle">
|
||||||
|
Bienvenidx a la aplicación de pedidos del
|
||||||
|
<strong>Mercado Popular de Subsistencia</strong>
|
||||||
|
</p>
|
||||||
|
<div>
|
||||||
|
<label class="label">Escribí el nombre de tu familia o grupo de convivencia</label>
|
||||||
|
<div class="columns">
|
||||||
|
<div class="column is-two-thirds">
|
||||||
|
<div class="field">
|
||||||
|
<div class="control">
|
||||||
|
<input class="input" @input="onType" v-model="searchString"/>
|
||||||
|
</div>
|
||||||
|
<p class="help">
|
||||||
|
Debe ser clarx para que tus compas del barrio te identifiquen.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="column is-one-third buttons">
|
||||||
|
<button class="button is-danger" v-if="!deshabilitado" @click="submit()">
|
||||||
|
Crear nuevo pedido
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div v-if="pedidos.length" class="block">
|
||||||
|
<label class="label">
|
||||||
|
Si ya comenzaste a hacer tu pedido este mes, elegilo en esta lista:
|
||||||
|
</label>
|
||||||
|
<p class="help">
|
||||||
|
Podés seguir escribiendo en el campo de arriba para refinar la búsqueda.
|
||||||
|
</p>
|
||||||
|
<div class="columns is-mobile"
|
||||||
|
v-for="(subpedidoExistente, index) in pedidos"
|
||||||
|
:class="{'has-background-grey-lighter': index % 2}"
|
||||||
|
:key="index">
|
||||||
|
<div class="column is-half-mobile is-two-thirds-desktop is-two-thirds-tablet">
|
||||||
|
<p class="nombre">
|
||||||
|
{{ subpedidoExistente.nombre }}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<div class="buttons column is-half-mobile is-one-third-desktop is-one-third-tablet">
|
||||||
|
<button class="button is-danger" @click="submit(subpedidoExistente)">
|
||||||
|
Continuar pedido
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import { mapActions, mapMutations, mapState } from "vuex";
|
||||||
|
import axios from "axios";
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'PedidoSelect',
|
||||||
|
async mounted() {
|
||||||
|
this.toggleTags(false);
|
||||||
|
await this.getGrupoDeCompra();
|
||||||
|
const sesion = await axios.get("/pedido/sesion");
|
||||||
|
if (sesion.data.id)
|
||||||
|
await this.elegirPedido({ pedido_id: sesion.data.id });
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
pedidos: [],
|
||||||
|
searchString: null,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
...mapState('pedido', ["grupo_de_compra"]),
|
||||||
|
deshabilitado() {
|
||||||
|
return !this.searchString?.trim()
|
||||||
|
|| this.pedidos.some(p => p.nombre.toLowerCase() === this.searchString.toLowerCase())
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
...mapActions('pedido', ["getGrupoDeCompra", "crearPedido", "elegirPedido"]),
|
||||||
|
...mapMutations("ui", ["toggleTags"]),
|
||||||
|
async getPedidos(nombre) {
|
||||||
|
const response = await axios.get('/api/subpedidos/',{
|
||||||
|
params: {
|
||||||
|
nombre: nombre,
|
||||||
|
grupo_de_compra: this.grupo_de_compra.id
|
||||||
|
}
|
||||||
|
});
|
||||||
|
this.pedidos = response.data;
|
||||||
|
},
|
||||||
|
onType() {
|
||||||
|
if (!this.searchString)
|
||||||
|
this.pedidos = [];
|
||||||
|
else
|
||||||
|
this.getPedidos(this.searchString);
|
||||||
|
},
|
||||||
|
async submit(pedido) {
|
||||||
|
if (pedido)
|
||||||
|
await this.elegirPedido({ pedido_id: pedido.id });
|
||||||
|
else
|
||||||
|
await this.crearPedido({
|
||||||
|
nombre: this.searchString,
|
||||||
|
grupo_de_compra_id: this.grupo_de_compra.id
|
||||||
|
});
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.nombre {
|
||||||
|
padding-top: calc(.5em - 1px);
|
||||||
|
margin-bottom: .5rem
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
|
@ -1,35 +1,42 @@
|
||||||
<template>
|
<template>
|
||||||
<div>
|
<div class="is-justify-content-center">
|
||||||
<div class="field has-addons contador">
|
<div class="field has-addons is-justify-content-center contador">
|
||||||
<div class="control">
|
<div class="control">
|
||||||
<button class="button is-small" @click.capture="decrementar();">
|
<button class="button is-small" :disabled="cantidadControl < 1" v-if="!aprobado" @click.capture="decrementar();">
|
||||||
<i class="fa fa-solid fa-minus"></i>
|
<i class="fa fa-solid fa-minus"></i>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<div class="control">
|
<div class="control">
|
||||||
<input id="cantidad" v-model="cantidad" class="input is-small" type="number" style="text-align: center">
|
<input id="cantidad"
|
||||||
|
v-model="cantidadControl"
|
||||||
|
class="input is-small"
|
||||||
|
type="number"
|
||||||
|
style="text-align: center"
|
||||||
|
:readonly="aprobado">
|
||||||
</div>
|
</div>
|
||||||
<div class="control" @click="incrementar();">
|
<div class="control">
|
||||||
<button class="button is-small">
|
<button class="button is-small" v-if="!aprobado" @click="incrementar();">
|
||||||
<i class="fa fa-solid fa-plus"></i>
|
<i class="fa fa-solid fa-plus"></i>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<button :disabled="disableConfirm()" class="button is-small is-success ml-1" @click="confirmar()">
|
<button :disabled="!hayCambios || cantidadControl < 0" v-if="!aprobado" class="button is-small is-success ml-1" @click="confirmar()">
|
||||||
<span class="icon">
|
<span class="icon">
|
||||||
<i class="fas fa-check"></i>
|
<i class="fas fa-check"></i>
|
||||||
</span>
|
</span>
|
||||||
</button>
|
</button>
|
||||||
<button :disabled="!puedeBorrar()" class="button is-small is-danger ml-1" @click="borrar()">
|
<button :disabled="!puedeBorrar" v-if="!aprobado" class="button is-small is-danger ml-1" @click="borrar()">
|
||||||
<span class="icon">
|
<span class="icon">
|
||||||
<i class="fas fa-trash-alt"></i>
|
<i class="fas fa-trash-alt"></i>
|
||||||
</span>
|
</span>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<div v-if="producto.requiere_notas" v-bind:class="{'has-icons-right': notas_warning_visible}" class="control is-full-width has-icons-left">
|
<div v-if="!aprobado && requiere_notas"
|
||||||
|
:class="{'has-icons-right': notas_warning_visible}"
|
||||||
|
class="control is-full-width has-icons-left">
|
||||||
<span class="icon is-small is-left">
|
<span class="icon is-small is-left">
|
||||||
<i class="fas fa-sticky-note"></i>
|
<i class="fas fa-sticky-note"></i>
|
||||||
</span>
|
</span>
|
||||||
<input v-model="notas" v-bind:class="{'is-danger': notas_warning_visible}" id="notas" class="input" type="text" placeholder="Talle o color" />
|
<input v-model="notasControl" v-bind:class="{'is-danger': notas_warning_visible}" id="notas" class="input" type="text" placeholder="Talle o color"/>
|
||||||
<span v-if="notas_warning_visible" class="icon is-small is-right">
|
<span v-if="notas_warning_visible" class="icon is-small is-right">
|
||||||
<i class="fas fa-exclamation-triangle"></i>
|
<i class="fas fa-exclamation-triangle"></i>
|
||||||
</span>
|
</span>
|
||||||
|
@ -43,98 +50,111 @@
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
export default {
|
import { mapActions, mapGetters, mapState } from "vuex";
|
||||||
|
|
||||||
|
export default {
|
||||||
props: {
|
props: {
|
||||||
producto: Object
|
producto_id: {
|
||||||
|
type: Number,
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
requiere_notas: {
|
||||||
|
type: Number,
|
||||||
|
required: true,
|
||||||
|
}
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
cantidad: this.cantidadEnChismosa(),
|
cantidadControl: 0,
|
||||||
notas: this.notasEnChismosa(),
|
notasControl: '',
|
||||||
notas_warning_visible: false,
|
notas_warning_visible: false,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
watch: {
|
||||||
|
cantidadEnChismosa() {
|
||||||
|
this.actualizar();
|
||||||
|
},
|
||||||
|
notasEnChismosa() {
|
||||||
|
this.actualizar();
|
||||||
|
}
|
||||||
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
Event.$on('sync-subpedido', (cantidad, productoId, notas) => {
|
this.actualizar();
|
||||||
if (this.producto.id === productoId)
|
},
|
||||||
this.sincronizar(cantidad, notas);
|
computed: {
|
||||||
});
|
...mapState('pedido', ["aprobado"]),
|
||||||
|
...mapGetters('pedido', ["enChismosa", "cantidad", "notas"]),
|
||||||
|
cantidadEnChismosa() {
|
||||||
|
return this.cantidad(this.producto_id);
|
||||||
|
},
|
||||||
|
notasEnChismosa() {
|
||||||
|
return this.notas(this.producto_id);
|
||||||
|
},
|
||||||
|
hayCambios() {
|
||||||
|
return this.cantidadControl !== this.cantidadEnChismosa || this.notasControl !== this.notasEnChismosa;
|
||||||
|
},
|
||||||
|
puedeBorrar() {
|
||||||
|
return this.enChismosa(this.producto_id) && !this.aprobado;
|
||||||
|
},
|
||||||
|
faltaNotas() {
|
||||||
|
return this.requiere_notas && this.cantidadControl > 0 && !this.notasControl;
|
||||||
|
},
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
notasEnChismosa() {
|
...mapActions('pedido', ["modificarChismosa"]),
|
||||||
return this.producto.pivot !== undefined ? this.producto.pivot.notas : "";
|
|
||||||
},
|
|
||||||
cantidadEnChismosa() {
|
|
||||||
return this.producto.pivot !== undefined ? this.producto.pivot.cantidad : 0;
|
|
||||||
},
|
|
||||||
decrementar() {
|
decrementar() {
|
||||||
this.cantidad -= 1;
|
this.cantidadControl -= 1;
|
||||||
},
|
},
|
||||||
incrementar() {
|
incrementar() {
|
||||||
this.cantidad += 1;
|
this.cantidadControl += 1;
|
||||||
},
|
},
|
||||||
confirmar() {
|
borrar() {
|
||||||
if (this.warningNotas()) {
|
this.cantidadControl = 0;
|
||||||
|
this.confirmar();
|
||||||
|
},
|
||||||
|
async confirmar() {
|
||||||
|
if (this.faltaNotas) {
|
||||||
this.notas_warning_visible = true;
|
this.notas_warning_visible = true;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
console.log("Emit sync " + this.cantidad + " " + this.notas);
|
await this.modificarChismosa({
|
||||||
Event.$emit('sync-subpedido', this.cantidad, this.producto.id, this.notas);
|
producto_id: this.producto_id,
|
||||||
|
cantidad: this.cantidadControl,
|
||||||
|
notas: this.notasControl
|
||||||
|
});
|
||||||
},
|
},
|
||||||
borrar() {
|
actualizar() {
|
||||||
this.cantidad = 0;
|
this.cantidadControl = this.cantidadEnChismosa;
|
||||||
this.confirmar();
|
this.notasControl = this.notasEnChismosa;
|
||||||
},
|
|
||||||
sincronizar(cantidad, notas) {
|
|
||||||
this.notas_warning_visible = false;
|
|
||||||
this.notas = notas;
|
|
||||||
this.cantidad = cantidad;
|
|
||||||
if (this.producto.pivot !== undefined) {
|
|
||||||
this.producto.pivot.cantidad = cantidad;
|
|
||||||
this.producto.pivot.notas = notas;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
hayCambios() {
|
|
||||||
if (this.cantidad != this.cantidadEnChismosa()) return true;
|
|
||||||
|
|
||||||
return this.cantidad > 0 && this.notas != this.notasEnChismosa();
|
|
||||||
},
|
|
||||||
puedeBorrar() {
|
|
||||||
return this.cantidadEnChismosa() > 0;
|
|
||||||
},
|
|
||||||
warningNotas() {
|
|
||||||
return this.producto.requiere_notas && this.cantidad > 0 && !this.notas;
|
|
||||||
},
|
|
||||||
disableConfirm() {
|
|
||||||
return !this.hayCambios();
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
/* Chrome, Safari, Edge, Opera */
|
/* Chrome, Safari, Edge, Opera */
|
||||||
input::-webkit-outer-spin-button,
|
input::-webkit-outer-spin-button,
|
||||||
input::-webkit-inner-spin-button {
|
input::-webkit-inner-spin-button {
|
||||||
-webkit-appearance: none;
|
-webkit-appearance: none;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Firefox */
|
/* Firefox */
|
||||||
input[type=number] {
|
input[type=number] {
|
||||||
appearance: textfield;
|
appearance: textfield;
|
||||||
-moz-appearance: textfield;
|
-moz-appearance: textfield;
|
||||||
}
|
}
|
||||||
|
|
||||||
.contador {
|
.contador {
|
||||||
min-width: 178px;
|
min-width: 1.5rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.is-danger {
|
.is-danger {
|
||||||
background-color: #fca697;
|
background-color: #fca697;
|
||||||
}
|
}
|
||||||
.is-danger::placeholder {
|
|
||||||
|
.is-danger::placeholder {
|
||||||
color: #fff;
|
color: #fff;
|
||||||
opacity: 1; /* Firefox */
|
opacity: 1; /* Firefox */
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
|
@ -1,83 +1,62 @@
|
||||||
<script>
|
<script>
|
||||||
|
import ProductoCantidad from "./ProductoCantidad.vue";
|
||||||
|
import { mapGetters, mapState } from "vuex";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: "ProductoCard",
|
name: "ProductoCard",
|
||||||
|
components: { ProductoCantidad },
|
||||||
props: {
|
props: {
|
||||||
producto: Object
|
producto: {
|
||||||
},
|
type: Object,
|
||||||
data() {
|
required: true
|
||||||
return {
|
|
||||||
cantidad: this.producto.cantidad,
|
|
||||||
enChismosa: this.producto.cantidad,
|
|
||||||
notas: this.producto.notas,
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
mounted() {
|
computed: {
|
||||||
Event.$on('sync-subpedido', (cantidad, productoId, notas) => {
|
...mapState('ui', ["show_chismosa"]),
|
||||||
if (this.producto.id === productoId)
|
...mapState('pedido', ["aprobado"]),
|
||||||
this.sincronizar(cantidad, notas);
|
...mapGetters('pedido', ["enChismosa", "cantidad"]),
|
||||||
});
|
fuePedido() {
|
||||||
|
return this.enChismosa(this.producto.id);
|
||||||
},
|
},
|
||||||
methods: {
|
cantidadEnChismosa() {
|
||||||
decrementar() {
|
return this.cantidad(this.producto.id);
|
||||||
this.cantidad -= 1;
|
|
||||||
},
|
|
||||||
incrementar() {
|
|
||||||
this.cantidad += 1;
|
|
||||||
},
|
|
||||||
confirmar() {
|
|
||||||
Event.$emit('sync-subpedido', this.cantidad, this.producto.id, this.notas);
|
|
||||||
},
|
|
||||||
borrar() {
|
|
||||||
this.cantidad = 0;
|
|
||||||
this.confirmar();
|
|
||||||
},
|
|
||||||
sincronizar(cantidad, notas) {
|
|
||||||
this.cantidad = cantidad;
|
|
||||||
this.producto.cantidad = cantidad;
|
|
||||||
this.enChismosa = cantidad;
|
|
||||||
this.notas = notas;
|
|
||||||
this.producto.notas = notas;
|
|
||||||
},
|
|
||||||
hayCambios() {
|
|
||||||
return this.cantidad !== this.enChismosa || this.notas !== this.producto.notas;
|
|
||||||
},
|
|
||||||
puedeBorrar() {
|
|
||||||
return this.enChismosa > 0;
|
|
||||||
},
|
},
|
||||||
|
conIconos() {
|
||||||
|
return this.producto.economia_solidaria || this.producto.nacional;
|
||||||
}
|
}
|
||||||
|
},
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="block column is-one-quarter-desktop is-full-mobile is-half-tablet min-width-from-desktop">
|
<div class="box is-flex is-flex-direction-column" style="height:100%">
|
||||||
<div class="box" style="height:100%">
|
<div class="columns is-mobile">
|
||||||
<div class="columns">
|
|
||||||
<div class="column">
|
<div class="column">
|
||||||
<p class="title is-6">
|
<p class="title is-6">
|
||||||
{{ producto.nombre }}
|
{{ producto.nombre }}
|
||||||
</p>
|
</p>
|
||||||
<p class="subtitle is-7" v-text="producto.proveedor"></p>
|
|
||||||
<span class="subtitle is-7 hidden-from-tablet" v-if="enChismosa !== 0">{{ enChismosa }} en chismosa</span>
|
|
||||||
</div>
|
</div>
|
||||||
<div class="column is-one-quarter has-text-right">
|
<div class="column is-one-quarter has-text-right">
|
||||||
<p class="has-text-weight-bold has-text-primary">
|
<p class="has-text-weight-bold has-text-primary block">
|
||||||
<span class="is-left-mobile">
|
${{ producto.precio }}
|
||||||
<img v-show="producto.economia_solidaria" height="30px" width="30px" src="/assets/solidaria.png" alt="proveedor de economía solidaria">
|
|
||||||
<img v-show="producto.nacional" height="30px" width="30px" src="/assets/uruguay.png" alt="proveedor nacional"/>
|
|
||||||
</span>
|
|
||||||
$<span v-text="producto.precio"></span>
|
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<footer class="columns">
|
<div class="columns mt-auto is-justify-content-left is-mobile">
|
||||||
<div class="column is-three-quarters">
|
<div v-if="conIconos" class="column has-text-left">
|
||||||
<pedidos-producto-cantidad :producto="producto"></pedidos-producto-cantidad>
|
<span>
|
||||||
|
<img v-show="producto.economia_solidaria" height="30px" width="30px" src="/assets/solidaria.png" alt="proveedor de economía solidaria">
|
||||||
|
<img v-show="producto.nacional" height="30px" width="30px" src="/assets/uruguay.png" alt="proveedor nacional"/>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<div class="column mt-auto"
|
||||||
|
:class="conIconos ? 'is-three-quarters-mobile is-two-thirds-tablet' : 'is-full'">
|
||||||
|
<producto-cantidad
|
||||||
|
:producto_id="producto.id"
|
||||||
|
:requiere_notas="producto.requiere_notas"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div class="column">
|
|
||||||
<p class="subtitle is-7 is-hidden-mobile" v-if="enChismosa > 0">{{ enChismosa }} en chismosa</p>
|
|
||||||
</div>
|
</div>
|
||||||
</footer>
|
|
||||||
</div><!-- END BOX -->
|
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Reference in a new issue