'date', 'expires_at' => 'date', ]; public function product() { return $this->belongsTo(Product::class); } public function size() { return $this->belongsTo(ProductSize::class); } public function recipe() { return $this->belongsTo(Recipe::class); } public function origins() { return $this->hasMany(BatchOrigin::class); } protected static function booted(): void { // Auto-calculate quantity_g before saving static::saving(function (Batch $batch) { if ($batch->units_produced && $batch->size_id) { $gramsPerUnit = $batch->size?->packing?->size ?? 0; $batch->quantity_g = $batch->units_produced * $gramsPerUnit; } }); static::created(function (Batch $batch) { $batch->deductSpices(); }); static::updated(function (Batch $batch) { if ($batch->wasChanged(['recipe_id', 'size_id', 'units_produced'])) { $batch->restoreSpices( $batch->getOriginal('recipe_id'), $batch->getOriginal('quantity_g'), ); $batch->deductSpices(); } }); static::deleting(function (Batch $batch) { $batch->restoreSpices($batch->recipe_id, $batch->quantity_g); }); } private function deductSpices(): void { if (! $this->quantity_g || ! $this->recipe_id) { return; } $recipe = Recipe::with('spices')->find($this->recipe_id); foreach ($recipe->spices as $spice) { $grams = $this->quantity_g * $spice->pivot->amount_in_percent / 100; $spice->decrement('quantity', $grams); } } private function restoreSpices(int $recipeId, float $quantityG): void { if (! $quantityG || ! $recipeId) { return; } $recipe = Recipe::with('spices')->find($recipeId); foreach ($recipe->spices as $spice) { $grams = $quantityG * $spice->pivot->amount_in_percent / 100; $spice->increment('quantity', $grams); } } }