initial checkin

This commit is contained in:
2026-09-29 09:40:32 +00:00
commit 50b7ccd65f
34 changed files with 11874 additions and 0 deletions
+350
View File
@@ -0,0 +1,350 @@
---
goal: DataObject Structure Summary — Reuse Strategy for 24HRS Messe-Lotse
version: 1.2
date_created: 2026-06-10
last_updated: 2026-06-16
owner: 24HRS Team
status: Planned
tags: architecture, data-model, pimcore, reuse
---
# Introduction
![Status: Planned](https://img.shields.io/badge/status-Planned-blue)
Consolidated DataObject structures for the MesseLotse rewrite. Defines which existing Pimcore DataObjects are reused from `rkcFairBundle` and `dgmMediaBaseBundle`, what fields are added, and what new entities are created in `MessebauBundle`.
**Reuse strategy:** Extend `fair` and `fairLocation` in `rkcFairBundle` with MesseLotse-specific fields. Reuse `Person` from `dgmMediaBaseBundle` as the contact/worker entity. All trade-fair-management logic lives in the new `MessebauBundle`.
---
## 1. fairLocation — `rkcFairBundle` (extend existing)
| Field | Type | Notes |
|------------------|----------------------------|----------------------------------|
| active | bool | existing |
| swidentifier | input | existing |
| omitSync | bool | existing |
| modified | datetime | existing |
| address | input | existing |
| imagesKey | input | existing |
| vaAssetId | input | existing |
| image1–5 | image | existing |
| boxOptionsTree | input | existing |
| boxes | relation | existing |
| **+ name** | **input** | **new — locale name, e.g. "Messe Frankfurt"** |
| **+ googleMapsUrl** | **input** | **new** |
| **+ notes** | **textarea** | **new** |
| **+ contacts** | **ContactAssignment[] (FC)** | **new — see §1a** |
### 1a. FieldCollection: ContactAssignment
| Field | Type | Notes |
|-----------|--------------------|------------------------------------|
| person | many-to-one → Person | reuses dgmMediaBaseBundle Person |
| role | select | technical / billing / operations / general |
| validFrom | date | |
| validTo | date | nullable (null = indefinite) |
| notes | textarea | |
*Same person+role+timeframe pattern as WorkerAssignment (§6c), scoped to fairLocation.*
---
## 2. fair — `rkcFairBundle` (extend existing)
| Field | Type | Notes |
|--------------------|----------------------------|----------------------------------|
| name | input | existing |
| swidentifier | input | existing |
| active | bool | existing |
| omitSync | bool | existing |
| modified | datetime | existing |
| location | many-to-one → fairLocation | existing |
| setupStartDate | datetime | existing |
| fairStartDate | datetime | existing |
| fairEndDate | datetime | existing |
| destructEndDate | datetime | existing |
| imagesKey | input | existing |
| vaAssetId | input | existing |
| image1–5 | image | existing |
| boxOptionsTree | input | existing |
| boxes | relation | existing |
| assignedArticles | relation | existing |
| **+ setupEndDate** | **datetime** | **new** |
| **+ destructStartDate** | **datetime** | **new** |
| **+ hallsUsed** | **input** | **new — free text, e.g. "Halle 5.1, 6, 8"** |
| **+ notes** | **textarea** | **new** |
| **+ regulations** | **many-to-many → Asset** | **new — simple relation, no metadata** |
| **+ documents** | **FairDocument[] (FieldCollection)** | **new — see §2a** |
### 2a. FieldCollection: FairDocument
| Field | Type | Notes |
|--------------|------------------------|----------------------------------------------------|
| asset | many-to-one → Asset | the file |
| documentType | select | `constructionBriefing` / `floorPlan` / `protocol` |
| date | datetime | protocol date or revision date |
| hallName | input | hall reference for floor plans |
| remarks | textarea | optional |
---
## 3. Person — `dgmMediaBaseBundle` (reuse as-is)
| Field | Type | Notes |
|---------------------|-------------------------|------------------------------------|
| firstname | input | existing |
| lastname | input | existing |
| email | input | existing |
| company | input | existing |
| salutation | select | existing |
| gender | select | existing |
| additionalAddresses | mediaBaseAddress[] (FC) | existing — contains telefonNumber, eMailAddress, faxNumber, full address |
| ... +28 other fields | | existing |
Used as relation target for:
- `fairLocation.contactPerson`
- `Customer.contactPerson` (future)
- `WorkerAssignment.person` (future, Slice 5 of `architecture-vertical-slices-1.0.md`)
---
## 4. Customer — `MessebauBundle` (new DO)
*Deferred — an existing Customer DO lives in a bundle not currently accessible. This section will be updated when that bundle is available.*
| Field | Type | Notes |
|-------------------|-------------------------|------------------------------------|
| company | input | |
| address | input | |
| contactPerson | many-to-one → Person | reuses dgmMediaBaseBundle Person |
| brandDoc | document | company-wide brand guidelines |
| consultationDocs | document[] (gallery) | multi-fair planning docs |
| contractDocs | document[] (gallery) | framework agreements |
| notes | textarea | |
---
## 5. Job — `MessebauBundle` (new DO)
### 5a. Master data
| Field | Type | Notes |
|--------------|-----------------------------|----------------------------------------------------|
| project | input | display name |
| customer | many-to-one → Customer | |
| fair | many-to-one → fair | rkcFairBundle |
| standType | select | `Systemstand` / `Reihstand` / `Eckstand` / `Kopfstand` / `Blockstand` / `Inselstand` |
| standSize | input | e.g. "6x4" |
| standHeight | numeric | meters |
| hall | input | e.g. "Halle 5.1 / Stand C12" |
| area | numeric | m² |
| workflowState| input | managed by Symfony Workflow |
| notes | textarea | |
### 5b. Date overrides (all nullable — fallback to `fair`)
| Field | Type |
|------------------------|----------|
| setupStartOverride | datetime |
| setupEndOverride | datetime |
| eventStartOverride | datetime |
| eventEndOverride | datetime |
| teardownStartOverride | datetime |
| teardownEndOverride | datetime |
### 5c. Asset fields
| Field | Type | Notes |
|-------------------------|--------------|--------------------------------------------|
| standImage | image | single booth photo |
| standGallery | image[] | gallery |
| briefingCustomerDoc | document | per-job override; null → inherit from customer |
| briefingPlanDoc | document | per-job override; null → inherit from fair floorPlan |
| briefingAdditionalDoc | document | |
| powerConfirmation | document | |
| wlanConfirmation | document | |
| cleaningConfirmation | document | |
| riggingQuote | document | |
| riggingDrawing | document | |
| riggingMesseConfirmation| document | |
| standApprovalDoc | document | |
| acceptancePhotos | image[] | |
| acceptanceSignature | image | |
| weeklyProtocols | document[] | |
### 5d. FieldCollections
| FieldCollection | Fields |
|----------------------|--------------------------------------------------------------------------------------------|
| BookingPlatformInfo | portalLink, email, password (encrypted), deadline |
| PowerInfo | kw, distributor, deadline |
| WlanInfo | type, deadline |
| CleaningInfo | deadline |
| RiggingInfo | supplierFirstname, supplierLastname, supplierEmail, supplierPhone, messeFirstname, messeLastname, messeEmail, messePhone, deadline |
| DruckproduktionInfo | qm, blockout, forexplatten, deadline |
| CateringInfo | baristaEnabled, baristaPackage, days, drinksEnabled, drinksDetails, foodEnabled, foodDetails |
| CostEstimate | standConstruction (int, EUR), activation (int, EUR), furniture (int, EUR), logistics (int, EUR) |
| Material | type (flooring/standsystem/hardware/furniture), name, quantity, notes — **multi** |
| ChecklistItem | text, checked, order — **multi** |
---
## 6. Resource Pool Entities — `MessebauBundle` (Slice 5)
*All person references reuse `Person` from dgmMediaBaseBundle.*
### 6a. Tree-Based Assignment Pattern
Assignment and booking entities are standalone DataObjects placed in the Pimcore tree under a `fair` or `Job` instance. Tree location expresses scope — no nullable `job` relation field is needed.
```
/Fairs/OMR2026/
├── ResourceAssignments/
│ ├── WA-pool-01 (fair-pool worker)
│ ├── PVA-pool-01 (fair-pool vehicle)
│ └── ...
├── AccommodationBookings/
│ ├── Hotel-Central/
│ │ └── Occupants/
│ │ ├── Anna-Müller
│ │ └── Max-Schmidt
│ └── Airbnb-Loft/
│ └── Occupants/
│ └── Lisa-Weber
├── Travel/
│ ├── Bahn-HH-Berlin/
│ │ └── Passengers/
│ │ ├── Anna-Müller
│ │ └── Max-Schmidt
│ └── Mietwagen-Frankfurt/
│ └── Passengers/
│ └── Lisa-Weber
├── Jobs/
│ ├── BoothBrevo/
│ │ └── ResourceAssignments/
│ │ ├── WA-001 (job-dedicated worker)
│ │ └── PVA-001 (job-dedicated vehicle)
│ └── BoothDmexco/
│ └── ResourceAssignments/
│ └── WA-002 (job-dedicated worker)
```
**Scope**: parent folder is `.../ResourceAssignments/` under `fair` → fair-pool (available for all jobs). Parent folder is `.../Jobs/{job}/ResourceAssignments/` → dedicated to that specific job. Bookings live directly under fair.
**Aggregation queries** (fair-level "how many Baristas?"):
```php
$listing = new WorkerAssignment\Listing();
$listing->setCondition("o_path LIKE '/Fairs/OMR2026/%'");
$allAssignments = $listing->load();
```
This returns both fair-pool and all job-dedicated assignments in one query. For scoped queries:
```php
// Fair-pool only
"o_path LIKE '/Fairs/OMR2026/ResourceAssignments/%'"
// Specific job only
"o_path LIKE '/Fairs/OMR2026/Jobs/BoothBrevo/ResourceAssignments/%'"
```
### 6b. Pool Entities (shared resource catalog)
| DO | Fields | Tree location |
|---|---|---|
| WorkerRole | name (Barista / Rigger / LorryDriver / FairWorker / Electrician / Cleaner) | `/ResourcePool/WorkerRoles/` |
| PoolVehicle | name, type, licensePlate, state (owned/hired/toHire), notes | `/ResourcePool/Vehicles/` |
| Equipment | name, description, state (owned/rented/toRent), notes | `/ResourcePool/Equipment/` |
| Accommodation | name, address, bookingReference, type (hotel/apartment/other), notes | `/ResourcePool/Accommodations/` |
### 6c. Worker + Vehicle + Equipment Assignments (standalone DOs, tree-scoped)
| DO | Fields | Tree location |
|---|---|---|
| WorkerAssignment | person → Person, role → WorkerRole, state (select: internal / hired / toHire, default from WorkerRole), startDate (datetime), endDate (datetime), offerDoc (document, nullable, external only), contractDoc (document, nullable, external only), billingDoc (document, nullable, external only), notes (textarea) | `/Fairs/{fair}/ResourceAssignments/` or `/Fairs/{fair}/Jobs/{job}/ResourceAssignments/` |
| PoolVehicleAssignment | poolVehicle → PoolVehicle, startDate (datetime), endDate (datetime), notes | same pattern |
| EquipmentAssignment | equipment → Equipment, startDate (datetime), endDate (datetime), notes | same pattern |
### 6d. Accommodation — Booking + Occupants Pattern
One real-world booking covers N persons. Documents (offer/contract/billing) live on the booking parent. Occupants are tree children.
**AccommodationBooking** (parent)
| Field | Type | Notes |
|---|---|---|
| accommodation | → Accommodation | |
| checkIn | date | |
| checkOut | date | |
| confirmationNumber | input | |
| offerDoc | document | nullable |
| contractDoc | document | nullable |
| billingDoc | document | nullable |
| totalCost | numeric (EUR) | nullable, for split billing |
| notes | textarea | |
Tree: `/Fairs/{fair}/AccommodationBookings/`
**AccommodationOccupant** (tree child of booking)
| Field | Type | Notes |
|---|---|---|
| person | → Person | |
| costShare | numeric (EUR) | nullable, for split billing |
Tree: `/Fairs/{fair}/AccommodationBookings/{booking}/Occupants/`
### 6e. Travel — Booking + Passengers Pattern
Same pattern as accommodation: one booking covers N travelers. Documents on the parent, passengers as children.
**TravelBooking** (parent)
| Field | Type | Notes |
|---|---|---|
| transportMethod | select | train / plane / rentalVan / ownCar |
| origin | input | |
| destination | input | |
| departureDateTime | datetime | |
| arrivalDateTime | datetime | |
| returnDepartureDateTime | datetime | nullable |
| returnArrivalDateTime | datetime | nullable |
| bookingReference | input | |
| offerDoc | document | nullable |
| contractDoc | document | nullable |
| billingDoc | document | nullable |
| totalCost | numeric (EUR) | nullable |
| notes | textarea | |
Tree: `/Fairs/{fair}/Travel/`
**TravelPassenger** (tree child of booking)
| Field | Type | Notes |
|---|---|---|
| person | → Person | |
| costShare | numeric (EUR) | nullable |
Tree: `/Fairs/{fair}/Travel/{booking}/Passengers/`
---
## 7. Bundle Responsibility Split
| Bundle | Owns | Reuses |
|-----------------------|-----------------------------------------------------|-----------------------------------|
| `rkcFairBundle` | fair + fairLocation (extended) | — |
| `dgmMediaBaseBundle` | Person | — |
| `MessebauBundle` | Customer, Job, ContactAssignment FC, FairDocument FC, all Job FCs, resource pool entities | Person, fair, fairLocation |
---
## 8. Related Documents
- [architecture-vertical-slices-1.0.md](architecture-vertical-slices-1.0.md) — implementation plan with 6 AI-sized vertical slices
- [architecture-rewrite-1.0.md](architecture-rewrite-1.0.md) — original plan (superseded, retained for reference)
- [ai-document-skills.md](ai-document-skills.md) — AI skill catalog and field routing matrix
- [3d-booth-generation.md](3d-booth-generation.md) — SketchUp + Aluvision + MCP pipeline