From 94fb81c57b2990c18213cf5842e447dac6ba5281 Mon Sep 17 00:00:00 2001 From: David Bomba Date: Wed, 25 Sep 2024 14:20:49 +1000 Subject: [PATCH] Small fixes for QB oauth --- .../ImportQuickbooksController.php | 39 +++---- app/Services/Quickbooks/QuickbooksService.php | 9 +- app/Services/Quickbooks/SdkWrapper.php | 4 +- .../Import/Quickbooks/QuickbooksTest.php | 103 +++++++++++++++--- 4 files changed, 110 insertions(+), 45 deletions(-) diff --git a/app/Http/Controllers/ImportQuickbooksController.php b/app/Http/Controllers/ImportQuickbooksController.php index e1d75589e3ea..3b3cf53b21eb 100644 --- a/app/Http/Controllers/ImportQuickbooksController.php +++ b/app/Http/Controllers/ImportQuickbooksController.php @@ -19,28 +19,6 @@ use App\Services\Quickbooks\QuickbooksService; class ImportQuickbooksController extends BaseController { - // private array $import_entities = [ - // 'client' => 'Customer', - // 'invoice' => 'Invoice', - // 'product' => 'Item', - // 'payment' => 'Payment' - // ]; - - public function onAuthorized(AuthorizedQuickbooksRequest $request) - { - - MultiDB::findAndSetDbByCompanyKey($request->getTokenContent()['company_key']); - $company = $request->getCompany(); - $qb = new QuickbooksService($company); - - $realm = $request->query('realmId'); - $access_token_object = $qb->sdk()->accessTokenFromCode($request->query('code'), $realm); - $qb->sdk()->saveOAuthToken($access_token_object); - - return redirect(config('ninja.react_url')); - - } - /** * Determine if the user is authorized to make this request. * @@ -59,5 +37,22 @@ class ImportQuickbooksController extends BaseController return redirect()->to($authorizationUrl); } + + public function onAuthorized(AuthorizedQuickbooksRequest $request) + { + + MultiDB::findAndSetDbByCompanyKey($request->getTokenContent()['company_key']); + $company = $request->getCompany(); + $qb = new QuickbooksService($company); + + $realm = $request->query('realmId'); + $access_token_object = $qb->sdk()->accessTokenFromCode($request->query('code'), $realm); + $qb->sdk()->saveOAuthToken($access_token_object); + + return redirect(config('ninja.react_url')); + + } + + } diff --git a/app/Services/Quickbooks/QuickbooksService.php b/app/Services/Quickbooks/QuickbooksService.php index 60bf92a86fc1..38460274277b 100644 --- a/app/Services/Quickbooks/QuickbooksService.php +++ b/app/Services/Quickbooks/QuickbooksService.php @@ -60,7 +60,6 @@ class QuickbooksService 'ClientSecret' => config('services.quickbooks.client_secret'), 'auth_mode' => 'oauth2', 'scope' => "com.intuit.quickbooks.accounting", - // 'RedirectURI' => 'https://developer.intuit.com/v2/OAuth2Playground/RedirectUrl', 'RedirectURI' => $this->testMode ? 'https://grok.romulus.com.au/quickbooks/authorized' : 'https://invoicing.co/quickbooks/authorized', 'baseUrl' => $this->testMode ? CoreConstants::SANDBOX_DEVELOPMENT : CoreConstants::QBO_BASEURL, ]; @@ -69,7 +68,7 @@ class QuickbooksService $this->sdk = DataService::Configure($merged); - $this->sdk->setLogLocation(storage_path("logs/quickbooks.log")); + // $this->sdk->setLogLocation(storage_path("logs/quickbooks.log")); $this->sdk->enableLog(); $this->sdk->setMinorVersion("73"); @@ -91,10 +90,10 @@ class QuickbooksService private function checkToken(): self { - if($this->company->quickbooks->accessTokenExpiresAt > time()) + if($this->company->quickbooks->accessTokenExpiresAt == 0 || $this->company->quickbooks->accessTokenExpiresAt > time()) return $this; - if($this->company->quickbooks->accessTokenExpiresAt < time() && $this->try_refresh){ + if($this->company->quickbooks->accessTokenExpiresAt && $this->company->quickbooks->accessTokenExpiresAt < time() && $this->try_refresh){ $this->sdk()->refreshToken($this->company->quickbooks->refresh_token); $this->company = $this->company->fresh(); $this->try_refresh = false; @@ -110,7 +109,7 @@ class QuickbooksService private function ninjaAccessToken(): array { - return isset($this->company->quickbooks->accessTokenKey) ? [ + return $this->company->quickbooks->accessTokenExpiresAt > 0 ? [ 'accessTokenKey' => $this->company->quickbooks->accessTokenKey, 'refreshTokenKey' => $this->company->quickbooks->refresh_token, 'QBORealmID' => $this->company->quickbooks->realmID, diff --git a/app/Services/Quickbooks/SdkWrapper.php b/app/Services/Quickbooks/SdkWrapper.php index d6ac56f43dfb..2fb7e688ac73 100644 --- a/app/Services/Quickbooks/SdkWrapper.php +++ b/app/Services/Quickbooks/SdkWrapper.php @@ -33,7 +33,7 @@ class SdkWrapper private function init(): self { - isset($this->company->quickbooks->accessTokenKey) ? $this->setNinjaAccessToken($this->company->quickbooks) : null; + $this->setNinjaAccessToken($this->company->quickbooks); return $this; @@ -104,7 +104,7 @@ class SdkWrapper $this->setAccessToken($token); - if($token_object->accessTokenExpiresAt < time()){ + if($token_object->accessTokenExpiresAt != 0 && $token_object->accessTokenExpiresAt < time()){ $this->refreshToken($token_object->refresh_token); } diff --git a/tests/Feature/Import/Quickbooks/QuickbooksTest.php b/tests/Feature/Import/Quickbooks/QuickbooksTest.php index d21fb0cc7b8f..9954486dbcdb 100644 --- a/tests/Feature/Import/Quickbooks/QuickbooksTest.php +++ b/tests/Feature/Import/Quickbooks/QuickbooksTest.php @@ -12,6 +12,7 @@ use App\Models\Product; use Tests\MockAccountData; use Illuminate\Support\Str; use App\DataMapper\ClientSync; +use App\DataMapper\InvoiceItem; use App\Utils\Traits\MakesHash; use App\Import\Providers\Quickbooks; use Illuminate\Support\Facades\Auth; @@ -26,7 +27,6 @@ class QuickbooksTest extends TestCase { use MakesHash; use MockAccountData; - use DatabaseTransactions; protected $quickbooks; protected $data; @@ -90,7 +90,13 @@ class QuickbooksTest extends TestCase // Send the create request to QuickBooks $resultingCustomerObj = $this->qb->sdk->Add($customer); - return $resultingCustomerObj; + $sync = new ClientSync(); + $sync->qb_id = data_get($resultingCustomerObj, 'Id.value'); + + $this->client->sync = $sync; + $this->client->save(); + + return [$resultingCustomerObj, $this->client->id]; } @@ -124,28 +130,77 @@ class QuickbooksTest extends TestCase $this->fail("The Customer could not be created: " . $error->getResponseBody()); } - $qb_id = data_get($resultingCustomerObj, 'Id.value'); + $qb_id = data_get($resultingCustomerObj[0], 'Id.value'); $this->assertNotNull($qb_id); - $sync = new ClientSync(); - $sync->qb_id = $qb_id; - $this->client->sync = $sync; - $this->client->save(); - - $c = $this->client->fresh(); - + $c = Client::find($resultingCustomerObj[1]); + $this->assertEquals($qb_id, $c->sync->qb_id); } - public function createQbInvoice($customer) + public function createQbInvoice($customer_payload) { + $customer = $customer_payload[0]; + $client_id = $customer_payload[1]; + + nlog(data_get($customer, 'Id.value')); + + $client = Client::find($client_id); + + nlog($client); + $item_product = new InvoiceItem(); + $item_product->product_key = $this->faker->word(); // Changed from randomWord() to word() + $item_product->notes = $this->faker->sentence(); + $item_product->quantity = 1; + $item_product->cost = 10; + $item_product->line_total = 10; + $item_product->type_id = '1'; + + $item_service = new InvoiceItem(); + $item_service->product_key = $this->faker->word(); // Changed from randomWord() to word() + $item_service->notes = $this->faker->sentence(); + $item_service->quantity = 1; + $item_service->cost = 20; + $item_service->line_total = 20; + $item_service->type_id = '2'; + + + $i = Invoice::factory()->create([ + 'company_id' => $this->company->id, + 'user_id' => $client->user_id, + 'client_id' => $client->id, + 'date' => '2024-09-01', + 'due_date' => '2024-09-30', + 'public_notes' => 'Test invoice', + 'tax_name1' => '', + 'tax_rate1' => 0, + 'tax_name2' => '', + 'tax_rate2' => 0, + 'tax_name3' => '', + 'tax_rate3' => 0, + 'amount' => 30, + 'paid_to_date' => 0, + 'is_amount_discount' => 0, + 'discount' => 0, + 'line_items' => [$item_product, $item_service], + ]); + + $i->calc()->getInvoice()->service()->applyNumber()->markSent()->createInvitations()->save(); + + $this->assertEquals(2, $i->status_id); + $this->assertEquals(30, $i->amount); + $this->assertEquals(0, $i->paid_to_date); + $this->assertEquals(0, $i->is_amount_discount); + $this->assertEquals(0, $i->discount); + $this->assertEquals(30, $i->balance); + $line_items = []; $line_num = 1; - foreach($this->invoice->line_items as $line_item) + foreach($i->line_items as $line_item) { $line_items[] = [ @@ -175,11 +230,12 @@ class QuickbooksTest extends TestCase "value" => data_get($customer, 'Id.value') ], "BillEmail" => [ - "Address" => $this->client->present()->email() + "Address" => $c->present()->email() ], - "DueDate" => $this->invoice->due_date, - "TotalAmt" => $this->invoice->amount, - "DocNumber" => $this->invoice->number, + "TxnDate" => $i->date, + "DueDate" => $i->due_date, + "TotalAmt" => $i->amount, + "DocNumber" => $i->number, // "Note" => $this->invoice->public_notes, ]; @@ -206,5 +262,20 @@ class QuickbooksTest extends TestCase return $typeMap[$line_item->type_id] ?? 'Service'; } + protected function tearDown(): void + { + + $this->company->clients()->forceDelete(); + $this->company->products()->forceDelete(); + $this->company->projects()->forceDelete(); + $this->company->tasks()->forceDelete(); + $this->company->vendors()->forceDelete(); + $this->company->expenses()->forceDelete(); + $this->company->purchase_orders()->forceDelete(); + $this->company->bank_transaction_rules()->forceDelete(); + $this->company->bank_transactions()->forceDelete(); + + parent::tearDown(); + } }