File "PaymentsExport.php"

Full Path: /var/www/html/back/app/Exports/PaymentsExport.php
File size: 4.5 KB
MIME-type: text/x-php
Charset: utf-8

<?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');
            },
        ];
    }
}