Warenwirtschaft: AP-48 — Produktbestand-Buchungsgründe pflegbar, getrennt Ein/Aus
Kundenentscheid 26.08. (D-5): Eingang und Ausgang haben eigene, pflegbare Gründe-Listen statt einer festen Liste im Controller. - Neues Modell/Tabelle stock_movement_reasons (label, direction in/out, pos, active, SoftDeletes) inkl. Seed der bisherigen Gründe sinnvoll auf Ein-/Ausgang aufgeteilt. - CRUD wie DisposalReason (SettingCrudController + FormRequest + Formular mit Richtungs-Auswahl); zwei Listen (Eingangs-/Ausgangs-Gründe) auf der Seite Einstellungen → Allgemeines, „Neu anlegen" mit vorbelegter Richtung. - Produktbestand-Maske: das Grund-Dropdown wird jetzt je nach Eingang/Ausgang per JS aus den passenden, gepflegten Gründen befüllt (manualReasons entfernt). - DeletionGuard: StockMovementReason immer löschbar. Migration create_stock_movement_reasons auf Dev-/Live-DB. 4 Tests, Suite 326 grün. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
e08c8dec40
commit
190713c21b
12 changed files with 381 additions and 22 deletions
57
tests/Feature/StockMovementReasonTest.php
Normal file
57
tests/Feature/StockMovementReasonTest.php
Normal file
|
|
@ -0,0 +1,57 @@
|
|||
<?php
|
||||
|
||||
use App\Models\StockMovementReason;
|
||||
use App\User;
|
||||
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||
use Tests\TestCase;
|
||||
|
||||
uses(TestCase::class, RefreshDatabase::class);
|
||||
|
||||
function smrAdmin(): User
|
||||
{
|
||||
$user = User::query()->create(['email' => uniqid('smr_', true).'@test.example', 'password' => bcrypt('password')]);
|
||||
$user->forceFill(['admin' => 9, 'confirmed' => true, 'active' => true, 'wizard' => 100, 'blocked' => false])->save();
|
||||
|
||||
return $user->fresh();
|
||||
}
|
||||
|
||||
test('AP-48: seed liefert getrennte gründe für eingang und ausgang', function () {
|
||||
expect(StockMovementReason::query()->where('direction', 'in')->count())->toBeGreaterThan(0)
|
||||
->and(StockMovementReason::query()->where('direction', 'out')->count())->toBeGreaterThan(0)
|
||||
// „Testervergabe" ist ein Ausgangs-, kein Eingangsgrund
|
||||
->and(StockMovementReason::query()->where('direction', 'out')->where('label', 'Testervergabe')->exists())->toBeTrue()
|
||||
->and(StockMovementReason::query()->where('direction', 'in')->where('label', 'Testervergabe')->exists())->toBeFalse();
|
||||
});
|
||||
|
||||
test('AP-48: grund kann mit richtung angelegt werden', function () {
|
||||
$this->actingAs(smrAdmin(), 'user');
|
||||
|
||||
$this->post(route('admin.inventory.stock-movement-reasons.store'), [
|
||||
'label' => 'AP48-Sonderentnahme',
|
||||
'direction' => 'out',
|
||||
'active' => '1',
|
||||
'pos' => '3',
|
||||
])->assertRedirect(route('admin.inventory.general'));
|
||||
|
||||
$reason = StockMovementReason::query()->where('label', 'AP48-Sonderentnahme')->firstOrFail();
|
||||
expect($reason->direction)->toBe('out')->and($reason->active)->toBeTrue();
|
||||
});
|
||||
|
||||
test('AP-48: produktbestand-maske liefert die gründe je richtung', function () {
|
||||
$this->actingAs(smrAdmin(), 'user');
|
||||
StockMovementReason::query()->create(['label' => 'AP48-NurEingang', 'direction' => 'in', 'active' => true, 'pos' => 9]);
|
||||
|
||||
$this->get(route('admin.inventory.product-stock.index'))
|
||||
->assertSuccessful()
|
||||
->assertSee('AP48-NurEingang');
|
||||
});
|
||||
|
||||
test('AP-48: grund ist immer löschbar', function () {
|
||||
$this->actingAs(smrAdmin(), 'user');
|
||||
$reason = StockMovementReason::query()->create(['label' => 'AP48-Weg', 'direction' => 'in', 'active' => true, 'pos' => 9]);
|
||||
|
||||
$this->delete(route('admin.inventory.stock-movement-reasons.destroy', $reason))
|
||||
->assertRedirect(route('admin.inventory.general'));
|
||||
|
||||
expect(StockMovementReason::query()->find($reason->id))->toBeNull();
|
||||
});
|
||||
Loading…
Add table
Add a link
Reference in a new issue