From 124ab46507ddb8764dd0a61d6994dfc72e7843bd Mon Sep 17 00:00:00 2001 From: twotalesanimation <80506065+twotalesanimation@users.noreply.github.com> Date: Fri, 2 Jan 2026 21:40:16 +0200 Subject: [PATCH] refactor: Split shipping_address into component fields for ShipLogic API - Create migration to add shipping_street_address, shipping_local_area, shipping_city, shipping_zone, shipping_country, shipping_postcode, shipping_type - Update Order model fillable array with new address component fields - Remove address parsing logic from CourierService - Use individual address fields directly in ShipLogic API payload - Fields match ShipLogic API requirements (street_address, local_area, city, zone, code, country, type) - Note: Custom orders address collection can be implemented later --- app/Models/Order.php | 7 + app/Services/CourierService.php | 71 +- ...split_shipping_address_into_components.php | 43 + .../adc4c4a369b2bee1705d8da3a6247c45.php | 793 ++++++++++++++++++ 4 files changed, 905 insertions(+), 9 deletions(-) create mode 100644 database/migrations/2026_01_02_000003_split_shipping_address_into_components.php create mode 100644 storage/framework/views/adc4c4a369b2bee1705d8da3a6247c45.php diff --git a/app/Models/Order.php b/app/Models/Order.php index 4515d72..a70f23b 100644 --- a/app/Models/Order.php +++ b/app/Models/Order.php @@ -26,6 +26,13 @@ class Order extends Model 'customer_email', 'customer_phone', 'shipping_address', + 'shipping_street_address', + 'shipping_local_area', + 'shipping_city', + 'shipping_zone', + 'shipping_country', + 'shipping_postcode', + 'shipping_type', 'notes', 'yoco_checkout_id', 'yoco_redirect_url', diff --git a/app/Services/CourierService.php b/app/Services/CourierService.php index 4ad6ffb..0825dc0 100644 --- a/app/Services/CourierService.php +++ b/app/Services/CourierService.php @@ -115,26 +115,70 @@ class CourierService } try { + // Fetch order to get customer and shipping details + $order = Order::findOrFail($orderId); + + // Validate required shipping info + if (! $order->customer_name || ! $order->shipping_street_address) { + throw new \Exception('Order missing required customer name or shipping address'); + } + + if (! $order->customer_email && ! $order->customer_phone) { + throw new \Exception('Order must have at least email or phone number'); + } + // Build shipment payload for Shiplogic $payload = [ - 'parcel' => [ - 'weight' => $weight, - 'height' => 10, // TODO: Update when height is captured separately - 'width' => $width, - 'length' => $length, + 'collection_address' => [ + 'street' => 'Two Tales Designs', // TODO: Get from AppSetting + 'city' => 'Cape Town', + 'postcode' => '8000', + 'country' => 'ZA', ], - 'destination' => [ - // TODO: Get from order's shipping address + 'collection_contact' => [ + 'email' => config('mail.from.address'), + 'mobile_number' => '+27000000000', // TODO: Get from AppSetting ], - 'reference' => $orderId, + 'delivery_address' => [ + 'type' => $order->shipping_type ?? 'residential', + 'street_address' => $order->shipping_street_address, + 'local_area' => $order->shipping_local_area, + 'city' => $order->shipping_city, + 'zone' => $order->shipping_zone, + 'code' => $order->shipping_postcode, + 'country' => $order->shipping_country ?? 'ZA', + ], + 'delivery_contact' => [ + 'name' => $order->customer_name, + 'email' => $order->customer_email, + 'mobile_number' => $order->customer_phone, + ], + 'parcels' => [ + [ + 'weight' => $weight, + 'height' => 10, // TODO: Update when height is captured separately + 'width' => $width, + 'length' => $length, + ], + ], + 'service_level_id' => $this->getServiceLevelId(), // Standard delivery + 'customer_reference' => $order->order_number, + 'mute_notifications' => false, ]; + Log::info('Creating Shiplogic shipment', [ + 'order_id' => $orderId, + 'order_number' => $order->order_number, + 'customer' => $order->customer_name, + 'delivery_address' => $street, + ]); + $response = Http::withHeaders([ 'Authorization' => "Bearer {$this->apiKey}", ])->post("{$this->baseUrl}/shipments", $payload); if (! $response->successful()) { - $errorMessage = $response->json('error.message', 'Unknown error'); + $errorMessage = $response->json('error.message', $response->json('message', 'Unknown error')); throw new \Exception("Courier API error: {$errorMessage}"); } @@ -155,6 +199,15 @@ class CourierService } } + /** + * Get service level ID for standard delivery + * TODO: Move to AppSetting and make configurable + */ + private function getServiceLevelId(): int + { + return 1; // Standard service level + } + /** * Validate packing gate: order must be packed with dimensions */ diff --git a/database/migrations/2026_01_02_000003_split_shipping_address_into_components.php b/database/migrations/2026_01_02_000003_split_shipping_address_into_components.php new file mode 100644 index 0000000..8ef4288 --- /dev/null +++ b/database/migrations/2026_01_02_000003_split_shipping_address_into_components.php @@ -0,0 +1,43 @@ +string('shipping_street_address')->nullable()->after('shipping_address'); + $table->string('shipping_local_area')->nullable()->after('shipping_street_address'); + $table->string('shipping_city')->nullable()->after('shipping_local_area'); + $table->string('shipping_zone')->nullable()->after('shipping_city'); + $table->string('shipping_country')->default('ZA')->after('shipping_zone'); + $table->string('shipping_postcode')->nullable()->after('shipping_country'); + $table->enum('shipping_type', ['residential', 'business'])->default('residential')->after('shipping_postcode'); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::table('orders', function (Blueprint $table) { + $table->dropColumn([ + 'shipping_street_address', + 'shipping_local_area', + 'shipping_city', + 'shipping_zone', + 'shipping_country', + 'shipping_postcode', + 'shipping_type', + ]); + }); + } +}; diff --git a/storage/framework/views/adc4c4a369b2bee1705d8da3a6247c45.php b/storage/framework/views/adc4c4a369b2bee1705d8da3a6247c45.php new file mode 100644 index 0000000..f1db8d5 --- /dev/null +++ b/storage/framework/views/adc4c4a369b2bee1705d8da3a6247c45.php @@ -0,0 +1,793 @@ +startSection('title', 'Request Custom Design - Additional Design'); ?> + +startSection('styles'); ?> + +stopSection(); ?> + +startSection('content'); ?> +
+
+

Request Custom Design

+

Create a custom wallpaper, mural, or fabric design tailored to your needs

+
+ + any()): ?> +
+

