234 lines
8.4 KiB
PHP
234 lines
8.4 KiB
PHP
<?php
|
|
|
|
namespace Database\Seeders;
|
|
|
|
use App\Models\Ingredient;
|
|
use App\Models\Location;
|
|
use App\Models\PackagingItem;
|
|
use App\Models\Product;
|
|
use App\Models\Production;
|
|
use App\Models\StockEntry;
|
|
use App\Models\Supplier;
|
|
use App\Services\ProductionService;
|
|
use App\User;
|
|
use Illuminate\Database\Seeder;
|
|
|
|
/**
|
|
* Demo-Daten für Phase 5 (Produktion): Rezeptur, eingegangene Chargen, Beispiel-Produktionsläufe.
|
|
* Baut auf {@see InventoryStammdatenTestSeeder} auf (Demo-Rohstoffe, Lagerort Köln, Verpackung).
|
|
*
|
|
* Aufruf: php artisan db:seed --class=ProductionDemoSeeder
|
|
*/
|
|
class ProductionDemoSeeder extends Seeder
|
|
{
|
|
public function run(): void
|
|
{
|
|
$this->call(InventoryStammdatenTestSeeder::class);
|
|
|
|
$location = Location::query()->where('name', 'Köln')->first()
|
|
?? Location::query()->where('name', 'Demo Test-Zentrallager')->first()
|
|
?? Location::query()->first();
|
|
|
|
if ($location === null) {
|
|
$this->command?->error('ProductionDemoSeeder: Kein Lagerort gefunden.');
|
|
|
|
return;
|
|
}
|
|
|
|
$ingShea = Ingredient::query()->where('name', 'Demo Wareneingang Shea Butter')->first();
|
|
$ingMandel = Ingredient::query()->where('name', 'Demo Wareneingang Mandelöl')->first();
|
|
|
|
if ($ingShea === null || $ingMandel === null) {
|
|
$this->command?->error('ProductionDemoSeeder: Demo-Inhaltsstoffe fehlen (Shea/Mandel).');
|
|
|
|
return;
|
|
}
|
|
|
|
$supplierOele = Supplier::query()->where('name', 'Demo-Lieferant Naturöle GmbH')->first();
|
|
if ($supplierOele === null) {
|
|
$this->command?->error('ProductionDemoSeeder: Demo-Lieferant fehlt.');
|
|
|
|
return;
|
|
}
|
|
|
|
$orderUser = User::query()->where('email', 'demo-wareneingang@example.test')->first();
|
|
if ($orderUser === null) {
|
|
$this->command?->error('ProductionDemoSeeder: User demo-wareneingang@example.test fehlt.');
|
|
|
|
return;
|
|
}
|
|
|
|
$sheaStock = StockEntry::query()
|
|
->where('ingredient_id', $ingShea->id)
|
|
->where('location_id', $location->id)
|
|
->where('status', 'received')
|
|
->orderByDesc('id')
|
|
->first();
|
|
|
|
if ($sheaStock === null) {
|
|
$sheaStock = StockEntry::factory()->received()->create([
|
|
'ingredient_id' => $ingShea->id,
|
|
'supplier_id' => $supplierOele->id,
|
|
'location_id' => $location->id,
|
|
'ordered_by' => $orderUser->id,
|
|
'ordered_at' => now()->subMonths(3)->format('Y-m-d'),
|
|
'ordered_quantity' => 8000,
|
|
'price_per_kg' => 8.5,
|
|
'entry_type' => 'ingredient',
|
|
'unit' => 'gram',
|
|
'packaging_item_id' => null,
|
|
'batch_number' => 'DEMO-SHEA-PROD',
|
|
'best_before' => now()->addMonths(18)->format('Y-m-d'),
|
|
]);
|
|
}
|
|
|
|
$mandelStock = StockEntry::query()
|
|
->where('ingredient_id', $ingMandel->id)
|
|
->where('location_id', $location->id)
|
|
->where('status', 'received')
|
|
->orderByDesc('received_at')
|
|
->orderByDesc('id')
|
|
->first();
|
|
|
|
if ($mandelStock === null) {
|
|
$mandelStock = StockEntry::factory()->received()->create([
|
|
'ingredient_id' => $ingMandel->id,
|
|
'supplier_id' => $supplierOele->id,
|
|
'location_id' => $location->id,
|
|
'ordered_by' => $orderUser->id,
|
|
'ordered_at' => now()->subMonths(2)->format('Y-m-d'),
|
|
'ordered_quantity' => 5000,
|
|
'price_per_kg' => 9.5,
|
|
'entry_type' => 'ingredient',
|
|
'unit' => 'gram',
|
|
'packaging_item_id' => null,
|
|
'batch_number' => 'DEMO-MANDEL-PROD',
|
|
'best_before' => now()->addMonths(20)->format('Y-m-d'),
|
|
]);
|
|
}
|
|
|
|
$bottle = PackagingItem::query()->where('name', 'Demo Braunglasflasche 30 ml')->first();
|
|
|
|
$product = Product::query()->firstOrCreate(
|
|
['name' => 'Demo Produktion Handcreme 30 ml'],
|
|
[
|
|
'title' => 'Demo Produktion Handcreme 30 ml',
|
|
'active' => true,
|
|
'shelf_life_type' => null,
|
|
'shelf_life_months' => null,
|
|
]
|
|
);
|
|
|
|
if ($product->p_ingredients()->count() === 0) {
|
|
$product->p_ingredients()->sync([
|
|
$ingShea->id => ['pos' => 0, 'gram' => 20, 'factor' => 1],
|
|
$ingMandel->id => ['pos' => 1, 'gram' => 15, 'factor' => 1],
|
|
]);
|
|
}
|
|
|
|
if ($bottle !== null && $product->packagings()->count() === 0) {
|
|
$product->packagings()->sync([
|
|
$bottle->id => ['quantity' => 1, 'pos' => 0],
|
|
]);
|
|
}
|
|
|
|
$service = app(ProductionService::class);
|
|
|
|
if (! Production::query()->where('product_id', $product->id)->exists()) {
|
|
$qty = 10;
|
|
$service->store(
|
|
[
|
|
'product_id' => $product->id,
|
|
'location_id' => $location->id,
|
|
'produced_at' => now()->subDays(3)->format('Y-m-d'),
|
|
'quantity' => $qty,
|
|
'notes' => 'Seeder: Demo-Produktionslauf (Shea + Mandel, Braunglas).',
|
|
],
|
|
[
|
|
[
|
|
'ingredient_id' => $ingShea->id,
|
|
'stock_entry_id' => $sheaStock->id,
|
|
'quantity_used' => (string) (20 * 1 * $qty),
|
|
],
|
|
[
|
|
'ingredient_id' => $ingMandel->id,
|
|
'stock_entry_id' => $mandelStock->id,
|
|
'quantity_used' => (string) (15 * 1 * $qty),
|
|
],
|
|
],
|
|
$orderUser->id
|
|
);
|
|
}
|
|
|
|
$mhdStock = StockEntry::query()
|
|
->where('ingredient_id', $ingMandel->id)
|
|
->where('location_id', $location->id)
|
|
->where('status', 'received')
|
|
->where('batch_number', 'DEMO-MHD-WARNUNG')
|
|
->first();
|
|
|
|
if ($mhdStock === null) {
|
|
$mhdStock = StockEntry::factory()->received()->create([
|
|
'ingredient_id' => $ingMandel->id,
|
|
'supplier_id' => $supplierOele->id,
|
|
'location_id' => $location->id,
|
|
'ordered_by' => $orderUser->id,
|
|
'ordered_at' => now()->subYear()->format('Y-m-d'),
|
|
'ordered_quantity' => 500,
|
|
'price_per_kg' => 9.5,
|
|
'entry_type' => 'ingredient',
|
|
'unit' => 'gram',
|
|
'packaging_item_id' => null,
|
|
'batch_number' => 'DEMO-MHD-WARNUNG',
|
|
'best_before' => '2027-06-01',
|
|
'received_at' => now()->subMonths(6)->format('Y-m-d'),
|
|
]);
|
|
}
|
|
|
|
$productMhd = Product::query()->firstOrCreate(
|
|
['name' => 'Demo Produktion MHD-Warnung (Test)'],
|
|
[
|
|
'title' => 'Demo MHD-Warnung',
|
|
'active' => true,
|
|
'shelf_life_type' => 'fixed',
|
|
'shelf_life_months' => 24,
|
|
]
|
|
);
|
|
|
|
if ($productMhd->p_ingredients()->count() === 0) {
|
|
$productMhd->p_ingredients()->sync([
|
|
$ingMandel->id => ['pos' => 0, 'gram' => 10, 'factor' => 1],
|
|
]);
|
|
}
|
|
|
|
if (! Production::query()->where('product_id', $productMhd->id)->exists()) {
|
|
$service->store(
|
|
[
|
|
'product_id' => $productMhd->id,
|
|
'location_id' => $location->id,
|
|
'produced_at' => '2026-03-01',
|
|
'quantity' => 1,
|
|
'notes' => 'Seeder: MHD-Warnung (Rohstoff-MHD vor Produkt-Ende).',
|
|
],
|
|
[
|
|
[
|
|
'ingredient_id' => $ingMandel->id,
|
|
'stock_entry_id' => $mhdStock->id,
|
|
'quantity_used' => '10',
|
|
],
|
|
],
|
|
$orderUser->id
|
|
);
|
|
}
|
|
|
|
$this->command?->info(sprintf(
|
|
'ProductionDemoSeeder: Produkt „%s“ (id=%d), MHD-Demo „%s“ (id=%d), Lagerort %s (id=%d).',
|
|
$product->name,
|
|
$product->id,
|
|
$productMhd->name,
|
|
$productMhd->id,
|
|
$location->name,
|
|
$location->id
|
|
));
|
|
}
|
|
}
|