1
0
mirror of https://github.com/invoiceninja/invoiceninja.git synced 2024-11-09 12:42:36 +01:00

Working on activity tracking

This commit is contained in:
Hillel Coren 2013-11-26 23:45:10 +02:00
parent ab4d9d4792
commit 7b41fbc779
14 changed files with 212 additions and 151 deletions

View File

@ -215,7 +215,7 @@ class AccountController extends \BaseController {
}
$client->save();
$client->contacts()->save($contact);
$client->contacts()->save($contact);
}
$message = pluralize('Successfully created ? client', $count);

View File

@ -25,7 +25,7 @@ class ClientController extends \BaseController {
})
->addColumn('contact', function($model)
{
return $model->contacts[0]->fullName();
return $model->contacts[0]->getFullName();
})
->addColumn('last_login', function($model)
{

View File

@ -40,6 +40,10 @@ class InvoiceController extends \BaseController {
public function view($invoiceKey)
{
$invoice = Invoice::with('invoice_items', 'client.account.account_gateways')->where('invoice_key', '=', $invoiceKey)->firstOrFail();
$contact = null;
Activity::viewInvoice($invoice, $contact)
return View::make('invoices.view')->with('invoice', $invoice);
}
@ -98,6 +102,7 @@ class InvoiceController extends \BaseController {
$payment = new Payment;
$payment->invoice_id = $invoice->id;
$payment->account_id = $invoice->account_id;
$payment->contact_id = 0;
$payment->transaction_reference = $response->getTransactionReference();
$payment->save();
@ -272,6 +277,8 @@ class InvoiceController extends \BaseController {
$message->to($contact->email);
});
Activity::emailInvoice($invoice, $contact);
Session::flash('message', 'Successfully emailed invoice');
} else {
Session::flash('message', 'Successfully saved invoice');

View File

@ -10,6 +10,7 @@ class ConfideSetupUsersTable extends Migration {
*/
public function up()
{
Schema::dropIfExists('activities');
Schema::dropIfExists('account_gateways');
Schema::dropIfExists('gateways');
Schema::dropIfExists('products');
@ -176,13 +177,13 @@ class ConfideSetupUsersTable extends Migration {
//$t->foreign('account_id')->references('id')->on('accounts');
});
Schema::create('payments', function($t)
{
$t->increments('id');
$t->integer('invoice_id');
$t->integer('account_id');
$t->integer('contact_id');
$t->integer('user_id');
$t->timestamps();
$t->softDeletes();
@ -193,6 +194,20 @@ class ConfideSetupUsersTable extends Migration {
//$t->foreign('account_id')->references('id')->on('accounts');
});
Schema::create('activities', function($t)
{
$t->increments('id');
$t->integer('account_id');
$t->integer('user_id');
$t->integer('client_id');
$t->integer('contact_id');
$t->integer('invoice_id');
$t->integer('payment_id');
$t->timestamps();
$t->integer('activity_type_id');
$t->text('message');
});
}
/**
@ -202,6 +217,7 @@ class ConfideSetupUsersTable extends Migration {
*/
public function down()
{
Schema::dropIfExists('activities');
Schema::dropIfExists('account_gateways');
Schema::dropIfExists('gateways');
Schema::dropIfExists('products');

View File

@ -6,10 +6,16 @@ class ConstantsSeeder extends Seeder
public function run()
{
DB::table('gateways')->delete();
Gateway::create(array(
'name' => 'PayPal Express',
'provider' => 'PayPal_Express'
));
/*
ActivityType::create(array(
'name' => 'Created invoice'
));
*/
}
}

View File

@ -5,15 +5,21 @@ class UserTableSeeder extends Seeder
public function run()
{
DB::table('users')->delete();
//DB::table('users')->delete();
/*
User::create(array(
'first_name' => 'Hillel',
$account = Account::create(array(
'name' => 'Acme Inc',
));
$user = User::create(array(
'account_id' => $account->id,
'first_name' => 'Hillel',
'last_name' => 'Coren',
'email' => 'hillelcoren@gmail.com',
'email' => 'hillelcoren@gmail.com',
'password' => Hash::make('1234'),
));
*/
*/
}
}

View File

@ -1,13 +1,16 @@
<?php
define("ACTIVITY_TYPE_CREATE_CLIENT", 1);
define("ACTIVITY_TYPE_ARCHIVE_CLIENT", 2);
define("ACTIVITY_TYPE_CREATE_INVOICE", 3);
define("ACTIVITY_TYPE_EMAIL_INVOICE", 4);
define("ACTIVITY_TYPE_VIEW_INVOICE", 5);
define("ACTIVITY_TYPE_ARCHIVE_INVOICE", 6);
define("ACTIVITY_TYPE_CREATE_PAYMENT", 7);
define("ACTIVITY_TYPE_ARCHIVE_PAYMENT", 8);
class Activity extends Eloquent
{
/*
define("ACTIVITY_TYPE_CONTACT_VIEW_INVOICE", 11);
define("ACTIVITY_TYPE_CONTACT_LOGIN", 12);
*/
private static function getBlank()
{
$user = Auth::user();
@ -25,7 +28,7 @@ define("ACTIVITY_TYPE_CONTACT_LOGIN", 12);
$activity->activity_type_id = ACTIVITY_TYPE_CREATE_CLIENT;
$activity->message = $user->getFullName() . ' created client ' . $client->name;
$activity->save();
}
}
public static function archiveClient($client)
{
@ -66,20 +69,19 @@ define("ACTIVITY_TYPE_CONTACT_LOGIN", 12);
$activity->save();
}
public static function createPayment($payment, $contact)
public static function createPayment($payment)
{
if ($contact)
{
$activity = new Activity;
$activity->contact_id = $contact->id;
$activity->message = $contact->getFullName() . ' created payment ' . $payment->transaction_reference;
}
else
if (Auth::check())
{
$activity = Activity::getBlank();
$activity->message = $user->getFullName() . ' created invoice ' . $payment->transaction_reference;
}
else
{
$activity = new Activity;
$activity->contact_id = $payment->contact_id;
$activity->message = $contact->getFullName() . ' created payment ' . $payment->transaction_reference;
}
$activity->payment_id = $payment->id;
$activity->invoice_id = $payment->invoice_id;
@ -101,11 +103,11 @@ define("ACTIVITY_TYPE_CONTACT_LOGIN", 12);
public static function viewInvoice($invoice, $contact)
{
$activity = new Activity;
$activity->contact_id = $contact->id;
//$activity->contact_id = $contact->id;
$activity->invoice_id = $invoice->id;
$activity->client_id = $invoice->client_id;
$activity->activity_type_id = ACTIVITY_TYPE_VIEW_INVOICE;
$activity->message = $contact->getFullName() . ' viewed invoice ' . $invoice->number;
$activity->save();
}
}
}

View File

@ -27,4 +27,9 @@ class Client extends Eloquent
{
return $this->hasMany('Contact');
}
}
}
Client::created(function($client)
{
Activity::createClient($client);
});

