'decimal:2', 'shipment_value' => 'decimal:2', 'weight' => 'decimal:2', ]; public function items() { return $this->hasMany(ShipmentRequestItem::class, 'shipment_request_id'); } public function shipment() { return $this->hasOne(Shipment::class, 'shipment_request_id'); } protected $appends = ['delivery_address']; /** * Accessor to get the delivery address as an array. * * @return array */ public function getDeliveryAddressAttribute() { return [ 'name' => $this->delivery_address_name, 'companyName' => $this->delivery_address_company_name, 'streetName' => $this->delivery_address_street_name, 'streetNumber' => $this->delivery_address_street_number, 'addressLine2' => $this->delivery_address_address_line_2, 'city' => $this->delivery_address_city, 'zip' => $this->delivery_address_zip, 'stateISO' => $this->delivery_address_state_iso, 'countryISO' => $this->delivery_address_country_iso, ]; } public function carrier() { return $this->belongsTo(Carrier::class, 'carrier_id'); } public function user() { return $this->belongsTo(User::class, 'user_id'); } public function invoice() { return $this->hasOne(ShipmentRequestInvoice::class, 'shipment_request_id'); } public function batchItem() { return $this->hasOne(ShipmentRequestBatchItem::class, 'shipment_request_id'); } public function batch() { return $this->hasOneThrough( ShipmentRequestBatch::class, ShipmentRequestBatchItem::class, 'shipment_request_id', // Foreign key on ShipmentRequestBatchItem table 'id', // Foreign key on ShipmentRequestBatch table 'id', // Local key on ShipmentRequest table 'shipment_request_batch_id' // Local key on ShipmentRequestBatchItem table ); } public function errors() { return $this->hasMany(ShipmentErrorLog::class, 'shipment_request_id'); } public function unresolvedErrors() { return $this->hasMany(ShipmentErrorLog::class)->where('resolved', false); } public function shipmentStatuses() { return $this->hasMany(ShipmentStatusHistory::class, 'shipment_request_id'); } public function currentShipmentStatus() { return $this->hasOne(ShipmentStatusHistory::class, 'shipment_request_id') ->latestOfMany(); // This ensures only the latest record is returned. } protected static function booted() { parent::boot(); // Handle saving events for both updates and first saves static::saving(function ($shipmentRequest) { $callbackService = App::make(CallbackService::class); // Check if the user has an API callback URL and callbacks are enabled if ($shipmentRequest->user->details->apiCallbackURL && $shipmentRequest->user->details->callbacks_enabled) { // Check if the model is being created (i.e., a first-time save) if ($shipmentRequest->isDirty() && !$shipmentRequest->exists) { ActionLog::create([ 'name' => "shipment_request_created", 'description' => "Shipment accepted to APP, reference no: '{$shipmentRequest->shipment_reference}'", 'user_id' => $shipmentRequest->user->id, 'shipment_request_id' => $shipmentRequest->id ]); $callbackService->sendCallback($shipmentRequest->user->details->apiCallbackURL, [ 'endpoint' => 'shipmentRequestCreated', 'result' => 'true', 'shipment_reference' => $shipmentRequest->shipment_reference, 'data' => [ 'createdFields' => $shipmentRequest->getAttributes(), // Fields that were initially set ], 'additionalInfo' => null ]); } // Check if the model is being updated else { ActionLog::create([ 'name' => "shipment_request_updated", 'description' => "Shipment updated, reference no: '{$shipmentRequest->shipment_reference}', changes: '" . var_export($shipmentRequest->getDirty(), true), 'user_id' => Auth::user()->id ?? 1, 'shipment_request_id' => $shipmentRequest->id ]); Log::channel('expedice')->info('Shipment updated by ' . (Auth::user()->name ?? '///'), [ 'shipment_request_id' => $shipmentRequest->id, 'changes' => $shipmentRequest->getDirty(), ]); $callbackService->sendCallback($shipmentRequest->user->details->apiCallbackURL, [ 'endpoint' => 'shipmentRequestUpdated', 'result' => 'true', 'shipment_reference' => $shipmentRequest->shipment_reference, 'data' => [ 'updatedFields' => $shipmentRequest->getDirty(), // Fields that were changed ], 'additionalInfo' => null ]); } } }); } public function createStorageRemovalEntries() { foreach ($this->items as $item) { // Check if an entry already exists $exists = ItemsStorageRemoval::where('shipment_request_item_id', $item->id)->exists(); // If it doesn't exist, create a new entry if (!$exists) { ItemsStorageRemoval::create([ 'shipment_request_item_id' => $item->id, 'entry_processed' => false, // Default value ]); } } } }