Compare commits

..

No commits in common. "e49c0432315679742edfe158c040561d7aa50855" and "db056e7d34071ba5c3a65db9dabff1b4f29a389a" have entirely different histories.

35 changed files with 140 additions and 661 deletions

View file

@ -12,7 +12,6 @@ use Illuminate\Support\Collection;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
use League\Csv\Exception;
use Mpdf\MpdfException;
class GrupoDeCompra extends Model
{
@ -38,14 +37,7 @@ class GrupoDeCompra extends Model
public function pedidosAprobados()
{
return $this->pedidosHogares()
->where('aprobado', 1);
}
public function pedidosHogares()
{
return $this->subpedidos
->where('tipo_pedido_id', '=', 1);
return $this->subpedidos->where('aprobado', 1);
}
public function totalARecaudar()
@ -128,15 +120,11 @@ class GrupoDeCompra extends Model
return TransporteHelper::cantidadTransporte($this->totalCentralesQuePaganTransporte());
}
/**
* @throws MpdfException
*/
public function exportarPedidosAPdf()
{
$subpedidos = $this->pedidosAprobados();
$fecha = now()->format('Y-m-d');
$filepath = $this->nombre . '-' . $fecha . '.pdf';
PdfHelper::exportarPedidos($filepath, $subpedidos);
PdfHelper::exportarPedidos($this->nombre . '-' . $fecha . '.pdf', $subpedidos);
}
function pedidoParaPdf(): array
@ -166,15 +154,11 @@ class GrupoDeCompra extends Model
return $view->render();
}
/**
* @throws MpdfException
*/
public static function exportarPedidosBarrialesAPdf()
{
$barrios = GrupoDeCompra::barriosMenosPruebaConPedidosAprobados()->get();
$barrios = GrupoDeCompra::barriosMenosPrueba()->get();
$fecha = now()->format('Y-m-d');
$filepath = 'pedidos_por_barrio-' . $fecha . '.pdf';
PdfHelper::exportarPedidos($filepath, $barrios);
PdfHelper::exportarPedidos('pedidos_por_barrio-' . $fecha . '.pdf', $barrios);
}
static function filaVacia(string $product, int $columns): array
@ -292,12 +276,9 @@ class GrupoDeCompra extends Model
return array($records, $i, $cantidad);
}
public static function barriosMenosPruebaConPedidosAprobados(): Builder
public static function barriosMenosPrueba(): Builder
{
return self::where('nombre', '<>', 'PRUEBA')
->whereHas('subpedidos', function ($query) {
$query->where('aprobado', true);
})
->orderBy('region')
->orderBy('nombre');
}
@ -305,7 +286,7 @@ class GrupoDeCompra extends Model
public static function transportePorBarrio(): array
{
$result = [];
$barrios = GrupoDeCompra::barriosMenosPruebaConPedidosAprobados()->get();
$barrios = GrupoDeCompra::barriosMenosPrueba()->get();
foreach ($barrios as $barrio) {
$result[] = $barrio->cantidadTransporte();

View file

@ -2,7 +2,6 @@
namespace App\Helpers;
use App\Http\Controllers\ComisionesController;
use Illuminate\Support\Facades\File;
use Illuminate\Support\Facades\Log;
use Iterator;
@ -14,13 +13,15 @@ use League\Csv\Writer;
class CsvHelper
{
/**
* @throws Exception
*/
public static function getRecords($filePath, $message): Iterator {
$csv = Reader::createFromPath($filePath);
try {
$csv = self::getReader($filePath);
$csv->setDelimiter("|");
$csv->setEnclosure("'");
$csv->setHeaderOffset(0);
return $csv->getRecords();
} catch (InvalidArgument|Exception $e) {
Log::error($e->getMessage());
@ -28,74 +29,20 @@ class CsvHelper
}
}
/**
* @throws Exception
*/
public static function cambiarParametro(string $id, string $valor): 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 {
$updated = false;
$filePath = resource_path(ComisionesController::PARAMETROS_PATH);
$csv = self::getReader($filePath);
$headers = $csv->getHeader();
$records = array_map(fn($r) => (array) $r, iterator_to_array($csv->getRecords()));
foreach ($records as &$record) {
if ($record['id'] === $id) {
$record['valor'] = $valor;
$updated = true;
break;
}
$writer = Writer::createFromPath(storage_path($filePath), 'w');
if ($headers) {
$writer->insertOne($headers);
}
unset($record);
if (!$updated)
throw new Exception("Parametro '{$id}' no encontrado.");
self::generarCsv($filePath, $records, $headers, "|", "'", false);
} catch (CannotInsertRecord | InvalidArgument $e) {
Log::error("Error al actualizar csv: " . $e->getMessage());
throw new Exception("Error al actualizar csv", $e);
$writer->insertAll($contenido);
} catch (CannotInsertRecord $e) {
Log::error($e->getMessage(), $e->getTrace());
}
}
/**
* @throws InvalidArgument
* @throws CannotInsertRecord
*/
public static function generarCsv($filePath, $contenido, $headers = null, $delimiter = null, $enclosure = null, $export = true): void
{
$path = $filePath;
if ($export) {
if (!File::exists(storage_path('csv/exports')))
File::makeDirectory(storage_path('csv/exports'), 0755, true);
$path = storage_path($filePath);
}
$writer = Writer::createFromPath($path, 'w');
if ($delimiter)
$writer->setDelimiter($delimiter);
if ($enclosure)
$writer->setEnclosure($enclosure);
if ($headers)
$writer->insertOne($headers);
$writer->insertAll($contenido);
}
/**
* @param string $filePath
* @return Reader
* @throws InvalidArgument
* @throws Exception
*/
private static function getReader(string $filePath): Reader
{
$csv = Reader::createFromPath($filePath);
$csv->setDelimiter("|");
$csv->setEnclosure("'");
$csv->setHeaderOffset(0);
return $csv;
}
}

View file

@ -4,7 +4,6 @@ namespace App\Http\Controllers;
use App\GrupoDeCompra;
use League\Csv\Exception;
use Mpdf\MpdfException;
class AdminController extends Controller
{
@ -18,12 +17,7 @@ class AdminController extends Controller
}
public function exportarPedidosAPdf(GrupoDeCompra $gdc) {
try {
$gdc->exportarPedidosAPdf();
return response();
} catch (MpdfException $e) {
return response()->json(['message' => $e->getMessage()], 500);
}
$gdc->exportarPedidosAPdf();
}
public function exportarPedidoACSV(GrupoDeCompra $gdc)

View file

@ -0,0 +1,21 @@
<?php
namespace App\Http\Controllers\Api;
use App\GrupoDeCompra;
use App\Http\Controllers\Controller;
use App\Http\Resources\SubpedidoResource;
use App\TipoPedido;
class OllasController extends Controller
{
public function pedido(GrupoDeCompra $gdc)
{
$tipoOlla = TipoPedido::firstOrCreate(['nombre' => 'olla']);
$pedido = $gdc->subpedidos()->firstOrCreate([
'nombre' => 'Pedido de Ollas de ' . $gdc->nombre,
'tipo_pedido_id' => $tipoOlla->id,
]);
return response()->json(new SubpedidoResource($pedido));
}
}

View file

@ -10,12 +10,10 @@ use App\Producto;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use League\Csv\Exception;
use Mpdf\MpdfException;
use Symfony\Component\HttpFoundation\BinaryFileResponse;
class ComisionesController
{
const PARAMETROS_PATH = 'csv/parametros.csv';
const CANASTAS_PATH = 'csv/canastas/';
const BARRIO = "Barrio";
const SALDO = "Saldo";
@ -56,12 +54,7 @@ class ComisionesController
}
public function pdf() {
try {
GrupoDeCompra::exportarPedidosBarrialesAPdf();
return response();
} catch (MpdfException $e) {
return response()->json(['message' => $e->getMessage()], 500);
}
GrupoDeCompra::exportarPedidosBarrialesAPdf();
}
public function cargarCanasta(Request $request): JsonResponse
@ -111,42 +104,4 @@ class ComisionesController
return response()->json(GrupoDeCompraResource::collection(GrupoDeCompra::all()));
}
public function obtenerParametros()
{
try {
$records = self::parametrosRecords();
$result = [];
foreach ($records as $record)
$result[] = $record;
return response()->json($result);
} catch (Exception $e) {
return response()->json(['message' => $e->getMessage()], 500);
}
}
public function modificarParametros(string $parametro_id, Request $request) {
try {
if (collect(self::parametrosRecords())
->contains('id', $parametro_id)) {
$valid = $request->validate([
'valor' => ['required', 'numeric', 'gte:0'],
]);
CsvHelper::cambiarParametro($parametro_id, $valid['valor']);
return response()->noContent();
}
return response()->json(['message' => 'Parametro no encontrado.'], 404);
} catch (Exception $e) {
return response()->json(['message' => $e->getMessage()], 500);
}
}
/**
* @throws Exception
*/
private static function parametrosRecords(): array
{
$records = CsvHelper::getRecords(resource_path(self::PARAMETROS_PATH), "No se pudo leer el archivo.");
return iterator_to_array($records);
}
}

View file

@ -2,38 +2,10 @@
namespace App\Http\Controllers;
use App\GrupoDeCompra;
use App\Http\Resources\PedidoOllasResource;
use App\TipoPedido;
use Illuminate\Http\Request;
class OllasController extends Controller
{
public function show()
{
return view('auth/login');
}
public function pedido(GrupoDeCompra $gdc)
{
$tipoOlla = TipoPedido::firstOrCreate(['nombre' => 'olla']);
$pedido = $gdc->subpedidos()->firstOrCreate([
'nombre' => 'Pedido de Ollas de ' . $gdc->nombre,
'tipo_pedido_id' => $tipoOlla->id,
]);
return response()->json(new PedidoOllasResource($pedido));
}
public function actualizarCantidadOllas(GrupoDeCompra $gdc, Request $request)
{
$valid = $request->validate([
'cantidad' => 'required|numeric|min:0',
]);
$pedido = $gdc->subpedidos()->where([
'nombre' => 'Pedido de Ollas de ' . $gdc->nombre
])->first();
$pedido->cantidad_ollas = $valid['cantidad'];
$pedido->save();
return response()->noContent();
}
}

View file

@ -19,7 +19,7 @@ class GrupoDeCompraResource extends JsonResource
'id' => $this->id,
'nombre' => $this->nombre,
'devoluciones_habilitadas' => $this->devoluciones_habilitadas,
'pedidos' => SubpedidoResource::collection($this->pedidosHogares()),
'pedidos' => SubpedidoResource::collection($this->subpedidos),
'total_a_recaudar' => number_format($this->totalARecaudar(),2),
'saldo' => number_format($this->saldo, 2, ".", ""),
'total_sin_devoluciones' => number_format($this->totalSinDevoluciones(),2),

