# API Zugriff

Diese Dokumentation beschreibt die verfügbaren API-Endpunkte für das Loyalty Plugin.

{% hint style="info" %}
Alle Endpunkte erfordern Authentifizierung (`auth_required: true`). Verwenden Sie die Shopware API-Authentifizierung mit OAuth oder einem API-Key.
{% endhint %}

***

## 1. Kundenprofil abrufen

Ruft ein einzelnes Kundenprofil mit allen Loyalty-Informationen ab.

### Endpunkt

```http
GET /api/cogi/loyalty/customer-profile/{customerId}
```

### Parameter

| Parameter    | Typ           | Pflicht | Beschreibung      |
| ------------ | ------------- | ------- | ----------------- |
| `customerId` | string (path) | Ja      | Die ID des Kunden |

### Response

**Status: 200 OK**

```json
{
  "status": "success",
  "data": {
    "id": "0x...",
    "customerId": "0x...",
    "points": 500,
    "pointsExpirationDate": "2025-12-31",
    "customFieldRewards": null,
    "setBirthday": true,
    "newsletter": false,
    "lastPointsReceived": "2024-01-20 14:30:00",
    "createdAt": "2024-01-15 10:30:00",
    "updatedAt": "2024-01-20 15:45:00",
    "level": {
      "id": "0x...",
      "name": "Silver",
      "minPoints": 100,
      "tagId": "0x...",
      "multiplier": 1.5,
      "color": "#FF5733"
    },
    "previousLevel": {
      "id": "0x...",
      "name": "Bronze",
      "minPoints": 0,
      "tagId": "0x...",
      "multiplier": 1.0,
      "color": "#C0C0C0",
      "pointsToFallDown": 400
    },
    "nextLevel": {
      "id": "0x...",
      "name": "Gold",
      "minPoints": 1000,
      "tagId": "0x...",
      "multiplier": 2.0,
      "color": "#FFD700",
      "pointsToReach": 500
    },
    "customer": {
      "id": "0x...",
      "email": "customer@example.com",
      "firstName": "Max",
      "lastName": "Mustermann",
      "customerNumber": "CUST-001"
    }
  }
}
```

**Status: 404 Not Found** (wenn Profil nicht gefunden)

```json
{
  "status": "error",
  "message": "Customer profile not found."
}
```

***

## 2. Kundenprofile abrufen (Liste)

Ruft mehrere Kundenprofile mit Filter- und Paginations-Optionen ab.

### Endpunkt

```http
GET /api/cogi/loyalty/customer-profiles
```

### Query-Parameter

| Parameter       | Typ                      | Pflicht | Beschreibung                                          |
| --------------- | ------------------------ | ------- | ----------------------------------------------------- |
| `customerIds`   | string (comma-separated) | Nein    | Filter nach Kunden-ID(s), kommagetrennt               |
| `levelId`       | string                   | Nein    | Filter nach Level-ID                                  |
| `minPoints`     | integer                  | Nein    | Mindestanzahl Punkte                                  |
| `maxPoints`     | integer                  | Nein    | Maximale Anzahl Punkte                                |
| `limit`         | integer                  | Nein    | Anzahl Ergebnisse (Standard: 20)                      |
| `offset`        | integer                  | Nein    | Offset für Pagination (Standard: 0)                   |
| `sortBy`        | string                   | Nein    | Sortierfeld (Standard: 'points')                      |
| `sortDirection` | string                   | Nein    | Sortierrichtung: 'ASC' oder 'DESC' (Standard: 'DESC') |

### Beispiel-Requests

Alle Profile mit mindestens 100 Punkten:

```http
GET /api/cogi/loyalty/customer-profiles?minPoints=100
```

Profile bestimmter Kunden:

```http
GET /api/cogi/loyalty/customer-profiles?customerIds=0x...,0x...,0x...
```

Profile eines bestimmten Levels:

```http
GET /api/cogi/loyalty/customer-profiles?levelId=0x...
```

Paginierte Ergebnisse:

```http
GET /api/cogi/loyalty/customer-profiles?limit=50&offset=100
```

Sortiert nach Punkten (aufsteigend):

```http
GET /api/cogi/loyalty/customer-profiles?sortBy=points&sortDirection=ASC
```

### Response

**Status: 200 OK**

