<?php declare(strict_types=1); namespace App\Exports; use App\Domain\Payment\Enums\PaymentTypeEnum; use App\Models\Payment; use App\Models\PaymentDistribution; use Illuminate\Database\Eloquent\Builder; use Maatwebsite\Excel\Concerns\FromCollection; use Maatwebsite\Excel\Concerns\WithEvents; use Maatwebsite\Excel\Concerns\WithHeadings; use Maatwebsite\Excel\Events\AfterSheet; class PaymentsExport implements FromCollection, WithHeadings, WithEvents { private mixed $minDate; private mixed $maxDate; private float $totalSum = 0; public function __construct(public Builder $source, public array $projectIds) { /**/ $this->minDate = $this->source->min('payment_date'); $this->maxDate = $this->source->max('payment_date'); } public function collection() { $result = []; $this->totalSum = 0; /** @var Payment $source */ $this->source->with([ 'distributions.project', 'distributions.article', 'creator', 'contragent', 'account' ])->each(function ($source) use (&$result): void { /** @var PaymentDistribution $distr */ $distr = $source->distributions()->whereIn('project_id', $this->projectIds)->first(); $typeSymbol = match ($source->payment_type) { PaymentTypeEnum::PAYMENT_TYPE_RECEPTION->value => '↓', PaymentTypeEnum::PAYMENT_TYPE_PAYMENT->value => '→', PaymentTypeEnum::PAYMENT_TYPE_ISSUEANCE->value => '↑', PaymentTypeEnum::PAYMENT_TYPE_MOVING->value => '↔', default => '', // fallback }; $this->totalSum += $source->amount; /** @var Payment $source */ $result[] = [ $source->payment_date, $typeSymbol, $source->name, $source->amount, $source->contragent->name, $distr?->project->short_description ?? '', $distr?->article->name ?? '', ($source->creator->first_name ?? '') . ' ' . ($source->creator->last_name ?? ''), $source->id, PaymentTypeEnum::getList()[$source->payment_type]['label'], $source->account->name ?? '', ]; }); return collect($result); } public function headings(): array { return [ 'Дата', ' ', 'Название', 'Сумма', 'Контрагент', 'Проект', 'Статья', 'Заявитель', 'ID', 'Тип платежа', 'Счет', ]; } public function registerEvents(): array { return [ AfterSheet::class => function (AfterSheet $event): void { $sheet = $event->sheet->getDelegate(); // Вставляем 3 строки сверху $sheet->insertNewRowBefore(1, 3); // Добавим заголовок отчета $sheet->setCellValue('B2', 'Оплаченные платежи СМР ГИТЭП'); $sheet->getStyle('B2')->getFont()->setSize(18); $sheet->setCellValue('B3', 'За период:'); $sheet->getStyle('B3')->getFont()->getColor()->setRGB('808080'); $sheet->setCellValue('C3', $this->minDate . ' - ' . $this->maxDate); $sheet->getStyle('C3')->getFont()->setBold(true); $sheet->setCellValue('D2', 'Всего:'); $sheet->getStyle('D2')->getFont()->getColor()->setRGB('808080'); $sheet->setCellValue('D3', $this->totalSum); $sheet->getStyle('D3')->getFont()->setBold(true); $sheet->getStyle('D3')->getNumberFormat()->setFormatCode('#,##0.00'); // Закрепить строку с заголовками $event->sheet->freezePane('A6'); $event->sheet->getStyle('D')->getNumberFormat()->setFormatCode('#,##0.00'); // Включить автофильтр на строке с заголовками (A4:K4) $sheet->setAutoFilter('A5:K5'); // Автоширина надо ли foreach (range('C', 'K') as $column) { $sheet->getColumnDimension($column)->setAutoSize(true); } $event->sheet->freezePane('E5'); }, ]; } }