Feat: Adds multi currency to imports and exports (#89)
* Also adds ability for user to export configurations
This commit is contained in:
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -198,4 +198,52 @@ class DailyChangeTest extends TestCase
|
||||
|
||||
$this->assertEqualsWithDelta($total_dividends, $last_dividend_change->total_dividends_earned, 0.01);
|
||||
}
|
||||
|
||||
public function test_daily_changes_synced_into_past_for_older_transactions(): void
|
||||
{
|
||||
$this->actingAs($user = User::factory()->create());
|
||||
|
||||
$portfolio = Portfolio::factory()->create();
|
||||
|
||||
// 1. test daily change will fill to the date of first transaction
|
||||
$first_transaction = Transaction::factory(5)->buy()->lastMonth()->portfolio($portfolio->id)->symbol('AAPL')->create();
|
||||
|
||||
$portfolio->syncDailyChanges();
|
||||
|
||||
$first_date = DailyChange::min('date');
|
||||
|
||||
$this->assertEquals($first_transaction->min('date')->toDateString(), $first_date);
|
||||
|
||||
// 2. test daily change will fill when new transaction pre-dates earliest daily change
|
||||
config()->set('app.env', 'local');
|
||||
$this->withoutDefer();
|
||||
|
||||
$second_transaction = Transaction::create([
|
||||
'symbol' => 'AAPL',
|
||||
'portfolio_id' => $portfolio->id,
|
||||
'date' => now()->subYears(3),
|
||||
'quantity' => 1,
|
||||
'cost_basis' => 39.89,
|
||||
'transaction_type' => 'BUY',
|
||||
]);
|
||||
|
||||
$second_date = DailyChange::min('date');
|
||||
|
||||
$this->assertEquals($second_transaction->date->toDateString(), $second_date);
|
||||
|
||||
// 3. test daily change will fill when new transaction is between earliest daily change and earliest transaction
|
||||
$third_transaction = Transaction::create([
|
||||
'symbol' => 'AAPL',
|
||||
'portfolio_id' => $portfolio->id,
|
||||
'date' => now()->subYears(1),
|
||||
'quantity' => 1,
|
||||
'cost_basis' => 39.89,
|
||||
'transaction_type' => 'BUY',
|
||||
]);
|
||||
|
||||
$daily_change_day_after = DailyChange::withDailyPerformance()->whereDate('daily_change.date', $third_transaction->date->addDay())->first();
|
||||
$daily_change_day_before = DailyChange::withDailyPerformance()->whereDate('daily_change.date', $third_transaction->date->subDay())->first();
|
||||
|
||||
$this->assertEquals(39.89, $daily_change_day_after->total_cost_basis - $daily_change_day_before->total_cost_basis);
|
||||
}
|
||||
}
|
||||
|
||||
+71
-42
@@ -6,6 +6,8 @@ namespace Tests;
|
||||
|
||||
use App\Exports\BackupExport;
|
||||
use App\Models\BackupImport as BackupImportModel;
|
||||
use App\Models\Holding;
|
||||
use App\Models\Portfolio;
|
||||
use App\Models\Transaction;
|
||||
use App\Models\User;
|
||||
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||
@@ -15,62 +17,89 @@ class ImportExportTest extends TestCase
|
||||
{
|
||||
use RefreshDatabase;
|
||||
|
||||
// todo: need to fix import export
|
||||
public function test_can_create_exports(): void
|
||||
{
|
||||
Excel::fake();
|
||||
|
||||
// public function test_can_create_exports(): void
|
||||
// {
|
||||
// Excel::fake();
|
||||
$this->actingAs($user = User::factory()->create());
|
||||
|
||||
// $this->actingAs($user = User::factory()->create());
|
||||
Transaction::factory(5)->buy()->lastYear()->symbol('AAPL')->create();
|
||||
|
||||
// Transaction::factory(5)->buy()->lastYear()->symbol('AAPL')->create();
|
||||
Excel::download(new BackupExport, now()->format('Y_m_d').'_investbrain_backup.xlsx');
|
||||
|
||||
// Excel::download(new BackupExport, now()->format('Y_m_d').'_investbrain_backup.xlsx');
|
||||
Excel::assertDownloaded(now()->format('Y_m_d').'_investbrain_backup.xlsx', function (BackupExport $export) {
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
// Excel::assertDownloaded(now()->format('Y_m_d').'_investbrain_backup.xlsx', function (BackupExport $export) {
|
||||
// return true;
|
||||
// });
|
||||
// }
|
||||
public function test_import_job_completes(): void
|
||||
{
|
||||
$this->actingAs($user = User::factory()->create());
|
||||
|
||||
// public function test_backup_job_completes(): void
|
||||
// {
|
||||
// $this->actingAs($user = User::factory()->create());
|
||||
$import_job = BackupImportModel::create([
|
||||
'user_id' => auth()->user()->id,
|
||||
'path' => __DIR__.'/0000_00_00_import_test.xlsx',
|
||||
]);
|
||||
|
||||
// $backup_job = BackupImportModel::create([
|
||||
// 'user_id' => auth()->user()->id,
|
||||
// 'path' => __DIR__.'/0000_00_00_import_test.xlsx',
|
||||
// ]);
|
||||
$import_job->refresh();
|
||||
|
||||
// $backup_job->refresh();
|
||||
$this->assertEquals('success', $import_job->status);
|
||||
}
|
||||
|
||||
// $this->assertEquals('success', $backup_job->status);
|
||||
// }
|
||||
public function test_import_job_inserts_rows(): void
|
||||
{
|
||||
$this->actingAs($user = User::factory()->create());
|
||||
|
||||
// public function test_backup_job_inserts_rows(): void
|
||||
// {
|
||||
// $this->actingAs($user = User::factory()->create());
|
||||
BackupImportModel::create([
|
||||
'user_id' => auth()->user()->id,
|
||||
'path' => __DIR__.'/0000_00_00_import_test.xlsx',
|
||||
]);
|
||||
|
||||
// BackupImportModel::create([
|
||||
// 'user_id' => auth()->user()->id,
|
||||
// 'path' => __DIR__.'/0000_00_00_import_test.xlsx',
|
||||
// ]);
|
||||
$this->assertEquals(3, $user->transactions->count());
|
||||
}
|
||||
|
||||
// $this->assertEquals(3, $user->transactions->count());
|
||||
// }
|
||||
public function test_import_job_calculates_correct_holding_data(): void
|
||||
{
|
||||
$this->actingAs($user = User::factory()->create());
|
||||
|
||||
// public function test_backup_job_calculates_correct_holding_data(): void
|
||||
// {
|
||||
// $this->actingAs($user = User::factory()->create());
|
||||
BackupImportModel::create([
|
||||
'user_id' => auth()->user()->id,
|
||||
'path' => __DIR__.'/0000_00_00_import_test.xlsx',
|
||||
]);
|
||||
|
||||
// BackupImportModel::create([
|
||||
// 'user_id' => auth()->user()->id,
|
||||
// 'path' => __DIR__.'/0000_00_00_import_test.xlsx',
|
||||
// ]);
|
||||
$holding = $user->holdings->first();
|
||||
|
||||
// $holding = $user->holdings->first();
|
||||
$this->assertEquals('AAPL', $holding->symbol);
|
||||
$this->assertEquals(6, $holding->quantity);
|
||||
$this->assertEqualsWithDelta(233.33, $holding->average_cost_basis, 0.01);
|
||||
}
|
||||
|
||||
// $this->assertEquals('AAPL', $holding->symbol);
|
||||
// $this->assertEquals(6, $holding->quantity);
|
||||
// $this->assertEqualsWithDelta(233.33, $holding->average_cost_basis, 0.01);
|
||||
// }
|
||||
public function test_configurations_are_set_on_import(): void
|
||||
{
|
||||
$this->actingAs($user = User::factory()->create());
|
||||
|
||||
Portfolio::create([
|
||||
'id' => '9e792bb8-94e7-4ed3-b8cc-43b50d34c337',
|
||||
'title' => 'Test Portfolio',
|
||||
]);
|
||||
|
||||
$holding = Holding::create([
|
||||
'id' => '9cf8a662-7347-49fb-b9de-0cc1430a8d1f',
|
||||
'portfolio_id' => '9e792bb8-94e7-4ed3-b8cc-43b50d34c337',
|
||||
'symbol' => 'ACME',
|
||||
'quantity' => 0,
|
||||
'reinvest_dividends' => false,
|
||||
]);
|
||||
|
||||
$this->assertEquals(false, $holding->reinvest_dividends);
|
||||
|
||||
BackupImportModel::create([
|
||||
'user_id' => auth()->user()->id,
|
||||
'path' => __DIR__.'/0000_00_00_import_configs_test.xlsx',
|
||||
]);
|
||||
|
||||
$holding->refresh();
|
||||
|
||||
$this->assertEquals(true, $holding->reinvest_dividends);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@ namespace Tests;
|
||||
|
||||
use App\Interfaces\MarketData\FakeMarketData;
|
||||
use App\Interfaces\MarketData\Types\Quote;
|
||||
use App\Models\BackupImport;
|
||||
use App\Models\Currency;
|
||||
use App\Models\CurrencyRate;
|
||||
use App\Models\DailyChange;
|
||||
@@ -549,4 +550,46 @@ class MultiCurrencyTest extends TestCase
|
||||
$this->assertEqualsWithDelta($metrics->get('realized_gain_dollars'), $dailyChange->last()->realized_gain_dollars, 0.01);
|
||||
$this->assertEqualsWithDelta($metrics->get('total_market_value') - $metrics->get('total_cost_basis'), $dailyChange->last()->total_gain, 0.01);
|
||||
}
|
||||
|
||||
public function test_multi_currency_import_calculates_correct_holding_data(): void
|
||||
{
|
||||
$this->actingAs($user = User::factory()->create());
|
||||
|
||||
Frankfurter::expects('setSymbols')
|
||||
->zeroOrMoreTimes()
|
||||
->andReturnSelf();
|
||||
Frankfurter::expects('timeSeries')
|
||||
->zeroOrMoreTimes()
|
||||
->andReturn(['rates' => [
|
||||
now()->subDays(3)->toDateString() => [
|
||||
'ZZZ' => .01,
|
||||
],
|
||||
now()->subDays(2)->toDateString() => [
|
||||
'ZZZ' => .01,
|
||||
],
|
||||
now()->subDays(1)->toDateString() => [
|
||||
'ZZZ' => .01,
|
||||
],
|
||||
now()->toDateString() => [
|
||||
'ZZZ' => .01,
|
||||
],
|
||||
]]);
|
||||
Frankfurter::expects('historical')
|
||||
->zeroOrMoreTimes()
|
||||
->andReturn([
|
||||
'rates' => [
|
||||
'GBP' => .89,
|
||||
],
|
||||
]);
|
||||
|
||||
BackupImport::create([
|
||||
'user_id' => auth()->user()->id,
|
||||
'path' => __DIR__.'/0000_00_00_import_multi_curr_test.xlsx',
|
||||
]);
|
||||
|
||||
$this->assertContains('AAPL', $user->holdings->pluck('symbol'));
|
||||
$this->assertContains('BP.L', $user->holdings->pluck('symbol'));
|
||||
$this->assertEquals(17, $user->holdings->sum('quantity'));
|
||||
$this->assertEqualsWithDelta(371.42, $user->holdings->sum('average_cost_basis'), 0.01);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user