To create attendance you need 3 Collections.
Collection 1 : Shift
Shift Document will have Schema like below
        const MYDBSchema = new mongoose.Schema({
        name: { type: String, default: 'Default' },
        weekend: { type: Array, default: [] },
        time: {type: Array, default: [] },
        lateIn: { type: Number, default: 0 },
        earlyOut: { type: Number, default: 0},
        halfDayHour: { type: Number }, // Half Day
        fullDayHour: { type: Number } // Full Day
        offset: { type: Number } // Timezone offset
        assignedEmployee: { type: Array, default: [] }
    });
As described above schema LateIn, Early Out will have number in format of Minute
Collection 2 : DailyReport
Daily Report Document will have Schema like below
     const MYDBSchema = new mongoose.Schema({
        user: { type: mongoose.Types.ObjectId}, // Reference of User
        shift: { type: mongoose.Types.ObjectId}, // Reference of User
        date: { type: Date }, // Start Of The Day Date . Example your offset -330 then store it as "2021-11-26T18:30:00.000Z"
        lateIn: { type: Number, default: 0 }, //  Will have total LAte In Seconds
        earlyOut: { type: Number, default: 0}, // Will have total Early Out Seconds
        overTime: { type: Number } // Will have Overtime
        breakTime: { type: Number } // Will have total Break Time
        initialInTime: { type: Date }, // Will have First Clock In
        finalOutTime: { type: Date } // Will have Final Clock Out
        totalWorkHour: { type: Number } // Will have Total Working Hour Seconds
        dayStatus: { type: Number } // Will define that day is Holiday or Weekend or Working Day
        timeStatus: { type:  Number } // Will have initial (absent), work (working), break (on break), end (Clocked Out),
});
Collection 3 : TimeSheets
Timesheet Document will look like this
 const MYDBSchema = new mongoose.Schema({
        user: { type: mongoose.Types.ObjectId}, // Reference of User
        dailyReport: { type: mongoose.Types.ObjectId}, // Reference of Daily Report
        date: { type: Date }, // Start Of The Day Date . Example your offset -330 then store it as "2021-11-26T18:30:00.000Z"
        inTime: { type: Date }, // Will have Clock In / Break In
        outTime: { type: Date } // Will have Clock Out / Break Out
        duration: { type: Number } // Will have Duration in Seconds difference between inTime and outTime
        type: { type: Number } // Break or Work
});
-> How shift will work
Everyday Run CRON either create Function that will create entry for everyday of each user by set timeStatus as initial
-> How Daily Report Will work
When ever user sends request for clock in. First need to grab Shift and then get timezone offset from the shift convert that date and fetch daily Report.
-> Create function like this
getShiftTiming({ shiftObject, date }) -> will return Object that contain { willStartAt: Date, endAt: Date }
getCurrentTiming({ date }) -> Will fetch Daily Report to send it to client
addIn ({ date, type }) -> Will fetch DailyReport and then create entry in TimeSheets collection as inTime and then change timeStatus to WORK / BREAK based on param type
addOut ({ date }) -> Will Fetch Daily Report and then fetch last TimeSheet and then set outTime
calculateDailyReport({ shiftDetail, dailyReportDetail }) -> Will calculate report based on TimeSheet Collection. It will fetch all records based on Daily Report and sum up duration and update dailyReport's totalWorkingHour, break and then take first timesheet's inTime and last timesheet's outTime and then set dailyReport's initialInTime = inTime and finalOutTime = outTime. Another function within this function will get called and it will ( lateIn -> getShiftTiming call this function and then get difference between initialInTime and willStart at it will be Late In seconds, overTime -> Substract breakTime from totalTime and then check it with shiftDetail's fullDayWorkingHour you will get overTime Seconds same way reverse logic you can get earlyOutTime )
At this way you can manage Shift. I also successfully managed Shift at ubsapp.com which is heavily dynamic than this example. It has extra feature that will allow user to update and add slots and request ( GEO Location and IP Access based Clock In And Clock Out lot other. )