2a10f9af38
**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
108 lines
4.1 KiB
PHP
108 lines
4.1 KiB
PHP
<?php
|
|
|
|
namespace App\Testing;
|
|
|
|
use Illuminate\Http\Client\Request;
|
|
use Illuminate\Http\Client\Response;
|
|
use Illuminate\Support\Facades\Http;
|
|
|
|
/**
|
|
* Mock HTTP Client for testing Shiplogic API interactions
|
|
*
|
|
* Usage in tests:
|
|
* ShiplogicMockClient::setup();
|
|
* // Now all HTTP requests to shiplogic will return mock responses
|
|
*/
|
|
class ShiplogicMockClient
|
|
{
|
|
/**
|
|
* Setup mock HTTP responses for Shiplogic API
|
|
*/
|
|
public static function setup(): void
|
|
{
|
|
Http::fake([
|
|
'shiplogic.*/rates' => Http::response(self::ratesResponse(), 200),
|
|
'shiplogic.*/shipments' => Http::response(self::shipmentsResponse(), 201),
|
|
'shiplogic.*/shipments/label' => Http::response(self::pdfResponse(), 200, [
|
|
'Content-Type' => 'application/pdf',
|
|
]),
|
|
'shiplogic.*/shipments/label/stickers' => Http::response(self::pdfResponse(), 200, [
|
|
'Content-Type' => 'application/pdf',
|
|
]),
|
|
]);
|
|
}
|
|
|
|
/**
|
|
* Mock response for /rates endpoint
|
|
*/
|
|
public static function ratesResponse(): array
|
|
{
|
|
return [
|
|
'id' => '550e8400-e29b-41d4-a716-446655440001',
|
|
'company_shipment_rates' => [
|
|
[
|
|
'id' => '9f67ff00-7a82-4d81-9481-4c5d8c8f1a00',
|
|
'company_code' => 'FEDEX',
|
|
'company_name' => 'FedEx',
|
|
'service_level' => [
|
|
'id' => '123456789',
|
|
'code' => 'FEDEX_INTERNATIONAL_PRIORITY_EXPRESS',
|
|
'name' => 'International Priority Express',
|
|
'description' => 'Fastest service',
|
|
],
|
|
'rate' => 125.50,
|
|
'currency' => 'GBP',
|
|
'transit_days' => '1-2',
|
|
'delivery_guarantee_date' => '2026-01-05',
|
|
],
|
|
[
|
|
'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',
|
|
],
|
|
],
|
|
];
|
|
}
|
|
|
|
/**
|
|
* Mock response for /shipments endpoint
|
|
*/
|
|
public static function shipmentsResponse(): array
|
|
{
|
|
return [
|
|
'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' => now()->toIso8601String(),
|
|
];
|
|
}
|
|
|
|
/**
|
|
* Mock PDF response
|
|
*/
|
|
public static function pdfResponse(): string
|
|
{
|
|
// Minimal valid PDF
|
|
return "%PDF-1.4\n1 0 obj\n<< /Type /Catalog /Pages 2 0 R >>\nendobj\n2 0 obj\n<< /Type /Pages /Kids [3 0 R] /Count 1 >>\nendobj\n3 0 obj\n<< /Type /Page /Parent 2 0 R /Resources << /Font << /F1 4 0 R >> >> /MediaBox [0 0 612 792] /Contents 5 0 R >>\nendobj\n4 0 obj\n<< /Type /Font /Subtype /Type1 /BaseFont /Helvetica >>\nendobj\n5 0 obj\n<< /Length 44 >>\nstream\nBT\n/F1 12 Tf\n100 700 Td\n(Mock PDF) Tj\nET\nendstream\nendobj\nxref\n0 6\n0000000000 65535 f\n0000000009 00000 n\n0000000058 00000 n\n0000000115 00000 n\n0000000273 00000 n\n0000000352 00000 n\ntrailer\n<< /Size 6 /Root 1 0 R >>\nstartxref\n446\n%%EOF";
|
|
}
|
|
}
|