Platform Export - Overview¶
Purpose¶
The Platform Export island handles exporting stock, prices, and order data to external sales platforms like Tyre24 and Autodoc. It includes a sophisticated pricing engine for calculating platform-specific prices.
Architecture¶
┌─────────────────────────────────────────────────────────────┐
│ PLATFORM EXPORT │
│ │
│ ┌──────────────┐ ┌────────────────────┐ │
│ │ Webshop │───►│ Pricing Engine │ │
│ │ API Call │ │ │ │
│ └──────────────┘ └─────────┬──────────┘ │
│ │ │
│ ┌───────────▼───────────┐ │
│ │ Export Generator │ │
│ │ │ │
│ └───────────┬───────────┘ │
│ │ │
│ ┌────────────────────┼────────────────────┐ │
│ │ │ │ │
│ ▼ ▼ ▼ │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐│
│ │ FTP │ │ API │ │ EDI ││
│ │ Uploader │ │ Publisher │ │ Sender ││
│ └─────────────┘ └─────────────┘ └─────────────┘│
│ │ │ │ │
└───────────┼────────────────────┼────────────────────┼──────┘
│ │ │
▼ ▼ ▼
┌──────────┐ ┌──────────┐ ┌──────────┐
│ Tyre24 │ │ Autodoc │ │ Other │
└──────────┘ └──────────┘ └──────────┘
Export Types¶
| Type | Direction | Content |
|---|---|---|
| Stock Export | Out | Available articles + prices |
| Order Import | In | Orders from platforms |
| Order Update | Out | Status changes |
| Tracking Export | Out | Shipment tracking info |
Platform Connections¶
Each platform can use different connection methods:
| Platform | Stock | Orders | Tracking |
|---|---|---|---|
| Tyre24 | FTP (CSV) | API | API |
| Autodoc | API | API | API |
| Custom | Configurable | Configurable | Configurable |
Pricing Engine¶
The pricing engine calculates platform-specific prices:
Export Price = AK + Margin + Transport Surcharge
Components¶
- AK (Aankoopprijs): Base purchase price
- Margin: Configurable at multiple levels
- Transport Surcharge: Weight-based staffel prices
Configuration per Platform¶
#[ORM\Entity]
class PlatformConfig
{
#[ORM\Id]
#[ORM\GeneratedValue]
#[ORM\Column]
private int $id;
#[ORM\Column(length: 50)]
private string $name; // "Tyre24", "Autodoc"
#[ORM\Column(length: 20)]
private string $connectionType; // 'ftp', 'api', 'edi'
#[ORM\Column(type: 'json')]
private array $connectionConfig; // Credentials, URLs, etc.
#[ORM\Column]
private bool $isActive = true;
#[ORM\OneToMany(mappedBy: 'platform', targetEntity: PlatformMarginRule::class)]
private Collection $marginRules;
#[ORM\OneToMany(mappedBy: 'platform', targetEntity: PlatformTransportTier::class)]
private Collection $transportTiers;
#[ORM\Column(type: 'json', nullable: true)]
private ?array $articleFilters; // Which articles to export
}
Data Flow¶
Stock Export¶
- Scheduler triggers export (e.g., every hour)
- Fetch active articles from Webshop API
- Apply article filters (brand, category, stock > 0)
- Calculate prices via Pricing Engine
- Generate export file/payload
- Send to platform via configured method
Order Import¶
- Poll platform for new orders (or receive webhook)
- Parse order data
- Match articles to internal catalog
- Create order in Webshop via API
- Confirm order to platform
Tracking Export¶
- Listen for Webshop tracking updates (webhook)
- Format tracking data per platform
- Send to platform
Connector Runtime Contract (AR-004 Closure)¶
All platform connectors (FTP/API/EDI) follow one reliability and operability contract.
Idempotency¶
Inbound and outbound messages require deterministic idempotency keys.
Examples:
platform-order-in:{platform}:{externalOrderId}:{externalVersion}
platform-stock-out:{platform}:{exportBatchId}:{articleHash}
platform-tracking-out:{platform}:{orderId}:{trackingCode}:{version}
Rules:
- Re-delivered key must not create duplicate orders/updates.
- Consumer inbox tracks processed keys and final disposition.
- Outbound publishers store send-attempt records keyed by idempotency key.
Retry and Backoff¶
- Retry temporary failures (timeouts,
5xx, rate limits) with exponential backoff. - Respect per-platform throttling and backoff hints (for example retry-after headers).
- Do not blind-retry permanent contract/validation errors.
- Escalate exhausted retries to DLQ with operator replay path.
Dead-Letter Queue and Replay¶
Separate DLQ per flow:
platform-orders-dlqplatform-stock-export-dlqplatform-tracking-dlq
Replay tooling must support filtering by platform, flow, and date range.
Checkpoints and Watermarks¶
Per platform and per flow keep:
last_order_cursor/last_poll_timelast_stock_export_batch_idlast_tracking_export_cursorlast_successful_run_at
Restart behavior resumes from checkpoint; overlap windows are allowed because idempotency deduplicates safely.
Queue Classes¶
high-priority:- order import
- order status updates
- tracking pushes
bulk:- stock export generation
- full listing rebuilds
Minimum Operational Metrics¶
- Per-platform success/failure rates per flow.
- Retry counts and DLQ depth per platform.
- Order import lag and stock export freshness lag.
- Duplicate-delivery suppression counts.
Acceptance Scenarios (Gherkin)¶
Feature: Platform connector runtime reliability
Scenario: Duplicate platform order delivery is idempotent
Given platform order O with idempotency key K was already processed
When the platform sends O again
Then no duplicate webshop order should be created
And the duplicate should be acknowledged
Scenario: Rate-limited stock export retries with backoff
Given platform API responds with rate limiting
When stock export is attempted
Then export should retry with backoff using platform hints
And successful retry should mark export batch complete once
Scenario: Failed tracking push can be replayed from DLQ
Given tracking export retries are exhausted
When message is moved to platform-tracking-dlq
And operator replays after platform recovery
Then tracking update should be delivered without duplication