Employee attendance management system in Node & MongoDB
Tags: node, mongodb, backend, javascript
Published: 2023-08-31 07:25:00

Create a Mongoose schema for the clockInClockOut with the specified fields:

```
const mongoose = require('mongoose');

const clockInClockOutSchema = new mongoose.Schema({
  entryDate: {
    type: Date,
    required: true,
  },
  employeeId: {
    type: mongoose.Schema.Types.ObjectId, // You can change this to the appropriate type based on your employee ID structure
    required: true,
  },
  clockTimes: [
    {
      clockedInTime: {
        type: Date,
        required: true,
      },
      clockedOutTime: {
        type: Date,
        required: true,
      },
    },
  ],
});

const ClockInClockOut = mongoose.model('ClockInClockOut', clockInClockOutSchema);

module.exports = ClockInClockOut;

```
Create an clock-In API:

```
// Define the API route to add clock in times
app.post('/api/clock-in', async (req, res) => {
  try {
    const { employeeId, entryDate, clockedInTime } = req.body;

    // Create a new clock in record
    const clockInRecord = new ClockInClockOut({
      employeeId,
      entryDate,
      clockTimes: [{ clockedInTime }],
    });

    // Save the record to MongoDB
    await clockInRecord.save();

    res.status(201).json(clockInRecord);
  } catch (error) {
    console.error(error);
    res.status(500).json({ error: 'Internal server error' });
  }
});
```
Create an clock-Out API:

```
// Define the API route to add clock out times
app.post('/api/clock-out', async (req, res) => {
  try {
    const { employeeId, entryDate, clockedOutTime } = req.body;

    // Find the clock in record for the specified employee and entryDate
    const clockInRecord = await ClockInClockOut.findOne({
      employeeId,
      entryDate,
    });

    if (!clockInRecord) {
      return res.status(404).json({ error: 'Clock in record not found' });
    }

    // Update the latest clock in entry with clockedOutTime
    const latestClockInEntry = clockInRecord.clockTimes[clockInRecord.clockTimes.length - 1];
    latestClockInEntry.clockedOutTime = clockedOutTime;

    // Save the updated record to MongoDB
    await clockInRecord.save();

    res.json(clockInRecord);
  } catch (error) {
    console.error(error);
    res.status(500).json({ error: 'Internal server error' });
  }
});

```
Create an API that retrieves all records for a specific employee based on their employeeId:

```
// Define the API route to get all records by employeeId
app.get('/api/records/:employeeId', async (req, res) => {
  try {
    const employeeId = req.params.employeeId;

    // Find all records for the specified employeeId
    const records = await ClockInClockOut.find({ employeeId });

    if (!records || records.length === 0) {
      return res.status(404).json({ error: 'No records found for the employee' });
    }

    // Calculate workedMinutes for each record
    const recordsWithWorkedMinutes = records.map(record => {
      let totalWorkedMinutes = 0;

      // Iterate through the clockTimes array and calculate workedMinutes
      record.clockTimes.forEach(entry => {
        const clockedInTime = new Date(entry.clockedInTime);
        const clockedOutTime = new Date(entry.clockedOutTime);

        // Calculate the time difference in milliseconds
        const timeDifferenceMs = clockedOutTime - clockedInTime;

        // Convert milliseconds to minutes
        const workedMinutes = Math.floor(timeDifferenceMs / (1000 * 60));

        totalWorkedMinutes += workedMinutes;
      });

      // Add workedMinutes to the record
      return { ...record._doc, workedMinutes: totalWorkedMinutes };
    });

    res.json(recordsWithWorkedMinutes);
  } catch (error) {
    console.error(error);
    res.status(500).json({ error: 'Internal server error' });
  }
});

```
API endpoint :GET /api/records/{employeeId}.
Response
```
[
  {
    "_id": "5f83a5cf0f0e1218f0c9f187",
    "entryDate": "2023-09-04T12:30:00.000Z",
    "employeeId": "123456789",
    "clockTimes": [
      {
        "clockedInTime": "2023-09-04T08:00:00.000Z",
        "clockedOutTime": "2023-09-04T12:00:00.000Z"
      },
      {
        "clockedInTime": "2023-09-04T13:00:00.000Z",
        "clockedOutTime": "2023-09-04T17:00:00.000Z"
      }
    ],
    "workedMinutes": 480 // Total worked minutes for this record (8 hours)
  },
  // More records for the same employeeId...
]

```
Create an API that retrieves the total worked minutes for an employee within a specified day range:

