pedi2/app/Helpers/PedidosExportHelper.php

219 lines
6.9 KiB
PHP

<?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;
}
}