```json
{
  "status": "success",
  "data": [
    {
      "id": "0x...",
      "customerId": "0x...",
      "points": 500,
      "pointsExpirationDate": "2025-12-31",
      "customFieldRewards": null,
      "setBirthday": true,
      "newsletter": false,
      "lastPointsReceived": "2024-01-20 14:30:00",
      "createdAt": "2024-01-15 10:30:00",
      "updatedAt": "2024-01-20 15:45:00",
      "level": {
        "id": "0x...",
        "name": "Silver",
        "minPoints": 100,
        "tagId": "0x...",
        "multiplier": 1.5,
        "color": "#FF5733"
      },
      "previousLevel": {
        "id": "0x...",
        "name": "Bronze",
        "minPoints": 0,
        "tagId": "0x...",
        "multiplier": 1.0,
        "color": "#C0C0C0",
        "pointsToFallDown": 400
      },
      "nextLevel": {
        "id": "0x...",
        "name": "Gold",
        "minPoints": 1000,
        "tagId": "0x...",
        "multiplier": 2.0,
        "color": "#FFD700",
        "pointsToReach": 500
      },
      "customer": {
        "id": "0x...",
        "email": "customer@example.com",
        "firstName": "Max",
        "lastName": "Mustermann",
        "customerNumber": "CUST-001"
      }
    }
  ],
  "total": 150,
  "limit": 20,
  "offset": 0
}
```

***

## 3. Kundentransaktionen abrufen

Ruft alle Transaktionen eines bestimmten Kunden ab.

### Endpunkt

```http
GET /api/cogi/loyalty/customer-transactions/{customerId}
```

### Parameter

| Parameter    | Typ           | Pflicht | Beschreibung      |
| ------------ | ------------- | ------- | ----------------- |
| `customerId` | string (path) | Ja      | Die ID des Kunden |

### Query-Parameter

| Parameter       | Typ     | Pflicht | Beschreibung                                          |
| --------------- | ------- | ------- | ----------------------------------------------------- |
| `received`      | boolean | Nein    | Filter nach empfangenen Transaktionen (true/false)    |
| `refund`        | boolean | Nein    | Filter nach erstatteten Transaktionen (true/false)    |
| `expired`       | boolean | Nein    | Filter nach abgelaufenen Transaktionen (true/false)   |
| `orderId`       | string  | Nein    | Filter nach Bestell-ID                                |
| `minValue`      | integer | Nein    | Mindestpunktwert                                      |
| `maxValue`      | integer | Nein    | Maximalpunktwert                                      |
| `limit`         | integer | Nein    | Anzahl Ergebnisse (Standard: 20)                      |
| `offset`        | integer | Nein    | Offset für Pagination (Standard: 0)                   |
| `sortBy`        | string  | Nein    | Sortierfeld (Standard: 'createdAt')                   |
| `sortDirection` | string  | Nein    | Sortierrichtung: 'ASC' oder 'DESC' (Standard: 'DESC') |

### Beispiel-Requests

Alle Transaktionen eines Kunden:

```http
GET /api/cogi/loyalty/customer-transactions/0x...
```

Nur empfangene Transaktionen:

```http
GET /api/cogi/loyalty/customer-transactions/0x...?received=true
```

Transaktionen einer bestimmten Bestellung:

```http
GET /api/cogi/loyalty/customer-transactions/0x...?orderId=0x...
```

Nur positive Transaktionen (Gutschriften):

```http
GET /api/cogi/loyalty/customer-transactions/0x...?minValue=1
```

Nur negative Transaktionen (Abzüge):

```http
GET /api/cogi/loyalty/customer-transactions/0x...?maxValue=-1
```

Paginierte Ergebnisse:

```http
GET /api/cogi/loyalty/customer-transactions/0x...?limit=50&offset=100
```

### Response

**Status: 200 OK**

