1
0
mirror of https://github.com/invoiceninja/invoiceninja.git synced 2024-11-14 07:02:34 +01:00
invoiceninja/tests/Feature/Bank/YodleeApiTest.php

645 lines
23 KiB
PHP
Raw Normal View History

2022-07-28 07:07:35 +02:00
<?php
/**
* Invoice Ninja (https://invoiceninja.com).
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2021. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://www.elastic.co/licensing/elastic-license
*/
namespace Tests\Feature\Bank;
2022-09-15 09:31:32 +02:00
use App\Factory\BankIntegrationFactory;
use App\Factory\BankTransactionFactory;
2022-07-28 07:07:35 +02:00
use App\Helpers\Bank\Yodlee\Yodlee;
2022-09-15 09:31:32 +02:00
use App\Helpers\Invoice\InvoiceSum;
use App\Jobs\Bank\MatchBankTransactions;
2023-12-01 14:30:33 +01:00
use App\Jobs\Bank\ProcessBankTransactionsYodlee;
2022-08-17 03:52:16 +02:00
use App\Models\BankIntegration;
use App\Models\BankTransaction;
2022-09-15 09:31:32 +02:00
use App\Models\Expense;
use App\Models\Invoice;
use App\Models\Payment;
2022-08-17 03:52:16 +02:00
use App\Services\Bank\BankService;
2022-07-28 07:07:35 +02:00
use Illuminate\Foundation\Testing\DatabaseTransactions;
2022-08-17 03:52:16 +02:00
use Tests\MockAccountData;
2022-07-28 07:07:35 +02:00
use Tests\TestCase;
class YodleeApiTest extends TestCase
{
use DatabaseTransactions;
2022-08-17 03:52:16 +02:00
use MockAccountData;
2022-07-28 07:07:35 +02:00
protected function setUp(): void
{
parent::setUp();
2022-07-28 09:33:47 +02:00
2022-10-27 22:56:38 +02:00
// if(!config('ninja.yodlee.client_id'))
2023-12-01 14:30:33 +01:00
$this->markTestSkipped('Skip test no Yodlee API credentials found');
2022-08-17 03:52:16 +02:00
$this->makeTestData();
2022-07-28 07:07:35 +02:00
}
2022-09-15 09:31:32 +02:00
public function testExpenseGenerationFromBankFeed()
{
$bi = BankIntegrationFactory::create($this->company->id, $this->user->id, $this->account->id);
$bi->save();
$bt = BankTransactionFactory::create($this->company->id, $this->user->id);
$bt->bank_integration_id = $bi->id;
$bt->description = 'Fuel';
$bt->amount = 10;
$bt->currency_code = $this->client->currency()->code;
$bt->date = now()->format('Y-m-d');
$bt->transaction_id = 1234567890;
$bt->category_id = 10000003;
2022-10-26 05:03:49 +02:00
$bt->base_type = 'DEBIT';
2022-09-15 09:31:32 +02:00
$bt->save();
2022-10-26 05:03:49 +02:00
$data = [];
$data['transactions'][] = [
2022-09-22 08:20:54 +02:00
'id' => $bt->id,
2022-09-15 09:31:32 +02:00
];
MatchBankTransactions::dispatchSync($this->company->id, $this->company->db, $data);
2022-10-26 05:03:49 +02:00
$expense = Expense::where('transaction_reference', 'Fuel')->first();
2022-09-15 09:31:32 +02:00
$this->assertNotNull($expense);
2023-12-01 14:30:33 +01:00
$this->assertEquals(10, (int) $expense->amount);
2022-09-15 09:31:32 +02:00
}
public function testIncomeMatchingAndPaymentGeneration()
{
$this->account->bank_integration_account_id = 'sbMem62e1e69547bfb2';
2022-09-15 09:31:32 +02:00
$this->account->save();
$invoice = Invoice::factory()->create(['user_id' => $this->user->id, 'company_id' => $this->company->id, 'client_id' => $this->client->id]);
$invoice->status_id = Invoice::STATUS_DRAFT;
$invoice->line_items = $this->buildLineItems();
$invoice->uses_inclusive_taxes = false;
$invoice->tax_rate1 = 0;
$invoice->tax_rate2 = 0;
$invoice->tax_rate3 = 0;
$invoice->discount = 0;
$invoice->number = 'TESTMATCHING';
$invoice->date = now()->format('Y-m-d');
$invoice->save();
$invoice_calc = new InvoiceSum($invoice);
$invoice_calc->build();
$invoice = $invoice_calc->getInvoice();
$invoice->save();
$invoice = $invoice->service()->markSent()->save();
$this->assertEquals(Invoice::STATUS_SENT, $invoice->status_id);
$this->assertEquals(10, $invoice->amount);
$this->assertEquals(10, $invoice->balance);
$bi = BankIntegrationFactory::create($this->company->id, $this->user->id, $this->account->id);
$bi->save();
$bt = BankTransactionFactory::create($this->company->id, $this->user->id);
$bt->bank_integration_id = $bi->id;
$bt->description = $invoice->number;
$bt->amount = 10;
$bt->currency_code = $this->client->currency()->code;
$bt->date = now()->format('Y-m-d');
$bt->transaction_id = 123456;
$bt->save();
2023-12-01 14:30:33 +01:00
2022-10-26 05:03:49 +02:00
$data['transactions'][] = [
2022-09-22 08:20:54 +02:00
'id' => $bt->id,
'invoice_ids' => $invoice->hashed_id
2022-09-15 09:31:32 +02:00
];
MatchBankTransactions::dispatchSync($this->company->id, $this->company->db, $data);
2022-09-21 09:00:49 +02:00
$payment = Payment::where('transaction_reference', $bt->description)->first();
$payment_count = Payment::where('transaction_reference', $bt->description)->count();
2022-09-15 09:31:32 +02:00
$this->assertNotNull($payment);
2023-12-01 14:30:33 +01:00
$this->assertEquals(10, (int) $payment->amount);
2022-09-15 09:31:32 +02:00
$this->assertEquals(4, $payment->status_id);
$this->assertEquals(1, $payment->invoices()->count());
$invoice = $invoice->fresh();
$this->assertEquals(Invoice::STATUS_PAID, $invoice->status_id);
$this->assertEquals(0, $invoice->balance);
$this->assertEquals(1, $payment_count);
2022-09-15 09:31:32 +02:00
}
2022-09-15 08:15:57 +02:00
public function testCategoryPropertyExists()
{
$yodlee = new Yodlee('sbMem62e1e69547bfb2');
$transactions = $yodlee->getTransactionCategories();
2023-12-01 14:30:33 +01:00
$this->assertTrue(property_exists($transactions, 'transactionCategory'));
2022-09-15 08:15:57 +02:00
$t = collect($transactions->transactionCategory);
$x = $t->firstWhere('highLevelCategoryId', 10000003);
$this->assertNotNull($x);
2022-09-15 08:21:47 +02:00
$this->assertEquals('Automotive Expenses', $x->highLevelCategoryName);
2022-09-15 08:15:57 +02:00
}
2023-12-01 14:30:33 +01:00
// public function testFunctionalMatching()
2023-11-26 08:41:42 +01:00
// {
2022-10-27 03:04:42 +02:00
2023-12-01 14:30:33 +01:00
// $yodlee = new Yodlee('sbMem62e1e69547bfb1');
2022-10-27 03:04:42 +02:00
2023-12-01 14:30:33 +01:00
// $accounts = $yodlee->getAccounts();
2022-10-27 03:04:42 +02:00
2023-12-01 14:30:33 +01:00
// foreach($accounts as $account)
2023-11-26 08:41:42 +01:00
// {
2023-12-20 16:04:31 +01:00
// if(!BankIntegration::where('bank_account_id', $account['id'])->where('company_id', $this->company->id)->exists())
2023-11-26 08:41:42 +01:00
// {
// $bank_integration = new BankIntegration();
// $bank_integration->company_id = $this->company->id;
// $bank_integration->account_id = $this->company->account_id;
// $bank_integration->user_id = $this->user->id;
// $bank_integration->bank_account_id = $account['id'];
// $bank_integration->bank_account_type = $account['account_type'];
// $bank_integration->bank_account_name = $account['account_name'];
// $bank_integration->bank_account_status = $account['account_status'];
// $bank_integration->bank_account_number = $account['account_number'];
// $bank_integration->provider_id = $account['provider_id'];
// $bank_integration->provider_name = $account['provider_name'];
// $bank_integration->nickname = $account['nickname'];
// $bank_integration->balance = $account['current_balance'];
// $bank_integration->currency = $account['account_currency'];
2022-08-17 03:52:16 +02:00
2023-12-01 14:30:33 +01:00
// $bank_integration->save();
2022-08-17 03:52:16 +02:00
2023-11-26 08:41:42 +01:00
// ProcessBankTransactions::dispatchSync('sbMem62e1e69547bfb1', $bank_integration);
2023-12-01 14:30:33 +01:00
// }
2023-11-26 08:41:42 +01:00
// }
2022-08-17 03:52:16 +02:00
2023-12-01 14:30:33 +01:00
// $this->assertGreaterThan(0, BankIntegration::count());
2023-11-26 08:41:42 +01:00
// $this->assertGreaterThan(0, BankTransaction::count());
2022-08-17 03:52:16 +02:00
2023-12-01 14:30:33 +01:00
// $this->invoice->company_id = $this->company->id;
2023-11-26 08:41:42 +01:00
// $this->invoice->number = "XXXXXX8501";
// $this->invoice->save();
2022-08-18 01:27:28 +02:00
2023-12-01 14:30:33 +01:00
// BankService::dispatchSync($this->company->id, $this->company->db);
// $bt = BankTransaction::where('invoice_ids', $this->invoice->hashed_id)->first();
2022-08-18 01:27:28 +02:00
2023-12-01 14:30:33 +01:00
// nlog(BankTransaction::where('company_id', $this->company->id)->pluck('invoice_ids'));
2022-08-18 01:27:28 +02:00
2023-12-01 14:30:33 +01:00
// $this->assertNotNull($bt);
2022-08-17 03:52:16 +02:00
2023-12-01 14:30:33 +01:00
// $this->assertEquals(BankTransaction::STATUS_MATCHED, $bt->status_id);
2022-10-27 03:04:42 +02:00
2023-12-01 14:30:33 +01:00
// }
2022-08-17 03:52:16 +02:00
2022-08-08 11:45:06 +02:00
public function testDataMatching()
{
$transaction = collect([
2023-12-01 14:30:33 +01:00
(object) [
2022-08-09 04:21:06 +02:00
'description' => 'tinkertonkton'
],
2023-12-01 14:30:33 +01:00
(object) [
2022-08-09 04:21:06 +02:00
'description' => 'spud'
],
]);
2022-08-08 11:45:06 +02:00
$this->assertEquals(2, $transaction->count());
$hit = $transaction->where('description', 'spud')->first();
$this->assertNotNull($hit);
$hit = $transaction->where('description', 'tinkertonkton')->first();
$this->assertNotNull($hit);
$hit = $transaction->contains('description', 'tinkertonkton');
$this->assertTrue($hit);
$transaction = collect([
2023-12-01 14:30:33 +01:00
(object) [
2022-08-08 11:45:06 +02:00
'description' => 'tinker and spice'
],
2023-12-01 14:30:33 +01:00
(object) [
2022-08-08 11:45:06 +02:00
'description' => 'spud with water'
],
]);
$hit = $transaction->contains('description', 'tinker and spice');
$this->assertTrue($hit);
2022-08-10 03:56:46 +02:00
$invoice = $transaction->first(function ($value, $key) {
2022-08-11 04:39:43 +02:00
return str_contains($value->description, 'tinker');
2022-08-10 03:56:46 +02:00
});
$this->assertNotNull($invoice);
2022-08-08 11:45:06 +02:00
}
2022-08-08 00:32:28 +02:00
public function testYodleeInstance()
2022-08-06 08:58:48 +02:00
{
2022-08-08 00:26:27 +02:00
$yodlee = new Yodlee();
2022-08-06 08:58:48 +02:00
2022-08-08 00:26:27 +02:00
$this->assertNotNull($yodlee);
2022-08-08 00:32:28 +02:00
$this->assertInstanceOf(Yodlee::class, $yodlee);
2022-08-06 08:58:48 +02:00
}
2022-07-28 07:07:35 +02:00
public function testAccessTokenGeneration()
{
2022-08-08 00:26:27 +02:00
$yodlee = new Yodlee('sbMem62e1e69547bfb1');
2022-07-28 07:07:35 +02:00
2022-08-11 04:39:43 +02:00
$access_token = $yodlee->getAccessToken();
2022-07-28 07:07:35 +02:00
$this->assertNotNull($access_token);
}
2023-12-01 14:30:33 +01:00
/**
[transactionCategory] => Array
(
[0] => stdClass Object
(
[id] => 1
[source] => SYSTEM
[classification] => PERSONAL
[category] => Uncategorized
[type] => UNCATEGORIZE
[highLevelCategoryId] => 10000017
[highLevelCategoryName] => Uncategorized
[defaultCategoryName] => Uncategorized
[defaultHighLevelCategoryName] => Uncategorized
)
[1] => stdClass Object
(
[id] => 2
[source] => SYSTEM
[classification] => PERSONAL
[category] => Automotive/Fuel
[type] => EXPENSE
[detailCategory] => Array
(
[0] => stdClass Object
(
[id] => 1041
[name] => Registration/Licensing
)
[1] => stdClass Object
(
[id] => 1145
[name] => Automotive
)
[2] => stdClass Object
(
[id] => 1218
[name] => Auto Fees/Penalties
)
[3] => stdClass Object
(
[id] => 1260
[name] => Car Appraisers
)
[4] => stdClass Object
(
[id] => 1261
[name] => Car Dealers
)
[5] => stdClass Object
(
[id] => 1262
[name] => Car Dealers and Leasing
)
[6] => stdClass Object
(
[id] => 1263
[name] => Car Parts and Accessories
)
[7] => stdClass Object
(
[id] => 1264
[name] => Car Wash and Detail
)
[8] => stdClass Object
(
[id] => 1265
[name] => Classic and Antique Car
)
[9] => stdClass Object
(
[id] => 1267
[name] => Maintenance and Repair
)
[10] => stdClass Object
(
[id] => 1268
[name] => Motorcycles/Mopeds/Scooters
)
[11] => stdClass Object
(
[id] => 1269
[name] => Oil and Lube
)
[12] => stdClass Object
(
[id] => 1270
[name] => Motorcycle Repair
)
[13] => stdClass Object
(
[id] => 1271
[name] => RVs and Motor Homes
)
[14] => stdClass Object
(
[id] => 1272
[name] => Motorcycle Sales
)
[15] => stdClass Object
(
[id] => 1273
[name] => Salvage Yards
)
[16] => stdClass Object
(
[id] => 1274
[name] => Smog Check
)
[17] => stdClass Object
(
[id] => 1275
[name] => Tires
)
[18] => stdClass Object
(
[id] => 1276
[name] => Towing
)
[19] => stdClass Object
(
[id] => 1277
[name] => Transmissions
)
[20] => stdClass Object
(
[id] => 1278
[name] => Used Cars
)
[21] => stdClass Object
(
[id] => 1240
[name] => e-Charging
)
[22] => stdClass Object
(
[id] => 1266
[name] => Gas Stations
)
)
[highLevelCategoryId] => 10000003
[highLevelCategoryName] => Automotive Expenses
[defaultCategoryName] => Automotive Expenses
[defaultHighLevelCategoryName] => Automotive Expenses
)
*/
2022-08-05 03:37:31 +02:00
2022-07-30 04:10:42 +02:00
public function testGetCategories()
2022-07-28 08:29:42 +02:00
{
2022-08-08 00:26:27 +02:00
$yodlee = new Yodlee('sbMem62e1e69547bfb2');
2022-07-30 04:10:42 +02:00
2022-08-08 00:26:27 +02:00
$transactions = $yodlee->getTransactionCategories();
2023-12-01 14:30:33 +01:00
2022-08-08 00:32:28 +02:00
$this->assertIsArray($transactions->transactionCategory);
2022-07-30 04:10:42 +02:00
}
2022-09-15 08:15:57 +02:00
2023-12-01 14:30:33 +01:00
/**
[2022-08-05 01:29:45] local.INFO: stdClass Object
(
[account] => Array
(
[0] => stdClass Object
(
[CONTAINER] => bank
[providerAccountId] => 11308693
[accountName] => My CD - 8878
[accountStatus] => ACTIVE
[accountNumber] => xxxx8878
[aggregationSource] => USER
[isAsset] => 1
[balance] => stdClass Object
(
[currency] => USD
[amount] => 49778.07
)
[id] => 12331861
[includeInNetWorth] => 1
[providerId] => 18769
[providerName] => Dag Site Captcha
[isManual] =>
[currentBalance] => stdClass Object
(
[currency] => USD
[amount] => 49778.07
)
[accountType] => CD
[displayedName] => LORETTA
[createdDate] => 2022-07-28T06:55:33Z
[lastUpdated] => 2022-07-28T06:56:09Z
[dataset] => Array
(
[0] => stdClass Object
(
[name] => BASIC_AGG_DATA
[additionalStatus] => AVAILABLE_DATA_RETRIEVED
[updateEligibility] => ALLOW_UPDATE
[lastUpdated] => 2022-07-28T06:55:50Z
[lastUpdateAttempt] => 2022-07-28T06:55:50Z
)
)
)
[1] => stdClass Object
(
[CONTAINER] => bank
[providerAccountId] => 11308693
[accountName] => Joint Savings - 7159
[accountStatus] => ACTIVE
[accountNumber] => xxxx7159
[aggregationSource] => USER
[isAsset] => 1
[balance] => stdClass Object
(
[currency] => USD
[amount] => 186277.45
)
[id] => 12331860
[includeInNetWorth] => 1
[providerId] => 18769
[providerName] => Dag Site Captcha
[isManual] =>
[availableBalance] => stdClass Object
(
[currency] => USD
[amount] => 186277.45
)
[currentBalance] => stdClass Object
(
[currency] => USD
[amount] => 186277.45
)
[accountType] => SAVINGS
[displayedName] => LYDIA
[createdDate] => 2022-07-28T06:55:33Z
[classification] => PERSONAL
[lastUpdated] => 2022-07-28T06:56:09Z
[dataset] => Array
(
[0] => stdClass Object
(
[name] => BASIC_AGG_DATA
[additionalStatus] => AVAILABLE_DATA_RETRIEVED
[updateEligibility] => ALLOW_UPDATE
[lastUpdated] => 2022-07-28T06:55:50Z
[lastUpdateAttempt] => 2022-07-28T06:55:50Z
)
)
)
*/
2022-07-30 04:10:42 +02:00
public function testGetAccounts()
{
2022-08-08 00:26:27 +02:00
$yodlee = new Yodlee('sbMem62e1e69547bfb1');
2022-07-28 08:29:42 +02:00
2022-08-08 00:26:27 +02:00
$accounts = $yodlee->getAccounts();
2022-08-15 22:03:12 +02:00
2022-08-08 01:15:31 +02:00
$this->assertIsArray($accounts);
2022-07-30 04:10:42 +02:00
}
2022-08-05 03:37:31 +02:00
2023-12-01 14:30:33 +01:00
/**
[2022-08-05 01:36:34] local.INFO: stdClass Object
(
[transaction] => Array
(
[0] => stdClass Object
(
[CONTAINER] => bank
[id] => 103953585
[amount] => stdClass Object
(
[amount] => 480.66
[currency] => USD
)
[categoryType] => UNCATEGORIZE
[categoryId] => 1
[category] => Uncategorized
[categorySource] => SYSTEM
[highLevelCategoryId] => 10000017
[createdDate] => 2022-08-04T21:50:17Z
[lastUpdated] => 2022-08-04T21:50:17Z
[description] => stdClass Object
(
[original] => CHEROKEE NATION TAX TA TAHLEQUAH OK
)
[isManual] =>
[sourceType] => AGGREGATED
[date] => 2022-08-03
[transactionDate] => 2022-08-03
[postDate] => 2022-08-03
[status] => POSTED
[accountId] => 12331794
[runningBalance] => stdClass Object
(
[amount] => 480.66
[currency] => USD
)
[checkNumber] => 998
)
*/
2022-08-05 03:37:31 +02:00
2022-07-30 04:10:42 +02:00
public function testGetTransactions()
{
2022-08-08 00:26:27 +02:00
$yodlee = new Yodlee('sbMem62e1e69547bfb1');
2022-08-05 05:45:53 +02:00
2022-08-08 00:26:27 +02:00
$transactions = $yodlee->getTransactions(['categoryId' => 2, 'fromDate' => '2000-01-01']);
2022-07-30 04:10:42 +02:00
2022-08-08 06:04:39 +02:00
$this->assertIsArray($transactions);
2022-07-28 08:29:42 +02:00
}
2022-08-08 04:46:41 +02:00
public function testGetTransactionsWithParams()
{
$yodlee = new Yodlee('sbMem62e1e69547bfb1');
$data = [
2022-08-08 04:59:56 +02:00
'basetype' => 'DEBIT', //CREDIT
2022-08-08 04:46:41 +02:00
'CONTAINER' => 'bank',
'top' => 500,
'fromDate' => '2000-10-10', /// YYYY-MM-DD
];
2023-12-01 14:30:33 +01:00
$accounts = $yodlee->getTransactions($data);
2022-08-08 04:46:41 +02:00
2022-08-17 03:52:16 +02:00
$this->assertIsArray($accounts);
2022-08-08 04:46:41 +02:00
}
2022-07-28 07:07:35 +02:00
}