๐งช TEST MODE IS ON โ location check is disabled. Turn off in Admin โ Setup when done testing.
Logged in as โ
My Attendance
๐ Private โ protected by real sign-in, not just an in-app screen. Only you can see this.
โ
Present
โ
Absent
โ
Est. Payout
Leave: 0
Late: 0
Advance due: โน0
Full DayHalf DayAbsentLeaveHolidayWeekly Off
Tap a Present/Half/Absent day to report an issue with that date.
Apply for Leave
Paid leave is earned automatically โ +1 day for every full month with zero unplanned absences.
No dates selected yet.
Request Attendance Correction
Think a date is marked wrong? Tell us the correct times and admin will review it.
๐
Sign In
First time here? Whatever PIN you enter becomes the admin PIN from now on.
Logged in as โ
Today โ
Loadingโฆ
Current Status
Who's punched in right now, live.
Note: "Current Status" always shows right-now activity, regardless of the date filter above.
Needs Attention
Payroll Snapshot
Estimated net payable across all employees' current pay cycles, and total advance money still owed back by employees. Updates live โ not yet finalized payslips.
Loadingโฆ
Leave Balance
Paid = earned automatically (1 day per clean month). Sick/Casual = annual entitlement from Setup.
Change My PIN
Firebase Connection
Connectingโฆ
Fix empty login dropdown
If the employee picker on the login screen is empty, it's because your existing employees were created before the public directory existed. Click once to fix it (safe to click again anytime).
๐ง Repair Missing Employee Records
If an employee can log in but their attendance/dashboard says "employee record not found", their record in attendance_employees was lost while their login (and the directory entry) still exists. Scan finds these and lets you restore the exact record โ using the same ID โ so their existing login keeps working with no PIN reset needed.
Restore Record
Employee ID: (fixed โ matches their existing login)
โ Firestore Security Rules
These rules make privacy real, enforced by Firebase itself โ an employee can only ever read their own data, no matter what the browser shows. No servers needed; this relies on Firebase's own Email/Password sign-in. Paste this in Firebase Console โ Firestore Database โ Rules โ Publish:
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
function isAdmin() {
return request.auth != null && request.auth.token.email == 'admin@aikm-attendance.local';
}
function isManager() {
return request.auth != null && request.auth.token.email == 'manager@aikm-attendance.local';
}
function isSelf(empId) {
return request.auth != null && request.auth.token.email == empId + '@aikm-attendance.local';
}
match /attendance_directory/{empId} {
allow read: if true;
allow write: if isAdmin();
}
match /attendance_employees/{empId} {
allow read: if isAdmin() || isManager() || isSelf(empId);
allow write: if isAdmin();
}
match /attendance_records/{id} {
allow read: if isAdmin() || isManager() || (request.auth != null && request.auth.token.email == resource.data.employeeId + '@aikm-attendance.local');
allow create, update: if isAdmin() || isManager() || (request.auth != null && request.auth.token.email == request.resource.data.employeeId + '@aikm-attendance.local');
allow delete: if isAdmin() || isManager();
}
match /attendance_leaves/{id} {
allow read: if isAdmin() || isManager() || (request.auth != null && request.auth.token.email == resource.data.employeeId + '@aikm-attendance.local');
allow create: if request.auth != null && request.auth.token.email == request.resource.data.employeeId + '@aikm-attendance.local';
allow update: if isAdmin() || isManager();
}
match /attendance_appeals/{id} {
allow read: if isAdmin() || isManager() || (request.auth != null && request.auth.token.email == resource.data.employeeId + '@aikm-attendance.local');
allow create: if request.auth != null && request.auth.token.email == request.resource.data.employeeId + '@aikm-attendance.local';
allow update: if isAdmin() || isManager();
}
match /attendance_advances/{id} {
allow read: if isAdmin() || (request.auth != null && request.auth.token.email == resource.data.employeeId + '@aikm-attendance.local');
allow write: if isAdmin();
}
match /attendance_payslips/{id} {
allow read: if isAdmin() || (request.auth != null && request.auth.token.email == resource.data.employeeId + '@aikm-attendance.local');
allow write: if isAdmin();
}
match /attendance_settings/{id} { allow read: if request.auth != null; allow write: if isAdmin(); }
match /attendance_holidays/{id} { allow read: if request.auth != null; allow write: if isAdmin(); }
match /attendance_weekoffs/{id} { allow read: if request.auth != null; allow write: if isAdmin() || isManager(); }
match /attendance_shifts/{id} { allow read: if request.auth != null; allow write: if isAdmin(); }
match /attendance_device_tokens/{id} { allow read, write: if request.auth != null; }
}
}
This replaces the older rules from before the Manager role existed.
One-time Firebase Console step
Firebase Console โ Build โ Authentication โ Sign-in method โ enable "Email/Password". That's the only setup needed โ no servers, no deployment.
Office Location
๐งช Test Mode
Skips the location check entirely so you can test punching in/out from anywhere โ not at the office. A red warning banner shows on the Punch tab whenever this is on, so it's hard to forget.
Shift & Late Rules
Half-day is credited automatically at half this many hours (e.g. 4.5h for a 9h day). Below that counts as incomplete/absent. Override per shift below if you run multiple shifts.
Applies to everyone unless overridden per employee (Employees tab) or manually assigned a different date for a specific week (Week Offs tab, for the "sometimes on another day" case).
Annual Leave Entitlements
Same entitlement applies to every employee, per calendar year (resets each January). Used and Remaining are calculated automatically.
Change Admin PIN
Shifts
Create a shift per timing (e.g. Morning, Evening, Night). Each has its own start time (for late marking) and full-day hour requirement. Assign employees to a shift in the Employees tab โ unassigned employees use the store default from Setup.
Employees
Add Employee
No PIN field here โ employees set their own PIN by picking their name on the login screen and verifying their date of birth. Real password, handled by Firebase, not stored by us.
Remaining % becomes Allowance automatically.
Attendance Log
Tap an employee to view their attendance calendar.
S
M
T
W
T
F
S
๐ข Full Day
๐ก Half Day
๐ด Absent
๐ต Leave
๐ฃ Holiday
โช Weekly Off
All Employees โ One Sheet
Uses the calendar month above. One file, dates down the rows, every employee as a column โ ready to open in Excel.
Quick Punch (Right Now)
Punch an employee in or out immediately, using the current time โ for when someone can't use their own phone.
Manually Mark Attendance (One Employee)
Overwrites/creates that day's punch times directly โ useful for testing, corrections, or when someone couldn't punch in themselves.
Bulk Mark Present (Tap Dates on Calendar)
For days when punching in wasn't possible (e.g. network down) โ tap any dates below to select them, then mark the chosen employees present using their normal shift hours. Holidays and each employee's own weekly-off days are skipped automatically.
No dates selected yet.
Holidays
Marked holidays are excluded from working days for everyone. Suggested national holidays need your approval before they count.
Leave Requests
Rotational Week Offs
Tap employees and dates below, then assign to all of them at once. Excluded from working days โ not paid extra, not counted absent.
No dates selected yet.
Salary Advances
Salary โ Current Cycle
Each employee's cycle is calculated automatically from their joining date. Holidays, weekly-offs and approved leave are handled automatically.
Payslip History
Payslips saved via "Finalize & Save" in the Salary tab. Export gives you every finalized payslip ever recorded, for offline backup.