161 lines
4.3 KiB
PHP
161 lines
4.3 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 ClientContractsExport 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' => 'Referenca'],
|
|
'customer' => ['label' => 'Stranka'],
|
|
'address' => ['label' => 'Naslov'],
|
|
'start' => ['label' => 'Začetek'],
|
|
'segment' => ['label' => 'Segment'],
|
|
'balance' => ['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 ($column === 'start') {
|
|
$formats[$letter] = self::DATE_EXCEL_FORMAT;
|
|
}
|
|
}
|
|
|
|
return $formats;
|
|
}
|
|
|
|
private function resolveValue(Contract $contract, string $column): mixed
|
|
{
|
|
return match ($column) {
|
|
'reference' => $contract->reference,
|
|
'customer' => optional($contract->clientCase?->person)->full_name,
|
|
'address' => optional($contract->clientCase?->person?->address)->address,
|
|
'start' => $this->formatDate($contract->start_date),
|
|
'segment' => $contract->segments?->first()?->name,
|
|
'balance' => optional($contract->account)->balance_amount,
|
|
default => null,
|
|
};
|
|
}
|
|
|
|
private function formatDate(?string $date): mixed
|
|
{
|
|
if (empty($date)) {
|
|
return null;
|
|
}
|
|
|
|
try {
|
|
$carbon = Carbon::parse($date);
|
|
|
|
return ExcelDate::dateTimeToExcel($carbon);
|
|
} catch (\Exception $e) {
|
|
return null;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @return array<string, string>
|
|
*/
|
|
private function getColumnLetterMap(): array
|
|
{
|
|
if ($this->columnLetterMap !== []) {
|
|
return $this->columnLetterMap;
|
|
}
|
|
|
|
$letter = 'A';
|
|
foreach ($this->columns as $column) {
|
|
$this->columnLetterMap[$letter] = $column;
|
|
$letter++;
|
|
}
|
|
|
|
return $this->columnLetterMap;
|
|
}
|
|
|
|
public function bindValue(Cell $cell, $value): bool
|
|
{
|
|
if (is_numeric($value)) {
|
|
$cell->setValueExplicit($value, DataType::TYPE_NUMERIC);
|
|
|
|
return true;
|
|
}
|
|
|
|
return parent::bindValue($cell, $value);
|
|
}
|
|
}
|