feat: add employee timing system, notification templates, and professor class plan sms
This commit is contained in:
@@ -0,0 +1,120 @@
|
||||
// /components/employeeTimings/employeeTimingModel.js
|
||||
'use strict';
|
||||
|
||||
const mongoose = require('mongoose');
|
||||
|
||||
const employeeTimingSchema = new mongoose.Schema({
|
||||
user: {
|
||||
type: mongoose.Schema.Types.ObjectId,
|
||||
ref: 'User',
|
||||
required: true,
|
||||
index: true
|
||||
},
|
||||
date: {
|
||||
type: Date,
|
||||
required: true,
|
||||
default: Date.now,
|
||||
index: true
|
||||
},
|
||||
entryTime: {
|
||||
type: String,
|
||||
trim: true,
|
||||
default: ''
|
||||
},
|
||||
exitTime: {
|
||||
type: String,
|
||||
trim: true,
|
||||
default: ''
|
||||
},
|
||||
note: {
|
||||
type: String,
|
||||
trim: true,
|
||||
default: ''
|
||||
},
|
||||
createdBy: {
|
||||
type: mongoose.Schema.Types.ObjectId,
|
||||
ref: 'User'
|
||||
},
|
||||
updatedBy: {
|
||||
type: mongoose.Schema.Types.ObjectId,
|
||||
ref: 'User'
|
||||
}
|
||||
}, {
|
||||
timestamps: true,
|
||||
toJSON: { virtuals: true },
|
||||
toObject: { virtuals: true }
|
||||
});
|
||||
|
||||
/**
|
||||
* Status virtual property:
|
||||
* - 'complete': both entryTime and exitTime are provided
|
||||
* - 'missing_exit': entryTime provided, but exitTime missing (Warning)
|
||||
* - 'missing_entry': exitTime provided, but entryTime missing (Warning)
|
||||
* - 'incomplete': both entryTime and exitTime are missing (Warning)
|
||||
*/
|
||||
employeeTimingSchema.virtual('status').get(function () {
|
||||
const hasEntry = Boolean(this.entryTime && String(this.entryTime).trim());
|
||||
const hasExit = Boolean(this.exitTime && String(this.exitTime).trim());
|
||||
|
||||
if (hasEntry && hasExit) return 'complete';
|
||||
if (hasEntry && !hasExit) return 'missing_exit';
|
||||
if (!hasEntry && hasExit) return 'missing_entry';
|
||||
return 'incomplete';
|
||||
});
|
||||
|
||||
/**
|
||||
* Warning flag virtual property:
|
||||
* True if record is incomplete (missing entry, missing exit, or both)
|
||||
*/
|
||||
employeeTimingSchema.virtual('hasWarning').get(function () {
|
||||
const hasEntry = Boolean(this.entryTime && String(this.entryTime).trim());
|
||||
const hasExit = Boolean(this.exitTime && String(this.exitTime).trim());
|
||||
return !(hasEntry && hasExit);
|
||||
});
|
||||
|
||||
/**
|
||||
* Warning message helper
|
||||
*/
|
||||
employeeTimingSchema.virtual('warningMessage').get(function () {
|
||||
const hasEntry = Boolean(this.entryTime && String(this.entryTime).trim());
|
||||
const hasExit = Boolean(this.exitTime && String(this.exitTime).trim());
|
||||
|
||||
if (hasEntry && !hasExit) return 'ورود ثبت شده ولی خروج ثبت نشده است';
|
||||
if (!hasEntry && hasExit) return 'خروج ثبت شده ولی ورود ثبت نشده است';
|
||||
if (!hasEntry && !hasExit) return 'زمان ورود و خروج هیچکدام ثبت نشده است';
|
||||
return null;
|
||||
});
|
||||
|
||||
/**
|
||||
* Duration in minutes calculation (if both entry and exit times are valid HH:mm)
|
||||
*/
|
||||
employeeTimingSchema.virtual('durationMinutes').get(function () {
|
||||
if (!this.entryTime || !this.exitTime) return null;
|
||||
const [inH, inM] = String(this.entryTime).split(':').map(Number);
|
||||
const [outH, outM] = String(this.exitTime).split(':').map(Number);
|
||||
if (Number.isNaN(inH) || Number.isNaN(inM) || Number.isNaN(outH) || Number.isNaN(outM)) {
|
||||
return null;
|
||||
}
|
||||
const startMinutes = inH * 60 + inM;
|
||||
let endMinutes = outH * 60 + outM;
|
||||
if (endMinutes < startMinutes) {
|
||||
// Crosses midnight
|
||||
endMinutes += 24 * 60;
|
||||
}
|
||||
return endMinutes - startMinutes;
|
||||
});
|
||||
|
||||
/**
|
||||
* Formatted duration in Persian/hours
|
||||
*/
|
||||
employeeTimingSchema.virtual('durationFormatted').get(function () {
|
||||
const minutes = this.durationMinutes;
|
||||
if (minutes === null || minutes === undefined) return '—';
|
||||
const h = Math.floor(minutes / 60);
|
||||
const m = minutes % 60;
|
||||
if (h === 0) return `${m} دقیقه`;
|
||||
if (m === 0) return `${h} ساعت`;
|
||||
return `${h} ساعت و ${m} دقیقه`;
|
||||
});
|
||||
|
||||
module.exports = mongoose.model('EmployeeTiming', employeeTimingSchema);
|
||||
Reference in New Issue
Block a user