Initial integration with Quickbooks
This commit is contained in:
parent
eb254def7a
commit
9fa773d283
7
app/Classes/External/Accounting.php
vendored
Normal file
7
app/Classes/External/Accounting.php
vendored
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Classes\External;
|
||||||
|
|
||||||
|
abstract class Accounting
|
||||||
|
{
|
||||||
|
}
|
50
app/Classes/External/Accounting/Quickbooks.php
vendored
Normal file
50
app/Classes/External/Accounting/Quickbooks.php
vendored
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Classes\External\Accounting;
|
||||||
|
|
||||||
|
use Illuminate\Support\Collection;
|
||||||
|
use Illuminate\Support\Facades\Auth;
|
||||||
|
use Illuminate\Support\Facades\Cache;
|
||||||
|
|
||||||
|
use QuickBooksOnline\API\Data\IPPCustomer;
|
||||||
|
use QuickBooksOnline\API\Facades\Customer;
|
||||||
|
|
||||||
|
use App\User;
|
||||||
|
use App\Classes\External\Accounting as Base;
|
||||||
|
|
||||||
|
class Quickbooks extends Base
|
||||||
|
{
|
||||||
|
private $api = NULL;
|
||||||
|
|
||||||
|
public function __construct(User $uo)
|
||||||
|
{
|
||||||
|
if (Auth::user())
|
||||||
|
throw new \Exception('User logged in - *TODO* handle this');
|
||||||
|
|
||||||
|
Auth::loginUsingId($uo->id);
|
||||||
|
|
||||||
|
$this->api = app('Spinen\QuickBooks\Client');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getCustomers($refresh=FALSE): Collection
|
||||||
|
{
|
||||||
|
if ($refresh)
|
||||||
|
Cache::forget(__METHOD__);
|
||||||
|
|
||||||
|
return Cache::remember(__METHOD__,86400,function() {
|
||||||
|
return collect($this->api->getDataService()->Query('SELECT * FROM Customer'));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public function updateCustomer(IPPCustomer $r,array $args)
|
||||||
|
{
|
||||||
|
$r->sparse = TRUE;
|
||||||
|
|
||||||
|
foreach ($args as $k=>$v)
|
||||||
|
{
|
||||||
|
$r->{$k} = $v;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->api->getDataService()->Update($r);
|
||||||
|
}
|
||||||
|
}
|
269
app/Console/Commands/QuickAccounts.php
Normal file
269
app/Console/Commands/QuickAccounts.php
Normal file
@ -0,0 +1,269 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Console\Commands;
|
||||||
|
|
||||||
|
use App\User;
|
||||||
|
use Illuminate\Console\Command;
|
||||||
|
use Illuminate\Support\Facades\DB;
|
||||||
|
use Illuminate\Support\Facades\Log;
|
||||||
|
|
||||||
|
use App\Classes\External\Accounting\Quickbooks;
|
||||||
|
use App\Models\Account;
|
||||||
|
use App\Models\External\Integrations;
|
||||||
|
use QuickBooksOnline\API\Data\IPPEmailAddress;
|
||||||
|
use QuickBooksOnline\API\Data\IPPPhysicalAddress;
|
||||||
|
|
||||||
|
class QuickAccounts extends Command
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* The name and signature of the console command.
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
protected $signature = 'external:sync:accounts {--m|match : Match Display Name}';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The console command description.
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
protected $description = 'Sync Account numbers with External Sources';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new command instance.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
parent::__construct();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Execute the console command.
|
||||||
|
*
|
||||||
|
* @return mixed
|
||||||
|
* @throws \Exception
|
||||||
|
*/
|
||||||
|
public function handle()
|
||||||
|
{
|
||||||
|
DB::listen(function($query) {
|
||||||
|
Log::debug('- SQL',['sql'=>$query->sql,'binding'=>$query->bindings]);
|
||||||
|
});
|
||||||
|
|
||||||
|
foreach (Integrations::active()->type('ACCOUNTING')->get() as $into)
|
||||||
|
{
|
||||||
|
switch ($into->name)
|
||||||
|
{
|
||||||
|
case 'quickbooks':
|
||||||
|
$api = new Quickbooks($into->user);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
throw new \Exception('No handler for: ',$into-name);
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ($api->getCustomers(TRUE) as $r)
|
||||||
|
{
|
||||||
|
$this->info(sprintf('Checking [%s] (%s)',$r->Id,$r->DisplayName));
|
||||||
|
|
||||||
|
if ($r->Notes == 'Cash Only')
|
||||||
|
{
|
||||||
|
$this->warn(sprintf('Skipping [%s] (%s)',$r->Id,$r->DisplayName));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (! $this->option('match') AND (! $r->CompanyName AND (! $r->FamilyName AND ! $r->GivenName)))
|
||||||
|
{
|
||||||
|
$this->error(sprintf('No COMPANY or PERSONAL details for [%s] (%s)',$r->Id,$r->DisplayName));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($this->option('match')) {
|
||||||
|
$ao = Account::where('company',$r->DisplayName);
|
||||||
|
|
||||||
|
if (! $ao->count()) {
|
||||||
|
$uo = User::where('lastname',$r->FamilyName);
|
||||||
|
|
||||||
|
if ($r->GivenName)
|
||||||
|
$uo->where('firstname',$r->GivenName);
|
||||||
|
|
||||||
|
if ($uo->count() > 1 OR (! $uo->count()))
|
||||||
|
{
|
||||||
|
$this->error(sprintf('No SINGLE Users matched for [%s] (%s)',$r->Id,$r->DisplayName));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
$uo = $uo->first();
|
||||||
|
$ao = $uo->accounts->where('active',TRUE);
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
if ($r->CompanyName) {
|
||||||
|
$ao = Account::where('company',$this->option('match') ? $r->DisplayName : $r->CompanyName);
|
||||||
|
} else {
|
||||||
|
$uo = User::where('lastname',$r->FamilyName);
|
||||||
|
|
||||||
|
if ($r->GivenName)
|
||||||
|
$uo->where('firstname',$r->GivenName);
|
||||||
|
|
||||||
|
if ($uo->count() > 1 OR (! $uo->count()))
|
||||||
|
{
|
||||||
|
$this->error(sprintf('No SINGLE matched for [%s] (%s)',$r->Id,$r->DisplayName));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
$uo = $uo->first();
|
||||||
|
$ao = $uo->accounts->where('active',TRUE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (! $ao->count())
|
||||||
|
{
|
||||||
|
$this->error(sprintf('No Accounts matched for [%s] (%s)',$r->Id,$r->DisplayName));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($ao->count() > 1)
|
||||||
|
{
|
||||||
|
$this->error(sprintf('Too Many Accounts (%s) matched for [%s] (%s)',$ao->count(),$r->Id,$r->DisplayName));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
$ao = $ao->first();
|
||||||
|
|
||||||
|
// If we are matching on DisplayName, make sure the account is updated correct for Business or Personal Accounts
|
||||||
|
$oldr = clone $r;
|
||||||
|
|
||||||
|
// @NOTE: This overwrites the ABN if it exists.
|
||||||
|
if ($r->PrimaryTaxIdentifier)
|
||||||
|
{
|
||||||
|
$this->warn(sprintf('ABN Overwrite for (%s)',$r->DisplayName));
|
||||||
|
}
|
||||||
|
|
||||||
|
switch ($ao->type)
|
||||||
|
{
|
||||||
|
case 'Business':
|
||||||
|
$r->CompanyName = $ao->company;
|
||||||
|
$r->ResaleNum = $ao->AccountId;
|
||||||
|
$r->SalesTermRef = '7'; // @todo
|
||||||
|
|
||||||
|
if ($ao->first_name)
|
||||||
|
$r->GivenName = chop($ao->user->firstname); // @todo shouldnt be required
|
||||||
|
if ($ao->last_name)
|
||||||
|
$r->FamilyName = $ao->user->lastname;
|
||||||
|
|
||||||
|
if ($ao->address1)
|
||||||
|
{
|
||||||
|
if (! $r->BillAddr)
|
||||||
|
$r->BillAddr = new IPPPhysicalAddress;
|
||||||
|
|
||||||
|
$r->BillAddr->Line1 = $ao->user->address1;
|
||||||
|
$r->BillAddr->Line2 = $ao->user->address2;
|
||||||
|
$r->BillAddr->City = $ao->user->city;
|
||||||
|
$r->BillAddr->CountrySubDivisionCode = strtoupper($ao->user->state);
|
||||||
|
$r->BillAddr->PostalCode = $ao->user->postcode;
|
||||||
|
$r->BillAddr->Country = 'Australia'; // @todo
|
||||||
|
|
||||||
|
//$r->ShipAddr = $r->BillAddr;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($ao->email) {
|
||||||
|
if (! $r->PrimaryEmailAddr)
|
||||||
|
$r->PrimaryEmailAddr = new IPPEmailAddress;
|
||||||
|
|
||||||
|
$r->PrimaryEmailAddr->Address = $ao->user->email;
|
||||||
|
$r->PreferredDeliveryMethod = 'Email';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (! $r->Balance)
|
||||||
|
$r->Active = $ao->active ? 'true' : 'false';
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'Private':
|
||||||
|
$r->CompanyName = NULL;
|
||||||
|
$r->DisplayName = sprintf('%s %s',$ao->user->lastname,$ao->user->firstname);
|
||||||
|
$r->ResaleNum = $ao->AccountId;
|
||||||
|
$r->SalesTermRef = '7'; // @todo
|
||||||
|
|
||||||
|
if ($ao->first_name)
|
||||||
|
$r->GivenName = chop($ao->user->firstname); // @todo shouldnt be required
|
||||||
|
if ($ao->last_name)
|
||||||
|
$r->FamilyName = $ao->user->lastname;
|
||||||
|
|
||||||
|
if ($ao->address1)
|
||||||
|
{
|
||||||
|
if (! $r->BillAddr)
|
||||||
|
$r->BillAddr = new IPPPhysicalAddress;
|
||||||
|
|
||||||
|
$r->BillAddr->Line1 = $ao->user->address1;
|
||||||
|
$r->BillAddr->Line2 = $ao->user->address2;
|
||||||
|
$r->BillAddr->City = $ao->user->city;
|
||||||
|
$r->BillAddr->CountrySubDivisionCode = strtoupper($ao->user->state);
|
||||||
|
$r->BillAddr->PostalCode = $ao->user->postcode;
|
||||||
|
$r->BillAddr->Country = 'Australia'; // @todo
|
||||||
|
|
||||||
|
//$r->ShipAddr = $r->BillAddr;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($ao->email) {
|
||||||
|
if (! $r->PrimaryEmailAddr)
|
||||||
|
$r->PrimaryEmailAddr = new IPPEmailAddress;
|
||||||
|
|
||||||
|
$r->PrimaryEmailAddr->Address = $ao->user->email;
|
||||||
|
$r->PreferredDeliveryMethod = 'Email';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (! $r->Balance)
|
||||||
|
$r->Active = $ao->active ? 'true' : 'false';
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
throw new \Exception('Unhandled account type: '.$ao->type);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// If something changed, lets update it.
|
||||||
|
if (count(array_diff_assoc(object_to_array($r,FALSE),object_to_array($oldr,FALSE))))
|
||||||
|
{
|
||||||
|
$api->updateCustomer($r,[]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// If external integration doesnt exist, lets create it.
|
||||||
|
if (! $ao->ExternalAccounting($into))
|
||||||
|
{
|
||||||
|
$ao->external()->attach([$into->id=>['site_id'=>1,'link'=>$r->Id]]); // @todo site_id
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the integration ID doesnt exist in the integration source, add it.
|
||||||
|
if (! $r->ResaleNum)
|
||||||
|
{
|
||||||
|
$api->updateCustomer($r,['ResaleNum'=>$ao->AccountId]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// If integration exist, double check the numbers match
|
||||||
|
if ($r->ResaleNum != $ao->AccountId) {
|
||||||
|
$this->warn(sprintf('Integration ID Mismatch AID [%s] ID [%s]',$ao->id,$r->Id));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function object_to_array($object,$encode=TRUE)
|
||||||
|
{
|
||||||
|
// For child arrays, we just encode
|
||||||
|
if ($encode)
|
||||||
|
return json_encode($object);
|
||||||
|
|
||||||
|
if (is_object($object)) {
|
||||||
|
return array_map(__FUNCTION__,get_object_vars($object));
|
||||||
|
} else if (is_array($object)) {
|
||||||
|
return array_map(__FUNCTION__,$object);
|
||||||
|
} else {
|
||||||
|
return $object;
|
||||||
|
}
|
||||||
|
}
|
@ -36,6 +36,11 @@ class Account extends Model
|
|||||||
return $this->belongsTo(Country::class);
|
return $this->belongsTo(Country::class);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function external()
|
||||||
|
{
|
||||||
|
return $this->belongsToMany(External\Integrations::class,'external_account',NULL,'external_integration_id');
|
||||||
|
}
|
||||||
|
|
||||||
public function invoices()
|
public function invoices()
|
||||||
{
|
{
|
||||||
return $this->hasMany(Invoice::class);
|
return $this->hasMany(Invoice::class);
|
||||||
@ -91,6 +96,11 @@ class Account extends Model
|
|||||||
return sprintf('<a href="/r/switch/start/%s"><i class="fa fa-external-link"></i></a>',$this->user_id);
|
return sprintf('<a href="/r/switch/start/%s"><i class="fa fa-external-link"></i></a>',$this->user_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function getTypeAttribute()
|
||||||
|
{
|
||||||
|
return $this->company ? 'Business' : 'Private';
|
||||||
|
}
|
||||||
|
|
||||||
private function _address()
|
private function _address()
|
||||||
{
|
{
|
||||||
$return = [];
|
$return = [];
|
||||||
@ -131,4 +141,19 @@ class Account extends Model
|
|||||||
return $item->active AND $item->due > 0;
|
return $item->active AND $item->due > 0;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the external account ID for a specific integration
|
||||||
|
*
|
||||||
|
* @param External\Integrations $o
|
||||||
|
* @return mixed
|
||||||
|
*/
|
||||||
|
public function ExternalAccounting(External\Integrations $o)
|
||||||
|
{
|
||||||
|
return $this
|
||||||
|
->external()
|
||||||
|
->where('id','=',$o->id)
|
||||||
|
->where('site_id','=',$this->site_id)
|
||||||
|
->first();
|
||||||
|
}
|
||||||
}
|
}
|
27
app/Models/External/Integrations.php
vendored
Normal file
27
app/Models/External/Integrations.php
vendored
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Models\External;
|
||||||
|
|
||||||
|
use Illuminate\Database\Eloquent\Model;
|
||||||
|
|
||||||
|
use App\User;
|
||||||
|
|
||||||
|
class Integrations extends Model
|
||||||
|
{
|
||||||
|
public $table = 'external_integrations';
|
||||||
|
|
||||||
|
public function user()
|
||||||
|
{
|
||||||
|
return $this->belongsTo(User::class);
|
||||||
|
}
|
||||||
|
|
||||||
|
function scopeActive()
|
||||||
|
{
|
||||||
|
return $this->where('active',TRUE);
|
||||||
|
}
|
||||||
|
|
||||||
|
function scopeType($query,string $type)
|
||||||
|
{
|
||||||
|
return $query->where('type',$type);
|
||||||
|
}
|
||||||
|
}
|
@ -10,10 +10,11 @@ use Leenooks\Carbon;
|
|||||||
use Leenooks\Traits\UserSwitch;
|
use Leenooks\Traits\UserSwitch;
|
||||||
use App\Notifications\ResetPasswordNotification;
|
use App\Notifications\ResetPasswordNotification;
|
||||||
use App\Models\Service;
|
use App\Models\Service;
|
||||||
|
use Spinen\QuickBooks\HasQuickBooksToken;
|
||||||
|
|
||||||
class User extends Authenticatable
|
class User extends Authenticatable
|
||||||
{
|
{
|
||||||
use HasApiTokens,Notifiable,UserSwitch;
|
use HasApiTokens,Notifiable,UserSwitch,HasQuickBooksToken;
|
||||||
|
|
||||||
protected $dates = ['created_at','updated_at','last_access'];
|
protected $dates = ['created_at','updated_at','last_access'];
|
||||||
protected $with = ['accounts.services'];
|
protected $with = ['accounts.services'];
|
||||||
|
@ -28,6 +28,7 @@
|
|||||||
"spatie/laravel-demo-mode": "^2.2",
|
"spatie/laravel-demo-mode": "^2.2",
|
||||||
"spatie/laravel-failed-job-monitor": "^3.0",
|
"spatie/laravel-failed-job-monitor": "^3.0",
|
||||||
"spatie/laravel-sitemap": "^5.2",
|
"spatie/laravel-sitemap": "^5.2",
|
||||||
|
"spinen/laravel-quickbooks-client": "^3.0",
|
||||||
"tymon/jwt-auth": "^0.5.12"
|
"tymon/jwt-auth": "^0.5.12"
|
||||||
},
|
},
|
||||||
"require-dev": {
|
"require-dev": {
|
||||||
|
63
composer.lock
generated
63
composer.lock
generated
@ -4,7 +4,7 @@
|
|||||||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
||||||
"This file is @generated automatically"
|
"This file is @generated automatically"
|
||||||
],
|
],
|
||||||
"content-hash": "811c846e37c98427b477d58a8e8ded48",
|
"content-hash": "8d997e88df489137705fe8a879e16642",
|
||||||
"packages": [
|
"packages": [
|
||||||
{
|
{
|
||||||
"name": "acacha/user",
|
"name": "acacha/user",
|
||||||
@ -4084,6 +4084,67 @@
|
|||||||
],
|
],
|
||||||
"time": "2018-04-12T09:34:43+00:00"
|
"time": "2018-04-12T09:34:43+00:00"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "spinen/laravel-quickbooks-client",
|
||||||
|
"version": "3.0.0",
|
||||||
|
"source": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/spinen/laravel-quickbooks-client.git",
|
||||||
|
"reference": "7360de3e07f1b397452c0b668787cfc0bb54b674"
|
||||||
|
},
|
||||||
|
"dist": {
|
||||||
|
"type": "zip",
|
||||||
|
"url": "https://api.github.com/repos/spinen/laravel-quickbooks-client/zipball/7360de3e07f1b397452c0b668787cfc0bb54b674",
|
||||||
|
"reference": "7360de3e07f1b397452c0b668787cfc0bb54b674",
|
||||||
|
"shasum": ""
|
||||||
|
},
|
||||||
|
"require": {
|
||||||
|
"illuminate/database": "5.5.*|5.6.*|5.7.*|5.8.*",
|
||||||
|
"illuminate/http": "5.5.*|5.6.*|5.7.*|5.8.*",
|
||||||
|
"illuminate/routing": "5.5.*|5.6.*|5.7.*|5.8.*",
|
||||||
|
"nesbot/carbon": "^1.26.3 || ^2.0",
|
||||||
|
"php": ">=7.2",
|
||||||
|
"quickbooks/v3-php-sdk": "^5.0.3"
|
||||||
|
},
|
||||||
|
"require-dev": {
|
||||||
|
"mockery/mockery": "^1",
|
||||||
|
"phpunit/phpunit": "~7.0.1|~8.0",
|
||||||
|
"psy/psysh": "^0.5.1",
|
||||||
|
"symfony/thanks": "^1.0"
|
||||||
|
},
|
||||||
|
"type": "library",
|
||||||
|
"extra": {
|
||||||
|
"laravel": {
|
||||||
|
"providers": [
|
||||||
|
"Spinen\\QuickBooks\\Providers\\ServiceProvider",
|
||||||
|
"Spinen\\QuickBooks\\Providers\\ClientServiceProvider"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"autoload": {
|
||||||
|
"psr-4": {
|
||||||
|
"Spinen\\QuickBooks\\": "src/"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"notification-url": "https://packagist.org/downloads/",
|
||||||
|
"license": [
|
||||||
|
"MIT"
|
||||||
|
],
|
||||||
|
"authors": [
|
||||||
|
{
|
||||||
|
"name": "Jimmy Puckett",
|
||||||
|
"email": "jimmy.puckett@spinen.com"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"description": "SPINEN's Laravel Client for QuickBooks.",
|
||||||
|
"keywords": [
|
||||||
|
"client",
|
||||||
|
"laravel",
|
||||||
|
"quickbooks",
|
||||||
|
"spinen"
|
||||||
|
],
|
||||||
|
"time": "2019-02-27T02:38:48+00:00"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "swiftmailer/swiftmailer",
|
"name": "swiftmailer/swiftmailer",
|
||||||
"version": "v6.2.1",
|
"version": "v6.2.1",
|
||||||
|
96
config/quickbooks.php
Normal file
96
config/quickbooks.php
Normal file
@ -0,0 +1,96 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
use App\User;
|
||||||
|
|
||||||
|
return [
|
||||||
|
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| Properties for the QuickBooks SDK DataService
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
| The configuration keys for the SDK are inconsistent in naming convention.
|
||||||
|
| We are adhering to snake_case. We make a sensible guess for 'base_url'
|
||||||
|
| using the app's env, but you can can it with 'QUICKBOOKS_API_URL'. Also,
|
||||||
|
| the 'redirect_uri' is made in the client from the 'quickbooks.token'
|
||||||
|
| named route, so it cannot be configured here.
|
||||||
|
|
|
||||||
|
| Most of the time, only 'QUICKBOOKS_CLIENT_ID' & 'QUICKBOOKS_CLIENT_SECRET'
|
||||||
|
| needs to be set.
|
||||||
|
|
|
||||||
|
| See: https://intuit.github.io/QuickBooks-V3-PHP-SDK/configuration.html
|
||||||
|
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
'data_service' => [
|
||||||
|
'auth_mode' => 'oauth2',
|
||||||
|
'base_url' => env('QUICKBOOKS_API_URL', config('app.env') === 'production' ? 'Production' : 'Development'),
|
||||||
|
'client_id' => env('QUICKBOOKS_CLIENT_ID'),
|
||||||
|
'client_secret' => env('QUICKBOOKS_CLIENT_SECRET'),
|
||||||
|
'scope' => 'com.intuit.quickbooks.accounting',
|
||||||
|
],
|
||||||
|
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| Properties to control logging
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
| Configures logging to <storage_path>/logs/quickbooks.log when in debug
|
||||||
|
| mode or when 'QUICKBOOKS_DEBUG' is true.
|
||||||
|
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
'logging' => [
|
||||||
|
'enabled' => env('QUICKBOOKS_DEBUG', config('app.debug')),
|
||||||
|
|
||||||
|
'location' => storage_path('logs'),
|
||||||
|
],
|
||||||
|
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| Properties to configure the routes
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
| There are several routes that are needed for the package, so these
|
||||||
|
| properties allow configuring them to fit the application as needed.
|
||||||
|
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
'route' => [
|
||||||
|
// Controls the middlewares for thr routes. Can be a string or array of strings
|
||||||
|
'middleware' => [
|
||||||
|
// Added to the protected routes for the package (i.e. connect & disconnect)
|
||||||
|
'authenticated' => 'auth',
|
||||||
|
// Added to all of the routes for the package
|
||||||
|
'default' => 'web',
|
||||||
|
],
|
||||||
|
'paths' => [
|
||||||
|
// Show forms to connect/disconnect
|
||||||
|
'connect' => 'connect',
|
||||||
|
// The DELETE takes place to remove token
|
||||||
|
'disconnect' => 'disconnect',
|
||||||
|
// Return URI that QuickBooks sends code to allow getting OAuth token
|
||||||
|
'token' => 'token',
|
||||||
|
],
|
||||||
|
'prefix' => 'quickbooks',
|
||||||
|
],
|
||||||
|
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| Properties for control the "user" relationship in Token
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
| The Token class has a "user" relationship, and these properties allow
|
||||||
|
| configuring the relationship.
|
||||||
|
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
'user' => [
|
||||||
|
'keys' => [
|
||||||
|
'foreign' => 'user_id',
|
||||||
|
'owner' => 'id',
|
||||||
|
],
|
||||||
|
'model' => User::class,
|
||||||
|
],
|
||||||
|
|
||||||
|
];
|
@ -0,0 +1,43 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
use Illuminate\Database\Migrations\Migration;
|
||||||
|
use Illuminate\Database\Schema\Blueprint;
|
||||||
|
use Illuminate\Support\Facades\Schema;
|
||||||
|
|
||||||
|
class CreateQuickBooksTokensTable extends Migration
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Run the migrations.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function up()
|
||||||
|
{
|
||||||
|
Schema::create('quickbooks_tokens', function (Blueprint $table) {
|
||||||
|
$table->increments('id');
|
||||||
|
$table->unsignedInteger('user_id');
|
||||||
|
$table->unsignedBigInteger('realm_id');
|
||||||
|
$table->longtext('access_token');
|
||||||
|
$table->datetime('access_token_expires_at');
|
||||||
|
$table->string('refresh_token');
|
||||||
|
$table->datetime('refresh_token_expires_at');
|
||||||
|
|
||||||
|
$table->timestamps();
|
||||||
|
|
||||||
|
$table->foreign('user_id')
|
||||||
|
->references('id')
|
||||||
|
->on('users')
|
||||||
|
->onDelete('cascade');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reverse the migrations.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function down()
|
||||||
|
{
|
||||||
|
Schema::dropIfExists('quickbooks_token');
|
||||||
|
}
|
||||||
|
}
|
37
database/migrations/2019_06_11_160940_add_external.php
Normal file
37
database/migrations/2019_06_11_160940_add_external.php
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
use Illuminate\Support\Facades\Schema;
|
||||||
|
use Illuminate\Database\Schema\Blueprint;
|
||||||
|
use Illuminate\Database\Migrations\Migration;
|
||||||
|
|
||||||
|
class AddExternal extends Migration
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Run the migrations.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function up()
|
||||||
|
{
|
||||||
|
Schema::create('external_integrations', function (Blueprint $table) {
|
||||||
|
$table->increments('id');
|
||||||
|
$table->string('name');
|
||||||
|
$table->longText('description');
|
||||||
|
$table->string('type');
|
||||||
|
$table->boolean('active');
|
||||||
|
|
||||||
|
$table->integer('user_id')->unsigned();
|
||||||
|
$table->foreign('user_id')->references('id')->on('users');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reverse the migrations.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function down()
|
||||||
|
{
|
||||||
|
Schema::dropIfExists('external_integrations');
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,39 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
use Illuminate\Support\Facades\Schema;
|
||||||
|
use Illuminate\Database\Schema\Blueprint;
|
||||||
|
use Illuminate\Database\Migrations\Migration;
|
||||||
|
|
||||||
|
class AddExternalAccount extends Migration
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Run the migrations.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function up()
|
||||||
|
{
|
||||||
|
Schema::create('external_account', function (Blueprint $table) {
|
||||||
|
$table->bigInteger('account_id');
|
||||||
|
$table->integer('site_id')->nullable();
|
||||||
|
$table->integer('external_integration_id')->unsigned();
|
||||||
|
$table->string('link');
|
||||||
|
|
||||||
|
$table->foreign('site_id')->references('id')->on('ab_setup');
|
||||||
|
$table->foreign('external_integration_id')->references('id')->on('external_integrations');
|
||||||
|
$table->foreign('account_id')->references('id')->on('ab_account');
|
||||||
|
|
||||||
|
$table->unique(['site_id','account_id','external_integration_id'],'sae');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reverse the migrations.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function down()
|
||||||
|
{
|
||||||
|
Schema::dropIfExists('external_account');
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user