'Cabang 1']); $admin = User::factory()->create(['role' => 'admin', 'branch' => $branch->name]); $product = Product::create([ 'name' => 'Kopi', 'category' => 'minuman', 'purchase_price' => 3000, 'selling_price' => 5000, 'branch' => $branch->name, ]); Stock::create([ 'product_id' => $product->id, 'branch' => $branch->name, 'quantity' => 3, 'unit' => 'Pcs', ]); $response = $this->actingAs($admin)->get('/laporan/perubahan-modal'); $response->assertOk(); $response->assertViewHas('data', function ($data) { return $data['modal_awal'] == 15000 && $data['modal_akhir'] == 15000; }); $balanceResponse = $this->actingAs($admin)->get('/laporan/neraca-keuangan'); $balanceResponse->assertOk(); $balanceResponse->assertViewHas('data', function ($data) { return $data['modal_akhir'] == 15000; }); } public function test_sale_creates_journal_entries_and_reports_reflect_sales_data() { $branch = Branch::create(['name' => 'Cabang 1']); $admin = User::factory()->create(['role' => 'admin', 'branch' => $branch->name]); $product = Product::create([ 'name' => 'Kopi', 'category' => 'minuman', 'purchase_price' => 4000, 'selling_price' => 5000, 'branch' => $branch->name, ]); Stock::create([ 'product_id' => $product->id, 'branch' => $branch->name, 'quantity' => 2, 'unit' => 'Pcs', ]); $response = $this->actingAs($admin)->post('/laporan/penjualan', [ 'date' => now()->toDateString(), 'product_id' => $product->id, 'quantity' => 1, 'total_price' => 5000, 'branch' => $branch->name, ]); $response->assertSessionHasNoErrors(); $this->assertDatabaseCount('journal_entries', 1); $this->assertDatabaseHas('journal_entries', ['reference_type' => 'Sale']); $pnlResponse = $this->actingAs($admin)->get('/laporan/neraca-laba-rugi'); $pnlResponse->assertOk(); $pnlResponse->assertViewHas('dataTotal', function ($data) { return $data['penjualan'] == 5000 && $data['pembelian'] == 4000 && $data['laba_kotor'] == 1000; }); $cashFlowResponse = $this->actingAs($admin)->get('/laporan/arus-kas'); $cashFlowResponse->assertOk(); $cashFlowResponse->assertViewHas('data', function ($data) { return $data['penerimaan_penjualan'] == 5000 && $data['arus_kas_operasi'] == 5000; }); } public function test_purchase_creates_raw_material_stock_and_product_stock_then_sale_reduces_stocks() { // Create branch and user $branch = Branch::create(['name' => 'Cabang 1']); $admin = User::factory()->create(['role' => 'admin', 'branch' => $branch->name]); // Create raw material $rm = RawMaterial::create(['name' => 'Tepung', 'unit' => 'gram', 'stock_quantity' => 0, 'branch' => $branch->name]); // Create product that uses 100 grams per unit $product = Product::create([ 'name' => 'Roti', 'category' => 'makanan', 'purchase_price' => 1000, 'selling_price' => 2000, 'branch' => $branch->name, ]); ProductRecipe::create([ 'product_id' => $product->id, 'raw_material_id' => $rm->id, 'quantity_needed' => 100, ]); // Ensure no product stock initially $this->assertDatabaseMissing('stocks', ['product_id' => $product->id, 'branch' => $branch->name, 'quantity' => 1]); // Simulate purchase of 1000 grams (1 kilogram) $response = $this->actingAs($admin)->post('/laporan/pembelian', [ 'date' => now()->toDateString(), 'item' => 'Beli Tepung', 'quantity' => '1000 gram', 'total_price' => 100000, 'type' => 'raw_material', 'raw_material_id' => $rm->id, 'branch' => $branch->name, ]); $response->assertSessionHasNoErrors(); $rm->refresh(); // 1000 grams purchased $this->assertEquals(1000, $rm->stock_quantity); // After recalculation, product stock should be floor(1000/100) = 10 $this->assertDatabaseHas('stocks', ['product_id' => $product->id, 'branch' => $branch->name, 'quantity' => 10]); // Simulate sale of 2 units $response2 = $this->actingAs($admin)->post('/laporan/penjualan', [ 'date' => now()->toDateString(), 'product_id' => $product->id, 'quantity' => 2, 'total_price' => 4000, 'branch' => $branch->name, ]); $response2->assertSessionHasNoErrors(); $rm->refresh(); // Raw material should be reduced by 2 * 100 = 200 grams -> remaining 800 $this->assertEquals(800, $rm->stock_quantity); // Product stock recalculated should be floor(800/100) = 8 $this->assertDatabaseHas('stocks', ['product_id' => $product->id, 'branch' => $branch->name, 'quantity' => 8]); } public function test_purchase_of_liters_keeps_stock_in_liters() { $branch = Branch::create(['name' => 'Cabang 1']); $admin = User::factory()->create(['role' => 'admin', 'branch' => $branch->name]); $rm = RawMaterial::create(['name' => 'Air Galon', 'unit' => 'Liter', 'stock_quantity' => 0, 'branch' => $branch->name]); $response = $this->actingAs($admin)->post('/laporan/pembelian', [ 'date' => now()->toDateString(), 'item' => 'Beli Air Galon', 'quantity' => '30 Liter', 'total_price' => 300000, 'type' => 'raw_material', 'raw_material_id' => $rm->id, 'branch' => $branch->name, ]); $response->assertSessionHasNoErrors(); $rm->refresh(); $this->assertEquals(30, $rm->stock_quantity); } public function test_sale_of_es_teh_reduces_tea_and_gallon_raw_materials() { $branch = Branch::create(['name' => 'Cabang 1']); $admin = User::factory()->create(['role' => 'admin', 'branch' => $branch->name]); $teh = RawMaterial::create(['name' => 'Teh', 'unit' => 'Gram', 'stock_quantity' => 100, 'branch' => $branch->name]); $airGalon = RawMaterial::create(['name' => 'Air Galon', 'unit' => 'Liter', 'stock_quantity' => 10, 'branch' => $branch->name]); $product = Product::create([ 'name' => 'Es Teh', 'category' => 'minuman', 'purchase_price' => 2000, 'selling_price' => 5000, 'branch' => $branch->name, ]); ProductRecipe::create([ 'product_id' => $product->id, 'raw_material_id' => $teh->id, 'quantity_needed' => 10 ]); ProductRecipe::create([ 'product_id' => $product->id, 'raw_material_id' => $airGalon->id, 'quantity_needed' => 1 ]); Stock::create(['product_id' => $product->id, 'branch' => $branch->name, 'quantity' => 10, 'unit' => 'Pcs']); $response = $this->actingAs($admin)->post('/laporan/penjualan', [ 'date' => now()->toDateString(), 'product_id' => $product->id, 'quantity' => 1, 'total_price' => 5000, 'branch' => $branch->name, ]); $response->assertSessionHasNoErrors(); $teh->refresh(); $airGalon->refresh(); $this->assertEquals(90, $teh->stock_quantity); $this->assertEquals(9, $airGalon->stock_quantity); $this->assertDatabaseHas('stocks', ['product_id' => $product->id, 'branch' => $branch->name, 'quantity' => 9]); } public function test_sale_reduces_product_stock_for_recipe_based_product() { $branch = Branch::create(['name' => 'Cabang 1']); $admin = User::factory()->create(['role' => 'admin', 'branch' => $branch->name]); $rm = RawMaterial::create(['name' => 'Teh', 'unit' => 'gram', 'stock_quantity' => 200, 'branch' => $branch->name]); $product = Product::create([ 'name' => 'Es Teh', 'category' => 'minuman', 'purchase_price' => 2000, 'selling_price' => 5000, 'branch' => $branch->name, ]); ProductRecipe::create([ 'product_id' => $product->id, 'raw_material_id' => $rm->id, 'quantity_needed' => 20, ]); Stock::create([ 'product_id' => $product->id, 'branch' => $branch->name, 'quantity' => 10, 'unit' => 'Pcs', ]); $response = $this->actingAs($admin)->post('/laporan/penjualan', [ 'date' => now()->toDateString(), 'product_id' => $product->id, 'quantity' => 1, 'total_price' => 5000, 'branch' => $branch->name, ]); $response->assertSessionHasNoErrors(); $rm->refresh(); $this->assertEquals(180, $rm->stock_quantity); $this->assertDatabaseHas('stocks', ['product_id' => $product->id, 'branch' => $branch->name, 'quantity' => 9]); } }