feat(fares): expose auto-price fields in the admin UI

Add base_price/per_nm/multiplier to the fare form, the subfleet fares
relation manager (toggleable, shown when auto pricing is on and hidden
otherwise, with the static price column inverted), and the low_cost toggle
to the airline form. Round-trip the new columns through the fare
importers/exporters.
This commit is contained in:
Arthur Parienté 2026-06-16 22:17:40 +02:00
parent 1eef92c9a8
commit 5572b42fc9
No known key found for this signature in database
7 changed files with 91 additions and 8 deletions

View File

@ -18,6 +18,9 @@ class FareExporter extends Exporter
ExportColumn::make('code'),
ExportColumn::make('name'),
ExportColumn::make('price'),
ExportColumn::make('base_price'),
ExportColumn::make('per_nm'),
ExportColumn::make('multiplier'),
ExportColumn::make('cost'),
ExportColumn::make('capacity'),
ExportColumn::make('type'),

View File

@ -28,6 +28,15 @@ class FareImporter extends Importer
ImportColumn::make('price')
->numeric()
->rules(['nullable', 'integer']),
ImportColumn::make('base_price')
->numeric()
->rules(['nullable', 'numeric']),
ImportColumn::make('per_nm')
->numeric()
->rules(['nullable', 'numeric']),
ImportColumn::make('multiplier')
->numeric()
->rules(['nullable', 'numeric']),
ImportColumn::make('cost')
->numeric()
->rules(['nullable', 'integer']),

View File

@ -43,9 +43,13 @@ class FaresRelationManager extends RelationManager
->updateStateUsing(function (Fare $record, string $state): void {
$record->pivot->update(['capacity' => $state]);
}),
// The static price is only meaningful when auto pricing is off
// (auto pricing computes the price), so hide it by default when
// auto pricing is on — the inverse of the override columns below.
TextInputColumn::make('pivot.price')
->label(__('common.price'))
->placeholder(__('common.inherited'))
->toggleable(isToggledHiddenByDefault: (bool) setting('fares.auto_price', false))
->updateStateUsing(function (Fare $record, string $state): void {
$record->pivot->update(['price' => $state]);
}),
@ -55,6 +59,30 @@ class FaresRelationManager extends RelationManager
->updateStateUsing(function (Fare $record, string $state): void {
$record->pivot->update(['cost' => $state]);
}),
// Auto-price override columns. Toggleable and hidden by default
// unless auto pricing is enabled, to keep the table uncluttered
// when these values aren't in use.
TextInputColumn::make('pivot.base_price')
->label(__('filament.fare_base_price'))
->placeholder(__('common.inherited'))
->toggleable(isToggledHiddenByDefault: !setting('fares.auto_price', false))
->updateStateUsing(function (Fare $record, string $state): void {
$record->pivot->update(['base_price' => $state]);
}),
TextInputColumn::make('pivot.per_nm')
->label(__('filament.fare_per_nm'))
->placeholder(__('common.inherited'))
->toggleable(isToggledHiddenByDefault: !setting('fares.auto_price', false))
->updateStateUsing(function (Fare $record, string $state): void {
$record->pivot->update(['per_nm' => $state]);
}),
TextInputColumn::make('pivot.multiplier')
->label(__('filament.fare_multiplier'))
->placeholder(__('common.inherited'))
->toggleable(isToggledHiddenByDefault: !setting('fares.auto_price', false))
->updateStateUsing(function (Fare $record, string $state): void {
$record->pivot->update(['multiplier' => $state]);
}),
])
->filters([
//

View File

@ -55,6 +55,15 @@ class AirlineForm
->onIcon(Heroicon::CheckCircle)
->offColor('danger')
->offIcon(Heroicon::XCircle),
Toggle::make('low_cost')
->label(__('filament.airline_low_cost'))
->helperText(__('filament.airline_low_cost_hint'))
->inline()
->onColor('success')
->onIcon(Heroicon::CheckCircle)
->offColor('danger')
->offIcon(Heroicon::XCircle),
])
->columnSpanFull()
->columns(3),

View File

@ -40,6 +40,29 @@ class FareForm
->helperText(__('filament.fare_price_hint'))
->numeric(),
TextInput::make('base_price')
->label(__('filament.fare_base_price'))
->helperText(__('filament.fare_base_price_hint'))
->numeric()
->minValue(0)
->default(0),
TextInput::make('per_nm')
->label(__('filament.fare_per_nm'))
->helperText(__('filament.fare_per_nm_hint'))
->numeric()
->minValue(0)
->step(0.0001)
->default(0),
TextInput::make('multiplier')
->label(__('filament.fare_multiplier'))
->helperText(__('filament.fare_multiplier_hint'))
->numeric()
->minValue(0)
->step(0.0001)
->default(1),
TextInput::make('cost')
->label(__('common.cost'))
->helperText(__('filament.fare_cost_hint'))

View File

@ -20,14 +20,17 @@ class FareImporter extends ImportExport
* Should match the database fields, for the most part
*/
public static array $columns = [
'code' => 'required',
'name' => 'required',
'type' => 'required',
'price' => 'nullable|numeric',
'cost' => 'nullable|numeric',
'capacity' => 'nullable|integer',
'notes' => 'nullable',
'active' => 'nullable|boolean',
'code' => 'required',
'name' => 'required',
'type' => 'required',
'price' => 'nullable|numeric',
'base_price' => 'nullable|numeric',
'per_nm' => 'nullable|numeric',
'multiplier' => 'nullable|numeric',
'cost' => 'nullable|numeric',
'capacity' => 'nullable|integer',
'notes' => 'nullable',
'active' => 'nullable|boolean',
];
/**

View File

@ -15,6 +15,14 @@ return [
'fare_price_hint' => 'This is the price of a ticket per unit (passenger or kg)',
'fare_cost_hint' => 'The operating cost per unit (passenger or kg)',
'fare_capacity_hint' => 'Max seats or capacity available. This can be adjusted in the subfleet',
'fare_base_price' => 'Base price',
'fare_base_price_hint' => 'Auto pricing: the fixed base price added before the per-distance amount. Absolute value only.',
'fare_per_nm' => 'Price per nautical mile',
'fare_per_nm_hint' => 'Auto pricing: amount added per nautical mile of distance. Absolute value only.',
'fare_multiplier' => 'Seat category multiplier',
'fare_multiplier_hint' => 'Auto pricing: multiplier for this seat category (e.g. 3 for business). Absolute value only.',
'airline_low_cost' => 'Low-cost carrier',
'airline_low_cost_hint' => 'Apply the low-cost auto-pricing multiplier to fares flown under this airline.',
'flight_information' => 'Flight Information',
'flight_pilot_pay_hint' => 'Fill this in to pay a pilot a fixed amount for this flight.',
'flight_load_factor_hint' => 'Percentage value for pax/cargo load, leave blank to use the default value.',