ifnex/04_Laravel/app/Http/Controllers/ShipmentPdfController.php
Kazem Alghasi 02c29db696 feat(core): implement order approval flow, credit system, and import invoicing
Introduce a comprehensive set of commercial features including a multi-step
order approval workflow, customer credit management, and specialized
import service invoicing.

Key changes:
- Implement `pending_approval` and `approved` shipment statuses to allow
  staff verification before customer payment.
- Add a credit system to `User` model with `credit_limit` and `credit_used`
  to manage customer balances and debts.
- Develop a new `importInvoice` PDF generation service following the
  "Sheet ENG Invoice" specification for import services.
- Add Filament resources for managing Audit Logs, Commitment Forms,
  Customer Credits, and Shipment Checklists.
- Implement staff-specific APIs for order approval/rejection and
  customer financial status monitoring.
- Integrate Kavenegar SMS service for mobile verification and notifications.
- Add bulk tracking import functionality via CSV/Excel.
- Update WordPress bridge assets (CSS/JS) to support the new multi-step
  order form UI and updated redirection logic.
- Update deployment configurations and documentation to reflect new
  production domains and feature sets.
2026-09-03 06:04:20 +03:30

184 lines
6.5 KiB
PHP

<?php
namespace App\Http\Controllers;
use App\Enums\ShipmentType;
use App\Models\Shipment;
use App\Services\PdfService;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Log;
class ShipmentPdfController extends Controller
{
public function __construct(protected PdfService $pdf) {}
/**
* تولید AWB PDF (برای همه نوع محموله‌ها)
*/
public function awb(Shipment $shipment)
{
try {
Log::info('Generating AWB PDF', ['shipment_id' => $shipment->id]);
$content = $this->pdf->awb($shipment);
Log::info('AWB PDF generated successfully', ['awb' => $shipment->awb_no]);
return response($content, 200, [
'Content-Type' => 'application/pdf',
'Content-Disposition' => 'attachment; filename="AWB-' . $shipment->awb_no . '.pdf"',
]);
} catch (\Throwable $e) {
Log::error('AWB PDF generation failed', [
'shipment_id' => $shipment->id,
'error' => $e->getMessage(),
'trace' => $e->getTraceAsString(),
]);
return response('PDF generation failed: ' . $e->getMessage(), 500);
}
}
/**
* تولید Invoice PDF — فقط برای محموله‌های دارای کالا (PARCEL)
*
* محموله‌های DOC (DOC_NORMAL/DOC_ECONOMY) که کالا ندارن،
* فاکتور صادراتی ندارن و این متد براشون ارور برمی‌گردونه.
*/
public function invoice(Shipment $shipment)
{
try {
// بارگذاری items برای بررسی
$shipment->loadMissing(['items']);
// بررسی نوع محموله
$isDocType = in_array($shipment->type, [
ShipmentType::DocNormal,
ShipmentType::DocEconomy,
]);
if ($isDocType && $shipment->items->isEmpty()) {
Log::info('Invoice PDF not available for DOC shipment without items', [
'shipment_id' => $shipment->id,
'type' => $shipment->type?->value,
]);
return response()->json([
'success' => false,
'message' => 'فاکتور فقط برای محموله‌های دارای کالا (PARCEL) صادر می‌شود.',
'hint' => 'محموله‌های DOC (مدارک) فاکتور صادراتی ندارند.',
], 400);
}
$content = $this->pdf->invoice($shipment);
Log::info('Invoice PDF generated successfully', [
'awb' => $shipment->awb_no,
'type' => $shipment->type?->value,
'items_count' => $shipment->items->count(),
]);
return response($content, 200, [
'Content-Type' => 'application/pdf',
'Content-Disposition' => 'attachment; filename="INVOICE-' . $shipment->awb_no . '.pdf"',
]);
} catch (\InvalidArgumentException $e) {
// خطای مربوط به نوع محموله
Log::info('Invoice PDF skipped', [
'shipment_id' => $shipment->id,
'reason' => $e->getMessage(),
]);
return response()->json([
'success' => false,
'message' => $e->getMessage(),
], 400);
} catch (\Throwable $e) {
Log::error('Invoice PDF generation failed', [
'shipment_id' => $shipment->id,
'error' => $e->getMessage(),
'trace' => $e->getTraceAsString(),
]);
return response('PDF generation failed: ' . $e->getMessage(), 500);
}
}
/**
* تولید Label PDF — اندازه استاندارد لیبل پستی (100x150mm)
*/
public function label(Shipment $shipment)
{
try {
$content = $this->pdf->label($shipment);
Log::info('Label PDF generated successfully', ['awb' => $shipment->awb_no]);
return response($content, 200, [
'Content-Type' => 'application/pdf',
'Content-Disposition' => 'attachment; filename="LABEL-' . $shipment->awb_no . '.pdf"',
]);
} catch (\Throwable $e) {
Log::error('Label PDF generation failed', [
'shipment_id' => $shipment->id,
'error' => $e->getMessage(),
'trace' => $e->getTraceAsString(),
]);
return response('PDF generation failed: ' . $e->getMessage(), 500);
}
}
/**
* تولید PDF فاکتور فروش خدمات (واردات) — مطابق Sheet ENG Invoice
*/
public function importInvoice(Shipment $shipment, Request $request)
{
try {
// دریافت پارامترها از درخواست
$options = $request->only([
'invoice_no',
'invoice_date',
'customs_office',
'exchange_rate',
'international_freight',
'pick_up_fee',
'brand_fee',
'report_fee',
'other_charges',
'customs_clearance',
'domestic_transport',
'warehousing_fee',
'order_registration_fee',
'other_clearance_charges',
'terms_and_conditions',
]);
// تبدیل exchange_rate به عدد
if (isset($options['exchange_rate'])) {
$options['exchange_rate'] = (float) $options['exchange_rate'];
}
$content = $this->pdf->importInvoice($shipment, $options);
Log::info('Import Invoice PDF generated successfully', [
'awb' => $shipment->awb_no,
'options' => $options,
]);
return response($content, 200, [
'Content-Type' => 'application/pdf',
'Content-Disposition' => 'attachment; filename="SERVICE-INVOICE-' . $shipment->awb_no . '.pdf"',
]);
} catch (\Throwable $e) {
Log::error('Import Invoice PDF generation failed', [
'shipment_id' => $shipment->id,
'error' => $e->getMessage(),
'trace' => $e->getTraceAsString(),
]);
return response('PDF generation failed: ' . $e->getMessage(), 500);
}
}
}