fix(finance-table): refine budget and variance calculations for improved accuracy

- Updated budget calculations to consistently include fixed costs across all tasks.
- Adjusted variance logic to align with the new budget calculations, ensuring accurate financial reporting.
- Increased save delay for fixed cost input to 5 seconds, allowing users more time to edit values.
- Added text selection on input focus for better user experience.
This commit is contained in:
chamiakJ
2025-06-12 16:21:48 +05:30
parent a08d1efc36
commit 4783b5ec10
2 changed files with 20 additions and 11 deletions

View File

@@ -85,13 +85,14 @@ const FinanceTableWrapper: React.FC<FinanceTableWrapperProps> = ({ activeTablesL
} else { } else {
// Leaf task - calculate values from individual task properties // Leaf task - calculate values from individual task properties
const leafTotalActual = (task.actual_cost_from_logs || 0) + (task.fixed_cost || 0); const leafTotalActual = (task.actual_cost_from_logs || 0) + (task.fixed_cost || 0);
const leafTotalBudget = (task.estimated_cost || 0) + (task.fixed_cost || 0);
return { return {
hours: acc.hours + (task.estimated_seconds || 0), hours: acc.hours + (task.estimated_seconds || 0),
cost: acc.cost + (task.actual_cost_from_logs || 0), cost: acc.cost + (task.actual_cost_from_logs || 0),
fixedCost: acc.fixedCost + (task.fixed_cost || 0), fixedCost: acc.fixedCost + (task.fixed_cost || 0),
totalBudget: acc.totalBudget + (task.estimated_cost || 0), totalBudget: acc.totalBudget + leafTotalBudget,
totalActual: acc.totalActual + leafTotalActual, totalActual: acc.totalActual + leafTotalActual,
variance: acc.variance + (leafTotalActual - (task.estimated_cost || 0)), variance: acc.variance + (leafTotalActual - leafTotalBudget),
total_time_logged: acc.total_time_logged + (task.total_time_logged_seconds || 0), total_time_logged: acc.total_time_logged + (task.total_time_logged_seconds || 0),
estimated_cost: acc.estimated_cost + (task.estimated_cost || 0) estimated_cost: acc.estimated_cost + (task.estimated_cost || 0)
}; };

View File

@@ -230,10 +230,9 @@ const FinanceTable = ({
// Only save if the value actually changed // Only save if the value actually changed
if (newFixedCost !== currentFixedCost && value !== null) { if (newFixedCost !== currentFixedCost && value !== null) {
handleFixedCostChange(value, taskId); handleFixedCostChange(value, taskId);
setSelectedTask(null); // Don't close the input automatically - let user explicitly close it
setEditingFixedCostValue(null);
} }
}, 1000); // Save after 1 second of inactivity }, 5000); // Save after 5 seconds of inactivity
}; };
// Immediate save function (for enter/blur) // Immediate save function (for enter/blur)
@@ -442,6 +441,10 @@ const FinanceTable = ({
// Immediate save on enter // Immediate save on enter
immediateSaveFixedCost(editingFixedCostValue, task.id); immediateSaveFixedCost(editingFixedCostValue, task.id);
}} }}
onFocus={(e) => {
// Select all text when input is focused
e.target.select();
}}
autoFocus autoFocus
style={{ width: '100%', textAlign: 'right', fontSize: Math.max(12, 14 - level * 0.5) }} style={{ width: '100%', textAlign: 'right', fontSize: Math.max(12, 14 - level * 0.5) }}
formatter={(value) => `${value}`.replace(/\B(?=(\d{3})+(?!\d))/g, ',')} formatter={(value) => `${value}`.replace(/\B(?=(\d{3})+(?!\d))/g, ',')}
@@ -472,22 +475,27 @@ const FinanceTable = ({
</Typography.Text> </Typography.Text>
); );
case FinanceTableColumnKeys.VARIANCE: case FinanceTableColumnKeys.VARIANCE:
const taskTotalBudgetForVariance = (task.estimated_cost || 0) + (task.fixed_cost || 0);
const taskTotalActualForVariance = (task.actual_cost_from_logs || 0) + (task.fixed_cost || 0);
const taskVariance = taskTotalActualForVariance - taskTotalBudgetForVariance;
return ( return (
<Typography.Text <Typography.Text
style={{ style={{
color: task.variance > 0 ? '#FF0000' : '#6DC376', color: taskVariance > 0 ? '#FF0000' : '#6DC376',
fontSize: Math.max(12, 14 - level * 0.5) fontSize: Math.max(12, 14 - level * 0.5)
}} }}
> >
{task.variance < 0 ? '+' + formatNumber(Math.abs(task.variance)) : {taskVariance < 0 ? '+' + formatNumber(Math.abs(taskVariance)) :
task.variance > 0 ? '-' + formatNumber(task.variance) : taskVariance > 0 ? '-' + formatNumber(taskVariance) :
formatNumber(task.variance)} formatNumber(taskVariance)}
</Typography.Text> </Typography.Text>
); );
case FinanceTableColumnKeys.TOTAL_BUDGET: case FinanceTableColumnKeys.TOTAL_BUDGET:
return <Typography.Text style={{ fontSize: Math.max(12, 14 - level * 0.5) }}>{formatNumber(task.total_budget)}</Typography.Text>; const taskTotalBudget = (task.estimated_cost || 0) + (task.fixed_cost || 0);
return <Typography.Text style={{ fontSize: Math.max(12, 14 - level * 0.5) }}>{formatNumber(taskTotalBudget)}</Typography.Text>;
case FinanceTableColumnKeys.TOTAL_ACTUAL: case FinanceTableColumnKeys.TOTAL_ACTUAL:
return <Typography.Text style={{ fontSize: Math.max(12, 14 - level * 0.5) }}>{formatNumber(task.total_actual)}</Typography.Text>; const taskTotalActual = (task.actual_cost_from_logs || 0) + (task.fixed_cost || 0);
return <Typography.Text style={{ fontSize: Math.max(12, 14 - level * 0.5) }}>{formatNumber(taskTotalActual)}</Typography.Text>;
case FinanceTableColumnKeys.COST: case FinanceTableColumnKeys.COST:
return <Typography.Text style={{ fontSize: Math.max(12, 14 - level * 0.5) }}>{formatNumber(task.actual_cost_from_logs || 0)}</Typography.Text>; return <Typography.Text style={{ fontSize: Math.max(12, 14 - level * 0.5) }}>{formatNumber(task.actual_cost_from_logs || 0)}</Typography.Text>;
default: default: