mirror of
https://github.com/invoiceninja/invoiceninja.git
synced 2025-06-23 20:00:33 -04:00
Working on invoice creation
This commit is contained in:
parent
ebdfa54489
commit
9053be4976
@ -309,7 +309,7 @@ class AccountController extends \BaseController {
|
|||||||
'email' => Contact::$fieldEmail,
|
'email' => Contact::$fieldEmail,
|
||||||
'mobile' => Contact::$fieldPhone,
|
'mobile' => Contact::$fieldPhone,
|
||||||
'phone' => Client::$fieldPhone,
|
'phone' => Client::$fieldPhone,
|
||||||
'name' => Client::$fieldName,
|
'name|organization' => Client::$fieldName,
|
||||||
'address|address1' => Client::$fieldAddress1,
|
'address|address1' => Client::$fieldAddress1,
|
||||||
'address2' => Client::$fieldAddress2,
|
'address2' => Client::$fieldAddress2,
|
||||||
'city' => Client::$fieldCity,
|
'city' => Client::$fieldCity,
|
||||||
|
@ -7,7 +7,7 @@ class ActivityController extends \BaseController {
|
|||||||
$clientId = Client::getPrivateId($clientPublicId);
|
$clientId = Client::getPrivateId($clientPublicId);
|
||||||
|
|
||||||
return Datatable::collection(Activity::scope()->where('client_id','=',$clientId)->get())
|
return Datatable::collection(Activity::scope()->where('client_id','=',$clientId)->get())
|
||||||
->addColumn('date', function($model) { return timestampToDateTimeString($model->created_at); })
|
->addColumn('date', function($model) { return timestampToDateString($model->created_at); })
|
||||||
->addColumn('message', function($model) { return $model->message; })
|
->addColumn('message', function($model) { return $model->message; })
|
||||||
->addColumn('balance', function($model) { return '$' . $model->balance; })
|
->addColumn('balance', function($model) { return '$' . $model->balance; })
|
||||||
->orderColumns('date')
|
->orderColumns('date')
|
||||||
|
@ -21,16 +21,21 @@ class ClientController extends \BaseController {
|
|||||||
|
|
||||||
public function getDatatable()
|
public function getDatatable()
|
||||||
{
|
{
|
||||||
$query = DB::table('clients')->join('contacts', 'clients.id', '=','contacts.client_id')->where('contacts.is_primary', '=', true);
|
$query = DB::table('clients')
|
||||||
|
->join('contacts', 'contacts.client_id', '=', 'clients.id')
|
||||||
|
->where('clients.account_id', '=', Auth::user()->account_id)
|
||||||
|
->where('clients.deleted_at', '=', null)
|
||||||
|
->where('contacts.is_primary', '=', true)
|
||||||
|
->select('clients.public_id','clients.name','contacts.first_name','contacts.last_name','clients.balance','clients.last_login','clients.created_at','contacts.phone','contacts.email');
|
||||||
|
|
||||||
return Datatable::query($query)
|
return Datatable::query($query)
|
||||||
->addColumn('checkbox', function($model) { return '<input type="checkbox" name="ids[]" value="' . $model->public_id . '">'; })
|
->addColumn('checkbox', function($model) { return '<input type="checkbox" name="ids[]" value="' . $model->public_id . '">'; })
|
||||||
->addColumn('name', function($model) { return link_to('clients/' . $model->public_id, $model->name); })
|
->addColumn('name', function($model) { return link_to('clients/' . $model->public_id, $model->name); })
|
||||||
->addColumn('first_name', function($model) { return $model->first_name . ' ' . $model->last_name; })
|
->addColumn('first_name', function($model) { return $model->first_name . ' ' . $model->last_name; })
|
||||||
->addColumn('balance', function($model) { return '$' . $model->balance; })
|
->addColumn('balance', function($model) { return '$' . $model->balance; })
|
||||||
->addColumn('clients.last_login', function($model) { return timestampToDateString($model->last_login); })
|
->addColumn('last_login', function($model) { return timestampToDateString($model->last_login); })
|
||||||
->addColumn('clients.created_at', function($model) { return timestampToDateString($model->created_at); })
|
->addColumn('created_at', function($model) { return timestampToDateString($model->created_at); })
|
||||||
->addColumn('email', function($model) { return HTML::mailto($model->email, $model->email); })
|
->addColumn('email', function($model) { return $model->email ? HTML::mailto($model->email, $model->email) : ''; })
|
||||||
->addColumn('phone', function($model) { return $model->phone; })
|
->addColumn('phone', function($model) { return $model->phone; })
|
||||||
->addColumn('dropdown', function($model)
|
->addColumn('dropdown', function($model)
|
||||||
{
|
{
|
||||||
@ -47,7 +52,7 @@ class ClientController extends \BaseController {
|
|||||||
</ul>
|
</ul>
|
||||||
</div>';
|
</div>';
|
||||||
})
|
})
|
||||||
->orderColumns('name','first_name','balance','clients.last_login','clients.created_at','email','phone')
|
->orderColumns('name','first_name','balance','last_login','created_at','email','phone')
|
||||||
->make();
|
->make();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -200,8 +205,7 @@ class ClientController extends \BaseController {
|
|||||||
public function bulk()
|
public function bulk()
|
||||||
{
|
{
|
||||||
$action = Input::get('action');
|
$action = Input::get('action');
|
||||||
$ids = Input::get('ids') ? Input::get('ids') : [Input::get('id')];
|
$ids = Input::get('id') ? Input::get('id') : Input::get('ids');
|
||||||
|
|
||||||
$clients = Client::scope($ids)->get();
|
$clients = Client::scope($ids)->get();
|
||||||
|
|
||||||
foreach ($clients as $client) {
|
foreach ($clients as $client) {
|
||||||
|
@ -18,25 +18,28 @@ class CreditController extends \BaseController {
|
|||||||
|
|
||||||
public function getDatatable($clientPublicId = null)
|
public function getDatatable($clientPublicId = null)
|
||||||
{
|
{
|
||||||
$collection = Credit::scope()->with('client');
|
$query = DB::table('credits')
|
||||||
|
->join('clients', 'clients.id', '=','credits.client_id')
|
||||||
|
->where('clients.account_id', '=', Auth::user()->account_id)
|
||||||
|
->where('clients.deleted_at', '=', null)
|
||||||
|
->select('credits.public_id', 'clients.name as client_name', 'clients.public_id as client_public_id', 'credits.amount', 'credits.credit_date');
|
||||||
|
|
||||||
if ($clientPublicId) {
|
if ($clientPublicId) {
|
||||||
$clientId = Client::getPrivateId($clientPublicId);
|
$query->where('clients.public_id', '=', $clientPublicId);
|
||||||
$collection->where('client_id','=',$clientId);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$table = Datatable::collection($collection->get());
|
$table = Datatable::query($query);
|
||||||
|
|
||||||
if (!$clientPublicId) {
|
if (!$clientPublicId) {
|
||||||
$table->addColumn('checkbox', function($model) { return '<input type="checkbox" name="ids[]" value="' . $model->public_id . '">'; })
|
$table->addColumn('checkbox', function($model) { return '<input type="checkbox" name="ids[]" value="' . $model->public_id . '">'; })
|
||||||
->addColumn('client', function($model) { return link_to('clients/' . $model->client->public_id, $model->client->name); });
|
->addColumn('client_name', function($model) { return link_to('clients/' . $model->client_public_id, $model->client_name); });
|
||||||
}
|
}
|
||||||
|
|
||||||
return $table->addColumn('amount', function($model){ return '$' . money_format('%i', $model->amount); })
|
return $table->addColumn('amount', function($model){ return '$' . money_format('%i', $model->amount); })
|
||||||
->addColumn('credit_date', function($model) { return (new Carbon($model->credit_date))->toFormattedDateString(); })
|
->addColumn('credit_date', function($model) { return timestampToDateString($model->credit_date); })
|
||||||
->addColumn('dropdown', function($model)
|
->addColumn('dropdown', function($model)
|
||||||
{
|
{
|
||||||
return '<div class="btn-group tr-action" style="display:none">
|
return '<div class="btn-group tr-action" style="visibility:hidden;">
|
||||||
<button type="button" class="btn btn-xs btn-default dropdown-toggle" data-toggle="dropdown">
|
<button type="button" class="btn btn-xs btn-default dropdown-toggle" data-toggle="dropdown">
|
||||||
Select <span class="caret"></span>
|
Select <span class="caret"></span>
|
||||||
</button>
|
</button>
|
||||||
@ -123,7 +126,7 @@ class CreditController extends \BaseController {
|
|||||||
public function bulk()
|
public function bulk()
|
||||||
{
|
{
|
||||||
$action = Input::get('action');
|
$action = Input::get('action');
|
||||||
$ids = Input::get('ids');
|
$ids = Input::get('id') ? Input::get('id') : Input::get('ids');
|
||||||
$credits = Credit::scope($ids)->get();
|
$credits = Credit::scope($ids)->get();
|
||||||
|
|
||||||
foreach ($credits as $credit) {
|
foreach ($credits as $credit) {
|
||||||
|
@ -20,19 +20,17 @@ class InvoiceController extends \BaseController {
|
|||||||
{
|
{
|
||||||
$query = DB::table('invoices')
|
$query = DB::table('invoices')
|
||||||
->join('clients', 'clients.id', '=','invoices.client_id')
|
->join('clients', 'clients.id', '=','invoices.client_id')
|
||||||
->join('invoice_statuses', 'invoice_statuses.id', '=', 'invoices.invoice_status_id');
|
->join('invoice_statuses', 'invoice_statuses.id', '=', 'invoices.invoice_status_id')
|
||||||
//->select('clients.public_id as client_public_id', 'invoice_number', 'clients.name', 'invoices.public_id', 'total', 'invoices.balance', 'invoice_date', 'due_date');
|
->where('invoices.account_id', '=', Auth::user()->account_id)
|
||||||
//dd($query->get());
|
->where('invoices.deleted_at', '=', null)
|
||||||
|
->select('clients.public_id as client_public_id', 'invoice_number', 'clients.name as client_name', 'invoices.public_id', 'total', 'invoices.balance', 'invoice_date', 'due_date', 'invoice_statuses.name as invoice_status_name');
|
||||||
|
|
||||||
if ($clientPublicId) {
|
if ($clientPublicId) {
|
||||||
$query->where('clients.public_id', '=', $clientPublicId);
|
$query->where('clients.public_id', '=', $clientPublicId);
|
||||||
//$clientId = Client::getPrivateId($clientPublicId);
|
|
||||||
//$collection->where('client_id','=',$clientId);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$table = Datatable::query($query);
|
$table = Datatable::query($query);
|
||||||
|
|
||||||
|
|
||||||
if (!$clientPublicId) {
|
if (!$clientPublicId) {
|
||||||
$table->addColumn('checkbox', function($model) { return '<input type="checkbox" name="ids[]" value="' . $model->public_id . '">'; });
|
$table->addColumn('checkbox', function($model) { return '<input type="checkbox" name="ids[]" value="' . $model->public_id . '">'; });
|
||||||
}
|
}
|
||||||
@ -40,17 +38,17 @@ class InvoiceController extends \BaseController {
|
|||||||
$table->addColumn('invoice_number', function($model) { return link_to('invoices/' . $model->public_id . '/edit', $model->invoice_number); });
|
$table->addColumn('invoice_number', function($model) { return link_to('invoices/' . $model->public_id . '/edit', $model->invoice_number); });
|
||||||
|
|
||||||
if (!$clientPublicId) {
|
if (!$clientPublicId) {
|
||||||
//$table->addColumn('client', function($model) { dd($model); return link_to('clients/' . $model->client_public_id, $model->client_name); });
|
$table->addColumn('client', function($model) { return link_to('clients/' . $model->client_public_id, $model->client_name); });
|
||||||
}
|
}
|
||||||
|
|
||||||
return $table->addColumn('total', function($model){ return '$' . money_format('%i', $model->total); })
|
return $table->addColumn('total', function($model){ return '$' . money_format('%i', $model->total); })
|
||||||
->addColumn('invoices.balance', function($model) { return '$' . money_format('%i', $model->balance); })
|
->addColumn('balance', function($model) { return '$' . money_format('%i', $model->balance); })
|
||||||
->addColumn('invoice_date', function($model) { return fromSqlDate($model->invoice_date); })
|
->addColumn('invoice_date', function($model) { return fromSqlDate($model->invoice_date); })
|
||||||
->addColumn('due_date', function($model) { return fromSqlDate($model->due_date); })
|
->addColumn('due_date', function($model) { return fromSqlDate($model->due_date); })
|
||||||
//->addColumn('status', function($model) { return $model->invoice_status->name; })
|
->addColumn('invoice_status_name', function($model) { return $model->invoice_status_name; })
|
||||||
->addColumn('dropdown', function($model)
|
->addColumn('dropdown', function($model)
|
||||||
{
|
{
|
||||||
return '<div class="btn-group tr-action" style="display:none">
|
return '<div class="btn-group tr-action" style="visibility:hidden;">
|
||||||
<button type="button" class="btn btn-xs btn-default dropdown-toggle" data-toggle="dropdown">
|
<button type="button" class="btn btn-xs btn-default dropdown-toggle" data-toggle="dropdown">
|
||||||
Select <span class="caret"></span>
|
Select <span class="caret"></span>
|
||||||
</button>
|
</button>
|
||||||
@ -62,7 +60,7 @@ class InvoiceController extends \BaseController {
|
|||||||
</ul>
|
</ul>
|
||||||
</div>';
|
</div>';
|
||||||
})
|
})
|
||||||
->orderColumns('number')
|
->orderColumns('invoice_number','client','total','balance','invoice_date','due_date','invoice_status_name')
|
||||||
->make();
|
->make();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -228,6 +226,7 @@ class InvoiceController extends \BaseController {
|
|||||||
'title' => '- ' . $invoice->invoice_number,
|
'title' => '- ' . $invoice->invoice_number,
|
||||||
'account' => Auth::user()->account,
|
'account' => Auth::user()->account,
|
||||||
'products' => Product::scope()->get(array('product_key','notes','cost','qty')),
|
'products' => Product::scope()->get(array('product_key','notes','cost','qty')),
|
||||||
|
'countries' => Country::orderBy('name')->get(),
|
||||||
'client' => $invoice->client,
|
'client' => $invoice->client,
|
||||||
'clients' => Client::scope()->orderBy('name')->get());
|
'clients' => Client::scope()->orderBy('name')->get());
|
||||||
return View::make('invoices.edit', $data);
|
return View::make('invoices.edit', $data);
|
||||||
@ -252,6 +251,7 @@ class InvoiceController extends \BaseController {
|
|||||||
'title' => '- New Invoice',
|
'title' => '- New Invoice',
|
||||||
'client' => $client,
|
'client' => $client,
|
||||||
'items' => json_decode(Input::old('items')),
|
'items' => json_decode(Input::old('items')),
|
||||||
|
'countries' => Country::orderBy('name')->get(),
|
||||||
'account' => Auth::user()->account,
|
'account' => Auth::user()->account,
|
||||||
'products' => Product::scope()->get(array('product_key','notes','cost','qty')),
|
'products' => Product::scope()->get(array('product_key','notes','cost','qty')),
|
||||||
'clients' => Client::scope()->orderBy('name')->get());
|
'clients' => Client::scope()->orderBy('name')->get());
|
||||||
@ -272,13 +272,9 @@ class InvoiceController extends \BaseController {
|
|||||||
{
|
{
|
||||||
$action = Input::get('action');
|
$action = Input::get('action');
|
||||||
|
|
||||||
if ($action == 'archive')
|
if ($action == 'archive' || $action == 'delete')
|
||||||
{
|
{
|
||||||
return InvoiceController::archive($publicId);
|
return InvoiceController::bulk();
|
||||||
}
|
|
||||||
else if ($action == 'delete')
|
|
||||||
{
|
|
||||||
return InvoiceController::delete($publicId);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$rules = array(
|
$rules = array(
|
||||||
@ -299,12 +295,25 @@ class InvoiceController extends \BaseController {
|
|||||||
if ($clientPublicId == "-1")
|
if ($clientPublicId == "-1")
|
||||||
{
|
{
|
||||||
$client = Client::createNew();
|
$client = Client::createNew();
|
||||||
$client->name = Input::get('client_name');
|
$client->name = Input::get('name');
|
||||||
|
$client->work_phone = Input::get('work_phone');
|
||||||
|
$client->address1 = Input::get('address1');
|
||||||
|
$client->address2 = Input::get('address2');
|
||||||
|
$client->city = Input::get('city');
|
||||||
|
$client->state = Input::get('state');
|
||||||
|
$client->postal_code = Input::get('postal_code');
|
||||||
|
if (Input::get('country_id')) {
|
||||||
|
$client->country_id = Input::get('country_id');
|
||||||
|
}
|
||||||
$client->save();
|
$client->save();
|
||||||
$clientId = $client->id;
|
$clientId = $client->id;
|
||||||
|
|
||||||
$contact = Contact::createNew();
|
$contact = Contact::createNew();
|
||||||
$contact->email = Input::get('client_email');
|
$contact->is_primary = true;
|
||||||
|
$contact->first_name = Input::get('first_name');
|
||||||
|
$contact->last_name = Input::get('last_name');
|
||||||
|
$contact->phone = Input::get('phone');
|
||||||
|
$contact->email = Input::get('email');
|
||||||
$client->contacts()->save($contact);
|
$client->contacts()->save($contact);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -328,14 +337,12 @@ class InvoiceController extends \BaseController {
|
|||||||
$client->invoices()->save($invoice);
|
$client->invoices()->save($invoice);
|
||||||
|
|
||||||
$items = json_decode(Input::get('items'));
|
$items = json_decode(Input::get('items'));
|
||||||
foreach ($items as $item) {
|
foreach ($items as $item)
|
||||||
|
{
|
||||||
if (!isset($item->cost))
|
if (!isset($item->cost)) {
|
||||||
{
|
|
||||||
$item->cost = 0;
|
$item->cost = 0;
|
||||||
}
|
}
|
||||||
if (!isset($item->qty))
|
if (!isset($item->qty)) {
|
||||||
{
|
|
||||||
$item->qty = 0;
|
$item->qty = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -432,7 +439,7 @@ class InvoiceController extends \BaseController {
|
|||||||
public function bulk()
|
public function bulk()
|
||||||
{
|
{
|
||||||
$action = Input::get('action');
|
$action = Input::get('action');
|
||||||
$ids = Input::get('ids');
|
$ids = Input::get('id') ? Input::get('id') : Input::get('ids');
|
||||||
$invoices = Invoice::scope($ids)->get();
|
$invoices = Invoice::scope($ids)->get();
|
||||||
|
|
||||||
foreach ($invoices as $invoice) {
|
foreach ($invoices as $invoice) {
|
||||||
@ -448,3 +455,4 @@ class InvoiceController extends \BaseController {
|
|||||||
|
|
||||||
return Redirect::to('invoices');
|
return Redirect::to('invoices');
|
||||||
}
|
}
|
||||||
|
}
|
@ -13,14 +13,18 @@ class PaymentController extends \BaseController
|
|||||||
|
|
||||||
public function getDatatable($clientPublicId = null)
|
public function getDatatable($clientPublicId = null)
|
||||||
{
|
{
|
||||||
$collection = Payment::scope()->with('invoice', 'client');
|
$query = DB::table('payments')
|
||||||
|
->join('clients', 'clients.id', '=','payments.client_id')
|
||||||
|
->leftJoin('invoices', 'invoices.id', '=','payments.invoice_id')
|
||||||
|
->where('payments.account_id', '=', Auth::user()->account_id)
|
||||||
|
->where('payments.deleted_at', '=', null)
|
||||||
|
->select('payments.public_id', 'payments.transaction_reference', 'clients.name as client_name', 'clients.public_id as client_public_id', 'payments.amount', 'payments.payment_date', 'invoices.public_id as invoice_public_id', 'invoices.invoice_number');
|
||||||
|
|
||||||
if ($clientPublicId) {
|
if ($clientPublicId) {
|
||||||
$clientId = Client::getPrivateId($clientPublicId);
|
$query->where('clients.public_id', '=', $clientPublicId);
|
||||||
$collection->where('client_id','=',$clientId);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$table = Datatable::collection($collection->get());
|
$table = Datatable::query($query);
|
||||||
|
|
||||||
if (!$clientPublicId) {
|
if (!$clientPublicId) {
|
||||||
$table->addColumn('checkbox', function($model) { return '<input type="checkbox" name="ids[]" value="' . $model->public_id . '">'; });
|
$table->addColumn('checkbox', function($model) { return '<input type="checkbox" name="ids[]" value="' . $model->public_id . '">'; });
|
||||||
@ -29,15 +33,15 @@ class PaymentController extends \BaseController
|
|||||||
$table->addColumn('transaction_reference', function($model) { return $model->transaction_reference ? $model->transaction_reference : '<i>Manual entry</i>'; });
|
$table->addColumn('transaction_reference', function($model) { return $model->transaction_reference ? $model->transaction_reference : '<i>Manual entry</i>'; });
|
||||||
|
|
||||||
if (!$clientPublicId) {
|
if (!$clientPublicId) {
|
||||||
$table->addColumn('client', function($model) { return link_to('clients/' . $model->client->public_id, $model->client->name); });
|
$table->addColumn('client_name', function($model) { return link_to('clients/' . $model->client_public_id, $model->client_name); });
|
||||||
}
|
}
|
||||||
|
|
||||||
return $table->addColumn('invoice_number', function($model) { return $model->invoice ? link_to('invoices/' . $model->invoice->public_id . '/edit', $model->invoice->invoice_number) : ''; })
|
return $table->addColumn('invoice_number', function($model) { return $model->invoice_public_id ? link_to('invoices/' . $model->invoice_public_id . '/edit', $model->invoice_invoice_number) : ''; })
|
||||||
->addColumn('amount', function($model) { return '$' . $model->amount; })
|
->addColumn('amount', function($model) { return '$' . $model->amount; })
|
||||||
->addColumn('date', function($model) { return timestampToDateTimeString($model->created_at); })
|
->addColumn('payment_date', function($model) { return timestampToDateString($model->payment_date); })
|
||||||
->addColumn('dropdown', function($model)
|
->addColumn('dropdown', function($model)
|
||||||
{
|
{
|
||||||
return '<div class="btn-group tr-action" style="display:none">
|
return '<div class="btn-group tr-action" style="visibility:hidden;">
|
||||||
<button type="button" class="btn btn-xs btn-default dropdown-toggle" data-toggle="dropdown">
|
<button type="button" class="btn btn-xs btn-default dropdown-toggle" data-toggle="dropdown">
|
||||||
Select <span class="caret"></span>
|
Select <span class="caret"></span>
|
||||||
</button>
|
</button>
|
||||||
@ -49,7 +53,7 @@ class PaymentController extends \BaseController
|
|||||||
</ul>
|
</ul>
|
||||||
</div>';
|
</div>';
|
||||||
})
|
})
|
||||||
->orderColumns('client')
|
->orderColumns('transaction_reference', 'client_name', 'invoice_number', 'amount', 'payment_date')
|
||||||
->make();
|
->make();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -131,7 +135,7 @@ class PaymentController extends \BaseController
|
|||||||
public function bulk()
|
public function bulk()
|
||||||
{
|
{
|
||||||
$action = Input::get('action');
|
$action = Input::get('action');
|
||||||
$ids = Input::get('ids');
|
$ids = Input::get('id') ? Input::get('id') : Input::get('ids');
|
||||||
$payments = Payment::scope($ids)->get();
|
$payments = Payment::scope($ids)->get();
|
||||||
|
|
||||||
foreach ($payments as $payment) {
|
foreach ($payments as $payment) {
|
||||||
|
@ -79,7 +79,7 @@ class Account extends Eloquent
|
|||||||
|
|
||||||
public function getNextInvoiceNumber()
|
public function getNextInvoiceNumber()
|
||||||
{
|
{
|
||||||
$order = Invoice::scope()->orderBy('invoice_number', 'DESC')->first();
|
$order = Invoice::withTrashed()->scope()->orderBy('invoice_number', 'DESC')->first();
|
||||||
|
|
||||||
if ($order)
|
if ($order)
|
||||||
{
|
{
|
||||||
|
@ -11,6 +11,7 @@
|
|||||||
|
|
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
//dd(DB::getQueryLog());
|
||||||
//dd(Client::getPrivateId(1));
|
//dd(Client::getPrivateId(1));
|
||||||
|
|
||||||
Route::get('/', 'HomeController@showWelcome');
|
Route::get('/', 'HomeController@showWelcome');
|
||||||
@ -48,10 +49,12 @@ Route::group(array('before' => 'auth'), function()
|
|||||||
Route::get('invoices/create/{client_id}', 'InvoiceController@create');
|
Route::get('invoices/create/{client_id}', 'InvoiceController@create');
|
||||||
Route::post('invoices/bulk', 'InvoiceController@bulk');
|
Route::post('invoices/bulk', 'InvoiceController@bulk');
|
||||||
|
|
||||||
|
Route::get('payments/{id}/edit', function() { return View::make('header'); });
|
||||||
Route::resource('payments', 'PaymentController');
|
Route::resource('payments', 'PaymentController');
|
||||||
Route::get('api/payments/{client_id?}', array('as'=>'api.payments', 'uses'=>'PaymentController@getDatatable'));
|
Route::get('api/payments/{client_id?}', array('as'=>'api.payments', 'uses'=>'PaymentController@getDatatable'));
|
||||||
Route::post('payments/bulk', 'PaymentController@bulk');
|
Route::post('payments/bulk', 'PaymentController@bulk');
|
||||||
|
|
||||||
|
Route::get('credits/{id}/edit', function() { return View::make('header'); });
|
||||||
Route::resource('credits', 'CreditController');
|
Route::resource('credits', 'CreditController');
|
||||||
Route::get('api/credits/{client_id?}', array('as'=>'api.credits', 'uses'=>'CreditController@getDatatable'));
|
Route::get('api/credits/{client_id?}', array('as'=>'api.credits', 'uses'=>'CreditController@getDatatable'));
|
||||||
Route::post('credits/bulk', 'PaymentController@bulk');
|
Route::post('credits/bulk', 'PaymentController@bulk');
|
||||||
|
97
app/views/client.blade.php
Executable file
97
app/views/client.blade.php
Executable file
@ -0,0 +1,97 @@
|
|||||||
|
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-md-6">
|
||||||
|
|
||||||
|
{{ Former::legend('Organization') }}
|
||||||
|
{{ Former::text('name') }}
|
||||||
|
{{ Former::text('work_phone')->label('Phone') }}
|
||||||
|
{{ Former::textarea('notes') }}
|
||||||
|
|
||||||
|
|
||||||
|
{{ Former::legend('Address') }}
|
||||||
|
{{ Former::text('address1')->label('Street') }}
|
||||||
|
{{ Former::text('address2')->label('Apt/Floor') }}
|
||||||
|
{{ Former::text('city') }}
|
||||||
|
{{ Former::text('state') }}
|
||||||
|
{{ Former::text('postal_code') }}
|
||||||
|
{{ Former::select('country_id')->addOption('','')->label('Country')
|
||||||
|
->fromQuery($countries, 'name', 'id')->select($client ? $client->country_id : '') }}
|
||||||
|
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<div class="col-md-6">
|
||||||
|
|
||||||
|
{{ Former::legend('Contacts') }}
|
||||||
|
<div data-bind='template: { foreach: contacts,
|
||||||
|
beforeRemove: hideContact,
|
||||||
|
afterAdd: showContact }'>
|
||||||
|
{{ Former::hidden('public_id')->data_bind("value: public_id, valueUpdate: 'afterkeydown'") }}
|
||||||
|
{{ Former::text('first_name')->data_bind("value: first_name, valueUpdate: 'afterkeydown'") }}
|
||||||
|
{{ Former::text('last_name')->data_bind("value: last_name, valueUpdate: 'afterkeydown'") }}
|
||||||
|
{{ Former::text('email')->data_bind("value: email, valueUpdate: 'afterkeydown'") }}
|
||||||
|
{{ Former::text('phone')->data_bind("value: phone, valueUpdate: 'afterkeydown'") }}
|
||||||
|
|
||||||
|
<div class="form-group">
|
||||||
|
<div class="col-lg-8 col-lg-offset-4">
|
||||||
|
<span data-bind="visible: $parent.contacts().length > 1">
|
||||||
|
{{ link_to('#', 'Remove contact', array('data-bind'=>'click: $parent.removeContact')) }}
|
||||||
|
</span>
|
||||||
|
<span data-bind="visible: $index() === ($parent.contacts().length - 1)" class="pull-right">
|
||||||
|
{{ link_to('#', 'Add contact', array('onclick'=>'return addContact()')) }}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
{{ Former::hidden('data')->data_bind("value: ko.toJSON(model)") }}
|
||||||
|
|
||||||
|
<script type="text/javascript">
|
||||||
|
|
||||||
|
$(function() {
|
||||||
|
$('#country_id').combobox();
|
||||||
|
});
|
||||||
|
|
||||||
|
function ContactModel() {
|
||||||
|
var self = this;
|
||||||
|
self.public_id = ko.observable('');
|
||||||
|
self.first_name = ko.observable('');
|
||||||
|
self.last_name = ko.observable('');
|
||||||
|
self.email = ko.observable('');
|
||||||
|
self.phone = ko.observable('');
|
||||||
|
}
|
||||||
|
|
||||||
|
function ContactsModel() {
|
||||||
|
var self = this;
|
||||||
|
self.contacts = ko.observableArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
@if ($client)
|
||||||
|
window.model = ko.mapping.fromJS({{ $client }});
|
||||||
|
@else
|
||||||
|
window.model = new ContactsModel();
|
||||||
|
addContact();
|
||||||
|
@endif
|
||||||
|
|
||||||
|
model.showContact = function(elem) { if (elem.nodeType === 1) $(elem).hide().slideDown() }
|
||||||
|
model.hideContact = function(elem) { if (elem.nodeType === 1) $(elem).slideUp(function() { $(elem).remove(); }) }
|
||||||
|
|
||||||
|
|
||||||
|
ko.applyBindings(model);
|
||||||
|
|
||||||
|
function addContact() {
|
||||||
|
model.contacts.push(new ContactModel());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
model.removeContact = function() {
|
||||||
|
model.contacts.remove(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
@ -70,13 +70,6 @@
|
|||||||
|
|
||||||
{{ Former::hidden('data')->data_bind("value: ko.toJSON(model)") }}
|
{{ Former::hidden('data')->data_bind("value: ko.toJSON(model)") }}
|
||||||
|
|
||||||
<center style="margin-top:16px">
|
|
||||||
{{ Button::lg_primary_submit('Save') }} |
|
|
||||||
{{ link_to('clients/' . ($client ? $client->public_id : ''), 'Cancel') }}
|
|
||||||
</center>
|
|
||||||
|
|
||||||
{{ Former::close() }}
|
|
||||||
|
|
||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
|
|
||||||
$(function() {
|
$(function() {
|
||||||
@ -105,7 +98,7 @@
|
|||||||
@endif
|
@endif
|
||||||
|
|
||||||
model.showContact = function(elem) { if (elem.nodeType === 1) $(elem).hide().slideDown() }
|
model.showContact = function(elem) { if (elem.nodeType === 1) $(elem).hide().slideDown() }
|
||||||
model.hideContact = function(elem) { if (elem.nodeType === 1) $(elem).slideUp(function() { $(elem).remove(); }) }
|
model.hideContact = function(elem) { if (elem.nodeType === 1) $(elem).slideUp(function() { $(elem).remove(); }) }
|
||||||
|
|
||||||
|
|
||||||
ko.applyBindings(model);
|
ko.applyBindings(model);
|
||||||
@ -122,4 +115,13 @@
|
|||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<center style="margin-top:16px">
|
||||||
|
{{ Button::lg_primary_submit('Save') }} |
|
||||||
|
{{ link_to('clients/' . ($client ? $client->public_id : ''), 'Cancel') }}
|
||||||
|
</center>
|
||||||
|
|
||||||
|
{{ Former::close() }}
|
||||||
|
|
||||||
@stop
|
@stop
|
@ -73,7 +73,7 @@
|
|||||||
->setUrl(url('api/activities/'. $client->public_id))
|
->setUrl(url('api/activities/'. $client->public_id))
|
||||||
->setOptions('sPaginationType', 'bootstrap')
|
->setOptions('sPaginationType', 'bootstrap')
|
||||||
->setOptions('bFilter', false)
|
->setOptions('bFilter', false)
|
||||||
->render() }}
|
->render('datatable') }}
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@ -84,7 +84,7 @@
|
|||||||
->setUrl(url('api/invoices/' . $client->public_id))
|
->setUrl(url('api/invoices/' . $client->public_id))
|
||||||
->setOptions('sPaginationType', 'bootstrap')
|
->setOptions('sPaginationType', 'bootstrap')
|
||||||
->setOptions('bFilter', false)
|
->setOptions('bFilter', false)
|
||||||
->render() }}
|
->render('datatable') }}
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
<div class="tab-pane" id="payments">
|
<div class="tab-pane" id="payments">
|
||||||
@ -94,7 +94,7 @@
|
|||||||
->setUrl(url('api/payments/' . $client->public_id))
|
->setUrl(url('api/payments/' . $client->public_id))
|
||||||
->setOptions('sPaginationType', 'bootstrap')
|
->setOptions('sPaginationType', 'bootstrap')
|
||||||
->setOptions('bFilter', false)
|
->setOptions('bFilter', false)
|
||||||
->render() }}
|
->render('datatable') }}
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
<div class="tab-pane" id="credits">
|
<div class="tab-pane" id="credits">
|
||||||
@ -104,7 +104,7 @@
|
|||||||
->setUrl(url('api/credits/' . $client->public_id))
|
->setUrl(url('api/credits/' . $client->public_id))
|
||||||
->setOptions('sPaginationType', 'bootstrap')
|
->setOptions('sPaginationType', 'bootstrap')
|
||||||
->setOptions('bFilter', false)
|
->setOptions('bFilter', false)
|
||||||
->render() }}
|
->render('datatable') }}
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
<tr>
|
<tr>
|
||||||
@foreach($columns as $i => $c)
|
@foreach($columns as $i => $c)
|
||||||
<th align="center" valign="middle" class="head{{ $i }}">
|
<th align="center" valign="middle" class="head{{ $i }}">
|
||||||
@if ($c == 'checkbox' && $haeCheckboxes = true)
|
@if ($c == 'checkbox' && $hasCheckboxes = true)
|
||||||
<input type="checkbox" id="selectAll"/>
|
<input type="checkbox" id="selectAll"/>
|
||||||
@else
|
@else
|
||||||
{{ $c }}
|
{{ $c }}
|
||||||
@ -32,7 +32,7 @@
|
|||||||
// dynamic table
|
// dynamic table
|
||||||
jQuery('.{{ $class }}').dataTable({
|
jQuery('.{{ $class }}').dataTable({
|
||||||
// Disable sorting on the first column
|
// Disable sorting on the first column
|
||||||
@if ($haeCheckboxes)
|
@if (isset($haeCheckboxes) && $hasCheckboxes)
|
||||||
"aoColumnDefs" : [ {
|
"aoColumnDefs" : [ {
|
||||||
'bSortable' : false,
|
'bSortable' : false,
|
||||||
'aTargets' : [ 0 ]
|
'aTargets' : [ 0 ]
|
||||||
|
@ -4,7 +4,6 @@
|
|||||||
|
|
||||||
<p> </p>
|
<p> </p>
|
||||||
|
|
||||||
|
|
||||||
{{ Former::open($url)->method($method)->addClass('main_form')->rules(array(
|
{{ Former::open($url)->method($method)->addClass('main_form')->rules(array(
|
||||||
'invoice_number' => 'required',
|
'invoice_number' => 'required',
|
||||||
'invoice_date' => 'required',
|
'invoice_date' => 'required',
|
||||||
@ -15,6 +14,7 @@
|
|||||||
|
|
||||||
@if ($invoice)
|
@if ($invoice)
|
||||||
{{ Former::populate($invoice); }}
|
{{ Former::populate($invoice); }}
|
||||||
|
{{ Former::populateField('id', $invoice->public_id); }}
|
||||||
{{ Former::populateField('invoice_date', fromSqlDate($invoice->invoice_date)); }}
|
{{ Former::populateField('invoice_date', fromSqlDate($invoice->invoice_date)); }}
|
||||||
{{ Former::populateField('due_date', fromSqlDate($invoice->due_date)); }}
|
{{ Former::populateField('due_date', fromSqlDate($invoice->due_date)); }}
|
||||||
@else
|
@else
|
||||||
@ -25,7 +25,7 @@
|
|||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-md-6">
|
<div class="col-md-6">
|
||||||
{{ Former::select('client')->addOption('', '')->fromQuery($clients, 'name', 'public_id')->select($client ? $client->public_id : '')
|
{{ Former::select('client')->addOption('', '')->fromQuery($clients, 'name', 'public_id')->select($client ? $client->public_id : '')
|
||||||
->help('<a style="cursor:pointer" data-toggle="modal" data-target="#myModal">Create new client</a>') }}
|
->help('<a style="cursor:pointer" data-toggle="modal" id="modalLink" onclick="showCreateNew()">Create new client</a>') }}
|
||||||
{{ Former::textarea('notes') }}
|
{{ Former::textarea('notes') }}
|
||||||
</div>
|
</div>
|
||||||
<div class="col-md-5">
|
<div class="col-md-5">
|
||||||
@ -117,7 +117,10 @@
|
|||||||
<div class="form-actions">
|
<div class="form-actions">
|
||||||
|
|
||||||
@if ($invoice)
|
@if ($invoice)
|
||||||
<div style="display:none">{{ Former::text('action') }}</div>
|
<div style="display:none">
|
||||||
|
{{ Former::text('action') }}
|
||||||
|
{{ Former::text('id') }}
|
||||||
|
</div>
|
||||||
{{ DropdownButton::normal('Download PDF',
|
{{ DropdownButton::normal('Download PDF',
|
||||||
Navigation::links(
|
Navigation::links(
|
||||||
array(
|
array(
|
||||||
@ -143,12 +146,40 @@
|
|||||||
|
|
||||||
|
|
||||||
<div class="modal fade" id="myModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
|
<div class="modal fade" id="myModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
|
||||||
<div class="modal-dialog">
|
<div class="modal-dialog" style="min-width:1000px">
|
||||||
<div class="modal-content">
|
<div class="modal-content">
|
||||||
<div class="modal-header">
|
<div class="modal-header">
|
||||||
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
|
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
|
||||||
<h4 class="modal-title" id="myModalLabel">New Client</h4>
|
<h4 class="modal-title" id="myModalLabel">New Client</h4>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div class="row" style="padding-left:16px;padding-right:16px" onkeypress="preventFormSubmit(event)">
|
||||||
|
<div class="col-md-6">
|
||||||
|
|
||||||
|
{{ Former::legend('Organization') }}
|
||||||
|
{{ Former::text('name') }}
|
||||||
|
{{ Former::text('work_phone')->label('Phone') }}
|
||||||
|
|
||||||
|
{{ Former::legend('Contact') }}
|
||||||
|
{{ Former::text('first_name') }}
|
||||||
|
{{ Former::text('last_name') }}
|
||||||
|
{{ Former::text('email') }}
|
||||||
|
{{ Former::text('phone') }}
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<div class="col-md-6">
|
||||||
|
{{ Former::legend('Address') }}
|
||||||
|
{{ Former::text('address1')->label('Street') }}
|
||||||
|
{{ Former::text('address2')->label('Apt/Floor') }}
|
||||||
|
{{ Former::text('city') }}
|
||||||
|
{{ Former::text('state') }}
|
||||||
|
{{ Former::text('postal_code') }}
|
||||||
|
{{ Former::select('country_id')->addOption('','')->label('Country')
|
||||||
|
->fromQuery($countries, 'name', 'id')->select($client ? $client->country_id : '') }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!--
|
||||||
<div class="modal-body" style="min-height:80px">
|
<div class="modal-body" style="min-height:80px">
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="name" class="control-label col-lg-2 col-sm-4">Name<sup>*</sup></label>
|
<label for="name" class="control-label col-lg-2 col-sm-4">Name<sup>*</sup></label>
|
||||||
@ -165,10 +196,14 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
-->
|
||||||
|
|
||||||
<div class="modal-footer">
|
<div class="modal-footer">
|
||||||
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
|
<span class="error-block" id="nameError" style="display:none;float:left">Please provide a value for the name field.</span><span> </span>
|
||||||
<button type="button" class="btn btn-primary" onclick="newClient()">Save</button>
|
<button type="button" class="btn btn-default" data-dismiss="modal">Cancel</button>
|
||||||
|
<button type="button" class="btn btn-primary" onclick="newClient()">Done</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -191,6 +226,8 @@
|
|||||||
|
|
||||||
$(function() {
|
$(function() {
|
||||||
|
|
||||||
|
$('#country_id').combobox();
|
||||||
|
|
||||||
$('#invoice_date').datepicker({
|
$('#invoice_date').datepicker({
|
||||||
autoclose: true,
|
autoclose: true,
|
||||||
todayHighlight: true
|
todayHighlight: true
|
||||||
@ -207,6 +244,8 @@
|
|||||||
$input.combobox();
|
$input.combobox();
|
||||||
$('.combobox-container input.form-control').attr('name', 'client_combobox').on('change', function(e) {
|
$('.combobox-container input.form-control').attr('name', 'client_combobox').on('change', function(e) {
|
||||||
refreshPDF();
|
refreshPDF();
|
||||||
|
}).on('keydown', function() {
|
||||||
|
$('#modalLink').text('Create new client');
|
||||||
});
|
});
|
||||||
enableHoverClick($('.combobox-container input.form-control'), $('.combobox-container input[name=client]'), '{{ URL::to('clients') }}');
|
enableHoverClick($('.combobox-container input.form-control'), $('.combobox-container input[name=client]'), '{{ URL::to('clients') }}');
|
||||||
|
|
||||||
@ -223,7 +262,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
$('#myModal').on('shown.bs.modal', function () {
|
$('#myModal').on('shown.bs.modal', function () {
|
||||||
$('#client_name').focus();
|
$('#name').focus();
|
||||||
})
|
})
|
||||||
|
|
||||||
$('#invoice_number').change(refreshPDF);
|
$('#invoice_number').change(refreshPDF);
|
||||||
@ -237,6 +276,16 @@
|
|||||||
refreshPDF();
|
refreshPDF();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
function showCreateNew() {
|
||||||
|
if ($('.combobox-container input[name=client]').val() != '-1') {
|
||||||
|
$('#myModal input').val('');
|
||||||
|
$('#myModal #country_id').val('');
|
||||||
|
$('#nameError').css( "display", "none" );
|
||||||
|
}
|
||||||
|
$('#myModal').modal('show');
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
function applyComboboxListeners() {
|
function applyComboboxListeners() {
|
||||||
var value;
|
var value;
|
||||||
$('.datalist').on('focus', function() {
|
$('.datalist').on('focus', function() {
|
||||||
@ -335,27 +384,27 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
function newClient() {
|
function newClient() {
|
||||||
var name = $('#client_name').val();
|
var name = $('#name').val();
|
||||||
var email = $('#client_email').val();
|
if (!name) {
|
||||||
if (!name || !email) {
|
if (!name) $('#nameError').css( "display", "inline" );
|
||||||
if (!name) $('#nameHelp').css( "display", "block" );
|
|
||||||
if (!email) $('#emailHelp').css( "display", "block" );
|
|
||||||
} else {
|
} else {
|
||||||
$('.combobox-container input[name=client]').val('-1');
|
$('.combobox-container input[name=client]').val('-1');
|
||||||
$('.combobox-container input.form-control').val(name);
|
$('.combobox-container input.form-control').val(name);
|
||||||
$('.combobox-container').addClass('combobox-selected');
|
$('.combobox-container').addClass('combobox-selected');
|
||||||
|
|
||||||
$('#nameHelp').css( "display", "none" );
|
$('#nameError').css( "display", "none" );
|
||||||
$('#emailHelp').css( "display", "none" );
|
|
||||||
//$('#client_name').val('');
|
//$('#client_name').val('');
|
||||||
|
$('#modalLink').text('Edit client details');
|
||||||
$('#myModal').modal('hide');
|
$('#myModal').modal('hide');
|
||||||
$('input#invoice_number').focus();
|
$('input#invoice_number').focus();
|
||||||
|
//$('[name="client_combobox"]').focus();
|
||||||
|
|
||||||
refreshPDF();
|
refreshPDF();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function nameKeyPress(event) {
|
|
||||||
|
function preventFormSubmit(event) {
|
||||||
if (event.keyCode === 13){
|
if (event.keyCode === 13){
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
newClient();
|
newClient();
|
||||||
|
@ -11,16 +11,14 @@
|
|||||||
{{ DropdownButton::normal('Archive',
|
{{ DropdownButton::normal('Archive',
|
||||||
Navigation::links(
|
Navigation::links(
|
||||||
array(
|
array(
|
||||||
array('Archive', "javascript:submitForm('archive')"),
|
array('Archive '.ucwords($entityType), "javascript:submitForm('archive')"),
|
||||||
array('Delete', "javascript:submitForm('delete')"),
|
array('Delete '.ucwords($entityType), "javascript:submitForm('delete')"),
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
, array('id'=>'archive'))->split(); }}
|
, array('id'=>'archive'))->split(); }}
|
||||||
|
|
||||||
|
|
||||||
@if (in_array($entityType, [ENTITY_CLIENT, ENTITY_INVOICE]))
|
|
||||||
{{ Button::primary_link(URL::to($entityType . 's/create'), 'New ' . ucwords($entityType), array('class' => 'pull-right')) }}
|
{{ Button::primary_link(URL::to($entityType . 's/create'), 'New ' . ucwords($entityType), array('class' => 'pull-right')) }}
|
||||||
@endif
|
|
||||||
|
|
||||||
{{ Datatable::table()
|
{{ Datatable::table()
|
||||||
->addColumn($columns)
|
->addColumn($columns)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user