Bug fixes

This commit is contained in:
Hillel Coren 2013-12-09 11:38:49 +02:00
parent 352cf9182a
commit 78d2d749fb
14 changed files with 222 additions and 55 deletions

View File

@ -0,0 +1,69 @@
<?php
use Illuminate\Console\Command;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Input\InputArgument;
class SendRecurringInvoices extends Command {
/**
* The console command name.
*
* @var string
*/
protected $name = 'ninja:send-invoices';
/**
* The console command description.
*
* @var string
*/
protected $description = 'Send recurring invoices';
/**
* Create a new command instance.
*
* @return void
*/
public function __construct()
{
parent::__construct();
}
/**
* Execute the console command.
*
* @return void
*/
public function fire()
{
$this->info('Running SendRecurringInvoices...');
$this->info('Done');
}
/**
* Get the console command arguments.
*
* @return array
*/
protected function getArguments()
{
return array(
//array('example', InputArgument::REQUIRED, 'An example argument.'),
);
}
/**
* Get the console command options.
*
* @return array
*/
protected function getOptions()
{
return array(
//array('example', null, InputOption::VALUE_OPTIONAL, 'An example option.', null),
);
}
}

View File

@ -44,9 +44,12 @@ class ClientController extends \BaseController {
Select <span class="caret"></span> Select <span class="caret"></span>
</button> </button>
<ul class="dropdown-menu" role="menu"> <ul class="dropdown-menu" role="menu">
<li><a href="' . URL::to('invoices/create/'.$model->public_id) . '">New Invoice</a></li>
<li><a href="' . URL::to('clients/'.$model->public_id.'/edit') . '">Edit Client</a></li> <li><a href="' . URL::to('clients/'.$model->public_id.'/edit') . '">Edit Client</a></li>
<li class="divider"></li> <li class="divider"></li>
<li><a href="' . URL::to('invoices/create/'.$model->public_id) . '">New Invoice</a></li>
<li><a href="' . URL::to('payments/create/'.$model->public_id) . '">New Payment</a></li>
<li><a href="' . URL::to('credits/create/'.$model->public_id) . '">New Credit</a></li>
<li class="divider"></li>
<li><a href="javascript:archiveEntity(' . $model->public_id. ')">Archive Client</a></li> <li><a href="javascript:archiveEntity(' . $model->public_id. ')">Archive Client</a></li>
<li><a href="javascript:deleteEntity(' . $model->public_id. ')">Delete Client</a></li> <li><a href="javascript:deleteEntity(' . $model->public_id. ')">Delete Client</a></li>
</ul> </ul>

View File

@ -56,10 +56,15 @@ class CreditController extends \BaseController {
} }
public function create() public function create($clientPublicId)
{ {
$client = null;
if ($clientPublicId) {
$client = Client::scope($clientPublicId)->firstOrFail();
}
$data = array( $data = array(
'client' => null, 'client' => $client,
'credit' => null, 'credit' => null,
'method' => 'POST', 'method' => 'POST',
'url' => 'credits', 'url' => 'credits',

View File

@ -245,11 +245,8 @@ class InvoiceController extends \BaseController {
'method' => 'PUT', 'method' => 'PUT',
'url' => 'invoices/' . $publicId, 'url' => 'invoices/' . $publicId,
'title' => '- ' . $invoice->invoice_number, 'title' => '- ' . $invoice->invoice_number,
'account' => Auth::user()->account, 'client' => $invoice->client);
'products' => Product::scope()->get(array('product_key','notes','cost','qty')), $data = array_merge($data, InvoiceController::getViewModel());
'countries' => Country::orderBy('name')->get(),
'client' => $invoice->client,
'clients' => Client::scope()->orderBy('name')->get());
return View::make('invoices.edit', $data); return View::make('invoices.edit', $data);
} }
@ -271,12 +268,29 @@ class InvoiceController extends \BaseController {
'url' => 'invoices', 'url' => 'invoices',
'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(), $data = array_merge($data, InvoiceController::getViewModel());
return View::make('invoices.edit', $data);
}
private static function getViewModel()
{
return [
'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()); 'countries' => Country::orderBy('name')->get(),
return View::make('invoices.edit', $data); 'clients' => Client::scope()->orderBy('name')->get(),
'frequencies' => array(
0 => '',
1 => 'Weekly',
2 => 'Two weeks',
3 => 'Four weeks',
4 => 'Monthly',
5 => 'Three months',
6 => 'Six months',
7 => 'Annually'
)
];
} }
/** /**
@ -353,9 +367,13 @@ class InvoiceController extends \BaseController {
$invoice->invoice_number = trim(Input::get('invoice_number')); $invoice->invoice_number = trim(Input::get('invoice_number'));
$invoice->discount = 0; $invoice->discount = 0;
$invoice->invoice_date = Utils::toSqlDate(Input::get('invoice_date')); $invoice->invoice_date = Utils::toSqlDate(Input::get('invoice_date'));
$invoice->due_date = Utils::toSqlDate(Input::get('due_date')); $invoice->due_date = Utils::toSqlDate(Input::get('due_date', null));
$invoice->notes = Input::get('notes'); $invoice->notes = Input::get('notes');
$invoice->how_often = Input::get('how_often');
$invoice->start_date = Utils::toSqlDate(Input::get('start_date', null));
$invoice->end_date = Utils::toSqlDate(Input::get('end_date', null));
$client->invoices()->save($invoice); $client->invoices()->save($invoice);
$items = json_decode(Input::get('items')); $items = json_decode(Input::get('items'));

View File

@ -58,10 +58,15 @@ class PaymentController extends \BaseController
} }
public function create() public function create($clientPublicId = 0)
{ {
$client = null;
if ($clientPublicId) {
$client = Client::scope($clientPublicId)->firstOrFail();
}
$data = array( $data = array(
'client' => null, 'client' => $client,
'invoice' => null, 'invoice' => null,
'invoices' => Invoice::with('client')->scope()->orderBy('invoice_number')->get(), 'invoices' => Invoice::with('client')->scope()->orderBy('invoice_number')->get(),
'payment' => null, 'payment' => null,

View File

@ -210,12 +210,16 @@ class ConfideSetupUsersTable extends Migration {
$t->string('invoice_number'); $t->string('invoice_number');
$t->float('discount'); $t->float('discount');
$t->date('invoice_date'); $t->date('invoice_date');
$t->date('due_date'); $t->date('due_date')->nullable();
$t->text('notes'); $t->text('notes');
$t->decimal('total', 10, 2); $t->decimal('total', 10, 2);
$t->decimal('balance', 10, 2); $t->decimal('balance', 10, 2);
$t->integer('how_often');
$t->date('start_date')->nullable();
$t->date('end_date')->nullable();
$t->foreign('client_id')->references('id')->on('clients')->onDelete('cascade'); $t->foreign('client_id')->references('id')->on('clients')->onDelete('cascade');
$t->foreign('account_id')->references('id')->on('accounts'); $t->foreign('account_id')->references('id')->on('accounts');
$t->foreign('invoice_status_id')->references('id')->on('invoice_statuses'); $t->foreign('invoice_status_id')->references('id')->on('invoice_statuses');

View File

@ -78,26 +78,11 @@ class Utils
return $date->toFormattedDateString(); return $date->toFormattedDateString();
} }
/*
function toDateString($date)
{
if ($date->year < 1900) {
return '';
}
$tz = Session::get('tz');
if (!$tz) {
$tz = 'US/Eastern';
}
$date->tz = $tz;
return $date->toFormattedDateString();
}
*/
public static function toSqlDate($date) public static function toSqlDate($date)
{ {
if (!$date) if (!$date)
{ {
return ''; return null;
} }
return DateTime::createFromFormat('m/d/Y', $date); return DateTime::createFromFormat('m/d/Y', $date);

View File

@ -34,6 +34,11 @@ class Invoice extends EntityModel
return ENTITY_INVOICE; return ENTITY_INVOICE;
} }
public function isRecurring()
{
return $this->how_often || $this->start_date || $this->end_date;
}
/* /*
public function getTotal() public function getTotal()
{ {

View File

@ -39,7 +39,7 @@ Route::filter('auth', function()
{ {
if (!Auth::check()) if (!Auth::check())
{ {
return Redirect::to('/login'); return Redirect::to('/');
} }
}); });
@ -57,16 +57,18 @@ Route::group(array('before' => 'auth'), function()
Route::resource('invoices', 'InvoiceController'); Route::resource('invoices', 'InvoiceController');
Route::get('api/invoices/{client_id?}', array('as'=>'api.invoices', 'uses'=>'InvoiceController@getDatatable')); Route::get('api/invoices/{client_id?}', array('as'=>'api.invoices', 'uses'=>'InvoiceController@getDatatable'));
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::get('payments/{id}/edit', function() { return View::make('header'); });
Route::resource('payments', 'PaymentController'); Route::resource('payments', 'PaymentController');
Route::get('payments/create/{client_id?}', 'PaymentController@create');
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::get('credits/{id}/edit', function() { return View::make('header'); });
Route::resource('credits', 'CreditController'); Route::resource('credits', 'CreditController');
Route::get('credits/create/{client_id?}', 'CreditController@create');
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');
@ -133,3 +135,11 @@ define('INVOICE_STATUS_SENT', 2);
define('INVOICE_STATUS_VIEWED', 3); define('INVOICE_STATUS_VIEWED', 3);
define('INVOICE_STATUS_PARTIAL', 4); define('INVOICE_STATUS_PARTIAL', 4);
define('INVOICE_STATUS_PAID', 5); define('INVOICE_STATUS_PAID', 5);
define('FREQUENCY_WEEKLY', 1);
define('FREQUENCY_TWO_WEEKS', 2);
define('FREQUENCY_FOUR_WEEKS', 3);
define('FREQUENCY_MONTHLY', 4);
define('FREQUENCY_THREE_MONTHS', 5);
define('FREQUENCY_SIX_MONTHS', 6);
define('FREQUENCY_ANNUALLY', 7);

View File

@ -11,3 +11,5 @@
| |
*/ */
//Artisan::add(new SendRecurringInvoices);
Artisan::resolve('SendRecurringInvoices');

