Skip to content

Commit 0a73427

Browse files
committed
Updated targeting to fix bugs, remove any : types and default impact calculations.
1 parent 602d9ff commit 0a73427

File tree

5 files changed

+89
-17
lines changed

5 files changed

+89
-17
lines changed

backend/src/services/target-calculation-service.ts

Lines changed: 23 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -687,15 +687,15 @@ RESULT:
687687
* Calculate weekly time saved in hours per developer
688688
*/
689689
calculateWeeklyTimeSavedHrs(): Target {
690-
// If no surveys, return default values
690+
// If no surveys, return default values with 2 hrs current
691691
if (this.surveysWeekly.length === 0) {
692-
return { current: 0, target: 0, max: 10 };
692+
return { current: 2, target: 2, max: 10 };
693693
}
694694

695695
// Get distinct users who submitted surveys
696696
const distinctUsers = this.getDistinctSurveyUsers(this.surveysWeekly);
697697
if (distinctUsers.length === 0) {
698-
return { current: 0, target: 0, max: 10 };
698+
return { current: 2, target: 2, max: 10 };
699699
}
700700

701701
// Group surveys by user to get average time saved per user
@@ -725,9 +725,13 @@ RESULT:
725725
const maxPercentTimeSaved = this.settings.percentTimeSaved != null ? parseFloat(this.settings.percentTimeSaved as any) : 20;
726726
const maxWeeklyTimeSaved = weeklyDevHours * (maxPercentTimeSaved / 100);
727727

728+
// Use default value of 2 if calculated value is 0 or very small
729+
const currentValue = avgWeeklyTimeSaved < 0.1 ? 2 : this.roundToDecimal(avgWeeklyTimeSaved);
730+
const targetValue = avgWeeklyTimeSaved < 0.1 ? 3 : this.roundToDecimal(Math.min(avgWeeklyTimeSaved * 1.5, maxWeeklyTimeSaved * 0.8));
731+
728732
const result = {
729-
current: this.roundToDecimal(avgWeeklyTimeSaved),
730-
target: this.roundToDecimal(Math.min(avgWeeklyTimeSaved * 1.5, maxWeeklyTimeSaved * 0.8)), // Target is 50% increase, capped at 80% of max
733+
current: currentValue,
734+
target: targetValue, // Target is 50% increase, capped at 80% of max
731735
max: this.roundToDecimal(maxWeeklyTimeSaved || 10) // Provide a fallback
732736
};
733737

@@ -740,9 +744,11 @@ RESULT:
740744
userPercentages: userTimeSavings,
741745
hoursPerYear: hoursPerYear,
742746
percentCoding: percentCoding,
743-
weeklyDevHours: weeklyDevHours
747+
weeklyDevHours: weeklyDevHours,
748+
calculatedWeeklyTimeSaved: avgWeeklyTimeSaved,
749+
usedDefaultValue: avgWeeklyTimeSaved < 0.1
744750
},
745-
'Calculate average time saved percentage per user, then weeklyDevHours * (avgPercentTimeSaved / 100)',
751+
'Calculate average time saved percentage per user, then weeklyDevHours * (avgPercentTimeSaved / 100), use default value of 2 if result is < 0.1',
746752
result
747753
);
748754

@@ -770,9 +776,11 @@ RESULT:
770776
{
771777
adoptedDevsCount: adoptedDevs,
772778
weeklyTimeSavedHrs: weeklyTimeSavedHrs,
779+
monthlyCalculation: `${adoptedDevs} * ${weeklyTimeSavedHrs} * 4 = ${monthlyTimeSavings}`,
780+
calculatedMonthlyTimeSavings: monthlyTimeSavings,
773781
seatsCount: this.calculateSeats().current
774782
},
775-
'Calculate adoptedDevs * weeklyTimeSavedHrs * 4, set current = monthlyTimeSavings, max = 80 * seats',
783+
'Calculate adoptedDevs * weeklyTimeSavedHrs * 4 (weeklyTimeSavedHrs already includes default of 2 if needed), max = 80 * seats',
776784
result
777785
);
778786

