feat: Complete Shiplogic integration with mobile-optimized ops workflow
**Shiplogic API Integration:**
- Fixed API base URL configuration (removed /api suffix)
- Implemented comprehensive request/response logging for rates and shipments endpoints
- Fixed PDF fetching: API returns S3 URLs, now downloads actual PDFs from S3
- Added tests and mock API responses for local development (routes/shiplogic-mock.php)
**Courier Service Enhancements:**
- Added redownloadShipmentPdfs() public method for re-downloading corrupted PDFs
- Enhanced error logging with full request/response bodies for debugging
- Proper binary PDF storage using Laravel Storage facade
- URL and S3 download handling for Shiplogic API responses
**Workflow & Operations:**
- Changed to manual "Ready for Collection" button instead of automatic move
- Operators now: scan QR → apply labels → click "Ready for Collection" → moves to Awaiting Collection
- Removed duplicate PDF attachments to Trello (was adding twice from two listeners)
- Fixed NotifySlackOnShipmentCreated to only handle Slack notifications
**Mobile-Optimized Ops Page:**
- Removed QR code display from order detail page
- Implemented responsive single-column layout for mobile phones
- Large touch-friendly buttons (full width, increased padding)
- Bold typography for better readability on small screens
- Larger input fields and tracking number displays
- Clear step-by-step instructions for warehouse operators
- Re-download PDF button for damaged/corrupted labels
**New Features:**
- POST /ops/orders/{uuid}/ready-for-collection endpoint
- Re-download PDFs functionality accessible from awaiting_collection and in_transit states
- Full audit logging for all operations via ops interface
- Proper error handling and user feedback
**Testing:**
- Added ShipmentCreationTest with mock HTTP client
- Created comprehensive testing guide (SHIPLOGIC_TESTING.md)
- Mock API routes for local development without hitting live API
This commit is contained in:
@@ -0,0 +1,223 @@
|
||||
# Shiplogic Integration Testing Guide
|
||||
|
||||
This guide explains how to test the Shiplogic API integration with mocked responses.
|
||||
|
||||
## Files Created
|
||||
|
||||
### 1. **routes/shiplogic-mock.php** - Mock API Endpoints
|
||||
Routes that simulate the Shiplogic API responses for local testing without hitting the live API.
|
||||
|
||||
**Endpoints:**
|
||||
- `POST /api/v1/mock/rates` - Returns available shipping rates/service levels
|
||||
- `POST /api/v1/mock/shipments` - Returns created shipment confirmation
|
||||
- `GET /api/v1/mock/shipments/label` - Returns waybill/label PDF
|
||||
- `GET /api/v1/mock/shipments/label/stickers` - Returns sticker labels PDF
|
||||
|
||||
**To Enable:**
|
||||
Add this line to `routes/web.php`:
|
||||
```php
|
||||
include base_path('routes/shiplogic-mock.php');
|
||||
```
|
||||
|
||||
Then mock routes are available at `http://localhost:8000/api/v1/mock/*`
|
||||
|
||||
### 2. **app/Testing/ShiplogicMockClient.php** - Test Helper
|
||||
PHP class for setting up HTTP mocking in tests. Uses Laravel's `Http::fake()` to intercept HTTP requests.
|
||||
|
||||
**Usage in Tests:**
|
||||
```php
|
||||
public function test_something()
|
||||
{
|
||||
ShiplogicMockClient::setup();
|
||||
|
||||
// Now all requests to shiplogic.* URLs will return mocked responses
|
||||
// Run your shipment creation logic here
|
||||
}
|
||||
```
|
||||
|
||||
### 3. **tests/Feature/ShipmentCreationTest.php** - Example Tests
|
||||
Two example test cases demonstrating:
|
||||
- End-to-end shipment creation workflow
|
||||
- ECO service level selection verification
|
||||
|
||||
## Test Flow
|
||||
|
||||
### Local Testing with Mock Routes
|
||||
|
||||
1. **Start Laravel server:**
|
||||
```bash
|
||||
php artisan serve
|
||||
```
|
||||
|
||||
2. **Update CourierService.php** to point to mock endpoints temporarily:
|
||||
```php
|
||||
// In CourierService.php constructor or config
|
||||
// Change: $this->baseUrl = config('services.shiplogic.api_base_url');
|
||||
// To test locally: $this->baseUrl = 'http://localhost:8000/api/v1/mock';
|
||||
```
|
||||
|
||||
3. **Trigger shipment creation** via Filament UI or directly:
|
||||
```php
|
||||
// Create an order
|
||||
$order = Order::factory()->create([...]);
|
||||
|
||||
// Trigger ReadyToShipIntent event
|
||||
event(new App\Events\ReadyToShipIntent($order));
|
||||
```
|
||||
|
||||
4. **Check logs** for detailed request/response logging:
|
||||
```bash
|
||||
tail -f storage/logs/laravel.log
|
||||
```
|
||||
|
||||
### Unit/Feature Testing with HTTP Mocking
|
||||
|
||||
1. **Run the test:**
|
||||
```bash
|
||||
php artisan test tests/Feature/ShipmentCreationTest.php
|
||||
```
|
||||
|
||||
2. **Test will:**
|
||||
- Mock all HTTP requests to shiplogic API
|
||||
- Create test order with required fields
|
||||
- Trigger shipment creation
|
||||
- Assert order has shipment metadata
|
||||
- Assert PDFs were stored locally
|
||||
|
||||
## Logging Details
|
||||
|
||||
The enhanced CourierService now logs at each stage:
|
||||
|
||||
### GET Rates Request
|
||||
```
|
||||
INFO: Fetching shipping rates from Shiplogic
|
||||
- order_uuid: 019b8335-4b47-7087-8b93-73f6aa39ee7a
|
||||
- api_url: https://api.shiplogic.com/rates
|
||||
- collection_address: {...}
|
||||
- delivery_address: {...}
|
||||
- parcel_dimensions: {...}
|
||||
```
|
||||
|
||||
### GET Rates Response
|
||||
```
|
||||
INFO: Rates API response received
|
||||
- status: 200
|
||||
- successful: true
|
||||
|
||||
OR
|
||||
|
||||
ERROR: Rates API error response
|
||||
- status: 400 (or other error code)
|
||||
- error_message: Invalid address format
|
||||
- full_response: {...}
|
||||
```
|
||||
|
||||
### CREATE Shipment Request
|
||||
```
|
||||
INFO: Creating Shiplogic shipment
|
||||
- order_uuid: 019b8335-4b47-7087-8b93-73f6aa39ee7a
|
||||
- order_number: ORDER-001
|
||||
- customer: John Doe
|
||||
- delivery_address: Apt 5B, 123 Main Street
|
||||
- service_level: FEDEX_INTERNATIONAL_ECONOMY
|
||||
- api_url: https://api.shiplogic.com/shipments
|
||||
- payload: {...}
|
||||
```
|
||||
|
||||
### CREATE Shipment Response
|
||||
```
|
||||
INFO: Shipment created in API
|
||||
- shipment_id: 550e8400-e29b-41d4-a716-446655440002
|
||||
- tracking_reference: SHP123456789
|
||||
```
|
||||
|
||||
## Debugging "Unknown Error"
|
||||
|
||||
If you see `ERROR: Failed to get shipping rates {"error":"Failed to fetch rates: Unknown error"}`:
|
||||
|
||||
1. **Enable detailed logging** - Now included in updated CourierService
|
||||
2. **Check the full API response** - Logs will now show the actual error response
|
||||
3. **Common issues:**
|
||||
- Invalid API key format
|
||||
- Missing required address fields
|
||||
- Invalid parcel dimensions
|
||||
- API endpoint URL incorrect
|
||||
- Network/SSL certificate issues
|
||||
|
||||
## Running Tests
|
||||
|
||||
```bash
|
||||
# Run all shipment creation tests
|
||||
php artisan test tests/Feature/ShipmentCreationTest.php
|
||||
|
||||
# Run specific test
|
||||
php artisan test tests/Feature/ShipmentCreationTest.php::test_shipment_creation_with_mock_api
|
||||
|
||||
# Run with verbose output
|
||||
php artisan test tests/Feature/ShipmentCreationTest.php -v
|
||||
|
||||
# Run and dump test database
|
||||
php artisan test tests/Feature/ShipmentCreationTest.php --debug
|
||||
```
|
||||
|
||||
## Mock Response Structure
|
||||
|
||||
All mock responses follow the actual Shiplogic API structure:
|
||||
|
||||
### Rates Response
|
||||
```json
|
||||
{
|
||||
"id": "550e8400-e29b-41d4-a716-446655440001",
|
||||
"company_shipment_rates": [
|
||||
{
|
||||
"id": "9f67ff00-7a82-4d81-9481-4c5d8c8f1a01",
|
||||
"company_code": "FEDEX",
|
||||
"company_name": "FedEx",
|
||||
"service_level": {
|
||||
"id": "123456790",
|
||||
"code": "FEDEX_INTERNATIONAL_ECONOMY",
|
||||
"name": "International Economy",
|
||||
"description": "Economy service (ECO)"
|
||||
},
|
||||
"rate": 45.75,
|
||||
"currency": "GBP",
|
||||
"transit_days": "5-7",
|
||||
"delivery_guarantee_date": "2026-01-09"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
### Shipments Response
|
||||
```json
|
||||
{
|
||||
"id": "550e8400-e29b-41d4-a716-446655440002",
|
||||
"short_tracking_reference": "SHP123456789",
|
||||
"tracking_reference": "SHP-123456789-ABC",
|
||||
"customer_reference": "ORDER-12345",
|
||||
"company_code": "FEDEX",
|
||||
"service_level": {
|
||||
"code": "FEDEX_INTERNATIONAL_ECONOMY",
|
||||
"name": "International Economy"
|
||||
},
|
||||
"collection_min_date": "2026-01-04",
|
||||
"delivery_min_date": "2026-01-09",
|
||||
"status": "created",
|
||||
"created_at": "2026-01-03T12:42:56.000000Z"
|
||||
}
|
||||
```
|
||||
|
||||
## Next Steps
|
||||
|
||||
1. ✅ Add detailed logging to CourierService
|
||||
2. ✅ Create mock API routes and test helper
|
||||
3. **TODO:** Test with actual order to capture real error
|
||||
4. **TODO:** Fix identified Shiplogic API integration issue
|
||||
5. **TODO:** Verify PDFs are being fetched and attached correctly
|
||||
|
||||
## Configuration Reference
|
||||
|
||||
Key configuration files for Shiplogic:
|
||||
- `config/services.php` - API credentials and collection address
|
||||
- `config/courier.php` - Courier service settings
|
||||
- `.env` - Environment variables (SHIPLOGIC_API_URL, SHIPLOGIC_API_KEY, collection address details)
|
||||
Reference in New Issue
Block a user