View File

@ -12,15 +12,25 @@
{{ DropdownButton::normal('Edit Client', {{ DropdownButton::normal('Edit Client',
Navigation::links( Navigation::links(
array( [
array('Edit Client', URL::to('clients/' . $client->public_id . '/edit')), ['Edit Client', URL::to('clients/' . $client->public_id . '/edit')],
array(Navigation::DIVIDER), [Navigation::DIVIDER],
array('Archive Client', "javascript:onArchiveClick()"), ['Archive Client', "javascript:onArchiveClick()"],
array('Delete Client', "javascript:onDeleteClick()"), ['Delete Client', "javascript:onDeleteClick()"],
]
) )
, ['id'=>'normalDropDown'])->split(); }}
{{ DropdownButton::primary('Create Invoice',
Navigation::links(
[
['Create Invoice', URL::to('invoices/create/' . $client->public_id )],
['Create Payment', URL::to('payments/create/' . $client->public_id )],
['Create Credit', URL::to('credits/create/' . $client->public_id )],
]
) )
, array('id'=>'actionDropDown'))->split(); }} , ['id'=>'primaryDropDown'])->split(); }}
{{ Button::primary_link(URL::to('invoices/create/' . $client->public_id), 'Create Invoice') }}
{{ Former::close() }} {{ Former::close() }}
</div> </div>
@ -112,9 +122,12 @@
<script type="text/javascript"> <script type="text/javascript">
$(function() { $(function() {
$('#actionDropDown > button:first').click(function() { $('#normalDropDown > button:first').click(function() {
window.location = '{{ URL::to('clients/' . $client->public_id . '/edit') }}'; window.location = '{{ URL::to('clients/' . $client->public_id . '/edit') }}';
}); });
$('#primaryDropDown > button:first').click(function() {
window.location = '{{ URL::to('invoices/create/' . $client->public_id ) }}';
});
}); });
function onArchiveClick() { function onArchiveClick() {

View File

@ -43,12 +43,14 @@
min-height: 600px; min-height: 600px;
} }
label.checkbox,
label.control-label { label.control-label {
font-weight: normal !important; font-weight: normal !important;
} }
div.panel { div.panel {
padding-left: 0px !important; padding-left: 0px !important;
padding-right: 0px !important; padding-right: 0px !important;
@ -205,6 +207,15 @@
cursor: move !important; cursor: move !important;
} }
/* Animate col width changes */
.row div {
-webkit-transition: width 0.5s ease, margin 0.5s ease;
-moz-transition: width 0.5s ease, margin 0.5s ease;
-o-transition: width 0.5s ease, margin 0.5s ease;
transition: width 0.5s ease, margin 0.5s ease;
}
</style> </style>
@stop @stop

