OrderResource
Die OrderResource verwaltet alle Dolmetsch-Aufträge der Plattform.
Konfiguration
File: OrderResource.php
| Eigenschaft | Wert |
|---|---|
| Model | App\Models\Order |
| Navigation Group | Auftragsverwaltung |
| Navigation Label | Aufträge |
| Navigation Icon | heroicon-o-shopping-bag |
| Navigation Sort | 1 |
State Machine
State-Farben
| State | Farbe | Beschreibung |
|---|---|---|
| Draft | gray | Entwurf |
| Open | warning | Offen, sucht Sprachmittler |
| Assigned | info | Sprachmittler zugewiesen |
| Running | primary | Termin läuft |
| Completed | success | Abgeschlossen |
| Cancelled | danger | Storniert |
| NotMatched | danger | Kein Sprachmittler gefunden |
| InvoiceCreated | info | Rechnung erstellt |
| PaymentInstructed | warning | Zahlung angewiesen |
| PaymentReceived | success | Zahlung erhalten |
Form-Struktur
Allgemeine Informationen
| Feld | Typ | Beschreibung |
|---|---|---|
| order_number | TextInput | Automatisch generiert, readonly |
| appointment_category_id | Select | Terminart (Behörde, Arzt, etc.) |
Auftraggeber
Forms\Components\Select::make('requester_id')
->relationship('requester', 'full_name')
->searchable()
->preload()
->createOptionForm([
// Inline-Erstellung eines neuen Auftraggebers
Forms\Components\TextInput::make('first_name')->required(),
Forms\Components\TextInput::make('last_name')->required(),
Forms\Components\TextInput::make('email')->email()->required(),
Forms\Components\TextInput::make('phone'),
Forms\Components\Hidden::make('role')->default('requester'),
])
->createOptionUsing(function (array $data) {
$user = User::create([
...$data,
'password' => bcrypt(Str::random(16)),
'state' => new Active,
]);
return $user->id;
})
Klient-Informationen
| Feld | Typ | Validierung |
|---|---|---|
| client_salutation | Select | nullable |
| client_first_name | TextInput | required, max:255 |
| client_last_name | TextInput | required, max:255 |
| client_phone | TextInput | nullable |
| client_email | TextInput | nullable, email |
| client_country_code | Select | 185+ Länder |
Termin-Details
| Feld | Typ | Beschreibung |
|---|---|---|
| scheduled_date | DatePicker | Termindatum |
| scheduled_time | TimePicker | Terminzeit |
| estimated_duration | TextInput | Geschätzte Dauer (Minuten) |
| location_street | TextInput | Straße |
| location_house_number | TextInput | Hausnummer |
| location_postal_code | TextInput | PLZ |
| location_city | TextInput | Stadt |
| location_additional_info | Textarea | Zusatzinfo (Raum, Etage) |
Check-In/Out Zeiten
Nur sichtbar bei entsprechendem State:
Forms\Components\Section::make('Check-In/Out')
->visible(fn (?Order $record) => $record?->state instanceof Assigned
|| $record?->state instanceof Running
|| $record?->state instanceof Completed)
->schema([
Forms\Components\DateTimePicker::make('check_in_time')
->label('Check-In Zeit'),
Forms\Components\DateTimePicker::make('check_out_time')
->label('Check-Out Zeit')
->visible(fn (?Order $record) => $record?->state instanceof Running
|| $record?->state instanceof Completed),
])
Sprachmittler-Präferenzen
| Feld | Typ | Beschreibung |
|---|---|---|
| desired_interpreter_id | Select | Wunsch-Sprachmittler |
| preferred_interpreter_gender | Select | Geschlechtspräferenz |
| interpreter_notes | Textarea | Hinweise für Sprachmittler |
Sprach-Informationen
| Feld | Typ | Beschreibung |
|---|---|---|
| client_languages | Select | Max 3 Sprachen des Klienten |
| target_language_codes | Select | Zielsprache (DE/EN) |
Kosten
Nur bei abgeschlossenen Aufträgen editierbar:
Forms\Components\Section::make('Kosten')
->visible(fn (?Order $record) => $record?->state instanceof Completed)
->schema([
Forms\Components\TextInput::make('total_amount')
->numeric()
->prefix('€')
->disabled(fn (?Order $record) => !$record?->state instanceof Completed),
Forms\Components\Repeater::make('additional_costs')
->relationship()
->schema([
Forms\Components\Select::make('category')
->options([
'travel' => 'Fahrtkosten',
'waiting' => 'Wartezeit',
'materials' => 'Materialien',
'overtime' => 'Überstunden',
'other' => 'Sonstiges',
])
->required(),
Forms\Components\TextInput::make('amount')
->numeric()
->prefix('€')
->required(),
Forms\Components\TextInput::make('description'),
]),
])
Table-Konfiguration
Spalten
| Spalte | Typ | Beschreibung |
|---|---|---|
| order_number | TextColumn | Sortierbar |
| requester.full_name | TextColumn | Auftraggeber |
| scheduled_at | TextColumn | Formatiert als Datum+Zeit |
| state | BadgeColumn | Farbcodiert |
| appointment_category.name | TextColumn | Terminart |
| full_address | TextColumn | Zusammengesetzte Adresse |
| client_languages | BadgeColumn | Klient-Sprachen |
| target_languages | BadgeColumn | Zielsprachen |
| total_amount | TextColumn | Mit € Suffix |
| current_interpreter.full_name | TextColumn | Aktueller Sprachmittler |
| is_over_30km | IconColumn | Indikator für weite Anfahrt |
Filter
| Filter | Typ | Beschreibung |
|---|---|---|
| scheduled_date | DateRangeFilter | Terminzeitraum |
| requester_id | SelectFilter | Auftraggeber |
| appointment_category_id | SelectFilter | Terminart |
| is_overdue | TernaryFilter | Überfällige Aufträge |
| is_today | TernaryFilter | Heutige Aufträge |
| is_this_week | TernaryFilter | Diese Woche |
| state | SelectFilter | Status |
Actions
State-Transition Actions
Action::make('assign')
->label('Sprachmittler zuweisen')
->icon('heroicon-o-user-plus')
->visible(fn (Order $record) => $record->state instanceof Open)
->form([
Forms\Components\Select::make('interpreter_id')
->label('Sprachmittler')
->options(function (Order $record) {
return User::interpreters()
->available()
->withDistanceFrom($record->location_latitude, $record->location_longitude)
->get()
->mapWithKeys(fn ($user) => [
$user->id => "{$user->full_name} ({$user->distance} km)"
]);
})
->required(),
])
->action(function (Order $record, array $data) {
$record->assignInterpreter($data['interpreter_id']);
})
Invoice Actions
| Action | Icon | Beschreibung | Sichtbarkeit |
|---|---|---|---|
| create_invoice | document-plus | Rechnung erstellen | Completed |
| download_invoice | arrow-down-tray | Rechnung herunterladen | InvoiceCreated+ |
| calculate_costs | calculator | Kosten berechnen | Completed |
Action::make('create_invoice')
->label('Rechnung erstellen')
->icon('heroicon-o-document-plus')
->visible(fn (Order $record) => $record->state instanceof Completed)
->requiresConfirmation()
->action(function (Order $record) {
$invoice = $record->createInvoice();
$record->transitionTo(InvoiceCreated::class);
Notification::make()
->success()
->title('Rechnung erstellt')
->body("Rechnungsnummer: {$invoice->invoice_number}")
->send();
})
Activity Timeline
ActivityTimelineAction::make('activity_timeline')
->label('Aktivitäten')
->icon('heroicon-o-clock')
->slideOver()
Relation Managers
Angezeigt als Tabs auf der ViewOrder-Seite:
OrderRequestsRelationManager
Zeigt alle Sprachmittler-Anfragen für diesen Auftrag.
| Spalte | Beschreibung |
|---|---|
| interpreter.full_name | Sprachmittler |
| state | Status (Badge) |
| score | Matching-Score |
| created_at | Erstellt am |
| responded_at | Beantwortet am |
InvoicesRelationManager
Zeigt alle Rechnungen für diesen Auftrag.
| Spalte | Beschreibung |
|---|---|
| invoice_number | Rechnungsnummer |
| version | Version |
| total_amount | Betrag |
| state | Status |
| created_at | Erstellt am |
Actions:
- download: Rechnung herunterladen
- regenerate: Rechnung neu generieren
AdditionalCostsRelationManager
Verwaltet Zusatzkosten.
| Spalte | Beschreibung |
|---|---|
| category | Kategorie (Badge) |
| amount | Betrag |
| description | Beschreibung |
ActivityLogRelationManager
Zeigt das Aktivitätsprotokoll.
Bulk Actions
| Action | Icon | Beschreibung |
|---|---|---|
| delete | trash | Aufträge löschen |
| export | arrow-down-tray | Als Excel exportieren |
| assign_bulk | user-plus | Mehrere zuweisen |
Pages
| Page | Klasse | Beschreibung |
|---|---|---|
| index | ListOrders | Übersichtstabelle |
| create | CreateOrder | Auftrag erstellen |
| view | ViewOrder | Detailansicht mit Tabs |
| edit | EditOrder | Auftrag bearbeiten |
ViewOrder mit Relation Managers
class ViewOrder extends ViewRecord
{
protected static string $resource = OrderResource::class;
use ViewRecord\Concerns\HasRelationManagers;
public function getRelationManagers(): array
{
return [
'order_requests' => OrderRequestsRelationManager::class,
'invoices' => InvoicesRelationManager::class,
'additional_costs' => AdditionalCostsRelationManager::class,
'activity_log' => ActivityLogRelationManager::class,
];
}
}