```json
{
  "status": "success",
  "data": [
    {
      "id": "0x...",
      "customerId": "0x...",
      "orderId": "0x...",
      "salesChannelId": "0x...",
      "value": 100,
      "description": "Punkte für Bestellung #12345",
      "received": true,
      "refund": false,
      "expired": false,
      "manuallyDeducted": false,
      "manuallyAdded": false,
      "intervalDeduction": false,
      "mailSent": true,
      "expirationDate": "2025-12-31 23:59:59",
      "createdAt": "2024-01-15 10:30:00",
      "updatedAt": "2024-01-15 10:30:00",
      "order": {
        "id": "0x...",
        "orderNumber": "12345",
        "amountTotal": 100.00,
        "currency": "EUR"
      },
      "customer": {
        "id": "0x...",
        "email": "customer@example.com",
        "firstName": "Max",
        "lastName": "Mustermann",
        "customerNumber": "CUST-001"
      },
      "salesChannel": {
        "id": "0x...",
        "name": "Storefront"
      }
    },
    {
      "id": "0x...",
      "customerId": "0x...",
      "orderId": null,
      "salesChannelId": "0x...",
      "value": -50,
      "description": "Manueller Abzug",
      "received": false,
      "refund": false,
      "expired": false,
      "manuallyDeducted": true,
      "manuallyAdded": false,
      "intervalDeduction": false,
      "mailSent": false,
      "expirationDate": null,
      "createdAt": "2024-01-20 14:15:00",
      "updatedAt": "2024-01-20 14:15:00",
      "order": null,
      "customer": {
        "id": "0x...",
        "email": "customer@example.com",
        "firstName": "Max",
        "lastName": "Mustermann",
        "customerNumber": "CUST-001"
      },
      "salesChannel": {
        "id": "0x...",
        "name": "Storefront"
      }
    }
  ],
  "total": 45,
  "limit": 20,
  "offset": 0
}
```

***

## 4. Punkte hinzufügen

Fügt Punkte für einen bestimmten Kunden hinzu. Nur positive Werte sind erlaubt.

### Endpunkt

```http
POST /api/cogi/loyalty/add-points
```

### Request Body

| Parameter        | Typ           | Pflicht | Beschreibung                                                             |
| ---------------- | ------------- | ------- | ------------------------------------------------------------------------ |
| `customerId`     | string (UUID) | Ja      | Die ID des Kunden                                                        |
| `points`         | integer       | Ja      | Anzahl der Punkte (muss positiv sein, größer als 0)                      |
| `description`    | string        | Nein    | Beschreibung der Transaktion (Standard: "Manuell gesetzt via API")       |
| `salesChannelId` | string (UUID) | Nein    | ID des Sales Channels                                                    |
| `orderId`        | string (UUID) | Nein    | ID der Bestellung (falls die Punkte mit einer Bestellung verknüpft sind) |

### Beispiel-Request

Punkte hinzufügen:

```json
{
  "customerId": "0x...",
  "points": 100,
  "description": "Bonus für Kundenfeedback",
  "salesChannelId": "0x..."
}
```

### Response

**Status: 200 OK**

```json
{
  "status": "success",
  "message": "Points set successfully.",
  "transactionId": "0x...",
  "data": {
    "id": "0x...",
    "customerId": "0x...",
    "points": 550,
    "pointsExpirationDate": "2025-12-31",
    "customFieldRewards": null,
    "setBirthday": true,
    "newsletter": false,
    "lastPointsReceived": "2024-01-21 10:00:00",
    "createdAt": "2024-01-15 10:30:00",
    "updatedAt": "2024-01-21 10:00:00",
    "level": {
      "id": "0x...",
      "name": "Silver",
      "minPoints": 100,
      "tagId": "0x...",
      "multiplier": 1.5,
      "color": "#FF5733"
    },
    "previousLevel": {
      "id": "0x...",
      "name": "Bronze",
      "minPoints": 0,
      "tagId": "0x...",
      "multiplier": 1.0,
      "color": "#C0C0C0",
      "pointsToFallDown": 450
    },
    "nextLevel": {
      "id": "0x...",
      "name": "Gold",
      "minPoints": 1000,
      "tagId": "0x...",
      "multiplier": 2.0,
      "color": "#FFD700",
      "pointsToReach": 450
    },
    "customer": {
      "id": "0x...",
      "email": "customer@example.com",
      "firstName": "Max",
      "lastName": "Mustermann",
      "customerNumber": "CUST-001"
    }
  }
}
```

**Status: 400 Bad Request** (bei ungültigen Parametern)

```json
{
  "status": "error",
  "message": "customerId is required."
}
```

**Status: 404 Not Found** (wenn Kunde nicht gefunden)

```json
{
  "status": "error",
  "message": "Customer not found."
}
```

### Hinweise

* Punkte werden über `releasePoints` verarbeitet, was das Profil automatisch aktualisiert und Level-Änderungen berücksichtigt.
* Nur positive Werte (größer als 0) sind erlaubt.
* Wenn der Kunde noch kein Profil hat, wird automatisch eines erstellt.
* Für jede Punkte-Änderung wird eine Transaktion erstellt, die in der Historie sichtbar ist.

