# Behaelter and Member Number Widget
This document describes the implementation of a widget for editing both behaelter (container) numbers and their corresponding member numbers in the backend.
## Overview
The implementation allows backend users to:
- Edit both behaelter numbers and their corresponding member numbers in a paired interface
- See which member number is associated with each behaelter
- Change the member number for individual behaelters
- Leave the member number field empty to use the booking member's number as a fallback
## Implementation Details
### 1. Widget Configuration
The behaelter_numbers field in `tl_vr_wa_reservation.php` has been updated to use the multiColumnWizard input type with two columns:
- **Behälternummer**: A text input for the behaelter number with validation for natural numbers
- **Mitgliedsnummer**: A text input for the member number with validation for natural numbers
```php
'behaelter_numbers' => array
(
'exclude' => true,
'inputType' => 'multiColumnWizard',
'eval' => array(
'tl_class' => 'clr',
'columnFields' => array
(
'behaelter' => array
(
'label' => $GLOBALS['TL_LANG']['MSC']['wa_behaelter_number'],
'inputType' => 'text',
'eval' => array('style' => 'width:200px', 'mandatory' => true, 'rgxp' => 'natural')
),
'member' => array
(
'label' => $GLOBALS['TL_LANG']['MSC']['wa_member_number'],
'inputType' => 'text',
'eval' => array('style' => 'width:200px', 'rgxp' => 'natural')
)
)
),
'sql' => "text NULL"
),
```
### 2. Callback Modifications
#### Load Callback
The `onBehaelterNumbersLoadCallback` method has been updated to:
- Handle the new data format (array of objects with behaelter and member)
- Convert old format data (simple array of behaelter numbers) to the new format
- Return the data in the format expected by the multiColumnWizard
```php
public function onBehaelterNumbersLoadCallback($varValue, DataContainer $dc)
{
if (!empty($varValue))
{
$decodedValue = \json_decode($varValue, true);
// Check if we have the new format (array of objects with behaelter and member)
// or the old format (simple array of behaelter numbers)
$isNewFormat = isset($decodedValue[0]) && is_array($decodedValue[0]) && isset($decodedValue[0]['behaelter']);
if ($isNewFormat) {
// The data is already in the correct format for the multiColumnWizard
return $decodedValue;
} else {
// Convert old format to new format
$result = [];
// Get the member associated with this reservation as fallback
$reservation = \vonRotenberg\WeinanlieferungBundle\Model\WeinanlieferungReservationModel::findByPk($dc->id);
$memberId = $reservation ? $reservation->uid : 0;
$memberModel = \Contao\MemberModel::findById($memberId);
$defaultMemberNo = $memberModel ? $memberModel->memberno : '';
foreach ($decodedValue as $behaelterNumber) {
$result[] = [
'behaelter' => $behaelterNumber,
'member' => $defaultMemberNo
];
}
return $result;
}
}
return $varValue;
}
```
#### Save Callback
The `onBehaelterNumbersSaveCallback` method has been updated to:
- Handle the data format from the multiColumnWizard (array of rows with behaelter and member)
- Validate the behaelter numbers
- Process the member numbers, using the default member number as a fallback if a member number is empty
- Return the processed data as JSON
```php
public function onBehaelterNumbersSaveCallback($varValue, DataContainer $dc)
{
if (!empty($varValue) && is_array($varValue))
{
// ... validation code ...
// Get the member associated with this reservation as fallback
$memberId = $reservation->uid;
$memberModel = \Contao\MemberModel::findById($memberId);
$defaultMemberNo = $memberModel ? $memberModel->memberno : '';
// Process the data from the multiColumnWizard
$processedData = [];
foreach ($varValue as $item) {
$behaelterNumber = $item['behaelter'];
// If member number is empty, use the default member number
$memberNumber = !empty($item['member']) ? $item['member'] : $defaultMemberNo;
$processedData[] = [
'behaelter' => $behaelterNumber,
'member' => $memberNumber
];
}
// Return the processed data as JSON
return json_encode($processedData);
}
return $varValue;
}
```
### 3. Language Labels
Language labels have been added to the default.php language file for the column headers:
```php
$GLOBALS['TL_LANG']['MSC']['wa_behaelter_number'] = 'Behälternummer';
$GLOBALS['TL_LANG']['MSC']['wa_member_number'] = 'Mitgliedsnummer';
```
## Data Structure
The behaelter_numbers field stores a JSON-encoded array of objects, each with:
- `behaelter`: The behaelter number
- `member`: The associated member number
Example:
```json
[
{
"behaelter": "123",
"member": "456"
},
{
"behaelter": "789",
"member": "456"
}
]
```
## Backward Compatibility
The implementation maintains backward compatibility with existing data:
- If the behaelter_numbers field contains the old format (simple array of behaelter numbers), it's automatically converted to the new format
- For old data, all behaelters are associated with the booking member's number
- The existing CSV export functionality continues to work with both old and new data formats
## Usage
To use the widget:
1. Edit a reservation in the backend
2. Scroll to the "Check-in" section
3. Enter behaelter numbers and optionally member numbers for each behaelter
4. If a member number is left empty, the booking member's number will be used as a fallback
5. Save the reservation
## Integration with Existing Features
This widget integrates with the existing features:
- The CSV export functionality uses the member numbers associated with each behaelter
- The backend booking list displays the behaelter numbers with their associated member numbers
- The check-in process in the frontend continues to work with the new data structure