```
// Define the API route to get employee-wise total worked minutes
app.get('/api/total-worked-minutes/:employeeId', async (req, res) => {
  try {
    const employeeId = req.params.employeeId;
    const { range, fromDate, toDate } = req.query;
    let filter = { employeeId };

    // Define a filter based on the requested range or custom date range
    if (range === 'today') {
      const currentDate = new Date();
      const startDate = new Date(currentDate);
      startDate.setHours(0, 0, 0, 0);
      filter = {
        ...filter,
        entryDate: { $gte: startDate, $lte: currentDate },
      };
    } else if (range === 'yesterday') {
      const currentDate = new Date();
      const startDate = new Date(currentDate);
      startDate.setDate(startDate.getDate() - 1);
      startDate.setHours(0, 0, 0, 0);
      const endDate = new Date(startDate);
      endDate.setHours(23, 59, 59, 999);
      filter = {
        ...filter,
        entryDate: { $gte: startDate, $lte: endDate },
      };
    } else if (range === 'last7days') {
      const currentDate = new Date();
      const startDate = new Date(currentDate);
      startDate.setDate(startDate.getDate() - 6);
      startDate.setHours(0, 0, 0, 0);
      filter = {
        ...filter,
        entryDate: { $gte: startDate, $lte: currentDate },
      };
    } else if (range === 'last15days') {
      const currentDate = new Date();
      const startDate = new Date(currentDate);
      startDate.setDate(startDate.getDate() - 14);
      startDate.setHours(0, 0, 0, 0);
      filter = {
        ...filter,
        entryDate: { $gte: startDate, $lte: currentDate },
      };
    } else if (range === 'last30days') {
      const currentDate = new Date();
      const startDate = new Date(currentDate);
      startDate.setDate(startDate.getDate() - 29);
      startDate.setHours(0, 0, 0, 0);
      filter = {
        ...filter,
        entryDate: { $gte: startDate, $lte: currentDate },
      };
    } else if (fromDate && toDate) {
      filter = {
        ...filter,
        entryDate: { $gte: new Date(fromDate), $lte: new Date(toDate) },
      };
    } else {
      return res.status(400).json({ error: 'Invalid range or missing parameters' });
    }

    // Find all records that match the filter
    const records = await ClockInClockOut.find(filter);

    if (!records || records.length === 0) {
      return res.status(404).json({ error: 'No records found for the employee' });
    }

    // Calculate total worked minutes for all records
    let totalWorkedMinutes = 0;
    records.forEach(record => {
      record.clockTimes.forEach(entry => {
        const clockedInTime = new Date(entry.clockedInTime);
        const clockedOutTime = new Date(entry.clockedOutTime);
        const timeDifferenceMs = clockedOutTime - clockedInTime;
        totalWorkedMinutes += Math.floor(timeDifferenceMs / (1000 * 60));
      });
    });

    res.json({ totalWorkedMinutes });
  } catch (error) {
    console.error(error);
    res.status(500).json({ error: 'Internal server error' });
  }
});

```

```
GET /api/total-worked-minutes/{employeeId}?range=today
Response:
{
  "totalWorkedMinutes": 360 
}
GET /api/total-worked-minutes/{employeeId}?range=last7days
Response:
{
  "totalWorkedMinutes": 1440 
}

```
API to retrieve total worked minutes individually for all employees within the requested date range:

```
// Define the API route to get total worked minutes for all employees within a specified day range
app.get('/api/total-worked-minutes', async (req, res) => {
  try {
    const { range } = req.query;
    let filter = {};

    // Define a filter based on the requested day range
    if (range === 'today') {
      const currentDate = new Date();
      const startDate = new Date(currentDate);
      startDate.setHours(0, 0, 0, 0);
      filter = {
        entryDate: { $gte: startDate, $lte: currentDate },
      };
    } else if (range === 'yesterday') {
      const currentDate = new Date();
      const startDate = new Date(currentDate);
      startDate.setDate(startDate.getDate() - 1);
      startDate.setHours(0, 0, 0, 0);
      const endDate = new Date(startDate);
      endDate.setHours(23, 59, 59, 999);
      filter = {
        entryDate: { $gte: startDate, $lte: endDate },
      };
    } else if (range === 'last7days') {
      const currentDate = new Date();
      const startDate = new Date(currentDate);
      startDate.setDate(startDate.getDate() - 6);
      startDate.setHours(0, 0, 0, 0);
      filter = {
        entryDate: { $gte: startDate, $lte: currentDate },
      };
    } else if (range === 'last15days') {
      const currentDate = new Date();
      const startDate = new Date(currentDate);
      startDate.setDate(startDate.getDate() - 14);
      startDate.setHours(0, 0, 0, 0);
      filter = {
        entryDate: { $gte: startDate, $lte: currentDate },
      };
    } else if (range === 'last30days') {
      const currentDate = new Date();
      const startDate = new Date(currentDate);
      startDate.setDate(startDate.getDate() - 29);
      startDate.setHours(0, 0, 0, 0);
      filter = {
        entryDate: { $gte: startDate, $lte: currentDate },
      };
    } else {
      return res.status(400).json({ error: 'Invalid range' });
    }

    // Find all records that match the filter
    const records = await ClockInClockOut.find(filter);

    if (!records || records.length === 0) {
      return res.status(404).json({ error: 'No records found within the specified range' });
    }

    const employeeWorkedMinutes = {};

    // Calculate total worked minutes for each employee
    records.forEach(record => {
      const employeeId = record.employeeId;
      let totalWorkedMinutes = 0;

      record.clockTimes.forEach(entry => {
        const clockedInTime = new Date(entry.clockedInTime);
        const clockedOutTime = new Date(entry.clockedOutTime);
        const timeDifferenceMs = clockedOutTime - clockedInTime;
        totalWorkedMinutes += Math.floor(timeDifferenceMs / (1000 * 60));
      });

      if (!employeeWorkedMinutes[employeeId]) {
        employeeWorkedMinutes[employeeId] = totalWorkedMinutes;
      } else {
        employeeWorkedMinutes[employeeId] += totalWorkedMinutes;
      }
    });

    res.json(employeeWorkedMinutes);
  } catch (error) {
    console.error(error);
    res.status(500).json({ error: 'Internal server error' });
  }
});

```

```
GET /api/total-worked-minutes?range=today
{
  "employeeId1": 240, 
  "employeeId2": 360, 
  // More employees...
}

GET /api/total-worked-minutes?range=last7days
{
  "employeeId1": 1200,
  "employeeId2": 900, 
  // More employees...
}
GET /api/total-worked-minutes?range=yesterday
{
  "employeeId1": 180,
  "employeeId2": 240
  // More employees...
}

```