***

## 5. Punkte abziehen

Zieht Punkte von einem bestimmten Kunden ab. Nur positive Werte sind erlaubt (werden intern als negative Transaktion gespeichert).

### Endpunkt

```http
POST /api/cogi/loyalty/remove-points
```

### Request Body

| Parameter        | Typ           | Pflicht | Beschreibung                                                                    |
| ---------------- | ------------- | ------- | ------------------------------------------------------------------------------- |
| `customerId`     | string (UUID) | Ja      | Die ID des Kunden                                                               |
| `points`         | integer       | Ja      | Anzahl der abzuziehenden Punkte (muss positiv sein, größer als 0)               |
| `description`    | string        | Nein    | Beschreibung der Transaktion (Standard: "Manuell abgezogen via API")            |
| `salesChannelId` | string (UUID) | Nein    | ID des Sales Channels                                                           |
| `orderId`        | string (UUID) | Nein    | ID der Bestellung (falls die Punkte-Abzüge mit einer Bestellung verknüpft sind) |

### Beispiel-Request

Punkte abziehen:

```json
{
  "customerId": "0x...",
  "points": 50,
  "description": "Korrektur wegen fehlerhafter Gutschrift",
  "salesChannelId": "0x..."
}
```

### Response

**Status: 200 OK**

```json
{
  "status": "success",
  "message": "Points deducted successfully.",
  "transactionId": "0x...",
  "data": {
    "id": "0x...",
    "customerId": "0x...",
    "points": 450,
    "pointsExpirationDate": "2025-12-31",
    "customFieldRewards": null,
    "setBirthday": true,
    "newsletter": false,
    "lastPointsReceived": "2024-01-20 14:30:00",
    "createdAt": "2024-01-15 10:30:00",
    "updatedAt": "2024-01-21 11:00:00",
    "level": {
      "id": "0x...",
      "name": "Silver",
      "minPoints": 100,
      "tagId": "0x...",
      "multiplier": 1.5,
      "color": "#FF5733"
    },
    "previousLevel": {
      "id": "0x...",
      "name": "Bronze",
      "minPoints": 0,
      "tagId": "0x...",
      "multiplier": 1.0,
      "color": "#C0C0C0",
      "pointsToFallDown": 350
    },
    "nextLevel": {
      "id": "0x...",
      "name": "Gold",
      "minPoints": 1000,
      "tagId": "0x...",
      "multiplier": 2.0,
      "color": "#FFD700",
      "pointsToReach": 550
    },
    "customer": {
      "id": "0x...",
      "email": "customer@example.com",
      "firstName": "Max",
      "lastName": "Mustermann",
      "customerNumber": "CUST-001"
    }
  }
}
```

**Status: 400 Bad Request** (bei ungültigen Parametern oder unzureichenden Punkten)

```json
{
  "status": "error",
  "message": "Insufficient points. Customer has 30 points, but 50 points were requested to be deducted."
}
```

**Status: 404 Not Found** (wenn Kunde oder Profil nicht gefunden)

```json
{
  "status": "error",
  "message": "Customer profile not found. Cannot deduct points from non-existent profile."
}
```

### Hinweise

* Punkte werden direkt vom Profil abgezogen. Das Level wird automatisch neu berechnet.
* Nur positive Werte (größer als 0) sind erlaubt. Der Wert wird intern als negative Transaktion gespeichert.
* Der Endpunkt prüft, ob der Kunde genügend Punkte hat. Bei unzureichenden Punkten wird ein Fehler zurückgegeben.
* Der Kunde muss bereits ein Profil haben. Es wird kein Profil erstellt, wenn keines existiert.
* Für jeden Punkte-Abzug wird eine Transaktion mit negativem Wert erstellt, die in der Historie sichtbar ist.

***

## Datenstrukturen

### Profile-Objekt

Das Profil-Objekt enthält folgende Felder:

