Merge branch 'feature/project-finance' of https://github.com/Worklenz/worklenz into feature/project-finance

This commit is contained in:
root
2025-06-06 09:14:09 +00:00
3 changed files with 52 additions and 32 deletions

View File

@@ -9,6 +9,7 @@ import { financeTableColumns, FinanceTableColumnKeys } from '@/lib/project/proje
import FinanceTable from './finance-table'; import FinanceTable from './finance-table';
import FinanceDrawer from '@/features/finance/finance-drawer/finance-drawer'; import FinanceDrawer from '@/features/finance/finance-drawer/finance-drawer';
import { IProjectFinanceGroup } from '@/types/project/project-finance.types'; import { IProjectFinanceGroup } from '@/types/project/project-finance.types';
import { createPortal } from 'react-dom';
interface FinanceTableWrapperProps { interface FinanceTableWrapperProps {
activeTablesList: IProjectFinanceGroup[]; activeTablesList: IProjectFinanceGroup[];
@@ -128,7 +129,9 @@ const FinanceTableWrapper: React.FC<FinanceTableWrapperProps> = ({ activeTablesL
fontSize: 18, fontSize: 18,
}} }}
> >
{`${totals.variance?.toFixed(2)}`} {totals.variance < 0 ? `+${Math.abs(totals.variance).toFixed(2)}` :
totals.variance > 0 ? `-${totals.variance.toFixed(2)}` :
`${totals.variance?.toFixed(2)}`}
</Typography.Text> </Typography.Text>
); );
case FinanceTableColumnKeys.TOTAL_TIME_LOGGED: case FinanceTableColumnKeys.TOTAL_TIME_LOGGED:
@@ -243,7 +246,7 @@ const FinanceTableWrapper: React.FC<FinanceTableWrapperProps> = ({ activeTablesL
</table> </table>
</Flex> </Flex>
<FinanceDrawer /> {createPortal(<FinanceDrawer />, document.body)}
</> </>
); );
}; };

View File

@@ -125,7 +125,13 @@ const FinanceTable = ({
case FinanceTableColumnKeys.TOTAL_ACTUAL: case FinanceTableColumnKeys.TOTAL_ACTUAL:
return <Typography.Text>{formatNumber(formattedTotals.total_actual)}</Typography.Text>; return <Typography.Text>{formatNumber(formattedTotals.total_actual)}</Typography.Text>;
case FinanceTableColumnKeys.VARIANCE: case FinanceTableColumnKeys.VARIANCE:
return <Typography.Text style={{ color: formattedTotals.variance > 0 ? '#FF0000' : '#6DC376' }}>{formatNumber(formattedTotals.variance)}</Typography.Text>; return (
<Typography.Text style={{ color: formattedTotals.variance > 0 ? '#FF0000' : '#6DC376' }}>
{formattedTotals.variance < 0 ? '+' + formatNumber(Math.abs(formattedTotals.variance)) :
formattedTotals.variance > 0 ? '-' + formatNumber(formattedTotals.variance) :
formatNumber(formattedTotals.variance)}
</Typography.Text>
);
default: default:
return null; return null;
} }
@@ -325,7 +331,9 @@ const FinanceTable = ({
color: task.variance > 0 ? '#FF0000' : '#6DC376' color: task.variance > 0 ? '#FF0000' : '#6DC376'
}} }}
> >
{formatNumber(task.variance)} {task.variance < 0 ? '+' + formatNumber(Math.abs(task.variance)) :
task.variance > 0 ? '-' + formatNumber(task.variance) :
formatNumber(task.variance)}
</Typography.Text> </Typography.Text>
); );
case FinanceTableColumnKeys.TOTAL_BUDGET: case FinanceTableColumnKeys.TOTAL_BUDGET:

View File

