Warenwirtschaft: AP-21 INCI-Erweiterungen
- Lagerort-Stammdaten Raum/Regal/Fach (storage_rooms/shelves/slots) mit CRUD auf Einstellungen -> Allgemein (SettingCrudController-Kinder, ein gemeinsamer StoreStorageSegmentRequest, generische Partials setting-list-card/-segment-form) - Ingredient: alt_name (Handelsname), Lagerort-FKs + storageLabel(), scopeUsedInActiveRecipes() - INCI-Formular: Lieferanten-Repeater mit Shop-URL je Lieferant (leer = Mail), Alternativname, drei Lagerort-Dropdowns - INCI-Liste: Filter "nur aktive (in Rezeptur aktiver Produkte)" + Spalte Alternativer Name - Rohstoffbestand-Detail: Bestellweg pro INCI-Lieferant (Pivot-URL statt order_method-Fallback), Kopf zeigt Alternativname + Lagerort - Hinweise-Doku fortgeschrieben inkl. Chargen-Format-Entscheid ttmmjj (AP-24) Tests: StorageSettingsTest, IngredientActiveRecipeFilterTest, IngredientOrderFieldsTest (Repeater-Format), RawMaterialStockTest erweitert (volle Suite 170 gruen, 613 Assertions) Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
parent
8c90d95c69
commit
d05df498d3
34 changed files with 1091 additions and 45 deletions
97
tests/Feature/IngredientActiveRecipeFilterTest.php
Normal file
97
tests/Feature/IngredientActiveRecipeFilterTest.php
Normal file
|
|
@ -0,0 +1,97 @@
|
|||
<?php
|
||||
|
||||
use App\Models\Ingredient;
|
||||
use App\Models\Product;
|
||||
use App\Models\ProductIngredient;
|
||||
use App\User;
|
||||
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||
use Tests\TestCase;
|
||||
|
||||
uses(TestCase::class, RefreshDatabase::class);
|
||||
|
||||
function activeRecipeUser(int $adminLevel = 7): User
|
||||
{
|
||||
$user = User::query()->create([
|
||||
'email' => uniqid('arf_', true).'@test.example',
|
||||
'password' => bcrypt('password'),
|
||||
]);
|
||||
$user->forceFill([
|
||||
'admin' => $adminLevel,
|
||||
'confirmed' => true,
|
||||
'active' => true,
|
||||
'wizard' => 100,
|
||||
'blocked' => false,
|
||||
])->save();
|
||||
|
||||
return $user->fresh();
|
||||
}
|
||||
|
||||
function activeRecipeIngredient(string $name): Ingredient
|
||||
{
|
||||
return Ingredient::query()->create(['name' => $name, 'active' => true]);
|
||||
}
|
||||
|
||||
function activeRecipeAttach(Product $product, Ingredient $ingredient, string $recipeType): void
|
||||
{
|
||||
ProductIngredient::query()->create([
|
||||
'product_id' => $product->id,
|
||||
'ingredient_id' => $ingredient->id,
|
||||
'pos' => 0,
|
||||
'gram' => 10,
|
||||
'factor' => 1.0,
|
||||
'recipe_type' => $recipeType,
|
||||
]);
|
||||
}
|
||||
|
||||
test('scope liefert nur inci aus herstellerrezepturen aktiver produkte', function () {
|
||||
$activeProduct = Product::query()->create(['name' => 'ARF-Aktiv', 'title' => 'ARF-Aktiv', 'active' => true]);
|
||||
$inactiveProduct = Product::query()->create(['name' => 'ARF-Inaktiv', 'title' => 'ARF-Inaktiv', 'active' => false]);
|
||||
|
||||
$inManufacturerActive = activeRecipeIngredient('ARF-Hersteller-Aktiv');
|
||||
$inManufacturerInactive = activeRecipeIngredient('ARF-Hersteller-Inaktiv');
|
||||
$onlyProductRecipe = activeRecipeIngredient('ARF-Nur-Produktrezeptur');
|
||||
$unused = activeRecipeIngredient('ARF-Unbenutzt');
|
||||
|
||||
activeRecipeAttach($activeProduct, $inManufacturerActive, 'manufacturer');
|
||||
activeRecipeAttach($inactiveProduct, $inManufacturerInactive, 'manufacturer');
|
||||
activeRecipeAttach($activeProduct, $onlyProductRecipe, 'product');
|
||||
|
||||
$names = Ingredient::query()->usedInActiveRecipes()->pluck('name')->all();
|
||||
|
||||
expect($names)->toBe(['ARF-Hersteller-Aktiv']);
|
||||
});
|
||||
|
||||
test('inci-liste filtert mit only_active auf herstellerrezepturen', function () {
|
||||
$this->actingAs(activeRecipeUser(7), 'user');
|
||||
|
||||
$product = Product::query()->create(['name' => 'ARF-Produkt', 'title' => 'ARF-Produkt', 'active' => true]);
|
||||
$used = activeRecipeIngredient('ARF-Verwendet');
|
||||
$unused = activeRecipeIngredient('ARF-Nicht-Verwendet');
|
||||
activeRecipeAttach($product, $used, 'manufacturer');
|
||||
|
||||
$this->get(route('admin_product_ingredients'))
|
||||
->assertSuccessful()
|
||||
->assertSee('ARF-Verwendet')
|
||||
->assertSee('ARF-Nicht-Verwendet')
|
||||
->assertSee('nur aktive');
|
||||
|
||||
$this->get(route('admin_product_ingredients', ['only_active' => 1]))
|
||||
->assertSuccessful()
|
||||
->assertSee('ARF-Verwendet')
|
||||
->assertDontSee('ARF-Nicht-Verwendet');
|
||||
});
|
||||
|
||||
test('inci-liste zeigt alternativen namen als spalte', function () {
|
||||
$this->actingAs(activeRecipeUser(7), 'user');
|
||||
|
||||
Ingredient::query()->create([
|
||||
'name' => 'LECITHIN',
|
||||
'alt_name' => 'Phospholipon 80 H',
|
||||
'active' => true,
|
||||
]);
|
||||
|
||||
$this->get(route('admin_product_ingredients'))
|
||||
->assertSuccessful()
|
||||
->assertSee('Alternativer Name')
|
||||
->assertSee('Phospholipon 80 H');
|
||||
});
|
||||
Loading…
Add table
Add a link
Reference in a new issue