diff --git a/app/Filtros/Filtro.php b/app/Filtros/Filtro.php index 737f27b..b78e038 100644 --- a/app/Filtros/Filtro.php +++ b/app/Filtros/Filtro.php @@ -46,17 +46,24 @@ class Filtro extends Model //Obtener nombre del método (snake_case a camelCase) $metodo = str_replace('_', '', lcfirst(ucwords($filtro, '_'))); - if(!method_exists($this, $metodo)) { continue; } + if (!method_exists($this, $metodo)) + continue; //Llamar métodos sin argumentos - if ($valor === null|| (is_a($valor,'String') && trim($valor)=='')){ $this->$metodo(); continue; } + if ($valor === null || (is_a($valor,'String') && trim($valor)=='')) { + $this->$metodo(); + continue; + } //Llamar métodos con argumentos try { $this->$metodo($valor); - } catch (Throwable $th) { - if (is_a($th,'TypeError') ) { throw new HttpException(400, sprintf($this->MENSAJES_ERROR['ARGUMENTO'],$filtro)); } - throw $th; + } catch (Throwable $error) { + if (is_a($error,'TypeError')) { + $mensaje = sprintf($this->MENSAJES_ERROR['ARGUMENTO'], $filtro); + throw new HttpException(400, $mensaje); + } + throw $error; } } @@ -66,12 +73,16 @@ class Filtro extends Model //Buscar un término en el nombre public function nombre(String $valor) { - $this->builder->where('nombre', "LIKE", "%" . $valor . "%")->orderByRaw("IF(nombre = '$valor',2,IF(nombre LIKE '$valor%',1,0)) DESC"); + $this->builder + ->where('nombre', "LIKE", "%" . $valor . "%") + ->orderByRaw("IF(nombre = '$valor',2,IF(nombre LIKE '$valor%',1,0)) DESC"); } public function alfabetico(String $order = 'asc') { - if(!in_array($order,['asc','desc'])) { throw new TypeError(); } + if (!in_array($order,['asc','desc'])) + throw new TypeError(); + $this->builder->orderBy('nombre', $order); } } diff --git a/app/Filtros/FiltroDeSubpedido.php b/app/Filtros/FiltroDeSubpedido.php index c889860..fafdbdc 100644 --- a/app/Filtros/FiltroDeSubpedido.php +++ b/app/Filtros/FiltroDeSubpedido.php @@ -8,7 +8,17 @@ class FiltroDeSubpedido extends Filtro { public function grupoDeCompra(String $valor) { - if (!is_numeric($valor)) { throw new TypeError();} + if (!is_numeric($valor)) + throw new TypeError(); + $this->builder->where('grupo_de_compra_id', intval($valor)); } + + public function tipoPedido(String $valor) + { + if (!is_numeric($valor)) + throw new TypeError(); + + $this->builder->where('tipo_pedido_id', intval($valor)); + } } diff --git a/app/GrupoDeCompra.php b/app/GrupoDeCompra.php index 782d16c..75c693a 100644 --- a/app/GrupoDeCompra.php +++ b/app/GrupoDeCompra.php @@ -12,6 +12,7 @@ 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 { @@ -23,6 +24,11 @@ class GrupoDeCompra extends Model return $this->hasMany(Subpedido::class); } + public function users(): HasMany + { + return $this->hasMany(User::class); + } + public function toggleDevoluciones(): bool { $this->devoluciones_habilitadas = !$this->devoluciones_habilitadas; @@ -32,7 +38,14 @@ class GrupoDeCompra extends Model public function pedidosAprobados() { - return $this->subpedidos->where('aprobado', 1); + return $this->pedidosHogares() + ->where('aprobado', 1); + } + + public function pedidosHogares() + { + return $this->subpedidos + ->where('tipo_pedido_id', '=', 1); } public function totalARecaudar() @@ -115,11 +128,15 @@ class GrupoDeCompra extends Model return TransporteHelper::cantidadTransporte($this->totalCentralesQuePaganTransporte()); } + /** + * @throws MpdfException + */ public function exportarPedidosAPdf() { $subpedidos = $this->pedidosAprobados(); $fecha = now()->format('Y-m-d'); - PdfHelper::exportarPedidos($this->nombre . '-' . $fecha . '.pdf', $subpedidos); + $filepath = $this->nombre . '-' . $fecha . '.pdf'; + PdfHelper::exportarPedidos($filepath, $subpedidos); } function pedidoParaPdf(): array @@ -149,126 +166,15 @@ class GrupoDeCompra extends Model return $view->render(); } + /** + * @throws MpdfException + */ public static function exportarPedidosBarrialesAPdf() { $barrios = GrupoDeCompra::barriosMenosPrueba()->get(); $fecha = now()->format('Y-m-d'); - PdfHelper::exportarPedidos('pedidos_por_barrio-' . $fecha . '.pdf', $barrios); - } - - static function filaVacia(string $product, int $columns): array - { - $fila = [$product]; - for ($i = 1; $i <= $columns; $i++) { - $fila[$i] = "0"; - } - return $fila; - } - - //Asume que los productos están gruadados en orden de fila - - /** - * @throws Exception - */ - public static function obtenerTemplateDeFilasVacias(int $columns): array - { - $productosFilaID = Producto::productosFilaID(); - $productosIDNombre = Producto::productosIDNombre(); - $num_fila = 1; - $template = []; - foreach ($productosFilaID as $fila => $id) { - for ($i = $num_fila; $i < $fila; $i++) { - $template[$i] = GrupoDeCompra::filaVacia("", $columns); - } - $template[$fila] = GrupoDeCompra::filaVacia($productosIDNombre[$id], $columns); - $num_fila = $fila + 1; - } - $template[TransporteHelper::filaTransporte()] = GrupoDeCompra::filaVacia("Bonos de transporte", $columns); - return $template; - } - - /** - * @throws Exception - */ - public function exportarPedidoEnCSV() - { - $records = $this->generarColumnaCantidades(); - - $fecha = now()->format('Y-m-d'); - CsvHelper::generarCsv('csv/exports/' . $this->nombre . '-' . $fecha . '.csv', $records); - } - - /** - * @throws Exception - */ - public function generarColumnaCantidades(): array - { - $productos_en_pedido = $this->productosPedidos(); - - //si no hay pedidos aprobados, salir - if ($productos_en_pedido->count() == 0) { - Log::debug("El grupo de compra " . $this->nombre . " no tiene pedidos aprobados."); - return []; - } - - $records = $this->obtenerTemplateDeFilasVacias(1); - $productos_id_fila = Producto::productosIDFila(); - foreach ($productos_en_pedido as $id => $producto_pedido) { - $fila = $productos_id_fila[$id]; - $records[$fila][1] = $producto_pedido->cantidad_pedida; - } - - $records[TransporteHelper::filaTransporte()][1] = $this->cantidadTransporte(); - - return $records; - } - - /** - * @throws Exception - */ - public function exportarPedidoConNucleosEnCSV() - { - $productos_en_pedido = $this->productosPedidos(); - - // si no hay pedidos aprobados, salir - if ($productos_en_pedido->count() == 0) { - Log::debug("El grupo de compra " . $this->nombre . " no tiene pedidos aprobados."); - return; - } - - $pedidos = $this->pedidosAprobados(); - // Generar tabla vacía con una columna por núcleo - $records = $this->obtenerTemplateDeFilasVacias($pedidos->count()); - $productos_id_fila = Producto::productosIDFila(); - - foreach ($productos_en_pedido as $id => $producto_pedido) { - $fila = $productos_id_fila[$id]; - $i = 1; - // Poner cantidad de cada producto para cada núcleo - foreach ($pedidos as $pedido) { - list($records, $i, $_) = $this->agregarCantidad($pedido, $id, $records, $fila, $i); - } - } - // Insertar lista de núcleos en la primera fila - $nucleos = [""]; - $i = 1; - foreach ($pedidos as $pedido) { - $nucleos[$i] = $pedido->nombre; - $i++; - } - array_splice($records, 0, 0, array($nucleos)); - - $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 - { - $producto = $pedido->productos()->find($id); - $cantidad = $producto == NULL ? 0 : $producto->pivot->cantidad; - $records[$fila][$i] = $cantidad; - $i++; - return array($records, $i, $cantidad); + $filepath = 'pedidos_por_barrio-' . $fecha . '.pdf'; + PdfHelper::exportarPedidos($filepath, $barrios); } public static function barriosMenosPrueba(): Builder @@ -278,18 +184,6 @@ class GrupoDeCompra extends Model ->orderBy('nombre'); } - public static function transportePorBarrio(): array - { - $result = []; - $barrios = GrupoDeCompra::barriosMenosPrueba()->get(); - - foreach ($barrios as $barrio) { - $result[] = $barrio->cantidadTransporte(); - } - - return $result; - } - public function productosPedidos($excluirBonos = false, $orderBy = 'producto_nombre'): Collection { $query = DB::table('pedidos_aprobados') diff --git a/app/Helpers/CsvHelper.php b/app/Helpers/CsvHelper.php index c27ff6d..c8d8c5a 100644 --- a/app/Helpers/CsvHelper.php +++ b/app/Helpers/CsvHelper.php @@ -2,6 +2,7 @@ namespace App\Helpers; +use App\Http\Controllers\ComisionesController; use Illuminate\Support\Facades\File; use Illuminate\Support\Facades\Log; use Iterator; @@ -13,15 +14,13 @@ use League\Csv\Writer; class CsvHelper { + /** * @throws Exception */ public static function getRecords($filePath, $message): Iterator { - $csv = Reader::createFromPath($filePath); try { - $csv->setDelimiter("|"); - $csv->setEnclosure("'"); - $csv->setHeaderOffset(0); + $csv = self::getReader($filePath); return $csv->getRecords(); } catch (InvalidArgument|Exception $e) { Log::error($e->getMessage()); @@ -29,20 +28,74 @@ class CsvHelper } } - public static function generarCsv($filePath, $contenido, $headers = null): void + /** + * @throws Exception + */ + public static function cambiarParametro(string $id, string $valor): void { - if (!File::exists(storage_path('csv/exports'))) { - File::makeDirectory(storage_path('csv/exports'), 0755, true); - } - try { - $writer = Writer::createFromPath(storage_path($filePath), 'w'); - if ($headers) { - $writer->insertOne($headers); + $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->insertAll($contenido); - } catch (CannotInsertRecord $e) { - Log::error($e->getMessage(), $e->getTrace()); + 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); } } + + /** + * @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; + } } diff --git a/app/Helpers/PedidosExportHelper.php b/app/Helpers/PedidosExportHelper.php new file mode 100644 index 0000000..b8672f2 --- /dev/null +++ b/app/Helpers/PedidosExportHelper.php @@ -0,0 +1,244 @@ +format('Y-m-d') . ".csv"; + $barrios = GrupoDeCompra::barriosMenosPrueba()->get(); + self::exportarCSV( + $filePath, + $barrios, + self::generarContenidoCSV( + $barrios, + fn ($grupoId) => + "subpedidos.grupo_de_compra_id = $grupoId + AND subpedidos.aprobado = 1 + AND subpedidos.tipo_pedido_id = 1" + ) + ); + } + /** + * @throws InvalidArgument + * @throws CannotInsertRecord + * @throws Exception + */ + static public function pedidosDeOllas() + { + $filePath = "csv/exports/pedidos-de-ollas-" . now()->format('Y-m-d') . ".csv"; + $barrios = GrupoDeCompra::barriosMenosPrueba()->get(); + + $contenido = self::generarContenidoCSV($barrios, + fn($grupoId) => "subpedidos.grupo_de_compra_id = $grupoId + AND subpedidos.tipo_pedido_id = 2"); + $ollas = self::cantidadDeOllasParaCSV($barrios, $contenido); + + self::exportarCSV( + $filePath, + $barrios, + $contenido->concat([$ollas]) + ); + } + + /** + * @throws Exception + */ + public static function cantidadDeOllasParaCSV(Collection $barrios, Collection $contenido) + { + $tipo_olla = TipoPedido::where('nombre', 'olla')->first()->id; + + $parametros = collect(CsvHelper::getRecords(resource_path("csv/parametros.csv"), "No se pudo leer el archivo.")); + $fila = [ + "producto" => "Cantidad de ollas", + "precio" => $parametros->where('id','monto-olla')->pluck('valor')->first(), + "paga_transporte" => false, + "fila" => $contenido->last()->fila + 1, + ]; + + foreach ($barrios as $barrio) { + $pedido = $barrio->subpedidos()->where('tipo_pedido_id', $tipo_olla)->first(); + $fila[$barrio->nombre] = $pedido->cantidad_ollas; + } + + return (object) $fila; + } + + /** + * @throws InvalidArgument + * @throws CannotInsertRecord + * @throws Exception + */ + static public function pedidoTotalDeBarrio(GrupoDeCompra $grupo) + { + $filePath = "csv/exports/" . $grupo->nombre . "-" . now()->format('Y-m-d') . ".csv"; + + $falsoBarrio = new GrupoDeCompra(['nombre' => 'Total']); + $falsoBarrio->id = $grupo->id; + $header = collect([$falsoBarrio]); + + self::exportarCSV( + $filePath, + $header, + self::generarContenidoCSV( + $header, + fn($grupoId) => "subpedidos.grupo_de_compra_id = $grupoId + AND subpedidos.aprobado = 1" + ), + ); + } + + /** + * @throws InvalidArgument + * @throws CannotInsertRecord + * @throws Exception + */ + static public function pedidosDeBarrio(GrupoDeCompra $grupo) + { + $filePath = "csv/exports/" . $grupo->nombre . "-completo-" . now()->format('Y-m-d') . ".csv"; + $subpedidos = $grupo->subpedidos()->where('aprobado', true)->get(); + self::exportarCSV( + $filePath, + $subpedidos, + self::generarContenidoCSV( + $subpedidos, + fn ($subpedidoId) => "subpedidos.id = $subpedidoId", + ) + ); + } + + /** + * @throws InvalidArgument + * @throws CannotInsertRecord + * @throws Exception + */ + private static function exportarCSV( + string $filename, + Collection $headers, + Collection $contenido + ): void { + $nombresColumnas = $headers->pluck('nombre')->toArray(); + $columnas = array_merge(['Producto'], $nombresColumnas); + $filaTransporte = TransporteHelper::filaTransporte(); + $planilla = []; + $ultimaFila = 1; + + foreach ($contenido as $fila) { + $filaActual = $fila->fila; + while ($filaActual - $ultimaFila > 1) { + $ultimaFila++; + $planilla[$ultimaFila] = [$ultimaFila === $filaTransporte ? 'Bono de transporte' : '---']; + } + $planilla[$filaActual] = [$fila->producto]; + foreach ($nombresColumnas as $nombre) + $planilla[$filaActual][] = $fila->$nombre ?? 0; + + $ultimaFila = $filaActual; + } + + $planilla[$filaTransporte] = array_merge(['Bono de transporte'], self::cantidadesTransporte($nombresColumnas, $contenido)); + + ksort($planilla); + CsvHelper::generarCsv($filename, $planilla, $columnas); + } + + /** + * @param Collection $headers + * @param Closure $filtroCallback + *
+ * Ejemplo de uso: + * `` + * PedidosExportHelper::generarContenidoCSV(GrupoDeCompra::barriosMenosPrueba(), + * fn($gdc_id) => "subpedidos.grupo_de_compra_id = $gdc_id"); + * `` + * @return Collection + * Los elementos son de la forma + * { + * fila: int (fila del producto), + * producto: string (nombre del producto), + * precio: float (precio del producto), + * paga_transporte: bool (1 o 0, calculado a partir de bono y categoria), + * barrio_1: string (cantidad pedida por barrio_1), + * ... + * barrio_n: string (cantidad pedida por barrio_n) + * } + */ + public static function generarContenidoCSV( + Collection $headers, + Closure $filtroCallback + ): Collection { + $expresionesColumnas = $headers->map(function ($header) use ($filtroCallback) { + $id = $header['id']; + $nombre = $header['nombre']; + $filtro = $filtroCallback($id); + return DB::raw(" + SUM(CASE WHEN $filtro THEN producto_subpedido.cantidad ELSE 0 END) as `$nombre` + "); + })->toArray(); + + $query = 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'); + + $columnasProducto = [ + 'productos.fila as fila', + 'productos.nombre as producto', + 'productos.precio as precio', + self::pagaTransporte(), + ]; + + return $query->select(array_merge( + $columnasProducto, + $expresionesColumnas + ))->groupBy('productos.fila', 'productos.id', 'productos.nombre') + ->orderBy('productos.fila') + ->get(); + } + + /** + * @return Expression + */ + public static function pagaTransporte(): Expression + { + return DB::raw('CASE WHEN productos.bono OR productos.categoria LIKE "%SUBSIDIADO%" THEN 0 ELSE 1 END as paga_transporte'); + } + + /** + * @param array $nombresColumnas + * @param Collection $contenido + * @return array + */ + public static function cantidadesTransporte(array $nombresColumnas, Collection $contenido): array + { + $transporte = []; + foreach ($nombresColumnas as $nombre) { + $suma = 0; + foreach ($contenido as $fila) { + if ($fila->paga_transporte) { + $cantidad = $fila->$nombre ?? 0; + $precio = $fila->precio ?? 0; + $suma += $cantidad * $precio; + } + } + $transporte[] = TransporteHelper::cantidadTransporte($suma); + } + return $transporte; + } +} diff --git a/app/Helpers/TransporteHelper.php b/app/Helpers/TransporteHelper.php index 046b4b8..7cc7eb6 100644 --- a/app/Helpers/TransporteHelper.php +++ b/app/Helpers/TransporteHelper.php @@ -4,21 +4,29 @@ namespace App\Helpers; use App\CanastaLog; use Illuminate\Support\Facades\Log; +use InvalidArgumentException; use League\Csv\Exception; class TransporteHelper { - const COSTO_TRANSPORTE = 15; - const MONTO_TRANSPORTE = 500; + private const COSTO_TRANSPORTE = "bono-transporte"; + private const MONTO_TRANSPORTE = "monto-transporte"; + private static ?array $parametros = null; + /** + * @throws Exception + */ public static function cantidadTransporte($monto) { - return ceil($monto / self::MONTO_TRANSPORTE); + return ceil($monto / self::getParametro(self::MONTO_TRANSPORTE)); } + /** + * @throws Exception + */ public static function totalTransporte($monto) { - return self::cantidadTransporte($monto) * self::COSTO_TRANSPORTE; + return self::cantidadTransporte($monto) * self::getParametro(self::COSTO_TRANSPORTE); } /** @@ -41,4 +49,28 @@ class TransporteHelper Log::error($error); throw new Exception($error); } + + /** + * @throws Exception + */ + public static function getParametro(string $id): int + { + if (self::$parametros === null) { + $records = CsvHelper::getRecords(resource_path('csv/parametros.csv'), "No se pudo leer el archivo."); + self::$parametros = []; + foreach ($records as $row) { + self::$parametros[$row['id']] = $row; + } + } + + if (!isset(self::$parametros[$id])) { + throw new InvalidArgumentException("Parámetro '$id' no encontrado."); + } + + return (int) self::$parametros[$id]['valor']; + } + + public static function resetParametros(): void { + self::$parametros = null; + } } diff --git a/app/Http/Controllers/AdminController.php b/app/Http/Controllers/AdminController.php index a280c84..5b788af 100644 --- a/app/Http/Controllers/AdminController.php +++ b/app/Http/Controllers/AdminController.php @@ -3,7 +3,9 @@ namespace App\Http\Controllers; use App\GrupoDeCompra; +use App\Helpers\PedidosExportHelper; use League\Csv\Exception; +use Mpdf\MpdfException; class AdminController extends Controller { @@ -17,13 +19,18 @@ class AdminController extends Controller } public function exportarPedidosAPdf(GrupoDeCompra $gdc) { - $gdc->exportarPedidosAPdf(); + try { + $gdc->exportarPedidosAPdf(); + return response(); + } catch (MpdfException $e) { + return response()->json(['message' => $e->getMessage()], 500); + } } public function exportarPedidoACSV(GrupoDeCompra $gdc) { try { - $gdc->exportarPedidoEnCSV(); + PedidosExportHelper::pedidoTotalDeBarrio($gdc); } catch (Exception $e) { return response()->json(['message' => $e->getMessage()]); } @@ -40,7 +47,7 @@ class AdminController extends Controller public function exportarPedidoConNucleosACSV(GrupoDeCompra $gdc) { try { - $gdc->exportarPedidoConNucleosEnCSV(); + PedidosExportHelper::pedidosDeBarrio($gdc); } catch (Exception $e) { return response()->json(['message' => $e->getMessage()]); } diff --git a/app/Http/Controllers/Api/SubpedidoController.php b/app/Http/Controllers/Api/SubpedidoController.php index 7e6b266..e340e01 100644 --- a/app/Http/Controllers/Api/SubpedidoController.php +++ b/app/Http/Controllers/Api/SubpedidoController.php @@ -4,6 +4,7 @@ namespace App\Http\Controllers\Api; use App\Http\Controllers\Controller; use App\Producto; +use App\TipoPedido; use Illuminate\Http\Request; use App\Filtros\FiltroDeSubpedido; use App\Subpedido; @@ -12,7 +13,6 @@ use App\Http\Resources\SubpedidoResource; use Illuminate\Validation\Rule; use Symfony\Component\HttpKernel\Exception\HttpException; - class SubpedidoController extends Controller { public function index(FiltroDeSubpedido $filtros, Request $request) @@ -25,17 +25,25 @@ class SubpedidoController extends Controller return SubpedidoResource::collection(Subpedido::filtrar($filtros)->get()); } - public function store(Request $request) + public function store(Request $request) { $validado = $this->validateSubpedido(); - if (Subpedido::where("nombre",$validado["nombre"])->where("grupo_de_compra_id",$validado["grupo_de_compra_id"])->get()->count()) { - throw new HttpException(400, "Ya existe un subpedido con este nombre"); - } - $s = new Subpedido(); - $s->nombre = $validado["nombre"]; - $s->grupo_de_compra_id = $validado["grupo_de_compra_id"]; - $s->save(); - return $this->show($s); + + if (Subpedido::where([ + "nombre" => $validado["nombre"], + "tipo_pedido_id" => $validado["tipo_id"], + "grupo_de_compra_id" => $validado["grupo_de_compra_id"]]) + ->get() + ->count()) + throw new HttpException(400, "Ya existe un pedido con este nombre"); + + $pedido = new Subpedido(); + $pedido->nombre = $validado["nombre"]; + $pedido->grupo_de_compra_id = $validado["grupo_de_compra_id"]; + $pedido->tipo_pedido_id = $validado["tipo_id"]; + $pedido->save(); + + return $this->show($pedido); } protected function validateSubpedido(): array @@ -45,7 +53,11 @@ class SubpedidoController extends Controller 'grupo_de_compra_id' => [ 'required', Rule::in(GrupoDeCompra::all()->pluck('id')), - ] + ], + 'tipo_id' => [ + 'required', + Rule::in(TipoPedido::all()->pluck('id')), + ], ]); } diff --git a/app/Http/Controllers/ComisionesController.php b/app/Http/Controllers/ComisionesController.php index 6c5d555..f4150aa 100644 --- a/app/Http/Controllers/ComisionesController.php +++ b/app/Http/Controllers/ComisionesController.php @@ -5,15 +5,19 @@ namespace App\Http\Controllers; use App\GrupoDeCompra; use App\Helpers\CanastaHelper; use App\Helpers\CsvHelper; +use App\Helpers\PedidosExportHelper; +use App\Helpers\TransporteHelper; use App\Http\Resources\GrupoDeCompraResource; 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"; @@ -26,7 +30,7 @@ class ComisionesController public function descargarPedidos() { try { - Producto::planillaTotales(); + PedidosExportHelper::pedidosBarriales(); } catch (Exception $e) { return response()->json(['message' => $e->getMessage()], 500); } @@ -40,6 +44,23 @@ class ComisionesController return response()->download($files[0]); } + public function descargarPedidosDeOllas() + { + try { + PedidosExportHelper::pedidosDeOllas(); + } catch (Exception $e) { + return response()->json(['message' => $e->getMessage()], 500); + } + $pattern = storage_path('csv/exports/pedidos-de-ollas-*.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(); @@ -54,7 +75,12 @@ class ComisionesController } public function pdf() { - GrupoDeCompra::exportarPedidosBarrialesAPdf(); + try { + GrupoDeCompra::exportarPedidosBarrialesAPdf(); + return response(); + } catch (MpdfException $e) { + return response()->json(['message' => $e->getMessage()], 500); + } } public function cargarCanasta(Request $request): JsonResponse @@ -104,4 +130,43 @@ class ComisionesController return response()->json(GrupoDeCompraResource::collection(GrupoDeCompra::all())); } + + public function obtenerParametros(): JsonResponse + { + 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']); + TransporteHelper::resetParametros(); + 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); + } } diff --git a/app/Http/Controllers/OllasController.php b/app/Http/Controllers/OllasController.php new file mode 100644 index 0000000..2b64615 --- /dev/null +++ b/app/Http/Controllers/OllasController.php @@ -0,0 +1,40 @@ + 'olla']); + $pedido = $gdc->subpedidos()->firstOrCreate([ + 'nombre' => 'Pedido de Ollas de ' . $gdc->nombre, + 'tipo_pedido_id' => $tipoOlla->id, + 'cantidad_ollas' => 0, + ]); + 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(); + } +} diff --git a/app/Http/Controllers/RouteController.php b/app/Http/Controllers/RouteController.php index e5b4a57..17893b5 100644 --- a/app/Http/Controllers/RouteController.php +++ b/app/Http/Controllers/RouteController.php @@ -15,6 +15,7 @@ class RouteController extends Controller $barrio = UserRole::where('nombre', 'barrio')->first(); $admin = UserRole::where('nombre', 'admin_barrio')->first(); $comision = UserRole::where('nombre', 'comision')->first(); + $ollas = UserRole::where('nombre', 'ollas')->first(); switch ($request->user()->role_id) { case $barrio->id: @@ -23,6 +24,8 @@ class RouteController extends Controller return redirect('/admin'); case $comision->id: return redirect('/comisiones'); + case $ollas->id: + return redirect('/ollas'); default: abort(400, 'Rol de usuario invalido'); } diff --git a/app/Http/Controllers/UserController.php b/app/Http/Controllers/UserController.php index 62243c5..0b271ac 100644 --- a/app/Http/Controllers/UserController.php +++ b/app/Http/Controllers/UserController.php @@ -11,6 +11,11 @@ use Illuminate\Support\Facades\Auth; class UserController extends Controller { + public function user(Request $request) + { + return ['user' => $request->user()->name]; + } + public function rol(Request $request) { return ["rol" => UserRole::find($request->user()->role_id)->nombre]; } @@ -21,6 +26,7 @@ class UserController extends Controller $result = [ 'grupo_de_compra' => null, ]; $grupo_de_compra = GrupoDeCompra::find($user->grupo_de_compra_id); switch (UserRole::findOrFail($user->role_id)->nombre) { + case 'ollas': case 'barrio': $result['grupo_de_compra'] = new GrupoDeCompraPedidoResource($grupo_de_compra); break; diff --git a/app/Http/Middleware/Authenticate.php b/app/Http/Middleware/Authenticate.php index 7eabcdf..5ae0330 100644 --- a/app/Http/Middleware/Authenticate.php +++ b/app/Http/Middleware/Authenticate.php @@ -3,16 +3,17 @@ namespace App\Http\Middleware; use Illuminate\Auth\Middleware\Authenticate as Middleware; +use Illuminate\Http\Request; class Authenticate extends Middleware { /** * Get the path the user should be redirected to when they are not authenticated. * - * @param \Illuminate\Http\Request $request + * @param Request $request * @return string|null */ - protected function redirectTo($request) + protected function redirectTo($request): string { if (!$request->expectsJson()) { $path = $request->path(); @@ -20,7 +21,10 @@ class Authenticate extends Middleware return route('admin.login'); if (preg_match('~^comisiones.*~i', $path)) return route('comisiones.login'); + if (preg_match('~^ollas.*~i', $path)) + return route('ollas.login'); return route('login'); } + return ''; } } diff --git a/app/Http/Resources/GrupoDeCompraPedidoResource.php b/app/Http/Resources/GrupoDeCompraPedidoResource.php index ea725f7..f369571 100644 --- a/app/Http/Resources/GrupoDeCompraPedidoResource.php +++ b/app/Http/Resources/GrupoDeCompraPedidoResource.php @@ -2,6 +2,7 @@ namespace App\Http\Resources; +use Illuminate\Http\Request; use Illuminate\Http\Resources\Json\JsonResource; class GrupoDeCompraPedidoResource extends JsonResource @@ -9,7 +10,7 @@ class GrupoDeCompraPedidoResource extends JsonResource /** * Transform the resource into an array. * - * @param \Illuminate\Http\Request $request + * @param Request $request * @return array */ public function toArray($request): array { diff --git a/app/Http/Resources/GrupoDeCompraResource.php b/app/Http/Resources/GrupoDeCompraResource.php index b67e14b..82f2120 100644 --- a/app/Http/Resources/GrupoDeCompraResource.php +++ b/app/Http/Resources/GrupoDeCompraResource.php @@ -19,7 +19,7 @@ class GrupoDeCompraResource extends JsonResource 'id' => $this->id, 'nombre' => $this->nombre, 'devoluciones_habilitadas' => $this->devoluciones_habilitadas, - 'pedidos' => SubpedidoResource::collection($this->subpedidos), + 'pedidos' => SubpedidoResource::collection($this->pedidosHogares()), 'total_a_recaudar' => number_format($this->totalARecaudar(),2), 'saldo' => number_format($this->saldo, 2, ".", ""), 'total_sin_devoluciones' => number_format($this->totalSinDevoluciones(),2), diff --git a/app/Http/Resources/PedidoOllasResource.php b/app/Http/Resources/PedidoOllasResource.php new file mode 100644 index 0000000..3af1d40 --- /dev/null +++ b/app/Http/Resources/PedidoOllasResource.php @@ -0,0 +1,30 @@ +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, + ]; + } +} diff --git a/app/Http/Resources/SubpedidoResource.php b/app/Http/Resources/SubpedidoResource.php index 89b911e..ec3483f 100644 --- a/app/Http/Resources/SubpedidoResource.php +++ b/app/Http/Resources/SubpedidoResource.php @@ -2,6 +2,7 @@ namespace App\Http\Resources; +use App\TipoPedido; use Illuminate\Http\Request; use Illuminate\Http\Resources\Json\JsonResource; @@ -29,7 +30,11 @@ class SubpedidoResource extends JsonResource 'cantidad_transporte' => number_format($this->cantidadTransporte()), 'total_sin_devoluciones' => number_format($this->totalSinDevoluciones(),2), 'devoluciones_total' => number_format($this->devoluciones_total,2), - 'devoluciones_notas' => $this->devoluciones_notas + 'devoluciones_notas' => $this->devoluciones_notas, + 'tipo' => [ + 'id' => $this->tipo_pedido_id, + 'nombre' => TipoPedido::find($this->tipo_pedido_id)->nombre + ], ]; } } diff --git a/app/Producto.php b/app/Producto.php index 5617617..0deffa6 100644 --- a/app/Producto.php +++ b/app/Producto.php @@ -11,7 +11,9 @@ 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 { @@ -19,15 +21,10 @@ 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); @@ -35,7 +32,9 @@ 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() @@ -53,77 +52,20 @@ class Producto extends Model return self::noBarriales()->pluck('nombre', 'id')->all(); } - static public function cantidadesPorBarrio(): Collection + public static function noBarriales() { - $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 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') - ->select(array_merge( - ['productos.fila as fila'], - ['productos.nombre as producto'], - $columnasBarrios - )) - ->groupBy('productos.fila', 'productos.id', 'productos.nombre') - ->orderBy('productos.fila') - ->get(); - } - - /** - * @throws Exception - */ - static public function planillaTotales() - { - $headers = ['Producto']; - $barrios = GrupoDeCompra::barriosMenosPrueba() - ->pluck('nombre')->toArray(); - $headers = array_merge($headers, $barrios); - - $cantidadesPorBarrio = self::cantidadesPorBarrio(); - $transportePorBarrio = GrupoDeCompra::transportePorBarrio(); - $planilla = []; - $ultimaFila = 1; - $filaTransporte = TransporteHelper::filaTransporte(); - - foreach ($cantidadesPorBarrio as $productoCantidades) { - $fila = $productoCantidades->fila; - while ($fila - $ultimaFila > 1) { - $ultimaFila++; - if ($ultimaFila == $filaTransporte) { - $planilla[$ultimaFila] = ['Bono de transporte']; - } else { - $planilla[$ultimaFila] = ['---']; - } - } - $planilla[$fila] = [$productoCantidades->producto]; - foreach ($barrios as $barrio) { - $planilla[$fila][] = $productoCantidades->$barrio ?? 0; - } - $ultimaFila = $fila; - } - - foreach ($transportePorBarrio as $key => $cantidad) { - $planilla[$filaTransporte][] = $cantidad; - } - - $fecha = now()->format('Y-m-d'); - CsvHelper::generarCsv('csv/exports/pedidos-por-barrio- ' . $fecha . '.csv', $planilla, $headers); + return self::where('nombre', 'not like', '%barrial%'); } 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', @@ -133,6 +75,10 @@ class Producto extends Model ->groupBy('producto'); } + /** + * @throws InvalidArgument + * @throws CannotInsertRecord + */ static public function planillaNotas() { $headers = ['Producto']; $barrios = GrupoDeCompra::barriosMenosPrueba() @@ -145,13 +91,16 @@ 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'); - CsvHelper::generarCsv('csv/exports/notas-por-barrio-' . $fecha . '.csv', $planilla, $headers); + $filePath = 'csv/exports/notas-por-barrio-' . $fecha . '.csv'; + CsvHelper::generarCsv($filePath, $planilla, $headers); } } diff --git a/app/Subpedido.php b/app/Subpedido.php index 26e38e4..df989af 100644 --- a/app/Subpedido.php +++ b/app/Subpedido.php @@ -12,7 +12,15 @@ use App\Filtros\FiltroDeSubpedido; class Subpedido extends Model { - protected $fillable = ['grupo_de_compra_id', 'aprobado', 'nombre', 'devoluciones_total', 'devoluciones_notas']; + protected $fillable = [ + 'grupo_de_compra_id', + 'aprobado', + 'nombre', + 'devoluciones_total', + 'devoluciones_notas', + 'tipo_pedido_id', + 'cantidad_ollas' + ]; public function productos(): BelongsToMany { @@ -24,6 +32,11 @@ class Subpedido extends Model return $this->belongsTo(GrupoDeCompra::class); } + public function tipoPedido(): BelongsTo + { + return $this->belongsTo(TipoPedido::class); + } + // Permite que se apliquen los filtros al hacer una request (por ejemplo, de búsqueda) public function scopeFiltrar($query, FiltroDeSubpedido $filtros): Builder { @@ -52,7 +65,11 @@ class Subpedido extends Model public function totalCentral() { - return $this->totalCentralesQueNoPaganTransporte() + $this->totalCentralesQuePaganTransporte() + $this->totalTransporte(); + return $this->totalCentralesSinTransporte() + $this->totalTransporte(); + } + + public function totalCentralesSinTransporte() { + return $this->totalCentralesQueNoPaganTransporte() + $this->totalCentralesQuePaganTransporte(); } public function totalCentralesQueNoPaganTransporte() diff --git a/app/TipoPedido.php b/app/TipoPedido.php new file mode 100644 index 0000000..310761a --- /dev/null +++ b/app/TipoPedido.php @@ -0,0 +1,10 @@ + 'UTC', + 'timezone' => 'America/Montevideo', /* |-------------------------------------------------------------------------- diff --git a/database/migrations/2025_06_20_001436_create_tipo_pedidos_table.php b/database/migrations/2025_06_20_001436_create_tipo_pedidos_table.php new file mode 100644 index 0000000..e40bdbc --- /dev/null +++ b/database/migrations/2025_06_20_001436_create_tipo_pedidos_table.php @@ -0,0 +1,43 @@ +id(); + $table->string("nombre"); + $table->timestamps(); + }); + + $hogar = TipoPedido::firstOrCreate(['nombre' => 'hogar']); + TipoPedido::firstOrCreate(['nombre' => 'olla']); + + Schema::table('subpedidos', function (Blueprint $table) use ($hogar) { + $table->foreignId('tipo_pedido_id')->default($hogar->id); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::dropIfExists('tipo_pedidos'); + Schema::table('subpedidos', function (Blueprint $table) { + $table->dropColumn('tipo_pedido_id'); + }); + } +} diff --git a/database/migrations/2025_06_20_040800_user_role_ollas.php b/database/migrations/2025_06_20_040800_user_role_ollas.php new file mode 100644 index 0000000..eaeb1d7 --- /dev/null +++ b/database/migrations/2025_06_20_040800_user_role_ollas.php @@ -0,0 +1,40 @@ + 'ollas']); + $barrios = GrupoDeCompra::all(); + foreach ($barrios as $barrio) { + $barrio->users()->firstOrCreate([ + 'name' => $barrio->nombre . '_ollas', + 'password' => Hash::make('123'), + 'role_id' => $ollasRol->id + ]); + } + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + $ollasRol = UserRole::where('nombre', 'ollas')->firstOrFail(); + User::where('role_id', $ollasRol->id)->delete(); + $ollasRol->delete(); + } +} diff --git a/database/migrations/2025_06_23_233548_cantidad_ollas_pedidos.php b/database/migrations/2025_06_23_233548_cantidad_ollas_pedidos.php new file mode 100644 index 0000000..ef944f9 --- /dev/null +++ b/database/migrations/2025_06_23_233548_cantidad_ollas_pedidos.php @@ -0,0 +1,32 @@ +integer('cantidad_ollas')->nullable(); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::table('subpedidos', function (Blueprint $table) { + $table->dropColumn('cantidad_ollas'); + }); + } +} diff --git a/database/seeds/DatabaseSeeder.php b/database/seeds/DatabaseSeeder.php index 57f6ac4..2e58402 100644 --- a/database/seeds/DatabaseSeeder.php +++ b/database/seeds/DatabaseSeeder.php @@ -24,5 +24,6 @@ class DatabaseSeeder extends Seeder $this->call(CanastaSeeder::class); $this->call(GrupoDeCompraSeeder::class); $this->call(UserSeeder::class); + $this->call(UsuarioOllasSeeder::class); } } diff --git a/database/seeds/UsuarioOllasSeeder.php b/database/seeds/UsuarioOllasSeeder.php new file mode 100644 index 0000000..dff4acf --- /dev/null +++ b/database/seeds/UsuarioOllasSeeder.php @@ -0,0 +1,34 @@ +first()->id; + + foreach ($barrios as $barrio) { + $usersToInsert[] = DatabaseSeeder::addTimestamps([ + 'name' => $barrio->nombre . '_ollas', + 'password' => Hash::make('123'), + 'role_id' => $ollas_id, + 'grupo_de_compra_id' => $barrio->id, + ]); + } + + foreach (array_chunk($usersToInsert,DatabaseSeeder::CHUNK_SIZE) as $chunk) + User::insert($chunk); + } +} diff --git a/package-lock.json b/package-lock.json index 6badddb..2370676 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1648,19 +1648,6 @@ "hasInstallScript": true, "optional": true, "dependencies": { - "@parcel/watcher-android-arm64": "2.5.1", - "@parcel/watcher-darwin-arm64": "2.5.1", - "@parcel/watcher-darwin-x64": "2.5.1", - "@parcel/watcher-freebsd-x64": "2.5.1", - "@parcel/watcher-linux-arm-glibc": "2.5.1", - "@parcel/watcher-linux-arm-musl": "2.5.1", - "@parcel/watcher-linux-arm64-glibc": "2.5.1", - "@parcel/watcher-linux-arm64-musl": "2.5.1", - "@parcel/watcher-linux-x64-glibc": "2.5.1", - "@parcel/watcher-linux-x64-musl": "2.5.1", - "@parcel/watcher-win32-arm64": "2.5.1", - "@parcel/watcher-win32-ia32": "2.5.1", - "@parcel/watcher-win32-x64": "2.5.1", "detect-libc": "^1.0.3", "is-glob": "^4.0.3", "micromatch": "^4.0.5", @@ -2056,7 +2043,6 @@ "dependencies": { "@babel/parser": "^7.23.5", "postcss": "^8.4.14", - "prettier": "^1.18.2 || ^2.0.0", "source-map": "^0.6.1" }, "optionalDependencies": { @@ -2102,7 +2088,6 @@ "merge-source-map": "^1.1.0", "postcss": "^7.0.36", "postcss-selector-parser": "^6.0.2", - "prettier": "^1.18.2 || ^2.0.0", "source-map": "~0.6.1", "vue-template-es2015-compiler": "^1.9.0" }, @@ -3555,7 +3540,6 @@ "anymatch": "^2.0.0", "async-each": "^1.0.1", "braces": "^2.3.2", - "fsevents": "^1.2.7", "glob-parent": "^3.1.0", "inherits": "^2.0.3", "is-binary-path": "^1.0.0", @@ -7975,9 +7959,6 @@ "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", "integrity": "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==", "dev": true, - "dependencies": { - "graceful-fs": "^4.1.6" - }, "optionalDependencies": { "graceful-fs": "^4.1.6" } @@ -11334,7 +11315,6 @@ "integrity": "sha512-d0NoFH4v6SjEK7BoX810Jsrhj7IQSYHAHLi/iSpgqKc7LaIDshFRlSg5LOymf9FqQhxEHs2W5ZQXlvy0KD45Uw==", "dev": true, "dependencies": { - "@parcel/watcher": "^2.4.1", "chokidar": "^4.0.0", "immutable": "^5.0.2", "source-map-js": ">=0.6.2 <2.0.0" @@ -13424,10 +13404,8 @@ "integrity": "sha512-9P3MWk6SrKjHsGkLT2KHXdQ/9SNkyoJbabxnKOoJepsvJjJG8uYTR3yTPxPQvNDI3w4Nz1xnE0TLHK4RIVe/MQ==", "dev": true, "dependencies": { - "chokidar": "^3.4.1", "graceful-fs": "^4.1.2", - "neo-async": "^2.5.0", - "watchpack-chokidar2": "^2.0.1" + "neo-async": "^2.5.0" }, "optionalDependencies": { "chokidar": "^3.4.1", @@ -13493,7 +13471,6 @@ "dependencies": { "anymatch": "~3.1.2", "braces": "~3.0.2", - "fsevents": "~2.3.2", "glob-parent": "~5.1.2", "is-binary-path": "~2.1.0", "is-glob": "~4.0.1", diff --git a/resources/csv/exports/.gitignore b/resources/csv/exports/.gitignore deleted file mode 100644 index e69de29..0000000 diff --git a/resources/csv/parametros.csv b/resources/csv/parametros.csv new file mode 100644 index 0000000..ebd8fda --- /dev/null +++ b/resources/csv/parametros.csv @@ -0,0 +1,4 @@ +id|nombre|valor +bono-transporte|'Bono de transporte'|15 +monto-transporte|'Monto para bono de transporte'|500 +monto-olla|'Monto por olla'|1200 diff --git a/resources/js/components/AppMain.vue b/resources/js/components/AppMain.vue index 09780fc..bddee51 100644 --- a/resources/js/components/AppMain.vue +++ b/resources/js/components/AppMain.vue @@ -5,9 +5,10 @@ import ComisionesBody from "./comisiones/Body.vue"; import AdminBody from "./admin/Body.vue"; import PedidosBody from "./pedidos/Body.vue"; import InfoTags from "./comunes/InfoTags.vue"; +import OllasBody from "./ollas/OllasBody.vue"; export default { name: 'Main', - components: { InfoTags, ComisionesBody, AdminBody, PedidosBody, NavBar }, + components: { OllasBody, InfoTags, ComisionesBody, AdminBody, PedidosBody, NavBar }, computed: { ...mapState("login", ["rol"]), }, @@ -26,6 +27,7 @@ export default { + diff --git a/resources/js/components/admin/AdminNavBarBrand.vue b/resources/js/components/admin/AdminNavBarBrand.vue new file mode 100644 index 0000000..bd27811 --- /dev/null +++ b/resources/js/components/admin/AdminNavBarBrand.vue @@ -0,0 +1,25 @@ + + + + + diff --git a/resources/js/components/comisiones/Body.vue b/resources/js/components/comisiones/Body.vue index 56287e4..3614c64 100644 --- a/resources/js/components/comisiones/Body.vue +++ b/resources/js/components/comisiones/Body.vue @@ -18,6 +18,11 @@ :class="seccionActiva === 'saldos-comisiones-seccion' ? 'is-active' : 'is-hidden'"> +
+ +
@@ -27,11 +32,12 @@ 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"; +import ParametrosSeccion from "./parametros/ParametrosSeccion.vue"; export default { name: "ComisionesBody", components: { + ParametrosSeccion, SaldosSeccion, CanastaSeccion, TabsSecciones, @@ -44,6 +50,7 @@ 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", diff --git a/resources/js/components/comisiones/ComisionesNavBarBrand.vue b/resources/js/components/comisiones/ComisionesNavBarBrand.vue new file mode 100644 index 0000000..eed7d60 --- /dev/null +++ b/resources/js/components/comisiones/ComisionesNavBarBrand.vue @@ -0,0 +1,31 @@ + + + + + diff --git a/resources/js/components/comisiones/DropdownDescargar.vue b/resources/js/components/comisiones/DropdownDescargar.vue index dc119a8..9e6be43 100644 --- a/resources/js/components/comisiones/DropdownDescargar.vue +++ b/resources/js/components/comisiones/DropdownDescargar.vue @@ -15,14 +15,17 @@ diff --git a/resources/js/components/comisiones/parametros/FilaParametro.vue b/resources/js/components/comisiones/parametros/FilaParametro.vue new file mode 100644 index 0000000..99add70 --- /dev/null +++ b/resources/js/components/comisiones/parametros/FilaParametro.vue @@ -0,0 +1,71 @@ + + + + + diff --git a/resources/js/components/comisiones/parametros/ParametrosSeccion.vue b/resources/js/components/comisiones/parametros/ParametrosSeccion.vue new file mode 100644 index 0000000..dbdc80f --- /dev/null +++ b/resources/js/components/comisiones/parametros/ParametrosSeccion.vue @@ -0,0 +1,41 @@ + + + + + diff --git a/resources/js/components/comunes/Burger.vue b/resources/js/components/comunes/Burger.vue new file mode 100644 index 0000000..bea3367 --- /dev/null +++ b/resources/js/components/comunes/Burger.vue @@ -0,0 +1,30 @@ + + + + + diff --git a/resources/js/components/comunes/NavBar.vue b/resources/js/components/comunes/NavBar.vue index e6a95d3..a84edb1 100644 --- a/resources/js/components/comunes/NavBar.vue +++ b/resources/js/components/comunes/NavBar.vue @@ -1,43 +1,33 @@