Refactor task management and add attachment functionality
- Updated task editing template to handle default status for new tasks and corrected variable names. - Enhanced work time reporting by rounding time to the nearest quarter hour and adjusting amount formatting. - Introduced TasksController to manage task-related operations, including status resolution and email notifications. - Added TaskAttachmentRepository for handling task attachments, including upload, rename, and delete functionalities. - Implemented WorkTimeRepository to fetch clients with unsettled tasks and calculate total work time. - Created unit tests for TasksController and TaskAttachmentRepository to ensure functionality and correctness.
This commit is contained in:
@@ -122,7 +122,7 @@ if ( is_array( $this -> parent_tasks ) )
|
||||
'label' => 'Status',
|
||||
'name' => 'status',
|
||||
'id' => 'status',
|
||||
'value' => $this -> task[ 'status' ],
|
||||
'value' => $this -> task[ 'id' ] ? $this -> task[ 'status' ] : 5,
|
||||
'values' => \factory\Tasks::get_statuses()
|
||||
] );?>
|
||||
<!-- priorytet -->
|
||||
@@ -157,7 +157,7 @@ if ( is_array( $this -> priorities ) )
|
||||
'label' => 'Powiadom o zmianie statusu',
|
||||
'name' => 'status_change_mail',
|
||||
'id' => 'status_change_mail',
|
||||
'checked' => ( $this -> task[ 'status_change_mail' ] or !$this -> taks['id'] ) ? true : false,
|
||||
'checked' => ( $this -> task[ 'status_change_mail' ] or !$this -> task['id'] ) ? true : false,
|
||||
'type' => 'checkbox'
|
||||
] );
|
||||
?>
|
||||
@@ -191,11 +191,11 @@ if ( is_array( $this -> priorities ) )
|
||||
'type' => 'checkbox'
|
||||
] );
|
||||
?>
|
||||
<div class="form_group" id="recursive-details">
|
||||
<div class="form_group" id="recursive-details" style="<?= $this -> task[ 'recursively' ] ? '' : 'display: none;';?>">
|
||||
<label class="label">Powtarzaj co:</label>
|
||||
<div class="input">
|
||||
<input type="text" class="form-control" name="frequency" value="<?= $this -> task[ 'id' ] ? $this -> task[ 'frequency' ] : 1;?>">
|
||||
<select name="period" class="form-control">
|
||||
<div class="input" style="display: flex; gap: 10px; align-items: center;">
|
||||
<input type="text" class="form-control" name="frequency" style="max-width: 110px;" value="<?= $this -> task[ 'id' ] ? $this -> task[ 'frequency' ] : 1;?>">
|
||||
<select name="period" class="form-control" style="max-width: 140px;">
|
||||
<option value="1" <? if ( $this -> task[ 'period' ] == '1' ):?>selected="selected"<? endif;?>>dni</option>
|
||||
<option value="2" <? if ( $this -> task[ 'period' ] == '2' ):?>selected="selected"<? endif;?>>m-ce</option>
|
||||
<option value="3" <? if ( $this -> task[ 'period' ] == '3' ):?>selected="selected"<? endif;?>>lata</option>
|
||||
@@ -216,7 +216,7 @@ if ( is_array( $this -> priorities ) )
|
||||
'label' => 'Pokaż w kalendarzu',
|
||||
'name' => 'show_in_calendar',
|
||||
'id' => 'show_in_calendar',
|
||||
'checked' => ( $this -> task[ 'show_in_calendar' ] or !$this -> taks['id'] ) ? true : false,
|
||||
'checked' => ( $this -> task[ 'show_in_calendar' ] or !$this -> task['id'] ) ? true : false,
|
||||
'type' => 'checkbox'
|
||||
] );
|
||||
?>
|
||||
@@ -262,11 +262,24 @@ echo $grid -> draw();
|
||||
<script type="text/javascript">
|
||||
$(document).ready(function ()
|
||||
{
|
||||
function toggleRecursiveDetails() {
|
||||
if ( $( '#recursively' ).is( ':checked' ) )
|
||||
$( '#recursive-details' ).show();
|
||||
else
|
||||
$( '#recursive-details' ).hide();
|
||||
}
|
||||
|
||||
$('input[type="checkbox"]').iCheck({
|
||||
checkboxClass: 'icheckbox_square-blue',
|
||||
radioClass: 'iradio_square-blue',
|
||||
});
|
||||
|
||||
toggleRecursiveDetails();
|
||||
|
||||
$( '#recursively' ).on( 'ifChanged change', function() {
|
||||
toggleRecursiveDetails();
|
||||
});
|
||||
|
||||
$( 'body' ).on( 'click', '.task-remove', function(e)
|
||||
{
|
||||
e.preventDefault();
|
||||
@@ -323,7 +336,19 @@ echo $grid -> draw();
|
||||
});
|
||||
|
||||
$( '#project_id, #client_id, #status' ).select2({
|
||||
theme: 'bootstrap-5'
|
||||
theme: 'bootstrap-5',
|
||||
minimumResultsForSearch: 0
|
||||
});
|
||||
|
||||
$( '#project_id, #client_id, #status' ).on( 'select2:open', function() {
|
||||
setTimeout( function() {
|
||||
var search_field = document.querySelector( '.select2-container--open .select2-search__field' );
|
||||
if ( search_field )
|
||||
{
|
||||
search_field.focus();
|
||||
search_field.select();
|
||||
}
|
||||
}, 0 );
|
||||
});
|
||||
});
|
||||
</script>
|
||||
</script>
|
||||
|
||||
@@ -4,8 +4,16 @@ $format_time = function( $seconds ) {
|
||||
return sprintf( "%02d%s%02d%s%02d", floor( $seconds / 3600 ), ':', ( $seconds / 60 ) % 60, ':', $seconds % 60 );
|
||||
};
|
||||
|
||||
$round_time_to_quarter = function( $seconds ) {
|
||||
$seconds = (int)$seconds;
|
||||
if ( $seconds <= 0 )
|
||||
return 0;
|
||||
|
||||
return (int)( round( $seconds / 900 ) * 900 );
|
||||
};
|
||||
|
||||
$format_amount = function( $amount ) {
|
||||
return number_format( (float)$amount, 2, '.', '' ) . ' zł';
|
||||
return number_format( (float)$amount, 0, '.', '' ) . ' zł';
|
||||
};
|
||||
|
||||
$billing_clients = [];
|
||||
@@ -37,11 +45,12 @@ foreach ( $this -> work_time_clients as $client )
|
||||
foreach ( $tasks as $task )
|
||||
{
|
||||
$task_time = isset( $task['time'] ) ? (int)$task['time'] : 0;
|
||||
$task_time = $round_time_to_quarter( $task_time );
|
||||
|
||||
if ( isset( $task['pay_rate'] ) and $task['pay_rate'] !== null and $task['pay_rate'] !== '' )
|
||||
$task_amount = (float)$task['pay_rate'];
|
||||
$task_amount = round( (float)$task['pay_rate'] );
|
||||
else
|
||||
$task_amount = (float)$this -> settings['hourly_rate'] * ( $task_time / 3600 );
|
||||
$task_amount = round( (float)$this -> settings['hourly_rate'] * ( $task_time / 3600 ) );
|
||||
|
||||
$summary['tasks_count']++;
|
||||
$summary['time'] += $task_time;
|
||||
@@ -122,7 +131,7 @@ usort( $billing_clients, function( $a, $b ) {
|
||||
<tbody>
|
||||
<? foreach ( $billing_clients as $summary ):?>
|
||||
<? $details_id = 'billing-details-' . md5( $summary['firm'] );?>
|
||||
<tr class="billing-client-row" data-details-id="<?= $details_id;?>" data-tasks-count="<?= $summary['tasks_count'];?>" data-time="<?= $summary['time'];?>" data-amount="<?= number_format( (float)$summary['amount'], 2, '.', '' );?>">
|
||||
<tr class="billing-client-row" data-details-id="<?= $details_id;?>" data-tasks-count="<?= $summary['tasks_count'];?>" data-time="<?= $summary['time'];?>" data-amount="<?= number_format( (float)$summary['amount'], 0, '.', '' );?>">
|
||||
<td class="billing-client-name"><a href="#<?= $summary['firm'];?>"><?= $summary['firm'];?></a></td>
|
||||
<td class="text-center billing-client-tasks"><?= $summary['tasks_count'];?></td>
|
||||
<td class="text-center billing-client-time"><?= $format_time( $summary['time'] );?></td>
|
||||
@@ -145,7 +154,7 @@ usort( $billing_clients, function( $a, $b ) {
|
||||
</thead>
|
||||
<tbody>
|
||||
<? foreach ( $summary['rows'] as $row ):?>
|
||||
<tr class="billing-task-row" data-task-time="<?= (int)$row['time'];?>" data-task-amount="<?= number_format( (float)$row['amount'], 2, '.', '' );?>">
|
||||
<tr class="billing-task-row" data-task-time="<?= (int)$row['time'];?>" data-task-amount="<?= number_format( (float)$row['amount'], 0, '.', '' );?>">
|
||||
<td><?= $row['month'];?></td>
|
||||
<td><?= $row['name'];?></td>
|
||||
<td class="text-center"><?= $format_time( $row['time'] );?></td>
|
||||
@@ -184,7 +193,7 @@ usort( $billing_clients, function( $a, $b ) {
|
||||
|
||||
function formatAmount( amount ) {
|
||||
amount = parseFloat( amount ) || 0;
|
||||
return amount.toFixed( 2 ) + ' z\u0142';
|
||||
return Math.round( amount ) + ' z\u0142';
|
||||
}
|
||||
|
||||
function refreshGlobalKpis() {
|
||||
@@ -311,7 +320,7 @@ usort( $billing_clients, function( $a, $b ) {
|
||||
{
|
||||
summary_row.attr( 'data-tasks-count', client_tasks_count );
|
||||
summary_row.attr( 'data-time', client_time );
|
||||
summary_row.attr( 'data-amount', client_amount.toFixed( 2 ) );
|
||||
summary_row.attr( 'data-amount', Math.round( client_amount ) );
|
||||
summary_row.find( '.billing-client-tasks' ).text( client_tasks_count );
|
||||
summary_row.find( '.billing-client-time' ).text( formatTime( client_time ) );
|
||||
summary_row.find( '.billing-client-amount' ).text( formatAmount( client_amount ) );
|
||||
|
||||
Reference in New Issue
Block a user