View file

@ -1,30 +0,0 @@
<?php
namespace App\Http\Resources;
use App\TipoPedido;
use Illuminate\Http\Resources\Json\JsonResource;
class PedidoOllasResource extends JsonResource
{
/**
* Transform the resource into an array.
*
* @param \Illuminate\Http\Request $request
* @return 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 [
'id' => $this->id,
'nombre' => $this->nombre,
'productos' => $productos,
'total' => number_format($this->totalCentralesSinTransporte(),2),
'cantidad_de_ollas' => $this->cantidad_ollas,
];
}
}

View file

@ -11,9 +11,7 @@ use Illuminate\Database\Eloquent\Relations\BelongsToMany;
use Illuminate\Http\Request;
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\DB;
use League\Csv\CannotInsertRecord;
use League\Csv\Exception;
use League\Csv\InvalidArgument;
class Producto extends Model
{
@ -21,10 +19,15 @@ class Producto extends Model
public function subpedidos(): BelongsToMany
{
return $this->belongsToMany(Subpedido::class, 'productos_subpedidos')
->withPivot(["cantidad", "notas"]);
return $this->belongsToMany(Subpedido::class, 'productos_subpedidos')->withPivot(["cantidad", "notas"]);
}
public static function noBarriales()
{
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)
public function scopeFiltrar($query, FiltroDeProducto $filtros): Builder
{
return $filtros->aplicar($query);
@ -32,9 +35,7 @@ class Producto extends Model
public static function getPaginar(Request $request): int
{
return $request->has('paginar') && intval($request->input('paginar')) ?
intval($request->input('paginar')) :
self::all()->count();
return $request->has('paginar') && intval($request->input('paginar')) ? intval($request->input('paginar')) : self::all()->count();
}
public static function productosFilaID()
@ -52,30 +53,19 @@ class Producto extends Model
return self::noBarriales()->pluck('nombre', 'id')->all();
}
public static function noBarriales()
{
return self::where('nombre', 'not like', '%barrial%');
}
static public function cantidadesPorBarrio(): Collection
{
$barrios = GrupoDeCompra::barriosMenosPruebaConPedidosAprobados()->pluck('id', 'nombre');
$barrios = GrupoDeCompra::barriosMenosPrueba()
->pluck('id', 'nombre');
$columnasBarrios = $barrios->map(function ($id, $nombre) {
return DB::raw("
SUM(CASE WHEN subpedidos.grupo_de_compra_id = $id
AND subpedidos.aprobado = 1
AND subpedidos.tipo_pedido_id = 1
THEN producto_subpedido.cantidad
ELSE 0 END)
as `$nombre`");
return DB::raw("SUM(CASE WHEN subpedidos.grupo_de_compra_id = $id AND subpedidos.aprobado = 1 THEN producto_subpedido.cantidad ELSE 0 END) as `$nombre`");
})->toArray();
return DB::table('productos')
->where('productos.nombre', 'not like', '%barrial%')
->leftJoin('producto_subpedido', 'productos.id', '=', 'producto_subpedido.producto_id')
->leftJoin('subpedidos', 'subpedidos.id', '=', 'producto_subpedido.subpedido_id')
->where('subpedidos.tipo_pedido_id', '=', 1)
->select(array_merge(
['productos.fila as fila'],
['productos.nombre as producto'],
@ -92,7 +82,8 @@ class Producto extends Model
static public function planillaTotales()
{
$headers = ['Producto'];
$barrios = GrupoDeCompra::barriosMenosPruebaConPedidosAprobados()->pluck('nombre')->toArray();
$barrios = GrupoDeCompra::barriosMenosPrueba()
->pluck('nombre')->toArray();
$headers = array_merge($headers, $barrios);
$cantidadesPorBarrio = self::cantidadesPorBarrio();
@ -118,24 +109,21 @@ class Producto extends Model
$ultimaFila = $fila;
}
foreach ($transportePorBarrio as $cantidad) {
foreach ($transportePorBarrio as $key => $cantidad) {
$planilla[$filaTransporte][] = $cantidad;
}
$fecha = now()->format('Y-m-d');
$filePath = 'csv/exports/pedidos-por-barrio- ' . $fecha . '.csv';
CsvHelper::generarCsv($filePath, $planilla, $headers);
CsvHelper::generarCsv('csv/exports/pedidos-por-barrio- ' . $fecha . '.csv', $planilla, $headers);
}
public static function notasPorBarrio(): Collection
{
return DB::table('productos')
->where('productos.nombre', 'not like', '%barrial%')
->join('producto_subpedido', 'productos.id', '=', 'producto_subpedido.producto_id')
->join('subpedidos', 'producto_subpedido.subpedido_id', '=', 'subpedidos.id')
->join('grupos_de_compra', 'subpedidos.grupo_de_compra_id', '=', 'grupos_de_compra.id')
->where('productos.requiere_notas', 1)
->where('subpedidos.tipo_pedido_id', '=', 1)
->select(
'productos.nombre as producto',
'grupos_de_compra.nombre as barrio',
@ -145,13 +133,9 @@ class Producto extends Model
->groupBy('producto');
}
/**
* @throws InvalidArgument
* @throws CannotInsertRecord
*/
static public function planillaNotas() {
$headers = ['Producto'];
$barrios = GrupoDeCompra::barriosMenosPruebaConPedidosAprobados()
$barrios = GrupoDeCompra::barriosMenosPrueba()
->pluck('nombre')->toArray();
$headers = array_merge($headers, $barrios);
@ -161,16 +145,13 @@ class Producto extends Model
foreach ($notasPorBarrio as $producto => $notasGrupo) {
$fila = [$producto];
foreach ($barrios as $barrio) {
$notas = $notasGrupo->where('barrio', $barrio)
->pluck('notas')
->implode('; ');
$notas = $notasGrupo->where('barrio', $barrio)->pluck('notas')->implode('; ');
$fila[] = $notas ?: '';
}
$planilla[] = $fila;
}
$fecha = now()->format('Y-m-d');
$filePath = 'csv/exports/notas-por-barrio-' . $fecha . '.csv';
CsvHelper::generarCsv($filePath, $planilla, $headers);
CsvHelper::generarCsv('csv/exports/notas-por-barrio-' . $fecha . '.csv', $planilla, $headers);
}
}

View file

@ -12,15 +12,7 @@ use App\Filtros\FiltroDeSubpedido;
class Subpedido extends Model
{
protected $fillable = [
'grupo_de_compra_id',
'aprobado',
'nombre',
'devoluciones_total',
'devoluciones_notas',
'tipo_pedido_id',
'cantidad_ollas'
];
protected $fillable = ['grupo_de_compra_id', 'aprobado', 'nombre', 'devoluciones_total', 'devoluciones_notas', 'tipo_pedido_id'];
public function productos(): BelongsToMany
{
@ -65,11 +57,7 @@ class Subpedido extends Model
public function totalCentral()
{
return $this->totalCentralesSinTransporte() + $this->totalTransporte();
}
public function totalCentralesSinTransporte() {
return $this->totalCentralesQueNoPaganTransporte() + $this->totalCentralesQuePaganTransporte();
return $this->totalCentralesQueNoPaganTransporte() + $this->totalCentralesQuePaganTransporte() + $this->totalTransporte();
}
public function totalCentralesQueNoPaganTransporte()

View file

@ -1,34 +0,0 @@
<?php
use App\Subpedido;
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class CantidadOllasPedidos extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::table('subpedidos', function (Blueprint $table) {
$table->integer('cantidad_ollas')->nullable();
});
Subpedido::where('tipo_pedido_id', 1)->update(['cantidad_ollas' => 0]);
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::table('subpedidos', function (Blueprint $table) {
$table->dropColumn('cantidad_ollas');
});
}
}

0
resources/csv/exports/.gitignore vendored Normal file
View file

View file

@ -1,3 +0,0 @@
id|nombre|valor
bono-transporte|'Bono de transporte'|15
monto-olla|'Monto por olla'|1200
1 id nombre valor
2 bono-transporte 'Bono de transporte' 15
3 monto-olla 'Monto por olla' 1200

View file

