# SQL prenotazione picking list Python-only

## Script

- `apply_python_parallel_pickinglist_patch.sql`
- `rollback_python_parallel_pickinglist_patch.sql`

## Obiettivo

Permettere a Python e C# di lavorare sullo stesso database senza condividere le stesse stored procedure operative.

Il C# continua a usare gli oggetti legacy:

- `dbo.XMag_ViewPackingList`
- `dbo.ViewPackingListRestante`
- `dbo.sp_xExePackingListPallet`
- `dbo.sp_xExePackingListPalletPrenota`
- `dbo.sp_ControllaPrenotazionePackingListPalletNew`

Il Python usa oggetti separati:

- `dbo.py_XMag_ViewPackingList`
- `dbo.py_ViewPackingListRestante`
- `dbo.py_sp_xExePackingListPallet`
- `dbo.py_sp_xExePackingListPalletPrenota`
- `dbo.py_sp_ControllaPrenotazionePackingListPalletNew`
- `dbo.PyPickingListReservation`

## Tabella `dbo.PyPickingListReservation`

### Scopo

Contiene la singola picking list prenotata dal programma Python.

### Schema

| Colonna | Tipo | Ruolo |
| --- | --- | --- |
| `ID` | `tinyint` | sempre `1`, enforced da check constraint |
| `Documento` | `varchar(8)` | documento prenotato |
| `IDOperatore` | `int` | operatore che ha fatto l'ultima azione |
| `ModUtente` | `varchar(50)` | login operatore |
| `ModDataOra` | `datetime` | timestamp modifica |

### Vincoli

- Primary key su `ID`.
- Check `ID = 1`.

Questa scelta implementa un singleton DB: il Python puo' avere una sola lista prenotata dal backoffice.

## Vista `dbo.py_XMag_ViewPackingList`

### Scopo

Replica la vista legacy `dbo.XMag_ViewPackingList` ma calcola `IDStato` usando `PyPickingListReservation`, non `Celle.IDStato` legacy.

### Logica `IDStato`

```sql
CASE
    WHEN pr.Documento IS NOT NULL
     AND pr.Documento = CAST(legacy.Documento AS varchar(8))
    THEN 1
    ELSE 0
END AS IDStato
```

## Vista `dbo.py_ViewPackingListRestante`

### Scopo

Espone solo le UDC non ancora spedite:

```sql
WHERE Cella <> 9999
```

La UI "Gestione Picking List" usa questa vista sia per la griglia alta sia per il dettaglio.

## Stored `dbo.py_sp_xExePackingListPallet`

### Parametri

| Parametro | Tipo | Ruolo |
| --- | --- | --- |
| `@IDOperatore` | `int` | operatore corrente |
| `@Documento` | `varchar(8)` | documento da prenotare/sprenotare |
| `@Azione` | `char(1)` | `P` prenota, `S` s-prenota |
| `@RC` | `int OUTPUT` | codice ritorno |

### Validazioni

- `@Azione` deve essere `P` o `S`, altrimenti `@RC = -10`.
- Il documento deve esistere in `py_XMag_ViewPackingList`, altrimenti `@RC = -20`.
- Se manca la riga singleton in `PyPickingListReservation`, viene creata.

### Prenotazione `P`

1. Se il documento e' gia' attivo, ritorna senza modifiche.
2. Azzera `IDStato` su tutte le celle con stato diverso da zero.
3. Mette `IDStato = 1` sulle celle del documento target.
4. Aggiorna `PyPickingListReservation` con documento, operatore e timestamp.
5. Scrive log tramite `sp_LogPackingList`.

### S-prenotazione `S`

1. Se il documento attivo non e' quello richiesto, ritorna senza modifiche.
2. Azzera `IDStato` sulle celle target.
3. Pulisce `PyPickingListReservation.Documento`.

## Stored `dbo.py_sp_xExePackingListPalletPrenota`

### Scopo

Mette `IDStato = 1` sulle celle ancora residue del documento. Viene usata dal controllo automatico prenotazione.

## Stored `dbo.py_sp_ControllaPrenotazionePackingListPalletNew`

### Scopo

Mantiene coerente la prenotazione mentre la picking list viene consumata dal barcode.

### Logica

1. Legge documento attivo da `PyPickingListReservation`.
2. Se non c'e' documento attivo, termina.
3. Se non esistono piu' righe residue in `py_ViewPackingListRestante`:
   - azzera `Celle.IDStato`;
   - svuota `PyPickingListReservation.Documento`;
   - termina.
4. Se esistono ancora residui:
   - azzera tutti gli `IDStato`;
   - richiama `py_sp_xExePackingListPalletPrenota` per prenotare le celle residue.

## Rollback

`rollback_python_parallel_pickinglist_patch.sql` elimina:

- `py_sp_ControllaPrenotazionePackingListPalletNew`
- `py_sp_xExePackingListPalletPrenota`
- `py_sp_xExePackingListPallet`
- `py_ViewPackingListRestante`
- `py_XMag_ViewPackingList`
- `PyPickingListReservation`

Non tocca gli oggetti legacy C#.

## Note review

- La stored Python usa una prenotazione singleton, quindi non gestisce due liste prenotate backoffice.
- L'azzeramento globale di `Celle.IDStato` e' coerente con la semantica attuale, ma in futuro dovra' essere rivalutato se piu' operatori o magazzini lavorano in parallelo.
- Le UDC non scaffalate condividono il fallback dati del modello legacy; questo e' noto e andra' riprogettato nel nuovo schema FlyWMS.