Please correct the following errors:

+ +
+ + + +
+ ✓ + +
+ + + +
+

How It Works

+ +
+ + +
+
+ + + +
+

Order Details

+ +
+ + + getBag($__errorArgs[1] ?? 'default'); +if ($__bag->has($__errorArgs[0])) : +if (isset($message)) { $__messageOriginal = $message; } +$message = $__bag->first($__errorArgs[0]); ?> +

+ +
+ +
+
+ + + getBag($__errorArgs[1] ?? 'default'); +if ($__bag->has($__errorArgs[0])) : +if (isset($message)) { $__messageOriginal = $message; } +$message = $__bag->first($__errorArgs[0]); ?> +

+ +
+
+ + + getBag($__errorArgs[1] ?? 'default'); +if ($__bag->has($__errorArgs[0])) : +if (isset($message)) { $__messageOriginal = $message; } +$message = $__bag->first($__errorArgs[0]); ?> +

+ +
+
+ +
+
+ + + getBag($__errorArgs[1] ?? 'default'); +if ($__bag->has($__errorArgs[0])) : +if (isset($message)) { $__messageOriginal = $message; } +$message = $__bag->first($__errorArgs[0]); ?> +

+ +
+
+ + + getBag($__errorArgs[1] ?? 'default'); +if ($__bag->has($__errorArgs[0])) : +if (isset($message)) { $__messageOriginal = $message; } +$message = $__bag->first($__errorArgs[0]); ?> +

+ +
+
+
+ + +
+

Design Brief

+ +
+ +

Tell us about your design concept, colors, style, and any specific requirements

+ + getBag($__errorArgs[1] ?? 'default'); +if ($__bag->has($__errorArgs[0])) : +if (isset($message)) { $__messageOriginal = $message; } +$message = $__bag->first($__errorArgs[0]); ?> +

+ +
+ +
+ + + getBag($__errorArgs[1] ?? 'default'); +if ($__bag->has($__errorArgs[0])) : +if (isset($message)) { $__messageOriginal = $message; } +$message = $__bag->first($__errorArgs[0]); ?> +

+ +
+
+ + +
+

Reference Images

+ +
+ +

Upload inspiration images, mood boards, or reference materials for your design

+
+ + + + +

Click to upload or drag and drop

+

PNG, JPG, GIF, WebP up to 5MB

+
+
+ getBag($__errorArgs[1] ?? 'default'); +if ($__bag->has($__errorArgs[0])) : +if (isset($message)) { $__messageOriginal = $message; } +$message = $__bag->first($__errorArgs[0]); ?> +

+ +
+
+ + +
+

Design Library

+ +
+ +
+
+ + +
+ + Cancel +
+
+ + +
+
+

Cost Summary

+ +
+ Material Cost + - +
+ +
+ Design Fee + - +
+ + + +
+ Deposit Required (20%) + R0.00 +
+ +
+ Note: 20% non-refundable deposit covers design work. Pay the remaining 80% after proof approval. +
+
+ +
+

Estimated Total:

+
R0.00
+ incl. VAT +
+
+ + + + +
+
+ + + stopSection(); ?> +make('layouts.app', array_diff_key(get_defined_vars(), ['__data' => 1, '__path' => 1]))->render(); ?> \ No newline at end of file