Deploy / deploy (push) Successful in 16s
Every delivery and batch now writes a signed movement entry instead of directly incrementing/decrementing spice.quantity. The balance is always the sum of all movements. Existing data is backfilled in the migration. Rohstoff edit page shows the full movement history (Lagerbewegungen tab). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
100 lines
2.6 KiB
PHP
100 lines
2.6 KiB
PHP
<?php
|
|
|
|
namespace App\Models;
|
|
|
|
use Illuminate\Database\Eloquent\Model;
|
|
|
|
class Batch extends Model
|
|
{
|
|
protected $fillable = [
|
|
'lot_number', 'product_id', 'size_id', 'recipe_id',
|
|
'units_produced', 'quantity_g', 'produced_at', 'expires_at',
|
|
];
|
|
|
|
protected $casts = [
|
|
'produced_at' => '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
|
|
{
|
|
static::saving(function (Batch $batch) {
|
|
if ($batch->units_produced && $batch->size_id) {
|
|
$batch->quantity_g = $batch->units_produced * ($batch->size?->packing?->size ?? 0);
|
|
}
|
|
});
|
|
|
|
static::created(function (Batch $batch) {
|
|
$batch->writeSpiceMovements();
|
|
});
|
|
|
|
static::updated(function (Batch $batch) {
|
|
if ($batch->wasChanged(['recipe_id', 'size_id', 'units_produced'])) {
|
|
$batch->deleteSpiceMovements();
|
|
$batch->writeSpiceMovements();
|
|
}
|
|
});
|
|
|
|
static::deleting(function (Batch $batch) {
|
|
$batch->deleteSpiceMovements();
|
|
});
|
|
}
|
|
|
|
private function writeSpiceMovements(): void
|
|
{
|
|
if (! $this->quantity_g || ! $this->recipe_id) {
|
|
return;
|
|
}
|
|
|
|
$recipe = Recipe::with('spices')->find($this->recipe_id);
|
|
if (! $recipe) {
|
|
return;
|
|
}
|
|
|
|
foreach ($recipe->spices as $spice) {
|
|
$grams = $this->quantity_g * $spice->pivot->amount_in_percent / 100;
|
|
SpiceStockMovement::create([
|
|
'spice_id' => $spice->id,
|
|
'amount' => -$grams,
|
|
'source_type' => 'batch',
|
|
'source_id' => $this->id,
|
|
'description' => 'Charge ' . $this->lot_number . ' (' . $spice->pivot->amount_in_percent . '%)',
|
|
]);
|
|
$spice->recalculateQuantity();
|
|
}
|
|
}
|
|
|
|
private function deleteSpiceMovements(): void
|
|
{
|
|
$spiceIds = SpiceStockMovement::where('source_type', 'batch')
|
|
->where('source_id', $this->id)
|
|
->pluck('spice_id');
|
|
|
|
SpiceStockMovement::where('source_type', 'batch')
|
|
->where('source_id', $this->id)
|
|
->delete();
|
|
|
|
Spice::whereIn('id', $spiceIds)->get()->each->recalculateQuantity();
|
|
}
|
|
}
|