diff --git a/server/src/main/java/com/objectcomputing/checkins/services/employee_hours/EmployeeHours.java b/server/src/main/java/com/objectcomputing/checkins/services/employee_hours/EmployeeHours.java index 3118ae37e6..4303f4dc79 100644 --- a/server/src/main/java/com/objectcomputing/checkins/services/employee_hours/EmployeeHours.java +++ b/server/src/main/java/com/objectcomputing/checkins/services/employee_hours/EmployeeHours.java @@ -1,7 +1,9 @@ package com.objectcomputing.checkins.services.employee_hours; import com.objectcomputing.checkins.converter.LocalDateConverter; +import com.objectcomputing.checkins.util.Util; import io.micronaut.core.annotation.Introspected; +import io.micronaut.core.annotation.Nullable; import io.micronaut.data.annotation.AutoPopulated; import io.micronaut.data.annotation.TypeDef; import io.micronaut.data.model.DataType; @@ -74,7 +76,19 @@ public class EmployeeHours { @TypeDef(type = DataType.DATE, converter = LocalDateConverter.class) private LocalDate asOfDate; - public EmployeeHours(UUID id, @NotNull String employeeId, @NotNull Float contributionHours, Float billableHours, Float ptoHours, LocalDate updatedDate, Float targetHours, LocalDate asOfDate) { + @Column(name="billable_utilization") + @TypeDef(type = DataType.FLOAT) + @Schema(description ="Billable utilization hours") + @Nullable + private Float billableUtilization; + + @Column(name="overtime_worked") + @TypeDef(type = DataType.FLOAT) + @Schema(description ="Number of hours of overtime worked") + @Nullable + private Float overtimeWorked; + + public EmployeeHours(UUID id, @NotNull String employeeId, @NotNull Float contributionHours, Float billableHours, Float ptoHours, LocalDate updatedDate, Float targetHours, LocalDate asOfDate, @Nullable Float billableUtilization, @Nullable Float overtimeWorked) { this.id = id; this.employeeId = employeeId; this.contributionHours = contributionHours; @@ -83,10 +97,12 @@ public EmployeeHours(UUID id, @NotNull String employeeId, @NotNull Float contrib this.updatedDate = updatedDate; this.targetHours = targetHours; this.asOfDate = asOfDate; + this.billableUtilization = billableUtilization; + this.overtimeWorked = overtimeWorked; } - public EmployeeHours(@NotNull String employeeId, @NotNull Float contributionHours, @NotNull Float billableHours, @NotNull Float ptoHours, LocalDate updatedDate, @NotNull Float targetHours, LocalDate asOfDate) { - this(null, employeeId, contributionHours, billableHours, ptoHours, updatedDate, targetHours, asOfDate); + public EmployeeHours(@NotNull String employeeId, @NotNull Float contributionHours, @NotNull Float billableHours, @NotNull Float ptoHours, LocalDate updatedDate, @NotNull Float targetHours, LocalDate asOfDate, @Nullable Float billableUtilization, @Nullable Float overtimeWorked) { + this(null, employeeId, contributionHours, billableHours, ptoHours, updatedDate, targetHours, asOfDate, billableUtilization, overtimeWorked); } @Override @@ -101,12 +117,15 @@ public boolean equals(Object o) { employeeId.equals(that.employeeId) && updatedDate.equals(that.updatedDate) && Float.compare(that.targetHours, targetHours) == 0 && - asOfDate.equals(that.asOfDate) ; + asOfDate.equals(that.asOfDate) && + Util.floatCompareNullSafeAndEqualWhenBothNull(that.billableUtilization, this.billableUtilization) == 0 && + Util.floatCompareNullSafeAndEqualWhenBothNull(that.overtimeWorked, this.overtimeWorked) == 0 + ; } @Override public int hashCode() { - return Objects.hash(id, employeeId, contributionHours, billableHours, ptoHours, updatedDate,targetHours, asOfDate); + return Objects.hash(id, employeeId, contributionHours, billableHours, ptoHours, updatedDate,targetHours, asOfDate, billableUtilization, overtimeWorked); } @Override @@ -120,6 +139,8 @@ public String toString() { ", updatedDate=" + updatedDate + ", targetHours=" + targetHours + ", asOfDate=" + asOfDate + + ", billableUtilization=" + this.billableUtilization + + ", overtimeWorked=" + this.overtimeWorked + '}'; } } diff --git a/server/src/main/java/com/objectcomputing/checkins/services/employee_hours/EmployeeHoursCSVHelper.java b/server/src/main/java/com/objectcomputing/checkins/services/employee_hours/EmployeeHoursCSVHelper.java index 72e2560edb..c81d4daacb 100644 --- a/server/src/main/java/com/objectcomputing/checkins/services/employee_hours/EmployeeHoursCSVHelper.java +++ b/server/src/main/java/com/objectcomputing/checkins/services/employee_hours/EmployeeHoursCSVHelper.java @@ -31,11 +31,22 @@ public static List employeeHrsCsv(InputStream inputStream) throws .parse(input); DateTimeFormatter formatter = DateTimeFormatter.ofPattern("M/d/yyyy"); for (CSVRecord csvRecord : csvParser) { - EmployeeHours employeeHours = new EmployeeHours(csvRecord.get("employeeId"), - Float.parseFloat(csvRecord.get("contributionHours")), - Float.parseFloat(csvRecord.get("billableHours")), - Float.parseFloat(csvRecord.get("ptoHours")), LocalDate.now(), Float.parseFloat(csvRecord.get("targetHours")), - LocalDate.parse(csvRecord.get("asOfDate"), formatter)); + String billableUtilizationString = csvRecord.get("billableUtilization"); + Float billableUtilization = (billableUtilizationString == null) ? null : Float.parseFloat(billableUtilizationString); + String overtimeWorkedString = csvRecord.get("overtimeWorked"); + Float overtimeWorked = (overtimeWorkedString == null) ? null : Float.parseFloat(overtimeWorkedString); + EmployeeHours employeeHours = new EmployeeHours + ( + csvRecord.get("employeeId"), + Float.parseFloat(csvRecord.get("contributionHours")), + Float.parseFloat(csvRecord.get("billableHours")), + Float.parseFloat(csvRecord.get("ptoHours")), + LocalDate.now(), + Float.parseFloat(csvRecord.get("targetHours")), + LocalDate.parse(csvRecord.get("asOfDate"), formatter), + billableUtilization, + overtimeWorked + ); employeeHoursList.add(employeeHours); } return employeeHoursList; diff --git a/server/src/main/java/com/objectcomputing/checkins/util/Util.java b/server/src/main/java/com/objectcomputing/checkins/util/Util.java index 5cca167fc4..b8063dbe5d 100644 --- a/server/src/main/java/com/objectcomputing/checkins/util/Util.java +++ b/server/src/main/java/com/objectcomputing/checkins/util/Util.java @@ -31,4 +31,11 @@ public static List nullSafeUUIDListToStringList(List uuidList) { } return stringsList; } + + public static int floatCompareNullSafeAndEqualWhenBothNull(Float f1, Float f2) { + if (f1 == null && f2 == null) return 0; + if (f1 == null || f2 == null) return 1; + return Float.compare(f1, f2); + } + } diff --git a/server/src/main/resources/db/common/V112__add_employee_hours_two_new_fields.sql b/server/src/main/resources/db/common/V112__add_employee_hours_two_new_fields.sql new file mode 100644 index 0000000000..d36da40bb1 --- /dev/null +++ b/server/src/main/resources/db/common/V112__add_employee_hours_two_new_fields.sql @@ -0,0 +1,2 @@ +ALTER TABLE employee_hours ADD column billable_utilization decimal; +ALTER TABLE employee_hours ADD column overtime_worked decimal; diff --git a/server/src/test/java/com/objectcomputing/checkins/services/employee_hours/test.csv b/server/src/test/java/com/objectcomputing/checkins/services/employee_hours/test.csv index 7722b885eb..b0eb89e48c 100644 --- a/server/src/test/java/com/objectcomputing/checkins/services/employee_hours/test.csv +++ b/server/src/test/java/com/objectcomputing/checkins/services/employee_hours/test.csv @@ -1,3 +1,3 @@ -employeeId,contributionHours,billableHours,ptoHours,targetHours,asOfDate -mr-bill-employee,12,123,1234,1850,"8/20/2021" -mr-bill-employee-pdl,13,124,1235,0,"8/20/2021" +employeeId,contributionHours,billableHours,ptoHours,targetHours,asOfDate,billableUtilization,overtimeWorked +mr-bill-employee,12,123,1234,1850,"8/20/2021",0,50 +mr-bill-employee-pdl,13,124,1235,0,"8/20/2021",, diff --git a/web-ui/src/components/contribution_hours/ProgressBar.jsx b/web-ui/src/components/contribution_hours/ProgressBar.jsx index dc985c79ef..fbc1417453 100644 --- a/web-ui/src/components/contribution_hours/ProgressBar.jsx +++ b/web-ui/src/components/contribution_hours/ProgressBar.jsx @@ -31,17 +31,21 @@ const propTypes = { * The value of the progress indicator for the determinate and buffer variants. * Value between 0 and 100. */ - billableHours: PropTypes.number, - contributionHours: PropTypes.number.isRequired, - targetHours: PropTypes.number.isRequired, - ptoHours: PropTypes.number + billableHours: PropTypes.number, + contributionHours: PropTypes.number.isRequired, + targetHours: PropTypes.number.isRequired, + ptoHours: PropTypes.number, + billableUtilization: PropTypes.number, + overtimeWorked: PropTypes.number, }; const LinearBuffer = ({ - billableHours, - contributionHours = 925, - targetHours = 1850, - ptoHours = 0 + billableHours, + contributionHours = 925, + targetHours = 1850, + ptoHours = 0, + billableUtilization, + overtimeWorked, }) => { return ( @@ -63,8 +67,7 @@ const LinearBuffer = ({ style={{ display: 'block' }} > Billable Hours: {billableHours} - Contribution Hours:{' '} - {contributionHours} - Target Hours: {targetHours} - PTO Hours:{' '} - {ptoHours} + {contributionHours} - Target Hours: {targetHours} - PTO Hours:{' '} {ptoHours} - Billable Utilization:{' '} {(billableUtilization) ? billableUtilization : '(none)'} - Overtime Worked:{' '} {(overtimeWorked) ? overtimeWorked : '(none)'} ); diff --git a/web-ui/src/components/contribution_hours/ProgressBar.test.jsx b/web-ui/src/components/contribution_hours/ProgressBar.test.jsx index 1a670069e9..4efa37168e 100644 --- a/web-ui/src/components/contribution_hours/ProgressBar.test.jsx +++ b/web-ui/src/components/contribution_hours/ProgressBar.test.jsx @@ -3,9 +3,9 @@ import ProgressBar from './ProgressBar'; import renderer from 'react-test-renderer'; it('has billable hours', () => { - snapshot(); + snapshot(); }); it('has no billable hours', () => { - snapshot(); + snapshot(); }); diff --git a/web-ui/src/components/contribution_hours/__snapshots__/ProgressBar.test.jsx.snap b/web-ui/src/components/contribution_hours/__snapshots__/ProgressBar.test.jsx.snap index 43541785a8..f9b1f0e150 100644 --- a/web-ui/src/components/contribution_hours/__snapshots__/ProgressBar.test.jsx.snap +++ b/web-ui/src/components/contribution_hours/__snapshots__/ProgressBar.test.jsx.snap @@ -37,7 +37,16 @@ exports[`has billable hours 1`] = ` 1850 - PTO Hours: + 0 + - Billable Utilization: + + + (none) + - Overtime Worked: + + + (none)

@@ -80,7 +89,16 @@ exports[`has no billable hours 1`] = ` 1850 - PTO Hours: + 0 + - Billable Utilization: + + + (none) + - Overtime Worked: + + + (none)