setupTenant(); $part = Part::create([ 'name' => 'Plăcuțe frână', 'category' => 'Frâne', 'buy_price' => 100, 'sell_price' => 100, 'stock' => 10, 'is_active' => true, ]); MarkupRule::create([ 'type' => 'category', 'key' => 'Frâne', 'markup_pct' => 35, 'priority' => 100, 'is_active' => true, ]); MarkupRule::applyToPart($part); $part->refresh(); $this->assertEquals(135.00, (float) $part->sell_price); } public function test_priority_picks_first_matching_rule(): void { $this->setupTenant(); $part = Part::create([ 'name' => 'Filtru', 'category' => 'Filtre', 'brand' => 'Bosch', 'buy_price' => 50, 'sell_price' => 50, 'stock' => 5, 'is_active' => true, ]); // Brand rule (priority 1 → applied first) MarkupRule::create(['type' => 'brand', 'key' => 'Bosch', 'markup_pct' => 50, 'priority' => 1, 'is_active' => true]); MarkupRule::create(['type' => 'category', 'key' => 'Filtre', 'markup_pct' => 20, 'priority' => 100, 'is_active' => true]); MarkupRule::applyToPart($part); $part->refresh(); $this->assertEquals(75.00, (float) $part->sell_price); } public function test_inactive_rule_is_skipped(): void { $this->setupTenant(); $part = Part::create([ 'name' => 'X', 'category' => 'Test', 'buy_price' => 100, 'sell_price' => 100, 'stock' => 1, 'is_active' => true, ]); MarkupRule::create([ 'type' => 'category', 'key' => 'Test', 'markup_pct' => 99, 'priority' => 1, 'is_active' => false, ]); MarkupRule::applyToPart($part); $part->refresh(); // Inactive rule skipped → fallback default markup 30%. $this->assertEquals(130.00, (float) $part->sell_price); } private function setupTenant(): void { $plan = Plan::create([ 'name' => 'Test', 'slug' => 'test', 'price' => 0, 'features' => [], ]); $company = Company::create([ 'plan_id' => $plan->id, 'slug' => 'unit-' . uniqid(), 'name' => 'Unit Test', 'status' => 'active', ]); app(TenantManager::class)->setCurrent($company); } }