@ -1,8 +1,10 @@
<script>
import { mapGetters, mapMutations, mapState } from "vuex";
import Burger from "../comunes/Burger.vue";
export default {
name: "AdminNavBarBrand",
name: "AdminNavBar",
components: { Burger },
computed: {
...mapState('ui', ["burger_activa"]),
...mapGetters('admin', ["barrio"])
@ -18,6 +20,7 @@ export default {
<p>
{{`Barrio: ${barrio}`}}
</p>
<burger/>
</div>
</template>

View file

@ -18,11 +18,6 @@
:class="seccionActiva === 'saldos-comisiones-seccion' ? 'is-active' : 'is-hidden'">
<saldos-seccion/>
</div>
<div class="block pb-6"
id="parametros-comisiones-seccion"
:class="seccionActiva === 'parametros-comisiones-seccion' ? 'is-active' : 'is-hidden'">
<parametros-seccion/>
</div>
</div>
</template>
@ -32,12 +27,11 @@ import DropdownDescargar from "./DropdownDescargar.vue";
import InputFileButton from "../comunes/InputFileButton.vue";
import CanastaSeccion from "./canasta/CanastaSeccion.vue";
import SaldosSeccion from "./saldos/SaldosSeccion.vue";
import ParametrosSeccion from "./parametros/ParametrosSeccion.vue";
import { mapActions } from "vuex";
export default {
name: "ComisionesBody",
components: {
ParametrosSeccion,
SaldosSeccion,
CanastaSeccion,
TabsSecciones,
@ -50,7 +44,6 @@ export default {
{ id: "pedidos-comisiones", nombre: "Pedidos" },
{ id: "canasta-comisiones", nombre: "Canasta" },
{ id: "saldos-comisiones", nombre: "Saldos" },
{ id: "parametros-comisiones", nombre: "Parámetros" },
],
tabActiva: "pedidos-comisiones",
seccionActiva: "pedidos-comisiones-seccion",

View file

@ -1,8 +1,10 @@
<script>
import { mapMutations, mapState } from "vuex";
import Burger from "../comunes/Burger.vue";
export default {
name: "ComisionesNavBarBrand",
name: "ComisionesNavBar",
components: { Burger },
computed: {
...mapState('ui', ["burger_activa"])
},
@ -24,6 +26,7 @@ export default {
<template>
<div class="navbar-item hide-below-1024">
<p>{{ nombre }}</p>
<burger/>
</div>
</template>

View file

@ -1,71 +0,0 @@
<script>
import {mapActions, mapGetters} from "vuex";
export default {
props: {
parametro: {
type: Object,
required: true,
}
},
data() {
return {
control: this.parametro.valor,
};
},
computed: {
hayCambios() {
return this.control !== this.parametro.valor;
}
},
methods: {
...mapActions("comisiones", ["cambiarParametro"]),
modificar() {
this.cambiarParametro({
parametro_id: this.parametro.id,
valor: this.control,
});
}
}
}
</script>
<template>
<tr>
<td>{{ parametro.nombre }}</td>
<td>
<div class="field">
<input :type="parametro.tipo"
:id="'input-' + parametro.id"
v-model="control"
class="has-text-right">
</div>
</td>
<td class="has-text-centered">
<div class="control">
<button class="button is-small is-success"
@click="modificar"
:disabled="!hayCambios">
<span class="icon">
<i class="fas fa-check"></i>
</span>
</button>
</div>
</td>
<td class="has-text-centered">
<div class="control">
<button class="button is-small is-danger"
@click="control = parametro.valor"
:disabled="!hayCambios">
<span class="icon">
<i class="fa fa-undo" aria-hidden="true"></i>
</span>
</button>
</div>
</td>
</tr>
</template>
<style scoped>
</style>

View file

@ -1,41 +0,0 @@
<script>
import FilaCaracteristica from "../../admin/FilaCaracteristica.vue";
import FilaParametro from "./FilaParametro.vue";
import { mapActions, mapState } from "vuex";
export default {
name:"ParametrosSeccion",
components: { FilaParametro, FilaCaracteristica },
methods: {
...mapActions("comisiones", ["getParametros"]),
},
computed: {
...mapState("comisiones", ["parametros"]),
},
async mounted() {
await this.getParametros();
},
}
</script>
<template>
<table class="table is-striped is-bordered">
<thead>
<tr>
<th> Parámetro </th>
<th> Valor $ </th>
<th> Cambiar </th>
<th> Deshacer </th>
</tr>
</thead>
<tbody>
<fila-parametro v-for="(p,i) in parametros"
:key="i"
:parametro="p"/>
</tbody>
</table>
</template>
<style scoped>
</style>

View file

@ -7,20 +7,13 @@
<a class="navbar-item" href="https://mps.org.uy">
<img src="/assets/logoMPS.png" height="28" alt="Logo del MPS">
</a>
<pedidos-nav-bar-brand v-if="rol === 'barrio'"/>
<ollas-nav-bar-brand v-else-if="rol === 'ollas'"/>
<admin-nav-bar-brand v-else-if="rol === 'admin_barrio'"/>
<comisiones-nav-bar-brand v-else/>
<burger/>
<pedidos-nav-bar v-if="rol === 'barrio'"/>
<ollas-nav-bar v-else-if="rol === 'ollas'"/>
<admin-nav-bar v-else-if="rol === 'admin_barrio'"/>
<comisiones-nav-bar v-else/>
</div>
<div class="navbar-menu" :class="{'is-active': burger_activa}">
<div class="navbar-start is-flex is-justify-content-center is-flex-grow-1">
<div v-if="mostrarAviso" class="is-absolute-center is-flex is-align-items-center navbar-item">
<span class="tag is-warning is-size-6">
Monto superado
</span>
</div>
</div>
<div class="navbar-menu"
:class="{'is-active': burger_activa}">
<div class="navbar-end">
<buscador v-if="pedidoDefinido"/>
<chismosa-dropdown v-if="pedidoDefinido"
@ -39,23 +32,18 @@
<script>
import ChismosaDropdown from '../pedidos/ChismosaDropdown.vue';
import { mapGetters, mapState } from "vuex";
import PedidosNavBarBrand from "../pedidos/PedidosNavBarBrand.vue";
import ComisionesNavBarBrand from "../comisiones/ComisionesNavBarBrand.vue";
import AdminNavBarBrand from "../admin/AdminNavBarBrand.vue";
import OllasNavBarBrand from "../ollas/OllasNavBarBrand.vue";
import PedidosNavBar from "../pedidos/PedidosNavBar.vue";
import ComisionesNavBar from "../comisiones/ComisionesNavBar.vue";
import AdminNavBar from "../admin/AdminNavBar.vue";
import OllasNavBar from "../ollas/OllasNavBar.vue";
import Buscador from "../pedidos/Buscador.vue";
import Burger from "./Burger.vue";
export default {
components: { Burger, Buscador, OllasNavBarBrand, AdminNavBarBrand, ComisionesNavBarBrand, PedidosNavBarBrand, ChismosaDropdown },
components: { Buscador, OllasNavBar, AdminNavBar, ComisionesNavBar, PedidosNavBar, ChismosaDropdown },
computed: {
...mapGetters('pedido', ["pedidoDefinido"]),
...mapGetters('ollas', ["montoSuperado"]),
...mapState('login', ["rol"]),
...mapState('ui', ["burger_activa"]),
mostrarAviso() {
return this.pedidoDefinido && this.rol === 'ollas' && this.montoSuperado;
}
...mapState('ui', ["burger_activa"])
},
methods: {
logOut() {
@ -67,9 +55,4 @@ export default {
</script>
<style>
.is-absolute-center {
position: absolute;
left: 50%;
transform: translateX(-50%);
}
</style>

View file

@ -1,71 +0,0 @@
<script>
import { mapActions, mapMutations, mapState } from "vuex";
export default {
name: "CantidadOllas",
methods: {
...mapActions("ollas", ["actualizarCantidadOllas"]),
...mapMutations("pedido", ["setCantidadOllas"]),
incrementar() {
this.control += 1;
this.actualizarDebounced();
},
decrementar() {
this.control -= 1;
this.actualizarDebounced();
},
async actualizarDebounced() {
const params = { cantidad: this.control };
clearTimeout(this.debounceTimer);
this.debounceTimer = setTimeout(() => {
this.setCantidadOllas(params);
this.actualizarCantidadOllas(params);
}, 500);
}
},
computed: {
...mapState("pedido", ["cantidad_de_ollas"])
},
data() {
return {
debounceTimer: null,
control: 0,
};
},
watch: {
cantidad_de_ollas() {
this.control = this.cantidad_de_ollas;
}
},
}
</script>
<template>
<div class="notification has-text-centered">
<label class="label">Cantidad de ollas:</label>
<div class="field has-addons is-justify-content-center contador">
<div class="control">
<button class="button is-small"
:disabled="control < 1"
@click.capture="decrementar">
<i class="fa fa-solid fa-minus"></i>
</button>
</div>
<div class="control">
<input id="cantidad"
v-model="control"
class="input is-small has-text-centered"
type="number"
@input="actualizarDebounced">
</div>
<div class="control">
<button class="button is-small" @click="incrementar">
<i class="fa fa-solid fa-plus"></i>
</button>
</div>
</div>
</div>
</template>
<style scoped>
</style>

View file

@ -1,11 +1,10 @@
<script>
import PedidosMain from "../pedidos/PedidosMain.vue";
import { mapActions, mapMutations } from "vuex";
import CantidadOllas from "./CantidadOllas.vue";
export default {
name: "OllasBody",
components: { CantidadOllas, PedidosMain },
components: { PedidosMain },
methods: {
...mapActions('pedido', ["getPedidoDeOllas", "getGrupoDeCompra"]),
...mapMutations('ui', ["migasOllas"])
@ -20,11 +19,7 @@ export default {
<template>
<div id="ollas-body" class="pb-6 mb-6">
<pedidos-main>
<template v-slot:cartel>
<cantidad-ollas/>
</template>
</pedidos-main>
<pedidos-main></pedidos-main>
</div>
</template>

View file

@ -1,33 +1,30 @@
<script>
import { mapActions, mapGetters, mapMutations, mapState } from "vuex";
import { mapGetters, mapMutations, mapState } from "vuex";
import Burger from "../comunes/Burger.vue";
import ChismosaDropdown from "../pedidos/ChismosaDropdown.vue";
export default {
name: "OllasNavBarBrand",
components: { ChismosaDropdown },
name: "OllasNavBar",
components: { Burger, ChismosaDropdown },
computed: {
...mapGetters('pedido', ["pedidoDefinido"]),
...mapGetters('ollas', ["montoTotal"]),
...mapState('ui', ["burger_activa"]),
...mapState('pedido', ["nombre"]),
...mapState('ui', ["burger_activa"])
},
methods: {
...mapActions('ollas', ["getMontoPorOlla"]),
...mapMutations('ui', ["toggleBurger"]),
},
async mounted() {
await this.getMontoPorOlla();
}
}
</script>
<template>
<div class="navbar-item hide-below-1024">
<p v-if="pedidoDefinido">{{ `${nombre} - Monto total: ${montoTotal}` }}</p>
<p v-if="pedidoDefinido">{{ nombre }}</p>
<chismosa-dropdown
v-if="pedidoDefinido"
class="hide-above-1023"
ariaControls="mobile"/>
<burger/>
</div>
</template>

View file

@ -1,11 +1,7 @@
<template>
<div id="pedidos-body" class="pb-6 mb-6">
<pedido-select v-if="!pedidoDefinido"/>
<pedidos-main v-else>
<template v-slot:cartel>
<cartel-pedido-aprobado/>
</template>
</pedidos-main>
<pedidos-main v-else/>
</div>
</template>
@ -13,11 +9,10 @@
import { mapGetters } from "vuex";
import PedidoSelect from "./PedidoSelect.vue";
import PedidosMain from "./PedidosMain.vue";
import CartelPedidoAprobado from "./CartelPedidoAprobado.vue";
export default {
name: "PedidosBody",
components: { CartelPedidoAprobado, PedidosMain, PedidoSelect },
components: { PedidosMain, PedidoSelect },
computed: {
...mapGetters('pedido', ["pedidoDefinido"]),
},

View file

@ -25,9 +25,9 @@ export default {
<template>
<div class="navbar-item field has-addons mt-1 mr-3 mb-1">
<a class="button is-small has-text-dark-grey" @click.capture="buscar">
<span class="icon">
<i class="fas fa-search"></i>
</span>
<span class="icon">
<i class="fas fa-search"></i>
</span>
</a>
<input class="input is-small"
type="text"

View file

@ -2,10 +2,10 @@
<div class="dropdown is-right navbar-item" :class="{'is-active': show_chismosa}">
<div class="dropdown-trigger">
<a class="text-a" aria-haspopup="true" :aria-controls="ariaControls" @click.capture="toggleChismosa">
<span class="icon is-small mr-1">
<img src="/assets/chismosa.png">
</span>
<span v-text="'$' + total"/>
<span class="icon is-small mr-1">
<img src="/assets/chismosa.png">
</span>
<span v-text="'$' + total"></span>
</a>
</div>
</div>

View file

@ -1,6 +1,6 @@
<template>
<nav class="breadcrumb is-centered has-background-danger-light is-fixed-top"
aria-label="breadcrumbs">
aria-label="breadcrumbs" v-show="visible">
<ul class="mt-4">
<li v-for="(miga, i) in migas" :key="i" :class="{'is-active': i === migaActiva}">
<a @click="clickMiga({ miga: miga })"
@ -17,11 +17,15 @@ import { mapActions, mapMutations, mapState } from "vuex";
export default {
methods: {
...mapActions('productos', ["getProductos"]),
...mapActions('ui', ["clickMiga"]),
...mapMutations('ui', ["addMiga"]),
},
computed: {
...mapState('ui', ["migas"]),
visible() {
return this.migas.length > 0;
},
migaActiva() {
return this.migas.length - 1;
},

View file

@ -2,12 +2,13 @@
import { defineComponent } from "vue";
import Canasta from "./Canasta.vue";
import Chismosa from "./Chismosa.vue";
import CartelPedidoAprobado from "./CartelPedidoAprobado.vue";
import NavMigas from "./NavMigas.vue";
import { mapActions, mapState } from "vuex";
export default defineComponent({
name: "PedidosMain",
components: { NavMigas, Chismosa, Canasta },
components: { NavMigas, CartelPedidoAprobado, Chismosa, Canasta },
computed: {
...mapState('ui', ["show_chismosa"]),
},
@ -25,7 +26,7 @@ export default defineComponent({
<nav-migas/>
<div class="columns">
<div class="column" :class="{ 'is-two-thirds-desktop is-hidden-touch': show_chismosa }">
<slot name="cartel"></slot>
<cartel-pedido-aprobado/>
<canasta/>
</div>
<div class="column is-full-touch" v-if="show_chismosa">

View file

@ -1,10 +1,11 @@
<script>
import { mapGetters, mapMutations, mapState } from "vuex";
import ChismosaDropdown from "./ChismosaDropdown.vue";
import Burger from "../comunes/Burger.vue";
export default {
name: "PedidosNavBarBrand",
components: { ChismosaDropdown },
name: "PedidosNavBar",
components: { Burger, ChismosaDropdown },
computed: {
...mapGetters('pedido', ["pedidoDefinido"]),
...mapState('pedido', ["nombre", "grupo_de_compra"]),
@ -25,6 +26,7 @@ export default {
v-if="pedidoDefinido"
class="hide-above-1023"
ariaControls="mobile"/>
<burger/>
</div>
</template>

View file

@ -6,7 +6,6 @@ import login from "./modules/login";
import pedido from "./modules/pedido";
import productos from "./modules/productos";
import ui from "./modules/ui";
import ollas from "./modules/ollas";
Vue.use(Vuex);
@ -18,6 +17,5 @@ export default new Vuex.Store({
pedido,
productos,
ui,
ollas,
},
});

View file

@ -3,7 +3,6 @@ import axios from "axios";
const state = {
lastFetch: undefined,
grupos_de_compra: [],
parametros: [],
};
const mutations = {
@ -11,15 +10,6 @@ const mutations = {
state.grupos_de_compra = data;
state.lastFetch = new Date();
},
setParametros(state, parametros) {
state.parametros = parametros;
state.parametros.forEach(
p => p.valor = Number.parseInt(p.valor)
);
},
actualizarParametro(state, { parametro_id, valor }) {
state.parametros.find(p => p.id === parametro_id).valor = valor;
},
setSaldo(state, { gdc_id, saldo }) {
const barrio = state.grupos_de_compra.find(gdc => gdc.id === gdc_id);
const i = state.grupos_de_compra.indexOf(barrio);
@ -32,22 +22,6 @@ const actions = {
const response = await axios.get('/api/grupos-de-compra/saldos');
commit('setGruposDeCompra', response.data);
},
async getParametros({ commit }) {
const response = await axios.get('/api/parametros');
commit('setParametros', response.data);
},
async cambiarParametro({ commit, dispatch }, { parametro_id, valor }) {
try {
await axios.put(
`/comisiones/parametros/${parametro_id}`,
{ valor: valor }
);
commit('actualizarParametro', { parametro_id, valor });
dispatch("ui/toast", { mensaje: 'Parámetro modificado con éxito' }, { root: true });
} catch (error) {
dispatch("ui/error", { error: error }, { root: true });
}
},
async setSaldo({ commit, dispatch }, { gdc_id, saldo }) {
try {
await axios.post(

View file

@ -103,7 +103,7 @@ const getters = {
};
case 'comisiones':
return {
fondo: "",
fondo: "has-background-grey-light",
texto: "",
botones: "is-dark"
};

View file

@ -1,40 +0,0 @@
import axios from "axios";
const state = {
monto_por_olla: undefined,
};
const mutations = {
setMontoPorOlla(state, parametros) {
state.monto_por_olla = Number.parseInt(parametros.find(p => p.id === 'monto-olla').valor);
},
};
const actions = {
async getMontoPorOlla({ commit }) {
const response = await axios.get('/api/parametros');
commit('setMontoPorOlla', response.data);
},
async actualizarCantidadOllas({ rootState }, { cantidad: cantidad}) {
const barrio = rootState.pedido.grupo_de_compra.id;
const params = { cantidad : cantidad };
await axios.put(`/ollas/${barrio}/cantidad`, params);
}
};
const getters = {
montoTotal(state, _, rootState) {
return state.monto_por_olla * rootState.pedido.cantidad_de_ollas;
},
montoSuperado: (_, getters, rootState) => {
return rootState.pedido.total > getters.montoTotal;
}
};
export default {
namespaced: true,
state,
mutations,
actions,
getters,
};

View file

@ -3,17 +3,16 @@ import axios from "axios";
const state = {
lastFetch: null,
grupo_de_compra: null,
pedido_id: 0,
nombre: "",
productos: [],
aprobado: false,
total: 0,
total_transporte: 0,
cantidad_transporte: 0,
total_sin_devoluciones: 0,
devoluciones_total: 0,
devoluciones_notas: "",
cantidad_de_ollas: 0,
pedido_id: null,
nombre: null,
productos: null,
aprobado: null,
total: null,
total_transporte: null,
cantidad_transporte: null,
total_sin_devoluciones: null,
devoluciones_total: null,
devoluciones_notas: null,
};
const mutations = {
@ -26,27 +25,13 @@ const mutations = {
state.nombre = pedido.nombre;
state.productos = pedido.productos;
state.aprobado = pedido.aprobado;
state.total = Number.parseFloat(pedido.total.replace(',',''));
state.total_transporte = Number.parseInt(pedido.total_transporte?.replace(',',''));
state.cantidad_transporte = Number.parseInt(pedido.cantidad_transporte?.replace(',',''));
state.total_sin_devoluciones = Number.parseFloat(pedido.total_sin_devoluciones?.replace(',',''));
state.devoluciones_total = Number.parseFloat(pedido.devoluciones_total?.replace(',',''));
state.total = pedido.total;
state.total_transporte = pedido.total_transporte;
state.cantidad_transporte = pedido.cantidad_transporte;
state.total_sin_devoluciones = pedido.total_sin_devoluciones;
state.devoluciones_total = pedido.devoluciones_total;
state.devoluciones_notas = pedido.devoluciones_notas;
},
setPedidoDeOllas(state, pedido) {
state.lastFetch = new Date();
state.pedido_id = pedido.id;
state.nombre = pedido.nombre;
state.productos = pedido.productos;
state.total = Number.parseFloat(pedido.total.replace(',',''));
state.cantidad_de_ollas = Number.parseInt(pedido.cantidad_de_ollas);
delete state.aprobado;
delete state.total_transporte;
delete state.cantidad_transporte;
delete state.total_sin_devoluciones;
delete state.devoluciones_total;
delete state.devoluciones_notas;
},
reset(state) {
state.lastFetch = null;
state.pedido_id = null;
@ -59,9 +44,6 @@ const mutations = {
state.total_sin_devoluciones = null;
state.devoluciones_total = null;
state.devoluciones_notas = null;
},
setCantidadOllas(state, { cantidad }) {
state.cantidad_de_ollas = cantidad;
}
};
@ -113,8 +95,9 @@ const actions = {
commit('reset');
},
async getPedidoDeOllas({ commit }) {
const response = await axios.get(`/ollas/${state.grupo_de_compra.id}`);
commit('setPedidoDeOllas', response.data);
const response = await axios.get(`/api/ollas/${state.grupo_de_compra.id}`);
console.log(response);
commit('setPedido', response.data);
},
};

View file

@ -49,5 +49,7 @@ Route::middleware('api')->group(function() {
Route::get('/','Api\ProductoController@index');
});
Route::get('/parametros', 'ComisionesController@obtenerParametros');
Route::prefix('ollas')->group(function() {
Route::get('/{gdc}','Api\OllasController@pedido');
});
});

View file

@ -56,13 +56,10 @@ Route::middleware(['auth', 'role:comision'])->group( function() {
Route::get('/comisiones/canasta/ejemplo', 'ComisionesController@descargarCanastaEjemplo')->name('comisiones.canasta.ejemplo');
Route::post('/comisiones/canasta', 'ComisionesController@cargarCanasta')->name('comisiones.canasta');
Route::post('/comisiones/saldos', 'ComisionesController@cargarSaldos')->name('comisiones.saldos');
Route::put('/comisiones/parametros/{parametro_id}', 'ComisionesController@modificarParametros');
});
Route::get('/ollas/login', 'OllasController@show')->name('ollas.login');
Route::middleware(['auth', 'role:ollas'])->prefix('ollas')->group( function() {
Route::get('/', 'RouteController@main')->name('ollas');
Route::get('/{gdc}','OllasController@pedido');
Route::put('/{gdc}/cantidad','OllasController@actualizarCantidadOllas');
Route::middleware(['auth', 'role:ollas'])->group( function() {
Route::get('/ollas', 'RouteController@main')->name('ollas');
});