# ED-04-004 – SourceDelivery Application Service

**Status:** Final

**Related**

- ED-04_SourceDelivery_Aggregate.md
- ED-04-001_SourceDelivery_Domain_Object.md
- ED-04-002_SourceDelivery_Persistence.md
- ED-04-003_SourceDelivery_Repository.md
- ADR002_SOURCE_DELIVERY_MODEL_V4.md
- DM001_Domain_Model_v0.7_FINAL.md
- DM002_Persistence_Model_v0.6_FINAL.md

---

# 1. Ziel

Dieses Work Package implementiert den Application Service zur Erzeugung und Verwaltung von `SourceDelivery`.

Der Service koordiniert den Eingang einer neuen Lieferung, erzeugt das Aggregate und speichert dieses über das Repository.

Er enthält keine fachliche Geschäftslogik.

---

# 2. Scope

Implementiert werden

- Erzeugen einer neuen `SourceDelivery`
- Übernahme der Request-Metadaten
- Persistierung über das Repository
- Rückgabe der erzeugten Lieferung

Nicht Bestandteil sind

- Verarbeitung einzelner SourceValues
- Candidate Discovery
- Reconciliation
- Statuswechsel während der Verarbeitung

---

# 3. Verantwortung

Der Application Service

- liest die Liefer-Metadaten,
- erzeugt das Aggregate,
- speichert das Aggregate,
- liefert die erzeugte `SourceDelivery` zurück.

Er entscheidet nicht über

- Matching,
- Candidate Discovery,
- Statusübergänge,
- Persistenzdetails.

---

# 4. Eingangsdaten

Der Service verarbeitet mindestens folgende Informationen.

| Feld | Pflicht | Herkunft |
|-------|:------:|----------|
| tenantId | ✓ | Runtime Context |
| sourceSystemId | ✓ | Runtime Context |
| deliveryChannel | ✓ | Runtime Context |
| externalDeliveryId | optional | Request (`delivery_id`) |

---

# 5. Ablauf

Der Service arbeitet nach folgendem Ablauf:

```text
Request
    │
    ▼
Request-Metadaten lesen
    │
    ▼
SourceDelivery::create(...)
    │
    ▼
Repository.save(...)
    │
    ▼
SourceDelivery zurückgeben
```

---

# 6. Verarbeitung der delivery_id

Ist im Request

```text
delivery_id
```

vorhanden,

wird dieser Wert unverändert übernommen.

Beispiel

```text
delivery_id = OR-TEST-20260725-001
```

führt zu

```text
externalDeliveryId = OR-TEST-20260725-001
```

Fehlt der Parameter,

wird

```text
externalDeliveryId = null
```

gesetzt.

Der Service erzeugt selbst keine externe Lieferkennung.

---

# 7. Erzeugung des Aggregates

Das Aggregate wird ausschließlich über

```php
SourceDelivery::create(...)
```

erzeugt.

Dabei werden

- neue interne ID,
- receivedAt,
- initialer Status RECEIVED

automatisch gesetzt.

---

# 8. Speicherung

Nach erfolgreicher Erzeugung erfolgt unmittelbar

```php
repository->save($sourceDelivery);
```

Weitere Verarbeitungsschritte erfolgen nicht innerhalb dieses Work Packages.

---

# 9. Rückgabewert

Der Service liefert das vollständig erzeugte Aggregate zurück.

Dieses enthält insbesondere

- interne ID,
- tenantId,
- sourceSystemId,
- deliveryChannel,
- externalDeliveryId,
- Status,
- receivedAt.

---

# 10. Fehlerbehandlung

Technische Fehler der Persistenz werden weitergegeben.

Fachliche Validierungen erfolgen ausschließlich innerhalb des Domain Models.

Der Application Service enthält keine eigene Validierungslogik.

---

# 11. Beispiel

OpenRefine ruft auf

```text
POST /reconcile/v2/

delivery_id=OR-TEST-20260725-001
```

Der Service erzeugt

```text
SourceDelivery

id                  = SD-...
tenantId            = digicult
sourceSystemId      = digiCULT.web
deliveryChannel     = OPENREFINE_RECONCILIATION_API
externalDeliveryId  = OR-TEST-20260725-001
status              = RECEIVED
receivedAt          = ...
```

und speichert dieses anschließend.

---

# 12. Unit Tests

Mindestens folgende Tests werden implementiert.

1. Neue SourceDelivery wird erzeugt.
2. Repository wird aufgerufen.
3. delivery_id wird übernommen.
4. Fehlende delivery_id führt zu NULL.
5. deliveryChannel wird übernommen.
6. tenantId wird übernommen.
7. sourceSystemId wird übernommen.
8. Das erzeugte Aggregate wird zurückgegeben.

---

# 13. Akzeptanzkriterien

Das Work Package gilt als abgeschlossen, wenn

- eine neue SourceDelivery erzeugt werden kann,
- alle Pflichtattribute korrekt übernommen werden,
- eine vorhandene delivery_id gespeichert wird,
- fehlende delivery_id zu NULL führt,
- das Repository genau einmal aufgerufen wird,
- das erzeugte Aggregate zurückgegeben wird,
- keine Geschäftslogik außerhalb des Domain Models implementiert wird.