| Feld                   | Typ                       | Beschreibung                                                  |
| ---------------------- | ------------------------- | ------------------------------------------------------------- |
| `id`                   | string (UUID)             | Eindeutige ID des Profils                                     |
| `customerId`           | string (UUID)             | ID des zugehörigen Kunden                                     |
| `points`               | integer                   | Aktuelle Anzahl der Punkte                                    |
| `pointsExpirationDate` | string (date) \| null     | Ablaufdatum der Punkte (falls vorhanden)                      |
| `customFieldRewards`   | array \| null             | Custom Field Rewards                                          |
| `setBirthday`          | boolean                   | Ob Geburtstag gesetzt ist                                     |
| `newsletter`           | boolean                   | Newsletter-Abonnement Status                                  |
| `lastPointsReceived`   | string (datetime) \| null | Datum und Uhrzeit, wann der Kunde zuletzt Punkte erhalten hat |
| `createdAt`            | string (datetime)         | Erstellungsdatum des Profils                                  |
| `updatedAt`            | string (datetime)         | Letztes Aktualisierungsdatum                                  |

Hinweis: `lastPointsReceived` ist `null`, wenn der Kunde noch nie Punkte erhalten hat oder wenn keine Transaktion mit positivem Wert gefunden werden kann.

### Level-Objekt

```json
{
  "id": "string (UUID)",
  "name": "string",
  "minPoints": "integer",
  "tagId": "string (UUID)",
  "multiplier": "float",
  "color": "string (hex color)"
}
```

### Previous Level-Objekt

Enthält alle Felder des Level-Objekts plus:

```json
{
  "pointsToFallDown": "integer"
}
```

### Next Level-Objekt

Enthält alle Felder des Level-Objekts plus:

```json
{
  "pointsToReach": "integer"
}
```

### Customer-Objekt

```json
{
  "id": "string (UUID)",
  "email": "string",
  "firstName": "string",
  "lastName": "string",
  "customerNumber": "string"
}
```

### Transaction-Objekt

```json
{
  "id": "string (UUID)",
  "customerId": "string (UUID)",
  "orderId": "string (UUID) | null",
  "salesChannelId": "string (UUID) | null",
  "value": "integer",
  "description": "string | null",
  "received": "boolean",
  "refund": "boolean",
  "expired": "boolean",
  "manuallyDeducted": "boolean",
  "manuallyAdded": "boolean",
  "intervalDeduction": "boolean",
  "mailSent": "boolean",
  "expirationDate": "string (datetime) | null",
  "createdAt": "string (datetime)",
  "updatedAt": "string (datetime)"
}
```

### Order-Objekt (in Transaction)

```json
{
  "id": "string (UUID)",
  "orderNumber": "string",
  "amountTotal": "float",
  "currency": "string (ISO code)"
}
```

***

## Fehlerbehandlung

Alle Endpunkte können folgende Fehlerantworten zurückgeben:

### 400 Bad Request

```json
{
  "status": "error",
  "message": "Fehlerbeschreibung"
}
```

### 404 Not Found

```json
{
  "status": "error",
  "message": "Resource not found."
}
```

### 500 Internal Server Error

```json
{
  "status": "error",
  "message": "Error description: [Detaillierte Fehlerbeschreibung]"
}
```

***

{% stepper %}
{% step %}

### Hinweise: Pagination

Verwenden Sie `limit` und `offset` für große Datensätze. Die Standard-Limit beträgt 20 Einträge.
{% endstep %}

{% step %}

### Hinweise: Sortierung

Standardmäßig werden Ergebnisse nach `createdAt` (Transaktionen) bzw. `points` (Profile) in absteigender Reihenfolge sortiert.
{% endstep %}

{% step %}

### Hinweise: Filter-Kombinationen

Mehrere Filter können kombiniert werden, um präzise Ergebnisse zu erhalten.
{% endstep %}

{% step %}

### Hinweise: Assoziationen

Order-, Customer- und SalesChannel-Informationen werden nur zurückgegeben, wenn sie verfügbar sind. Prüfen Sie auf `null`-Werte.
{% endstep %}

{% step %}

### Hinweise: Punkte-Werte

In Transaktionen sind positive Werte Gutschriften und negative Werte Abzüge.
{% endstep %}

{% step %}

### Hinweise: UUID-Format

Alle IDs sind UUIDs im Binärformat (0x...). Stellen Sie sicher, dass Ihre Client-Implementierung diese korrekt verarbeitet.
{% endstep %}
{% endstepper %}

***

## Beispiele für häufige Use Cases

Alle Profile eines bestimmten Levels abrufen:

```http
GET /api/cogi/loyalty/customer-profiles?levelId=0x...&limit=100
```

Top-Kunden nach Punkten abrufen:

