ifnex/04_Laravel/app/Imports/ShippingRatesImport.php

212 lines
6.1 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?php
namespace App\Imports;
use App\Enums\ShipmentType;
use App\Models\ShippingRate;
use App\Models\SystemSetting;
use Maatwebsite\Excel\Concerns\OnEachRow;
use Maatwebsite\Excel\Concerns\WithMultipleSheets;
use Maatwebsite\Excel\Concerns\WithStartRow;
use Maatwebsite\Excel\Row;
class ShippingRatesImport implements WithMultipleSheets
{
/**
* تعریف شیت‌های مختلف فایل اکسل و کلاس‌های پردازش‌گر مربوطه
*/
public function sheets(): array
{
return [
'Export Rate' => new RateSheetImport('export'),
'Import Rate' => new RateSheetImport('import'),
'DocEco' => new SimpleRateSheetImport(ShipmentType::DocEconomy, 'export'),
];
}
}
/**
* کلاس برای پردازش شیت‌های استاندارد نرخ‌ها (Export Rate و Import Rate)
*/
class RateSheetImport implements OnEachRow, WithStartRow
{
protected int $imported = 0;
protected int $skipped = 0;
protected array $errors = [];
public function __construct(protected string $direction) {}
/**
* شروع خواندن از ردیف ۵ (۴ ردیف اول هدر هستند)
*/
public function startRow(): int
{
return 5;
}
/**
* پردازش هر ردیف از شیت
*/
public function onRow(Row $row)
{
$rowIndex = $row->getIndex();
$cells = $row->toArray();
// بررسی اعتبار ستون وزن (ستون اول)
if (empty($cells[0]) || !is_numeric($cells[0])) {
$this->skipped++;
return;
}
try {
// تشخیص نوع سرویس (Doc یا Parcel)
$type = $this->resolveType($rowIndex, $cells);
// استخراج و نرمال‌سازی قیمت‌های ۱۰ زون
$zones = [];
for ($i = 1; $i <= 10; $i++) {
$val = str_replace([',', ' '], '', (string) ($cells[$i] ?? 0));
$zones['zone_' . $i] = is_numeric($val) ? (float) $val : 0;
}
// ثبت یا به‌روزرسانی نرخ در دیتابیس
ShippingRate::updateOrCreate(
[
'direction' => $this->direction,
'type' => $type->value,
'weight' => (float) $cells[0],
],
$zones
);
$this->imported++;
} catch (\Throwable $e) {
$this->errors[] = "Row $rowIndex: " . $e->getMessage();
$this->skipped++;
}
}
/**
* دریافت آمار عملیات ایمپورت
*/
public function getStats(): array
{
return [
'imported' => $this->imported,
'skipped' => $this->skipped,
'errors' => $this->errors,
];
}
/**
* تشخیص نوع سرویس بر اساس محتوای ردیف
*/
private function resolveType(int $rowIndex, array $cells): ShipmentType
{
$header = strtoupper((string) ($cells[3] ?? ''));
if (str_contains($header, 'DOCUMENT') || str_contains($header, 'DOC')) {
return ShipmentType::DocNormal;
}
if (str_contains($header, 'NON') || str_contains($header, 'PARCEL')) {
return ShipmentType::Parcel;
}
// اگر نوع مشخص نبود، بر اساس شماره ردیف حدس می‌زنیم
return $rowIndex < 10 ? ShipmentType::DocNormal : ShipmentType::Parcel;
}
}
/**
* کلاس برای پردازش شیت ساده‌تر نرخ‌ها (DocEco)
*/
class SimpleRateSheetImport implements OnEachRow, WithStartRow
{
protected int $imported = 0;
protected int $skipped = 0;
protected array $errors = [];
public function __construct(
protected ShipmentType $type,
protected string $direction = 'export'
) {}
/**
* شروع خواندن از ردیف ۲ (۱ ردیف اول هدر است)
*/
public function startRow(): int
{
return 2;
}
/**
* پردازش هر ردیف از شیت
*/
public function onRow(Row $row)
{
$cells = $row->toArray();
// بررسی اعتبار ستون وزن (ستون اول)
if (empty($cells[0]) || !is_numeric($cells[0])) {
$this->skipped++;
return;
}
try {
$weight = (float) $cells[0];
$zoneNumber = (int) $cells[1];
$rawValue = str_replace([',', ' '], '', (string) ($cells[2] ?? 0));
$rawValue = is_numeric($rawValue) ? (float) $rawValue : 0;
// بررسی اعتبار شماره زون و قیمت
if ($zoneNumber < 1 || $zoneNumber > 10 || $rawValue <= 0) {
$this->skipped++;
return;
}
// تبدیل قیمت از AED به IRR
$aedToIrr = (float) SystemSetting::get('aed_to_irr', 455000);
$value = $aedToIrr > 0 ? $rawValue / $aedToIrr : $rawValue;
$zoneColumn = 'zone_' . $zoneNumber;
// ایجاد مقادیر پیش‌فرض برای زون‌ها
$defaults = [];
for ($i = 1; $i <= 10; $i++) {
$defaults['zone_' . $i] = 0;
}
// یافتن یا ایجاد رکورد و به‌روزرسانی قیمت زون
$record = ShippingRate::firstOrCreate(
[
'direction' => $this->direction,
'type' => $this->type->value,
'weight' => $weight,
],
$defaults
);
$record->{$zoneColumn} = $value;
$record->save();
$this->imported++;
} catch (\Throwable $e) {
$this->errors[] = "Row " . $row->getIndex() . ": " . $e->getMessage();
$this->skipped++;
}
}
/**
* دریافت آمار عملیات ایمپورت
*/
public function getStats(): array
{
return [
'imported' => $this->imported,
'skipped' => $this->skipped,
'errors' => $this->errors,
];
}
}