Warenwirtschaft: AP-36 — Rezeptur-Textphasen ohne Rohstoffe anzeigen
Phasen ohne Rohstoffzeile (reine Hinweisphasen wie „Vorbereitung"/„Nachbereitung") verschwanden in der Produktionsmaske, weil buildPhaseGroups() leere Gruppen wegfilterte. Filter so angepasst, dass benannte Phasen erhalten bleiben und nur der namenlose „lose" Sammeltopf verworfen wird. Die Phasen kommen serverseitig bereits in pos-Reihenfolge (recipePhases orderBy pos), sodass „Vorbereitung" korrekt über „Phase A" steht. Test sichert den recipeJson-Datenvertrag ab. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
00be848604
commit
d60947c34d
2 changed files with 55 additions and 1 deletions
|
|
@ -181,7 +181,10 @@
|
|||
if (loose.ingredients.length) {
|
||||
groups.push(loose);
|
||||
}
|
||||
return groups.filter(function (g) { return g.ingredients.length > 0; });
|
||||
// AP-36: benannte Phasen ohne Rohstoffe (reine Text-/Hinweisphasen wie
|
||||
// „Vorbereitung"/„Nachbereitung") bleiben erhalten — nur der namenlose
|
||||
// „lose" Sammeltopf wird verworfen, wenn er leer ist.
|
||||
return groups.filter(function (g) { return g.ingredients.length > 0 || g.name != null; });
|
||||
}
|
||||
|
||||
function renderIngredientWrap(ing, $container) {
|
||||
|
|
|
|||
|
|
@ -1,10 +1,12 @@
|
|||
<?php
|
||||
|
||||
use App\Models\Ingredient;
|
||||
use App\Models\Location;
|
||||
use App\Models\Product;
|
||||
use App\Models\RecipePhase;
|
||||
use App\Repositories\ProductRepository;
|
||||
use App\Services\ProductionService;
|
||||
use App\User;
|
||||
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||
use Tests\TestCase;
|
||||
|
||||
|
|
@ -190,3 +192,52 @@ test('produktion rechnet unveraendert ueber alle phasen', function () {
|
|||
expect($required[$a->id])->toBe(300.0)
|
||||
->and($required[$b->id])->toBe(200.0);
|
||||
});
|
||||
|
||||
test('AP-36: recipeJson liefert auch phasen ohne rohstoffe (textphasen)', function () {
|
||||
// Die eigentliche Anzeige-Korrektur sitzt im JS (buildPhaseGroups rendert leere
|
||||
// benannte Phasen). Dieser Test sichert den Datenvertrag ab, auf den das JS baut:
|
||||
// eine Phase ohne Rohstoffzeile muss im recipeJson-Payload erhalten bleiben.
|
||||
$product = ap23MakeProduct('AP36-Textphase');
|
||||
$a = ap23MakeIngredient('AP36-Sheabutter');
|
||||
|
||||
ap23SaveManufacturerRecipe($product, [
|
||||
'mfg_phase_name' => ['Vorbereitung', 'Phase A'],
|
||||
'mfg_phase_note' => ['Arbeitsplatz desinfizieren', ''],
|
||||
// nur die zweite Phase trägt einen Rohstoff — „Vorbereitung" bleibt leer
|
||||
'mfg_ingredient_id' => [(string) $a->id],
|
||||
'mfg_row_phase' => ['1'],
|
||||
'mfg_gram' => ['100'],
|
||||
'mfg_factor' => ['1,00'],
|
||||
]);
|
||||
|
||||
$user = phaseJsonUser();
|
||||
$this->actingAs($user, 'user');
|
||||
|
||||
$location = Location::factory()->create();
|
||||
$response = $this->getJson(route('admin.inventory.api.products.recipe', [
|
||||
'product' => $product->id,
|
||||
'location_id' => $location->id,
|
||||
'quantity' => 1,
|
||||
]))->assertSuccessful();
|
||||
|
||||
$phases = collect($response->json('phases'));
|
||||
expect($phases)->toHaveCount(2);
|
||||
$vorbereitung = $phases->firstWhere('name', 'Vorbereitung');
|
||||
expect($vorbereitung)->not->toBeNull()
|
||||
->and($vorbereitung['note'])->toBe('Arbeitsplatz desinfizieren');
|
||||
// Vorbereitung steht vor Phase A (pos-Reihenfolge)
|
||||
expect($phases[0]['name'])->toBe('Vorbereitung');
|
||||
});
|
||||
|
||||
function phaseJsonUser(): User
|
||||
{
|
||||
$user = User::query()->create([
|
||||
'email' => uniqid('ap36_', true).'@test.example',
|
||||
'password' => bcrypt('password'),
|
||||
]);
|
||||
$user->forceFill([
|
||||
'admin' => 7, 'confirmed' => true, 'active' => true, 'wizard' => 100, 'blocked' => false,
|
||||
])->save();
|
||||
|
||||
return $user->fresh();
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue