mirror of
https://github.com/invoiceninja/invoiceninja.git
synced 2025-06-23 20:00:33 -04:00
Working on recurring invoices
This commit is contained in:
parent
0611004e77
commit
f97fa8991f
@ -22,9 +22,9 @@ class SendRecurringInvoices extends Command {
|
|||||||
{
|
{
|
||||||
$this->info(date('Y-m-d') . ' Running SendRecurringInvoices...');
|
$this->info(date('Y-m-d') . ' Running SendRecurringInvoices...');
|
||||||
|
|
||||||
$today = date('Y-m-d');
|
$today = new DateTime();
|
||||||
|
|
||||||
$invoices = Invoice::with('account', 'invoice_items')->whereRaw('start_date <= ? AND (end_date IS NULL OR end_date >= ?)', array($today, $today))->get();
|
$invoices = RecurringInvoice::with('account', 'invoice_items')->whereRaw('start_date <= ? AND (end_date IS NULL OR end_date >= ?)', array($today, $today))->get();
|
||||||
$this->info(count($invoices) . ' recurring invoice(s) found');
|
$this->info(count($invoices) . ' recurring invoice(s) found');
|
||||||
|
|
||||||
foreach ($invoices as $recurInvoice)
|
foreach ($invoices as $recurInvoice)
|
||||||
@ -38,7 +38,7 @@ class SendRecurringInvoices extends Command {
|
|||||||
|
|
||||||
$invoice = Invoice::createNew($recurInvoice);
|
$invoice = Invoice::createNew($recurInvoice);
|
||||||
$invoice->client_id = $recurInvoice->client_id;
|
$invoice->client_id = $recurInvoice->client_id;
|
||||||
$invoice->parent_id = $recurInvoice->id;
|
$invoice->recurring_invoice_id = $recurInvoice->id;
|
||||||
$invoice->invoice_number = $recurInvoice->account->getNextInvoiceNumber();
|
$invoice->invoice_number = $recurInvoice->account->getNextInvoiceNumber();
|
||||||
$invoice->total = $recurInvoice->total;
|
$invoice->total = $recurInvoice->total;
|
||||||
$invoice->invoice_date = new DateTime();
|
$invoice->invoice_date = new DateTime();
|
||||||
|
@ -99,7 +99,9 @@ class ClientController extends \BaseController {
|
|||||||
|
|
||||||
$data = array(
|
$data = array(
|
||||||
'client' => $client,
|
'client' => $client,
|
||||||
'title' => '- ' . $client->name);
|
'title' => '- ' . $client->name,
|
||||||
|
'hasRecurringInvoices' => RecurringInvoice::whereClientId($client->id)->count() > 0
|
||||||
|
);
|
||||||
|
|
||||||
return View::make('clients.show', $data);
|
return View::make('clients.show', $data);
|
||||||
}
|
}
|
||||||
|
@ -279,15 +279,15 @@ class InvoiceController extends \BaseController {
|
|||||||
return View::make('invoices.edit', $data);
|
return View::make('invoices.edit', $data);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static function getViewModel()
|
public static function getViewModel($isRecurring = false)
|
||||||
{
|
{
|
||||||
return [
|
return [
|
||||||
|
'isRecurring' => $isRecurring,
|
||||||
'account' => Auth::user()->account,
|
'account' => Auth::user()->account,
|
||||||
'products' => Product::scope()->get(array('product_key','notes','cost','qty')),
|
'products' => Product::scope()->get(array('product_key','notes','cost','qty')),
|
||||||
'countries' => Country::orderBy('name')->get(),
|
'countries' => Country::orderBy('name')->get(),
|
||||||
'clients' => Client::scope()->orderBy('name')->get(),
|
'clients' => Client::scope()->orderBy('name')->get(),
|
||||||
'frequencies' => array(
|
'frequencies' => array(
|
||||||
0 => '',
|
|
||||||
1 => 'Weekly',
|
1 => 'Weekly',
|
||||||
2 => 'Two weeks',
|
2 => 'Two weeks',
|
||||||
3 => 'Four weeks',
|
3 => 'Four weeks',
|
||||||
@ -371,16 +371,12 @@ class InvoiceController extends \BaseController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
$invoice->client_id = $client->id;
|
$invoice->client_id = $client->id;
|
||||||
$invoice->invoice_number = trim(Input::get('invoice_number'));
|
|
||||||
$invoice->discount = 0;
|
$invoice->discount = 0;
|
||||||
|
$invoice->invoice_number = trim(Input::get('invoice_number'));
|
||||||
$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', null));
|
$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'));
|
||||||
|
280
app/controllers/RecurringInvoiceController.php
Executable file
280
app/controllers/RecurringInvoiceController.php
Executable file
@ -0,0 +1,280 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
class RecurringInvoiceController extends \BaseController {
|
||||||
|
|
||||||
|
public function index()
|
||||||
|
{
|
||||||
|
return View::make('list', array(
|
||||||
|
'entityType'=>ENTITY_RECURRING_INVOICE,
|
||||||
|
'title' => '- Invoices',
|
||||||
|
'columns'=>['checkbox', 'Client', 'Total', 'How Often', 'Start Date', 'End Date', 'Action']
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getDatatable($clientPublicId = null)
|
||||||
|
{
|
||||||
|
$query = DB::table('recurring_invoices')
|
||||||
|
->join('clients', 'clients.id', '=', 'recurring_invoices.client_id')
|
||||||
|
->join('frequencies', 'recurring_invoices.frequency_id', '=', 'frequencies.id')
|
||||||
|
->where('recurring_invoices.account_id', '=', Auth::user()->account_id)
|
||||||
|
->where('recurring_invoices.deleted_at', '=', null)
|
||||||
|
->select('clients.public_id as client_public_id', 'clients.name as client_name', 'recurring_invoices.public_id', 'total', 'frequencies.name as frequency', 'start_date', 'end_date');
|
||||||
|
|
||||||
|
if ($clientPublicId) {
|
||||||
|
$query->where('clients.public_id', '=', $clientPublicId);
|
||||||
|
}
|
||||||
|
|
||||||
|
$table = Datatable::query($query);
|
||||||
|
|
||||||
|
if (!$clientPublicId) {
|
||||||
|
$table->addColumn('checkbox', function($model) { return '<input type="checkbox" name="ids[]" value="' . $model->public_id . '">'; });
|
||||||
|
}
|
||||||
|
|
||||||
|
//$table->addColumn('invoice_number', function($model) { return link_to('invoices/' . $model->public_id . '/edit', $model->invoice_number); });
|
||||||
|
|
||||||
|
if (!$clientPublicId) {
|
||||||
|
$table->addColumn('client', function($model) { return link_to('clients/' . $model->client_public_id, $model->client_name); });
|
||||||
|
}
|
||||||
|
|
||||||
|
return $table->addColumn('total', function($model) { return '$' . money_format('%i', $model->total); })
|
||||||
|
->addColumn('frequency', function($model) { return $model->frequency; })
|
||||||
|
->addColumn('start_date', function($model) { return Utils::fromSqlDate($model->start_date); })
|
||||||
|
->addColumn('end_date', function($model) { return Utils::fromSqlDate($model->end_date); })
|
||||||
|
->addColumn('dropdown', function($model)
|
||||||
|
{
|
||||||
|
return '<div class="btn-group tr-action" style="visibility:hidden;">
|
||||||
|
<button type="button" class="btn btn-xs btn-default dropdown-toggle" data-toggle="dropdown">
|
||||||
|
Select <span class="caret"></span>
|
||||||
|
</button>
|
||||||
|
<ul class="dropdown-menu" role="menu">
|
||||||
|
<li><a href="' . URL::to('invoices/'.$model->public_id.'/edit') . '">Edit Recurring Invoice</a></li>
|
||||||
|
<li class="divider"></li>
|
||||||
|
<li><a href="' . URL::to('invoices/'.$model->public_id.'/archive') . '">Archive Recurring Invoice</a></li>
|
||||||
|
<li><a href="javascript:deleteEntity(' . $model->public_id . ')">Delete Recurring Invoice</a></li>
|
||||||
|
</ul>
|
||||||
|
</div>';
|
||||||
|
})
|
||||||
|
->orderColumns('client','total','how_often','start_date','end_date')
|
||||||
|
->make();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function edit($publicId)
|
||||||
|
{
|
||||||
|
$invoice = RecurringInvoice::scope($publicId)->with('account.country', 'client', 'invoice_items')->firstOrFail();
|
||||||
|
Utils::trackViewed($invoice->getName() . ' - ' . $invoice->client->name, ENTITY_RECURRING_INVOICE);
|
||||||
|
|
||||||
|
$data = array(
|
||||||
|
'account' => $invoice->account,
|
||||||
|
'invoice' => $invoice,
|
||||||
|
'method' => 'PUT',
|
||||||
|
'url' => 'recurring_invoices/' . $publicId,
|
||||||
|
'title' => '- ' . $invoice->getName(),
|
||||||
|
'client' => $invoice->client);
|
||||||
|
$data = array_merge($data, InvoiceController::getViewModel(true));
|
||||||
|
return View::make('invoices.edit', $data);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function create($clientPublicId = 0)
|
||||||
|
{
|
||||||
|
$client = null;
|
||||||
|
$invoiceNumber = Auth::user()->account->getNextInvoiceNumber();
|
||||||
|
$account = Account::with('country')->findOrFail(Auth::user()->account_id);
|
||||||
|
|
||||||
|
if ($clientPublicId) {
|
||||||
|
$client = Client::scope($clientPublicId)->firstOrFail();
|
||||||
|
}
|
||||||
|
|
||||||
|
$data = array(
|
||||||
|
'account' => $account,
|
||||||
|
'invoice' => null,
|
||||||
|
'invoiceNumber' => $invoiceNumber,
|
||||||
|
'method' => 'POST',
|
||||||
|
'url' => 'recurring_invoices',
|
||||||
|
'title' => '- New Recurring Invoice',
|
||||||
|
'client' => $client,
|
||||||
|
'items' => json_decode(Input::old('items')));
|
||||||
|
$data = array_merge($data, InvoiceController::getViewModel(true));
|
||||||
|
return View::make('invoices.edit', $data);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function store()
|
||||||
|
{
|
||||||
|
return RecurringInvoiceController::save();
|
||||||
|
}
|
||||||
|
|
||||||
|
private function save($publicId = null)
|
||||||
|
{
|
||||||
|
$action = Input::get('action');
|
||||||
|
|
||||||
|
if ($action == 'archive' || $action == 'delete')
|
||||||
|
{
|
||||||
|
return RecurringInvoiceController::bulk();
|
||||||
|
}
|
||||||
|
|
||||||
|
$rules = array(
|
||||||
|
'client' => 'required',
|
||||||
|
);
|
||||||
|
$validator = Validator::make(Input::all(), $rules);
|
||||||
|
|
||||||
|
if ($validator->fails()) {
|
||||||
|
return Redirect::to('invoices/create')
|
||||||
|
->withInput()
|
||||||
|
->withErrors($validator);
|
||||||
|
} else {
|
||||||
|
|
||||||
|
$clientPublicId = Input::get('client');
|
||||||
|
|
||||||
|
if ($clientPublicId == "-1")
|
||||||
|
{
|
||||||
|
$client = Client::createNew();
|
||||||
|
$client->name = trim(Input::get('name'));
|
||||||
|
$client->work_phone = trim(Input::get('work_phone'));
|
||||||
|
$client->address1 = trim(Input::get('address1'));
|
||||||
|
$client->address2 = trim(Input::get('address2'));
|
||||||
|
$client->city = trim(Input::get('city'));
|
||||||
|
$client->state = trim(Input::get('state'));
|
||||||
|
$client->postal_code = trim(Input::get('postal_code'));
|
||||||
|
if (Input::get('country_id')) {
|
||||||
|
$client->country_id = Input::get('country_id');
|
||||||
|
}
|
||||||
|
$client->save();
|
||||||
|
$clientId = $client->id;
|
||||||
|
|
||||||
|
$contact = Contact::createNew();
|
||||||
|
$contact->is_primary = true;
|
||||||
|
$contact->first_name = trim(Input::get('first_name'));
|
||||||
|
$contact->last_name = trim(Input::get('last_name'));
|
||||||
|
$contact->phone = trim(Input::get('phone'));
|
||||||
|
$contact->email = trim(Input::get('email'));
|
||||||
|
$client->contacts()->save($contact);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
$client = Client::scope($clientPublicId)->with('contacts')->firstOrFail();
|
||||||
|
$contact = $client->contacts()->first();
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($publicId) {
|
||||||
|
$invoice = RecurringInvoice::scope($publicId)->firstOrFail();
|
||||||
|
$invoice->invoice_items()->forceDelete();
|
||||||
|
} else {
|
||||||
|
$invoice = RecurringInvoice::createNew();
|
||||||
|
}
|
||||||
|
|
||||||
|
$invoice->client_id = $client->id;
|
||||||
|
$invoice->discount = 0;
|
||||||
|
$invoice->frequency_id = Input::get('frequency');
|
||||||
|
$invoice->start_date = Utils::toSqlDate(Input::get('start_date', null));
|
||||||
|
$invoice->end_date = Utils::toSqlDate(Input::get('end_date', null));
|
||||||
|
|
||||||
|
$invoice->notes = Input::get('notes');
|
||||||
|
$client->invoices()->save($invoice);
|
||||||
|
|
||||||
|
$items = json_decode(Input::get('items'));
|
||||||
|
$total = 0;
|
||||||
|
|
||||||
|
foreach ($items as $item)
|
||||||
|
{
|
||||||
|
if (!isset($item->cost)) {
|
||||||
|
$item->cost = 0;
|
||||||
|
}
|
||||||
|
if (!isset($item->qty)) {
|
||||||
|
$item->qty = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
$total += floatval($item->qty) * floatval($item->cost);
|
||||||
|
}
|
||||||
|
|
||||||
|
$invoice->total = $total;
|
||||||
|
$invoice->save();
|
||||||
|
|
||||||
|
foreach ($items as $item)
|
||||||
|
{
|
||||||
|
if (!$item->cost && !$item->qty && !$item->product_key && !$item->notes)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($item->product_key)
|
||||||
|
{
|
||||||
|
$product = Product::findProductByKey(trim($item->product_key));
|
||||||
|
|
||||||
|
if (!$product)
|
||||||
|
{
|
||||||
|
$product = Product::createNew();
|
||||||
|
$product->product_key = trim($item->product_key);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
$product->notes = $item->notes;
|
||||||
|
$product->cost = $item->cost;
|
||||||
|
$product->qty = $item->qty;
|
||||||
|
*/
|
||||||
|
|
||||||
|
$product->save();
|
||||||
|
}
|
||||||
|
|
||||||
|
$invoiceItem = RecurringInvoiceItem::createNew();
|
||||||
|
$invoiceItem->product_id = isset($product) ? $product->id : null;
|
||||||
|
$invoiceItem->product_key = trim($item->product_key);
|
||||||
|
$invoiceItem->notes = trim($item->notes);
|
||||||
|
$invoiceItem->cost = floatval($item->cost);
|
||||||
|
$invoiceItem->qty = floatval($item->qty);
|
||||||
|
|
||||||
|
$invoice->invoice_items()->save($invoiceItem);
|
||||||
|
}
|
||||||
|
|
||||||
|
Session::flash('message', 'Successfully saved recurring invoice');
|
||||||
|
$url = 'recurring_invoices/' . $invoice->public_id . '/edit';
|
||||||
|
return Redirect::to($url);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Display the specified resource.
|
||||||
|
*
|
||||||
|
* @param int $id
|
||||||
|
* @return Response
|
||||||
|
*/
|
||||||
|
public function show($publicId)
|
||||||
|
{
|
||||||
|
return Redirect::to('recurring_invoices/'.$publicId.'/edit');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update the specified resource in storage.
|
||||||
|
*
|
||||||
|
* @param int $id
|
||||||
|
* @return Response
|
||||||
|
*/
|
||||||
|
public function update($publicId)
|
||||||
|
{
|
||||||
|
return RecurringInvoiceController::save($publicId);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove the specified resource from storage.
|
||||||
|
*
|
||||||
|
* @param int $id
|
||||||
|
* @return Response
|
||||||
|
*/
|
||||||
|
public function bulk()
|
||||||
|
{
|
||||||
|
$action = Input::get('action');
|
||||||
|
$ids = Input::get('id') ? Input::get('id') : Input::get('ids');
|
||||||
|
$invoices = RecurringInvoice::scope($ids)->get();
|
||||||
|
|
||||||
|
foreach ($invoices as $invoice) {
|
||||||
|
if ($action == 'archive') {
|
||||||
|
$invoice->delete();
|
||||||
|
} else if ($action == 'delete') {
|
||||||
|
$invoice->forceDelete();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$message = Utils::pluralize('Successfully '.$action.'d ? recurring invoice', count($ids));
|
||||||
|
Session::flash('message', $message);
|
||||||
|
|
||||||
|
return Redirect::to('invoices');
|
||||||
|
}
|
||||||
|
}
|
@ -17,10 +17,12 @@ class ConfideSetupUsersTable extends Migration {
|
|||||||
Schema::dropIfExists('account_gateways');
|
Schema::dropIfExists('account_gateways');
|
||||||
Schema::dropIfExists('gateways');
|
Schema::dropIfExists('gateways');
|
||||||
Schema::dropIfExists('payments');
|
Schema::dropIfExists('payments');
|
||||||
|
Schema::dropIfExists('recurring_invoice_items');
|
||||||
Schema::dropIfExists('invoice_items');
|
Schema::dropIfExists('invoice_items');
|
||||||
Schema::dropIfExists('products');
|
Schema::dropIfExists('products');
|
||||||
Schema::dropIfExists('contacts');
|
Schema::dropIfExists('contacts');
|
||||||
Schema::dropIfExists('invoices');
|
Schema::dropIfExists('invoices');
|
||||||
|
Schema::dropIfExists('recurring_invoices');
|
||||||
Schema::dropIfExists('password_reminders');
|
Schema::dropIfExists('password_reminders');
|
||||||
Schema::dropIfExists('clients');
|
Schema::dropIfExists('clients');
|
||||||
Schema::dropIfExists('users');
|
Schema::dropIfExists('users');
|
||||||
@ -28,6 +30,7 @@ class ConfideSetupUsersTable extends Migration {
|
|||||||
Schema::dropIfExists('invoice_statuses');
|
Schema::dropIfExists('invoice_statuses');
|
||||||
Schema::dropIfExists('countries');
|
Schema::dropIfExists('countries');
|
||||||
Schema::dropIfExists('timezones');
|
Schema::dropIfExists('timezones');
|
||||||
|
Schema::dropIfExists('frequencies');
|
||||||
|
|
||||||
Schema::create('countries', function($table)
|
Schema::create('countries', function($table)
|
||||||
{
|
{
|
||||||
@ -200,6 +203,38 @@ class ConfideSetupUsersTable extends Migration {
|
|||||||
$t->string('name');
|
$t->string('name');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
Schema::create('frequencies', function($t)
|
||||||
|
{
|
||||||
|
$t->increments('id');
|
||||||
|
$t->string('name');
|
||||||
|
});
|
||||||
|
|
||||||
|
Schema::create('recurring_invoices', function($t)
|
||||||
|
{
|
||||||
|
$t->increments('id');
|
||||||
|
$t->unsignedInteger('client_id');
|
||||||
|
$t->unsignedInteger('user_id');
|
||||||
|
$t->unsignedInteger('account_id');
|
||||||
|
$t->timestamps();
|
||||||
|
$t->softDeletes();
|
||||||
|
|
||||||
|
$t->float('discount');
|
||||||
|
$t->text('notes');
|
||||||
|
$t->decimal('total', 10, 2);
|
||||||
|
|
||||||
|
$t->unsignedInteger('frequency_id');
|
||||||
|
$t->date('start_date')->nullable();
|
||||||
|
$t->date('end_date')->nullable();
|
||||||
|
$t->date('last_sent_date')->nullable();
|
||||||
|
|
||||||
|
$t->foreign('client_id')->references('id')->on('clients')->onDelete('cascade');
|
||||||
|
$t->foreign('account_id')->references('id')->on('accounts');
|
||||||
|
$t->foreign('user_id')->references('id')->on('users');
|
||||||
|
$t->foreign('frequency_id')->references('id')->on('frequencies');
|
||||||
|
|
||||||
|
$t->unsignedInteger('public_id');
|
||||||
|
$t->unique( array('account_id','public_id') );
|
||||||
|
});
|
||||||
|
|
||||||
Schema::create('invoices', function($t)
|
Schema::create('invoices', function($t)
|
||||||
{
|
{
|
||||||
@ -220,17 +255,13 @@ class ConfideSetupUsersTable extends Migration {
|
|||||||
$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->unsignedInteger('recurring_invoice_id')->nullable();
|
||||||
$t->date('start_date')->nullable();
|
|
||||||
$t->date('end_date')->nullable();
|
|
||||||
$t->date('last_sent_date')->nullable();
|
|
||||||
$t->unsignedInteger('parent_id')->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('user_id')->references('id')->on('users');
|
$t->foreign('user_id')->references('id')->on('users');
|
||||||
$t->foreign('invoice_status_id')->references('id')->on('invoice_statuses');
|
$t->foreign('invoice_status_id')->references('id')->on('invoice_statuses');
|
||||||
$t->foreign('parent_id')->references('id')->on('invoices');
|
$t->foreign('recurring_invoice_id')->references('id')->on('recurring_invoices');
|
||||||
|
|
||||||
$t->unsignedInteger('public_id');
|
$t->unsignedInteger('public_id');
|
||||||
$t->unique( array('account_id','public_id') );
|
$t->unique( array('account_id','public_id') );
|
||||||
@ -302,6 +333,29 @@ class ConfideSetupUsersTable extends Migration {
|
|||||||
$t->unique( array('account_id','public_id') );
|
$t->unique( array('account_id','public_id') );
|
||||||
});
|
});
|
||||||
|
|
||||||
|
Schema::create('recurring_invoice_items', function($t)
|
||||||
|
{
|
||||||
|
$t->increments('id');
|
||||||
|
$t->unsignedInteger('account_id');
|
||||||
|
$t->unsignedInteger('user_id');
|
||||||
|
$t->unsignedInteger('recurring_invoice_id');
|
||||||
|
$t->unsignedInteger('product_id')->nullable();
|
||||||
|
$t->timestamps();
|
||||||
|
$t->softDeletes();
|
||||||
|
|
||||||
|
$t->string('product_key');
|
||||||
|
$t->string('notes');
|
||||||
|
$t->decimal('cost', 10, 2);
|
||||||
|
$t->decimal('qty', 10, 2);
|
||||||
|
|
||||||
|
$t->foreign('recurring_invoice_id')->references('id')->on('recurring_invoices')->onDelete('cascade');
|
||||||
|
$t->foreign('product_id')->references('id')->on('products');
|
||||||
|
$t->foreign('user_id')->references('id')->on('users');
|
||||||
|
|
||||||
|
$t->unsignedInteger('public_id');
|
||||||
|
$t->unique( array('account_id','public_id') );
|
||||||
|
});
|
||||||
|
|
||||||
Schema::create('payments', function($t)
|
Schema::create('payments', function($t)
|
||||||
{
|
{
|
||||||
$t->increments('id');
|
$t->increments('id');
|
||||||
@ -363,6 +417,7 @@ class ConfideSetupUsersTable extends Migration {
|
|||||||
$t->unsignedInteger('contact_id');
|
$t->unsignedInteger('contact_id');
|
||||||
$t->unsignedInteger('payment_id');
|
$t->unsignedInteger('payment_id');
|
||||||
$t->unsignedInteger('invoice_id');
|
$t->unsignedInteger('invoice_id');
|
||||||
|
$t->unsignedInteger('recurring_invoice_id');
|
||||||
$t->unsignedInteger('credit_id');
|
$t->unsignedInteger('credit_id');
|
||||||
$t->unsignedInteger('invitation_id');
|
$t->unsignedInteger('invitation_id');
|
||||||
|
|
||||||
@ -390,10 +445,12 @@ class ConfideSetupUsersTable extends Migration {
|
|||||||
Schema::dropIfExists('account_gateways');
|
Schema::dropIfExists('account_gateways');
|
||||||
Schema::dropIfExists('gateways');
|
Schema::dropIfExists('gateways');
|
||||||
Schema::dropIfExists('payments');
|
Schema::dropIfExists('payments');
|
||||||
|
Schema::dropIfExists('recurring_invoice_items');
|
||||||
Schema::dropIfExists('invoice_items');
|
Schema::dropIfExists('invoice_items');
|
||||||
Schema::dropIfExists('products');
|
Schema::dropIfExists('products');
|
||||||
Schema::dropIfExists('contacts');
|
Schema::dropIfExists('contacts');
|
||||||
Schema::dropIfExists('invoices');
|
Schema::dropIfExists('invoices');
|
||||||
|
Schema::dropIfExists('recurring_invoices');
|
||||||
Schema::dropIfExists('password_reminders');
|
Schema::dropIfExists('password_reminders');
|
||||||
Schema::dropIfExists('clients');
|
Schema::dropIfExists('clients');
|
||||||
Schema::dropIfExists('users');
|
Schema::dropIfExists('users');
|
||||||
@ -401,5 +458,6 @@ class ConfideSetupUsersTable extends Migration {
|
|||||||
Schema::dropIfExists('invoice_statuses');
|
Schema::dropIfExists('invoice_statuses');
|
||||||
Schema::dropIfExists('countries');
|
Schema::dropIfExists('countries');
|
||||||
Schema::dropIfExists('timezones');
|
Schema::dropIfExists('timezones');
|
||||||
|
Schema::dropIfExists('frequencies');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -50,6 +50,14 @@ class ConstantsSeeder extends Seeder
|
|||||||
InvoiceStatus::create(array('name' => 'Partial'));
|
InvoiceStatus::create(array('name' => 'Partial'));
|
||||||
InvoiceStatus::create(array('name' => 'Paid'));
|
InvoiceStatus::create(array('name' => 'Paid'));
|
||||||
|
|
||||||
|
Frequency::create(array('name' => 'Weekly'));
|
||||||
|
Frequency::create(array('name' => 'Two weeks'));
|
||||||
|
Frequency::create(array('name' => 'Four weeks'));
|
||||||
|
Frequency::create(array('name' => 'Monthly'));
|
||||||
|
Frequency::create(array('name' => 'Three months'));
|
||||||
|
Frequency::create(array('name' => 'Six months'));
|
||||||
|
Frequency::create(array('name' => 'Annually'));
|
||||||
|
|
||||||
$gateways = [
|
$gateways = [
|
||||||
array('name'=>'Authorize.Net AIM', 'provider'=>'AuthorizeNet_AIM'),
|
array('name'=>'Authorize.Net AIM', 'provider'=>'AuthorizeNet_AIM'),
|
||||||
array('name'=>'Authorize.Net SIM', 'provider'=>'AuthorizeNet_SIM'),
|
array('name'=>'Authorize.Net SIM', 'provider'=>'AuthorizeNet_SIM'),
|
||||||
|
@ -207,4 +207,9 @@ class Utils
|
|||||||
$year = intval(date('Y'));
|
$year = intval(date('Y'));
|
||||||
return $year + $offset;
|
return $year + $offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static function getEntityName($entityType)
|
||||||
|
{
|
||||||
|
return ucwords(str_replace('_', ' ', $entityType));
|
||||||
|
}
|
||||||
}
|
}
|
@ -15,6 +15,10 @@ define("ACTIVITY_TYPE_DELETE_PAYMENT", 11);
|
|||||||
define("ACTIVITY_TYPE_CREATE_CREDIT", 12);
|
define("ACTIVITY_TYPE_CREATE_CREDIT", 12);
|
||||||
define("ACTIVITY_TYPE_ARCHIVE_CREDIT", 13);
|
define("ACTIVITY_TYPE_ARCHIVE_CREDIT", 13);
|
||||||
define("ACTIVITY_TYPE_DELETE_CREDIT", 14);
|
define("ACTIVITY_TYPE_DELETE_CREDIT", 14);
|
||||||
|
define("ACTIVITY_TYPE_CREATE_RECURRING_INVOICE", 15);
|
||||||
|
define("ACTIVITY_TYPE_ARCHIVE_RECURRING_INVOICE", 16);
|
||||||
|
define("ACTIVITY_TYPE_DELETE_RECURRING_INVOICE", 17);
|
||||||
|
|
||||||
|
|
||||||
class Activity extends Eloquent
|
class Activity extends Eloquent
|
||||||
{
|
{
|
||||||
@ -94,6 +98,26 @@ class Activity extends Eloquent
|
|||||||
$activity->save();
|
$activity->save();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static function createRecurringInvoice($invoice)
|
||||||
|
{
|
||||||
|
$activity = Activity::getBlank();
|
||||||
|
$activity->recurring_invoice_id = $invoice->id;
|
||||||
|
$activity->client_id = $invoice->client_id;
|
||||||
|
$activity->activity_type_id = ACTIVITY_TYPE_CREATE_RECURRING_INVOICE;
|
||||||
|
$activity->message = Auth::user()->getFullName() . ' created recurring invoice ' . link_to('recurring_invoices/'.$invoice->public_id, $invoice->getName());
|
||||||
|
$activity->save();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function archiveRecurringInvoice($invoice)
|
||||||
|
{
|
||||||
|
$activity = Activity::getBlank();
|
||||||
|
$activity->recurring_invoice_id = $invoice->id;
|
||||||
|
$activity->client_id = $invoice->client_id;
|
||||||
|
$activity->activity_type_id = ACTIVITY_TYPE_ARCHIVE_INVOICE;
|
||||||
|
$activity->message = Auth::user()->getFullName() . ' archived recurring invoice ' . $invoice->getName();
|
||||||
|
$activity->save();
|
||||||
|
}
|
||||||
|
|
||||||
public static function createPayment($payment)
|
public static function createPayment($payment)
|
||||||
{
|
{
|
||||||
if (Auth::check())
|
if (Auth::check())
|
||||||
|
6
app/models/Frequency.php
Executable file
6
app/models/Frequency.php
Executable file
@ -0,0 +1,6 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
class Frequency extends Eloquent
|
||||||
|
{
|
||||||
|
public $timestamps = false;
|
||||||
|
}
|
@ -33,55 +33,6 @@ 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 shouldSendToday()
|
|
||||||
{
|
|
||||||
$dayOfWeekToday = date('w');
|
|
||||||
$dayOfWeekStart = date('w', strtotime($this->start_date));
|
|
||||||
|
|
||||||
$dayOfMonthToday = date('j');
|
|
||||||
$dayOfMonthStart = date('j', strtotime($this->start_date));
|
|
||||||
|
|
||||||
if (!$this->last_sent_date) {
|
|
||||||
$daysSinceLastSent = 0;
|
|
||||||
$monthsSinceLastSent = 0;
|
|
||||||
} else {
|
|
||||||
$date1 = new DateTime($this->last_sent_date);
|
|
||||||
$date2 = new DateTime();
|
|
||||||
$diff = $date2->diff($date1);
|
|
||||||
$daysSinceLastSent = $diff->format("%a");
|
|
||||||
$monthsSinceLastSent = ($diff->format('%y') * 12) + $diff->format('%m');
|
|
||||||
|
|
||||||
if ($daysSinceLastSent == 0) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
switch ($this->how_often)
|
|
||||||
{
|
|
||||||
case FREQUENCY_WEEKLY:
|
|
||||||
return $dayOfWeekStart == $dayOfWeekToday;
|
|
||||||
case FREQUENCY_TWO_WEEKS:
|
|
||||||
return $dayOfWeekStart == $dayOfWeekToday && (!$daysSinceLastSent || $daysSinceLastSent == 14);
|
|
||||||
case FREQUENCY_FOUR_WEEKS:
|
|
||||||
return $dayOfWeekStart == $dayOfWeekToday && (!$daysSinceLastSent || $daysSinceLastSent == 28);
|
|
||||||
case FREQUENCY_MONTHLY:
|
|
||||||
return $dayOfMonthStart == $dayOfMonthToday || $daysSinceLastSent > 31;
|
|
||||||
case FREQUENCY_THREE_MONTHS:
|
|
||||||
return ($dayOfMonthStart == $dayOfMonthToday && (!$daysSinceLastSent || $monthsSinceLastSent == 3)) || $daysSinceLastSent > (3 * 31);
|
|
||||||
case FREQUENCY_SIX_MONTHS:
|
|
||||||
return ($dayOfMonthStart == $dayOfMonthToday && (!$daysSinceLastSent || $monthsSinceLastSent == 6)) || $daysSinceLastSent > (6 * 31);
|
|
||||||
case FREQUENCY_ANNUALLY:
|
|
||||||
return ($dayOfMonthStart == $dayOfMonthToday && (!$daysSinceLastSent || $monthsSinceLastSent == 12)) || $daysSinceLastSent > (12 *31);
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Invoice::created(function($invoice)
|
Invoice::created(function($invoice)
|
||||||
|
88
app/models/RecurringInvoice.php
Executable file
88
app/models/RecurringInvoice.php
Executable file
@ -0,0 +1,88 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
class RecurringInvoice extends EntityModel
|
||||||
|
{
|
||||||
|
protected $hidden = array('id', 'account_id', 'client_id', 'created_at', 'updated_at', 'deleted_at');
|
||||||
|
|
||||||
|
public function account()
|
||||||
|
{
|
||||||
|
return $this->belongsTo('Account');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function client()
|
||||||
|
{
|
||||||
|
return $this->belongsTo('Client');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function invoice_items()
|
||||||
|
{
|
||||||
|
return $this->hasMany('RecurringInvoiceItem');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function freqency()
|
||||||
|
{
|
||||||
|
return $this->belongsTo('Frequency');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getName()
|
||||||
|
{
|
||||||
|
return $this->start_date;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getEntityType()
|
||||||
|
{
|
||||||
|
return ENTITY_RECURRING_INVOICE;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function shouldSendToday()
|
||||||
|
{
|
||||||
|
$dayOfWeekToday = date('w');
|
||||||
|
$dayOfWeekStart = date('w', strtotime($this->start_date));
|
||||||
|
|
||||||
|
$dayOfMonthToday = date('j');
|
||||||
|
$dayOfMonthStart = date('j', strtotime($this->start_date));
|
||||||
|
|
||||||
|
if (!$this->last_sent_date) {
|
||||||
|
$daysSinceLastSent = 0;
|
||||||
|
$monthsSinceLastSent = 0;
|
||||||
|
} else {
|
||||||
|
$date1 = new DateTime($this->last_sent_date);
|
||||||
|
$date2 = new DateTime();
|
||||||
|
$diff = $date2->diff($date1);
|
||||||
|
$daysSinceLastSent = $diff->format("%a");
|
||||||
|
$monthsSinceLastSent = ($diff->format('%y') * 12) + $diff->format('%m');
|
||||||
|
|
||||||
|
if ($daysSinceLastSent == 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
switch ($this->frequency_id)
|
||||||
|
{
|
||||||
|
case FREQUENCY_WEEKLY:
|
||||||
|
return $dayOfWeekStart == $dayOfWeekToday;
|
||||||
|
case FREQUENCY_TWO_WEEKS:
|
||||||
|
return $dayOfWeekStart == $dayOfWeekToday && (!$daysSinceLastSent || $daysSinceLastSent == 14);
|
||||||
|
case FREQUENCY_FOUR_WEEKS:
|
||||||
|
return $dayOfWeekStart == $dayOfWeekToday && (!$daysSinceLastSent || $daysSinceLastSent == 28);
|
||||||
|
case FREQUENCY_MONTHLY:
|
||||||
|
return $dayOfMonthStart == $dayOfMonthToday || $daysSinceLastSent > 31;
|
||||||
|
case FREQUENCY_THREE_MONTHS:
|
||||||
|
return ($dayOfMonthStart == $dayOfMonthToday && (!$daysSinceLastSent || $monthsSinceLastSent == 3)) || $daysSinceLastSent > (3 * 31);
|
||||||
|
case FREQUENCY_SIX_MONTHS:
|
||||||
|
return ($dayOfMonthStart == $dayOfMonthToday && (!$daysSinceLastSent || $monthsSinceLastSent == 6)) || $daysSinceLastSent > (6 * 31);
|
||||||
|
case FREQUENCY_ANNUALLY:
|
||||||
|
return ($dayOfMonthStart == $dayOfMonthToday && (!$daysSinceLastSent || $monthsSinceLastSent == 12)) || $daysSinceLastSent > (12 *31);
|
||||||
|
default:
|
||||||
|
echo "Error: invalid frequency_id - ".$this->frequency_id; exit; //TODO_FIX
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
RecurringInvoice::created(function($invoice)
|
||||||
|
{
|
||||||
|
Activity::createInvoice($invoice, true);
|
||||||
|
});
|
6
app/models/RecurringInvoiceItem.php
Executable file
6
app/models/RecurringInvoiceItem.php
Executable file
@ -0,0 +1,6 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
class RecurringInvoiceItem extends EntityModel
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
@ -14,6 +14,10 @@
|
|||||||
//dd(DB::getQueryLog());
|
//dd(DB::getQueryLog());
|
||||||
//dd(Client::getPrivateId(1));
|
//dd(Client::getPrivateId(1));
|
||||||
//dd(new DateTime());
|
//dd(new DateTime());
|
||||||
|
Route::get('/send_emails', function() {
|
||||||
|
Artisan::call('ninja:send-invoices');
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
Route::get('/', 'HomeController@showWelcome');
|
Route::get('/', 'HomeController@showWelcome');
|
||||||
Route::post('get_started', 'AccountController@getStarted');
|
Route::post('get_started', 'AccountController@getStarted');
|
||||||
@ -61,6 +65,9 @@ Route::group(array('before' => 'auth'), function()
|
|||||||
Route::get('invoices/create/{client_id?}', 'InvoiceController@create');
|
Route::get('invoices/create/{client_id?}', 'InvoiceController@create');
|
||||||
Route::post('invoices/bulk', 'InvoiceController@bulk');
|
Route::post('invoices/bulk', 'InvoiceController@bulk');
|
||||||
|
|
||||||
|
Route::resource('recurring_invoices', 'RecurringInvoiceController');
|
||||||
|
Route::get('api/recurring_invoices/{client_id?}', array('as'=>'api.recurring_invoices', 'uses'=>'RecurringInvoiceController@getDatatable'));
|
||||||
|
|
||||||
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('payments/create/{client_id?}', 'PaymentController@create');
|
||||||
@ -93,12 +100,17 @@ HTML::macro('menu_link', function($type) {
|
|||||||
$types = $type.'s';
|
$types = $type.'s';
|
||||||
$Type = ucfirst($type);
|
$Type = ucfirst($type);
|
||||||
$Types = ucfirst($types);
|
$Types = ucfirst($types);
|
||||||
$class = ( Request::is($types) || Request::is($types.'/*')) ? ' active' : '';
|
$class = ( Request::is($types) || Request::is('*'.$type.'*')) ? ' active' : '';
|
||||||
return '<li class="dropdown '.$class.'">
|
$str= '<li class="dropdown '.$class.'">
|
||||||
<a href="'.URL::to($types).'" class="dropdown-toggle">'.$Types.'</a>
|
<a href="'.URL::to($types).'" class="dropdown-toggle">'.$Types.'</a>
|
||||||
<ul class="dropdown-menu" id="menu1">
|
<ul class="dropdown-menu" id="menu1">
|
||||||
<!-- <li><a href="'.URL::to($types).'">List '.$Types.'</a></li> -->
|
<li><a href="'.URL::to($types).'">View '.$Types.'</a></li>';
|
||||||
<li><a href="'.URL::to($types.'/create').'">New '.$Type.'</a></li>
|
|
||||||
|
if ($Type == 'Invoice') {
|
||||||
|
$str .= '<li><a href="'.URL::to('recurring_invoices').'">View Recurring Invoices</a></li>';
|
||||||
|
}
|
||||||
|
|
||||||
|
return $str . '<li><a href="'.URL::to($types.'/create').'">New '.$Type.'</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
</li>';
|
</li>';
|
||||||
});
|
});
|
||||||
@ -116,6 +128,7 @@ define("ENV_PRODUCTION", "production");
|
|||||||
define("RECENTLY_VIEWED", "RECENTLY_VIEWED");
|
define("RECENTLY_VIEWED", "RECENTLY_VIEWED");
|
||||||
define("ENTITY_CLIENT", "client");
|
define("ENTITY_CLIENT", "client");
|
||||||
define("ENTITY_INVOICE", "invoice");
|
define("ENTITY_INVOICE", "invoice");
|
||||||
|
define("ENTITY_RECURRING_INVOICE", "recurring_invoice");
|
||||||
define("ENTITY_PAYMENT", "payment");
|
define("ENTITY_PAYMENT", "payment");
|
||||||
define("ENTITY_CREDIT", "credit");
|
define("ENTITY_CREDIT", "credit");
|
||||||
|
|
||||||
|
@ -89,6 +89,15 @@
|
|||||||
|
|
||||||
<div class="tab-pane" id="invoices">
|
<div class="tab-pane" id="invoices">
|
||||||
|
|
||||||
|
@if ($hasRecurringInvoices)
|
||||||
|
{{ Datatable::table()
|
||||||
|
->addColumn('Total', 'How Often', 'Start Date', 'End Date')
|
||||||
|
->setUrl(url('api/recurring_invoices/' . $client->public_id))
|
||||||
|
->setOptions('sPaginationType', 'bootstrap')
|
||||||
|
->setOptions('bFilter', false)
|
||||||
|
->render('datatable') }}
|
||||||
|
@endif
|
||||||
|
|
||||||
{{ Datatable::table()
|
{{ Datatable::table()
|
||||||
->addColumn('Invoice Number', 'Total', 'Amount Due', 'Invoice Date', 'Due Date', 'Status')
|
->addColumn('Invoice Number', 'Total', 'Amount Due', 'Invoice Date', 'Due Date', 'Status')
|
||||||
->setUrl(url('api/invoices/' . $client->public_id))
|
->setUrl(url('api/invoices/' . $client->public_id))
|
||||||
|
@ -13,9 +13,7 @@
|
|||||||
|
|
||||||
{{ Former::open($url)->method($method)->addClass('main_form')->rules(array(
|
{{ Former::open($url)->method($method)->addClass('main_form')->rules(array(
|
||||||
'client' => 'required',
|
'client' => 'required',
|
||||||
'invoice_number' => 'required',
|
'product_key' => 'max:14',
|
||||||
'invoice_date' => 'required',
|
|
||||||
'product_key' => 'max:14',
|
|
||||||
)); }}
|
)); }}
|
||||||
|
|
||||||
<!-- <h3>{{ $title }} Invoice</h3> -->
|
<!-- <h3>{{ $title }} Invoice</h3> -->
|
||||||
@ -30,6 +28,7 @@
|
|||||||
@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')) }}
|
||||||
|
{{ Former::populateField('frequency', FREQUENCY_MONTHLY) }}
|
||||||
@endif
|
@endif
|
||||||
|
|
||||||
<div class="row" style="min-height:195px">
|
<div class="row" style="min-height:195px">
|
||||||
@ -39,19 +38,25 @@
|
|||||||
{{ Former::textarea('notes') }}
|
{{ Former::textarea('notes') }}
|
||||||
</div>
|
</div>
|
||||||
<div class="col-md-5" id="col_2">
|
<div class="col-md-5" id="col_2">
|
||||||
{{ Former::text('invoice_number')->label('Invoice #') }}
|
<div id="recurring_checkbox">
|
||||||
{{-- Former::text('invoice_date')->label('Invoice Date')->data_date_format('yyyy-mm-dd') --}}
|
{{ Former::checkbox('recurring')->text('Enable automatic invoicing | <a href="#">Learn more</a>')->onchange('toggleRecurring()')
|
||||||
{{ Former::text('invoice_date') }}
|
->inlineHelp($invoice && $invoice->last_sent_date ? 'Last invoice sent ' . Utils::timestampToDateString($invoice->last_sent_date) : '') }}
|
||||||
{{ Former::text('due_date')->help('<a id="showRecurring" style="cursor:pointer" onclick="toggleRecurring(true)">Enable recurring</a>') }}
|
</div>
|
||||||
{{-- Former::text('discount')->data_bind("value: discount, valueUpdate: 'afterkeydown'") --}}
|
<div id="recurring_off">
|
||||||
|
{{ Former::text('invoice_number')->label('Invoice #') }}
|
||||||
|
{{ Former::text('invoice_date') }}
|
||||||
|
{{ Former::text('due_date') }}
|
||||||
|
|
||||||
|
{{-- Former::text('discount')->data_bind("value: discount, valueUpdate: 'afterkeydown'") --}}
|
||||||
|
{{-- Former::text('invoice_date')->label('Invoice Date')->data_date_format('yyyy-mm-dd') --}}
|
||||||
|
</div>
|
||||||
|
<div id="recurring_on" style="display:none">
|
||||||
|
{{ Former::select('frequency')->label('How often')->options($frequencies)->onchange('updateRecurringStats()') }}
|
||||||
|
{{ Former::text('start_date')->onchange('updateRecurringStats()') }}
|
||||||
|
{{ Former::text('end_date')->onchange('updateRecurringStats()') }}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-md-3" id="col_3" style="display:none">
|
<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>
|
||||||
|
|
||||||
@ -156,7 +161,7 @@
|
|||||||
@endif
|
@endif
|
||||||
|
|
||||||
{{ Button::primary_submit('Save Invoice') }}
|
{{ Button::primary_submit('Save Invoice') }}
|
||||||
{{ Button::primary('Send Email', array('onclick' => 'onEmailClick()')) }}
|
{{ Button::primary('Send Email', array('id' => 'email_button', 'onclick' => 'onEmailClick()')) }}
|
||||||
</div>
|
</div>
|
||||||
<p> </p>
|
<p> </p>
|
||||||
|
|
||||||
@ -294,9 +299,19 @@
|
|||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
@if ($invoice && $invoice->isRecurring())
|
$('label.radio').addClass('radio-inline');
|
||||||
toggleRecurring(true);
|
|
||||||
@endif;
|
|
||||||
|
@if ($isRecurring)
|
||||||
|
$('#recurring').prop('checked', true);
|
||||||
|
@if ($invoice)
|
||||||
|
$('#recurring_checkbox').hide();
|
||||||
|
@endif
|
||||||
|
@elseif (isset($invoice->recurring_invoice_id) && $invoice->recurring_invoice_id)
|
||||||
|
$('#recurring_checkbox > div > div').html('Created by a {{ link_to('/recurring_invoices/'.$invoice->recurring_invoice_id, 'recurring invoice') }}').css('padding-top','6px');
|
||||||
|
@endif
|
||||||
|
|
||||||
|
toggleRecurring();
|
||||||
|
|
||||||
applyComboboxListeners();
|
applyComboboxListeners();
|
||||||
refreshPDF();
|
refreshPDF();
|
||||||
@ -636,8 +651,25 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function toggleRecurring(show)
|
function toggleRecurring()
|
||||||
{
|
{
|
||||||
|
var enabled = $('#recurring').is(':checked');
|
||||||
|
|
||||||
|
if (enabled) {
|
||||||
|
$('#recurring_on').show();
|
||||||
|
$('#recurring_off').hide();
|
||||||
|
$('#email_button').prop('disabled', true);
|
||||||
|
@if (!$isRecurring)
|
||||||
|
$('.main_form').prop('action', '{{ URL::to('/recurring_invoices') }}');
|
||||||
|
@endif
|
||||||
|
} else {
|
||||||
|
$('#recurring_on').hide();
|
||||||
|
$('#recurring_off').show();
|
||||||
|
$('#email_button').prop('disabled', false);
|
||||||
|
$('.main_form').prop('action', '{{ $url }}');
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
$('#col_1').toggleClass('col-md-6 col-md-5');
|
$('#col_1').toggleClass('col-md-6 col-md-5');
|
||||||
$('#col_2').toggleClass('col-md-5 col-md-3');
|
$('#col_2').toggleClass('col-md-5 col-md-3');
|
||||||
|
|
||||||
@ -654,6 +686,26 @@
|
|||||||
if (!show) {
|
if (!show) {
|
||||||
$('#how_often, #start_date, #end_date').val('')
|
$('#how_often, #start_date, #end_date').val('')
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
};
|
||||||
|
|
||||||
|
function updateRecurringStats()
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
var howOften = $('#how_often').val();
|
||||||
|
var startDate = $('#start_date').val();
|
||||||
|
var endDate = $('#end_date').val();
|
||||||
|
console.log("%s %s %s", howOften, startDate, endDate);
|
||||||
|
|
||||||
|
var str = "Send ";
|
||||||
|
if (!endDate) {
|
||||||
|
str += " an unlimited number of ";
|
||||||
|
} else {
|
||||||
|
str += "";
|
||||||
|
}
|
||||||
|
str += " emails";
|
||||||
|
$('#stats').html(str);
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
var products = {{ $products }};
|
var products = {{ $products }};
|
||||||
|
@ -18,7 +18,7 @@
|
|||||||
, array('id'=>'archive'))->split(); }}
|
, array('id'=>'archive'))->split(); }}
|
||||||
|
|
||||||
|
|
||||||
{{ Button::primary_link(URL::to($entityType . 's/create'), 'New ' . ucwords($entityType), array('class' => 'pull-right')) }}
|
{{ Button::primary_link(URL::to($entityType . 's/create'), 'New ' . Utils::getEntityName($entityType), array('class' => 'pull-right')) }}
|
||||||
|
|
||||||
{{ Datatable::table()
|
{{ Datatable::table()
|
||||||
->addColumn($columns)
|
->addColumn($columns)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user