Compare commits

..

12 commits

12 changed files with 261 additions and 19 deletions

View file

@ -171,7 +171,7 @@ class GrupoDeCompra extends Model
*/ */
public static function exportarPedidosBarrialesAPdf() public static function exportarPedidosBarrialesAPdf()
{ {
$barrios = GrupoDeCompra::barriosMenosPruebaConPedidosAprobados()->get(); $barrios = GrupoDeCompra::barriosMenosPrueba()->get();
$fecha = now()->format('Y-m-d'); $fecha = now()->format('Y-m-d');
$filepath = 'pedidos_por_barrio-' . $fecha . '.pdf'; $filepath = 'pedidos_por_barrio-' . $fecha . '.pdf';
PdfHelper::exportarPedidos($filepath, $barrios); PdfHelper::exportarPedidos($filepath, $barrios);
@ -292,12 +292,9 @@ class GrupoDeCompra extends Model
return array($records, $i, $cantidad); return array($records, $i, $cantidad);
} }
public static function barriosMenosPruebaConPedidosAprobados(): Builder public static function barriosMenosPrueba(): Builder
{ {
return self::where('nombre', '<>', 'PRUEBA') return self::where('nombre', '<>', 'PRUEBA')
->whereHas('subpedidos', function ($query) {
$query->where('aprobado', true);
})
->orderBy('region') ->orderBy('region')
->orderBy('nombre'); ->orderBy('nombre');
} }
@ -305,7 +302,7 @@ class GrupoDeCompra extends Model
public static function transportePorBarrio(): array public static function transportePorBarrio(): array
{ {
$result = []; $result = [];
$barrios = GrupoDeCompra::barriosMenosPruebaConPedidosAprobados()->get(); $barrios = GrupoDeCompra::barriosMenosPrueba()->get();
foreach ($barrios as $barrio) { foreach ($barrios as $barrio) {
$result[] = $barrio->cantidadTransporte(); $result[] = $barrio->cantidadTransporte();

View file

@ -0,0 +1,219 @@
<?php
namespace App\Helpers;
use App\GrupoDeCompra;
use Closure;
use Illuminate\Database\Query\Expression;
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\DB;
use League\Csv\CannotInsertRecord;
use League\Csv\Exception;
use League\Csv\InvalidArgument;
class PedidosExportHelper
{
/**
* @throws InvalidArgument
* @throws CannotInsertRecord
* @throws Exception
*/
static public function pedidosBarriales()
{
$filePath = "csv/exports/pedidos-por-barrio-" . now()->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();
self::exportarCSV(
$filePath,
$barrios,
self::generarContenidoCSV(
$barrios,
fn ($grupoId) =>
"subpedidos.grupo_de_compra_id = $grupoId
AND subpedidos.tipo_pedido_id = 2"
)
);
}
/**
* @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
* <br>
* 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;
}
}

View file

@ -3,6 +3,7 @@
namespace App\Http\Controllers; namespace App\Http\Controllers;
use App\GrupoDeCompra; use App\GrupoDeCompra;
use App\Helpers\PedidosExportHelper;
use League\Csv\Exception; use League\Csv\Exception;
use Mpdf\MpdfException; use Mpdf\MpdfException;
@ -29,7 +30,7 @@ class AdminController extends Controller
public function exportarPedidoACSV(GrupoDeCompra $gdc) public function exportarPedidoACSV(GrupoDeCompra $gdc)
{ {
try { try {
$gdc->exportarPedidoEnCSV(); PedidosExportHelper::pedidoTotalDeBarrio($gdc);
} catch (Exception $e) { } catch (Exception $e) {
return response()->json(['message' => $e->getMessage()]); return response()->json(['message' => $e->getMessage()]);
} }
@ -46,7 +47,7 @@ class AdminController extends Controller
public function exportarPedidoConNucleosACSV(GrupoDeCompra $gdc) public function exportarPedidoConNucleosACSV(GrupoDeCompra $gdc)
{ {
try { try {
$gdc->exportarPedidoConNucleosEnCSV(); PedidosExportHelper::pedidosDeBarrio($gdc);
} catch (Exception $e) { } catch (Exception $e) {
return response()->json(['message' => $e->getMessage()]); return response()->json(['message' => $e->getMessage()]);
} }

View file

@ -31,7 +31,7 @@ class SubpedidoController extends Controller
if (Subpedido::where([ if (Subpedido::where([
"nombre" => $validado["nombre"], "nombre" => $validado["nombre"],
"tipo_pedido_id" => $validado["tipo_pedido_id"], "tipo_pedido_id" => $validado["tipo_id"],
"grupo_de_compra_id" => $validado["grupo_de_compra_id"]]) "grupo_de_compra_id" => $validado["grupo_de_compra_id"]])
->get() ->get()
->count()) ->count())

View file

@ -5,6 +5,7 @@ namespace App\Http\Controllers;
use App\GrupoDeCompra; use App\GrupoDeCompra;
use App\Helpers\CanastaHelper; use App\Helpers\CanastaHelper;
use App\Helpers\CsvHelper; use App\Helpers\CsvHelper;
use App\Helpers\PedidosExportHelper;
use App\Http\Resources\GrupoDeCompraResource; use App\Http\Resources\GrupoDeCompraResource;
use App\Producto; use App\Producto;
use Illuminate\Http\JsonResponse; use Illuminate\Http\JsonResponse;
@ -28,7 +29,7 @@ class ComisionesController
public function descargarPedidos() public function descargarPedidos()
{ {
try { try {
Producto::planillaTotales(); PedidosExportHelper::pedidosBarriales();
} catch (Exception $e) { } catch (Exception $e) {
return response()->json(['message' => $e->getMessage()], 500); return response()->json(['message' => $e->getMessage()], 500);
} }
@ -42,6 +43,23 @@ class ComisionesController
return response()->download($files[0]); 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 public function descargarNotas(): BinaryFileResponse
{ {
Producto::planillaNotas(); Producto::planillaNotas();

View file

@ -59,7 +59,8 @@ class Producto extends Model
static public function cantidadesPorBarrio(): Collection static public function cantidadesPorBarrio(): Collection
{ {
$barrios = GrupoDeCompra::barriosMenosPruebaConPedidosAprobados()->pluck('id', 'nombre'); $barrios = GrupoDeCompra::barriosMenosPrueba()
->pluck('id', 'nombre');
$columnasBarrios = $barrios->map(function ($id, $nombre) { $columnasBarrios = $barrios->map(function ($id, $nombre) {
return DB::raw(" return DB::raw("
@ -92,7 +93,7 @@ class Producto extends Model
static public function planillaTotales() static public function planillaTotales()
{ {
$headers = ['Producto']; $headers = ['Producto'];
$barrios = GrupoDeCompra::barriosMenosPruebaConPedidosAprobados()->pluck('nombre')->toArray(); $barrios = GrupoDeCompra::barriosMenosPrueba()->pluck('nombre')->toArray();
$headers = array_merge($headers, $barrios); $headers = array_merge($headers, $barrios);
$cantidadesPorBarrio = self::cantidadesPorBarrio(); $cantidadesPorBarrio = self::cantidadesPorBarrio();
@ -151,7 +152,7 @@ class Producto extends Model
*/ */
static public function planillaNotas() { static public function planillaNotas() {
$headers = ['Producto']; $headers = ['Producto'];
$barrios = GrupoDeCompra::barriosMenosPruebaConPedidosAprobados() $barrios = GrupoDeCompra::barriosMenosPrueba()
->pluck('nombre')->toArray(); ->pluck('nombre')->toArray();
$headers = array_merge($headers, $barrios); $headers = array_merge($headers, $barrios);

View file

@ -67,7 +67,7 @@ return [
| |
*/ */
'timezone' => 'UTC', 'timezone' => 'America/Montevideo',
/* /*
|-------------------------------------------------------------------------- |--------------------------------------------------------------------------

View file

@ -15,14 +15,17 @@
<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="/comisiones/pedidos/descargar" class="dropdown-item"> <a href="/comisiones/pedidos/descargar" class="dropdown-item">
Pedidos por barrio Pedidos por barrio en csv
</a> </a>
<a href="/comisiones/pedidos/notas" class="dropdown-item"> <a href="/comisiones/pedidos/notas" class="dropdown-item">
Notas por barrio Notas por barrio en csv
</a> </a>
<a href="/comisiones/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>
<a href="/comisiones/pedidos/ollas" class="dropdown-item">
Pedidos de ollas en csv
</a>
</div> </div>
</div> </div>
</div> </div>

View file

@ -11,6 +11,7 @@ export default defineComponent({
components: { CantidadOllas, NavMigas, Chismosa, Canasta }, components: { CantidadOllas, NavMigas, Chismosa, Canasta },
computed: { computed: {
...mapState('ui', ["show_chismosa"]), ...mapState('ui', ["show_chismosa"]),
...mapState('login', ["rol"])
}, },
methods: { methods: {
...mapActions('productos', ["init"]), ...mapActions('productos', ["init"]),
@ -24,7 +25,7 @@ export default defineComponent({
<template> <template>
<div> <div>
<nav-migas/> <nav-migas/>
<cantidad-ollas/> <cantidad-ollas v-if="rol === 'ollas'"/>
<div class="columns"> <div class="columns">
<div class="column" :class="{ 'is-two-thirds-desktop is-hidden-touch': show_chismosa }"> <div class="column" :class="{ 'is-two-thirds-desktop is-hidden-touch': show_chismosa }">
<slot name="cartel"></slot> <slot name="cartel"></slot>

View file

@ -117,6 +117,7 @@ export default {
this.notas_warning_visible = true; this.notas_warning_visible = true;
return; return;
} }
this.notas_warning_visible = false;
await this.modificarChismosa({ await this.modificarChismosa({
producto_id: this.producto_id, producto_id: this.producto_id,
cantidad: this.cantidadControl, cantidad: this.cantidadControl,

View file

@ -103,9 +103,9 @@ const getters = {
}; };
case 'comisiones': case 'comisiones':
return { return {
fondo: "has-background-dark", fondo: "has-background-grey",
texto: "has-text-white", texto: "has-text-white",
botones: "is-white", botones: "danger-dark-button",
}; };
case 'ollas': case 'ollas':
return { return {

View file

@ -53,6 +53,7 @@ Route::middleware(['auth', 'role:comision'])->group( function() {
Route::get('/comisiones/pedidos/descargar', 'ComisionesController@descargarPedidos')->name('comisiones.pedidos.descargar'); Route::get('/comisiones/pedidos/descargar', 'ComisionesController@descargarPedidos')->name('comisiones.pedidos.descargar');
Route::get('/comisiones/pedidos/notas', 'ComisionesController@descargarNotas')->name('comisiones.pedidos.descargar'); Route::get('/comisiones/pedidos/notas', 'ComisionesController@descargarNotas')->name('comisiones.pedidos.descargar');
Route::get('/comisiones/pedidos/pdf', 'ComisionesController@pdf')->name('comisiones.pedidos.pdf'); Route::get('/comisiones/pedidos/pdf', 'ComisionesController@pdf')->name('comisiones.pedidos.pdf');
Route::get('/comisiones/pedidos/ollas', 'ComisionesController@descargarPedidosDeOllas')->name('comisiones.pedidos.ollas');
Route::get('/comisiones/canasta/ejemplo', 'ComisionesController@descargarCanastaEjemplo')->name('comisiones.canasta.ejemplo'); Route::get('/comisiones/canasta/ejemplo', 'ComisionesController@descargarCanastaEjemplo')->name('comisiones.canasta.ejemplo');
Route::post('/comisiones/canasta', 'ComisionesController@cargarCanasta')->name('comisiones.canasta'); Route::post('/comisiones/canasta', 'ComisionesController@cargarCanasta')->name('comisiones.canasta');
Route::post('/comisiones/saldos', 'ComisionesController@cargarSaldos')->name('comisiones.saldos'); Route::post('/comisiones/saldos', 'ComisionesController@cargarSaldos')->name('comisiones.saldos');