```http
GET /api/cogi/loyalty/customer-profiles?sortBy=points&sortDirection=DESC&limit=10
```

Alle Transaktionen eines Kunden für eine Bestellung:

```http
GET /api/cogi/loyalty/customer-transactions/0x...?orderId=0x...
```

Nur aktive (nicht abgelaufene) Transaktionen:

```http
GET /api/cogi/loyalty/customer-transactions/0x...?expired=false
```

Alle Transaktionen mit Gutschriften (positive Werte):

```http
GET /api/cogi/loyalty/customer-transactions/0x...?minValue=1
```

Punkte für einen Kunden hinzufügen:

```http
POST /api/cogi/loyalty/add-points
Content-Type: application/json

{
  "customerId": "0x...",
  "points": 100,
  "description": "Bonus für Kundenfeedback"
}
```

Punkte von einem Kunden abziehen:

```http
POST /api/cogi/loyalty/remove-points
Content-Type: application/json

{
  "customerId": "0x...",
  "points": 50,
  "description": "Korrektur wegen fehlerhafter Gutschrift"
}
```

***

## 6. Verfügbare Aktionen abrufen

Ruft alle Aktionen ab, die der Kunde noch ausführen kann, um weitere Punkte zu erhalten.

### Endpunkt

```http
GET /api/cogi/loyalty/available-actions/{customerId}
```

### Parameter

| Parameter    | Typ           | Pflicht | Beschreibung      |
| ------------ | ------------- | ------- | ----------------- |
| `customerId` | string (path) | Ja      | Die ID des Kunden |

### Query-Parameter

| Parameter        | Typ           | Pflicht | Beschreibung                                                          |
| ---------------- | ------------- | ------- | --------------------------------------------------------------------- |
| `salesChannelId` | string (UUID) | Nein    | ID des Sales Channels (falls nicht vom Kunden abgeleitet werden kann) |

### Response

**Status: 200 OK**

```json
{
  "status": "success",
  "data": {
    "availableActions": [
      {
        "type": "newsletter",
        "name": "Newsletter",
        "points": 50,
        "completed": false,
        "description": "Newsletter abonnieren"
      },
      {
        "type": "birthday",
        "name": "Geburtstag",
        "points": 100,
        "completed": false,
        "description": "Geburtstag im Profil speichern"
      },
      {
        "type": "customField",
        "name": "customFieldName",
        "points": 25,
        "completed": true,
        "description": "Profilinformationen vervollständigen (bereits ausgefüllt, wartet auf Belohnung)",
        "fieldFilled": true
      }
    ],
    "totalAvailablePoints": 175,
    "count": 3
  }
}
```

**Status: 404 Not Found** (wenn Kunde oder Profil nicht gefunden)

```json
{
  "status": "error",
  "message": "Customer not found."
}
```

### Verfügbare Aktionstypen

| Typ           | Beschreibung                     |
| ------------- | -------------------------------- |
| `newsletter`  | Newsletter-Abonnement            |
| `birthday`    | Geburtstag im Profil setzen      |
| `customField` | Custom Field im Profil ausfüllen |

### Response-Felder

| Feld          | Typ     | Beschreibung                                                     |
| ------------- | ------- | ---------------------------------------------------------------- |
| `type`        | string  | Typ der Aktion (newsletter, birthday, customField)               |
| `name`        | string  | Name der Aktion                                                  |
| `points`      | integer | Anzahl der Punkte, die für diese Aktion vergeben werden          |
| `completed`   | boolean | Ob die Aktion bereits ausgeführt wurde (aber noch nicht belohnt) |
| `description` | string  | Beschreibung der Aktion                                          |
| `fieldFilled` | boolean | (Nur bei customField) Ob das Feld bereits ausgefüllt ist         |

### Hinweise

* Newsletter: Wird nur angezeigt, wenn der Kunde noch kein Newsletter-Abonnement hat und noch keine Newsletter-Punkte erhalten hat.
* Geburtstag: Wird nur angezeigt, wenn der Geburtstag noch nicht gesetzt wurde und noch keine Geburtstags-Punkte erhalten wurden.
* Custom Fields: Werden nur angezeigt, wenn die Felder konfiguriert sind und noch nicht belohnt wurden. Die Aktion wird auch angezeigt, wenn das Feld bereits ausgefüllt ist, aber noch keine Belohnung erhalten hat.

***
