---
name: bdd-gherkin
description: >
  Use when: writing Gherkin BDD scenarios for PHR/payroll workflows, creating feature files
  for lpbunified or WCS modules, building Xray traceability, or translating business requirements
  into Given/When/Then format readable by PHR functional analysts and PO's (SAFe team).
  Triggers: "gherkin", "BDD", "given when then", "scenario", "feature file", "acceptatietest",
  "business scenario", "cucumber", "Xray", "Jira traceability", "@RiskLevel", "SAFe"
---

# SKILL: BDD Gherkin — Lima Next Gen (lpbunified + WCS)

Referentie voor Gherkin BDD scenario's voor lpbunified en WCS. Schrijf in het Nederlands.
Scenario's zijn **levende documentatie** — PO's lezen deze zonder codekennis.

## Lima Next Gen Xray Standaard

**Verplichte tags op elke Feature of Scenario:**

```gherkin
@Xray-LN1234 @RiskLevel-High
Functie: DIMONA-aangifte flow
```

| Tag | Formaat | Waarden |
|-----|---------|---------|
| `@Xray-LNXXXX` | Jira ticket ID | `@Xray-LN1234`, `@Xray-WCS-456` |
| `@RiskLevel-X` | Risicoclassificatie | `@RiskLevel-High`, `@RiskLevel-Medium`, `@RiskLevel-Low` |
| `@Smoke` | Snelle sanity check | Subset voor pipeline gate |
| `@Regression` | Volledige regressie | Nightly run |
| `@Security` | RBAC / auth testen | Altijd bij multi-tenant + rol-checks |

## Taalconventies

```gherkin
# language: nl

@Xray-LN0000 @RiskLevel-Medium
Functie: [Domein — kort beschrijvend]
  Als [rol]
  Wil ik [wat doen]
  Zodat [businesswaarde]

  Scenario: [actief beschrijvend, positief]
  Scenario: [negatief pad beschrijven wat fout gaat]
  Scenarioschema: [meerdere data-combinaties]
```

**Rollen**: personeelslid, HR-medewerker, payroll-beheerder, diensthoofd, loonsecretaris, EGOV-admin, WCS-beheerder, klant-beheerder

## Standaard Achtergrond

```gherkin
Achtergrond:
  Gegeven ik ben aangemeld als "HR-medewerker" voor werkgever "Testgemeente"
  En de actieve loonperiode is "januari 2026"
  En de tenant context is "sndb=TESTGEM"
```

### Xray Voorbeeld met Rollen (EGOV/LTDS)

```gherkin
@Xray-LN1234 @Security @RiskLevel-High
Functie: EGov Admin toegang tot LTDS API
  Als EGOV Admin
  Wil ik LTDS declaraties kunnen raadplegen
  Zodat ik de RSZ-aangifte kan bewaken

  Scenarioschema: API toegangscontrole per rol
    Gegeven ik ben geauthenticeerd via Keycloak als "<Rol>"
    En de tenant context is "<TenantID>"
    Als ik een GET-verzoek stuur naar "/api/v1/egov/ltds/declarations/<DeclaratieID>"
    Dan antwoordt de API met statuscode "<StatusCode>"
    En is er een audit log entry aangemaakt met actie "READ_LTDS"

    Voorbeelden:
      | Rol           | TenantID    | DeclaratieID | StatusCode |
      | EGOV Admin    | sndb=TESTGEM | valid_01    | 200        |
      | PO            | sndb=TESTGEM | valid_01    | 403        |
      | GS Klant      | sndb=TESTGEM | valid_01    | 403        |
```

## Domein-specifieke Scenario's

### Maandverwerking (e-kalender)
```gherkin
Functie: Maandafsluiting e-Kalender
  Als payroll-beheerder
  Wil ik de maand januari 2026 afsluiten
  Zodat de loonberekening kan starten

  Scenario: Succesvolle maandafsluiting
    Gegeven alle prestaties voor januari 2026 zijn ingegeven
    En de maandstatus staat op "Open"
    Als ik de maandafsluiting start voor januari 2026
    Dan staat de status op "Afgesloten"
    En ontvang ik een bevestigingsmail

  Scenario: Afsluiting met ontbrekende prestaties
    Gegeven 3 medewerkers hebben geen prestaties voor januari 2026
    Als ik de maandafsluiting start
    Dan zie ik een waarschuwingslijst met de 3 betrokken medewerkers

  Scenario: Heropenen afgesloten maand
    Gegeven de maandstatus staat op "Afgesloten"
    Als ik de maand heropent
    Dan staat de status op "Open"
    En kunnen prestaties opnieuw aangepast worden
```

