<?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}; /** * Synchronise customers with our accounts. * * This will: * + Create the account in the accounting system * + Update the account in the accounting system with our data (we are master) */ class AccountingAccountSync implements ShouldQueue { use Dispatchable, InteractsWithQueue, Queueable, SerializesModels; private const LOGKEY = 'JAS'; private ProviderToken $to; /** * Create a new job instance. * * @param ProviderToken $to */ public function __construct(ProviderToken $to) { $this->to = $to; } /** * Execute the job. * * @return void * @throws \Exception */ public function handle() { $api = $this->to->API(); $ref = Account::select('id','site_id','company','user_id')->with(['user'])->get(); foreach ($api->getCustomers() as $acc) { $o = NULL; // See if we are already linked if (($x=$this->to->provider->accounts->where('pivot.ref',$acc->id))->count() === 1) { $o = $x->pop(); // If not, see if our reference matches } elseif (($x=$ref->filter(function($item) use ($acc) { return $item->sid == $acc->ref; }))->count() === 1) { $o = $x->pop(); // Look based on Name } elseif (($x=$ref->filter(function($item) use ($acc) { return $item->company == $acc->companyname || $item->name == $acc->fullname || $item->user->email == $acc->email; }))->count() === 1) { $o = $x->pop(); } else { // Log not found Log::alert(sprintf('%s:Customer not found [%s:%s]',self::LOGKEY,$acc->id,$acc->DisplayName)); continue; } $o->providers()->syncWithoutDetaching([ $this->to->provider->id => [ 'ref' => $acc->id, 'synctoken' => $acc->synctoken, 'created_at'=>Carbon::create($acc->created_at), 'updated_at'=>Carbon::create($acc->updated_at), 'site_id'=>$this->to->site_id, ], ]); Log::alert(sprintf('%s:Customer updated [%s:%s]',self::LOGKEY,$o->id,$acc->id)); // Check if QB is out of Sync and update it. $acc->syncOriginal(); $acc->PrimaryEmailAddr = (object)['Address'=>$o->user->email]; $acc->ResaleNum = $o->sid; $acc->GivenName = $o->user->firstname; $acc->FamilyName = $o->user->lastname; $acc->CompanyName = $o->name; $acc->DisplayName = $o->name; $acc->FullyQualifiedName = $o->name; //$acc->Active = (bool)$o->active; // @todo implement in-activity, but only if all invoices are paid and services cancelled if ($acc->getDirty()) { Log::info(sprintf('%s:Customer [%s] (%s:%s) has changed',self::LOGKEY,$o->sid,$acc->id,$acc->DisplayName),['dirty'=>$acc->getDirty()]); $acc->sparse = 'true'; AccountingCustomerUpdate::dispatch($this->to,$acc); } // @todo Identify accounts in our DB that are not in accounting } } }