feat: Implement Slack, Trello, and Courier (ShipLogic) integration

- Add 14 domain events for order lifecycle (OrderCreated, OrderPacked, ShipmentCreated, ParcelDelivered, etc.)
- Create SlackNotifierService with channels for orders, design, production, shipping, ops-alerts
- Create TrelloService to create cards, move cards between lists, attach files, check items
- Create CourierService to integrate with ShipLogic API for shipment creation and document retrieval
- Create PackingController to explicitly capture packing dimensions and weight
- Create ShippingController with multi-layer guards: packing validation, payment/approval verification, idempotency
- Create TrelloWebhookController to handle incoming Trello webhooks as intent signals
- Create CourierWebhookController to handle Shiplogic status updates
- Create event listeners for Slack notifications and Trello card updates
- Create EventServiceProvider to register all events and listeners
- Add database migration for packing, courier, and Trello data columns
- Create config files for slack, trello, and courier integration
- Update .env with integration secrets placeholders
- Add routes for /orders/{id}/pack, /orders/{id}/ship, /api/webhooks/trello, /api/webhooks/courier

Key architectural decisions:
- Packing is explicit ops action (not automatic from status)
- Shipment creation only after: Trello intent + packing confirmed + payment/approval rules met
- Courier API failures keep order in Ready to Ship state (safe retry)
- Trello and Slack are mirrors of backend state, not decision makers
- All side effects flow through event listeners, maintaining separation of concerns
This commit is contained in:
twotalesanimation
2026-01-02 13:47:31 +02:00
parent 4730f5770c
commit 12aadfd917
35 changed files with 1815 additions and 0 deletions
+7
View File
@@ -0,0 +1,7 @@
<?php
return [
'api_key' => env('COURIER_API_KEY'),
'api_base_url' => env('COURIER_API_BASE_URL', 'https://api.shiplogic.com/api'),
'webhook_secret' => env('COURIER_WEBHOOK_SECRET'),
];
+11
View File
@@ -0,0 +1,11 @@
<?php
return [
'webhooks' => [
'orders' => env('SLACK_WEBHOOK_ORDERS'),
'design' => env('SLACK_WEBHOOK_DESIGN'),
'production' => env('SLACK_WEBHOOK_PRODUCTION'),
'shipping' => env('SLACK_WEBHOOK_SHIPPING'),
'ops_alerts' => env('SLACK_WEBHOOK_OPS'),
],
];
+36
View File
@@ -0,0 +1,36 @@
<?php
return [
'api_key' => env('TRELLO_API_KEY'),
'api_token' => env('TRELLO_API_TOKEN'),
'board_id' => env('TRELLO_BOARD_ID'),
'webhook_secret' => env('TRELLO_WEBHOOK_SECRET'),
'lists' => [
'standard' => [
'new_order' => env('TRELLO_LIST_ID_NEW_ORDER'),
'prep' => env('TRELLO_LIST_ID_PREP'),
'printing' => env('TRELLO_LIST_ID_PRINTING'),
'inspection' => env('TRELLO_LIST_ID_INSPECTION'),
'packing' => env('TRELLO_LIST_ID_PACKING'),
'ready_to_ship' => env('TRELLO_LIST_ID_READY_TO_SHIP'),
'awaiting_collection' => env('TRELLO_LIST_ID_AWAITING_COLLECTION'),
'in_transit' => env('TRELLO_LIST_ID_IN_TRANSIT'),
'done' => env('TRELLO_LIST_ID_DONE'),
],
'custom' => [
'new_custom_order' => env('TRELLO_LIST_ID_NEW_CUSTOM_ORDER'),
'design' => env('TRELLO_LIST_ID_DESIGN'),
'awaiting_approval' => env('TRELLO_LIST_ID_AWAITING_APPROVAL'),
'awaiting_balance' => env('TRELLO_LIST_ID_AWAITING_BALANCE'),
'ready_for_print' => env('TRELLO_LIST_ID_READY_FOR_PRINT'),
'printing' => env('TRELLO_LIST_ID_PRINTING'),
'inspection' => env('TRELLO_LIST_ID_INSPECTION'),
'packing' => env('TRELLO_LIST_ID_PACKING'),
'ready_to_ship' => env('TRELLO_LIST_ID_READY_TO_SHIP'),
'awaiting_collection' => env('TRELLO_LIST_ID_AWAITING_COLLECTION'),
'in_transit' => env('TRELLO_LIST_ID_IN_TRANSIT'),
'done' => env('TRELLO_LIST_ID_DONE'),
],
],
];