তবে জেনে রাখা ভালো প্রত্যেকটি লগইন ইউসার একটি নির্দিষ্ট কোম্পানির সাথে যুক্ত এখন আমাদের নিচের মতো মডেল আছে
Employee
প্রতিটা এমপ্লয়ী একটি কোম্পানির সাথে সংযুক্ত যখন একজন লগইন ব্যবহারকারী Employee রেজিস্টার করবে তখন ওই ব্যবহারকারীর কোম্পানি ওই এমপ্লয়ী তে সেভ হবে যেমন যদি একজন গারমের্ন্টস x এর hr একটি শ্রমিক বা এমপ্লয়ী এর তথ্য সিস্টেম এ ঢুকাবে তখন স্বয়ংক্রিয় ভাবে গারমের্ন্টস x এর hr এর কোম্পানি গারমের্ন্টস x employee তে যুক্ত হয়ে যাবে।
class Employee(models.Model):
company = models.ForeignKey(
Company,
on_delete=models.CASCADE,
related_name='company_employees',
verbose_name=_("Company"),
null=True, blank=True,
)
employee_id = models.CharField(
max_length=20,
verbose_name=_("Employee ID"),
)
department = models.CharField(max_length=50, null=True, blank=True, verbose_name=_("Department name"))
position = models.CharField(max_length=50, null=True, blank=True, verbose_name=_("Position title"))
contact_number = models.CharField(max_length=15, null=True, blank=True, verbose_name=_("Contact number"))
date_of_joining = models.DateField(null=True, blank=True, verbose_name=_("Date of joining"))
মেশিন এ প্রথমে user রেজিস্টার এর পর ওই একই employee_id দিয়ে Employee রেজিস্টার করতে হবে এরপর অ্যাটেনডেন্স রেকর্ড এ মেশিনের ডেটা ঢুকাতে হবে
class AttendanceLog(models.Model):
"""
ব্যবহারকারীর চেক ইন এবং চেক আউট তথ্য সংরক্ষণ করার জন্য উপস্থিতি লগ মডেল।
"""
employee = models.ForeignKey(
Employee,
on_delete=models.CASCADE,
related_name='attendance_logs',
verbose_name=_("Employee")
)
company = models.ForeignKey(Company, on_delete=models.CASCADE, related_name='attendance_logs',null=True)
device = models.ForeignKey(Device, on_delete=models.CASCADE, null=True, blank=True)
punch_datetime = models.DateTimeField(default=timezone.now, verbose_name=_("Date & Time of Punch"))
STATUS_CHOICES = [
('IN', 'Check-In'),
('OUT', 'Check-Out'),
('BREAK_IN', 'Break-In'),
('BREAK_OUT', 'Break-Out'),
]
in_out_status = models.CharField(max_length=20, choices=STATUS_CHOICES, default='IN', verbose_name=_("In/Out Status"))
VERIFICATION_CHOICES = [
('FP', 'Fingerprint'),
('FACE', 'Face'),
('CARD', 'Card'),
('PWD', 'Password'),
('GPS', 'GPS'),
('MANUAL', 'Manual'),
]
verification_method = models.CharField(
max_length=10,
choices=VERIFICATION_CHOICES,
default='FP',
verbose_name=_("Verification Method")
)
punch_mode = models.CharField(
max_length=10,
choices=[('AUTO', 'Auto'), ('MANUAL', 'Manual')],
default='AUTO',
verbose_name=_("Punch Mode")
)
work_code = models.CharField(
max_length=20,
null=True,
blank=True,
verbose_name=_("Work Code")
)
locationName = models.CharField(max_length=255, null=True, blank=True)
latitude = models.FloatField(null=True, blank=True)
longitude = models.FloatField(null=True, blank=True)
createdAt = models.DateTimeField(auto_now_add=True)
updatedAt = models.DateTimeField(auto_now=True)এর পর আমরা আমাদের বাকি মডেল গুলো দেখি
শিফট,Schedule, WorkHours মডেল
class Shift(models.Model):
STATUS_CHOICES = [
('ACTIVE', 'Active'),
('INACTIVE', 'Inactive'),
]
name = models.CharField(max_length=50) # Name of the shift
start_time = models.TimeField() # Shift start time
end_time = models.TimeField() # Shift end time
break_duration = models.DurationField(null=True, blank=True) # Optional break duration
company = models.ForeignKey(Company, on_delete=models.CASCADE, related_name='shifts',null=True)
status = models.CharField(max_length=10, choices=STATUS_CHOICES, default='ACTIVE') # Shift status
class Workday(models.Model):
day = models.CharField(max_length=10, choices=[
('MON', 'Monday'),
('TUE', 'Tuesday'),
('WED', 'Wednesday'),
('THU', 'Thursday'),
('FRI', 'Friday'),
('SAT', 'Saturday'),
('SUN', 'Sunday'),
])
def __str__(self):
return self.day
class Schedule(models.Model):
employee = models.ForeignKey(Employee, on_delete=models.CASCADE) # Employee linked to the schedule
shift = models.ForeignKey(Shift, on_delete=models.CASCADE) # The shift they are assigned to
workdays = models.ManyToManyField(Workday) # Allow multiple workdays
def __str__(self):
return f"{self.employee.user.username} - {self.shift.name} - {', '.join([day.day for day in self.workdays.all()])}"
class WorkHours(models.Model):
employee = models.ForeignKey(Employee, on_delete=models.CASCADE) # Employee linked to the work hours
company = models.ForeignKey(Company, on_delete=models.CASCADE,null=True, blank=True) # Linking work hours with company
date = models.DateField() # Date for which hours are calculated
total_hours = models.DurationField() # Total worked hours
overtime_hours = models.DurationField(null=True, blank=True) # Optional overtime hours
def __str__(self):
return f"{self.employee.user.username} - {self.date} - {self.total_hours}"
এখানে মূলত একজন অ্যাডমিনের মাধ্যমে কিভাবে Shift, Schedule, এবং WorkHours কাজ করে তা ধাপে ধাপে বুঝিয়ে দেওয়া হবে।
গল্পের শুরু
১. কোম্পানির অ্যাডমিন রাফি শিফট এবং কর্মী যোগ করে
রাফি তার কোম্পানির অ্যাডমিন। কোম্পানির কিছু কর্মী রয়েছে যাদের তিনি শিফটে কাজ করতে চান। রাফি প্রথমে কর্মীদের জন্য শিফট তৈরি করবেন এবং সেই শিফটে কর্মী যোগ করবেন। এরপর তিনি প্রতিটি কর্মীর কাজের সময় (Work Hours) মাপবেন।
Step 1: নতুন Shift তৈরি করা
প্রথমেই রাফি তার কোম্পানির জন্য বিভিন্ন Shift তৈরি করেন। যেমন, সকাল শিফট এবং বিকাল শিফট। ধরো সকাল শিফট শুরু হবে সকাল ৮টায় এবং শেষ হবে দুপুর ২টায়। এর জন্য রাফি নতুন একটি শিফট তৈরি করেন।
shift_morning = Shift.objects.create(
name="Morning Shift",
start_time="08:00:00",
end_time="14:00:00",
company=Company.objects.get(id=1) # রাফির কোম্পানির আইডি
)
Step 2: কর্মী যোগ করা
রাফি নতুন একজন কর্মী ‘তাহমিদ’ যোগ করলেন তার কোম্পানিতে। Employee মডেলের মাধ্যমে সেই কর্মী যোগ করা হলো।
employee_tahmid = Employee.objects.create(
company=Company.objects.get(id=1), # রাফির কোম্পানি
employee_id="EMP123",
department="IT",
position="Developer",
contact_number="017XXXXXXXX",
date_of_joining="2023-10-01"
)
২. রাফি তাহমিদকে একটি শিফটে যুক্ত করেন
কর্মী যুক্ত করার পর, রাফি এখন তাহমিদকে একটি শিফটে যুক্ত করতে চাইছেন। ধরো, তাহমিদকে সকাল শিফটে কাজ করার জন্য নির্ধারণ করা হলো। রাফি একটি Schedule তৈরি করে তাহমিদকে সেই শিফটে যুক্ত করেন।
schedule = Schedule.objects.create(
employee=employee_tahmid, # তাহমিদ কর্মী
shift=shift_morning, # সকাল শিফট
)
৩. তাহমিদের চেক-ইন এবং চেক-আউট লগ করা
এখন তাহমিদ যখন অফিসে আসবেন, তখন তার চেক-ইন (Check-In) ও চেক-আউট (Check-Out) লগ হবে। প্রতিবার তার উপস্থিতি লগ করার জন্য রাফি AttendanceLog ব্যবহার করবেন। ধরো তাহমিদ সকালে ৮:১০ এ চেক-ইন করলেন, এবং তার অবস্থানও লোগ করা হলো:
Step 3: তাহমিদের চেক-ইন লগ করা
AttendanceLog.objects.create(
employee=employee_tahmid,
company=employee_tahmid.company,
device=Device.objects.get(id=1), # ধরো একটা ডিভাইস
punch_datetime="2023-10-14 08:10:00",
in_out_status="IN", # চেক-ইন
verification_method="FP", # ফিঙ্গারপ্রিন্ট
punch_mode="AUTO", # অটো মোড
locationName="Office Main Gate",
latitude=23.780777,
longitude=90.419312
)
Step 4: তাহমিদের চেক-আউট লগ করা
ধরো তাহমিদ দুপুর ২টায় অফিস থেকে বের হলেন। এবার চেক-আউট লগ হবে।
AttendanceLog.objects.create(
employee=employee_tahmid,
company=employee_tahmid.company,
device=Device.objects.get(id=1),
punch_datetime="2023-10-14 14:00:00",
in_out_status="OUT", # চেক-আউট
verification_method="FP",
punch_mode="AUTO",
locationName="Office Main Gate",
latitude=23.780777,
longitude=90.419312
)
৪. ওয়ার্ক আওয়ার্স গণনা করা
এখন রাফি হিসাব করবেন তাহমিদ কতক্ষণ কাজ করেছেন। তাহমিদ সকালে ৮:১০ এ চেক-ইন করেছিলেন এবং দুপুর ২টায় চেক-আউট করেছিলেন। তাহলে তাহমিদ মোট কত ঘণ্টা কাজ করেছেন?
Step 5: ওয়ার্ক আওয়ার্স যোগ করা
রাফি WorkHours মডেল ব্যবহার করে তাহমিদের কাজের সময় (Total Work Hours) গণনা করলেন।
from datetime import timedelta
work_hours = timedelta(hours=5, minutes=50) # তাহমিদ ৫ ঘণ্টা ৫০ মিনিট কাজ করেছেন
overtime = timedelta(hours=0) # কোনো ওভারটাইম নেই
WorkHours.objects.create(
employee=employee_tahmid,
company=employee_tahmid.company,
date="2023-10-14", # কাজের তারিখ
total_hours=work_hours,
overtime_hours=overtime # ওভারটাইম নেই
)
এভাবে রাফি তার কোম্পানিতে শিফট তৈরি করে কর্মী যুক্ত করেন এবং তাদের উপস্থিতি ও কাজের সময় নিবন্ধন করেন। তিনি প্রতিদিনের AttendanceLog এবং WorkHours দেখে সহজেই কর্মীদের কাজের সময় এবং উপস্থিতি যাচাই করতে পারেন।
এই উদাহরণ থেকে রাফি শিখে গেলেন কিভাবে তার কোম্পানিতে কর্মীদের শিফট যুক্ত করা, চেক-ইন/চেক-আউট লগ করা, এবং মোট কাজের সময় গণনা করা যায়।