View File

@ -14,11 +14,6 @@ class Contact extends Eloquent
return $this->belongsTo('Client');
}
public function fullName()
{
return $this->first_name . ' ' . $this->last_name;
}
public function lastLogin()
{
if ($this->last_login == '0000-00-00 00:00:00')
@ -30,4 +25,18 @@ class Contact extends Eloquent
return $this->last_login;
}
}
public function getFullName()
{
$fullName = $this->first_name . ' ' . $this->last_name;
if ($fullName == ' ')
{
return "Unknown";
}
else
{
return $fullName;
}
}
}

View File

@ -25,4 +25,9 @@ class Invoice extends Eloquent
return $total;
}
}
}
Invoice::created(function($invoice)
{
Activity::createInvoice($invoice);
});

View File

@ -8,4 +8,9 @@ class Payment extends Eloquent
{
return $this->belongsTo('Invoice');
}
}
}
Payment::created(function($payment)
{
Activity::createPayment($payment);
});

View File

@ -68,4 +68,17 @@ class User extends ConfideUser implements UserInterface, RemindableInterface {
return $this->email;
}
public function getFullName()
{
$fullName = $this->first_name . ' ' . $this->last_name;
if ($fullName == ' ')
{
return "Unknown";
}
else
{
return $fullName;
}
}
}

View File

@ -261,11 +261,11 @@
<div class="collapse navbar-collapse" id="navbar-collapse-1">
<ul class="nav navbar-nav" style="font-weight: bold">
{{ HTML::nav_link('home', 'Home') }}
{{-- HTML::nav_link('home', 'Home') --}}
{{ HTML::menu_link('client') }}
{{ HTML::menu_link('invoice') }}
{{ HTML::menu_link('payment') }}
{{ HTML::nav_link('reports', 'Reports') }}
{{-- HTML::nav_link('reports', 'Reports') --}}
</ul>
<form class="navbar-form navbar-right" role="search">
<div class="form-group">

View File

