diff --git a/app/Http/Controllers/ImportQuickbooksController.php b/app/Http/Controllers/ImportQuickbooksController.php index be08f66333..88e6a180b8 100644 --- a/app/Http/Controllers/ImportQuickbooksController.php +++ b/app/Http/Controllers/ImportQuickbooksController.php @@ -15,7 +15,7 @@ use App\Http\Requests\Quickbooks\AuthorizedQuickbooksRequest; use App\Libraries\MultiDB; use Illuminate\Support\Facades\Cache; use App\Http\Requests\Quickbooks\AuthQuickbooksRequest; -use App\Services\Import\Quickbooks\QuickbooksService; +use App\Services\Quickbooks\QuickbooksService; class ImportQuickbooksController extends BaseController { diff --git a/app/Services/Import/Quickbooks/QuickbooksService.php b/app/Services/Quickbooks/Jobs/QuickbooksSync.php similarity index 73% rename from app/Services/Import/Quickbooks/QuickbooksService.php rename to app/Services/Quickbooks/Jobs/QuickbooksSync.php index 08188d3dd3..9a7d0dbac7 100644 --- a/app/Services/Import/Quickbooks/QuickbooksService.php +++ b/app/Services/Quickbooks/Jobs/QuickbooksSync.php @@ -9,31 +9,38 @@ * @license https://www.elastic.co/licensing/elastic-license */ -namespace App\Services\Import\Quickbooks; +namespace App\Services\Quickbooks\Jobs; -use App\Factory\ClientContactFactory; -use App\Factory\ClientFactory; -use App\Factory\InvoiceFactory; -use App\Factory\ProductFactory; use App\Models\Client; use App\Models\Company; use App\Models\Invoice; use App\Models\Product; -use QuickBooksOnline\API\Core\CoreConstants; -use QuickBooksOnline\API\DataService\DataService; -use App\Services\Import\Quickbooks\Transformers\ClientTransformer; -use App\Services\Import\Quickbooks\Transformers\InvoiceTransformer; -use App\Services\Import\Quickbooks\Transformers\PaymentTransformer; -use App\Services\Import\Quickbooks\Transformers\ProductTransformer; +use App\Libraries\MultiDB; +use Illuminate\Bus\Queueable; +use App\Factory\ClientFactory; +use App\Factory\InvoiceFactory; +use App\Factory\ProductFactory; +use App\Factory\ClientContactFactory; +use App\DataMapper\QuickbooksSettings; +use Illuminate\Queue\SerializesModels; +use Illuminate\Queue\InteractsWithQueue; +use Illuminate\Contracts\Queue\ShouldQueue; +use Illuminate\Foundation\Bus\Dispatchable; +use App\Services\Quickbooks\QuickbooksService; +use Illuminate\Queue\Middleware\WithoutOverlapping; +use App\Services\Quickbooks\Transformers\ClientTransformer; +use App\Services\Quickbooks\Transformers\InvoiceTransformer; +use App\Services\Quickbooks\Transformers\PaymentTransformer; +use App\Services\Quickbooks\Transformers\ProductTransformer; -// quickbooks_realm_id -// quickbooks_refresh_token -// quickbooks_refresh_expires -class QuickbooksService +class QuickbooksSync implements ShouldQueue { - public DataService $sdk; - - private $entities = [ + use Dispatchable; + use InteractsWithQueue; + use Queueable; + use SerializesModels; + + private array $entities = [ 'product' => 'Item', 'client' => 'Customer', 'invoice' => 'Invoice', @@ -42,73 +49,34 @@ class QuickbooksService 'payment' => 'Payment', ]; - private bool $testMode = true; + private QuickbooksService $qbs; - private mixed $settings; + private ?array $settings; - public function __construct(private Company $company) + private Company $company; + + public function __construct(public int $company_id, public string $db) { - $this->init(); - $this->settings = $this->company->quickbooks->settings; } - private function init(): self - { - - $config = [ - 'ClientID' => config('services.quickbooks.client_id'), - '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://above-distinctly-teal.ngrok-free.app/quickbooks/authorized' : 'https://invoicing.co/quickbooks/authorized', - 'baseUrl' => $this->testMode ? CoreConstants::SANDBOX_DEVELOPMENT : CoreConstants::QBO_BASEURL, - ]; - - $merged = array_merge($config, $this->ninjaAccessToken()); - - $this->sdk = DataService::Configure($merged); - - $this->sdk->setLogLocation(storage_path("logs/quickbooks.log")); - $this->sdk->enableLog(); - - $this->sdk->setMinorVersion("73"); - $this->sdk->throwExceptionOnError(true); - - return $this; - } - - private function ninjaAccessToken() - { - return isset($this->company->quickbooks->accessTokenKey) ? [ - 'accessTokenKey' => $this->company->quickbooks->accessTokenKey, - 'refreshTokenKey' => $this->company->quickbooks->refresh_token, - 'QBORealmID' => $this->company->quickbooks->realmID, - ] : []; - } - - public function sdk(): SdkWrapper - { - return new SdkWrapper($this->sdk, $this->company); - } - /** - * //@todo - refactor to a job - * - * @return void + * Execute the job. */ - public function syncFromQb() + public function handle() { - //syncable_records. - - foreach($this->entities as $key => $entity) - { - if(!$this->syncGate($key, 'pull')) + MultiDB::setDb($this->db); + + $this->company = Company::find($this->company_id); + $this->qbs = new QuickbooksService($this->company); + $this->settings = $this->company->quickbooks->settings; + + nlog("here we go!"); + foreach($this->entities as $key => $entity) { + if(!$this->syncGate($key, 'pull')) { continue; + } - $records = $this->sdk()->fetchRecords($entity); - - // nlog(json_encode($records)); + $records = $this->qbs->sdk()->fetchRecords($entity); $this->processEntitySync($key, $records); @@ -126,10 +94,10 @@ class QuickbooksService return (bool) $this->settings[$entity]['sync'] && $this->settings[$entity]['update_record']; } - private function harvestQbEntityName(string $entity): string - { - return $this->entities[$entity]; - } + // private function harvestQbEntityName(string $entity): string + // { + // return $this->entities[$entity]; + // } private function processEntitySync(string $entity, $records) { @@ -171,7 +139,7 @@ class QuickbooksService foreach($payment_ids as $payment_id) { - $payment = $this->sdk->FindById('Payment', $payment_id); + $payment = $this->qbs->sdk->FindById('Payment', $payment_id); $payment_transformer = new PaymentTransformer($this->company); $transformed = $payment_transformer->qbToNinja($payment); @@ -261,7 +229,6 @@ class QuickbooksService foreach($records as $record) { $ninja_data = $product_transformer->qbToNinja($record); -// nlog($ninja_data); if($product = $this->findProduct($ninja_data['hash'])) { @@ -326,4 +293,16 @@ class QuickbooksService } + + public function middleware() + { + return [new WithoutOverlapping("qbs-{$this->company_id}-{$this->db}")]; + } + + public function failed($exception) + { + nlog("QuickbooksSync failed => ".$exception->getMessage()); + config(['queue.failed.driver' => null]); + + } } diff --git a/app/Services/Quickbooks/QuickbooksService.php b/app/Services/Quickbooks/QuickbooksService.php new file mode 100644 index 0000000000..d61e1065bb --- /dev/null +++ b/app/Services/Quickbooks/QuickbooksService.php @@ -0,0 +1,94 @@ +init(); + } + + private function init(): self + { + + $config = [ + 'ClientID' => config('services.quickbooks.client_id'), + '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://above-distinctly-teal.ngrok-free.app/quickbooks/authorized' : 'https://invoicing.co/quickbooks/authorized', + 'baseUrl' => $this->testMode ? CoreConstants::SANDBOX_DEVELOPMENT : CoreConstants::QBO_BASEURL, + ]; + + $merged = array_merge($config, $this->ninjaAccessToken()); + + $this->sdk = DataService::Configure($merged); + + $this->sdk->setLogLocation(storage_path("logs/quickbooks.log")); + $this->sdk->enableLog(); + + $this->sdk->setMinorVersion("73"); + $this->sdk->throwExceptionOnError(true); + + return $this; + } + + private function ninjaAccessToken() + { + return isset($this->company->quickbooks->accessTokenKey) ? [ + 'accessTokenKey' => $this->company->quickbooks->accessTokenKey, + 'refreshTokenKey' => $this->company->quickbooks->refresh_token, + 'QBORealmID' => $this->company->quickbooks->realmID, + ] : []; + } + + public function sdk(): SdkWrapper + { + return new SdkWrapper($this->sdk, $this->company); + } + + /** + * //@todo - refactor to a job + * + * @return void + */ + public function syncFromQb() + { + QuickbooksSync::dispatch($this->company); + } + +} diff --git a/app/Services/Import/Quickbooks/SdkWrapper.php b/app/Services/Quickbooks/SdkWrapper.php similarity index 99% rename from app/Services/Import/Quickbooks/SdkWrapper.php rename to app/Services/Quickbooks/SdkWrapper.php index afc1502a71..eda0006b33 100644 --- a/app/Services/Import/Quickbooks/SdkWrapper.php +++ b/app/Services/Quickbooks/SdkWrapper.php @@ -9,7 +9,7 @@ * @license https://www.elastic.co/licensing/elastic-license */ -namespace App\Services\Import\Quickbooks; +namespace App\Services\Quickbooks; use App\DataMapper\QuickbooksSettings; use Carbon\Carbon; diff --git a/app/Services/Import/Quickbooks/Transformers/BaseTransformer.php b/app/Services/Quickbooks/Transformers/BaseTransformer.php similarity index 97% rename from app/Services/Import/Quickbooks/Transformers/BaseTransformer.php rename to app/Services/Quickbooks/Transformers/BaseTransformer.php index 349bd9ff67..a9b6439d03 100644 --- a/app/Services/Import/Quickbooks/Transformers/BaseTransformer.php +++ b/app/Services/Quickbooks/Transformers/BaseTransformer.php @@ -10,7 +10,7 @@ * @license https://www.elastic.co/licensing/elastic-license */ -namespace App\Services\Import\Quickbooks\Transformers; +namespace App\Services\Quickbooks\Transformers; use App\Models\Client; use App\Models\Company; diff --git a/app/Services/Import/Quickbooks/Transformers/ClientTransformer.php b/app/Services/Quickbooks/Transformers/ClientTransformer.php similarity index 97% rename from app/Services/Import/Quickbooks/Transformers/ClientTransformer.php rename to app/Services/Quickbooks/Transformers/ClientTransformer.php index 859eab3fd4..d66532a8a2 100644 --- a/app/Services/Import/Quickbooks/Transformers/ClientTransformer.php +++ b/app/Services/Quickbooks/Transformers/ClientTransformer.php @@ -10,7 +10,7 @@ * @license https://www.elastic.co/licensing/elastic-license */ -namespace App\Services\Import\Quickbooks\Transformers; +namespace App\Services\Quickbooks\Transformers; use App\DataMapper\ClientSettings; diff --git a/app/Services/Import/Quickbooks/Transformers/InvoiceTransformer.php b/app/Services/Quickbooks/Transformers/InvoiceTransformer.php similarity index 99% rename from app/Services/Import/Quickbooks/Transformers/InvoiceTransformer.php rename to app/Services/Quickbooks/Transformers/InvoiceTransformer.php index b8aab65714..4e5273a55c 100644 --- a/app/Services/Import/Quickbooks/Transformers/InvoiceTransformer.php +++ b/app/Services/Quickbooks/Transformers/InvoiceTransformer.php @@ -10,7 +10,7 @@ * @license https://www.elastic.co/licensing/elastic-license */ -namespace App\Services\Import\Quickbooks\Transformers; +namespace App\Services\Quickbooks\Transformers; use App\Models\Client; use App\Models\Company; diff --git a/app/Services/Import/Quickbooks/Transformers/PaymentTransformer.php b/app/Services/Quickbooks/Transformers/PaymentTransformer.php similarity index 97% rename from app/Services/Import/Quickbooks/Transformers/PaymentTransformer.php rename to app/Services/Quickbooks/Transformers/PaymentTransformer.php index 247ee1dc75..9b1d0a6691 100644 --- a/app/Services/Import/Quickbooks/Transformers/PaymentTransformer.php +++ b/app/Services/Quickbooks/Transformers/PaymentTransformer.php @@ -9,7 +9,7 @@ * @license https://www.elastic.co/licensing/elastic-license */ -namespace App\Services\Import\Quickbooks\Transformers; +namespace App\Services\Quickbooks\Transformers; use App\Models\Company; use App\Models\Payment; diff --git a/app/Services/Import/Quickbooks/Transformers/ProductTransformer.php b/app/Services/Quickbooks/Transformers/ProductTransformer.php similarity index 95% rename from app/Services/Import/Quickbooks/Transformers/ProductTransformer.php rename to app/Services/Quickbooks/Transformers/ProductTransformer.php index 4ec71a5b6e..7b638d23e5 100644 --- a/app/Services/Import/Quickbooks/Transformers/ProductTransformer.php +++ b/app/Services/Quickbooks/Transformers/ProductTransformer.php @@ -10,7 +10,7 @@ * @license https://www.elastic.co/licensing/elastic-license */ -namespace App\Services\Import\Quickbooks\Transformers; +namespace App\Services\Quickbooks\Transformers; /** * Class ProductTransformer. diff --git a/tests/Feature/Http/Controllers/ImportQuickbooksControllerTest.php b/tests/Feature/Http/Controllers/ImportQuickbooksControllerTest.php index aeaf01aa12..4f9feb3a41 100644 --- a/tests/Feature/Http/Controllers/ImportQuickbooksControllerTest.php +++ b/tests/Feature/Http/Controllers/ImportQuickbooksControllerTest.php @@ -2,9 +2,9 @@ namespace Tests\Feature\Http\Controllers; -use App\Services\Import\Quickbooks\Contracts\SdkInterface as QuickbooksInterface; -use App\Services\Import\Quickbooks\Service as QuickbooksService; -use App\Services\Import\Quickbooks\SdkWrapper as QuickbooksSDK; +use App\Services\Quickbooks\Contracts\SdkInterface as QuickbooksInterface; +use App\Services\Quickbooks\Service as QuickbooksService; +use App\Services\Quickbooks\SdkWrapper as QuickbooksSDK; use Illuminate\Foundation\Testing\DatabaseTransactions; use Illuminate\Foundation\Testing\RefreshDatabase; use Illuminate\Foundation\Testing\WithFaker; diff --git a/tests/Integration/Services/Import/Quickbooks/QuickBooksServiceTest.php b/tests/Integration/Services/Import/Quickbooks/QuickBooksServiceTest.php index 6a99158653..52f7860d9a 100644 --- a/tests/Integration/Services/Import/Quickbooks/QuickBooksServiceTest.php +++ b/tests/Integration/Services/Import/Quickbooks/QuickBooksServiceTest.php @@ -2,9 +2,9 @@ namespace Tests\Integration\Services\Import\Quickbooks; -use App\Services\Import\Quickbooks\Contracts\SdkInterface as QuickbooksInterface; -use App\Services\Import\Quickbooks\Service as QuickbooksService; -use App\Services\Import\Quickbooks\SdkWrapper as QuickbooksSDK; +use App\Services\Quickbooks\Contracts\SdkInterface as QuickbooksInterface; +use App\Services\Quickbooks\Service as QuickbooksService; +use App\Services\Quickbooks\SdkWrapper as QuickbooksSDK; use Illuminate\Support\Collection; use Illuminate\Support\Arr; use Tests\TestCase; diff --git a/tests/Unit/Services/Import/Quickbooks/SdkWrapperTest.php b/tests/Unit/Services/Import/Quickbooks/SdkWrapperTest.php index 291f8aae2d..5af90e4f50 100644 --- a/tests/Unit/Services/Import/Quickbooks/SdkWrapperTest.php +++ b/tests/Unit/Services/Import/Quickbooks/SdkWrapperTest.php @@ -7,8 +7,8 @@ namespace Tests\Unit\Services\Import\Quickbooks; use Mockery; use Tests\TestCase; use Illuminate\Support\Arr; -use App\Services\Import\Quickbooks\Contracts\SdkInterface; -use App\Services\Import\Quickbooks\SdkWrapper as QuickbookSDK; +use App\Services\Quickbooks\Contracts\SdkInterface; +use App\Services\Quickbooks\SdkWrapper as QuickbookSDK; class SdkWrapperTest extends TestCase { diff --git a/tests/Unit/Services/Import/Quickbooks/ServiceTest.php b/tests/Unit/Services/Import/Quickbooks/ServiceTest.php index b441e5ed56..327136ebd0 100644 --- a/tests/Unit/Services/Import/Quickbooks/ServiceTest.php +++ b/tests/Unit/Services/Import/Quickbooks/ServiceTest.php @@ -5,8 +5,8 @@ namespace Tests\Unit\Services\Import\Quickbooks; use Mockery; use Tests\TestCase; use Illuminate\Support\Collection; -use App\Services\Import\Quickbooks\Service as QuickbooksService; -use App\Services\Import\Quickbooks\Contracts\SdkInterface as QuickbooksInterface; +use App\Services\Quickbooks\Service as QuickbooksService; +use App\Services\Quickbooks\Contracts\SdkInterface as QuickbooksInterface; class ServiceTest extends TestCase {