Add supplier linking

This commit is contained in:
Deon George
2022-08-07 12:17:20 +10:00
parent a1fd36aa6f
commit 2722c92bcf
10 changed files with 339 additions and 11 deletions

View File

@@ -0,0 +1,67 @@
<?php
namespace App\Console\Commands;
use Carbon\Carbon;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\Config;
use App\Models\{Site,Supplier,User};
class SupplierAccountSync extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'supplier:account:sync'
.' {siteid : Site ID}'
.' {supplier : Supplier Name}'
.' {--f|forceprod : Force Prod API on dev environment}';
/**
* The console command description.
*
* @var string
*/
protected $description = 'Sync accounts with a supplier';
/**
* Execute the console command.
*
* @return int
*/
public function handle()
{
Config::set('site',Site::findOrFail($this->argument('siteid')));
$so = Supplier::where('name',$this->argument('supplier'))->singleOrFail();
foreach ($so->API($this->option('forceprod'))->getCustomers(['fetchall'=>true]) as $customer) {
// Check if we have this customer already (by ID)
if ($so->users->where('pivot.id',$customer->id)->count()) {
$this->info(sprintf('User already linked (%s:%s)',$customer->id,$customer->email));
} elseif ($x=User::where('email',$customer->email)->single()) {
//dump($x->suppliers->first());
if ($x->suppliers->count()) {
$this->alert(sprintf('User [%d:%s] already linked to this supplier with ID (%s)',$customer->id,$customer->email,$x->suppliers->first()->pivot->id));
} else {
$this->warn(sprintf('User [%d:%s] has same email (%s:%s) - Linked',$x->id,$x->email,$customer->id,$customer->email));
$so->users()->syncWithoutDetaching([
$x->id => [
'id'=>$customer->id,
'site_id'=>$x->site_id, // @todo See if we can have this handled automatically
'created_at'=>Carbon::create($customer->date_added),
]
]);
}
} else {
$this->error(sprintf('User doesnt exist with email (%s)',$customer->email));
}
}
}
}

View File

@@ -7,7 +7,7 @@ use Illuminate\Support\Collection;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Gate;
use App\Models\{Account,Invoice,Payment,Service,Service\Broadband,Service\Phone,User};
use App\Models\{Account,Invoice,Payment,Service,Supplier,User};
class SearchController extends Controller
{
@@ -39,9 +39,20 @@ class SearchController extends Controller
->orderBy('firstname')
->limit(10)->get() as $o)
{
$result->push(['name'=>sprintf('%s (%s)',$o->name,$o->lid),'value'=>'/u/home/'.$o->id,'category'=>'Users']);
$result->push(['name'=>sprintf('%s (%s) - %s',$o->name,$o->lid,$o->email),'value'=>'/u/home/'.$o->id,'category'=>'Users']);
}
# Look for User by Supplier
if (is_numeric($request->input('term')))
foreach (Supplier::Search($request->input('term'))
->whereIN('user_id',$user_ids)
->orderBy('name')
->limit(10)->get() as $o)
{
$oo = $o->users->filter(function($item) use ($request) { return str_contains($item->pivot->id,$request->input('term')); })->pop();
$result->push(['name'=>sprintf('%s (%s:%s)',$oo->name,$o->name,$oo->pivot->id),'value'=>'/u/home/'.$oo->id,'category'=>'Suppliers']);
}
# Look for Account
foreach (Account::Search($request->input('term'))
->whereIN('user_id',$user_ids)

View File

@@ -0,0 +1,55 @@
<?php
namespace App\Http\Controllers;
use Carbon\Carbon;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Session;
use App\Models\{Supplier,User};
class UserController extends Controller
{
/**
* Add a supplier to a user's profile
*
* @param Request $request
* @param User $o
* @return \Illuminate\Http\RedirectResponse
*/
public function supplier_addedit(Request $request,User $o)
{
Session::put('supplier_update',true);
$validated = $request->validate([
'id'=>'required|string',
'supplier_id'=>'required|exists:suppliers,id',
]);
$o->suppliers()->attach([
$validated['supplier_id'] => [
'id'=>$validated['id'],
'site_id'=>$o->site_id,
'created_at'=>Carbon::now(),
]
]);
return redirect()->back()->with('success','Supplier Added');
}
/**
* Remove a supplier from a user's profile
*
* @param User $o
* @param Supplier $so
* @return \Illuminate\Http\RedirectResponse
*/
public function supplier_delete(User $o,Supplier $so)
{
Session::put('supplier_update',true);
$o->suppliers()->detach([$so->id]);
return redirect()->back()->with('success','Supplier Deleted');
}
}

View File

@@ -8,6 +8,7 @@ use Illuminate\Support\Arr;
use Illuminate\Support\Collection;
use Leenooks\Traits\ScopeActive;
use App\Models\Scopes\SiteScope;
use App\Models\Supplier\{Broadband,Domain,Email,Ethernet,Generic,Host,HSPA,Phone,SSL,Type};
class Supplier extends Model
@@ -98,17 +99,72 @@ class Supplier extends Model
/* RELATIONS */
// @todo Need to put in an integrity constraint to support the hasOne()
// @todo Some suppliers have multiple different configuration urls/passwords and contacts for different types of services, perhaps this should be hasMany()?
// EG: Crazy Domains, "domains" and "hosting".
/**
* Supplier Detail Configuration
*
* @return \Illuminate\Database\Eloquent\Relations\HasOne
*/
public function detail()
{
return $this->hasOne(SupplierDetail::class)
->withoutGlobalScope(\App\Models\Scopes\SiteScope::class);
->withoutGlobalScope(SiteScope::class);
}
public function users()
{
return $this->belongsToMany(User::class)
->withPivot('id','created_at');
}
/**
* Search for a record
*
* @param $query
* @param string $term
*/
public function scopeSearch($query,string $term)
{
if (is_numeric($term)) {
$query->select('suppliers.*')
->join('supplier_user',['supplier_user.supplier_id'=>'suppliers.id'])
->orWhere('supplier_user.id','like','%'.$term.'%');
}
return $query;
}
/* METHODS */
public function api_class(): ?string
{
return config('services.supplier.'.strtolower($this->name).'.api');
}
private function api_key(): string
{
return Arr::get($this->detail->connections,'api_key');
}
private function api_secret(): string
{
return Arr::get($this->detail->connections,'api_secret');
}
public function API(bool $forceprod=FALSE): mixed
{
return $this->hasAPIdetails() ? new ($this->api_class())($this->api_key(),$this->api_secret(),$forceprod) : NULL;
}
/**
* Do we have API details for this supplier
*
* @return bool
*/
public function hasAPIdetails(): bool
{
return $this->api_class() && (collect(['api_key','api_secret'])->diff($this->detail->connections->keys())->count() === 0);
}
/**
* Return the traffic records, that were not matched to a service.
*

View File

@@ -161,6 +161,13 @@ class User extends Authenticatable implements IDs
->active();
}
public function suppliers()
{
return $this->belongsToMany(Supplier::class)
->where('supplier_user.site_id',$this->site_id)
->withPivot('id','created_at');
}
/* ATTRIBUTES */
/**
@@ -231,7 +238,7 @@ class User extends Authenticatable implements IDs
});
} elseif (is_numeric($term)) {
$query->where('id','like','%'.$term.'%');
$query->where('users.id','like','%'.$term.'%');
} elseif (preg_match('/\@/',$term)) {
$query->where('email','like','%'.$term.'%');