fix: Project screen budget data and decimal precision#166
fix: Project screen budget data and decimal precision#166
Conversation
There was a problem hiding this comment.
Pull request overview
This PR updates how the Project screen derives budgeted time/cost data from Business Central (switching to contracted “Billable” planning lines), fixes UOM (DAY/HOUR) conversions when editing planning lines, and improves Project charts/precision for time display.
Changes:
- Use Billable Job Planning Lines for “Time Budgeted” and budget-related totals instead of weekly Plan/Budget allocations.
- Fix PlanResourceModal read/write to convert quantities correctly between resource base units (DAY/HOUR) and hours.
- Extend charts to include up to 12 future weeks of planned hours and standardize time values to 2 decimal places in tooltips/labels.
Reviewed changes
Copilot reviewed 5 out of 5 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| src/services/bc/projectService.ts | Updates project-list budget hours aggregation to filter Billable/Both line types. |
| src/services/bc/projectDetailsService.ts | Updates project analytics to compute planned hours and budget totals from Billable lines. |
| src/components/projects/ProjectKPICards.tsx | Displays time values with 2-decimal precision; updates “Time Budgeted” tooltip copy. |
| src/components/projects/ProjectCharts.tsx | Extends weekly window into the future; improves y-axis scaling; uses 2-decimal precision in tooltips. |
| src/components/plan/PlanResourceModal.tsx | Adds UOM conversion map usage and converts quantities to/from hours when reading/writing planning lines. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| // Billable lines represent the contracted project budget | ||
| // Budget lines are weekly allocations from the Plan screen and are not included in budget/price totals | ||
| const billableLines = planningLines.filter((line: BCJobPlanningLine) => | ||
| isBillableLine(line.lineType) | ||
| ); | ||
| budgetCost = budgetLines.reduce( | ||
| (sum: number, line: BCJobPlanningLine) => sum + line.totalCost, | ||
|
|
||
| // Budget Cost: sum totalPrice from Billable lines (contracted budget) with breakdown by type | ||
| budgetCost = billableLines.reduce( | ||
| (sum: number, line: BCJobPlanningLine) => sum + line.totalPrice, | ||
| 0 | ||
| ); |
There was a problem hiding this comment.
budgetCost is now computed from billableLines by summing line.totalPrice. A few lines later, billablePrice is also computed from the same billableLines by summing line.totalPrice, which makes budgetCost and billablePrice identical and breaks the intended cost-vs-price distinction (and the existing UI/tooltips that say Budget Cost comes from totalCost). If Budget Cost is meant to remain an internal cost budget, this should sum totalCost (and breakdowns should use totalCost) while billablePrice continues to use totalPrice.
There was a problem hiding this comment.
Intentional. The user confirmed Budget Cost should show the contracted amount (totalPrice from Billable lines), not internal cost. For their workflow the project budget IS the contracted price.
There was a problem hiding this comment.
I wasn't sure about this one ... needs further confirmation / investigation I think.
| .then((resourceUOMs) => { | ||
| setUomMap(buildUOMConversionMap(resourceUOMs)); | ||
| }) | ||
| .catch(() => { |
There was a problem hiding this comment.
If getResourceUnitsOfMeasure() fails, the code silently falls back to an empty UOM map. In that case convertToHours/convertFromHours will behave like identity functions, potentially reintroducing the DAY/HOUR UOM bug and writing incorrect quantities back to BC. Consider surfacing an error (e.g., toast) and preventing save until UOM data is available (or retrying fetch on submit).
| .catch(() => { | |
| .catch((error) => { | |
| console.error('Failed to load resource units of measure', error); | |
| toast.error('Failed to load resource units of measure'); |
There was a problem hiding this comment.
Low risk since empty map means identity conversion (hours pass through as-is, which is correct for HOUR-based resources). Will consider adding error surfacing in a follow-up.
- Use Billable lines for Time Budgeted and Budget Cost instead of Budget lines - Fix PlanResourceModal UOM conversion on read/write paths - Extend chart window to show future planned hours - Use two decimal places for time values - Dynamic Y-axis labels for Spend vs Budget chart Fixes #151, #157, #158, #159, #160, #161, #162, #165 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
5c0f044 to
c4141b7
Compare
|
Tested, addressed Copilot comments, check please @BenGWeeks |
Summary
Issues Fixed
Files Changed
src/components/plan/PlanResourceModal.tsx— UOM conversion on read/writesrc/components/projects/ProjectCharts.tsx— future weeks, Y-axis scaling, decimalssrc/components/projects/ProjectKPICards.tsx— two decimals, tooltip updatesrc/services/bc/projectDetailsService.ts— Billable lines for budget datasrc/services/bc/projectService.ts— Billable lines for project list budgetTest plan
🤖 Generated with Claude Code