266 lines
9.6 KiB
PHP
266 lines
9.6 KiB
PHP
<?php
|
|
|
|
namespace Tests\Feature;
|
|
|
|
use Illuminate\Foundation\Testing\RefreshDatabase;
|
|
use Tests\TestCase;
|
|
use App\Models\User;
|
|
use App\Models\Branch;
|
|
use App\Models\RawMaterial;
|
|
use App\Models\Product;
|
|
use App\Models\ProductRecipe;
|
|
use App\Models\Stock;
|
|
use App\Models\JournalEntry;
|
|
|
|
class IntegrationPurchaseToSaleTest extends TestCase
|
|
{
|
|
use RefreshDatabase;
|
|
|
|
public function test_equity_and_balance_sheet_use_stock_based_modal()
|
|
{
|
|
$branch = Branch::create(['name' => '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]);
|
|
}
|
|
}
|