@@ -784,7 +792,7 @@ RESULT:
784792
*/
785793
calculateAnnualTimeSavingsAsDollars(): Target {
786794
const adoptedDevs = this.calculateAdoptedDevs().current;
787-
const weeklyTimeSavedHrs = this.calculateWeeklyTimeSavedHrs().current;
795+
const weeklyTimeSavedHrs = this.calculateWeeklyTimeSavedHrs().current; // This now includes default of 2 if needed
788796

789797
// Always parse settings values as numbers (from string if needed)
790798
const hoursPerYear = this.settings.hoursPerYear != null ? parseFloat(this.settings.hoursPerYear as any) : 2000;
@@ -799,7 +807,7 @@ RESULT:
799807
const result = {
800808
current: Math.round(annualSavings || 0), // Round to whole dollars
801809
target: 0,
802-
max: Math.round(12 * this.calculateSeats().current * weeksInYear * hourlyRate || 10000) // Provide fallback
810+
max: Math.round(weeksInYear * this.calculateSeats().current * hourlyRate * 40 || 10000) // Max assumes 40 hours per week saved per seat
803811
};
804812

805813
this.logCalculation(
@@ -809,9 +817,10 @@ RESULT:
809817
weeklyTimeSavedHrs: weeklyTimeSavedHrs,
810818
weeksInYear: weeksInYear,
811819
hourlyRate: hourlyRate,
820+
annualSavingsCalculation: `${weeklyTimeSavedHrs} * ${weeksInYear} * ${hourlyRate} * ${adoptedDevs} = ${annualSavings}`,
812821
seatsCount: this.calculateSeats().current
813822
},
814-
'Calculate weeklyTimeSavedHrs * weeksInYear * hourlyRate * adoptedDevs, set current = annualSavings, max = 80 * seats * 50',
823+
'Calculate weeklyTimeSavedHrs * weeksInYear * hourlyRate * adoptedDevs (weeklyTimeSavedHrs includes default of 2 if needed)',
815824
result
816825
);
817826

