diff --git a/app/commands/SendRecurringInvoices.php b/app/commands/SendRecurringInvoices.php index 38aca636a242..5e86c449bd82 100755 --- a/app/commands/SendRecurringInvoices.php +++ b/app/commands/SendRecurringInvoices.php @@ -39,7 +39,7 @@ class SendRecurringInvoices extends Command { $invoice = Invoice::createNew($recurInvoice); $invoice->client_id = $recurInvoice->client_id; $invoice->recurring_invoice_id = $recurInvoice->id; - $invoice->invoice_number = $recurInvoice->account->getNextInvoiceNumber(); + $invoice->invoice_number = 'R' . $recurInvoice->account->getNextInvoiceNumber(); $invoice->amount = $recurInvoice->amount; $invoice->currency_id = $recurInvoice->currency_id; $invoice->invoice_date = date_create(); diff --git a/app/controllers/AccountController.php b/app/controllers/AccountController.php index 7b61e8fdc38d..2725fb81cff0 100755 --- a/app/controllers/AccountController.php +++ b/app/controllers/AccountController.php @@ -67,10 +67,14 @@ class AccountController extends \BaseController { { if ($section == ACCOUNT_DETAILS) { - $account = Account::with('users')->findOrFail(Auth::user()->account_id); - $countries = Country::remember(DEFAULT_QUERY_CACHE)->orderBy('name')->get(); + $data = [ + 'account' => Account::with('users')->findOrFail(Auth::user()->account_id), + 'countries' => Country::remember(DEFAULT_QUERY_CACHE)->orderBy('name')->get(), + 'sizes' => Size::remember(DEFAULT_QUERY_CACHE)->orderBy('id')->get(), + 'industries' => Industry::remember(DEFAULT_QUERY_CACHE)->orderBy('name')->get(), + ]; - return View::make('accounts.details', array('account'=>$account, 'countries'=>$countries)); + return View::make('accounts.details', $data); } else if ($section == ACCOUNT_SETTINGS) { @@ -444,7 +448,7 @@ class AccountController extends \BaseController { { $rules = array( 'name' => 'required', - 'email' => 'email|required' + 'email' => 'email|required|unique:users,email,' . Auth::user()->id . ',id' ); $validator = Validator::make(Input::all(), $rules); @@ -465,12 +469,14 @@ class AccountController extends \BaseController { $account->state = trim(Input::get('state')); $account->postal_code = trim(Input::get('postal_code')); $account->country_id = Input::get('country_id') ? Input::get('country_id') : null; + $account->size_id = Input::get('size_id') ? Input::get('size_id') : null; + $account->industry_id = Input::get('industry_id') ? Input::get('industry_id') : null; $account->save(); $user = $account->users()->first(); $user->first_name = trim(Input::get('first_name')); $user->last_name = trim(Input::get('last_name')); - $user->email = trim(Input::get('email')); + $user->username = $user->email = trim(Input::get('email')); $user->phone = trim(Input::get('phone')); $user->save(); @@ -484,7 +490,7 @@ class AccountController extends \BaseController { { $path = Input::file('logo')->getRealPath(); File::delete('logo/' . $account->account_key . '.jpg'); - Image::make($path)->resize(150, 100, true, false)->save('logo/' . $account->account_key . '.jpg'); + Image::make($path)->resize(120, 80, true, false)->save('logo/' . $account->account_key . '.jpg'); } Session::flash('message', 'Successfully updated details'); @@ -494,11 +500,13 @@ class AccountController extends \BaseController { public function checkEmail() { - $email = User::where('email', '=', Input::get('email'))->where('id', '<>', Auth::user()->id)->first(); + $email = User::withTrashed()->where('email', '=', Input::get('email'))->where('id', '<>', Auth::user()->id)->first(); - if ($email) { + if ($email) + { return "taken"; - } else { + } + else { return "available"; } } diff --git a/app/controllers/ClientController.php b/app/controllers/ClientController.php index 501283f03aae..a97f8129b8ad 100755 --- a/app/controllers/ClientController.php +++ b/app/controllers/ClientController.php @@ -1,7 +1,18 @@ clientRepo = $clientRepo; + } + /** * Display a listing of the resource. * @@ -9,9 +20,6 @@ class ClientController extends \BaseController { */ public function index() { - //$clients = Client::orderBy('name')->get(); - //return View::make('clients.index')->with('clients', $clients); - return View::make('list', array( 'entityType'=>ENTITY_CLIENT, 'title' => '- Clients', @@ -21,29 +29,9 @@ class ClientController extends \BaseController { public function getDatatable() { - $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','clients.work_phone','contacts.email','clients.currency_id'); + $clients = $this->clientRepo->find(Input::get('sSearch')); - $filter = Input::get('sSearch'); - if ($filter) - { - $query->where(function($query) use ($filter) - { - $query->where('clients.name', 'like', '%'.$filter.'%') - ->orWhere('contacts.first_name', 'like', '%'.$filter.'%') - ->orWhere('contacts.last_name', 'like', '%'.$filter.'%') - ->orWhere('contacts.email', 'like', '%'.$filter.'%'); - }); - } - - //$query->get(); - //dd(DB::getQueryLog()); - - return Datatable::query($query) + return Datatable::query($clients) ->addColumn('checkbox', function($model) { return ''; }) ->addColumn('name', function($model) { return link_to('clients/' . $model->public_id, $model->name); }) ->addColumn('first_name', function($model) { return link_to('clients/' . $model->public_id, $model->first_name . ' ' . $model->last_name); }) @@ -85,8 +73,8 @@ class ClientController extends \BaseController { 'method' => 'POST', 'url' => 'clients', 'title' => '- New Client', - 'clientSizes' => ClientSize::remember(DEFAULT_QUERY_CACHE)->orderBy('id')->get(), - 'clientIndustries' => ClientIndustry::remember(DEFAULT_QUERY_CACHE)->orderBy('name')->get(), + 'sizes' => Size::remember(DEFAULT_QUERY_CACHE)->orderBy('id')->get(), + 'industries' => Industry::remember(DEFAULT_QUERY_CACHE)->orderBy('name')->get(), 'paymentTerms' => PaymentTerm::remember(DEFAULT_QUERY_CACHE)->orderBy('num_days')->get(['name', 'num_days']), 'currencies' => Currency::remember(DEFAULT_QUERY_CACHE)->orderBy('name')->get(), 'countries' => Country::remember(DEFAULT_QUERY_CACHE)->orderBy('name')->get()); @@ -112,7 +100,7 @@ class ClientController extends \BaseController { */ public function show($publicId) { - $client = Client::scope($publicId)->with('contacts', 'client_size', 'client_industry')->firstOrFail(); + $client = Client::scope($publicId)->with('contacts', 'size', 'industry')->firstOrFail(); Utils::trackViewed($client->getDisplayName(), ENTITY_CLIENT); $data = array( @@ -138,9 +126,9 @@ class ClientController extends \BaseController { 'method' => 'PUT', 'url' => 'clients/' . $publicId, 'title' => '- ' . $client->name, - 'clientSizes' => ClientSize::remember(DEFAULT_QUERY_CACHE)->orderBy('id')->get(), + 'sizes' => Size::remember(DEFAULT_QUERY_CACHE)->orderBy('id')->get(), 'paymentTerms' => PaymentTerm::remember(DEFAULT_QUERY_CACHE)->orderBy('num_days')->get(['name', 'num_days']), - 'clientIndustries' => ClientIndustry::remember(DEFAULT_QUERY_CACHE)->orderBy('name')->get(), + 'industries' => Industry::remember(DEFAULT_QUERY_CACHE)->orderBy('name')->get(), 'currencies' => Currency::remember(DEFAULT_QUERY_CACHE)->orderBy('name')->get(), 'countries' => Country::remember(DEFAULT_QUERY_CACHE)->orderBy('name')->get()); return View::make('clients.edit', $data); @@ -185,8 +173,8 @@ class ClientController extends \BaseController { $client->postal_code = trim(Input::get('postal_code')); $client->country_id = Input::get('country_id') ? Input::get('country_id') : null; $client->private_notes = trim(Input::get('private_notes')); - $client->client_size_id = Input::get('client_size_id') ? Input::get('client_size_id') : null; - $client->client_industry_id = Input::get('client_industry_id') ? Input::get('client_industry_id') : null; + $client->size_id = Input::get('size_id') ? Input::get('size_id') : null; + $client->industry_id = Input::get('industry_id') ? Input::get('industry_id') : null; $client->currency_id = Input::get('currency_id') ? Input::get('currency_id') : null; $client->payment_terms = Input::get('payment_terms'); $client->website = trim(Input::get('website')); @@ -244,11 +232,14 @@ class ClientController extends \BaseController { $ids = Input::get('id') ? Input::get('id') : Input::get('ids'); $clients = Client::scope($ids)->get(); - foreach ($clients as $client) { - if ($action == 'delete') { + foreach ($clients as $client) + { + if ($action == 'delete') + { $client->is_deleted = true; $client->save(); } + $client->delete(); } diff --git a/app/controllers/CreditController.php b/app/controllers/CreditController.php index 96322dc4b726..9f0e129edf27 100755 --- a/app/controllers/CreditController.php +++ b/app/controllers/CreditController.php @@ -1,7 +1,18 @@ -creditRepo = $creditRepo; + } + /** * Display a listing of the resource. * @@ -18,31 +29,12 @@ class CreditController extends \BaseController { public function getDatatable($clientPublicId = null) { - $query = DB::table('credits') - ->join('clients', 'clients.id', '=','credits.client_id') - ->join('contacts', 'contacts.client_id', '=', 'clients.id') - ->where('clients.account_id', '=', Auth::user()->account_id) - ->where('clients.deleted_at', '=', null) - ->where('credits.deleted_at', '=', null) - ->where('contacts.is_primary', '=', true) - ->select('credits.public_id', 'clients.name as client_name', 'clients.public_id as client_public_id', 'credits.amount', 'credits.credit_date', 'credits.currency_id', 'contacts.first_name', 'contacts.last_name', 'contacts.email'); + $credits = $this->creditRepo->find($clientPublicId, Input::get('sSearch')); - if ($clientPublicId) { - $query->where('clients.public_id', '=', $clientPublicId); - } + $table = Datatable::query($credits); - $filter = Input::get('sSearch'); - if ($filter) + if (!$clientPublicId) { - $query->where(function($query) use ($filter) - { - $query->where('clients.name', 'like', '%'.$filter.'%'); - }); - } - - $table = Datatable::query($query); - - if (!$clientPublicId) { $table->addColumn('checkbox', function($model) { return ''; }) ->addColumn('client_name', function($model) { return link_to('clients/' . $model->client_public_id, Utils::getClientDisplayName($model)); }); } @@ -56,14 +48,12 @@ class CreditController extends \BaseController { Select
'; }) - ->orderColumns('number') + ->orderColumns('number') ->make(); } @@ -119,26 +109,16 @@ class CreditController extends \BaseController { $validator = Validator::make(Input::all(), $rules); - if ($validator->fails()) { + if ($validator->fails()) + { $url = $publicId ? 'credits/' . $publicId . '/edit' : 'credits/create'; return Redirect::to($url) ->withErrors($validator) ->withInput(); - } else { - if ($publicId) { - $credit = Credit::scope($publicId)->firstOrFail(); - } else { - $credit = Credit::createNew(); - } - - $invoiceId = Input::get('invoice') && Input::get('invoice') != "-1" ? Invoice::getPrivateId(Input::get('invoice')) : null; - - $credit->client_id = Client::getPrivateId(Input::get('client')); - $credit->credit_date = Utils::toSqlDate(Input::get('credit_date')); - $credit->invoice_id = $invoiceId; - $credit->amount = floatval(Input::get('amount')); - $credit->currency_id = Input::get('currency_id') ? Input::get('currency_id') : null; - $credit->save(); + } + else + { + $this->creditRepo->save($publicId, Input::all()); $message = $publicId ? 'Successfully updated credit' : 'Successfully created credit'; Session::flash('message', $message); @@ -149,18 +129,10 @@ class CreditController extends \BaseController { public function bulk() { $action = Input::get('action'); - $ids = Input::get('id') ? Input::get('id') : Input::get('ids'); - $credits = Credit::scope($ids)->get(); + $ids = Input::get('id') ? Input::get('id') : Input::get('ids'); + $count = $this->creditRepo->bulk($ids, $action); - foreach ($credits as $credit) { - if ($action == 'delete') { - $credit->is_deleted = true; - $credit->save(); - } - $credit->delete(); - } - - $message = Utils::pluralize('Successfully '.$action.'d ? credit', count($credits)); + $message = Utils::pluralize('Successfully '.$action.'d ? credit', $count); Session::flash('message', $message); return Redirect::to('credits'); diff --git a/app/controllers/InvoiceController.php b/app/controllers/InvoiceController.php index 10e190fcc158..380bec4139bc 100755 --- a/app/controllers/InvoiceController.php +++ b/app/controllers/InvoiceController.php @@ -116,41 +116,27 @@ class InvoiceController extends \BaseController { public function view($invitationKey) { - $invitation = Invitation::with('user', 'invoice.invoice_items', 'invoice.client.account', 'invoice.client.contacts') + $invitation = Invitation::with('user', 'invoice.invoice_items', 'invoice.account.country', 'invoice.client.contacts', 'invoice.client.country') ->where('invitation_key', '=', $invitationKey)->firstOrFail(); - $user = $invitation->user; $invoice = $invitation->invoice; - + if (!$invoice || $invoice->is_deleted) { return View::make('invoices.deleted'); } $client = $invoice->client; - + if (!$client || $client->is_deleted) { return View::make('invoices.deleted'); } - - if (!$invoice->isViewed()) - { - $invoice->invoice_status_id = INVOICE_STATUS_VIEWED; - $invoice->save(); - } - - $now = Carbon::now()->toDateTimeString(); - $invitation->viewed_date = $now; - $invitation->save(); + Activity::viewInvoice($invitation); - $client = $invoice->client; - $client->last_login = $now; - $client->save(); + $client->account->loadLocalizationSettings(); - Activity::viewInvoice($invitation); - $data = array( 'invoice' => $invoice->hidePrivateFields(), 'invitation' => $invitation @@ -298,7 +284,7 @@ class InvoiceController extends \BaseController { public function edit($publicId) { - $invoice = Invoice::scope($publicId)->with('account.country', 'client.contacts', 'invoice_items')->firstOrFail(); + $invoice = Invoice::scope($publicId)->with('account.country', 'client.contacts', 'client.country', 'invoice_items')->firstOrFail(); Utils::trackViewed($invoice->invoice_number . ' - ' . $invoice->client->getDisplayName(), ENTITY_INVOICE); $contactIds = DB::table('invitations') @@ -350,12 +336,12 @@ class InvoiceController extends \BaseController { 'account' => Auth::user()->account, 'products' => Product::scope()->get(array('product_key','notes','cost','qty')), 'countries' => Country::remember(DEFAULT_QUERY_CACHE)->orderBy('name')->get(), - 'clients' => Client::scope()->with('contacts')->orderBy('name')->get(), + 'clients' => Client::scope()->with('contacts', 'country')->orderBy('name')->get(), 'taxRates' => TaxRate::scope()->orderBy('name')->get(), 'currencies' => Currency::remember(DEFAULT_QUERY_CACHE)->orderBy('name')->get(), - 'clientSizes' => ClientSize::remember(DEFAULT_QUERY_CACHE)->orderBy('id')->get(), + 'sizes' => Size::remember(DEFAULT_QUERY_CACHE)->orderBy('id')->get(), 'paymentTerms' => PaymentTerm::remember(DEFAULT_QUERY_CACHE)->orderBy('num_days')->get(['name', 'num_days']), - 'clientIndustries' => ClientIndustry::remember(DEFAULT_QUERY_CACHE)->orderBy('name')->get(), + 'industries' => Industry::remember(DEFAULT_QUERY_CACHE)->orderBy('name')->get(), 'frequencies' => array( 1 => 'Weekly', 2 => 'Two weeks', @@ -419,7 +405,7 @@ class InvoiceController extends \BaseController { foreach ($client->contacts as $contact) { - if ($contact->send_invoice) + if ($contact->send_invoice || count($client->contacts) == 1) { $sendInvoiceIds[] = $contact->id; } @@ -505,11 +491,14 @@ class InvoiceController extends \BaseController { $ids = Input::get('id') ? Input::get('id') : Input::get('ids'); $invoices = Invoice::scope($ids)->get(); - foreach ($invoices as $invoice) { - if ($action == 'delete') { + foreach ($invoices as $invoice) + { + if ($action == 'delete') + { $invoice->is_deleted = true; $invoice->save(); } + $invoice->delete(); } diff --git a/app/controllers/PaymentController.php b/app/controllers/PaymentController.php index 7fdd1df73228..35f574f1fdb5 100755 --- a/app/controllers/PaymentController.php +++ b/app/controllers/PaymentController.php @@ -1,7 +1,18 @@ paymentRepo = $paymentRepo; + } + public function index() { return View::make('list', array( @@ -13,30 +24,8 @@ class PaymentController extends \BaseController public function getDatatable($clientPublicId = null) { - $query = DB::table('payments') - ->join('clients', 'clients.id', '=','payments.client_id') - ->leftJoin('invoices', 'invoices.id', '=','payments.invoice_id') - ->join('contacts', 'contacts.client_id', '=', 'clients.id') - ->where('payments.account_id', '=', Auth::user()->account_id) - ->where('payments.deleted_at', '=', null) - ->where('clients.deleted_at', '=', null) - ->where('contacts.is_primary', '=', true) - ->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', 'payments.currency_id', 'contacts.first_name', 'contacts.last_name', 'contacts.email'); - - if ($clientPublicId) { - $query->where('clients.public_id', '=', $clientPublicId); - } - - $filter = Input::get('sSearch'); - if ($filter) - { - $query->where(function($query) use ($filter) - { - $query->where('clients.name', 'like', '%'.$filter.'%'); - }); - } - - $table = Datatable::query($query); + $payments = $this->paymentRepo->find($clientPublicId, Input::get('sSearch')); + $table = Datatable::query($payments); if (!$clientPublicId) { $table->addColumn('checkbox', function($model) { return ''; }); @@ -58,8 +47,6 @@ class PaymentController extends \BaseController Select @@ -123,26 +110,16 @@ class PaymentController extends \BaseController ); $validator = Validator::make(Input::all(), $rules); - if ($validator->fails()) { + if ($validator->fails()) + { $url = $publicId ? 'payments/' . $publicId . '/edit' : 'payments/create'; return Redirect::to($url) ->withErrors($validator) ->withInput(); - } else { - if ($publicId) { - $payment = Payment::scope($publicId)->firstOrFail(); - } else { - $payment = Payment::createNew(); - } - - $invoiceId = Input::get('invoice') && Input::get('invoice') != "-1" ? Invoice::getPrivateId(Input::get('invoice')) : null; - - $payment->client_id = Client::getPrivateId(Input::get('client')); - $payment->invoice_id = $invoiceId; - $payment->currency_id = Input::get('currency_id') ? Input::get('currency_id') : null; - $payment->payment_date = Utils::toSqlDate(Input::get('payment_date')); - $payment->amount = floatval(Input::get('amount')); - $payment->save(); + } + else + { + $this->paymentRepo->save($publicId, Input::all()); $message = $publicId ? 'Successfully updated payment' : 'Successfully created payment'; Session::flash('message', $message); @@ -154,15 +131,7 @@ class PaymentController extends \BaseController { $action = Input::get('action'); $ids = Input::get('id') ? Input::get('id') : Input::get('ids'); - $payments = Payment::scope($ids)->get(); - - foreach ($payments as $payment) { - if ($action == 'delete') { - $payment->is_deleted = true; - $payment->save(); - } - $payment->delete(); - } + $count = $this->paymentRepo->bulk($ids, $action); $message = Utils::pluralize('Successfully '.$action.'d ? payment', count($payments)); Session::flash('message', $message); diff --git a/app/database/migrations/2013_11_05_180133_confide_setup_users_table.php b/app/database/migrations/2013_11_05_180133_confide_setup_users_table.php index c90c97614342..9638598df53a 100755 --- a/app/database/migrations/2013_11_05_180133_confide_setup_users_table.php +++ b/app/database/migrations/2013_11_05_180133_confide_setup_users_table.php @@ -25,8 +25,6 @@ class ConfideSetupUsersTable extends Migration { Schema::dropIfExists('invoices'); Schema::dropIfExists('password_reminders'); Schema::dropIfExists('clients'); - Schema::dropIfExists('client_sizes'); - Schema::dropIfExists('client_industries'); Schema::dropIfExists('users'); Schema::dropIfExists('accounts'); Schema::dropIfExists('currencies'); @@ -36,7 +34,9 @@ class ConfideSetupUsersTable extends Migration { Schema::dropIfExists('frequencies'); Schema::dropIfExists('date_formats'); Schema::dropIfExists('datetime_formats'); - + Schema::dropIfExists('sizes'); + Schema::dropIfExists('industries'); + Schema::create('countries', function($table) { $table->increments('id'); @@ -101,6 +101,18 @@ class ConfideSetupUsersTable extends Migration { $t->string('decimal_separator'); }); + Schema::create('sizes', function($t) + { + $t->increments('id'); + $t->string('name'); + }); + + Schema::create('industries', function($t) + { + $t->increments('id'); + $t->string('name'); + }); + Schema::create('accounts', function($t) { $t->increments('id'); @@ -124,6 +136,8 @@ class ConfideSetupUsersTable extends Migration { $t->string('postal_code'); $t->unsignedInteger('country_id')->nullable(); $t->text('invoice_terms'); + $t->unsignedInteger('industry_id')->nullable(); + $t->unsignedInteger('size_id')->nullable(); $t->boolean('invoice_taxes')->default(true); $t->boolean('invoice_item_taxes')->default(false); @@ -131,8 +145,10 @@ class ConfideSetupUsersTable extends Migration { $t->foreign('timezone_id')->references('id')->on('timezones'); $t->foreign('date_format_id')->references('id')->on('date_formats'); $t->foreign('datetime_format_id')->references('id')->on('datetime_formats'); - $t->foreign('country_id')->references('id')->on('countries'); - $t->foreign('currency_id')->references('id')->on('currencies'); + $t->foreign('country_id')->references('id')->on('countries'); + $t->foreign('currency_id')->references('id')->on('currencies'); + $t->foreign('industry_id')->references('id')->on('industries'); + $t->foreign('size_id')->references('id')->on('sizes'); }); Schema::create('gateways', function($t) @@ -201,18 +217,6 @@ class ConfideSetupUsersTable extends Migration { $t->string('token'); }); - Schema::create('client_sizes', function($t) - { - $t->increments('id'); - $t->string('name'); - }); - - Schema::create('client_industries', function($t) - { - $t->increments('id'); - $t->string('name'); - }); - Schema::create('clients', function($t) { $t->increments('id'); @@ -235,16 +239,16 @@ class ConfideSetupUsersTable extends Migration { $t->decimal('paid_to_date', 13, 4); $t->timestamp('last_login')->nullable(); $t->string('website'); - $t->unsignedInteger('client_industry_id')->nullable(); - $t->unsignedInteger('client_size_id')->nullable(); + $t->unsignedInteger('industry_id')->nullable(); + $t->unsignedInteger('size_id')->nullable(); $t->boolean('is_deleted'); $t->integer('payment_terms'); $t->foreign('account_id')->references('id')->on('accounts')->onDelete('cascade'); $t->foreign('user_id')->references('id')->on('users')->onDelete('cascade'); $t->foreign('country_id')->references('id')->on('countries'); - $t->foreign('client_industry_id')->references('id')->on('client_industries'); - $t->foreign('client_size_id')->references('id')->on('client_sizes'); + $t->foreign('industry_id')->references('id')->on('industries'); + $t->foreign('size_id')->references('id')->on('sizes'); $t->foreign('currency_id')->references('id')->on('currencies'); $t->unsignedInteger('public_id')->index(); @@ -439,7 +443,7 @@ class ConfideSetupUsersTable extends Migration { $t->string('payer_id'); $t->foreign('invoice_id')->references('id')->on('invoices'); - $t->foreign('account_id')->references('id')->on('accounts'); + $t->foreign('account_id')->references('id')->on('accounts')->onDelete('cascade'); $t->foreign('client_id')->references('id')->on('clients')->onDelete('cascade'); $t->foreign('contact_id')->references('id')->on('contacts'); $t->foreign('user_id')->references('id')->on('users')->onDelete('cascade');; @@ -466,7 +470,7 @@ class ConfideSetupUsersTable extends Migration { $t->date('credit_date')->nullable(); $t->string('credit_number'); - $t->foreign('account_id')->references('id')->on('accounts'); + $t->foreign('account_id')->references('id')->on('accounts')->onDelete('cascade'); $t->foreign('client_id')->references('id')->on('clients')->onDelete('cascade'); $t->foreign('invoice_id')->references('id')->on('invoices')->onDelete('cascade'); $t->foreign('contact_id')->references('id')->on('contacts'); @@ -526,8 +530,6 @@ class ConfideSetupUsersTable extends Migration { Schema::dropIfExists('invoices'); Schema::dropIfExists('password_reminders'); Schema::dropIfExists('clients'); - Schema::dropIfExists('client_sizes'); - Schema::dropIfExists('client_industries'); Schema::dropIfExists('users'); Schema::dropIfExists('accounts'); Schema::dropIfExists('currencies'); @@ -537,5 +539,7 @@ class ConfideSetupUsersTable extends Migration { Schema::dropIfExists('frequencies'); Schema::dropIfExists('date_formats'); Schema::dropIfExists('datetime_formats'); + Schema::dropIfExists('sizes'); + Schema::dropIfExists('industries'); } } diff --git a/app/database/seeds/ConstantsSeeder.php b/app/database/seeds/ConstantsSeeder.php index f8a0815f83f6..9b525cfd46c3 100755 --- a/app/database/seeds/ConstantsSeeder.php +++ b/app/database/seeds/ConstantsSeeder.php @@ -58,41 +58,41 @@ class ConstantsSeeder extends Seeder Frequency::create(array('name' => 'Six months')); Frequency::create(array('name' => 'Annually')); - ClientIndustry::create(array('name' => 'Accounting & Legal')); - ClientIndustry::create(array('name' => 'Advertising')); - ClientIndustry::create(array('name' => 'Aerospace')); - ClientIndustry::create(array('name' => 'Agriculture')); - ClientIndustry::create(array('name' => 'Automotive')); - ClientIndustry::create(array('name' => 'Banking & Finance')); - ClientIndustry::create(array('name' => 'Biotechnology')); - ClientIndustry::create(array('name' => 'Broadcasting')); - ClientIndustry::create(array('name' => 'Business Services')); - ClientIndustry::create(array('name' => 'Commodities & Chemicals')); - ClientIndustry::create(array('name' => 'Communications')); - ClientIndustry::create(array('name' => 'Computers & Hightech')); - ClientIndustry::create(array('name' => 'Defense')); - ClientIndustry::create(array('name' => 'Energy')); - ClientIndustry::create(array('name' => 'Entertainment')); - ClientIndustry::create(array('name' => 'Government')); - ClientIndustry::create(array('name' => 'Healthcare & Life Sciences')); - ClientIndustry::create(array('name' => 'Insurance')); - ClientIndustry::create(array('name' => 'Manufacturing')); - ClientIndustry::create(array('name' => 'Marketing')); - ClientIndustry::create(array('name' => 'Media')); - ClientIndustry::create(array('name' => 'Nonprofit & Higher Ed')); - ClientIndustry::create(array('name' => 'Pharmaceuticals')); - ClientIndustry::create(array('name' => 'Professional Services & Consulting')); - ClientIndustry::create(array('name' => 'Real Estate')); - ClientIndustry::create(array('name' => 'Retail & Wholesale')); - ClientIndustry::create(array('name' => 'Sports')); - ClientIndustry::create(array('name' => 'Transportation')); - ClientIndustry::create(array('name' => 'Travel & Luxury')); + Industry::create(array('name' => 'Accounting & Legal')); + Industry::create(array('name' => 'Advertising')); + Industry::create(array('name' => 'Aerospace')); + Industry::create(array('name' => 'Agriculture')); + Industry::create(array('name' => 'Automotive')); + Industry::create(array('name' => 'Banking & Finance')); + Industry::create(array('name' => 'Biotechnology')); + Industry::create(array('name' => 'Broadcasting')); + Industry::create(array('name' => 'Business Services')); + Industry::create(array('name' => 'Commodities & Chemicals')); + Industry::create(array('name' => 'Communications')); + Industry::create(array('name' => 'Computers & Hightech')); + Industry::create(array('name' => 'Defense')); + Industry::create(array('name' => 'Energy')); + Industry::create(array('name' => 'Entertainment')); + Industry::create(array('name' => 'Government')); + Industry::create(array('name' => 'Healthcare & Life Sciences')); + Industry::create(array('name' => 'Insurance')); + Industry::create(array('name' => 'Manufacturing')); + Industry::create(array('name' => 'Marketing')); + Industry::create(array('name' => 'Media')); + Industry::create(array('name' => 'Nonprofit & Higher Ed')); + Industry::create(array('name' => 'Pharmaceuticals')); + Industry::create(array('name' => 'Professional Services & Consulting')); + Industry::create(array('name' => 'Real Estate')); + Industry::create(array('name' => 'Retail & Wholesale')); + Industry::create(array('name' => 'Sports')); + Industry::create(array('name' => 'Transportation')); + Industry::create(array('name' => 'Travel & Luxury')); - ClientSize::create(array('name' => '1 - 10')); - ClientSize::create(array('name' => '11 - 50')); - ClientSize::create(array('name' => '51 - 100')); - ClientSize::create(array('name' => '101 - 500')); - ClientSize::create(array('name' => '500+')); + Size::create(array('name' => '1 - 10')); + Size::create(array('name' => '11 - 50')); + Size::create(array('name' => '51 - 100')); + Size::create(array('name' => '101 - 500')); + Size::create(array('name' => '500+')); PaymentTerm::create(array('num_days' => 7, 'name' => 'Net 7')); PaymentTerm::create(array('num_days' => 10, 'name' => 'Net 10')); diff --git a/app/handlers/UserEventHandler.php b/app/handlers/UserEventHandler.php index 40294b6a22d9..92e97c8c26bd 100755 --- a/app/handlers/UserEventHandler.php +++ b/app/handlers/UserEventHandler.php @@ -17,7 +17,7 @@ class UserEventHandler public function onLogin() { - $account = Account::findOrFail(Auth::user()->account_id); + $account = Auth::user()->account; $account->last_login = Carbon::now()->toDateTimeString(); $account->save(); @@ -26,13 +26,6 @@ class UserEventHandler public function onRefresh() { - $user = User::whereId(Auth::user()->id)->with('account', 'account.date_format', 'account.datetime_format', 'account.timezone')->firstOrFail(); - $account = $user->account; - - Session::put(SESSION_TIMEZONE, $account->timezone ? $account->timezone->name : DEFAULT_TIMEZONE); - Session::put(SESSION_DATE_FORMAT, $account->date_format ? $account->date_format->format : DEFAULT_DATE_FORMAT); - Session::put(SESSION_DATE_PICKER_FORMAT, $account->date_format ? $account->date_format->picker_format : DEFAULT_DATE_PICKER_FORMAT); - Session::put(SESSION_DATETIME_FORMAT, $account->datetime_format ? $account->datetime_format->format : DEFAULT_DATETIME_FORMAT); - Session::put(SESSION_CURRENCY, $account->currency_id ? $account->currency_id : DEFAULT_CURRENCY); + Auth::user()->account->loadLocalizationSettings(); } } \ No newline at end of file diff --git a/app/models/Account.php b/app/models/Account.php index b73830c008fd..51d08eb4f73b 100755 --- a/app/models/Account.php +++ b/app/models/Account.php @@ -49,6 +49,15 @@ class Account extends Eloquent return $this->belongsTo('DatetimeFormat'); } + public function size() + { + return $this->belongsTo('Size'); + } + + public function industry() + { + return $this->belongsTo('Industry'); + } public function isGatewayConfigured($gatewayId = 0) { @@ -93,12 +102,13 @@ class Account extends Eloquent } public function getNextInvoiceNumber() - { - $order = Invoice::withTrashed()->scope(false, $this->id)->orderBy('invoice_number', 'DESC')->first(); + { + $order = Invoice::withTrashed()->scope(false, $this->id)->orderBy('created_at', 'DESC')->first(); if ($order) { - $number = intval($order->invoice_number) + 1; + $number = preg_replace("/[^0-9]/", "", $order->invoice_number); + $number = intval($number) + 1; return str_pad($number, 4, "0", STR_PAD_LEFT); } else @@ -106,4 +116,15 @@ class Account extends Eloquent return DEFAULT_INVOICE_NUMBER; } } + + public function loadLocalizationSettings() + { + $this->load('timezone', 'date_format', 'datetime_format'); + + Session::put(SESSION_TIMEZONE, $this->timezone ? $this->timezone->name : DEFAULT_TIMEZONE); + Session::put(SESSION_DATE_FORMAT, $this->date_format ? $this->date_format->format : DEFAULT_DATE_FORMAT); + Session::put(SESSION_DATE_PICKER_FORMAT, $this->date_format ? $this->date_format->picker_format : DEFAULT_DATE_PICKER_FORMAT); + Session::put(SESSION_DATETIME_FORMAT, $this->datetime_format ? $this->datetime_format->format : DEFAULT_DATETIME_FORMAT); + Session::put(SESSION_CURRENCY, $this->currency_id ? $this->currency_id : DEFAULT_CURRENCY); + } } \ No newline at end of file diff --git a/app/models/Activity.php b/app/models/Activity.php index 10be81338ad2..8a1f61dc713c 100755 --- a/app/models/Activity.php +++ b/app/models/Activity.php @@ -234,6 +234,23 @@ class Activity extends Eloquent public static function viewInvoice($invitation) { + $invoice = $invitation->invoice; + + if (!$invoice->isViewed()) + { + $invoice->invoice_status_id = INVOICE_STATUS_VIEWED; + $invoice->save(); + } + + $now = Carbon::now()->toDateTimeString(); + + $invitation->viewed_date = $now; + $invitation->save(); + + $client = $invoice->client; + $client->last_login = $now; + $client->save(); + $activity = new Activity; $activity->user_id = $invitation->user_id; $activity->account_id = $invitation->user->account_id; diff --git a/app/models/Client.php b/app/models/Client.php index 2c91d6f02eac..06a266e5b601 100755 --- a/app/models/Client.php +++ b/app/models/Client.php @@ -37,14 +37,14 @@ class Client extends EntityModel return $this->belongsTo('Country'); } - public function client_size() + public function size() { - return $this->belongsTo('ClientSize'); + return $this->belongsTo('Size'); } - public function client_industry() + public function industry() { - return $this->belongsTo('ClientIndustry'); + return $this->belongsTo('Industry'); } public function getName() diff --git a/app/models/Country.php b/app/models/Country.php index bfd714a7261f..0c273c4ad513 100755 --- a/app/models/Country.php +++ b/app/models/Country.php @@ -2,5 +2,5 @@ class Country extends Eloquent { - + protected $visible = ['id', 'name']; } \ No newline at end of file diff --git a/app/models/ClientSize.php b/app/models/Industry.php similarity index 54% rename from app/models/ClientSize.php rename to app/models/Industry.php index 2dea3ae45193..66c1a1cbadaf 100755 --- a/app/models/ClientSize.php +++ b/app/models/Industry.php @@ -1,6 +1,6 @@ setVisible(['invoice_number', 'discount', 'po_number', 'invoice_date', 'due_date', 'terms', 'currency_id', 'public_notes', 'amount', 'balance', 'invoice_items', 'client', 'tax_name', 'tax_rate']); + $this->setVisible(['invoice_number', 'discount', 'po_number', 'invoice_date', 'due_date', 'terms', 'currency_id', 'public_notes', 'amount', 'balance', 'invoice_items', 'client', 'tax_name', 'tax_rate', 'account']); - $this->client->setVisible(['name', 'address1', 'address2', 'city', 'state', 'postal_code', 'work_phone', 'payment_terms', 'contacts']); + $this->client->setVisible(['name', 'address1', 'address2', 'city', 'state', 'postal_code', 'work_phone', 'payment_terms', 'contacts', 'country']); + $this->account->setVisible(['name', 'address1', 'address2', 'city', 'state', 'postal_code', 'country']); foreach ($this->invoice_items as $invoiceItem) { diff --git a/app/models/ClientIndustry.php b/app/models/Size.php similarity index 51% rename from app/models/ClientIndustry.php rename to app/models/Size.php index caffc42b0197..d4f9f2cac3ab 100755 --- a/app/models/ClientIndustry.php +++ b/app/models/Size.php @@ -1,6 +1,6 @@ invitations as $invitation) { - $invitation->sent_date = Carbon::now()->toDateTimeString(); + $invitation->sent_date = \Carbon::now()->toDateTimeString(); $invitation->save(); $data = array('link' => URL::to('view') . '/' . $invitation->invitation_key); diff --git a/app/ninja/repositories/ClientRepository.php b/app/ninja/repositories/ClientRepository.php index dbfed6632a93..ef9f23c0f8b4 100755 --- a/app/ninja/repositories/ClientRepository.php +++ b/app/ninja/repositories/ClientRepository.php @@ -5,6 +5,29 @@ use Contact; class ClientRepository { + public function find($filter = null) + { + $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','clients.work_phone','contacts.email','clients.currency_id'); + + if ($filter) + { + $query->where(function($query) use ($filter) + { + $query->where('clients.name', 'like', '%'.$filter.'%') + ->orWhere('contacts.first_name', 'like', '%'.$filter.'%') + ->orWhere('contacts.last_name', 'like', '%'.$filter.'%') + ->orWhere('contacts.email', 'like', '%'.$filter.'%'); + }); + } + + return $query; + } + public function save($publicId, $data) { if ($publicId == "-1") @@ -28,8 +51,8 @@ class ClientRepository $client->postal_code = trim($data['postal_code']); $client->country_id = $data['country_id'] ? $data['country_id'] : null; $client->private_notes = trim($data['private_notes']); - $client->client_size_id = $data['client_size_id'] ? $data['client_size_id'] : null; - $client->client_industry_id = $data['client_industry_id'] ? $data['client_industry_id'] : null; + $client->size_id = $data['size_id'] ? $data['size_id'] : null; + $client->industry_id = $data['industry_id'] ? $data['industry_id'] : null; $client->currency_id = $data['currency_id'] ? $data['currency_id'] : null; $client->payment_terms = $data['payment_terms']; $client->website = trim($data['website']); diff --git a/app/ninja/repositories/CreditRepository.php b/app/ninja/repositories/CreditRepository.php new file mode 100755 index 000000000000..86c64f1aba31 --- /dev/null +++ b/app/ninja/repositories/CreditRepository.php @@ -0,0 +1,75 @@ +join('clients', 'clients.id', '=','credits.client_id') + ->join('contacts', 'contacts.client_id', '=', 'clients.id') + ->where('clients.account_id', '=', \Auth::user()->account_id) + ->where('clients.deleted_at', '=', null) + ->where('credits.deleted_at', '=', null) + ->where('contacts.is_primary', '=', true) + ->select('credits.public_id', 'clients.name as client_name', 'clients.public_id as client_public_id', 'credits.amount', 'credits.credit_date', 'credits.currency_id', 'contacts.first_name', 'contacts.last_name', 'contacts.email'); + + if ($clientPublicId) + { + $query->where('clients.public_id', '=', $clientPublicId); + } + + if ($filter) + { + $query->where(function($query) use ($filter) + { + $query->where('clients.name', 'like', '%'.$filter.'%'); + }); + } + + return $query; + } + + public function save($publicId = null, $input) + { + if ($publicId) + { + $credit = Credit::scope($publicId)->firstOrFail(); + } + else + { + $credit = Credit::createNew(); + } + + $credit->client_id = Client::getPrivateId($input['client']); + $credit->credit_date = Utils::toSqlDate($input['credit_date']); + $credit->invoice_id = isset($input['invoice']) && $input['invoice'] != "-1" ? Invoice::getPrivateId($input['invoice']) : null; + $credit->amount = floatval($input['amount']); + $credit->currency_id = $input['currency_id'] ? $input['currency_id'] : null; + $credit->save(); + + return $credit; + } + + public function bulk($ids, $action) + { + $credits = Credit::scope($ids)->get(); + + foreach ($credits as $credit) + { + if ($action == 'delete') + { + $credit->is_deleted = true; + $credit->save(); + } + + $credit->delete(); + } + + return count($credits); + } +} \ No newline at end of file diff --git a/app/ninja/repositories/PaymentRepository.php b/app/ninja/repositories/PaymentRepository.php new file mode 100755 index 000000000000..99728456b8f7 --- /dev/null +++ b/app/ninja/repositories/PaymentRepository.php @@ -0,0 +1,76 @@ +join('clients', 'clients.id', '=','payments.client_id') + ->leftJoin('invoices', 'invoices.id', '=','payments.invoice_id') + ->join('contacts', 'contacts.client_id', '=', 'clients.id') + ->where('payments.account_id', '=', \Auth::user()->account_id) + ->where('payments.deleted_at', '=', null) + ->where('clients.deleted_at', '=', null) + ->where('contacts.is_primary', '=', true) + ->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', 'payments.currency_id', 'contacts.first_name', 'contacts.last_name', 'contacts.email'); + + if ($clientPublicId) + { + $query->where('clients.public_id', '=', $clientPublicId); + } + + if ($filter) + { + $query->where(function($query) use ($filter) + { + $query->where('clients.name', 'like', '%'.$filter.'%'); + }); + } + + return $query; + } + + public function save($publicId = null, $input) + { + if ($publicId) + { + $payment = Payment::scope($publicId)->firstOrFail(); + } + else + { + $payment = Payment::createNew(); + } + + $payment->client_id = Client::getPrivateId($input['client']); + $payment->invoice_id = isset($input['invoice']) && $input['invoice'] != "-1" ? Invoice::getPrivateId($input['invoice']) : null; + $payment->currency_id = $input['currency_id'] ? $input['currency_id'] : null; + $payment->payment_date = Utils::toSqlDate($input['payment_date']); + $payment->amount = floatval($input['amount']); + $payment->save(); + + return $payment; + } + + public function bulk($ids, $action) + { + $payments = Payment::scope($ids)->get(); + + foreach ($payments as $payment) + { + if ($action == 'delete') + { + $payment->is_deleted = true; + $payment->save(); + } + + $payment->delete(); + } + + return count($payments); + } +} \ No newline at end of file diff --git a/app/views/accounts/details.blade.php b/app/views/accounts/details.blade.php index 1494507c7632..594e9a126162 100755 --- a/app/views/accounts/details.blade.php +++ b/app/views/accounts/details.blade.php @@ -42,7 +42,7 @@ {{ Former::text('state')->label('State/Province') }} {{ Former::text('postal_code') }} {{ Former::select('country_id')->addOption('','')->label('Country') - ->fromQuery($countries, 'name', 'id')->select($account ? $account->country_id : '') }} + ->fromQuery($countries, 'name', 'id') }} @@ -53,6 +53,13 @@ {{ Former::text('last_name') }} {{ Former::text('email') }} {{ Former::text('phone') }} + + {{ Former::legend('Additional Info') }} + {{ Former::select('size_id')->addOption('','')->label('Size') + ->fromQuery($sizes, 'name', 'id') }} + {{ Former::select('industry_id')->addOption('','')->label('Industry') + ->fromQuery($industries, 'name', 'id') }} + diff --git a/app/views/accounts/settings.blade.php b/app/views/accounts/settings.blade.php index b5eea5d9bf48..9f4233b3c544 100755 --- a/app/views/accounts/settings.blade.php +++ b/app/views/accounts/settings.blade.php @@ -18,7 +18,8 @@ @endforeach @endif - {{ Former::select('gateway_id')->label('Provider')->addOption('', '')->fromQuery($gateways, 'name', 'id')->onchange('setFieldsShown()'); }} + {{ Former::select('gateway_id')->label('Provider')->addOption('', '') + ->fromQuery($gateways, 'name', 'id')->onchange('setFieldsShown()'); }} @foreach ($gateways as $gateway) @@ -41,13 +42,13 @@ {{ Former::legend('Localization') }} {{ Former::select('currency_id')->addOption('','')->label('Currency') - ->fromQuery($currencies, 'name', 'id')->select($account->currency_id) }} + ->fromQuery($currencies, 'name', 'id') }} {{ Former::select('timezone_id')->addOption('','')->label('Timezone') - ->fromQuery($timezones, 'location', 'id')->select($account->timezone_id) }} + ->fromQuery($timezones, 'location', 'id') }} {{ Former::select('date_format_id')->addOption('','')->label('Date Format') - ->fromQuery($dateFormats, 'label', 'id')->select($account->date_format_id) }} + ->fromQuery($dateFormats, 'label', 'id') }} {{ Former::select('datetime_format_id')->addOption('','')->label('Date/Time Format') - ->fromQuery($datetimeFormats, 'label', 'id')->select($account->datetime_format_id) }} + ->fromQuery($datetimeFormats, 'label', 'id') }} {{ Former::legend('Notifications') }} {{ Former::checkbox('notify_sent')->label(' ')->text('Email me when an invoice is sent') }} diff --git a/app/views/client.blade.php b/app/views/client.blade.php index 5eb30ac51eb8..7794f9adcd3c 100755 --- a/app/views/client.blade.php +++ b/app/views/client.blade.php @@ -15,7 +15,7 @@ {{ Former::text('state') }} {{ Former::text('postal_code') }} {{ Former::select('country_id')->addOption('','')->label('Country') - ->fromQuery($countries, 'name', 'id')->select($client ? $client->country_id : '') }} + ->fromQuery($countries, 'name', 'id') }} diff --git a/app/views/clients/edit.blade.php b/app/views/clients/edit.blade.php index 35bf06cf8838..8fe5365bb636 100755 --- a/app/views/clients/edit.blade.php +++ b/app/views/clients/edit.blade.php @@ -35,7 +35,7 @@ {{ Former::text('state')->label('State/Province') }} {{ Former::text('postal_code') }} {{ Former::select('country_id')->addOption('','')->label('Country') - ->fromQuery($countries, 'name', 'id')->select($client ? $client->country_id : '') }} + ->fromQuery($countries, 'name', 'id') }} @@ -68,10 +68,10 @@ ->fromQuery($paymentTerms, 'name', 'num_days') }} {{ Former::select('currency_id')->addOption('','')->label('Currency') ->fromQuery($currencies, 'name', 'id')->select(Session::get(SESSION_CURRENCY, DEFAULT_CURRENCY)) }} - {{ Former::select('client_size_id')->addOption('','')->label('Size') - ->fromQuery($clientSizes, 'name', 'id')->select($client ? $client->client_size_id : '') }} - {{ Former::select('client_industry_id')->addOption('','')->label('Industry') - ->fromQuery($clientIndustries, 'name', 'id')->select($client ? $client->client_industry_id : '') }} + {{ Former::select('size_id')->addOption('','')->label('Size') + ->fromQuery($sizes, 'name', 'id') }} + {{ Former::select('industry_id')->addOption('','')->label('Industry') + ->fromQuery($industries, 'name', 'id') }} {{ Former::textarea('private_notes') }} diff --git a/app/views/header.blade.php b/app/views/header.blade.php index f9d03a0b3e52..271b256758e9 100755 --- a/app/views/header.blade.php +++ b/app/views/header.blade.php @@ -87,10 +87,11 @@ + @endif