Compare commits
No commits in common. "1a20b7a3f11a97111aa3f3c76f5682156d73c39d" and "4c273364c730ed1f5b010995010a5e566289bfb9" have entirely different histories.
1a20b7a3f1
...
4c273364c7
@ -3,16 +3,14 @@
|
|||||||
namespace App\Console\Commands\Intuit;
|
namespace App\Console\Commands\Intuit;
|
||||||
|
|
||||||
use Illuminate\Console\Command;
|
use Illuminate\Console\Command;
|
||||||
use Intuit\Exceptions\NotTokenException;
|
|
||||||
use Intuit\Jobs\AccountingCustomerUpdate;
|
use Intuit\Jobs\AccountingCustomerUpdate;
|
||||||
use Intuit\Models\Customer as AccAccount;
|
use Intuit\Models\Customer as AccAccount;
|
||||||
use Intuit\Traits\ProviderTokenTrait;
|
|
||||||
|
|
||||||
use App\Models\Account;
|
use App\Models\{Account,ProviderOauth,User};
|
||||||
|
|
||||||
class AccountAdd extends Command
|
class AccountAdd extends Command
|
||||||
{
|
{
|
||||||
use ProviderTokenTrait;
|
private const provider = 'intuit';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The name and signature of the console command.
|
* The name and signature of the console command.
|
||||||
@ -34,10 +32,15 @@ class AccountAdd extends Command
|
|||||||
* Execute the console command.
|
* Execute the console command.
|
||||||
*
|
*
|
||||||
* @return int
|
* @return int
|
||||||
* @throws NotTokenException
|
|
||||||
*/
|
*/
|
||||||
public function handle()
|
public function handle()
|
||||||
{
|
{
|
||||||
|
$uo = User::where('email',$this->argument('user') ?: config('osb.admin'))->singleOrFail();
|
||||||
|
|
||||||
|
$so = ProviderOauth::where('name',self::provider)->singleOrFail();
|
||||||
|
if (! ($to=$so->token($uo)))
|
||||||
|
abort(500,sprintf('Unknown Tokens for [%s]',$uo->email));
|
||||||
|
|
||||||
$o = Account::findOrFail($this->argument('id'));
|
$o = Account::findOrFail($this->argument('id'));
|
||||||
|
|
||||||
$acc = new AccAccount;
|
$acc = new AccAccount;
|
||||||
@ -50,9 +53,6 @@ class AccountAdd extends Command
|
|||||||
$acc->FullyQualifiedName = $o->name;
|
$acc->FullyQualifiedName = $o->name;
|
||||||
$acc->Active = (bool)$o->active;
|
$acc->Active = (bool)$o->active;
|
||||||
|
|
||||||
return AccountingCustomerUpdate::dispatchSync(
|
return AccountingCustomerUpdate::dispatchSync($to,$acc);
|
||||||
$this->providerToken($this->argument('user')),
|
|
||||||
$acc
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
56
app/Console/Commands/Intuit/AccountGet.php
Normal file
56
app/Console/Commands/Intuit/AccountGet.php
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Console\Commands\Intuit;
|
||||||
|
|
||||||
|
use GuzzleHttp\Exception\ConnectException;
|
||||||
|
use Illuminate\Console\Command;
|
||||||
|
use Intuit\Exceptions\ConnectionIssueException;
|
||||||
|
|
||||||
|
use App\Models\{ProviderOauth,User};
|
||||||
|
|
||||||
|
class AccountGet extends Command
|
||||||
|
{
|
||||||
|
private const provider = 'intuit';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The name and signature of the console command.
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
protected $signature = 'intuit:account:get'
|
||||||
|
.' {id : Account ID}'
|
||||||
|
.' {user? : User Email}';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The console command description.
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
protected $description = 'Get an account from quickbooks';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Execute the console command.
|
||||||
|
*
|
||||||
|
* @return int
|
||||||
|
*/
|
||||||
|
public function handle()
|
||||||
|
{
|
||||||
|
$uo = User::where('email',$this->argument('user') ?: config('osb.admin'))->singleOrFail();
|
||||||
|
|
||||||
|
$so = ProviderOauth::where('name',self::provider)->singleOrFail();
|
||||||
|
if (! ($to=$so->token($uo)))
|
||||||
|
abort(500,sprintf('Unknown Tokens for [%s]',$uo->email));
|
||||||
|
|
||||||
|
try {
|
||||||
|
$api = $to->API();
|
||||||
|
dump($api->getAccountQuery($this->argument('id')));
|
||||||
|
|
||||||
|
} catch (ConnectException|ConnectionIssueException $e) {
|
||||||
|
$this->error($e->getMessage());
|
||||||
|
|
||||||
|
return self::FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return self::SUCCESS;
|
||||||
|
}
|
||||||
|
}
|
@ -3,17 +3,16 @@
|
|||||||
namespace App\Console\Commands\Intuit;
|
namespace App\Console\Commands\Intuit;
|
||||||
|
|
||||||
use Illuminate\Console\Command;
|
use Illuminate\Console\Command;
|
||||||
use Intuit\Exceptions\NotTokenException;
|
|
||||||
use Intuit\Traits\ProviderTokenTrait;
|
|
||||||
|
|
||||||
use App\Jobs\AccountingAccountSync;
|
use App\Models\{ProviderOauth,User};
|
||||||
|
use App\Jobs\AccountingAccountSync as Job;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Synchronise Customers with Accounts
|
* Synchronise Customers with Accounts
|
||||||
*/
|
*/
|
||||||
class AccountSync extends Command
|
class AccountSync extends Command
|
||||||
{
|
{
|
||||||
use ProviderTokenTrait;
|
private const provider = 'intuit';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The name and signature of the console command.
|
* The name and signature of the console command.
|
||||||
@ -34,11 +33,16 @@ class AccountSync extends Command
|
|||||||
* Execute the console command.
|
* Execute the console command.
|
||||||
*
|
*
|
||||||
* @return int
|
* @return int
|
||||||
* @throws NotTokenException
|
|
||||||
*/
|
*/
|
||||||
public function handle()
|
public function handle()
|
||||||
{
|
{
|
||||||
AccountingAccountSync::dispatchSync($this->providerToken($this->argument('user')));
|
$uo = User::where('email',$this->argument('user') ?: config('osb.admin'))->singleOrFail();
|
||||||
|
|
||||||
|
$so = ProviderOauth::where('name',self::provider)->singleOrFail();
|
||||||
|
if (! ($to=$so->token($uo)))
|
||||||
|
abort(500,sprintf('Unknown Tokens for [%s]',$uo->email));
|
||||||
|
|
||||||
|
Job::dispatchSync($to);
|
||||||
|
|
||||||
return self::SUCCESS;
|
return self::SUCCESS;
|
||||||
}
|
}
|
||||||
|
@ -5,20 +5,19 @@ namespace App\Console\Commands\Intuit;
|
|||||||
use Illuminate\Console\Command;
|
use Illuminate\Console\Command;
|
||||||
use Intuit\Jobs\AccountingInvoiceUpdate;
|
use Intuit\Jobs\AccountingInvoiceUpdate;
|
||||||
use Intuit\Models\Invoice as AccInvoice;
|
use Intuit\Models\Invoice as AccInvoice;
|
||||||
use Intuit\Traits\ProviderTokenTrait;
|
|
||||||
|
|
||||||
use App\Models\Invoice;
|
use App\Models\{Invoice,ProviderOauth,User};
|
||||||
|
|
||||||
class InvoiceAdd extends Command
|
class InvoiceAdd extends Command
|
||||||
{
|
{
|
||||||
use ProviderTokenTrait;
|
private const provider = 'intuit';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The name and signature of the console command.
|
* The name and signature of the console command.
|
||||||
*
|
*
|
||||||
* @var string
|
* @var string
|
||||||
*/
|
*/
|
||||||
protected $signature = 'intuit:invoice:add'
|
protected $signature = 'accounting:invoice:add'
|
||||||
.' {id : Invoice ID}'
|
.' {id : Invoice ID}'
|
||||||
.' {user? : User Email}';
|
.' {user? : User Email}';
|
||||||
|
|
||||||
@ -37,46 +36,44 @@ class InvoiceAdd extends Command
|
|||||||
*/
|
*/
|
||||||
public function handle()
|
public function handle()
|
||||||
{
|
{
|
||||||
$to = $this->providerToken($this->argument('user'));
|
$uo = User::where('email',$this->argument('user') ?: config('osb.admin'))->singleOrFail();
|
||||||
|
|
||||||
$io = Invoice::findOrFail($this->argument('id'));
|
$so = ProviderOauth::where('name',self::provider)->singleOrFail();
|
||||||
|
if (! ($to=$so->token($uo)))
|
||||||
|
abort(500,sprintf('Unknown Tokens for [%s]',$uo->email));
|
||||||
|
|
||||||
|
$o = Invoice::findOrFail($this->argument('id'));
|
||||||
|
|
||||||
// Check the customer exists
|
// Check the customer exists
|
||||||
if ($io->account->providers->where('pivot.provider_oauth_id',$to->provider->id)->count() !== 1)
|
if ($o->account->providers->where('pivot.provider_oauth_id',$so->id)->count() !== 1)
|
||||||
throw new \Exception(sprintf('Account [%d] for Invoice [%d] not defined',$io->account_id,$io->id));
|
throw new \Exception(sprintf('Account [%d] for Invoice [%d] not defined',$o->account_id,$o->id));
|
||||||
|
|
||||||
$ao = $io->account->providers->where('pivot.provider_oauth_id',$to->provider->id)->pop();
|
$ao = $o->account->providers->where('pivot.provider_oauth_id',$so->id)->pop();
|
||||||
|
|
||||||
// Some validation
|
// Some validation
|
||||||
if (! $ao->pivot->ref) {
|
if (! $ao->pivot->ref) {
|
||||||
$this->error(sprintf('Accounting not defined for account [%d]',$io->account_id));
|
$this->error(sprintf('Accounting not defined for account [%d]',$o->account_id));
|
||||||
|
exit(1);
|
||||||
return self::FAILURE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$acc = new AccInvoice;
|
$acc = new AccInvoice;
|
||||||
$acc->CustomerRef = (object)['value'=>$ao->pivot->ref];
|
$acc->CustomerRef = (object)['value'=>$ao->pivot->ref];
|
||||||
$acc->DocNumber = $io->lid;
|
$acc->DocNumber = $o->lid;
|
||||||
$acc->TxnDate = $io->created_at->format('Y-m-d');
|
$acc->TxnDate = $o->created_at->format('Y-m-d');
|
||||||
$acc->DueDate = $io->due_at->format('Y-m-d');
|
$acc->DueDate = $o->due_at->format('Y-m-d');
|
||||||
|
|
||||||
$lines = collect();
|
$lines = collect();
|
||||||
$c = 0;
|
$c = 0;
|
||||||
$subtotal = 0;
|
|
||||||
|
|
||||||
// @todo Group these by ItemRef and the Same Unit Price and Description, so that we can then use quantity to represent the number of them.
|
// @todo Group these by ItemRef and the Same Unit Price and Description, so that we can then use quantity to represent the number of them.
|
||||||
foreach ($io->items->groupBy(
|
foreach ($o->items->groupBy(function($item) use ($so) {
|
||||||
fn($item)=>
|
return sprintf('%s.%s.%s.%s',$item->item_type_name,$item->price_base,$item->product->provider_ref($so),$item->taxes->pluck('description')->join('|'));
|
||||||
sprintf('%s.%s.%s.%s',
|
}) as $os)
|
||||||
$item->item_type_name,
|
|
||||||
$item->price_base,
|
|
||||||
$item->product->provider_ref($to->provider),
|
|
||||||
$item->taxes->pluck('description')->join('|'))) as $os)
|
|
||||||
{
|
{
|
||||||
$key = $os->first();
|
$key = $os->first();
|
||||||
|
|
||||||
// Some validation
|
// Some validation
|
||||||
if (! ($ref=$key->product->provider_ref($to->provider))) {
|
if (! ($ref=$key->product->provider_ref($so))) {
|
||||||
$this->error(sprintf('Accounting not defined in product [%d]',$key->product_id));
|
$this->error(sprintf('Accounting not defined in product [%d]',$key->product_id));
|
||||||
|
|
||||||
return self::FAILURE;
|
return self::FAILURE;
|
||||||
@ -98,36 +95,15 @@ class InvoiceAdd extends Command
|
|||||||
'UnitPrice' => $key->price_base,
|
'UnitPrice' => $key->price_base,
|
||||||
'ItemRef' => ['value'=>$ref],
|
'ItemRef' => ['value'=>$ref],
|
||||||
// @todo It is assumed there is only 1 tax category
|
// @todo It is assumed there is only 1 tax category
|
||||||
'TaxCodeRef' => ['value'=>$key->taxes->first()->tax->provider_ref($to->provider)],
|
'TaxCodeRef' => ['value'=>$key->taxes->first()->tax->provider_ref($so)],
|
||||||
];
|
];
|
||||||
$line->Amount = round($os->sum('quantity')*$key->price_base,2);
|
$line->Amount = $os->sum('quantity')*$key->price_base;
|
||||||
|
|
||||||
$subtotal += $line->Amount;
|
|
||||||
|
|
||||||
$lines->push($line);
|
$lines->push($line);
|
||||||
}
|
}
|
||||||
|
|
||||||
$acc->Line = $lines;
|
$acc->Line = $lines;
|
||||||
|
|
||||||
// If our subtotal doesnt match, we need to add a tax line
|
|
||||||
if ($io->subtotal !== $subtotal) {
|
|
||||||
$acc->TxnTaxDetail = (object)[
|
|
||||||
'TotalTax' => $x=$io->total-$subtotal,
|
|
||||||
'TaxLine' => [
|
|
||||||
(object) [
|
|
||||||
'Amount' => $x,
|
|
||||||
'DetailType' => 'TaxLineDetail',
|
|
||||||
'TaxLineDetail' => (object)[
|
|
||||||
'TaxRateRef' => (object)['value'=>23],
|
|
||||||
'NetAmountTaxable' => $io->subtotal,
|
|
||||||
]
|
|
||||||
]
|
|
||||||
]
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
dump($acc);
|
|
||||||
|
|
||||||
return AccountingInvoiceUpdate::dispatchSync($to,$acc);
|
return AccountingInvoiceUpdate::dispatchSync($to,$acc);
|
||||||
}
|
}
|
||||||
}
|
}
|
56
app/Console/Commands/Intuit/InvoiceGet.php
Normal file
56
app/Console/Commands/Intuit/InvoiceGet.php
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Console\Commands\Intuit;
|
||||||
|
|
||||||
|
use GuzzleHttp\Exception\ConnectException;
|
||||||
|
use Illuminate\Console\Command;
|
||||||
|
use Intuit\Exceptions\ConnectionIssueException;
|
||||||
|
|
||||||
|
use App\Models\{ProviderOauth,User};
|
||||||
|
|
||||||
|
class InvoiceGet extends Command
|
||||||
|
{
|
||||||
|
private const provider = 'intuit';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The name and signature of the console command.
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
protected $signature = 'intuit:invoice:get'
|
||||||
|
.' {id : Invoice ID}'
|
||||||
|
.' {user? : User Email}';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The console command description.
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
protected $description = 'Get an invoice from the quickbooks';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Execute the console command.
|
||||||
|
*
|
||||||
|
* @return int
|
||||||
|
*/
|
||||||
|
public function handle()
|
||||||
|
{
|
||||||
|
$uo = User::where('email',$this->argument('user') ?: config('osb.admin'))->singleOrFail();
|
||||||
|
|
||||||
|
$so = ProviderOauth::where('name',self::provider)->singleOrFail();
|
||||||
|
if (! ($to=$so->token($uo)))
|
||||||
|
abort(500,sprintf('Unknown Tokens for [%s]',$uo->email));
|
||||||
|
|
||||||
|
try {
|
||||||
|
$api = $to->API();
|
||||||
|
dump($api->getInvoiceQuery($this->argument('id')));
|
||||||
|
|
||||||
|
} catch (ConnectException|ConnectionIssueException $e) {
|
||||||
|
$this->error($e->getMessage());
|
||||||
|
|
||||||
|
return self::FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return self::SUCCESS;
|
||||||
|
}
|
||||||
|
}
|
@ -3,17 +3,13 @@
|
|||||||
namespace App\Console\Commands\Intuit;
|
namespace App\Console\Commands\Intuit;
|
||||||
|
|
||||||
use Illuminate\Console\Command;
|
use Illuminate\Console\Command;
|
||||||
use Intuit\Exceptions\NotTokenException;
|
|
||||||
use Intuit\Traits\ProviderTokenTrait;
|
|
||||||
|
|
||||||
use App\Models\Product;
|
use App\Models\{Product,ProviderOauth,User};
|
||||||
|
use App\Jobs\AccountingItemSync as Job;
|
||||||
|
|
||||||
/**
|
|
||||||
* Return a list of products and their accounting id
|
|
||||||
*/
|
|
||||||
class ItemList extends Command
|
class ItemList extends Command
|
||||||
{
|
{
|
||||||
use ProviderTokenTrait;
|
private const provider = 'intuit';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The name and signature of the console command.
|
* The name and signature of the console command.
|
||||||
@ -34,11 +30,16 @@ class ItemList extends Command
|
|||||||
* Execute the console command.
|
* Execute the console command.
|
||||||
*
|
*
|
||||||
* @return int
|
* @return int
|
||||||
* @throws NotTokenException
|
|
||||||
*/
|
*/
|
||||||
public function handle()
|
public function handle()
|
||||||
{
|
{
|
||||||
$to = $this->providerToken($this->argument('user'));
|
$uo = User::where('email',$this->argument('user') ?: config('osb.admin'))->singleOrFail();
|
||||||
|
|
||||||
|
$so = ProviderOauth::where('name',self::provider)->singleOrFail();
|
||||||
|
if (($x=$so->tokens->where('user_id',$uo->id))->count() !== 1)
|
||||||
|
abort(500,sprintf('Unknown Tokens for [%s]',$uo->email));
|
||||||
|
|
||||||
|
$to = $x->pop();
|
||||||
|
|
||||||
// Current Products used by services
|
// Current Products used by services
|
||||||
$products = Product::select(['products.*'])
|
$products = Product::select(['products.*'])
|
||||||
@ -47,12 +48,19 @@ class ItemList extends Command
|
|||||||
->where('services.active',TRUE)
|
->where('services.active',TRUE)
|
||||||
->get();
|
->get();
|
||||||
|
|
||||||
|
$api = $so->API($to,TRUE); // @todo Remove TRUE
|
||||||
|
|
||||||
|
$acc = $api->getItems()->pluck('pid','FullyQualifiedName');
|
||||||
|
|
||||||
foreach ($products as $po) {
|
foreach ($products as $po) {
|
||||||
if (! $x=$po->provider_ref($to->provider))
|
if (! $po->accounting)
|
||||||
$this->error(sprintf('Product [%03d](%s) doesnt have accounting set',$po->id,$po->name));
|
$this->error(sprintf('Product [%d](%s) doesnt have accounting set',$po->id,$po->name));
|
||||||
|
|
||||||
|
elseif ($acc->has($po->accounting) === FALSE)
|
||||||
|
$this->error(sprintf('Product [%d](%s) accounting [%s] doesnt exist?',$po->id,$po->name,$po->accounting));
|
||||||
|
|
||||||
else
|
else
|
||||||
$this->info(sprintf('Product [%03d](%s) set to accounting [%s]',$po->id,$po->name,$x));
|
$this->info(sprintf('Product [%d](%s) set to accounting [%s]',$po->id,$po->name,$po->accounting));
|
||||||
}
|
}
|
||||||
|
|
||||||
return self::SUCCESS;
|
return self::SUCCESS;
|
||||||
|
61
app/Console/Commands/Intuit/PaymentGet.php
Normal file
61
app/Console/Commands/Intuit/PaymentGet.php
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Console\Commands\Intuit;
|
||||||
|
|
||||||
|
use GuzzleHttp\Exception\ConnectException;
|
||||||
|
use Illuminate\Console\Command;
|
||||||
|
use Intuit\Exceptions\ConnectionIssueException;
|
||||||
|
|
||||||
|
use App\Jobs\AccountingPaymentSync as Job;
|
||||||
|
use App\Models\{ProviderOauth,User};
|
||||||
|
|
||||||
|
class PaymentGet extends Command
|
||||||
|
{
|
||||||
|
private const provider = 'intuit';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The name and signature of the console command.
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
protected $signature = 'accounting:payment:get'
|
||||||
|
.' {id : Payment ID}'
|
||||||
|
.' {user? : User Email}';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The console command description.
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
protected $description = 'Get a payment from the accounting provider';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Execute the console command.
|
||||||
|
*
|
||||||
|
* @return int
|
||||||
|
*/
|
||||||
|
public function handle()
|
||||||
|
{
|
||||||
|
$uo = User::where('email',$this->argument('user') ?: config('osb.admin'))->singleOrFail();
|
||||||
|
|
||||||
|
$so = ProviderOauth::where('name',self::provider)->singleOrFail();
|
||||||
|
if (! ($to=$so->token($uo)))
|
||||||
|
abort(500,sprintf('Unknown Tokens for [%s]',$uo->email));
|
||||||
|
|
||||||
|
try {
|
||||||
|
$api = $to->API();
|
||||||
|
$acc = $api->getPayment($this->argument('id'));
|
||||||
|
dump($acc);
|
||||||
|
|
||||||
|
} catch (ConnectException|ConnectionIssueException $e) {
|
||||||
|
$this->error($e->getMessage());
|
||||||
|
|
||||||
|
return Command::FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($acc)
|
||||||
|
Job::dispatchSync($to,$acc);
|
||||||
|
|
||||||
|
return self::SUCCESS;
|
||||||
|
}
|
||||||
|
}
|
38
app/Http/Controllers/AccountingController.php
Normal file
38
app/Http/Controllers/AccountingController.php
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Controllers;
|
||||||
|
|
||||||
|
use Illuminate\Support\Collection;
|
||||||
|
|
||||||
|
use App\Models\{ProviderOauth,User};
|
||||||
|
|
||||||
|
class AccountingController extends Controller
|
||||||
|
{
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
$this->middleware('auth');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Query the accounting system and get a valid list of accounting codes
|
||||||
|
*
|
||||||
|
* @param string $provider
|
||||||
|
* @return Collection
|
||||||
|
*/
|
||||||
|
public static function list(string $provider): Collection
|
||||||
|
{
|
||||||
|
// @todo This should be a variable
|
||||||
|
$uo = User::findOrFail(1);
|
||||||
|
|
||||||
|
$so = ProviderOauth::where('name',$provider)->singleOrFail();
|
||||||
|
if (! ($to=$so->token($uo)))
|
||||||
|
abort(500,sprintf('Unknown Tokens for [%s]',$uo->email));
|
||||||
|
|
||||||
|
$api = $to->API();
|
||||||
|
|
||||||
|
return $api->getItems()
|
||||||
|
->pluck('pid','Id')
|
||||||
|
->transform(function($item,$value) { return ['id'=>$value,'value'=>$item]; })
|
||||||
|
->values();
|
||||||
|
}
|
||||||
|
}
|
@ -3,7 +3,6 @@
|
|||||||
namespace App\Http\Controllers;
|
namespace App\Http\Controllers;
|
||||||
|
|
||||||
use Illuminate\Http\Request;
|
use Illuminate\Http\Request;
|
||||||
use Illuminate\Support\Arr;
|
|
||||||
use Illuminate\Support\Collection;
|
use Illuminate\Support\Collection;
|
||||||
|
|
||||||
use App\Http\Requests\ProductAddEdit;
|
use App\Http\Requests\ProductAddEdit;
|
||||||
@ -18,14 +17,14 @@ class ProductController extends Controller
|
|||||||
* @return Collection
|
* @return Collection
|
||||||
* @throws \Exception
|
* @throws \Exception
|
||||||
*/
|
*/
|
||||||
public function api_supplied_products(Request $request): Collection
|
public function api_supplier_products(Request $request): Collection
|
||||||
{
|
{
|
||||||
switch ($request->type) {
|
switch ($request->type) {
|
||||||
case Product\Broadband::class:
|
case Product\Broadband::class:
|
||||||
return Product\Broadband::select(['id','supplier_item_id'])
|
return Product\Broadband::select(['id','supplier_item_id'])
|
||||||
->with(['supplied.supplier_detail.supplier'])
|
->with(['supplied.supplier_detail.supplier'])
|
||||||
->get()
|
->get()
|
||||||
->map(fn($item)=>['id'=>$item->id,'name'=>sprintf('%s: %s',$item->supplied->supplier->name,$item->supplied->name)])
|
->map(function($item) { return ['id'=>$item->id,'name'=>sprintf('%s: %s',$item->supplied->supplier->name,$item->supplied->name)]; })
|
||||||
->sortBy('name')
|
->sortBy('name')
|
||||||
->values();
|
->values();
|
||||||
|
|
||||||
@ -33,7 +32,7 @@ class ProductController extends Controller
|
|||||||
return Product\Domain::select(['id','supplier_item_id'])
|
return Product\Domain::select(['id','supplier_item_id'])
|
||||||
->with(['supplied.supplier_detail.supplier'])
|
->with(['supplied.supplier_detail.supplier'])
|
||||||
->get()
|
->get()
|
||||||
->map(fn($item)=>['id'=>$item->id,'name'=>sprintf('%s: %s',$item->supplied->supplier->name,$item->supplied->name)])
|
->map(function($item) { return ['id'=>$item->id,'name'=>sprintf('%s: %s',$item->supplied->supplier->name,$item->supplied->name)]; })
|
||||||
->sortBy('name')
|
->sortBy('name')
|
||||||
->values();
|
->values();
|
||||||
|
|
||||||
@ -41,7 +40,7 @@ class ProductController extends Controller
|
|||||||
return Product\Email::select(['id','supplier_item_id'])
|
return Product\Email::select(['id','supplier_item_id'])
|
||||||
->with(['supplied.supplier_detail.supplier'])
|
->with(['supplied.supplier_detail.supplier'])
|
||||||
->get()
|
->get()
|
||||||
->map(fn($item)=>['id'=>$item->id,'name'=>sprintf('%s: %s',$item->supplied->supplier->name,$item->supplied->name)])
|
->map(function($item) { return ['id'=>$item->id,'name'=>sprintf('%s: %s',$item->supplied->supplier->name,$item->supplied->name)]; })
|
||||||
->sortBy('name')
|
->sortBy('name')
|
||||||
->values();
|
->values();
|
||||||
|
|
||||||
@ -49,7 +48,7 @@ class ProductController extends Controller
|
|||||||
return Product\Generic::select(['id','supplier_item_id'])
|
return Product\Generic::select(['id','supplier_item_id'])
|
||||||
->with(['supplied.supplier_detail.supplier'])
|
->with(['supplied.supplier_detail.supplier'])
|
||||||
->get()
|
->get()
|
||||||
->map(fn($item)=>['id'=>$item->id,'name'=>sprintf('%s: %s',$item->supplied->supplier->name,$item->supplied->name)])
|
->map(function($item) { return ['id'=>$item->id,'name'=>sprintf('%s: %s',$item->supplied->supplier->name,$item->supplied->name)]; })
|
||||||
->sortBy('name')
|
->sortBy('name')
|
||||||
->values();
|
->values();
|
||||||
|
|
||||||
@ -57,7 +56,7 @@ class ProductController extends Controller
|
|||||||
return Product\Host::select(['id','supplier_item_id'])
|
return Product\Host::select(['id','supplier_item_id'])
|
||||||
->with(['supplied.supplier_detail.supplier'])
|
->with(['supplied.supplier_detail.supplier'])
|
||||||
->get()
|
->get()
|
||||||
->map(fn($item)=>['id'=>$item->id,'name'=>sprintf('%s: %s',$item->supplied->supplier->name,$item->supplied->name)])
|
->map(function($item) { return ['id'=>$item->id,'name'=>sprintf('%s: %s',$item->supplied->supplier->name,$item->supplied->name)]; })
|
||||||
->sortBy('name')
|
->sortBy('name')
|
||||||
->values();
|
->values();
|
||||||
|
|
||||||
@ -65,7 +64,7 @@ class ProductController extends Controller
|
|||||||
return Product\Phone::select(['id','supplier_item_id'])
|
return Product\Phone::select(['id','supplier_item_id'])
|
||||||
->with(['supplied.supplier_detail.supplier'])
|
->with(['supplied.supplier_detail.supplier'])
|
||||||
->get()
|
->get()
|
||||||
->map(fn($item)=>['id'=>$item->id,'name'=>sprintf('%s: %s',$item->supplied->supplier->name,$item->supplied->name)])
|
->map(function($item) { return ['id'=>$item->id,'name'=>sprintf('%s: %s',$item->supplied->supplier->name,$item->supplied->name)]; })
|
||||||
->sortBy('name')
|
->sortBy('name')
|
||||||
->values();
|
->values();
|
||||||
|
|
||||||
@ -74,16 +73,32 @@ class ProductController extends Controller
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public function addedit(ProductAddEdit $request,Product $o)
|
/**
|
||||||
|
* Update a suppliers details
|
||||||
|
*
|
||||||
|
* @param Request $request
|
||||||
|
* @param Product $o
|
||||||
|
* @return \Illuminate\Contracts\Foundation\Application|\Illuminate\Contracts\View\Factory|\Illuminate\Contracts\View\View|\Illuminate\Http\RedirectResponse
|
||||||
|
*/
|
||||||
|
public function details(Request $request,Product $o)
|
||||||
{
|
{
|
||||||
foreach (Arr::except($request->validated(),['translate','accounting','pricing','active']) as $key => $item)
|
if (! $o->exists && $request->name)
|
||||||
|
$o = Product::where('name',$request->name)->firstOrNew();
|
||||||
|
|
||||||
|
return view('theme.backend.adminlte.product.details')
|
||||||
|
->with('breadcrumb',collect(['Products'=>url('a/product')]))
|
||||||
|
->with('o',$o);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function details_addedit(ProductAddEdit $request,Product $o)
|
||||||
|
{
|
||||||
|
foreach ($request->except(['_token','submit','translate','accounting']) as $key => $item)
|
||||||
$o->{$key} = $item;
|
$o->{$key} = $item;
|
||||||
|
|
||||||
$o->active = (bool)$request->active;
|
$o->active = (bool)$request->active;
|
||||||
|
|
||||||
// Trim down the pricing array, remove null values
|
// Trim down the pricing array, remove null values
|
||||||
$o->pricing = collect($request->validated('pricing'))
|
$o->pricing = $o->pricing->map(function($item) {
|
||||||
->map(function($item) {
|
|
||||||
foreach ($item as $k=>$v) {
|
foreach ($item as $k=>$v) {
|
||||||
if (is_array($v)) {
|
if (is_array($v)) {
|
||||||
$v = array_filter($v);
|
$v = array_filter($v);
|
||||||
@ -96,32 +111,39 @@ class ProductController extends Controller
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
$o->save();
|
$o->save();
|
||||||
|
|
||||||
} catch (\Exception $e) {
|
} catch (\Exception $e) {
|
||||||
return redirect()
|
return redirect()->back()->withErrors($e->getMessage())->withInput();
|
||||||
->back()
|
|
||||||
->withErrors($e->getMessage())
|
|
||||||
->withInput();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$o->load(['translate']);
|
$o->load(['translate']);
|
||||||
$oo = $o->translate ?: new ProductTranslate;
|
$oo = $o->translate ?: new ProductTranslate;
|
||||||
foreach ($request->validated('translate',[]) as $key => $item)
|
foreach ($request->get('translate',[]) as $key => $item)
|
||||||
$oo->{$key} = $item;
|
$oo->{$key} = $item;
|
||||||
|
|
||||||
$o->translate()->save($oo);
|
$o->translate()->save($oo);
|
||||||
|
|
||||||
foreach ($request->validated('accounting',[]) as $k=>$v) {
|
if ($request->accounting)
|
||||||
|
foreach ($request->accounting as $k=>$v)
|
||||||
$o->providers()->syncWithoutDetaching([
|
$o->providers()->syncWithoutDetaching([
|
||||||
$k => [
|
$k => [
|
||||||
'ref' => $v,
|
'ref' => $v,
|
||||||
'site_id'=>$o->site_id,
|
'site_id'=>$o->site_id,
|
||||||
],
|
],
|
||||||
]);
|
]);
|
||||||
}
|
|
||||||
|
|
||||||
return redirect()
|
return redirect()
|
||||||
->back()
|
->back()
|
||||||
->with('success','Product saved');
|
->with('success','Product saved');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Manage products for a site
|
||||||
|
*
|
||||||
|
* @note This method is protected by the routes
|
||||||
|
* @return \Illuminate\Contracts\Foundation\Application|\Illuminate\Contracts\View\Factory|\Illuminate\Contracts\View\View
|
||||||
|
*/
|
||||||
|
public function home()
|
||||||
|
{
|
||||||
|
return view('theme.backend.adminlte.product.home');
|
||||||
|
}
|
||||||
}
|
}
|
@ -3,9 +3,7 @@
|
|||||||
namespace App\Http\Requests;
|
namespace App\Http\Requests;
|
||||||
|
|
||||||
use Illuminate\Foundation\Http\FormRequest;
|
use Illuminate\Foundation\Http\FormRequest;
|
||||||
use Illuminate\Support\Facades\Gate;
|
use Illuminate\Support\Facades\Auth;
|
||||||
|
|
||||||
use App\Models\ProviderOauth;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Editing Suppliers
|
* Editing Suppliers
|
||||||
@ -19,7 +17,7 @@ class ProductAddEdit extends FormRequest
|
|||||||
*/
|
*/
|
||||||
public function authorize()
|
public function authorize()
|
||||||
{
|
{
|
||||||
return Gate::allows('wholesaler');
|
return Auth::user()->isWholesaler();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -36,21 +34,7 @@ class ProductAddEdit extends FormRequest
|
|||||||
'active' => 'sometimes|accepted',
|
'active' => 'sometimes|accepted',
|
||||||
'model' => 'sometimes|string', // @todo Check that it is a valid model type
|
'model' => 'sometimes|string', // @todo Check that it is a valid model type
|
||||||
'model_id' => 'sometimes|int', // @todo Check that it is a valid model type
|
'model_id' => 'sometimes|int', // @todo Check that it is a valid model type
|
||||||
'accounting' => [
|
'accounting' => 'nullable|array', // @todo Validate that the value is in the accounting system
|
||||||
'nullable',
|
|
||||||
'array',
|
|
||||||
function (string $attribute,mixed $value,\Closure $fail) {
|
|
||||||
if (! is_array($value))
|
|
||||||
$fail("Invalid format for {$attribute}");
|
|
||||||
|
|
||||||
foreach ($value as $k=>$v) {
|
|
||||||
if (! ProviderOauth::where('id',$k)->exists())
|
|
||||||
$fail("Provider doesnt exist [$k]");
|
|
||||||
|
|
||||||
// @todo Validate that the value is in the accounting system
|
|
||||||
}
|
|
||||||
},
|
|
||||||
],
|
|
||||||
'pricing' => 'required|array', // @todo Validate the elements in the pricing
|
'pricing' => 'required|array', // @todo Validate the elements in the pricing
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
@ -11,11 +11,10 @@ use Illuminate\Support\Collection;
|
|||||||
use Illuminate\Support\Facades\Auth;
|
use Illuminate\Support\Facades\Auth;
|
||||||
use Illuminate\Support\Facades\File;
|
use Illuminate\Support\Facades\File;
|
||||||
use Illuminate\Support\Str;
|
use Illuminate\Support\Str;
|
||||||
use Intuit\Exceptions\NotTokenException;
|
|
||||||
use Intuit\Traits\ProviderTokenTrait;
|
|
||||||
use Leenooks\Traits\ScopeActive;
|
use Leenooks\Traits\ScopeActive;
|
||||||
|
|
||||||
use App\Casts\CollectionOrNull;
|
use App\Casts\CollectionOrNull;
|
||||||
|
use App\Http\Controllers\AccountingController;
|
||||||
use App\Interfaces\{IDs,ProductItem};
|
use App\Interfaces\{IDs,ProductItem};
|
||||||
use App\Traits\{ProductDetails,ProviderRef};
|
use App\Traits\{ProductDetails,ProviderRef};
|
||||||
|
|
||||||
@ -67,7 +66,7 @@ use App\Traits\{ProductDetails,ProviderRef};
|
|||||||
*/
|
*/
|
||||||
class Product extends Model implements IDs
|
class Product extends Model implements IDs
|
||||||
{
|
{
|
||||||
use HasFactory,ProductDetails,ScopeActive,ProviderRef,ProviderTokenTrait;
|
use HasFactory,ProductDetails,ScopeActive,ProviderRef;
|
||||||
|
|
||||||
protected $casts = [
|
protected $casts = [
|
||||||
'pricing' => CollectionOrNull::class,
|
'pricing' => CollectionOrNull::class,
|
||||||
@ -369,18 +368,7 @@ class Product extends Model implements IDs
|
|||||||
|
|
||||||
public function accounting(string $provider): Collection
|
public function accounting(string $provider): Collection
|
||||||
{
|
{
|
||||||
$so = ProviderOauth::where('name',self::provider)
|
return AccountingController::list($provider);
|
||||||
->sole();
|
|
||||||
|
|
||||||
if (! ($to=$so->token(Auth::user())))
|
|
||||||
throw new NotTokenException(sprintf('Unknown Tokens for [%s]',Auth::user()->email));
|
|
||||||
|
|
||||||
return $to
|
|
||||||
->API()
|
|
||||||
->getItems()
|
|
||||||
->pluck('pid','Id')
|
|
||||||
->transform(fn($item,$value)=>['id'=>$value,'value'=>$item])
|
|
||||||
->values();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -35,6 +35,5 @@ class AppServiceProvider extends ServiceProvider
|
|||||||
|
|
||||||
Route::model('co',\App\Models\Checkout::class);
|
Route::model('co',\App\Models\Checkout::class);
|
||||||
Route::model('po',\App\Models\Payment::class);
|
Route::model('po',\App\Models\Payment::class);
|
||||||
Route::model('pdo',\App\Models\Product::class);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -11,8 +11,6 @@ trait ProviderRef
|
|||||||
{
|
{
|
||||||
public function provider_ref(ProviderOauth $poo): ?string
|
public function provider_ref(ProviderOauth $poo): ?string
|
||||||
{
|
{
|
||||||
return (($x=$this->providers->where('pivot.provider_oauth_id',$poo->id))->count() === 1)
|
return (($x=$this->providers->where('pivot.provider_oauth_id',$poo->id))->count() === 1) ? $x->pop()->pivot->ref : NULL;
|
||||||
? $x->pop()->pivot->ref
|
|
||||||
: NULL;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -11,12 +11,12 @@
|
|||||||
"barryvdh/laravel-snappy": "^1.0",
|
"barryvdh/laravel-snappy": "^1.0",
|
||||||
"clarkeash/doorman": "^9.0",
|
"clarkeash/doorman": "^9.0",
|
||||||
"eduardokum/laravel-mail-auto-embed": "^2.0",
|
"eduardokum/laravel-mail-auto-embed": "^2.0",
|
||||||
|
"laravel/dreamscape": "^0.1.0",
|
||||||
"laravel/framework": "^11.0",
|
"laravel/framework": "^11.0",
|
||||||
|
"laravel/intuit": "^0.1.7",
|
||||||
"laravel/passport": "^12.0",
|
"laravel/passport": "^12.0",
|
||||||
"laravel/socialite": "^5.15",
|
"laravel/socialite": "^5.15",
|
||||||
"laravel/ui": "^4.5",
|
"laravel/ui": "^4.5",
|
||||||
"leenooks/dreamscape": "^0.1.4",
|
|
||||||
"leenooks/intuit": "^0.2",
|
|
||||||
"leenooks/laravel": "^11.1",
|
"leenooks/laravel": "^11.1",
|
||||||
"leenooks/passkey": "^0.2",
|
"leenooks/passkey": "^0.2",
|
||||||
"paypal/paypal-checkout-sdk": "^1.0",
|
"paypal/paypal-checkout-sdk": "^1.0",
|
||||||
|
192
composer.lock
generated
192
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": "ae477f3c8e083f7f127d92de0a070e8d",
|
"content-hash": "fb7ccbd2314d05ba26778931b6ab0e03",
|
||||||
"packages": [
|
"packages": [
|
||||||
{
|
{
|
||||||
"name": "barryvdh/laravel-snappy",
|
"name": "barryvdh/laravel-snappy",
|
||||||
@ -1502,6 +1502,36 @@
|
|||||||
},
|
},
|
||||||
"time": "2023-12-18T09:12:11+00:00"
|
"time": "2023-12-18T09:12:11+00:00"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "laravel/dreamscape",
|
||||||
|
"version": "0.1.3",
|
||||||
|
"source": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://gitea.dege.au/laravel/dreamscape.git",
|
||||||
|
"reference": "bdf6ad2fbf8d8017b45cb0d5d68ffd7149195774"
|
||||||
|
},
|
||||||
|
"require": {
|
||||||
|
"jenssegers/model": "^1.5"
|
||||||
|
},
|
||||||
|
"type": "library",
|
||||||
|
"autoload": {
|
||||||
|
"psr-4": {
|
||||||
|
"Dreamscape\\": "src"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"authors": [
|
||||||
|
{
|
||||||
|
"name": "Deon George",
|
||||||
|
"email": "deon@dege.au"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"description": "Dreamscape API",
|
||||||
|
"keywords": [
|
||||||
|
"dreamscape",
|
||||||
|
"laravel"
|
||||||
|
],
|
||||||
|
"time": "2024-07-03T02:48:46+00:00"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "laravel/framework",
|
"name": "laravel/framework",
|
||||||
"version": "v11.20.0",
|
"version": "v11.20.0",
|
||||||
@ -1708,6 +1738,43 @@
|
|||||||
},
|
},
|
||||||
"time": "2024-08-06T14:39:21+00:00"
|
"time": "2024-08-06T14:39:21+00:00"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "laravel/intuit",
|
||||||
|
"version": "0.1.10",
|
||||||
|
"source": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://gitea.dege.au/laravel/intuit.git",
|
||||||
|
"reference": "947e1358b52270ff36bf87f4b4c60e9e54bf892d"
|
||||||
|
},
|
||||||
|
"require": {
|
||||||
|
"jenssegers/model": "^1.5"
|
||||||
|
},
|
||||||
|
"type": "library",
|
||||||
|
"extra": {
|
||||||
|
"laravel": {
|
||||||
|
"providers": [
|
||||||
|
"Intuit\\Providers\\IntuitServiceProvider"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"autoload": {
|
||||||
|
"psr-4": {
|
||||||
|
"Intuit\\": "src"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"authors": [
|
||||||
|
{
|
||||||
|
"name": "Deon George",
|
||||||
|
"email": "deon@dege.au"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"description": "Intuit API",
|
||||||
|
"keywords": [
|
||||||
|
"intuit",
|
||||||
|
"laravel"
|
||||||
|
],
|
||||||
|
"time": "2024-07-14T03:46:04+00:00"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "laravel/passport",
|
"name": "laravel/passport",
|
||||||
"version": "v12.3.0",
|
"version": "v12.3.0",
|
||||||
@ -2222,16 +2289,16 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "league/commonmark",
|
"name": "league/commonmark",
|
||||||
"version": "2.5.2",
|
"version": "2.5.1",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/thephpleague/commonmark.git",
|
"url": "https://github.com/thephpleague/commonmark.git",
|
||||||
"reference": "df09d5b6a4188f8f3c3ab2e43a109076a5eeb767"
|
"reference": "ac815920de0eff6de947eac0a6a94e5ed0fb147c"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/thephpleague/commonmark/zipball/df09d5b6a4188f8f3c3ab2e43a109076a5eeb767",
|
"url": "https://api.github.com/repos/thephpleague/commonmark/zipball/ac815920de0eff6de947eac0a6a94e5ed0fb147c",
|
||||||
"reference": "df09d5b6a4188f8f3c3ab2e43a109076a5eeb767",
|
"reference": "ac815920de0eff6de947eac0a6a94e5ed0fb147c",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
@ -2324,7 +2391,7 @@
|
|||||||
"type": "tidelift"
|
"type": "tidelift"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"time": "2024-08-14T10:56:57+00:00"
|
"time": "2024-07-24T12:52:09+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "league/config",
|
"name": "league/config",
|
||||||
@ -2988,82 +3055,13 @@
|
|||||||
],
|
],
|
||||||
"time": "2024-03-23T07:42:40+00:00"
|
"time": "2024-03-23T07:42:40+00:00"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"name": "leenooks/dreamscape",
|
|
||||||
"version": "0.1.4",
|
|
||||||
"source": {
|
|
||||||
"type": "git",
|
|
||||||
"url": "https://gitea.dege.au/laravel/dreamscape.git",
|
|
||||||
"reference": "2680154d53879a4454f62086a072d031501f3531"
|
|
||||||
},
|
|
||||||
"require": {
|
|
||||||
"jenssegers/model": "^1.5"
|
|
||||||
},
|
|
||||||
"type": "library",
|
|
||||||
"autoload": {
|
|
||||||
"psr-4": {
|
|
||||||
"Dreamscape\\": "src"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"authors": [
|
|
||||||
{
|
|
||||||
"name": "Deon George",
|
|
||||||
"email": "deon@dege.au"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"description": "Dreamscape API",
|
|
||||||
"keywords": [
|
|
||||||
"dreamscape",
|
|
||||||
"laravel",
|
|
||||||
"leenooks"
|
|
||||||
],
|
|
||||||
"time": "2024-08-11T11:10:05+00:00"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "leenooks/intuit",
|
|
||||||
"version": "0.2.1",
|
|
||||||
"source": {
|
|
||||||
"type": "git",
|
|
||||||
"url": "https://gitea.dege.au/laravel/intuit.git",
|
|
||||||
"reference": "9d81824b52dadc7b5fc0db9912373ecfb0942da7"
|
|
||||||
},
|
|
||||||
"require": {
|
|
||||||
"jenssegers/model": "^1.5"
|
|
||||||
},
|
|
||||||
"type": "library",
|
|
||||||
"extra": {
|
|
||||||
"laravel": {
|
|
||||||
"providers": [
|
|
||||||
"Intuit\\Providers\\IntuitServiceProvider"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"autoload": {
|
|
||||||
"psr-4": {
|
|
||||||
"Intuit\\": "src"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"authors": [
|
|
||||||
{
|
|
||||||
"name": "Deon George",
|
|
||||||
"email": "deon@dege.au"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"description": "Intuit API",
|
|
||||||
"keywords": [
|
|
||||||
"intuit",
|
|
||||||
"laravel",
|
|
||||||
"leenooks"
|
|
||||||
],
|
|
||||||
"time": "2024-08-14T12:18:57+00:00"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"name": "leenooks/laravel",
|
"name": "leenooks/laravel",
|
||||||
"version": "11.1.11",
|
"version": "11.1.10",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://gitea.dege.au/laravel/leenooks.git",
|
"url": "https://gitea.dege.au/laravel/leenooks.git",
|
||||||
"reference": "83470c3ff575e62a3e7b66f07177ef9c95c8a54d"
|
"reference": "92dd7ac3cb6598e55af3cbc95d9cf7af44318a30"
|
||||||
},
|
},
|
||||||
"type": "library",
|
"type": "library",
|
||||||
"extra": {
|
"extra": {
|
||||||
@ -3096,7 +3094,7 @@
|
|||||||
"laravel",
|
"laravel",
|
||||||
"leenooks"
|
"leenooks"
|
||||||
],
|
],
|
||||||
"time": "2024-08-14T12:19:53+00:00"
|
"time": "2024-08-10T12:25:03+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "leenooks/passkey",
|
"name": "leenooks/passkey",
|
||||||
@ -4017,16 +4015,16 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "phpseclib/phpseclib",
|
"name": "phpseclib/phpseclib",
|
||||||
"version": "3.0.41",
|
"version": "3.0.39",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/phpseclib/phpseclib.git",
|
"url": "https://github.com/phpseclib/phpseclib.git",
|
||||||
"reference": "621c73f7dcb310b61de34d1da4c4204e8ace6ceb"
|
"reference": "211ebc399c6e73c225a018435fe5ae209d1d1485"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/phpseclib/phpseclib/zipball/621c73f7dcb310b61de34d1da4c4204e8ace6ceb",
|
"url": "https://api.github.com/repos/phpseclib/phpseclib/zipball/211ebc399c6e73c225a018435fe5ae209d1d1485",
|
||||||
"reference": "621c73f7dcb310b61de34d1da4c4204e8ace6ceb",
|
"reference": "211ebc399c6e73c225a018435fe5ae209d1d1485",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
@ -4107,7 +4105,7 @@
|
|||||||
],
|
],
|
||||||
"support": {
|
"support": {
|
||||||
"issues": "https://github.com/phpseclib/phpseclib/issues",
|
"issues": "https://github.com/phpseclib/phpseclib/issues",
|
||||||
"source": "https://github.com/phpseclib/phpseclib/tree/3.0.41"
|
"source": "https://github.com/phpseclib/phpseclib/tree/3.0.39"
|
||||||
},
|
},
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
@ -4123,7 +4121,7 @@
|
|||||||
"type": "tidelift"
|
"type": "tidelift"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"time": "2024-08-12T00:13:54+00:00"
|
"time": "2024-06-24T06:27:33+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "psr/clock",
|
"name": "psr/clock",
|
||||||
@ -8912,16 +8910,16 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "phpunit/phpunit",
|
"name": "phpunit/phpunit",
|
||||||
"version": "11.3.1",
|
"version": "11.3.0",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/sebastianbergmann/phpunit.git",
|
"url": "https://github.com/sebastianbergmann/phpunit.git",
|
||||||
"reference": "fe179875ef0c14e90b75617002767eae0a742641"
|
"reference": "a8dce73a8938dfec7ac0daa91bdbcaae7d7188a3"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/fe179875ef0c14e90b75617002767eae0a742641",
|
"url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/a8dce73a8938dfec7ac0daa91bdbcaae7d7188a3",
|
||||||
"reference": "fe179875ef0c14e90b75617002767eae0a742641",
|
"reference": "a8dce73a8938dfec7ac0daa91bdbcaae7d7188a3",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
@ -8942,7 +8940,7 @@
|
|||||||
"phpunit/php-timer": "^7.0.1",
|
"phpunit/php-timer": "^7.0.1",
|
||||||
"sebastian/cli-parser": "^3.0.2",
|
"sebastian/cli-parser": "^3.0.2",
|
||||||
"sebastian/code-unit": "^3.0.1",
|
"sebastian/code-unit": "^3.0.1",
|
||||||
"sebastian/comparator": "^6.0.2",
|
"sebastian/comparator": "^6.0.1",
|
||||||
"sebastian/diff": "^6.0.2",
|
"sebastian/diff": "^6.0.2",
|
||||||
"sebastian/environment": "^7.2.0",
|
"sebastian/environment": "^7.2.0",
|
||||||
"sebastian/exporter": "^6.1.3",
|
"sebastian/exporter": "^6.1.3",
|
||||||
@ -8992,7 +8990,7 @@
|
|||||||
"support": {
|
"support": {
|
||||||
"issues": "https://github.com/sebastianbergmann/phpunit/issues",
|
"issues": "https://github.com/sebastianbergmann/phpunit/issues",
|
||||||
"security": "https://github.com/sebastianbergmann/phpunit/security/policy",
|
"security": "https://github.com/sebastianbergmann/phpunit/security/policy",
|
||||||
"source": "https://github.com/sebastianbergmann/phpunit/tree/11.3.1"
|
"source": "https://github.com/sebastianbergmann/phpunit/tree/11.3.0"
|
||||||
},
|
},
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
@ -9008,7 +9006,7 @@
|
|||||||
"type": "tidelift"
|
"type": "tidelift"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"time": "2024-08-13T06:14:23+00:00"
|
"time": "2024-08-02T03:56:43+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "sebastian/cli-parser",
|
"name": "sebastian/cli-parser",
|
||||||
@ -9182,16 +9180,16 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "sebastian/comparator",
|
"name": "sebastian/comparator",
|
||||||
"version": "6.0.2",
|
"version": "6.0.1",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/sebastianbergmann/comparator.git",
|
"url": "https://github.com/sebastianbergmann/comparator.git",
|
||||||
"reference": "450d8f237bd611c45b5acf0733ce43e6bb280f81"
|
"reference": "131942b86d3587291067a94f295498ab6ac79c20"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/450d8f237bd611c45b5acf0733ce43e6bb280f81",
|
"url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/131942b86d3587291067a94f295498ab6ac79c20",
|
||||||
"reference": "450d8f237bd611c45b5acf0733ce43e6bb280f81",
|
"reference": "131942b86d3587291067a94f295498ab6ac79c20",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
@ -9247,7 +9245,7 @@
|
|||||||
"support": {
|
"support": {
|
||||||
"issues": "https://github.com/sebastianbergmann/comparator/issues",
|
"issues": "https://github.com/sebastianbergmann/comparator/issues",
|
||||||
"security": "https://github.com/sebastianbergmann/comparator/security/policy",
|
"security": "https://github.com/sebastianbergmann/comparator/security/policy",
|
||||||
"source": "https://github.com/sebastianbergmann/comparator/tree/6.0.2"
|
"source": "https://github.com/sebastianbergmann/comparator/tree/6.0.1"
|
||||||
},
|
},
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
@ -9255,7 +9253,7 @@
|
|||||||
"type": "github"
|
"type": "github"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"time": "2024-08-12T06:07:25+00:00"
|
"time": "2024-07-03T04:48:07+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "sebastian/complexity",
|
"name": "sebastian/complexity",
|
||||||
|
@ -1,14 +1,14 @@
|
|||||||
@extends('adminlte::layouts.app')
|
@extends('adminlte::layouts.app')
|
||||||
|
|
||||||
@section('htmlheader_title')
|
@section('htmlheader_title')
|
||||||
{{ $pdo->name ?: 'New Product' }}
|
{{ $o->name ?: 'New Product' }}
|
||||||
@endsection
|
@endsection
|
||||||
@section('page_title')
|
@section('page_title')
|
||||||
{{ $pdo->name ?: 'New Product' }}
|
{{ $o->name ?: 'New Product' }}
|
||||||
@endsection
|
@endsection
|
||||||
|
|
||||||
@section('contentheader_title')
|
@section('contentheader_title')
|
||||||
{{ $pdo->name ?: 'New Product' }}
|
{{ $o->name ?: 'New Product' }}
|
||||||
@endsection
|
@endsection
|
||||||
@section('contentheader_description')
|
@section('contentheader_description')
|
||||||
@endsection
|
@endsection
|
||||||
@ -23,8 +23,8 @@
|
|||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-12">
|
<div class="col-12">
|
||||||
<div class="card">
|
<div class="card">
|
||||||
<div class="card-header bg-dark p-2">
|
<div class="card-header bg-dark d-flex p-0">
|
||||||
<ul class="nav nav-pills">
|
<ul class="nav nav-pills w-100 p-2">
|
||||||
<li class="nav-item"><a class="nav-link active" href="#details" data-toggle="tab">Detail</a></li>
|
<li class="nav-item"><a class="nav-link active" href="#details" data-toggle="tab">Detail</a></li>
|
||||||
<li class="nav-item"><a class="nav-link" href="#services" data-toggle="tab">Services</a></li>
|
<li class="nav-item"><a class="nav-link" href="#services" data-toggle="tab">Services</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
|
@ -1,32 +1,54 @@
|
|||||||
<!-- $pdo=Product::class -->
|
<!-- $o = Product::class -->
|
||||||
@use(App\Models\Group)
|
|
||||||
@use(App\Models\Invoice)
|
|
||||||
@use(App\Models\Product)
|
|
||||||
@use(App\Models\ProviderOauth)
|
|
||||||
|
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-12">
|
<div class="col-12">
|
||||||
<h3>Product Details <x-leenooks::button.success class="float-right"/></h3>
|
<h3>Product Details @include('adminlte::widget.success_button')</h3>
|
||||||
<hr>
|
<hr>
|
||||||
|
|
||||||
<form method="POST">
|
<form class="g-0 needs-validation" method="POST" enctype="multipart/form-data" role="form">
|
||||||
@csrf
|
@csrf
|
||||||
|
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<!-- Product ID -->
|
<!-- Product ID -->
|
||||||
<div class="col-12 col-sm-9 col-md-4 col-xl-3">
|
<div class="col-12 col-sm-9 col-md-4 col-xl-3">
|
||||||
<x-leenooks::form.text id="translate.name_short" name="translate[name_short]" icon="fa-atom" label="Product ID" old="translate.name_short" :value="$pdo->pid"/>
|
@include('adminlte::widget.form_text',[
|
||||||
|
'label'=>'Product ID',
|
||||||
|
'icon'=>'fas fa-atom',
|
||||||
|
'id'=>'translate.name_short',
|
||||||
|
'old'=>'translate.name_short',
|
||||||
|
'name'=>'translate[name_short]',
|
||||||
|
'value'=>$o->pid,
|
||||||
|
])
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Product Name -->
|
<!-- Product Name -->
|
||||||
<div class="col-12 col-sm-9 col-md-8 col-xl-9">
|
<div class="col-12 col-sm-9 col-md-8 col-xl-9">
|
||||||
<x-leenooks::form.text id="translate.name_detail" name="translate[name_detail]" icon="fa-atom" label="Product Name" old="translate.name_detail" :value="$pdo->name"/>
|
@include('adminlte::widget.form_text',[
|
||||||
|
'label'=>'Product Name',
|
||||||
|
'icon'=>'fas fa-atom',
|
||||||
|
'id'=>'translate.name_detail',
|
||||||
|
'old'=>'translate.name_detail',
|
||||||
|
'name'=>'translate[name_detail]',
|
||||||
|
'value'=>$o->name,
|
||||||
|
])
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-12">
|
<div class="col-12">
|
||||||
<x-leenooks::form.textarea id="translate.description" name="translate[description]" label="Product Description" placeholder="Full Description..." old="translate.description" :value="$pdo->description"/>
|
<div class="form-group @error('description') is-invalid @enderror">
|
||||||
|
<!-- Product Description -->
|
||||||
|
<label for="description_full" class="col-form-label">Product Description</label>
|
||||||
|
<div class="input-group">
|
||||||
|
<div class="w-100">
|
||||||
|
<textarea class="textarea" id="description" name="translate[description]" placeholder="Full Description">{!! old('description',$o->description) ?? '' !!}</textarea>
|
||||||
|
<span class="invalid-feedback" role="alert">
|
||||||
|
@error('description')
|
||||||
|
{{ $message }}
|
||||||
|
@enderror
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@ -35,21 +57,48 @@
|
|||||||
<div class="row">
|
<div class="row">
|
||||||
<!-- Active -->
|
<!-- Active -->
|
||||||
<div class="col-6">
|
<div class="col-6">
|
||||||
<x-leenooks::form.toggle name="active" label="Active" :value="$pdo->active"/>
|
@include('adminlte::widget.form_toggle',[
|
||||||
|
'label'=>'Active',
|
||||||
|
'id'=>'active',
|
||||||
|
'old'=>'active',
|
||||||
|
'name'=>'active',
|
||||||
|
'value'=>$o->active ?? '',
|
||||||
|
])
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<!-- Product Type -->
|
<!-- Product Type -->
|
||||||
<div class="col-12">
|
<div class="col-12">
|
||||||
<x-leenooks::form.select name="model" icon="fa-list" label="Product" choose="true" groupby="active" :value="get_class($pdo->type)" :options="Product::availableTypes()->transform(fn($item)=>['id'=>$item,'value'=>$item])"/>
|
@include('adminlte::widget.form_select',[
|
||||||
|
'label'=>'Product Type',
|
||||||
|
'icon'=>'fas fa-list',
|
||||||
|
'id'=>'model',
|
||||||
|
'old'=>'model',
|
||||||
|
'name'=>'model',
|
||||||
|
'options'=>\App\Models\Product::availableTypes()->transform(function($item) { return ['id'=>$item,'value'=>$item]; }),
|
||||||
|
'value'=>get_class($o->type),
|
||||||
|
])
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<!-- Supplied Product -->
|
<!-- Supplied Product -->
|
||||||
<div class="col-12" id="supplied_product">
|
<div class="col-12" id="supplier_product">
|
||||||
<x-leenooks::form.select name="model_id" icon="fa-shopping-cart" label="Supplied Product"/>
|
<div class="form-group">
|
||||||
|
<label for="model_id">Supplied Product</label>
|
||||||
|
<div class="input-group has-validation">
|
||||||
|
<div class="input-group-prepend">
|
||||||
|
<span class="input-group-text"><i class="fa-fw fas fa-shopping-cart"></i></span>
|
||||||
|
</div>
|
||||||
|
<select class="form-control @error('model_id') is-invalid @enderror" id="model_id" name="model_id"></select>
|
||||||
|
<span class="invalid-feedback" role="alert">
|
||||||
|
@error('model_id')
|
||||||
|
{{ $message }}
|
||||||
|
@enderror
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@ -58,10 +107,26 @@
|
|||||||
<div class="col-12">
|
<div class="col-12">
|
||||||
<span class="h5">Accounting</span>
|
<span class="h5">Accounting</span>
|
||||||
<hr>
|
<hr>
|
||||||
|
@foreach (\App\Models\ProviderOauth::providers() as $apo)
|
||||||
<!-- @todo When returning with a bad value old() is not selecting the previous value, may need to have the full html here instead of a component -->
|
<div class="form-group">
|
||||||
@foreach (ProviderOauth::providers() as $apo)
|
<label for="{{ $x=sprintf('acc_%d',$apo->id) }}">{{ ucfirst($apo->name) }}</label>
|
||||||
<x-leenooks::form.select :id="sprintf('acc_%d',$apo->id)" :name="sprintf('accounting[%d]',$apo->id)" icon="fa-calculator" :label="ucfirst($apo->name)" :choose="true" :value="$pdo->provider_ref($apo)" old="accounting" :options="$pdo->accounting($apo->name)"/>
|
<div class="input-group has-validation">
|
||||||
|
<div class="input-group-prepend">
|
||||||
|
<span class="input-group-text"><i class="fa-fw fas fa-calculator"></i></span>
|
||||||
|
</div>
|
||||||
|
<select class="form-control @error($x) is-invalid @enderror select" id="{{ $x }}" name="{{ sprintf('accounting[%d]',$apo->id) }}">
|
||||||
|
<option></option>
|
||||||
|
@foreach ($o->accounting($apo->name) as $v)
|
||||||
|
<option value="{{ $v['id'] }}" @if($o->provider_ref($apo) === (string)$v['id'])selected @endif>{{ $v['value'] }}</option>
|
||||||
|
@endforeach
|
||||||
|
</select>
|
||||||
|
<span class="invalid-feedback" role="alert">
|
||||||
|
@error($x)
|
||||||
|
{{ $message }}
|
||||||
|
@enderror
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
@endforeach
|
@endforeach
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -71,20 +136,20 @@
|
|||||||
<span class="h5">Pricing</span><small> Ex Taxes</small>
|
<span class="h5">Pricing</span><small> Ex Taxes</small>
|
||||||
<hr>
|
<hr>
|
||||||
@error('pricing')
|
@error('pricing')
|
||||||
<x-leenooks::errors/>
|
@include('adminlte::widget.errors')
|
||||||
@enderror
|
@enderror
|
||||||
|
|
||||||
<ul class="nav nav-pills w-100 pl-0 pt-2 pb-2">
|
<ul class="nav nav-pills w-100 pl-0 pt-2 pb-2">
|
||||||
@foreach($g=Group::pricing()->active()->get() as $go)
|
@foreach(\App\Models\Group::pricing()->active()->get() as $go)
|
||||||
<li class="nav-item"><a class="nav-link @if(! $loop->index)active @endif" href="#pg_{{ $go->id }}" data-toggle="tab">{{ $go->name }}</a></li>
|
<li class="nav-item"><a class="nav-link @if(! $loop->index)active @endif" href="#pg_{{ $go->id }}" data-toggle="tab">{{ $go->name }}</a></li>
|
||||||
@endforeach
|
@endforeach
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
<div class="tab-content">
|
<div class="tab-content">
|
||||||
@foreach($g as $go)
|
@foreach(\App\Models\Group::pricing()->active()->get() as $go)
|
||||||
<div class="tab-pane fade @if(! $loop->index)show active @endif" id="pg_{{ $go->id }}">
|
<div class="tab-pane fade @if(! $loop->index)show active @endif" id="pg_{{ $go->id }}" role="tabpanel">
|
||||||
|
|
||||||
@foreach(Invoice::billing_periods as $bp=>$detail)
|
@foreach(\App\Models\Invoice::billing_periods as $bp=>$detail)
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-6">
|
<div class="col-6">
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
@ -93,13 +158,13 @@
|
|||||||
<div class="input-group-prepend">
|
<div class="input-group-prepend">
|
||||||
<span class="input-group-text"><i class="fa-fw fas fa-calculator"></i></span>
|
<span class="input-group-text"><i class="fa-fw fas fa-calculator"></i></span>
|
||||||
</div>
|
</div>
|
||||||
<input type="text" class="form-control text-right @error($x) is-invalid @enderror" id="{{ $x }}" name="{{ sprintf('pricing[%d][%d][base]',$bp,$go->id) }}" {{ ($ca=$pdo->charge_available($bp,$go)) ? 'value' : 'placeholder' }}="{{ $c=$pdo->charge($bp,$go,'base') }}" @if(is_null($c) || ! $ca) disabled @endif>
|
<input type="text" class="form-control text-right @error($x) is-invalid @enderror" id="{{ $x }}" name="{{ sprintf('pricing[%d][%d][base]',$bp,$go->id) }}" {{ ($ca=$o->charge_available($bp,$go)) ? 'value' : 'placeholder' }}="{{ $c=$o->charge($bp,$go,'base') }}" @if(is_null($c) || ! $ca) disabled @endif>
|
||||||
<div class="input-group-append">
|
<div class="input-group-append">
|
||||||
<div class="input-group-text">
|
<div class="input-group-text">
|
||||||
<input type="checkbox" name="{{ sprintf('pricing[%d][show]',$bp) }}" @if($c && $ca)checked @endif>
|
<input type="checkbox" name="{{ sprintf('pricing[%d][show]',$bp) }}" @if($c && $ca)checked @endif>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<span class="invalid-feedback">
|
<span class="invalid-feedback" role="alert">
|
||||||
@error($x)
|
@error($x)
|
||||||
{{ $message }}
|
{{ $message }}
|
||||||
@enderror
|
@enderror
|
||||||
@ -115,8 +180,8 @@
|
|||||||
<div class="input-group-prepend">
|
<div class="input-group-prepend">
|
||||||
<span class="input-group-text"><i class="fa-fw fas fa-cog"></i></span>
|
<span class="input-group-text"><i class="fa-fw fas fa-cog"></i></span>
|
||||||
</div>
|
</div>
|
||||||
<input type="text" class="form-control text-right @error($x) is-invalid @enderror" id="{{ $x }}" name="{{ sprintf('pricing[%d][%d][setup]',$bp,$go->id) }}" {{ $ca ? 'value' : 'placeholder' }}="{{ $c=$pdo->charge($bp,$go,'setup') }}" @if(is_null($c) || ! $ca) disabled @endif>
|
<input type="text" class="form-control text-right @error($x) is-invalid @enderror" id="{{ $x }}" name="{{ sprintf('pricing[%d][%d][setup]',$bp,$go->id) }}" {{ $ca ? 'value' : 'placeholder' }}="{{ $c=$o->charge($bp,$go,'setup') }}" @if(is_null($c) || ! $ca) disabled @endif>
|
||||||
<span class="invalid-feedback">
|
<span class="invalid-feedback" role="alert">
|
||||||
@error($x)
|
@error($x)
|
||||||
{{ $message }}
|
{{ $message }}
|
||||||
@enderror
|
@enderror
|
||||||
@ -133,9 +198,12 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col">
|
<!-- Buttons -->
|
||||||
<x-leenooks::button.reset/>
|
<div class="col-12">
|
||||||
<x-leenooks::button.submit class="float-right">Save</x-leenooks::button.submit>
|
<a href="{{ url('/home') }}" class="btn btn-danger">Cancel</a>
|
||||||
|
@can('wholesaler')
|
||||||
|
<button type="submit" name="submit" class="btn btn-success mr-0 float-right">@if ($o->exists)Save @else Add @endif</button>
|
||||||
|
@endcan
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
@ -143,9 +211,14 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
@section('page-scripts')
|
@section('page-scripts')
|
||||||
|
@css(select2)
|
||||||
|
@css(simplemde)
|
||||||
|
@js(select2,autofocus)
|
||||||
|
@js(simplemde)
|
||||||
|
|
||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
// Get a list of supplier items matching this type to populate model_id
|
// Get a list of supplier items matching this type to populate model_id
|
||||||
function supplied_products(type,destination,selected) {
|
function supplier_products(type,destination,selected) {
|
||||||
destination.prop('disabled',true);
|
destination.prop('disabled',true);
|
||||||
|
|
||||||
$.ajax({
|
$.ajax({
|
||||||
@ -153,10 +226,11 @@
|
|||||||
dataType: 'json',
|
dataType: 'json',
|
||||||
data: {type: type},
|
data: {type: type},
|
||||||
cache: false,
|
cache: false,
|
||||||
url: '{{ url('a/supplied_products') }}',
|
url: '{{ url('api/a/supplier_products') }}',
|
||||||
timeout: 2000,
|
timeout: 2000,
|
||||||
error: function(x) {
|
error: function(x) {
|
||||||
// @todo add a spinner
|
// @todo add a spinner
|
||||||
|
//spinner.toggleClass('d-none').toggleClass('fa-spin');
|
||||||
alert('Failed to submit');
|
alert('Failed to submit');
|
||||||
},
|
},
|
||||||
success: function(data) {
|
success: function(data) {
|
||||||
@ -172,24 +246,28 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
$(document).ready(function() {
|
$(document).ready(function() {
|
||||||
|
new SimpleMDE({ element: $('.textarea')[0], forceSync: true });
|
||||||
|
|
||||||
$('#model').on('change',function(item) {
|
$('#model').on('change',function(item) {
|
||||||
if ($(this).val()) {
|
if ($(this).val()) {
|
||||||
$('#supplied_product').show();
|
$('#supplier_product').show();
|
||||||
supplied_products($(this).val(),$('#model_id'));
|
supplier_products($(this).val(),$('#model_id'));
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
$('#supplied_product').hide();
|
$('#supplier_product').hide();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// After we render the page, hide the supplied_product if this product has no model.
|
$('#model_id').select2();
|
||||||
|
$('.select').select2();
|
||||||
|
|
||||||
|
// After we render the page, hide the supplier_product if this product has no model.
|
||||||
// We do this here, because adding d-none to the div results in the select2 input not presenting correctly
|
// We do this here, because adding d-none to the div results in the select2 input not presenting correctly
|
||||||
if (! $('#model').val())
|
if (! $('#model').val())
|
||||||
$('#supplied_product').hide();
|
$('#supplier_product').hide();
|
||||||
else
|
else
|
||||||
supplied_products($('#model').val(),$('#model_id'),{{ old('model_id',$pdo->model_id) }});
|
supplier_products($('#model').val(),$('#model_id'),{{ old('model_id',$o->model_id) }});
|
||||||
|
|
||||||
// @todo when there is a value in 1 of the two boxes in the row, the toggle incorrectly disables one and enables the other
|
|
||||||
$('input[type=checkbox]').on('click',function(item) {
|
$('input[type=checkbox]').on('click',function(item) {
|
||||||
var input = $(this).parent().parent().parent().find('input[type="text"]');
|
var input = $(this).parent().parent().parent().find('input[type="text"]');
|
||||||
input.prop('disabled',(i,v)=>!v);
|
input.prop('disabled',(i,v)=>!v);
|
||||||
|
@ -1,18 +1,25 @@
|
|||||||
<!-- $o=Product::class -->
|
<!-- $o = Product::class -->
|
||||||
@use(App\Models\Product)
|
|
||||||
|
|
||||||
<div class="card card-dark">
|
<div class="card card-dark">
|
||||||
<div class="card-header">
|
<div class="card-header">
|
||||||
<h1 class="card-title">Product Configuration</h1>
|
<h1 class="card-title">Product Configuration</h1>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
<form method="POST">
|
<form class="g-0 needs-validation" method="POST" enctype="multipart/form-data" role="form">
|
||||||
@csrf
|
@csrf
|
||||||
|
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-12 col-sm-9 col-md-6 col-xl-5">
|
<div class="col-12 col-sm-9 col-md-6 col-xl-5">
|
||||||
<x-leenooks::form.select name="product_id" icon="fa-list" label="Product" choose="true" groupby="active" :value="$po?->id ?? ''" :options="Product::get()->sortBy(fn($item)=>($item->active ? '0' : '1').$item->name)->transform(fn($item)=>['id'=>$item->id,'value'=>$item->name,'active'=>$item->active])"/>
|
@include('adminlte::widget.form_select',[
|
||||||
|
'label'=>'Product',
|
||||||
|
'icon'=>'fas fa-list',
|
||||||
|
'id'=>'product_id',
|
||||||
|
'old'=>'product_id',
|
||||||
|
'name'=>'product_id',
|
||||||
|
'groupby'=>'active',
|
||||||
|
'options'=>\App\Models\Product::get()->sortBy(function($item) { return ($item->active ? '0' : '1').$item->name; })->transform(function($item) { return ['id'=>$item->id,'value'=>$item->name,'active'=>$item->active]; }),
|
||||||
|
'value'=>isset($o) ? $o->id : NULL,
|
||||||
|
])
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
@ -20,10 +27,13 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
@section('page-scripts')
|
@section('page-scripts')
|
||||||
|
@css(select2)
|
||||||
|
@js(select2,autofocus)
|
||||||
|
|
||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
$(document).ready(function() {
|
$(document).ready(function() {
|
||||||
$('#product_id').on('change',function(item) {
|
$('#product_id').on('change',function(item) {
|
||||||
window.location.href = '{{ url('a/product') }}/'+item.target.value;
|
window.location.href = '{{ url('a/product/details') }}/'+item.target.value;
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
<!-- $pdo=Product::class -->
|
<!-- $o = Product::class -->
|
||||||
<div class="row">
|
<div class="row">
|
||||||
@if(count($pdo->services))
|
@if(count($o->services))
|
||||||
<div class="col-7">
|
<div class="col-7">
|
||||||
<table class="table table-hover" id="table">
|
<table class="table table-hover w-100" id="table">
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th>ID</th>
|
<th>ID</th>
|
||||||
@ -17,7 +17,7 @@
|
|||||||
</thead>
|
</thead>
|
||||||
|
|
||||||
<tbody>
|
<tbody>
|
||||||
@foreach ($pdo->services as $so)
|
@foreach ($o->services as $so)
|
||||||
<tr>
|
<tr>
|
||||||
<td><a href="{{ url('u/service',[$so->id]) }}">{{ $so->sid }}</a></td>
|
<td><a href="{{ url('u/service',[$so->id]) }}">{{ $so->sid }}</a></td>
|
||||||
<td>{{ $so->start_at ? $so->start_at->format('Y-m-d') : '-' }}</td>
|
<td>{{ $so->start_at ? $so->start_at->format('Y-m-d') : '-' }}</td>
|
||||||
@ -38,12 +38,24 @@
|
|||||||
@endif
|
@endif
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@pa(datatables,select)
|
|
||||||
|
|
||||||
@section('page-scripts')
|
@section('page-scripts')
|
||||||
|
@css(datatables,bootstrap4|rowgroup|select|searchpanes|searchpanes-left)
|
||||||
|
@js(datatables,bootstrap4|rowgroup|select|searchpanes)
|
||||||
|
|
||||||
|
<style>
|
||||||
|
tr.odd td:first-child,
|
||||||
|
tr.even td:first-child {
|
||||||
|
padding-left: 3em;
|
||||||
|
}
|
||||||
|
table.dataTable tr.dtrg-group.dtrg-level-1 td {
|
||||||
|
background-color: #e0e0e0;
|
||||||
|
color: #4c110f;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
$(document).ready(function() {
|
$(document).ready(function() {
|
||||||
@if(count($pdo->services))
|
@if(count($o->services))
|
||||||
$('#table').DataTable({
|
$('#table').DataTable({
|
||||||
paging: true,
|
paging: true,
|
||||||
pageLength: 25,
|
pageLength: 25,
|
||||||
@ -54,12 +66,34 @@
|
|||||||
autoWidth: false,
|
autoWidth: false,
|
||||||
fixedHeader: true,
|
fixedHeader: true,
|
||||||
order: [[4,'desc'],[0,'asc']],
|
order: [[4,'desc'],[0,'asc']],
|
||||||
|
rowGroup: {
|
||||||
|
dataSrc: 4,
|
||||||
|
},
|
||||||
columnDefs: [
|
columnDefs: [
|
||||||
{
|
{
|
||||||
targets: [4],
|
targets: [4],
|
||||||
visible: false,
|
visible: false,
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
language: {
|
||||||
|
searchPanes: {
|
||||||
|
clearMessage: 'Clear',
|
||||||
|
title: 'Filters: %d',
|
||||||
|
collapse: 'Filter',
|
||||||
|
}
|
||||||
|
},
|
||||||
|
searchPanes: {
|
||||||
|
cascadePanes: true,
|
||||||
|
viewTotal: true,
|
||||||
|
layout: 'columns-1',
|
||||||
|
dataLength: 20,
|
||||||
|
controls: false,
|
||||||
|
},
|
||||||
|
dom: '<"dtsp-verticalContainer"<"dtsp-verticalPanes"P><"dtsp-dataTable"Bfrtip>>',
|
||||||
|
});
|
||||||
|
|
||||||
|
$('tbody').on('click','tr', function () {
|
||||||
|
$(this).toggleClass('selected');
|
||||||
});
|
});
|
||||||
@endif
|
@endif
|
||||||
});
|
});
|
||||||
|
@ -3,6 +3,11 @@
|
|||||||
use Illuminate\Support\Facades\Route;
|
use Illuminate\Support\Facades\Route;
|
||||||
use Intuit\Controllers\Webhook;
|
use Intuit\Controllers\Webhook;
|
||||||
|
|
||||||
|
use App\Http\Controllers\{AccountingController,
|
||||||
|
AdminController,
|
||||||
|
CheckoutController,
|
||||||
|
ProductController};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|--------------------------------------------------------------------------
|
|--------------------------------------------------------------------------
|
||||||
| API Routes
|
| API Routes
|
||||||
@ -14,4 +19,13 @@ use Intuit\Controllers\Webhook;
|
|||||||
|
|
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
// Wholesaler API calls
|
||||||
|
Route::group(['middleware'=>['auth:api','role:wholesaler']], function() {
|
||||||
|
Route::get('a/supplier_products',[ProductController::class,'api_supplier_products']);
|
||||||
|
});
|
||||||
|
|
||||||
|
Route::group(['middleware'=>'auth:api'], function() {
|
||||||
|
Route::any('/intuit/accounting/list',[AccountingController::class,'list']);
|
||||||
|
});
|
||||||
|
|
||||||
Route::any('/intuit/webhook',[Webhook::class,'webhook']);
|
Route::any('/intuit/webhook',[Webhook::class,'webhook']);
|
@ -90,13 +90,11 @@ Route::group(['middleware'=>['auth','role:wholesaler'],'prefix'=>'a'],function()
|
|||||||
->where('o','[0-9]+');
|
->where('o','[0-9]+');
|
||||||
|
|
||||||
// Product Setup
|
// Product Setup
|
||||||
Route::view('product','theme.backend.adminlte.product.home',['breadcrumb'=>collect(['x'=>'foobar'])]);
|
Route::match(['get'],'product',[ProductController::class,'home']);
|
||||||
Route::view('product/{pdo}','theme.backend.adminlte.product.details',['breadcrumb'=>collect(['Products'=>url('a/product')])])
|
Route::get('product/details/{o?}',[ProductController::class,'details'])
|
||||||
->where('pdo','[0-9]+');
|
->where('o','[0-9]+');
|
||||||
Route::post('product/{o?}',[ProductController::class,'addedit'])
|
Route::post('product/details/{o?}',[ProductController::class,'details_addedit'])
|
||||||
->where('o','[0-9]+');
|
->where('o','[0-9]+');
|
||||||
|
|
||||||
Route::get('supplied_products',[ProductController::class,'api_supplied_products']);
|
|
||||||
|
|
||||||
// Supplier Setup
|
// Supplier Setup
|
||||||
Route::get('supplier',[SupplierController::class,'admin_home']);
|
Route::get('supplier',[SupplierController::class,'admin_home']);
|
||||||
@ -129,6 +127,11 @@ Route::group(['middleware'=>['auth','role:wholesaler'],'prefix'=>'a'],function()
|
|||||||
// @todo This should probably go to resellers - implement a change audit log first
|
// @todo This should probably go to resellers - implement a change audit log first
|
||||||
Route::post('service/update/{o}',[ServiceController::class,'update'])
|
Route::post('service/update/{o}',[ServiceController::class,'update'])
|
||||||
->where('o','[0-9]+');
|
->where('o','[0-9]+');
|
||||||
|
|
||||||
|
//@deprecated
|
||||||
|
// Route::get('service/{o}','AdminHomeController@service');
|
||||||
|
// Route::post('service/{o}','AdminHomeController@service_update');
|
||||||
|
// Route::get('accounting/connect','AccountingController@connect');
|
||||||
});
|
});
|
||||||
|
|
||||||
// Our Reseller Routes
|
// Our Reseller Routes
|
||||||
|
Loading…
Reference in New Issue
Block a user