Add default rate / amount for time tracking / tasks #1575

This commit is contained in:
Hillel Coren 2017-10-17 13:57:20 +03:00
parent 7ef9bc9cd6
commit 697de9b3b2
18 changed files with 109 additions and 2 deletions

View File

@ -262,7 +262,7 @@ class TaskController extends BaseController
$this->taskRepo->save($ids, ['action' => $action]);
return Redirect::to('tasks')->withMessage(trans($action == 'stop' ? 'texts.stopped_task' : 'texts.resumed_task'));
} elseif ($action == 'invoice' || $action == 'add_to_invoice') {
$tasks = Task::scope($ids)->with('client')->orderBy('project_id', 'id')->get();
$tasks = Task::scope($ids)->with('account', 'client', 'project')->orderBy('project_id', 'id')->get();
$clientPublicId = false;
$data = [];
@ -294,6 +294,7 @@ class TaskController extends BaseController
'publicId' => $task->public_id,
'description' => $task->present()->invoiceDescription($account, $showProject),
'duration' => $task->getHours(),
'cost' => $task->getRate(),
];
$lastProjectId = $task->project_id;
}

View File

@ -176,6 +176,7 @@ class Account extends Eloquent
'credit_number_counter',
'credit_number_prefix',
'credit_number_pattern',
'task_rate',
];
/**

View File

@ -52,6 +52,7 @@ class Client extends EntityModel
'invoice_number_counter',
'quote_number_counter',
'public_notes',
'task_rate',
];

View File

@ -24,6 +24,7 @@ class Project extends EntityModel
*/
protected $fillable = [
'name',
'task_rate',
];
/**

View File

@ -145,6 +145,24 @@ class Task extends EntityModel
return self::calcDuration($this);
}
/**
* @return float
*/
public function getRate()
{
$value = 0;
if ($this->project && floatval($this->project->task_rate)) {
$value = $this->project->task_rate;
} elseif ($this->client && floatval($this->client->task_rate)) {
$value = $this->client->task_rate;
} else {
$value = $this->account->task_rate;
}
return Utils::roundSignificant($value);
}
/**
* @return int
*/

View File

@ -38,6 +38,12 @@ class ProjectDatatable extends EntityDatatable
}
},
],
[
'task_rate',
function ($model) {
return floatval($model->task_rate) ? Utils::roundSignificant($model->task_rate) : '';
}
],
];
}

View File

@ -35,6 +35,7 @@ class ProjectRepository extends BaseRepository
'projects.public_id',
'projects.user_id',
'projects.deleted_at',
'projects.task_rate',
'projects.is_deleted',
DB::raw("COALESCE(NULLIF(clients.name,''), NULLIF(CONCAT(contacts.first_name, ' ', contacts.last_name),''), NULLIF(contacts.email,'')) client_name"),
'clients.user_id as client_user_id',

View File

@ -274,6 +274,7 @@ class AccountTransformer extends EntityTransformer
'reset_counter_date' => $account->reset_counter_date,
'custom_contact_label1' => $account->custom_contact_label1,
'custom_contact_label2' => $account->custom_contact_label2,
'task_rate' => (float) $account->task_rate,
];
}
}

View File

@ -37,6 +37,7 @@ class ClientTransformer extends EntityTransformer
* @SWG\Property(property="vat_number", type="string", example="123456")
* @SWG\Property(property="id_number", type="string", example="123456")
* @SWG\Property(property="language_id", type="integer", example=1)
* @SWG\Property(property="task_rate", type="number", format="float", example=10)
*/
protected $defaultIncludes = [
'contacts',
@ -135,6 +136,7 @@ class ClientTransformer extends EntityTransformer
'custom_value2' => $client->custom_value2,
'invoice_number_counter' => (int) $client->invoice_number_counter,
'quote_number_counter' => (int) $client->quote_number_counter,
'task_rate' => (float) $client->task_rate,
]);
}
}

View File

@ -16,6 +16,7 @@ class ProjectTransformer extends EntityTransformer
* @SWG\Property(property="updated_at", type="integer", example=1451160233, readOnly=true)
* @SWG\Property(property="archived_at", type="integer", example=1451160233, readOnly=true)
* @SWG\Property(property="is_deleted", type="boolean", example=false, readOnly=true)
* @SWG\Property(property="task_rate", type="number", format="float", example=10)
*/
public function transform(Project $project)
{
@ -26,6 +27,7 @@ class ProjectTransformer extends EntityTransformer
'updated_at' => $this->getTimestamp($project->updated_at),
'archived_at' => $this->getTimestamp($project->deleted_at),
'is_deleted' => (bool) $project->is_deleted,
'task_rate' => (float) $project->task_rate,
]);
}
}

