mirror of
https://github.com/invoiceninja/invoiceninja.git
synced 2025-07-07 11:04:41 -04:00
Bug fixes
This commit is contained in:
parent
352cf9182a
commit
78d2d749fb
69
app/commands/SendRecurringInvoices.php
Executable file
69
app/commands/SendRecurringInvoices.php
Executable 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),
|
||||
);
|
||||
}
|
||||
|
||||
}
|
@ -44,8 +44,11 @@ class ClientController extends \BaseController {
|
||||
Select <span class="caret"></span>
|
||||
</button>
|
||||
<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><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:deleteEntity(' . $model->public_id. ')">Delete Client</a></li>
|
||||
|
@ -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(
|
||||
'client' => null,
|
||||
'client' => $client,
|
||||
'credit' => null,
|
||||
'method' => 'POST',
|
||||
'url' => 'credits',
|
||||
|
@ -245,11 +245,8 @@ class InvoiceController extends \BaseController {
|
||||
'method' => 'PUT',
|
||||
'url' => 'invoices/' . $publicId,
|
||||
'title' => '- ' . $invoice->invoice_number,
|
||||
'account' => Auth::user()->account,
|
||||
'products' => Product::scope()->get(array('product_key','notes','cost','qty')),
|
||||
'countries' => Country::orderBy('name')->get(),
|
||||
'client' => $invoice->client,
|
||||
'clients' => Client::scope()->orderBy('name')->get());
|
||||
'client' => $invoice->client);
|
||||
$data = array_merge($data, InvoiceController::getViewModel());
|
||||
return View::make('invoices.edit', $data);
|
||||
}
|
||||
|
||||
@ -271,14 +268,31 @@ class InvoiceController extends \BaseController {
|
||||
'url' => 'invoices',
|
||||
'title' => '- New Invoice',
|
||||
'client' => $client,
|
||||
'items' => json_decode(Input::old('items')),
|
||||
'countries' => Country::orderBy('name')->get(),
|
||||
'account' => Auth::user()->account,
|
||||
'products' => Product::scope()->get(array('product_key','notes','cost','qty')),
|
||||
'clients' => Client::scope()->orderBy('name')->get());
|
||||
'items' => json_decode(Input::old('items')));
|
||||
$data = array_merge($data, InvoiceController::getViewModel());
|
||||
return View::make('invoices.edit', $data);
|
||||
}
|
||||
|
||||
private static function getViewModel()
|
||||
{
|
||||
return [
|
||||
'account' => Auth::user()->account,
|
||||
'products' => Product::scope()->get(array('product_key','notes','cost','qty')),
|
||||
'countries' => Country::orderBy('name')->get(),
|
||||
'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'
|
||||
)
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Store a newly created resource in storage.
|
||||
*
|
||||
@ -353,9 +367,13 @@ class InvoiceController extends \BaseController {
|
||||
$invoice->invoice_number = trim(Input::get('invoice_number'));
|
||||
$invoice->discount = 0;
|
||||
$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->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);
|
||||
|
||||
$items = json_decode(Input::get('items'));
|
||||
|
@ -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(
|
||||
'client' => null,
|
||||
'client' => $client,
|
||||
'invoice' => null,
|
||||
'invoices' => Invoice::with('client')->scope()->orderBy('invoice_number')->get(),
|
||||
'payment' => null,
|
||||
|
@ -210,12 +210,16 @@ class ConfideSetupUsersTable extends Migration {
|
||||
$t->string('invoice_number');
|
||||
$t->float('discount');
|
||||
$t->date('invoice_date');
|
||||
$t->date('due_date');
|
||||
$t->date('due_date')->nullable();
|
||||
$t->text('notes');
|
||||
|
||||
$t->decimal('total', 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('account_id')->references('id')->on('accounts');
|
||||
$t->foreign('invoice_status_id')->references('id')->on('invoice_statuses');
|
||||
|
@ -78,26 +78,11 @@ class Utils
|
||||
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)
|
||||
{
|
||||
if (!$date)
|
||||
{
|
||||
return '';
|
||||
return null;
|
||||
}
|
||||
|
||||
return DateTime::createFromFormat('m/d/Y', $date);
|
||||
|
@ -34,6 +34,11 @@ class Invoice extends EntityModel
|
||||
return ENTITY_INVOICE;
|
||||
}
|
||||
|
||||
public function isRecurring()
|
||||
{
|
||||
return $this->how_often || $this->start_date || $this->end_date;
|
||||
}
|
||||
|
||||
/*
|
||||
public function getTotal()
|
||||
{
|
||||
|
@ -39,7 +39,7 @@ Route::filter('auth', function()
|
||||
{
|
||||
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::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::get('payments/{id}/edit', function() { return View::make('header'); });
|
||||
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::post('payments/bulk', 'PaymentController@bulk');
|
||||
|
||||
Route::get('credits/{id}/edit', function() { return View::make('header'); });
|
||||
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::post('credits/bulk', 'PaymentController@bulk');
|
||||
|
||||
@ -132,4 +134,12 @@ define('INVOICE_STATUS_DRAFT', 1);
|
||||
define('INVOICE_STATUS_SENT', 2);
|
||||
define('INVOICE_STATUS_VIEWED', 3);
|
||||
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);
|
||||
|
@ -11,3 +11,5 @@
|
||||
|
|
||||
*/
|
||||
|
||||
//Artisan::add(new SendRecurringInvoices);
|
||||
Artisan::resolve('SendRecurringInvoices');
|
||||
|
@ -12,15 +12,25 @@
|
||||
|
||||
{{ DropdownButton::normal('Edit Client',
|
||||
Navigation::links(
|
||||
array(
|
||||
array('Edit Client', URL::to('clients/' . $client->public_id . '/edit')),
|
||||
array(Navigation::DIVIDER),
|
||||
array('Archive Client', "javascript:onArchiveClick()"),
|
||||
array('Delete Client', "javascript:onDeleteClick()"),
|
||||
)
|
||||
[
|
||||
['Edit Client', URL::to('clients/' . $client->public_id . '/edit')],
|
||||
[Navigation::DIVIDER],
|
||||
['Archive Client', "javascript:onArchiveClick()"],
|
||||
['Delete Client', "javascript:onDeleteClick()"],
|
||||
]
|
||||
)
|
||||
, array('id'=>'actionDropDown'))->split(); }}
|
||||
{{ Button::primary_link(URL::to('invoices/create/' . $client->public_id), 'Create Invoice') }}
|
||||
, ['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 )],
|
||||
]
|
||||
)
|
||||
, ['id'=>'primaryDropDown'])->split(); }}
|
||||
|
||||
{{ Former::close() }}
|
||||
|
||||
</div>
|
||||
@ -112,9 +122,12 @@
|
||||
<script type="text/javascript">
|
||||
|
||||
$(function() {
|
||||
$('#actionDropDown > button:first').click(function() {
|
||||
$('#normalDropDown > button:first').click(function() {
|
||||
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() {
|
||||
|
@ -43,12 +43,14 @@
|
||||
min-height: 600px;
|
||||
}
|
||||
|
||||
label.checkbox,
|
||||
label.control-label {
|
||||
font-weight: normal !important;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
div.panel {
|
||||
padding-left: 0px !important;
|
||||
padding-right: 0px !important;
|
||||
@ -205,6 +207,15 @@
|
||||
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>
|
||||
|
||||
@stop
|
||||
|
@ -25,23 +25,33 @@
|
||||
{{ Former::populateField('id', $invoice->public_id); }}
|
||||
{{ Former::populateField('invoice_date', Utils::fromSqlDate($invoice->invoice_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
|
||||
{{ Former::populateField('invoice_number', $invoiceNumber) }}
|
||||
{{ Former::populateField('invoice_date', date('m/d/Y')) }}
|
||||
@endif
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
<div class="row" style="min-height:195px">
|
||||
<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')
|
||||
->help('<a style="cursor:pointer" data-toggle="modal" id="modalLink" onclick="showCreateNew()">Create new client</a>') }}
|
||||
{{ Former::textarea('notes') }}
|
||||
{{ Former::textarea('notes') }}
|
||||
</div>
|
||||
<div class="col-md-5">
|
||||
<div class="col-md-5" id="col_2">
|
||||
{{ 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('invoice_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'") --}}
|
||||
|
||||
|
||||
</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>
|
||||
|
||||
@ -246,7 +256,7 @@
|
||||
refreshPDF();
|
||||
});
|
||||
|
||||
$('#due_date').datepicker({
|
||||
$('#due_date,#start_date').datepicker({
|
||||
autoclose: true,
|
||||
todayHighlight: true
|
||||
});
|
||||
@ -284,6 +294,10 @@
|
||||
});
|
||||
|
||||
|
||||
@if ($invoice && $invoice->isRecurring())
|
||||
toggleRecurring(true);
|
||||
@endif;
|
||||
|
||||
applyComboboxListeners();
|
||||
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 clients = {{ $clients }};
|
||||
var clientMap = {};
|
||||
|
@ -86,6 +86,11 @@
|
||||
$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) {
|
||||
console.log('client change');
|
||||
var clientId = $('input[name=client]').val();
|
||||
@ -106,7 +111,6 @@
|
||||
}
|
||||
$('select#invoice').combobox('refresh');
|
||||
}).trigger('change');
|
||||
$input.combobox();
|
||||
|
||||
var $input = $('select#invoice').on('change', function(e) {
|
||||
$clientCombobox = $('select#client');
|
||||
@ -122,7 +126,6 @@
|
||||
autoclose: true,
|
||||
todayHighlight: true
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
</script>
|
||||
|
Loading…
x
Reference in New Issue
Block a user