mirror of
https://github.com/invoiceninja/invoiceninja.git
synced 2025-07-09 03:14:30 -04:00
Add credits to the client portal
This commit is contained in:
parent
456ab445c5
commit
5d04bdab21
@ -22,6 +22,7 @@ use App\Ninja\Repositories\InvoiceRepository;
|
|||||||
use App\Ninja\Repositories\PaymentRepository;
|
use App\Ninja\Repositories\PaymentRepository;
|
||||||
use App\Ninja\Repositories\ActivityRepository;
|
use App\Ninja\Repositories\ActivityRepository;
|
||||||
use App\Ninja\Repositories\DocumentRepository;
|
use App\Ninja\Repositories\DocumentRepository;
|
||||||
|
use App\Ninja\Repositories\CreditRepository;
|
||||||
use App\Events\InvoiceInvitationWasViewed;
|
use App\Events\InvoiceInvitationWasViewed;
|
||||||
use App\Events\QuoteInvitationWasViewed;
|
use App\Events\QuoteInvitationWasViewed;
|
||||||
use App\Services\PaymentService;
|
use App\Services\PaymentService;
|
||||||
@ -33,13 +34,14 @@ class ClientPortalController extends BaseController
|
|||||||
private $paymentRepo;
|
private $paymentRepo;
|
||||||
private $documentRepo;
|
private $documentRepo;
|
||||||
|
|
||||||
public function __construct(InvoiceRepository $invoiceRepo, PaymentRepository $paymentRepo, ActivityRepository $activityRepo, DocumentRepository $documentRepo, PaymentService $paymentService)
|
public function __construct(InvoiceRepository $invoiceRepo, PaymentRepository $paymentRepo, ActivityRepository $activityRepo, DocumentRepository $documentRepo, PaymentService $paymentService, CreditRepository $creditRepo)
|
||||||
{
|
{
|
||||||
$this->invoiceRepo = $invoiceRepo;
|
$this->invoiceRepo = $invoiceRepo;
|
||||||
$this->paymentRepo = $paymentRepo;
|
$this->paymentRepo = $paymentRepo;
|
||||||
$this->activityRepo = $activityRepo;
|
$this->activityRepo = $activityRepo;
|
||||||
$this->documentRepo = $documentRepo;
|
$this->documentRepo = $documentRepo;
|
||||||
$this->paymentService = $paymentService;
|
$this->paymentService = $paymentService;
|
||||||
|
$this->creditRepo = $creditRepo;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function view($invitationKey)
|
public function view($invitationKey)
|
||||||
@ -439,6 +441,40 @@ class ClientPortalController extends BaseController
|
|||||||
return $this->invoiceRepo->getClientDatatable($contact->id, ENTITY_QUOTE, Input::get('sSearch'));
|
return $this->invoiceRepo->getClientDatatable($contact->id, ENTITY_QUOTE, Input::get('sSearch'));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function creditIndex()
|
||||||
|
{
|
||||||
|
if (!$contact = $this->getContact()) {
|
||||||
|
return $this->returnError();
|
||||||
|
}
|
||||||
|
|
||||||
|
$account = $contact->account;
|
||||||
|
|
||||||
|
if (!$account->enable_client_portal) {
|
||||||
|
return $this->returnError();
|
||||||
|
}
|
||||||
|
|
||||||
|
$color = $account->primary_color ? $account->primary_color : '#0b4d78';
|
||||||
|
$data = [
|
||||||
|
'color' => $color,
|
||||||
|
'account' => $account,
|
||||||
|
'clientFontUrl' => $account->getFontsUrl(),
|
||||||
|
'title' => trans('texts.credits'),
|
||||||
|
'entityType' => ENTITY_CREDIT,
|
||||||
|
'columns' => Utils::trans(['credit_date', 'credit_amount', 'credit_balance']),
|
||||||
|
];
|
||||||
|
|
||||||
|
return response()->view('public_list', $data);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function creditDatatable()
|
||||||
|
{
|
||||||
|
if (!$contact = $this->getContact()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->creditRepo->getClientDatatable($contact->client_id);
|
||||||
|
}
|
||||||
|
|
||||||
public function documentIndex()
|
public function documentIndex()
|
||||||
{
|
{
|
||||||
if (!$contact = $this->getContact()) {
|
if (!$contact = $this->getContact()) {
|
||||||
|
@ -2,8 +2,10 @@
|
|||||||
|
|
||||||
namespace App\Http\ViewComposers;
|
namespace App\Http\ViewComposers;
|
||||||
|
|
||||||
|
use DB;
|
||||||
use Cache;
|
use Cache;
|
||||||
use Illuminate\View\View;
|
use Illuminate\View\View;
|
||||||
|
use App\Models\Contact;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ClientPortalHeaderComposer.php.
|
* ClientPortalHeaderComposer.php.
|
||||||
@ -21,6 +23,30 @@ class ClientPortalHeaderComposer
|
|||||||
*/
|
*/
|
||||||
public function compose(View $view)
|
public function compose(View $view)
|
||||||
{
|
{
|
||||||
$view->with('testing', 'value');
|
$contactKey = session('contact_key');
|
||||||
|
|
||||||
|
if ( ! $contactKey) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
$contact = Contact::where('contact_key', '=', $contactKey)
|
||||||
|
->with('client')
|
||||||
|
->first();
|
||||||
|
|
||||||
|
if ( ! $contact || $contact->is_deleted) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
$client = $contact->client;
|
||||||
|
|
||||||
|
$hasDocuments = DB::table('invoices')
|
||||||
|
->where('invoices.client_id', '=', $client->id)
|
||||||
|
->whereNull('invoices.deleted_at')
|
||||||
|
->join('documents', 'documents.invoice_id', '=', 'invoices.id')
|
||||||
|
->count();
|
||||||
|
|
||||||
|
$view->with('hasQuotes', $client->quotes->count());
|
||||||
|
$view->with('hasCredits', $client->creditsWithBalance->count());
|
||||||
|
$view->with('hasDocuments', $hasDocuments);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -52,6 +52,7 @@ Route::group(['middleware' => 'auth:client'], function() {
|
|||||||
Route::post('client/payment_methods/default', 'ClientPortalController@setDefaultPaymentMethod');
|
Route::post('client/payment_methods/default', 'ClientPortalController@setDefaultPaymentMethod');
|
||||||
Route::post('client/payment_methods/{source_id}/remove', 'ClientPortalController@removePaymentMethod');
|
Route::post('client/payment_methods/{source_id}/remove', 'ClientPortalController@removePaymentMethod');
|
||||||
Route::get('client/quotes', 'ClientPortalController@quoteIndex');
|
Route::get('client/quotes', 'ClientPortalController@quoteIndex');
|
||||||
|
Route::get('client/credits', 'ClientPortalController@creditIndex');
|
||||||
Route::get('client/invoices', 'ClientPortalController@invoiceIndex');
|
Route::get('client/invoices', 'ClientPortalController@invoiceIndex');
|
||||||
Route::get('client/invoices/recurring', 'ClientPortalController@recurringInvoiceIndex');
|
Route::get('client/invoices/recurring', 'ClientPortalController@recurringInvoiceIndex');
|
||||||
Route::post('client/invoices/auto_bill', 'ClientPortalController@setAutoBill');
|
Route::post('client/invoices/auto_bill', 'ClientPortalController@setAutoBill');
|
||||||
@ -63,6 +64,7 @@ Route::group(['middleware' => 'auth:client'], function() {
|
|||||||
Route::get('client/documents/{invitation_key}/{filename?}', 'ClientPortalController@getInvoiceDocumentsZip');
|
Route::get('client/documents/{invitation_key}/{filename?}', 'ClientPortalController@getInvoiceDocumentsZip');
|
||||||
|
|
||||||
Route::get('api/client.quotes', ['as'=>'api.client.quotes', 'uses'=>'ClientPortalController@quoteDatatable']);
|
Route::get('api/client.quotes', ['as'=>'api.client.quotes', 'uses'=>'ClientPortalController@quoteDatatable']);
|
||||||
|
Route::get('api/client.credits', ['as'=>'api.client.credits', 'uses'=>'ClientPortalController@creditDatatable']);
|
||||||
Route::get('api/client.invoices', ['as'=>'api.client.invoices', 'uses'=>'ClientPortalController@invoiceDatatable']);
|
Route::get('api/client.invoices', ['as'=>'api.client.invoices', 'uses'=>'ClientPortalController@invoiceDatatable']);
|
||||||
Route::get('api/client.recurring_invoices', ['as'=>'api.client.recurring_invoices', 'uses'=>'ClientPortalController@recurringInvoiceDatatable']);
|
Route::get('api/client.recurring_invoices', ['as'=>'api.client.recurring_invoices', 'uses'=>'ClientPortalController@recurringInvoiceDatatable']);
|
||||||
Route::get('api/client.documents', ['as'=>'api.client.documents', 'uses'=>'ClientPortalController@documentDatatable']);
|
Route::get('api/client.documents', ['as'=>'api.client.documents', 'uses'=>'ClientPortalController@documentDatatable']);
|
||||||
|
@ -159,6 +159,14 @@ class Client extends EntityModel
|
|||||||
return $this->hasMany('App\Models\Invoice');
|
return $this->hasMany('App\Models\Invoice');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return \Illuminate\Database\Eloquent\Relations\HasMany
|
||||||
|
*/
|
||||||
|
public function quotes()
|
||||||
|
{
|
||||||
|
return $this->hasMany('App\Models\Invoice')->where('invoice_type_id', '=', INVOICE_TYPE_QUOTE);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return \Illuminate\Database\Eloquent\Relations\HasMany
|
* @return \Illuminate\Database\Eloquent\Relations\HasMany
|
||||||
*/
|
*/
|
||||||
@ -223,6 +231,14 @@ class Client extends EntityModel
|
|||||||
return $this->hasMany('App\Models\Credit');
|
return $this->hasMany('App\Models\Credit');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return \Illuminate\Database\Eloquent\Relations\HasMany
|
||||||
|
*/
|
||||||
|
public function creditsWithBalance()
|
||||||
|
{
|
||||||
|
return $this->hasMany('App\Models\Credit')->where('balance', '>', 0);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return mixed
|
* @return mixed
|
||||||
*/
|
*/
|
||||||
|
@ -58,10 +58,36 @@ class CreditRepository extends BaseRepository
|
|||||||
return $query;
|
return $query;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function getClientDatatable($clientId)
|
||||||
|
{
|
||||||
|
$query = DB::table('credits')
|
||||||
|
->join('accounts', 'accounts.id', '=', 'credits.account_id')
|
||||||
|
->join('clients', 'clients.id', '=', 'credits.client_id')
|
||||||
|
->where('credits.client_id', '=', $clientId)
|
||||||
|
->where('clients.deleted_at', '=', null)
|
||||||
|
->where('credits.deleted_at', '=', null)
|
||||||
|
->where('credits.balance', '>', 0)
|
||||||
|
->select(
|
||||||
|
DB::raw('COALESCE(clients.currency_id, accounts.currency_id) currency_id'),
|
||||||
|
DB::raw('COALESCE(clients.country_id, accounts.country_id) country_id'),
|
||||||
|
'credits.amount',
|
||||||
|
'credits.balance',
|
||||||
|
'credits.credit_date'
|
||||||
|
);
|
||||||
|
|
||||||
|
$table = \Datatable::query($query)
|
||||||
|
->addColumn('credit_date', function ($model) { return Utils::fromSqlDate($model->credit_date); })
|
||||||
|
->addColumn('amount', function ($model) { return Utils::formatMoney($model->amount, $model->currency_id, $model->country_id); })
|
||||||
|
->addColumn('balance', function ($model) { return Utils::formatMoney($model->balance, $model->currency_id, $model->country_id); })
|
||||||
|
->make();
|
||||||
|
|
||||||
|
return $table;
|
||||||
|
}
|
||||||
|
|
||||||
public function save($input, $credit = null)
|
public function save($input, $credit = null)
|
||||||
{
|
{
|
||||||
$publicId = isset($data['public_id']) ? $data['public_id'] : false;
|
$publicId = isset($data['public_id']) ? $data['public_id'] : false;
|
||||||
|
|
||||||
if ($credit) {
|
if ($credit) {
|
||||||
// do nothing
|
// do nothing
|
||||||
} elseif ($publicId) {
|
} elseif ($publicId) {
|
||||||
|
@ -34,7 +34,7 @@ class ComposerServiceProvider extends ServiceProvider
|
|||||||
|
|
||||||
view()->composer(
|
view()->composer(
|
||||||
[
|
[
|
||||||
'invited.dashboard',
|
'public.header'
|
||||||
],
|
],
|
||||||
'App\Http\ViewComposers\ClientPortalHeaderComposer'
|
'App\Http\ViewComposers\ClientPortalHeaderComposer'
|
||||||
);
|
);
|
||||||
|
@ -76,13 +76,17 @@
|
|||||||
{!! link_to('/client/dashboard', trans('texts.dashboard') ) !!}
|
{!! link_to('/client/dashboard', trans('texts.dashboard') ) !!}
|
||||||
</li>
|
</li>
|
||||||
@endif
|
@endif
|
||||||
<li {!! Request::is('*client/quotes') ? 'class="active"' : '' !!}>
|
@if (isset($hasQuotes) && $hasQuotes)
|
||||||
{!! link_to('/client/quotes', trans('texts.quotes') ) !!}
|
<li {!! Request::is('*client/quotes') ? 'class="active"' : '' !!}>
|
||||||
</li>
|
{!! link_to('/client/quotes', trans('texts.quotes') ) !!}
|
||||||
|
</li>
|
||||||
|
@endif
|
||||||
<li {!! Request::is('*client/invoices') ? 'class="active"' : '' !!}>
|
<li {!! Request::is('*client/invoices') ? 'class="active"' : '' !!}>
|
||||||
{!! link_to('/client/invoices', trans('texts.invoices') ) !!}
|
{!! link_to('/client/invoices', trans('texts.invoices') ) !!}
|
||||||
</li>
|
</li>
|
||||||
@if (isset($account) && $account->hasFeature(FEATURE_DOCUMENTS))
|
@if (isset($account)
|
||||||
|
&& $account->hasFeature(FEATURE_DOCUMENTS)
|
||||||
|
&& (isset($hasDocuments) && $hasDocuments))
|
||||||
<li {!! Request::is('*client/documents') ? 'class="active"' : '' !!}>
|
<li {!! Request::is('*client/documents') ? 'class="active"' : '' !!}>
|
||||||
{!! link_to('/client/documents', trans('texts.documents') ) !!}
|
{!! link_to('/client/documents', trans('texts.documents') ) !!}
|
||||||
</li>
|
</li>
|
||||||
@ -95,6 +99,11 @@
|
|||||||
<li {!! Request::is('*client/payments') ? 'class="active"' : '' !!}>
|
<li {!! Request::is('*client/payments') ? 'class="active"' : '' !!}>
|
||||||
{!! link_to('/client/payments', trans('texts.payments') ) !!}
|
{!! link_to('/client/payments', trans('texts.payments') ) !!}
|
||||||
</li>
|
</li>
|
||||||
|
@if (isset($hasCredits) && $hasCredits)
|
||||||
|
<li {!! Request::is('*client/credits') ? 'class="active"' : '' !!}>
|
||||||
|
{!! link_to('/client/credits', trans('texts.credits') ) !!}
|
||||||
|
</li>
|
||||||
|
@endif
|
||||||
</ul>
|
</ul>
|
||||||
@endif
|
@endif
|
||||||
</div><!--/.nav-collapse -->
|
</div><!--/.nav-collapse -->
|
||||||
|
Loading…
x
Reference in New Issue
Block a user