/var/www/html/back/app/Exports/PaymentsExport.php
<?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');
},
];
}
}