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.
184 lines
6.5 KiB
PHP
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);
|
|
}
|
|
}
|
|
}
|