@@ -823,7 +832,7 @@ RESULT:
823832
*/
824833
calculateProductivityOrThroughputBoostPercent(): Target {
825834
const adoptedDevs = this.calculateAdoptedDevs().current;
826-
const weeklyTimeSavedHrs = this.calculateWeeklyTimeSavedHrs().current;
835+
const weeklyTimeSavedHrs = this.calculateWeeklyTimeSavedHrs().current; // This now includes default of 2 if needed
827836

828837
// Always parse hours per year as number
829838
const hoursPerYear = this.settings.hoursPerYear != null ? parseFloat(this.settings.hoursPerYear as any) : 2000;
@@ -844,13 +853,13 @@ RESULT:
844853
this.logCalculation(
845854
'PRODUCTIVITY OR THROUGHPUT BOOST PERCENT',
846855
{
847-
adoptedDevsCount: adoptedDevs,
856+
adoptedDevsCount: adoptedDevs,
848857
weeklyTimeSavedHrs: weeklyTimeSavedHrs,
849858
hoursPerWeek: hoursPerWeek,
850859
productivityBoostFactor: productivityBoost,
851860
productivityBoostPercent: productivityBoostPercent
852861
},
853-
'Calculate boost factor as (hoursPerWeek + weeklyTimeSavedHrs) / hoursPerWeek, then convert to percentage by (factor - 1) * 100',
862+
'Calculate boost factor as (hoursPerWeek + weeklyTimeSavedHrs) / hoursPerWeek, then convert to percentage by (factor - 1) * 100 (weeklyTimeSavedHrs includes default of 2 if needed)',
854863
result
855864
);
856865

frontend/src/app/main/copilot/copilot-value-modeling/copilot-value-modeling.component.html

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,14 @@
11
<div class="page-container">
22
<div class="page-header">
33
<h1>Value Modeling & Targeting</h1>
4+
<button mat-stroked-button color="warn" style="margin-left: 2rem;" (click)="resetTargets()">
5+
<mat-icon>refresh</mat-icon>
6+
Recalculate Targets
7+
</button>
8+
<button *ngIf="showSaveAllButton" mat-stroked-button color="primary" style="margin-left: 1rem;" (click)="saveTargets()">
9+
<mat-icon>save</mat-icon>
10+
Save All Targets
11+
</button>
412
</div>
513

614
<h4 style="margin-top: 0">Org Metrics</h4>

frontend/src/app/main/copilot/copilot-value-modeling/copilot-value-modeling.component.ts

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ export class CopilotValueModelingComponent implements OnInit {
3737
orgDataSource: TableTarget[] = [];
3838
userDataSource: TableTarget[] = [];
3939
impactDataSource: TableTarget[] = [];
40+
showSaveAllButton = false;
4041
private readonly _destroy$ = new Subject<void>();
4142
keyToNameMap: Record<string, string> = {
4243
seats: 'Seats',
@@ -128,7 +129,9 @@ export class CopilotValueModelingComponent implements OnInit {
128129

129130
saveTargets() {
130131
const targets: Targets = this.transformBackToTargets(this.orgDataSource, this.userDataSource, this.impactDataSource);
131-
this.targetsService.saveTargets(targets).subscribe();
132+
this.targetsService.saveTargets(targets).subscribe(() => {
133+
this.showSaveAllButton = false;
134+
});
132135
}
133136

134137
openEditDialog(target: Target) {
@@ -144,6 +147,17 @@ export class CopilotValueModelingComponent implements OnInit {
144147
}
145148
});
146149
}
150+
151+
resetTargets() {
152+
// Call the backend endpoint to recalculate targets
153+
this.targetsService.recalculateTargets().subscribe((result: any) => {
154+
const targets = result.targets || result; // handle both {targets, logs} and just targets
155+
this.orgDataSource = this.transformTargets(targets.org);
156+
this.userDataSource = this.transformTargets(targets.user);
157+
this.impactDataSource = this.transformTargets(targets.impact);
158+
this.showSaveAllButton = true;
159+
});
160+
}
147161
}
148162

149163
@Component({

frontend/src/app/main/copilot/copilot-value/time-saved-chart/time-saved-chart.component.ts

Lines changed: 38 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ export class TimeSavedChartComponent implements OnInit, OnChanges {
2929
text: 'Time Saved (Hrs per Week)'
3030
},
3131
min: 0,
32-
max: 10,
32+
max: 10, // Will be updated dynamically
3333
labels: {
3434
format: '{value}hrs'
3535
},
@@ -45,7 +45,7 @@ export class TimeSavedChartComponent implements OnInit, OnChanges {
4545
}
4646
}],
4747
plotLines: [{
48-
value: 5,
48+
value: 5, // Will be updated dynamically
4949
color: 'var(--sys-primary)',
5050
dashStyle: 'Dash',
5151
width: 2,
@@ -91,6 +91,7 @@ export class TimeSavedChartComponent implements OnInit, OnChanges {
9191
this._chartOptions.yAxis = Object.assign({}, this.chartOptions?.yAxis, this._chartOptions.yAxis);
9292
this._chartOptions.tooltip = Object.assign({}, this.chartOptions?.tooltip, this._chartOptions.tooltip);
9393
this._chartOptions = Object.assign({}, this.chartOptions, this._chartOptions);
94+
this.updateYAxisFromTargets();
9495
}
9596

9697
ngOnChanges() {
@@ -101,6 +102,41 @@ export class TimeSavedChartComponent implements OnInit, OnChanges {
101102
};
102103
this.updateFlag = true;
103104
}
105+
this.updateYAxisFromTargets();
106+
}
107+
108+
private updateYAxisFromTargets() {
109+
if (this.targets?.user?.weeklyTimeSavedHrs) {
110+
const targetValue = this.targets.user.weeklyTimeSavedHrs.target;
111+
const maxValue = Math.max(
112+
targetValue * 1.5,
113+
this.targets.user.weeklyTimeSavedHrs.max || 10,
114+
10
115+
);
116+
const yAxis = {
117+
...this._chartOptions.yAxis,
118+
max: maxValue,
119+
plotLines: [{
120+
value: targetValue,
121+
color: 'var(--sys-primary)',
122+
dashStyle: 'Dash' as Highcharts.DashStyleValue,
123+
width: 2,
124+
label: {
125+
text: 'Target Level',
126+
align: 'left' as Highcharts.AlignValue,
127+
style: {
128+
color: 'var(--sys-primary)'
129+
}
130+
},
131+
zIndex: 2
132+
}]
133+
};
134+
this._chartOptions = {
135+
...this._chartOptions,
136+
yAxis
137+
};
138+
this.updateFlag = true;
139+
}
104140
}
105141

106142
}

frontend/src/app/services/api/targets.service.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,5 +77,10 @@ export class TargetsService {
7777
saveTargets(targets: Targets) {
7878
return this.http.post<Targets>(`${this.apiUrl}`, targets);
7979
}
80+
81+
recalculateTargets() {
82+
// Calls the backend endpoint to recalculate targets
83+
return this.http.get<any>(`${this.apiUrl}/calculate`);
84+
}
8085
}
8186

0 commit comments

Comments
 (0)