I am designing a solution to store employee day attendance, which can be recorded either as hours or as an interval within a day. The goal is to maintain a monthly attendance list for each employee. Depending on hours or interval values, timeSheet view will be generated containing either intervals or hours (each employee can have either hours or intervals provided to their attendance)
To implement this, I have created an Attendance domain class (which will have same structure in sql table) that represents a specific attendance record, which can be categorized as work, holiday, or sick leave. The class has the following properties:
public class Attendance : IAggregateRoot
{
public Attendance(
DateTime day,
TimeInterval? interval, // value object containing timespan of startsAt and endAt
double? hours,
AttendanceType type)
{
day = day.Date;
if (hours is null && interval is null) throw new Exception("At least one parameter must be provided.");
Id = Guid.NewGuid();
Type = type;
if (interval != null)
{
if (interval.StartsAt.Hours >= 24 || interval.EndsAt.Hours >= 24) throw new BadRequestException(Errors.Attendances.IntervalOverflow);
StartsA = day.AddHours(interval.StartsAt.Hours);
EndsAt = day.AddHours(interval.EndsAt.Hours);
Range = new DateRange(startDate, endDate);
Hours = interval.TotalHours();
}
else
{
Range = new DateRange(day, day.AddHours(24));
Hours = hours!.Value;
}
}
public Guid Id { get; private set; }
public DateTime Day => Range.StartsAt.Date;
public DateTime StartsAt { get; protected set; }
public DateTime EndsAt { get; protected set; }
public double Hours { get; private set; }
public AttendanceType Type { get; private set; }
public Guid EmployeeId { get; private set; }
}
}
If an interval is provided, I validate that the start and end times are within the valid range of 0-23 hours. Then, I set the StartsAt and EndsAt properties accordingly and calculate the total hours.
For cases where only hours are provided, I assume the attendance occurred within a single day, and I create a date range from the given day parameter to the next day, spanning 24 hours.
Pros:
- It is quite simple to search for attendances on a specific day.
- It is flexible and easy to maintain.
Cons:
- It creates many records. For each employee, it will contain about 40 records each month. However, SQL can easily handle this.
- It can be unclear when there is an interval. It has "startsAt" and "endsAt" specific fields, but when hours are inputted, it creates an interval for the full day, which can be unclear. Perhaps it would be better to store an additional field called "Date" that specifies which exact day the attendance belongs to.
- There can be multiple attendances per day with hours which will contain same startsAt and endsAt fields and will make overlap that (but it's not a problem as only hours will be shown)
I would like to get feedback on whether this implementation is valid and if there are any improvements or suggestions to make it more robust. I am afraid that I making something wrong having hours or interval together in attendance.
DateTime
instead ofDateTimeOffset
? Which .NET and C# versions are you using? \$\endgroup\$