Customer account sync with Intuit
This commit is contained in:
parent
c1a64e2094
commit
4b85e01e93
7
app/Classes/External/Accounting.php
vendored
7
app/Classes/External/Accounting.php
vendored
@ -1,7 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
namespace App\Classes\External;
|
|
||||||
|
|
||||||
abstract class Accounting
|
|
||||||
{
|
|
||||||
}
|
|
68
app/Classes/External/Accounting/Quickbooks.php
vendored
68
app/Classes/External/Accounting/Quickbooks.php
vendored
@ -1,68 +0,0 @@
|
|||||||
<?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 App\Classes\External\Accounting as Base;
|
|
||||||
use App\Models\User;
|
|
||||||
|
|
||||||
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 getInvoice(int $id,$refresh=FALSE)
|
|
||||||
{
|
|
||||||
if ($refresh)
|
|
||||||
Cache::forget(__METHOD__.$id);
|
|
||||||
|
|
||||||
return Cache::remember(__METHOD__.$id,86400,function() use ($id) {
|
|
||||||
return $this->api->getDataService()->Query(sprintf("SELECT * FROM Invoice where id = '%s'",$id));
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getInvoices($refresh=FALSE): Collection
|
|
||||||
{
|
|
||||||
if ($refresh)
|
|
||||||
Cache::forget(__METHOD__);
|
|
||||||
|
|
||||||
return Cache::remember(__METHOD__,86400,function() {
|
|
||||||
return collect($this->api->getDataService()->Query('SELECT * FROM Invoice'));
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
public function updateCustomer(IPPCustomer $r,array $args)
|
|
||||||
{
|
|
||||||
$r->sparse = TRUE;
|
|
||||||
|
|
||||||
foreach ($args as $k=>$v)
|
|
||||||
{
|
|
||||||
$r->{$k} = $v;
|
|
||||||
}
|
|
||||||
|
|
||||||
return $this->api->getDataService()->Update($r);
|
|
||||||
}
|
|
||||||
}
|
|
48
app/Console/Commands/AccountingAccountSync.php
Normal file
48
app/Console/Commands/AccountingAccountSync.php
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Console\Commands;
|
||||||
|
|
||||||
|
use Illuminate\Console\Command;
|
||||||
|
use Illuminate\Support\Facades\Config;
|
||||||
|
|
||||||
|
use App\Models\{ProviderOauth,Site,User};
|
||||||
|
use App\Jobs\AccountingAccountSync as Job;
|
||||||
|
|
||||||
|
class AccountingAccountSync extends Command
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* The name and signature of the console command.
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
protected $signature = 'accounting:account:sync'
|
||||||
|
.' {siteid : Site ID}'
|
||||||
|
.' {provider : Provider Name}'
|
||||||
|
.' {user : User Email}';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The console command description.
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
protected $description = 'Command description';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Execute the console command.
|
||||||
|
*
|
||||||
|
* @return int
|
||||||
|
*/
|
||||||
|
public function handle()
|
||||||
|
{
|
||||||
|
$site = Site::findOrFail($this->argument('siteid'));
|
||||||
|
Config::set('site',$site);
|
||||||
|
|
||||||
|
$so = ProviderOauth::where('name',$this->argument('provider'))->singleOrFail();
|
||||||
|
$uo = User::where('email',$this->argument('user'))->singleOrFail();
|
||||||
|
|
||||||
|
if (($x=$so->tokens->where('user_id',$uo->id))->count() !== 1)
|
||||||
|
abort(500,sprintf('Unknown Tokens for [%s]',$uo->email));
|
||||||
|
|
||||||
|
Job::dispatchSync($x->pop());
|
||||||
|
}
|
||||||
|
}
|
@ -1,261 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
namespace App\Console\Commands;
|
|
||||||
|
|
||||||
use Illuminate\Console\Command;
|
|
||||||
use QuickBooksOnline\API\Data\IPPEmailAddress;
|
|
||||||
use QuickBooksOnline\API\Data\IPPPhysicalAddress;
|
|
||||||
|
|
||||||
use App\Classes\External\Accounting\Quickbooks;
|
|
||||||
use App\Models\{Account,External\Integrations,User};
|
|
||||||
|
|
||||||
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()
|
|
||||||
{
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
95
app/Jobs/AccountingAccountSync.php
Normal file
95
app/Jobs/AccountingAccountSync.php
Normal file
@ -0,0 +1,95 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Jobs;
|
||||||
|
|
||||||
|
use Carbon\Carbon;
|
||||||
|
use Illuminate\Bus\Queueable;
|
||||||
|
use Illuminate\Contracts\Queue\ShouldBeUnique;
|
||||||
|
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||||
|
use Illuminate\Foundation\Bus\Dispatchable;
|
||||||
|
use Illuminate\Queue\InteractsWithQueue;
|
||||||
|
use Illuminate\Queue\SerializesModels;
|
||||||
|
use Illuminate\Support\Facades\Log;
|
||||||
|
use Intuit\Jobs\AccountingCustomerUpdate;
|
||||||
|
|
||||||
|
use App\Models\{Account,ProviderToken};
|
||||||
|
|
||||||
|
class AccountingAccountSync implements ShouldQueue
|
||||||
|
{
|
||||||
|
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
|
||||||
|
|
||||||
|
private const LOGKEY = 'JAS';
|
||||||
|
|
||||||
|
private ProviderToken $to;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new job instance.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function __construct(ProviderToken $to)
|
||||||
|
{
|
||||||
|
$this->to = $to;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Execute the job.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function handle()
|
||||||
|
{
|
||||||
|
$api = $this->to->provider->API($this->to);
|
||||||
|
$accounts = Account::get();
|
||||||
|
|
||||||
|
foreach ($api->getCustomers() as $customer) {
|
||||||
|
$ao = NULL;
|
||||||
|
|
||||||
|
// See if we are already linked
|
||||||
|
if (($x=$this->to->provider->accounts->where('pivot.ref',$customer->id))->count() === 1) {
|
||||||
|
$ao = $x->pop();
|
||||||
|
|
||||||
|
// If not, see if our reference matches
|
||||||
|
} elseif (($x=$accounts->filter(function($item) use ($customer) { return $item->sid == $customer->ref; }))->count() === 1) {
|
||||||
|
$ao = $x->pop();
|
||||||
|
|
||||||
|
// Look based on Name
|
||||||
|
} elseif (($x=$accounts->filter(function($item) use ($customer) { return $item->company == $customer->companyname || $item->name == $customer->fullname; }))->count() === 1) {
|
||||||
|
$ao = $x->pop();
|
||||||
|
|
||||||
|
} else {
|
||||||
|
// Log not found
|
||||||
|
Log::alert(sprintf('%s:Customer not found [%s:%s]',self::LOGKEY,$customer->id,$customer->DisplayName));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
$ao->providers()->syncWithoutDetaching([
|
||||||
|
$this->to->provider->id => [
|
||||||
|
'ref' => $customer->id,
|
||||||
|
'synctoken' => $customer->synctoken,
|
||||||
|
'created_at'=>Carbon::create($customer->created_at),
|
||||||
|
'updated_at'=>Carbon::create($customer->updated_at),
|
||||||
|
'site_id'=>$ao->site_id, // @todo See if we can have this handled automatically
|
||||||
|
],
|
||||||
|
]);
|
||||||
|
|
||||||
|
// Check if QB is out of Sync and update it.
|
||||||
|
$customer->syncOriginal();
|
||||||
|
$customer->PrimaryEmailAddr = (object)['Address'=>$ao->user->email];
|
||||||
|
$customer->ResaleNum = $ao->sid;
|
||||||
|
$customer->GivenName = $ao->user->firstname;
|
||||||
|
$customer->FamilyName = $ao->user->lastname;
|
||||||
|
$customer->CompanyName = $ao->name;
|
||||||
|
$customer->DisplayName = $ao->name;
|
||||||
|
$customer->FullyQualifiedName = $ao->name;
|
||||||
|
//$customer->Active = (bool)$ao->active;
|
||||||
|
|
||||||
|
if ($customer->getDirty()) {
|
||||||
|
Log::info(sprintf('%s:Customer [%s] (%s:%s) has changed',self::LOGKEY,$ao->sid,$customer->id,$customer->DisplayName),['dirty'=>$customer->getDirty()]);
|
||||||
|
$customer->sparse = 'true';
|
||||||
|
|
||||||
|
AccountingCustomerUpdate::dispatch($this->to,$customer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -7,6 +7,7 @@ use Illuminate\Database\Eloquent\Model;
|
|||||||
use Leenooks\Traits\ScopeActive;
|
use Leenooks\Traits\ScopeActive;
|
||||||
|
|
||||||
use App\Interfaces\IDs;
|
use App\Interfaces\IDs;
|
||||||
|
use App\Traits\SiteID;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class Account
|
* Class Account
|
||||||
@ -22,6 +23,7 @@ use App\Interfaces\IDs;
|
|||||||
*/
|
*/
|
||||||
class Account extends Model implements IDs
|
class Account extends Model implements IDs
|
||||||
{
|
{
|
||||||
|
use SiteID;
|
||||||
use HasFactory,ScopeActive;
|
use HasFactory,ScopeActive;
|
||||||
|
|
||||||
/* INTERFACES */
|
/* INTERFACES */
|
||||||
@ -43,6 +45,13 @@ class Account extends Model implements IDs
|
|||||||
return $this->hasMany(Charge::class);
|
return $this->hasMany(Charge::class);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function providers()
|
||||||
|
{
|
||||||
|
return $this->belongsToMany(ProviderOauth::class,'account_provider')
|
||||||
|
->where('account_provider.site_id',$this->site_id)
|
||||||
|
->withPivot('ref','synctoken','created_at','updated_at');
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return the country the user belongs to
|
* Return the country the user belongs to
|
||||||
*/
|
*/
|
||||||
|
@ -4,14 +4,25 @@ namespace App\Models;
|
|||||||
|
|
||||||
use Illuminate\Database\Eloquent\Model;
|
use Illuminate\Database\Eloquent\Model;
|
||||||
|
|
||||||
|
use App\Traits\SiteID;
|
||||||
|
|
||||||
class ProviderOauth extends Model
|
class ProviderOauth extends Model
|
||||||
{
|
{
|
||||||
|
use SiteID;
|
||||||
|
|
||||||
protected $table = 'provider_oauth';
|
protected $table = 'provider_oauth';
|
||||||
|
|
||||||
protected $fillable = ['name','active'];
|
protected $fillable = ['name','active'];
|
||||||
|
|
||||||
/* RELATIONS */
|
/* RELATIONS */
|
||||||
|
|
||||||
|
public function accounts()
|
||||||
|
{
|
||||||
|
return $this->belongsToMany(Account::class,'account_provider')
|
||||||
|
->where('account_provider.site_id',$this->site_id)
|
||||||
|
->withPivot('ref','synctoken','created_at','updated_at');
|
||||||
|
}
|
||||||
|
|
||||||
public function tokens()
|
public function tokens()
|
||||||
{
|
{
|
||||||
return $this->hasMany(ProviderToken::class);
|
return $this->hasMany(ProviderToken::class);
|
||||||
@ -21,4 +32,26 @@ class ProviderOauth extends Model
|
|||||||
{
|
{
|
||||||
return $this->hasMany(UserOauth::class);
|
return $this->hasMany(UserOauth::class);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* METHODS */
|
||||||
|
|
||||||
|
public function api_class(): ?string
|
||||||
|
{
|
||||||
|
return config('services.provider.'.strtolower($this->name).'.api');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function API(ProviderToken $o,bool $tryprod=FALSE): mixed
|
||||||
|
{
|
||||||
|
return ($this->api_class() && $o->access_token) ? new ($this->api_class())($o,$tryprod) : NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Do we have API details for this supplier
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function hasAPIdetails(): bool
|
||||||
|
{
|
||||||
|
return $this->api_class() && $this->access_token && (! $this->hasAccessTokenExpired());
|
||||||
|
}
|
||||||
}
|
}
|
@ -2,11 +2,11 @@
|
|||||||
|
|
||||||
namespace App\Models;
|
namespace App\Models;
|
||||||
|
|
||||||
use Illuminate\Database\Eloquent\Model;
|
use Intuit\Models\ProviderToken as ProviderTokenBase;
|
||||||
|
|
||||||
use App\Traits\SiteID;
|
use App\Traits\SiteID;
|
||||||
|
|
||||||
class ProviderToken extends Model
|
class ProviderToken extends ProviderTokenBase
|
||||||
{
|
{
|
||||||
use SiteID;
|
use SiteID;
|
||||||
|
|
||||||
|
28
composer.lock
generated
28
composer.lock
generated
@ -1960,16 +1960,16 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "laravel/framework",
|
"name": "laravel/framework",
|
||||||
"version": "v9.24.0",
|
"version": "v9.25.1",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/laravel/framework.git",
|
"url": "https://github.com/laravel/framework.git",
|
||||||
"reference": "053840f579cf01d353d81333802afced79b1c0af"
|
"reference": "e8af8c2212e3717757ea7f459a655a2e9e771109"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/laravel/framework/zipball/053840f579cf01d353d81333802afced79b1c0af",
|
"url": "https://api.github.com/repos/laravel/framework/zipball/e8af8c2212e3717757ea7f459a655a2e9e771109",
|
||||||
"reference": "053840f579cf01d353d81333802afced79b1c0af",
|
"reference": "e8af8c2212e3717757ea7f459a655a2e9e771109",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
@ -2136,7 +2136,7 @@
|
|||||||
"issues": "https://github.com/laravel/framework/issues",
|
"issues": "https://github.com/laravel/framework/issues",
|
||||||
"source": "https://github.com/laravel/framework"
|
"source": "https://github.com/laravel/framework"
|
||||||
},
|
},
|
||||||
"time": "2022-08-09T13:43:22+00:00"
|
"time": "2022-08-16T16:36:05+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "laravel/passport",
|
"name": "laravel/passport",
|
||||||
@ -2862,16 +2862,16 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "league/flysystem",
|
"name": "league/flysystem",
|
||||||
"version": "3.2.0",
|
"version": "3.2.1",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/thephpleague/flysystem.git",
|
"url": "https://github.com/thephpleague/flysystem.git",
|
||||||
"reference": "ed0ecc7f9b5c2f4a9872185846974a808a3b052a"
|
"reference": "81aea9e5217084c7850cd36e1587ee4aad721c6b"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/thephpleague/flysystem/zipball/ed0ecc7f9b5c2f4a9872185846974a808a3b052a",
|
"url": "https://api.github.com/repos/thephpleague/flysystem/zipball/81aea9e5217084c7850cd36e1587ee4aad721c6b",
|
||||||
"reference": "ed0ecc7f9b5c2f4a9872185846974a808a3b052a",
|
"reference": "81aea9e5217084c7850cd36e1587ee4aad721c6b",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
@ -2932,7 +2932,7 @@
|
|||||||
],
|
],
|
||||||
"support": {
|
"support": {
|
||||||
"issues": "https://github.com/thephpleague/flysystem/issues",
|
"issues": "https://github.com/thephpleague/flysystem/issues",
|
||||||
"source": "https://github.com/thephpleague/flysystem/tree/3.2.0"
|
"source": "https://github.com/thephpleague/flysystem/tree/3.2.1"
|
||||||
},
|
},
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
@ -2948,7 +2948,7 @@
|
|||||||
"type": "tidelift"
|
"type": "tidelift"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"time": "2022-07-26T07:26:36+00:00"
|
"time": "2022-08-14T20:48:34+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "league/mime-type-detection",
|
"name": "league/mime-type-detection",
|
||||||
@ -3373,11 +3373,11 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "leenooks/intuit",
|
"name": "leenooks/intuit",
|
||||||
"version": "0.1.0",
|
"version": "0.1.1",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://dev.leenooks.net/leenooks/intuit",
|
"url": "https://dev.leenooks.net/leenooks/intuit",
|
||||||
"reference": "bbbdff040fa7d49e5acec38ce3a7c5a35af58a30"
|
"reference": "1567806b87b27b588545a3a630cffc575ef07141"
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
"jenssegers/model": "^1.5"
|
"jenssegers/model": "^1.5"
|
||||||
@ -3407,7 +3407,7 @@
|
|||||||
"laravel",
|
"laravel",
|
||||||
"leenooks"
|
"leenooks"
|
||||||
],
|
],
|
||||||
"time": "2022-08-12T04:41:22+00:00"
|
"time": "2022-08-18T13:18:14+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "leenooks/laravel",
|
"name": "leenooks/laravel",
|
||||||
|
@ -43,10 +43,16 @@ return [
|
|||||||
'redirect' => '/auth/google/callback',
|
'redirect' => '/auth/google/callback',
|
||||||
],
|
],
|
||||||
|
|
||||||
|
'provider' => [
|
||||||
|
'intuit' => [
|
||||||
|
'api'=> \Intuit\API::class,
|
||||||
|
]
|
||||||
|
],
|
||||||
|
|
||||||
'supplier' => [
|
'supplier' => [
|
||||||
'crazydomain' => [
|
'crazydomain' => [
|
||||||
'api'=> \Dreamscape\API::class,
|
'api'=> \Dreamscape\API::class,
|
||||||
'registrar' => 'crazydomain', // Key in the domain_registrars table
|
'registrar' => 'crazydomain', // Key in the domain_registrars table
|
||||||
]
|
],
|
||||||
],
|
],
|
||||||
];
|
];
|
||||||
|
38
database/migrations/2022_08_15_171005_qb_account_sync.php
Normal file
38
database/migrations/2022_08_15_171005_qb_account_sync.php
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
use Illuminate\Database\Migrations\Migration;
|
||||||
|
use Illuminate\Database\Schema\Blueprint;
|
||||||
|
use Illuminate\Support\Facades\Schema;
|
||||||
|
|
||||||
|
return new class extends Migration
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Run the migrations.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function up()
|
||||||
|
{
|
||||||
|
Schema::create('account_provider', function (Blueprint $table) {
|
||||||
|
$table->timestamps();
|
||||||
|
$table->integer('account_id')->unsigned();
|
||||||
|
$table->integer('provider_oauth_id')->unsigned();
|
||||||
|
$table->integer('site_id')->unsigned();
|
||||||
|
$table->string('ref');
|
||||||
|
$table->integer('synctoken');
|
||||||
|
|
||||||
|
$table->foreign(['account_id','site_id'])->references(['id','site_id'])->on('accounts');
|
||||||
|
$table->foreign(['provider_oauth_id','site_id'])->references(['id','site_id'])->on('provider_oauth');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reverse the migrations.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function down()
|
||||||
|
{
|
||||||
|
Schema::dropIfExists('account_provider');
|
||||||
|
}
|
||||||
|
};
|
Loading…
Reference in New Issue
Block a user