refactor(tickets): reuse dynamic columns in exports

This commit is contained in:
2026-08-31 12:31:32 -03:00
parent bda94d02af
commit 636e39e98e
4 changed files with 90 additions and 87 deletions

View File

@@ -6,6 +6,7 @@ use App\Domains\Tenant\Models\Tenant;
use App\Domains\Ticket\Models\Ticket;
use Carbon\CarbonInterface;
use Illuminate\Support\Collection;
use PhpOffice\PhpSpreadsheet\Cell\Coordinate;
use PhpOffice\PhpSpreadsheet\Cell\DataType;
use PhpOffice\PhpSpreadsheet\Shared\Date;
use PhpOffice\PhpSpreadsheet\Spreadsheet;
@@ -16,13 +17,17 @@ use Symfony\Component\HttpFoundation\StreamedResponse;
class AdminAppTicketExcelService
{
public function __construct(private readonly AdminAppTicketReportService $reportService) {}
public function __construct(
private readonly AdminAppTicketReportService $reportService,
private readonly AdminAppTicketColumnService $columnService,
) {}
/** @param Collection<int, Ticket> $tickets */
public function download(Tenant $tenant, Collection $tickets, string $timeZone): StreamedResponse
{
$generatedAt = now();
$rows = $this->reportService->rows($tickets);
$columns = $this->columnService->columns($tenant);
$spreadsheet = new Spreadsheet;
$spreadsheet->getProperties()
->setCreator('Shopit')
@@ -30,48 +35,52 @@ class AdminAppTicketExcelService
->setSubject($tenant->nombre);
$sheet = $spreadsheet->getActiveSheet();
$sheet->setTitle('Tickets');
$sheet->fromArray([
'N° de orden',
'Categoría',
'Producto',
'Tipo',
'Importe',
'Cliente',
'ID',
'Fecha',
'Estado',
'Escaneado por',
], null, 'A1');
$sheet->fromArray([array_column($columns, 'label')], null, 'A1');
foreach ($rows as $index => $ticket) {
$row = $index + 2;
$sheet->setCellValueExplicit(
"A{$row}",
$ticket['order_number'] === null ? '-' : '#'.$ticket['order_number'],
DataType::TYPE_STRING,
);
$sheet->setCellValueExplicit("B{$row}", $ticket['category'], DataType::TYPE_STRING);
$sheet->setCellValueExplicit("C{$row}", $ticket['product'], DataType::TYPE_STRING);
$sheet->setCellValueExplicit("D{$row}", $ticket['type'], DataType::TYPE_STRING);
if ($ticket['amount'] !== null) {
$sheet->setCellValue("E{$row}", $ticket['amount']);
}
$sheet->setCellValueExplicit("F{$row}", $ticket['client'], DataType::TYPE_STRING);
$sheet->setCellValueExplicit("G{$row}", $ticket['ticket'], DataType::TYPE_STRING);
if ($ticket['date'] instanceof CarbonInterface) {
$sheet->setCellValue(
"H{$row}",
Date::dateTimeToExcel($ticket['date']->copy()->timezone($timeZone)),
foreach ($columns as $columnIndex => $column) {
$coordinate = Coordinate::stringFromColumnIndex($columnIndex + 1).$row;
$value = $ticket[$column['key']] ?? null;
if ($column['type'] === 'currency' && $value !== null) {
$sheet->setCellValue($coordinate, (float) $value);
continue;
}
if ($column['type'] === 'date' && $value instanceof CarbonInterface) {
$sheet->setCellValue(
$coordinate,
Date::dateTimeToExcel($value->copy()->timezone($timeZone)),
);
continue;
}
$sheet->setCellValueExplicit(
$coordinate,
$this->reportService->displayValue($value, $column['type'], $timeZone),
DataType::TYPE_STRING,
);
}
$sheet->setCellValueExplicit("I{$row}", $ticket['status'], DataType::TYPE_STRING);
$sheet->setCellValueExplicit("J{$row}", $ticket['scanned_by'], DataType::TYPE_STRING);
}
$lastRow = max(2, $rows->count() + 1);
$sheet->getStyle("E2:E{$lastRow}")->getNumberFormat()->setFormatCode('$ #,##0.00');
$sheet->getStyle("H2:H{$lastRow}")->getNumberFormat()->setFormatCode('dd/mm/yyyy hh:mm');
$sheet->getStyle('A1:J1')->applyFromArray([
$lastColumn = Coordinate::stringFromColumnIndex(count($columns));
foreach ($columns as $columnIndex => $column) {
$letter = Coordinate::stringFromColumnIndex($columnIndex + 1);
if ($column['type'] === 'currency') {
$sheet->getStyle("{$letter}2:{$letter}{$lastRow}")
->getNumberFormat()->setFormatCode('$ #,##0.00');
}
if ($column['type'] === 'date') {
$sheet->getStyle("{$letter}2:{$letter}{$lastRow}")
->getNumberFormat()->setFormatCode('dd/mm/yyyy hh:mm');
}
$sheet->getColumnDimension($letter)->setWidth($column['excel_width']);
}
$sheet->getStyle("A1:{$lastColumn}1")->applyFromArray([
'font' => ['bold' => true, 'color' => ['rgb' => 'FFFFFF']],
'fill' => [
'fillType' => Fill::FILL_SOLID,
@@ -81,14 +90,7 @@ class AdminAppTicketExcelService
]);
$sheet->getRowDimension(1)->setRowHeight(24);
$sheet->freezePane('A2');
$sheet->setAutoFilter("A1:J{$lastRow}");
foreach ([
'A' => 14, 'B' => 18, 'C' => 22, 'D' => 18, 'E' => 15,
'F' => 30, 'G' => 39, 'H' => 20, 'I' => 13, 'J' => 28,
] as $column => $width) {
$sheet->getColumnDimension($column)->setWidth($width);
}
$sheet->setAutoFilter("A1:{$lastColumn}{$lastRow}");
$filename = 'tickets_'.$tenant->codigo.'_'
.$generatedAt->copy()->timezone($timeZone)->format('Ymd_His').'.xlsx';

View File

@@ -11,15 +11,21 @@ use Illuminate\Support\Collection;
class AdminAppTicketPdfService
{
public function __construct(private readonly AdminAppTicketReportService $reportService) {}
public function __construct(
private readonly AdminAppTicketReportService $reportService,
private readonly AdminAppTicketColumnService $columnService,
) {}
/** @param Collection<int, Ticket> $tickets */
public function download(Tenant $tenant, Collection $tickets, string $timeZone): Response
{
$generatedAt = now();
$columns = $this->columnService->columns($tenant);
$rows = $this->reportService->rows($tickets);
$pdf = Pdf::loadView('pdf.adminapp.tickets', [
'tenant' => $tenant,
'tickets' => $this->reportService->rows($tickets),
'columns' => $columns,
'tickets' => $this->reportService->displayRows($rows, $columns, $timeZone),
'generatedAt' => $generatedAt,
'timeZone' => $timeZone,
])->setPaper('a3', 'landscape');