171 lines
4.7 KiB
PHP
171 lines
4.7 KiB
PHP
<?php
|
|
|
|
namespace App\Exports;
|
|
|
|
use App\Models\Contract;
|
|
use Illuminate\Database\Eloquent\Builder;
|
|
use Illuminate\Support\Carbon;
|
|
use Maatwebsite\Excel\Concerns\FromQuery;
|
|
use Maatwebsite\Excel\Concerns\ShouldAutoSize;
|
|
use Maatwebsite\Excel\Concerns\WithColumnFormatting;
|
|
use Maatwebsite\Excel\Concerns\WithCustomValueBinder;
|
|
use Maatwebsite\Excel\Concerns\WithHeadings;
|
|
use Maatwebsite\Excel\Concerns\WithMapping;
|
|
use PhpOffice\PhpSpreadsheet\Cell\Cell;
|
|
use PhpOffice\PhpSpreadsheet\Cell\DataType;
|
|
use PhpOffice\PhpSpreadsheet\Cell\DefaultValueBinder;
|
|
use PhpOffice\PhpSpreadsheet\Shared\Date as ExcelDate;
|
|
use PhpOffice\PhpSpreadsheet\Style\NumberFormat;
|
|
|
|
class SegmentContractsExport extends DefaultValueBinder implements FromQuery, ShouldAutoSize, WithColumnFormatting, WithCustomValueBinder, WithHeadings, WithMapping
|
|
{
|
|
public const DATE_EXCEL_FORMAT = 'dd"."mm"."yyyy';
|
|
|
|
public const TEXT_EXCEL_FORMAT = NumberFormat::FORMAT_TEXT;
|
|
|
|
/**
|
|
* @var array<string, string>
|
|
*/
|
|
private array $columnLetterMap = [];
|
|
|
|
/**
|
|
* @var array<string, array{label: string}>
|
|
*/
|
|
public const COLUMN_METADATA = [
|
|
'reference' => ['label' => 'Pogodba'],
|
|
'client_case' => ['label' => 'Primer'],
|
|
'client' => ['label' => 'Stranka'],
|
|
'type' => ['label' => 'Vrsta'],
|
|
'start_date' => ['label' => 'Začetek'],
|
|
'end_date' => ['label' => 'Konec'],
|
|
'account' => ['label' => 'Stanje'],
|
|
];
|
|
|
|
/**
|
|
* @param array<int, string> $columns
|
|
*/
|
|
public function __construct(private Builder $query, private array $columns) {}
|
|
|
|
/**
|
|
* @return array<int, string>
|
|
*/
|
|
public static function allowedColumns(): array
|
|
{
|
|
return array_keys(self::COLUMN_METADATA);
|
|
}
|
|
|
|
public static function columnLabel(string $column): string
|
|
{
|
|
return self::COLUMN_METADATA[$column]['label'] ?? $column;
|
|
}
|
|
|
|
public function query(): Builder
|
|
{
|
|
return $this->query;
|
|
}
|
|
|
|
/**
|
|
* @return array<int, mixed>
|
|
*/
|
|
public function map($row): array
|
|
{
|
|
return array_map(fn (string $column) => $this->resolveValue($row, $column), $this->columns);
|
|
}
|
|
|
|
/**
|
|
* @return array<int, string>
|
|
*/
|
|
public function headings(): array
|
|
{
|
|
return array_map(fn (string $column) => self::columnLabel($column), $this->columns);
|
|
}
|
|
|
|
/**
|
|
* @return array<string, string>
|
|
*/
|
|
public function columnFormats(): array
|
|
{
|
|
$formats = [];
|
|
|
|
foreach ($this->getColumnLetterMap() as $letter => $column) {
|
|
if ($column === 'reference') {
|
|
$formats[$letter] = self::TEXT_EXCEL_FORMAT;
|
|
|
|
continue;
|
|
}
|
|
|
|
if (in_array($column, ['start_date', 'end_date'], true)) {
|
|
$formats[$letter] = self::DATE_EXCEL_FORMAT;
|
|
}
|
|
}
|
|
|
|
return $formats;
|
|
}
|
|
|
|
private function resolveValue(Contract $contract, string $column): mixed
|
|
{
|
|
return match ($column) {
|
|
'reference' => $contract->reference,
|
|
'client_case' => optional($contract->clientCase?->person)->full_name,
|
|
'client' => optional($contract->clientCase?->client?->person)->full_name,
|
|
'type' => optional($contract->type)->name,
|
|
'start_date' => $this->formatDate($contract->start_date),
|
|
'end_date' => $this->formatDate($contract->end_date),
|
|
'account' => optional($contract->account)->balance_amount,
|
|
default => null,
|
|
};
|
|
}
|
|
|
|
private function formatDate(mixed $value): ?float
|
|
{
|
|
$carbon = Carbon::make($value);
|
|
|
|
if (! $carbon) {
|
|
return null;
|
|
}
|
|
|
|
return ExcelDate::dateTimeToExcel($carbon->copy()->startOfDay());
|
|
}
|
|
|
|
private function columnLetter(int $index): string
|
|
{
|
|
$index++;
|
|
$letter = '';
|
|
|
|
while ($index > 0) {
|
|
$remainder = ($index - 1) % 26;
|
|
$letter = chr(65 + $remainder).$letter;
|
|
$index = intdiv($index - 1, 26);
|
|
}
|
|
|
|
return $letter;
|
|
}
|
|
|
|
public function bindValue(Cell $cell, $value): bool
|
|
{
|
|
$columnKey = $this->getColumnLetterMap()[$cell->getColumn()] ?? null;
|
|
|
|
if ($columnKey === 'reference') {
|
|
$cell->setValueExplicit((string) $value, DataType::TYPE_STRING);
|
|
|
|
return true;
|
|
}
|
|
|
|
return parent::bindValue($cell, $value);
|
|
}
|
|
|
|
/**
|
|
* @return array<string, string>
|
|
*/
|
|
private function getColumnLetterMap(): array
|
|
{
|
|
if ($this->columnLetterMap === []) {
|
|
foreach ($this->columns as $index => $column) {
|
|
$this->columnLetterMap[$this->columnLetter($index)] = $column;
|
|
}
|
|
}
|
|
|
|
return $this->columnLetterMap;
|
|
}
|
|
}
|