ifnex/04_Laravel/app/Http/Controllers/Api/PricingController.php
Kazem Alghasi 563f89495c fix(pricing): restore array-based calculate() and harden pricing API
Restore the array-based signature of PriceCalculatorService::calculate()
to fix the TypeError thrown when PricingController and CustomerOrderController
called it with an array (the previous commit had switched to 4 separate
string params without updating the callers).

- PriceCalculatorService: support multiple input formats for direction
  (export|import|Outbound|Inbound) and type (DOC_NORMAL|DOC_ECONOMY|PARCEL|
  DOCUMENT|NON DOC) for backward compatibility with admin and customer flows.
- ExchangeRateService: add convertToIrr() for explicit AED→IRR conversion
  (was missing but referenced by the calculator).
- PricingController: expand validation rules to accept new shipment types
  and a discount_code string (was 'discount' numeric). Add 3-layer exception
  handling (422 validation / 400 business / 500 server).
- PriceTestPage: compute volumetric weight from dimensions (IATA: L×W×H/5000),
  resolve destination country by direction, and show errors as Filament
  notifications instead of crashing.
2026-10-29 14:40:58 +03:30

60 lines
2.3 KiB
PHP

<?php
namespace App\Http\Controllers\Api;
use App\Services\PriceCalculatorService;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Validation\ValidationException;
class PricingController
{
public function __construct(protected PriceCalculatorService $calculator) {}
public function calculate(Request $request): JsonResponse
{
try {
$validated = $request->validate([
'direction' => ['required', 'string', 'in:Outbound,Inbound,export,import'],
'type' => ['required', 'string', 'in:DOC_NORMAL,DOC_ECONOMY,PARCEL,DOCUMENT,NON DOC'],
'country_iso' => ['required', 'string', 'size:2'],
'weight' => ['required', 'numeric', 'min:0'],
'volumetric_weight' => ['required', 'numeric', 'min:0'],
'extra_service' => ['nullable', 'numeric', 'min:0'],
'packing_cost' => ['nullable', 'numeric', 'min:0'],
'domestic_pickup' => ['nullable', 'numeric', 'min:0'],
'domestic_delivery' => ['nullable', 'numeric', 'min:0'],
'warehousing_cost' => ['nullable', 'numeric', 'min:0'],
'discount_code' => ['nullable', 'string', 'max:50'],
]);
} catch (ValidationException $e) {
return response()->json([
'success' => false,
'message' => 'Validation failed',
'errors' => $e->errors(),
], 422);
}
try {
$result = $this->calculator->calculate($validated);
return response()->json($result);
} catch (\InvalidArgumentException $e) {
return response()->json([
'success' => false,
'message' => $e->getMessage(),
], 422);
} catch (\RuntimeException $e) {
// خطاهای «زون یافت نشد» یا «نرخ یافت نشد» — خطای کسب‌وکار، نه سرور
return response()->json([
'success' => false,
'message' => $e->getMessage(),
], 400);
} catch (\Throwable $e) {
report($e);
return response()->json([
'success' => false,
'message' => 'خطای داخلی سرور هنگام محاسبه قیمت.',
], 500);
}
}
}