View File

@ -25,23 +25,33 @@
{{ Former::populateField('id', $invoice->public_id); }} {{ Former::populateField('id', $invoice->public_id); }}
{{ Former::populateField('invoice_date', Utils::fromSqlDate($invoice->invoice_date)); }} {{ Former::populateField('invoice_date', Utils::fromSqlDate($invoice->invoice_date)); }}
{{ Former::populateField('due_date', Utils::fromSqlDate($invoice->due_date)); }} {{ Former::populateField('due_date', Utils::fromSqlDate($invoice->due_date)); }}
{{ Former::populateField('start_date', Utils::fromSqlDate($invoice->start_date)); }}
{{ Former::populateField('end_date', Utils::fromSqlDate($invoice->end_date)); }}
@else @else
{{ Former::populateField('invoice_number', $invoiceNumber) }} {{ Former::populateField('invoice_number', $invoiceNumber) }}
{{ Former::populateField('invoice_date', date('m/d/Y')) }} {{ Former::populateField('invoice_date', date('m/d/Y')) }}
@endif @endif
<div class="row"> <div class="row" style="min-height:195px">
<div class="col-md-6"> <div class="col-md-6" id="col_1">
{{ Former::select('client')->addOption('', '')->fromQuery($clients, 'name', 'public_id')->select($client ? $client->public_id : '')->addGroupClass('client_select') {{ Former::select('client')->addOption('', '')->fromQuery($clients, 'name', 'public_id')->select($client ? $client->public_id : '')->addGroupClass('client_select')
->help('<a style="cursor:pointer" data-toggle="modal" id="modalLink" onclick="showCreateNew()">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" id="col_2">
{{ Former::text('invoice_number')->label('Invoice #') }} {{ 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')->data_date_format('yyyy-mm-dd') --}}
{{ Former::text('invoice_date')->label('Invoice Date') }} {{ Former::text('invoice_date') }}
{{ Former::text('due_date')->label('Due Date') }} {{ Former::text('due_date')->help('<a id="showRecurring" style="cursor:pointer" onclick="toggleRecurring(true)">Enable recurring</a>') }}
{{-- Former::text('discount')->data_bind("value: discount, valueUpdate: 'afterkeydown'") --}} {{-- Former::text('discount')->data_bind("value: discount, valueUpdate: 'afterkeydown'") --}}
</div>
<div class="col-md-3" id="col_3" style="display:none">
{{ Former::select('how_often')->options($frequencies) }}
{{ Former::text('start_date') }}
{{ Former::text('end_date')->help('<a id="hideRecurring" style="cursor:pointer;display:none" onclick="toggleRecurring(false)">Disable recurring</a>') }}
</div> </div>
</div> </div>
@ -246,7 +256,7 @@
refreshPDF(); refreshPDF();
}); });
$('#due_date').datepicker({ $('#due_date,#start_date').datepicker({
autoclose: true, autoclose: true,
todayHighlight: true todayHighlight: true
}); });
@ -284,6 +294,10 @@
}); });
@if ($invoice && $invoice->isRecurring())
toggleRecurring(true);
@endif;
applyComboboxListeners(); applyComboboxListeners();
refreshPDF(); refreshPDF();
}); });
@ -622,6 +636,26 @@
} }
} }
function toggleRecurring(show)
{
$('#col_1').toggleClass('col-md-6 col-md-5');
$('#col_2').toggleClass('col-md-5 col-md-3');
if (show) {
setTimeout(function() {
$('#col_3').show();
}, 500);
} else {
$('#col_3').hide();
}
$('#showRecurring,#hideRecurring').toggle();
if (!show) {
$('#how_often, #start_date, #end_date').val('')
}
}
var products = {{ $products }}; var products = {{ $products }};
var clients = {{ $clients }}; var clients = {{ $clients }};
var clientMap = {}; var clientMap = {};

View File

@ -86,6 +86,11 @@
$input.append(new Option(client.name, client.public_id)); $input.append(new Option(client.name, client.public_id));
} }
@if ($client)
$('select#client').val({{ $client->public_id }});
@endif
$input.combobox();
$input.on('change', function(e) { $input.on('change', function(e) {
console.log('client change'); console.log('client change');
var clientId = $('input[name=client]').val(); var clientId = $('input[name=client]').val();
@ -106,7 +111,6 @@
} }
$('select#invoice').combobox('refresh'); $('select#invoice').combobox('refresh');
}).trigger('change'); }).trigger('change');
$input.combobox();
var $input = $('select#invoice').on('change', function(e) { var $input = $('select#invoice').on('change', function(e) {
$clientCombobox = $('select#client'); $clientCombobox = $('select#client');
@ -122,7 +126,6 @@
autoclose: true, autoclose: true,
todayHighlight: true todayHighlight: true
}); });
}); });
</script> </script>