Add recipe versioning: auto-bump on change, history sub-page
Deploy / deploy (push) Successful in 16s

Each time the recipe name or spices are changed on the product edit
page, a new version is created instead of overwriting the current one.
Unchanged saves are skipped. A 'Rezept-Versionen' button opens a
sub-page (/produkt/{id}/rezept-versionen) listing all versions with
their spices and timestamps; the active version is highlighted in green.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Malek TellissiandClaude Sonnet 4.6 committed 2026-09-12 05:52:59 +02:00
1 parent 4775cffaae
commit a7e7375edd
4 files changed
+128 -21

No files matched your search

@@ -14,16 +14,23 @@ class EditProduct extends EditRecord
protected function getHeaderActions(): array
{
return [
Actions\Action::make('rezept-versionen')
->label('Rezept-Versionen')
->icon('heroicon-o-clock')
->color('gray')
->url(fn () => ProductResource::getUrl('recipe-history', ['record' => $this->record])),
Actions\DeleteAction::make(),
];
}
protected function afterSave(): void {
protected function afterSave(): void
{
$this->syncSizes();
$this->syncRecipe();
}
protected function syncSizes(): void {
protected function syncSizes(): void
{
$product = $this->record;
$sizes = collect($this->data['sizes'] ?? [])
@@ -45,29 +52,48 @@ class EditProduct extends EditRecord
protected function syncRecipe(): void
{
$product = $this->record;
$name = $this->data['recipe_name'] ?? null;
$spices = $this->data['recipe_spices'] ?? [];
$name = $this->data['recipe_name'] ?? null;
$spices = $this->data['recipe_spices'] ?? [];
if (! $name) {
return;
}
$pivotData = collect($spices)->mapWithKeys(fn ($s) => [
$s['spice_id'] => ['amount_in_percent' => $s['amount_in_percent']],
$newPivot = collect($spices)->mapWithKeys(fn ($s) => [
(int) $s['spice_id'] => (float) $s['amount_in_percent'],
])->toArray();
if ($product->recipe) {
$product->recipe->update(['name' => $name]);
$product->recipe->spices()->sync($pivotData);
} else {
$nextVersion = Recipe::where('product_id', $product->id)->max('version') + 1;
$recipe = Recipe::create([
'name' => $name,
'product_id' => $product->id,
'version' => $nextVersion,
]);
$recipe->spices()->sync($pivotData);
$product->update(['recipes_id' => $recipe->id]);
$current = $product->recipe;
if ($current) {
$current->load('spices');
$existingPivot = $current->spices->mapWithKeys(fn ($s) => [
$s->id => (float) $s->pivot->amount_in_percent,
])->toArray();
$nameChanged = $current->name !== $name;
$spicesChanged = $existingPivot != $newPivot;
if (! $nameChanged && ! $spicesChanged) {
return;
}
}
$nextVersion = Recipe::where('product_id', $product->id)->max('version') + 1;
$recipe = Recipe::create([
'name' => $name,
'product_id' => $product->id,
'version' => $nextVersion,
]);
$recipe->spices()->sync(
collect($newPivot)->mapWithKeys(fn ($pct, $id) => [
$id => ['amount_in_percent' => $pct],
])->toArray()
);
$product->update(['recipes_id' => $recipe->id]);
}
}