### Loonberekening
```gherkin
Functie: Loonsimulatie
  Als HR-medewerker

  Scenario: Simulatie voltijds personeelslid barema B1
    Gegeven het personeelslid heeft barema "B1" trap "0"
    En een voltijdse betrekking (100%)
    Als ik een loonsimulatie uitvoer
    Dan toont het resultaat het bruto maandloon
    En de werkgeversbijdrage RSZ
    En het netto maandloon na inhoudingen

  Scenarioschema: Simulatie met variabel percentage
    Gegeven barema "B1" trap "0" en "<percentage>%" tewerkstelling
    Als ik een loonsimulatie uitvoer
    Dan bedraagt het netto maandloon "<netto>"
    Voorbeelden:
      | percentage | netto    |
      | 100        | 2.187,50 |
      | 50         | 1.093,75 |
```

### DIMONA
```gherkin
Functie: DIMONA-aangifte

  Scenario: DIMONA-IN voor nieuwe medewerker
    Gegeven een nieuw personeelslid start op "01-02-2026"
    Als ik een DIMONA-IN aangifte indien
    Dan ontvangt de aangifte een RSZ-referentienummer
    En de status is "Ingediend bij RSZ"

  Scenario: Ongeldige INSZ weigeren
    Gegeven rijksregisternummer "12345" (ongeldig)
    Als ik de aangifte wil indienen
    Dan verschijnt "Ongeldig rijksregisternummer"
```

### Multi-tenant Isolatie
```gherkin
Functie: Data-isolatie tussen gemeenten

  Scenario: Gemeente A ziet geen personeel van gemeente B
    Gegeven ik ben aangemeld als medewerker van "Gemeente A"
    Als ik het personeelsoverzicht open
    Dan zie ik enkel personeel van "Gemeente A"
    En zijn medewerkers van andere gemeenten niet zichtbaar
```

## Traceability Matrix Template (Xray-ready)

```markdown
| Xray ID | Feature | Jira Ticket | RiskLevel | Test Type | Tool | Status |
|---------|---------|-------------|-----------|-----------|------|--------|
| LN-EKA-001 | Maandafsluiting | REQ-EKA-045 | High | E2E | Playwright | 🔄 In progress |
| LN-DIM-001 | DIMONA-IN | REQ-DIM-012 | High | Integration | REST Assured | ✅ Klaar |
| LN-PAY-001 | Loonsimulatie | REQ-PAY-089 | Medium | E2E | Playwright | ❌ Gepland |
| WCS-USR-001 | Gebruiker aanmaken | WCS-234 | High | E2E | Cypress | ✅ Klaar (happy) |
| WCS-USR-002 | Dubbele gebruiker weigeren | WCS-234 | Medium | E2E | Cypress | ❌ Gepland |
| WCS-SEC-001 | @AuthorizeAction coverage | WCS-456 | High | Integration | JUnit reflectie | ❌ Gepland |
```

## Anti-patronen

| ❌ NIET | ✅ WEL |
|---------|-------|
| "Gegeven ik POST naar /rest/..." | Domein-taal zonder technische details |
| "Dan bevat de JSON 'status': 'OK'" | "Dan staat de status op 'Afgesloten'" |
| `new Date()` in scenario's | Expliciete datum "januari 2026" |
| Engelstalige Gherkin | Nederlands voor PHR-domein |
| Feature zonder `@Xray-ID` | Altijd `@Xray-LNXXXX` toevoegen |
| Feature zonder `@RiskLevel` | Altijd risico classificeren |
| Hardcoded INSZ/KBO in scenario's | Placeholder `<INSZ>` of `${werkgeverId}` |
