diff --git a/app/commands/SendRecurringInvoices.php b/app/commands/SendRecurringInvoices.php index 9f4d482d117e..1e582149b8bc 100755 --- a/app/commands/SendRecurringInvoices.php +++ b/app/commands/SendRecurringInvoices.php @@ -22,9 +22,9 @@ class SendRecurringInvoices extends Command { { $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'); foreach ($invoices as $recurInvoice) @@ -38,7 +38,7 @@ class SendRecurringInvoices extends Command { $invoice = Invoice::createNew($recurInvoice); $invoice->client_id = $recurInvoice->client_id; - $invoice->parent_id = $recurInvoice->id; + $invoice->recurring_invoice_id = $recurInvoice->id; $invoice->invoice_number = $recurInvoice->account->getNextInvoiceNumber(); $invoice->total = $recurInvoice->total; $invoice->invoice_date = new DateTime(); diff --git a/app/controllers/ClientController.php b/app/controllers/ClientController.php index 6fe3133cf378..9430ffae2468 100755 --- a/app/controllers/ClientController.php +++ b/app/controllers/ClientController.php @@ -99,7 +99,9 @@ class ClientController extends \BaseController { $data = array( 'client' => $client, - 'title' => '- ' . $client->name); + 'title' => '- ' . $client->name, + 'hasRecurringInvoices' => RecurringInvoice::whereClientId($client->id)->count() > 0 + ); return View::make('clients.show', $data); } diff --git a/app/controllers/InvoiceController.php b/app/controllers/InvoiceController.php index 7c7fd18cf185..0294ee4c9e11 100755 --- a/app/controllers/InvoiceController.php +++ b/app/controllers/InvoiceController.php @@ -279,15 +279,15 @@ class InvoiceController extends \BaseController { return View::make('invoices.edit', $data); } - private static function getViewModel() + public static function getViewModel($isRecurring = false) { return [ + 'isRecurring' => $isRecurring, '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', @@ -366,21 +366,17 @@ class InvoiceController extends \BaseController { if ($publicId) { $invoice = Invoice::scope($publicId)->firstOrFail(); $invoice->invoice_items()->forceDelete(); - } else { + } else { $invoice = Invoice::createNew(); } $invoice->client_id = $client->id; - $invoice->invoice_number = trim(Input::get('invoice_number')); $invoice->discount = 0; + $invoice->invoice_number = trim(Input::get('invoice_number')); $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->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')); diff --git a/app/controllers/RecurringInvoiceController.php b/app/controllers/RecurringInvoiceController.php new file mode 100755 index 000000000000..e70b8b25f98a --- /dev/null +++ b/app/controllers/RecurringInvoiceController.php @@ -0,0 +1,280 @@ +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 ''; }); + } + + //$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 '
'; + }) + ->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'); + } +} \ No newline at end of file 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 dff39acf18a7..6081bbdc95a2 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 @@ -17,10 +17,12 @@ class ConfideSetupUsersTable extends Migration { Schema::dropIfExists('account_gateways'); Schema::dropIfExists('gateways'); Schema::dropIfExists('payments'); + Schema::dropIfExists('recurring_invoice_items'); Schema::dropIfExists('invoice_items'); Schema::dropIfExists('products'); Schema::dropIfExists('contacts'); Schema::dropIfExists('invoices'); + Schema::dropIfExists('recurring_invoices'); Schema::dropIfExists('password_reminders'); Schema::dropIfExists('clients'); Schema::dropIfExists('users'); @@ -28,6 +30,7 @@ class ConfideSetupUsersTable extends Migration { Schema::dropIfExists('invoice_statuses'); Schema::dropIfExists('countries'); Schema::dropIfExists('timezones'); + Schema::dropIfExists('frequencies'); Schema::create('countries', function($table) { @@ -200,6 +203,38 @@ class ConfideSetupUsersTable extends Migration { $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) { @@ -220,17 +255,13 @@ class ConfideSetupUsersTable extends Migration { $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->date('last_sent_date')->nullable(); - $t->unsignedInteger('parent_id')->nullable(); + $t->unsignedInteger('recurring_invoice_id')->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('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->unique( array('account_id','public_id') ); @@ -302,6 +333,29 @@ class ConfideSetupUsersTable extends Migration { $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) { $t->increments('id'); @@ -363,6 +417,7 @@ class ConfideSetupUsersTable extends Migration { $t->unsignedInteger('contact_id'); $t->unsignedInteger('payment_id'); $t->unsignedInteger('invoice_id'); + $t->unsignedInteger('recurring_invoice_id'); $t->unsignedInteger('credit_id'); $t->unsignedInteger('invitation_id'); @@ -390,16 +445,19 @@ class ConfideSetupUsersTable extends Migration { Schema::dropIfExists('account_gateways'); Schema::dropIfExists('gateways'); Schema::dropIfExists('payments'); + Schema::dropIfExists('recurring_invoice_items'); Schema::dropIfExists('invoice_items'); Schema::dropIfExists('products'); Schema::dropIfExists('contacts'); Schema::dropIfExists('invoices'); + Schema::dropIfExists('recurring_invoices'); Schema::dropIfExists('password_reminders'); Schema::dropIfExists('clients'); Schema::dropIfExists('users'); Schema::dropIfExists('accounts'); Schema::dropIfExists('invoice_statuses'); Schema::dropIfExists('countries'); - Schema::dropIfExists('timezones'); + Schema::dropIfExists('timezones'); + Schema::dropIfExists('frequencies'); } } diff --git a/app/database/seeds/ConstantsSeeder.php b/app/database/seeds/ConstantsSeeder.php index 5c41b34e08f3..569afae27217 100755 --- a/app/database/seeds/ConstantsSeeder.php +++ b/app/database/seeds/ConstantsSeeder.php @@ -50,6 +50,14 @@ class ConstantsSeeder extends Seeder InvoiceStatus::create(array('name' => 'Partial')); 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 = [ array('name'=>'Authorize.Net AIM', 'provider'=>'AuthorizeNet_AIM'), array('name'=>'Authorize.Net SIM', 'provider'=>'AuthorizeNet_SIM'), diff --git a/app/libraries/utils.php b/app/libraries/utils.php index 22b50c810ae0..fb8a64f256dc 100755 --- a/app/libraries/utils.php +++ b/app/libraries/utils.php @@ -207,4 +207,9 @@ class Utils $year = intval(date('Y')); return $year + $offset; } + + public static function getEntityName($entityType) + { + return ucwords(str_replace('_', ' ', $entityType)); + } } \ No newline at end of file diff --git a/app/models/Activity.php b/app/models/Activity.php index 71d033c8d2ff..97d223352dd4 100755 --- a/app/models/Activity.php +++ b/app/models/Activity.php @@ -15,6 +15,10 @@ define("ACTIVITY_TYPE_DELETE_PAYMENT", 11); define("ACTIVITY_TYPE_CREATE_CREDIT", 12); define("ACTIVITY_TYPE_ARCHIVE_CREDIT", 13); 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 { @@ -94,6 +98,26 @@ class Activity extends Eloquent $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) { if (Auth::check()) diff --git a/app/models/Frequency.php b/app/models/Frequency.php new file mode 100755 index 000000000000..deac8c7a88ae --- /dev/null +++ b/app/models/Frequency.php @@ -0,0 +1,6 @@ +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) diff --git a/app/models/RecurringInvoice.php b/app/models/RecurringInvoice.php new file mode 100755 index 000000000000..b625288c8948 --- /dev/null +++ b/app/models/RecurringInvoice.php @@ -0,0 +1,88 @@ +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); +}); \ No newline at end of file diff --git a/app/models/RecurringInvoiceItem.php b/app/models/RecurringInvoiceItem.php new file mode 100755 index 000000000000..10d61a2ed75d --- /dev/null +++ b/app/models/RecurringInvoiceItem.php @@ -0,0 +1,6 @@ + 'auth'), function() Route::get('invoices/create/{client_id?}', 'InvoiceController@create'); 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::resource('payments', 'PaymentController'); Route::get('payments/create/{client_id?}', 'PaymentController@create'); @@ -93,12 +100,17 @@ HTML::macro('menu_link', function($type) { $types = $type.'s'; $Type = ucfirst($type); $Types = ucfirst($types); - $class = ( Request::is($types) || Request::is($types.'/*')) ? ' active' : ''; - return ' +@@ -294,9 +299,19 @@ }); - @if ($invoice && $invoice->isRecurring()) - toggleRecurring(true); - @endif; + $('label.radio').addClass('radio-inline'); + + + @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(); 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_2').toggleClass('col-md-5 col-md-3'); @@ -654,7 +686,27 @@ if (!show) { $('#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 clients = {{ $clients }}; diff --git a/app/views/list.blade.php b/app/views/list.blade.php index 3170da94066b..f2b3651b0b7b 100755 --- a/app/views/list.blade.php +++ b/app/views/list.blade.php @@ -18,7 +18,7 @@ , 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() ->addColumn($columns)