@@ -314,90 +314,99 @@ const ProjectViewFinance = () => {
} }
style={{ marginBottom: 16 }} style={{ marginBottom: 16 }}
loading={loading} loading={loading}
size="small"
> >
<Row gutter={[16, 16]}> <Row gutter={[12, 8]}>
<Col xs={24} sm={12} md={8} lg={6}> <Col xs={12} sm={8} md={6} lg={4} xl={3}>
<Statistic <Statistic
title="Total Budget" title="Total Budget"
value={budgetStatistics.totalBudget} value={budgetStatistics.totalBudget}
precision={2} precision={2}
prefix={projectCurrency.toUpperCase()} prefix={projectCurrency.toUpperCase()}
valueStyle={{ color: '#1890ff' }} valueStyle={{ color: '#1890ff', fontSize: '16px' }}
style={{ textAlign: 'center' }}
/> />
</Col> </Col>
<Col xs={24} sm={12} md={8} lg={6}> <Col xs={12} sm={8} md={6} lg={4} xl={3}>
<Statistic <Statistic
title="Actual Cost" title="Actual Cost"
value={budgetStatistics.totalActualCost} value={budgetStatistics.totalActualCost}
precision={2} precision={2}
prefix={projectCurrency.toUpperCase()} prefix={projectCurrency.toUpperCase()}
valueStyle={{ color: '#52c41a' }} valueStyle={{ color: '#52c41a', fontSize: '16px' }}
style={{ textAlign: 'center' }}
/> />
</Col> </Col>
<Col xs={24} sm={12} md={8} lg={6}> <Col xs={12} sm={8} md={6} lg={4} xl={3}>
<Statistic <Statistic
title="Variance" title="Variance"
value={budgetStatistics.totalVariance} value={Math.abs(budgetStatistics.totalVariance)}
precision={2} precision={2}
prefix={budgetStatistics.totalVariance >= 0 ? '+' : ''} prefix={projectCurrency.toUpperCase()}
suffix={projectCurrency.toUpperCase()} suffix={budgetStatistics.totalVariance < 0 ? ' under' : budgetStatistics.totalVariance > 0 ? ' over' : ''}
valueStyle={{ valueStyle={{
color: budgetStatistics.totalVariance > 0 ? '#ff4d4f' : '#52c41a' color: budgetStatistics.totalVariance > 0 ? '#ff4d4f' : '#52c41a',
fontSize: '16px'
}} }}
style={{ textAlign: 'center' }}
/> />
</Col> </Col>
<Col xs={24} sm={12} md={8} lg={6}> <Col xs={12} sm={8} md={6} lg={4} xl={3}>
<Statistic <Statistic
title="Budget Utilization" title="Utilization"
value={budgetStatistics.budgetUtilization} value={budgetStatistics.budgetUtilization}
precision={1} precision={1}
suffix="%" suffix="%"
valueStyle={{ valueStyle={{
color: budgetStatistics.budgetUtilization > 100 ? '#ff4d4f' : color: budgetStatistics.budgetUtilization > 100 ? '#ff4d4f' :
budgetStatistics.budgetUtilization > 80 ? '#faad14' : '#52c41a' budgetStatistics.budgetUtilization > 80 ? '#faad14' : '#52c41a',
fontSize: '16px'
}} }}
style={{ textAlign: 'center' }}
/> />
</Col> </Col>
</Row> <Col xs={12} sm={8} md={6} lg={4} xl={3}>
<Row gutter={[16, 16]} style={{ marginTop: 16 }}>
<Col xs={24} sm={12} md={8} lg={6}>
<Statistic <Statistic
title="Estimated Cost" title="Estimated"
value={budgetStatistics.totalEstimatedCost} value={budgetStatistics.totalEstimatedCost}
precision={2} precision={2}
prefix={projectCurrency.toUpperCase()} prefix={projectCurrency.toUpperCase()}
valueStyle={{ color: '#722ed1' }} valueStyle={{ color: '#722ed1', fontSize: '16px' }}
style={{ textAlign: 'center' }}
/> />
</Col> </Col>
<Col xs={24} sm={12} md={8} lg={6}> <Col xs={12} sm={8} md={6} lg={4} xl={3}>
<Statistic <Statistic
title="Fixed Cost" title="Fixed Cost"
value={budgetStatistics.totalFixedCost} value={budgetStatistics.totalFixedCost}
precision={2} precision={2}
prefix={projectCurrency.toUpperCase()} prefix={projectCurrency.toUpperCase()}
valueStyle={{ color: '#fa8c16' }} valueStyle={{ color: '#fa8c16', fontSize: '16px' }}
style={{ textAlign: 'center' }}
/> />
</Col> </Col>
<Col xs={24} sm={12} md={8} lg={6}> <Col xs={12} sm={8} md={6} lg={4} xl={3}>
<Statistic <Statistic
title="Cost from Time Logs" title="Time Logs"
value={budgetStatistics.totalActualCost - budgetStatistics.totalFixedCost} value={budgetStatistics.totalActualCost - budgetStatistics.totalFixedCost}
precision={2} precision={2}
prefix={projectCurrency.toUpperCase()} prefix={projectCurrency.toUpperCase()}
valueStyle={{ color: '#13c2c2' }} valueStyle={{ color: '#13c2c2', fontSize: '16px' }}
style={{ textAlign: 'center' }}
/> />
</Col> </Col>
<Col xs={24} sm={12} md={8} lg={6}> <Col xs={12} sm={8} md={6} lg={4} xl={3}>
<Statistic <Statistic
title="Budget Status" title="Remaining"
value={budgetStatistics.totalBudget - budgetStatistics.totalActualCost} value={budgetStatistics.totalBudget - budgetStatistics.totalActualCost}
precision={2} precision={2}
prefix={budgetStatistics.totalBudget - budgetStatistics.totalActualCost >= 0 ? '+' : ''} prefix={budgetStatistics.totalBudget - budgetStatistics.totalActualCost >= 0 ? '+' : ''}
suffix={`${projectCurrency.toUpperCase()} remaining`} suffix={projectCurrency.toUpperCase()}
valueStyle={{ valueStyle={{
color: budgetStatistics.totalBudget - budgetStatistics.totalActualCost >= 0 ? '#52c41a' : '#ff4d4f' color: budgetStatistics.totalBudget - budgetStatistics.totalActualCost >= 0 ? '#52c41a' : '#ff4d4f',
fontSize: '16px'
}} }}
style={{ textAlign: 'center' }}
/> />
</Col> </Col>
</Row> </Row>