booking('2019-12-31', 100); $this->booking('2020-01-01', 50.25); $this->booking('2020-01-31', 20.10, $this->expenseAccount); $this->booking('2020-03-01', 10, $this->expenseAccount); $this->booking('2020-12-31', 5.50); $this->booking('2021-01-01', 999); $this->actingAs($this->user); } public function test_balance_includes_cutoff_day_and_excludes_future_bookings() { $this->seedCashFlows(); $this->assertEquals(0, SubBooking::balanceAt('2019-12-30')); $this->assertEquals(100, SubBooking::balanceAt('2019-12-31')); $this->assertEquals(130.15, SubBooking::balanceAt('2020-01-31'), '', 0.001); $this->assertEquals(125.65, SubBooking::balanceAt('2020-12-31'), '', 0.001); } public function test_interval_totals_include_both_endpoints_and_sign_expenses() { $this->seedCashFlows(); $this->assertEquals(55.75, SubBooking::incomesInInterval('2020-01-01', '2020-12-31')->first()->incomes, '', 0.001); $this->assertEquals(-30.10, SubBooking::expedituresInInterval('2020-01-01', '2020-12-31')->first()->expeditures, '', 0.001); } public function test_monthly_totals_fill_empty_months_across_a_year_boundary() { $this->booking('2019-12-31', 10); $this->booking('2020-02-01', 25); $months = SubBooking::incomesInInterval('2019-12-01', '2020-02-29', true); $this->assertSame([[2019, 12], [2020, 1], [2020, 2]], $months->map(function ($month) { return [(int) $month->year, (int) $month->month]; })->all()); $this->assertEquals([10, 0, 25], $months->pluck('incomes')->all()); } public function test_monthly_balance_report_carries_opening_balance_through_empty_months() { $this->seedCashFlows(); $response = $this->get('/reports/balances/2020')->assertStatus(200)->assertViewIs('reports.balances'); $data = $response->original->getData(); $this->assertEquals(100, $data['startBalance']); $balances = $data['balances']; $this->assertCount(12, $balances); $this->assertEquals(50.25, $balances[0]->incomes); $this->assertEquals(-20.10, $balances[0]->expeditures, '', 0.001); $this->assertEquals(30.15, $balances[0]->monthBalance, '', 0.001); $this->assertEquals(130.15, $balances[0]->accountBalance, '', 0.001); $this->assertEquals(0, $balances[1]->monthBalance); $this->assertEquals(130.15, $balances[1]->accountBalance, '', 0.001); $this->assertEquals(120.15, $balances[2]->accountBalance, '', 0.001); $this->assertEquals(125.65, $balances[11]->accountBalance, '', 0.001); $this->assertSame('01.01.2021', $balances[11]->date); } /** @dataProvider cashbookPaths */ public function test_cashbook_and_print_view_filter_year_and_show_correct_totals($path) { $this->seedCashFlows(); $response = $this->get($path)->assertStatus(200); $data = $response->original->getData(); $this->assertCount(4, $data['bookings']->flatten()); $this->assertEquals(100, $data['sums'][0]['balance']); $this->assertEquals(-20.10, $data['sums'][1]['expeditures'], '', 0.001); $this->assertEquals(150.25, $data['sums'][1]['incomes'], '', 0.001); $this->assertEquals(130.15, $data['sums'][1]['balance'], '', 0.001); $this->assertEquals(130.15, $data['sums'][2]['balance'], '', 0.001); $this->assertEquals(125.65, $data['sums'][12]['balance'], '', 0.001); } public function cashbookPaths() { return [['/bookings/year-2020'], ['/bookings/year-2020/print']]; } /** @dataProvider compactReportPaths */ public function test_scope_report_totals_match_cashbook_and_exclude_other_years($path) { $this->seedCashFlows(); $response = $this->get($path)->assertStatus(200); $data = $response->original->getData(); $this->assertEquals(100, $data['startBalance']); $this->assertEquals(25.65, $data['scopes']->sum('balance'), '', 0.001); $this->assertEquals(125.65, $data['endBalance'], '', 0.001); } public function compactReportPaths() { return [['/reports/scopes/compact/2020'], ['/reports/scopes/compact/2020/print']]; } public function test_project_report_excludes_other_projects_and_orders_bookings_by_date() { $late = $this->booking('2020-03-01', 80); $early = $this->booking('2020-01-01', 20, $this->expenseAccount); $this->booking('2020-02-01', 999, null, ['project_id' => null]); $response = $this->actingAs($this->user)->get('/reports/projects/' . $this->project->id) ->assertStatus(200)->assertSee($this->project->name); $data = $response->original->getData(); $this->assertEquals(80, $data['incomes']); $this->assertEquals(20, $data['expeditures']); $this->assertSame([$early->id, $late->id], $data['projectBookings']->pluck('booking_id')->values()->all()); } public function test_reports_render_with_an_empty_database() { $this->actingAs($this->user); $response = $this->get('/reports/balances/2020')->assertStatus(200); $data = $response->original->getData(); $this->assertEquals(0, $data['startBalance']); $this->assertCount(12, $data['balances']); foreach ($data['balances'] as $balance) { $this->assertEquals(0, $balance->accountBalance); } $this->get('/reports/scopes/compact/2020')->assertStatus(200)->assertViewHas('endBalance', 0); $this->get('/bookings/year-2020')->assertStatus(200); } }