View File

@ -0,0 +1,47 @@
<?php
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class AddDefaultRates extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::table('accounts', function ($table) {
$table->decimal('task_rate', 12, 4);
});
Schema::table('clients', function ($table) {
$table->decimal('task_rate', 12, 4);
});
Schema::table('projects', function ($table) {
$table->decimal('task_rate', 12, 4);
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::table('accounts', function ($table) {
$table->dropColumn('task_rate');
});
Schema::table('clients', function ($table) {
$table->dropColumn('task_rate');
});
Schema::table('projects', function ($table) {
$table->dropColumn('task_rate');
});
}
}

View File

@ -2483,6 +2483,9 @@ $LANG = array(
'clear' => 'Clear',
'warn_payment_gateway' => 'Note: to accept online payments :link to add a payment gateway.',
'setup_desktop_app' => 'Setup the desktop app',
'task_rate' => 'Task Rate',
'task_rate_help' => 'Set the default <b>rate for invoiced tasks</b>.',
);
return $LANG;

View File

@ -19,6 +19,7 @@
]) !!}
{{ Former::populate($account) }}
{{ Former::populateField('task_rate', floatval($account->task_rate) ? Utils::roundSignificant($account->task_rate) : '') }}
@include('accounts.nav', ['selected' => ACCOUNT_COMPANY_DETAILS])
@ -99,6 +100,11 @@
->fromQuery(\App\Models\PaymentTerm::getSelectOptions(), 'name', 'num_days')
->help(trans('texts.payment_terms_help') . ' | ' . link_to('/settings/payment_terms', trans('texts.customize_options'))) !!}
@if ($account->isModuleEnabled(ENTITY_TASK))
{!! Former::text('task_rate')
->help('task_rate_help')!!}
@endif
</div>
</div>
</div>

View File

@ -23,6 +23,7 @@
@if ($client)
{!! Former::populate($client) !!}
{!! Former::populateField('task_rate', floatval($client->task_rate) ? Utils::roundSignificant($client->task_rate) : '') !!}
{!! Former::hidden('public_id') !!}
@else
{!! Former::populateField('invoice_number_counter', 1) !!}
@ -155,6 +156,10 @@
->fromQuery(\App\Models\PaymentTerm::getSelectOptions(), 'name', 'num_days')
->placeholder($account->present()->paymentTerms)
->help(trans('texts.payment_terms_help')) !!}
@if ($account->isModuleEnabled(ENTITY_TASK))
{!! Former::text('task_rate')
->help('task_rate_help') !!}
@endif
{!! Former::select('size_id')->addOption('','')
->fromQuery($sizes, 'name', 'id') !!}
{!! Former::select('industry_id')->addOption('','')

View File

@ -111,6 +111,8 @@
{{ $client->country->name }}<br/>
@endif
<br/>
@if ($client->account->custom_client_label1 && $client->custom_value1)
{{ $client->account->custom_client_label1 . ': ' . $client->custom_value1 }}<br/>
@endif
@ -122,6 +124,10 @@
<i class="fa fa-phone" style="width: 20px"></i>{{ $client->work_phone }}
@endif
@if (floatval($client->task_rate))
<p>{{ trans('texts.task_rate') }}: {{ Utils::roundSignificant($client->task_rate) }}</p>
@endif
@if ($client->public_notes)
<p><i>{{ $client->public_notes }}</i></p>
@endif

View File

@ -893,6 +893,7 @@
var item = model.invoice().addItem(true);
item.notes(task.description);
item.qty(task.duration);
item.cost(task.cost);
item.task_public_id(task.publicId);
}
model.invoice().has_tasks(true);

View File

@ -1013,8 +1013,10 @@ ko.bindingHandlers.productTypeahead = {
model.notes(datum.notes);
}
if (datum.cost) {
if (! model.cost() || ! model.task_public_id()) {
model.cost(roundSignificant(datum.cost, 2));
}
}
if (!model.qty()) {
model.qty(1);
}

View File

@ -12,6 +12,7 @@
@if ($project)
{!! Former::populate($project) !!}
{!! Former::populateField('task_rate', floatval($project->task_rate) ? Utils::roundSignificant($project->task_rate) : '') !!}
@endif
<span style="display:none">
@ -39,6 +40,8 @@
{!! Former::text('name') !!}
{!! Former::text('task_rate')
->help('task_rate_help') !!}
</div>
</div>