@ -2,127 +2,114 @@
@section('content')
</div>
<div>
<div class=".container">
<p>&nbsp;</p>
<div class="row">
{{ Former::open($url)->method($method)->addClass('main_form')->rules(array(
'number' => 'required',
)); }}
<div class="col-md-6 col-sm-10">
<div>
{{ Former::open($url)->method($method)->addClass('main_form')->rules(array(
'number' => 'required',
)); }}
<!-- <h3>{{ $title }} Invoice</h3> -->
<!-- <h3>{{ $title }} Invoice</h3> -->
@if ($invoice)
{{ Former::populate($invoice); }}
{{ Former::populateField('issued_on', DateTime::createFromFormat('Y-m-d', $invoice->issued_on)->format('m/d/Y')); }}
@else
{{ Former::populateField('issued_on', date('m/d/Y')) }}
@endif
<div class="row">
<div class="col-md-6">
{{ Former::select('client')->addOption('', '')->fromQuery($clients, 'name', 'id')->select($client ? $client->id : '')
->help('<a class="ul" data-toggle="modal" data-target="#myModal">Create new client</a>'); }}
</div>
<div class="col-md-6">
{{ Former::text('number') }}
{{ Former::text('issued_on') }}
{{ Former::text('discount')->data_bind("value: discount, valueUpdate: 'afterkeydown'") }}
</div>
</div>
<p>&nbsp;</p>
</div>
<div style="padding-left:16px">
<input type="text" name="items" data-bind="value: ko.toJSON(items)" style="display:none"/>
<table class="table invoice-table" style="margin-bottom: 0px !important;">
<thead>
<tr>
<th class="hide-border"></th>
<th>Item</th>
<th>Description</th>
<th>Unit&nbsp;Cost</th>
<th>Quantity</th>
<th>Line&nbsp;Total</th>
<th class="hide-border"></th>
</tr>
</thead>
<tbody data-bind="sortable: { data: items, afterMove: onDragged }">
<tr data-bind="event: { mouseover: showActions, mouseout: hideActions }" class="sortable-row">
<td style="width:50px;" class="hide-border">
<i data-bind="click: $parent.addItem, visible: actionsVisible" class="fa fa-plus-circle" style="cursor:pointer" title="Add item"></i>&nbsp;
<i data-bind="visible: actionsVisible" class="fa fa-sort"></i>
</td>
<td style="width:120px">
<input data-bind="value: product_key, valueUpdate: 'afterkeydown'" onchange="refreshPDF()"/>
</td>
<td style="width:300px">
<textarea data-bind="value: notes, valueUpdate: 'afterkeydown'" rows="1" cols="60" onchange="refreshPDF()"></textarea>
</td>
<td style="width:100px">
<input data-bind="value: cost, valueUpdate: 'afterkeydown'" style="text-align: right" onchange="refreshPDF()"//>
</td>
<td style="width:80px">
<input data-bind="value: qty, valueUpdate: 'afterkeydown'" style="text-align: right" onchange="refreshPDF()"//>
</td>
<!--
<td style="width:100px">
<input data-bind="value: tax, valueUpdate: 'afterkeydown'"/>
</td>
-->
<td style="width:100px;background-color: #FFFFFF;text-align: right">
<span data-bind="text: total"></span>
</td>
<td style="width:20px; cursor:pointer" class="hide-border">
&nbsp;<i data-bind="click: $parent.removeItem, visible: actionsVisible() &amp;&amp; $parent.items().length > 1" class="fa fa-minus-circle" title="Remove item"/>
</td>
</tr>
</tbody>
<tfoot>
<tr data-bind="visible: subtotal() != total()">
<td colspan="3" class="hide-border"/>
<td colspan="2">Subtotal</td>
<td style="text-align: right"><span data-bind="text: subtotal"/></td>
</tr>
<tr data-bind="visible: discount() > 0">
<td colspan="3" class="hide-border"/>
<td colspan="2">Discount</td>
<td style="text-align: right"><span data-bind="text: discounted"/></td>
</tr>
<tr>
<td colspan="3" class="hide-border"/>
<td colspan="2">Invoice Total</td>
<td style="text-align: right"><span data-bind="text: total"/></td>
</tr>
</tfoot>
</table>
</div>
<input type="checkbox" name="send_email_checkBox" id="send_email_checkBox" value="true" style="display:none"/>
<p>&nbsp;</p>
<div class="form-actions">
{{ Button::primary('Download PDF', array('onclick' => 'onDownloadClick()')) }}
{{ Button::primary_submit('Save Invoice') }}
{{ Button::primary('Send Email', array('onclick' => 'onEmailClick()')) }}
</div>
<p>&nbsp;</p>
@if ($invoice)
{{ Former::populate($invoice); }}
{{ Former::populateField('issued_on', DateTime::createFromFormat('Y-m-d', $invoice->issued_on)->format('m/d/Y')); }}
@else
{{ Former::populateField('issued_on', date('m/d/Y')) }}
@endif
<div class="row">
<div class="col-md-6">
{{ Former::select('client')->addOption('', '')->fromQuery($clients, 'name', 'id')->select($client ? $client->id : '')
->help('<a class="ul" data-toggle="modal" data-target="#myModal">Create new client</a>'); }}
</div>
<div class="col-md-6">
<!-- <textarea rows="20" cols="120" id="pdfText" onkeyup="runCode()"></textarea> -->
<!-- <iframe frameborder="1" width="600" height="600" style="display:block;margin: 0 auto"></iframe> -->
<iframe frameborder="1" width="92%" height="600" style="display:block;margin: 0 auto"></iframe>
<div class="col-md-5">
{{ Former::text('number')->label('Invoice #') }}
{{ Former::text('issued_on')->label('Invoice Date') }}
{{-- Former::text('discount')->data_bind("value: discount, valueUpdate: 'afterkeydown'") --}}
</div>
</div>
<p>&nbsp;</p>
<input type="text" name="items" data-bind="value: ko.toJSON(items)" style="display:none"/>
<table class="table invoice-table" style="margin-bottom: 0px !important;">
<thead>
<tr>
<th class="hide-border"></th>
<th>Item</th>
<th>Description</th>
<th>Unit&nbsp;Cost</th>
<th>Quantity</th>
<th>Line&nbsp;Total</th>
<th class="hide-border"></th>
</tr>
</thead>
<tbody data-bind="sortable: { data: items, afterMove: onDragged }">
<tr data-bind="event: { mouseover: showActions, mouseout: hideActions }" class="sortable-row">
<td style="width:50px;" class="hide-border">
<i data-bind="click: $parent.addItem, visible: actionsVisible" class="fa fa-plus-circle" style="cursor:pointer" title="Add item"></i>&nbsp;
<i data-bind="visible: actionsVisible" class="fa fa-sort"></i>
</td>
<td style="width:120px">
<input data-bind="value: product_key, valueUpdate: 'afterkeydown'" onchange="refreshPDF()"/>
</td>
<td style="width:300px">
<textarea data-bind="value: notes, valueUpdate: 'afterkeydown'" rows="1" cols="60" onchange="refreshPDF()"></textarea>
</td>
<td style="width:100px">
<input data-bind="value: cost, valueUpdate: 'afterkeydown'" style="text-align: right" onchange="refreshPDF()"//>
</td>
<td style="width:80px">
<input data-bind="value: qty, valueUpdate: 'afterkeydown'" style="text-align: right" onchange="refreshPDF()"//>
</td>
<!--
<td style="width:100px">
<input data-bind="value: tax, valueUpdate: 'afterkeydown'"/>
</td>
-->
<td style="width:100px;background-color: #FFFFFF;text-align: right">
<span data-bind="text: total"></span>
</td>
<td style="width:20px; cursor:pointer" class="hide-border">
&nbsp;<i data-bind="click: $parent.removeItem, visible: actionsVisible() &amp;&amp; $parent.items().length > 1" class="fa fa-minus-circle" title="Remove item"/>
</td>
</tr>
</tbody>
<tfoot>
<tr data-bind="visible: subtotal() != total()">
<td colspan="3" class="hide-border"/>
<td colspan="2">Subtotal</td>
<td style="text-align: right"><span data-bind="text: subtotal"/></td>
</tr>
<tr data-bind="visible: discount() > 0">
<td colspan="3" class="hide-border"/>
<td colspan="2">Discount</td>
<td style="text-align: right"><span data-bind="text: discounted"/></td>
</tr>
<tr>
<td colspan="3" class="hide-border"/>
<td colspan="2">Invoice Total</td>
<td style="text-align: right"><span data-bind="text: total"/></td>
</tr>
</tfoot>
</table>
<input type="checkbox" name="send_email_checkBox" id="send_email_checkBox" value="true" style="display:none"/>
<p>&nbsp;</p>
<div class="form-actions">
{{ Button::primary('Download PDF', array('onclick' => 'onDownloadClick()')) }}
{{ Button::primary_submit('Save Invoice') }}
{{ Button::primary('Send Email', array('onclick' => 'onEmailClick()')) }}
</div>
<p>&nbsp;</p>
<!-- <textarea rows="20" cols="120" id="pdfText" onkeyup="runCode()"></textarea> -->
<!-- <iframe frameborder="1" width="600" height="600" style="display:block;margin: 0 auto"></iframe> -->
<iframe frameborder="1" width="92%" height="600" style="display:block;margin: 0 auto"></iframe>
<div class="modal fade" id="myModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
<div class="modal-dialog">