From dd088d866815a13048894f0b20288a385a514008 Mon Sep 17 00:00:00 2001 From: Hillel Coren Date: Mon, 2 Dec 2013 14:22:29 +0200 Subject: [PATCH] Added timezone support --- app/controllers/AccountController.php | 13 +- app/controllers/ClientController.php | 2 +- app/controllers/InvoiceController.php | 16 ++- ...11_05_180133_confide_setup_users_table.php | 13 +- app/database/seeds/ConstantsSeeder.php | 119 ++++++++++++++++++ app/models/Account.php | 5 + app/models/Activity.php | 6 +- app/models/Client.php | 2 +- app/models/Invitation.php | 10 ++ app/models/Timezone.php | 6 + app/routes.php | 28 ++++- app/views/accounts/details.blade.php | 3 +- app/views/header.blade.php | 2 +- app/views/invoices/edit.blade.php | 3 +- public/js/script.js | 14 ++- 15 files changed, 218 insertions(+), 24 deletions(-) create mode 100755 app/models/Timezone.php diff --git a/app/controllers/AccountController.php b/app/controllers/AccountController.php index cb4e344132..cb977de907 100755 --- a/app/controllers/AccountController.php +++ b/app/controllers/AccountController.php @@ -37,6 +37,8 @@ class AccountController extends \BaseController { } Auth::login($user); + Session::put('tz', 'US/Eastern'); + return Redirect::to('invoices/create'); } @@ -46,8 +48,9 @@ class AccountController extends \BaseController { { $account = Account::with('users')->find(Auth::user()->account_id); $countries = Country::orderBy('name')->get(); + $timezones = Timezone::orderBy('location')->get(); - return View::make('accounts.details', array('account'=>$account, 'countries'=>$countries)); + return View::make('accounts.details', array('account'=>$account, 'countries'=>$countries, 'timezones'=>$timezones)); } else if ($section == ACCOUNT_SETTINGS) { @@ -421,7 +424,8 @@ class AccountController extends \BaseController { $account->city = Input::get('city'); $account->state = Input::get('state'); $account->postal_code = Input::get('postal_code'); - $account->country_id = Input::get('country_id'); + $account->country_id = Input::get('country_id') ? Input::get('country_id') : null; + $account->timezone_id = Input::get('timezone_id') ? Input::get('timezone_id') : null; $account->save(); $user = $account->users()->first(); @@ -431,6 +435,11 @@ class AccountController extends \BaseController { $user->phone = Input::get('phone'); $user->save(); + if (Input::get('timezone_id')) { + $timezone = Timezone::find(Input::get('timezone_id')); + Session::put('tz', $timezone->name); + } + /* Logo image file */ if ($file = Input::file('logo')) { diff --git a/app/controllers/ClientController.php b/app/controllers/ClientController.php index 45ebc493e5..98439f8059 100755 --- a/app/controllers/ClientController.php +++ b/app/controllers/ClientController.php @@ -28,7 +28,7 @@ class ClientController extends \BaseController { ->addColumn('contact', function($model) { return $model->contacts[0]->getFullName(); }) ->addColumn('balance', function($model) { return '$' . $model->balance; }) ->addColumn('last_login', function($model) { return $model->contacts[0]->getLastLogin(); }) - ->addColumn('date_created', function($model) { return $model->getDateCreated(); }) + ->addColumn('date_created', function($model) { return $model->created_at->toFormattedDateString(); }) ->addColumn('email', function($model) { return HTML::mailto($model->contacts[0]->email, $model->contacts[0]->email); }) ->addColumn('phone', function($model) { return $model->contacts[0]->phone; }) ->addColumn('dropdown', function($model) diff --git a/app/controllers/InvoiceController.php b/app/controllers/InvoiceController.php index f24b640c0e..ec3b8c2d4f 100755 --- a/app/controllers/InvoiceController.php +++ b/app/controllers/InvoiceController.php @@ -37,8 +37,8 @@ class InvoiceController extends \BaseController { return $table->addColumn('total', function($model){ return '$' . money_format('%i', $model->getTotal()); }) ->addColumn('amount_due', function($model) { return '$' . money_format('%i', $model->getTotal()); }) - ->addColumn('invoice_date', function($model) { return (new Carbon($model->invoice_date))->toFormattedDateString(); }) - ->addColumn('due_date', function($model) { return $model->due_date == '0000-00-00' ? '' : (new Carbon($model->due_date))->toFormattedDateString(); }) + ->addColumn('invoice_date', function($model) { return fromSqlDate($model->invoice_date); }) + ->addColumn('due_date', function($model) { return fromSqlDate($model->due_date); }) ->addColumn('status', function($model) { return $model->invoice_status->name; }) ->addColumn('dropdown', function($model) { @@ -61,13 +61,14 @@ class InvoiceController extends \BaseController { public function view($key) { - $invitation = Invitation::with('invoice.invoice_items', 'invoice.client.account.account_gateways')->where('key', '=', $key)->firstOrFail(); - $contact = null; + $invitation = Invitation::with('user', 'invoice.account', 'invoice.invoice_items', 'invoice.client.account.account_gateways')->where('key', '=', $key)->firstOrFail(); + + $user = $invitation->user; - $invitation->viewed_date = new date('Y-m-d H:i:s'); + $invitation->viewed_date = Carbon::now()->toDateTimeString(); $invitation->save(); - Activity::log($invitation->invoice->client, ACTIVITY_TYPE_VIEW_INVOICE, $contact, $invitation); + Activity::viewInvoice($invitation); return View::make('invoices.view')->with('invoice', $invitation->invoice); } @@ -320,9 +321,12 @@ class InvoiceController extends \BaseController { $product->key = $item->product_key; } + /* $product->notes = $item->notes; $product->cost = $item->cost; $product->qty = $item->qty; + */ + $product->save(); } 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 341fae4e00..e3909ed58e 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 @@ -26,6 +26,7 @@ class ConfideSetupUsersTable extends Migration { Schema::dropIfExists('accounts'); Schema::dropIfExists('invoice_statuses'); Schema::dropIfExists('countries'); + Schema::dropIfExists('timezones'); Schema::create('countries', function($table) @@ -46,10 +47,18 @@ class ConfideSetupUsersTable extends Migration { $table->boolean('eea')->default(0); }); + Schema::create('timezones', function($t) + { + $t->increments('id'); + $t->string('name'); + $t->string('location'); + }); Schema::create('accounts', function($t) { $t->increments('id'); + $t->unsignedInteger('timezone_id')->nullable(); + $t->timestamps(); $t->softDeletes(); @@ -65,6 +74,7 @@ class ConfideSetupUsersTable extends Migration { $t->string('postal_code'); $t->unsignedInteger('country_id')->nullable(); + $t->foreign('timezone_id')->references('id')->on('timezones'); $t->foreign('country_id')->references('id')->on('countries'); }); @@ -290,6 +300,7 @@ class ConfideSetupUsersTable extends Migration { $t->unsignedInteger('payment_id'); $t->unsignedInteger('invoice_id'); $t->unsignedInteger('credit_id'); + $t->unsignedInteger('invitation_id'); $t->text('message'); $t->integer('activity_type_id'); @@ -324,6 +335,6 @@ class ConfideSetupUsersTable extends Migration { Schema::dropIfExists('accounts'); Schema::dropIfExists('invoice_statuses'); Schema::dropIfExists('countries'); - + Schema::dropIfExists('timezones'); } } diff --git a/app/database/seeds/ConstantsSeeder.php b/app/database/seeds/ConstantsSeeder.php index 3784966a54..59a549db08 100755 --- a/app/database/seeds/ConstantsSeeder.php +++ b/app/database/seeds/ConstantsSeeder.php @@ -75,5 +75,124 @@ class ConstantsSeeder extends Seeder { Gateway::create($gateway); } + + $timezones = array( + 'Pacific/Midway' => "(GMT-11:00) Midway Island", + 'US/Samoa' => "(GMT-11:00) Samoa", + 'US/Hawaii' => "(GMT-10:00) Hawaii", + 'US/Alaska' => "(GMT-09:00) Alaska", + 'US/Pacific' => "(GMT-08:00) Pacific Time (US & Canada)", + 'America/Tijuana' => "(GMT-08:00) Tijuana", + 'US/Arizona' => "(GMT-07:00) Arizona", + 'US/Mountain' => "(GMT-07:00) Mountain Time (US & Canada)", + 'America/Chihuahua' => "(GMT-07:00) Chihuahua", + 'America/Mazatlan' => "(GMT-07:00) Mazatlan", + 'America/Mexico_City' => "(GMT-06:00) Mexico City", + 'America/Monterrey' => "(GMT-06:00) Monterrey", + 'Canada/Saskatchewan' => "(GMT-06:00) Saskatchewan", + 'US/Central' => "(GMT-06:00) Central Time (US & Canada)", + 'US/Eastern' => "(GMT-05:00) Eastern Time (US & Canada)", + 'US/East-Indiana' => "(GMT-05:00) Indiana (East)", + 'America/Bogota' => "(GMT-05:00) Bogota", + 'America/Lima' => "(GMT-05:00) Lima", + 'America/Caracas' => "(GMT-04:30) Caracas", + 'Canada/Atlantic' => "(GMT-04:00) Atlantic Time (Canada)", + 'America/La_Paz' => "(GMT-04:00) La Paz", + 'America/Santiago' => "(GMT-04:00) Santiago", + 'Canada/Newfoundland' => "(GMT-03:30) Newfoundland", + 'America/Buenos_Aires' => "(GMT-03:00) Buenos Aires", + 'Greenland' => "(GMT-03:00) Greenland", + 'Atlantic/Stanley' => "(GMT-02:00) Stanley", + 'Atlantic/Azores' => "(GMT-01:00) Azores", + 'Atlantic/Cape_Verde' => "(GMT-01:00) Cape Verde Is.", + 'Africa/Casablanca' => "(GMT) Casablanca", + 'Europe/Dublin' => "(GMT) Dublin", + 'Europe/Lisbon' => "(GMT) Lisbon", + 'Europe/London' => "(GMT) London", + 'Africa/Monrovia' => "(GMT) Monrovia", + 'Europe/Amsterdam' => "(GMT+01:00) Amsterdam", + 'Europe/Belgrade' => "(GMT+01:00) Belgrade", + 'Europe/Berlin' => "(GMT+01:00) Berlin", + 'Europe/Bratislava' => "(GMT+01:00) Bratislava", + 'Europe/Brussels' => "(GMT+01:00) Brussels", + 'Europe/Budapest' => "(GMT+01:00) Budapest", + 'Europe/Copenhagen' => "(GMT+01:00) Copenhagen", + 'Europe/Ljubljana' => "(GMT+01:00) Ljubljana", + 'Europe/Madrid' => "(GMT+01:00) Madrid", + 'Europe/Paris' => "(GMT+01:00) Paris", + 'Europe/Prague' => "(GMT+01:00) Prague", + 'Europe/Rome' => "(GMT+01:00) Rome", + 'Europe/Sarajevo' => "(GMT+01:00) Sarajevo", + 'Europe/Skopje' => "(GMT+01:00) Skopje", + 'Europe/Stockholm' => "(GMT+01:00) Stockholm", + 'Europe/Vienna' => "(GMT+01:00) Vienna", + 'Europe/Warsaw' => "(GMT+01:00) Warsaw", + 'Europe/Zagreb' => "(GMT+01:00) Zagreb", + 'Europe/Athens' => "(GMT+02:00) Athens", + 'Europe/Bucharest' => "(GMT+02:00) Bucharest", + 'Africa/Cairo' => "(GMT+02:00) Cairo", + 'Africa/Harare' => "(GMT+02:00) Harare", + 'Europe/Helsinki' => "(GMT+02:00) Helsinki", + 'Europe/Istanbul' => "(GMT+02:00) Istanbul", + 'Asia/Jerusalem' => "(GMT+02:00) Jerusalem", + 'Europe/Kiev' => "(GMT+02:00) Kyiv", + 'Europe/Minsk' => "(GMT+02:00) Minsk", + 'Europe/Riga' => "(GMT+02:00) Riga", + 'Europe/Sofia' => "(GMT+02:00) Sofia", + 'Europe/Tallinn' => "(GMT+02:00) Tallinn", + 'Europe/Vilnius' => "(GMT+02:00) Vilnius", + 'Asia/Baghdad' => "(GMT+03:00) Baghdad", + 'Asia/Kuwait' => "(GMT+03:00) Kuwait", + 'Africa/Nairobi' => "(GMT+03:00) Nairobi", + 'Asia/Riyadh' => "(GMT+03:00) Riyadh", + 'Asia/Tehran' => "(GMT+03:30) Tehran", + 'Europe/Moscow' => "(GMT+04:00) Moscow", + 'Asia/Baku' => "(GMT+04:00) Baku", + 'Europe/Volgograd' => "(GMT+04:00) Volgograd", + 'Asia/Muscat' => "(GMT+04:00) Muscat", + 'Asia/Tbilisi' => "(GMT+04:00) Tbilisi", + 'Asia/Yerevan' => "(GMT+04:00) Yerevan", + 'Asia/Kabul' => "(GMT+04:30) Kabul", + 'Asia/Karachi' => "(GMT+05:00) Karachi", + 'Asia/Tashkent' => "(GMT+05:00) Tashkent", + 'Asia/Kolkata' => "(GMT+05:30) Kolkata", + 'Asia/Kathmandu' => "(GMT+05:45) Kathmandu", + 'Asia/Yekaterinburg' => "(GMT+06:00) Ekaterinburg", + 'Asia/Almaty' => "(GMT+06:00) Almaty", + 'Asia/Dhaka' => "(GMT+06:00) Dhaka", + 'Asia/Novosibirsk' => "(GMT+07:00) Novosibirsk", + 'Asia/Bangkok' => "(GMT+07:00) Bangkok", + 'Asia/Jakarta' => "(GMT+07:00) Jakarta", + 'Asia/Krasnoyarsk' => "(GMT+08:00) Krasnoyarsk", + 'Asia/Chongqing' => "(GMT+08:00) Chongqing", + 'Asia/Hong_Kong' => "(GMT+08:00) Hong Kong", + 'Asia/Kuala_Lumpur' => "(GMT+08:00) Kuala Lumpur", + 'Australia/Perth' => "(GMT+08:00) Perth", + 'Asia/Singapore' => "(GMT+08:00) Singapore", + 'Asia/Taipei' => "(GMT+08:00) Taipei", + 'Asia/Ulaanbaatar' => "(GMT+08:00) Ulaan Bataar", + 'Asia/Urumqi' => "(GMT+08:00) Urumqi", + 'Asia/Irkutsk' => "(GMT+09:00) Irkutsk", + 'Asia/Seoul' => "(GMT+09:00) Seoul", + 'Asia/Tokyo' => "(GMT+09:00) Tokyo", + 'Australia/Adelaide' => "(GMT+09:30) Adelaide", + 'Australia/Darwin' => "(GMT+09:30) Darwin", + 'Asia/Yakutsk' => "(GMT+10:00) Yakutsk", + 'Australia/Brisbane' => "(GMT+10:00) Brisbane", + 'Australia/Canberra' => "(GMT+10:00) Canberra", + 'Pacific/Guam' => "(GMT+10:00) Guam", + 'Australia/Hobart' => "(GMT+10:00) Hobart", + 'Australia/Melbourne' => "(GMT+10:00) Melbourne", + 'Pacific/Port_Moresby' => "(GMT+10:00) Port Moresby", + 'Australia/Sydney' => "(GMT+10:00) Sydney", + 'Asia/Vladivostok' => "(GMT+11:00) Vladivostok", + 'Asia/Magadan' => "(GMT+12:00) Magadan", + 'Pacific/Auckland' => "(GMT+12:00) Auckland", + 'Pacific/Fiji' => "(GMT+12:00) Fiji", + ); + + foreach ($timezones as $name => $location) { + Timezone::create(array('name'=>$name, 'location'=>$location)); + } } } \ No newline at end of file diff --git a/app/models/Account.php b/app/models/Account.php index 0e694fa2b9..a5b3120314 100755 --- a/app/models/Account.php +++ b/app/models/Account.php @@ -29,6 +29,11 @@ class Account extends Eloquent return $this->belongsTo('Country'); } + public function timezone() + { + return $this->belongsTo('Timezone'); + } + public function isGatewayConfigured($gatewayId = 0) { if ($gatewayId) diff --git a/app/models/Activity.php b/app/models/Activity.php index 3c1257c92d..d17fe01068 100755 --- a/app/models/Activity.php +++ b/app/models/Activity.php @@ -70,6 +70,7 @@ class Activity extends Eloquent public static function emailInvoice($invitation) { $activity = Activity::getBlank(); + $activity->client_id = $invitation->invoice->client_id; $activity->invoice_id = $invitation->invoice_id; $activity->contact_id = $invitation->contact_id; $activity->activity_type_id = ACTIVITY_TYPE_EMAIL_INVOICE; @@ -111,7 +112,10 @@ class Activity extends Eloquent public static function viewInvoice($invitation) { $activity = new Activity; - $activity->invitation_id = $invitation->invitation_id; + $activity->user_id = $invitation->user_id; + $activity->account_id = $invitation->user->account_id; + $activity->client_id = $invitation->invoice->client_id; + $activity->invitation_id = $invitation->id; $activity->contact_id = $invitation->contact_id; $activity->invoice_id = $invitation->invoice_id; $activity->activity_type_id = ACTIVITY_TYPE_VIEW_INVOICE; diff --git a/app/models/Client.php b/app/models/Client.php index 2b9c9bea07..179b2d67e9 100755 --- a/app/models/Client.php +++ b/app/models/Client.php @@ -100,7 +100,7 @@ class Client extends Eloquent implements iEntity } public function getDateCreated() - { + { if ($this->created_at == '0000-00-00 00:00:00') { return '---'; diff --git a/app/models/Invitation.php b/app/models/Invitation.php index 17200e483c..c66ea1cd1e 100644 --- a/app/models/Invitation.php +++ b/app/models/Invitation.php @@ -8,6 +8,16 @@ class Invitation extends Eloquent { return $this->belongsTo('Invoice'); } + + public function contact() + { + return $this->belongsTo('Contact'); + } + + public function user() + { + return $this->belongsTo('User'); + } } Invitation::created(function($invitation) diff --git a/app/models/Timezone.php b/app/models/Timezone.php new file mode 100755 index 0000000000..e3790b5ff2 --- /dev/null +++ b/app/models/Timezone.php @@ -0,0 +1,6 @@ +year < 1900) { + return ''; + } + $tz = Session::get('tz'); + if (!$tz) { + $tz = 'US/Eastern'; + } + $date->tz = $tz; + return $date->toFormattedDateString(); +} +*/ + +function toDateTimeString($date) +{ + +} + function toSqlDate($date) { if (!$date) @@ -142,14 +162,14 @@ function fromSqlDate($date) { return ''; } - + return DateTime::createFromFormat('Y-m-d', $date)->format('m/d/Y'); } function processedRequest($url) -{ - Session::put(Input::get('_token'), $url); - Session::put('_token', md5(microtime())); +{ + //Session::put(Input::get('_token'), $url); + //Session::put('_token', md5(microtime())); } diff --git a/app/views/accounts/details.blade.php b/app/views/accounts/details.blade.php index ad43e3835c..b18efe2434 100755 --- a/app/views/accounts/details.blade.php +++ b/app/views/accounts/details.blade.php @@ -29,7 +29,8 @@ {{ Former::legend('Account') }} {{ Former::text('name') }} - + {{ Former::select('timezone_id')->addOption('','')->label('Timezone') + ->fromQuery($timezones, 'location', 'id')->select($account->timezone_id) }} {{ Former::file('logo')->max(2, 'MB')->accept('image')->wrap('test') }} @if (file_exists($account->getLogoPath())) diff --git a/app/views/header.blade.php b/app/views/header.blade.php index 2d02cdf802..75f6de9a0f 100755 --- a/app/views/header.blade.php +++ b/app/views/header.blade.php @@ -102,7 +102,7 @@ } div.dataTables_paginate.paging_bootstrap { - margin-top: -20px; + margin-top: -30px; } table.table tbody tr.odd { diff --git a/app/views/invoices/edit.blade.php b/app/views/invoices/edit.blade.php index 8743914ee3..8d49826521 100755 --- a/app/views/invoices/edit.blade.php +++ b/app/views/invoices/edit.blade.php @@ -28,6 +28,7 @@
{{ Former::text('invoice_number')->label('Invoice #') }} + {{-- Former::text('invoice_date')->label('Invoice Date')->data_date_format('yyyy-mm-dd') --}} {{ Former::text('invoice_date')->label('Invoice Date') }} {{ Former::text('due_date')->label('Due Date') }} {{-- Former::text('discount')->data_bind("value: discount, valueUpdate: 'afterkeydown'") --}} @@ -255,7 +256,7 @@ state: "{{ $account->state }}", postal_code: "{{ $account->postal_code }}", country: { - name: "{{ $account->country->name }}" + name: "{{ $account->country ? $account->country->name : '' }}" } }, client: { diff --git a/public/js/script.js b/public/js/script.js index bbe7c20e57..a88685555a 100755 --- a/public/js/script.js +++ b/public/js/script.js @@ -122,7 +122,7 @@ function generatePDF(invoice) { y += 16; doc.text(tableLeft, y, invoice.account.city + ', ' + invoice.account.state + ' ' + invoice.account.postal_code); y += 16; - doc.text(tableLeft, y, invoice.account.country.name); + doc.text(tableLeft, y, invoice.account.country ? invoice.account.country.name : ''); var clientX = headerRight - (doc.getStringUnitWidth(invoice.client.name) * doc.internal.getFontSize()); @@ -186,13 +186,17 @@ function formatMoney(num) { /* Set the defaults for DataTables initialisation */ $.extend( true, $.fn.dataTable.defaults, { - "sDom": "t<'row-fluid'<'span6'l><'span6'p>>", + "sDom": "t<'row-fluid'<'span6'i><'span6'p>>", + //"sDom": "<'row'<'span6'l><'span6'f>r>t<'row'<'span6'i><'span6'p>>", "sPaginationType": "bootstrap", "bProcessing": false, - "bInfo": false, + //"iDisplayLength": 50, + "bInfo": true, "oLanguage": { - "sLengthMenu": "_MENU_ records per page" - } + //"sLengthMenu": "_MENU_ records per page" + "sLengthMenu": "_MENU_" + }, + //"sScrollY": "500px", } );