| 📷 | Emp# | CPR/ID | Name | Position | Department | Branch | Nat | Gender | Employment Date | Probation End | Supervisor | Shift | Phone | Basic (BHD) | Total Salary (BHD) | Payment | Annual Leave | Sick Leave | Status | Actions |
|---|
Filter and tick one, several, or all employees, then generate — company, CR number, and the employer's representative are filled in automatically per employee from their branch (set once in "Companies / Branches" in Settings). After signing, scan and upload it above with document type "Non-Disclosure Agreement (NDA)" to keep it on file.
| Emp# | Name | Branch | Department | Company (auto) |
|---|
Digitized from your Ministry-approved Sanction List (Law 36/2012) — review each entry against your original PDF before relying on it officially. Edit, delete, or add your own violations any time.
Pick the employee, the violation, and which occurrence this is — the penalty fills in automatically from the template. Produces one bilingual (English + Arabic) letter on a single A4 page.
Issued by HR Department — signed by the Group HR Manager on file for the employee's company (set in Settings → Companies/Branches).
Only the document list (who has what, expiry dates, notes) syncs automatically. The actual scanned files back up to the cloud individually as they're uploaded (files under 4MB) — opening a document on a device that doesn't have it locally will fetch it from the cloud automatically if it was backed up.
| Preview | Employee | Branch | Emp# | Document type | Filename | Expiry date | Note | Uploaded | Actions |
|---|
Upload accepts the same columns as the "⬇ Excel" download (Emp#, Annual Entitlement, Annual Balance, Sick Leave, Comp Leave, Partial Leave) — the easiest way is to download it, edit the numbers, and upload the same file back. Rows are matched by Emp#; only columns present in the file are updated, and you'll see a preview before anything is applied.
| Emp# | Name | Department | Branch | Annual Entitlement | Annual Balance | Sick Leave | Comp Leave | Partial Leave | Adjust |
|---|
Requests submitted by staff from their punch page — sick leave requires an attached certificate photo, annual leave doesn't. Approving deducts the balance automatically and logs it in the adjustment log below (with Undo available there).
| Submitted | Emp# | Name | Branch | Type | From | To | Days | Reason | Certificate | Status | Actions |
|---|
| Date | Emp# | Name | Leave type | Change | Balance after | Reason | Certificate | Undo |
|---|
Every sick or annual leave request submitted by staff from their punch page lands here first, oldest first, so nothing sits unreviewed. Approve deducts the balance automatically and logs it; Reject needs no balance change. Use "✉ Email" to open your own email app with the details pre-filled — set up recipients once in Settings.
| Submitted | Emp# | Name | Branch | Type | From | To | Days | Reason | Certificate | Decision |
|---|
| Loan # | Emp# | Name | Branch | Dept | Loan amount | Monthly deduction | Start date | Months | Total paid | Remaining | Status | Note | Actions |
|---|
Tamkeen support applies to Bahraini nationals only. Coverage declines by year from the accepted date: Year 1 — 70%, Year 2 — 50%, Year 3 — 30%, then the program completes and the company covers 100% of basic salary. Coverage is calculated on salary up to 800 BHD only — any amount above that is entirely the company's responsibility (e.g. on a 1,500 BHD salary, Tamkeen's percentage applies to the first 800 BHD; the remaining 700 BHD is never covered). Pick an accepted date and click Enroll to add someone; edit the date inline any time.
| Emp# | Name | Branch | Accepted Date | Program Year | Coverage % | Company Covers | Tamkeen Covers | Program End | Status | Actions |
|---|
| Department | Branch | Total Staff | Bahraini | Non-Bahraini | Male | Female | Total Basic (BHD) |
|---|
| Emp# | Name | Branch | Dept | Date | Punch In | Punch Out | Hours | Status | Action |
|---|
Shows where staff punched in/out, with each person's name shown right on the map — no need to tap a pin to see who it is. 🟢 solid green = punched in and still on-site (no punch-out yet today); green outline = a completed punch-in; 🟠 orange = punch-out; grey circles are your configured site geofences. With Live on, this syncs from the cloud and redraws automatically every 30 seconds while this tab stays open.
Upload the monthly attendance export (same layout as TIME_SHEET.xlsx). Rows matched by Id = Employee #. Net Working Hours parsed per row, seconds rounded up to next full minute.
| Emp# | Name | Dept | Nat |
|---|
Select a branch to generate a separate payroll run per branch. Leave "All branches" to run one combined payroll.
OT Rules — Nat B: OT after 9 hrs/day × 1.25; Nat NB: OT after 8.75 hrs/day × 1.0; Friday/Public holiday: all hours × 1.5.
GOSI — employee's share is deducted automatically: 8% of GOSI salary for Bahraini nationals, 1% for non-Bahraini, per SIO regulations. Uncheck "Include GOSI deduction" to skip it for a specific run.
⏰ Late arrivals — total late-punch-in hours for the payroll period (based on shift start times and the grace period set in Attendance → Shift times) always show below as "Late hrs" for review. Tick "Deduct for late arrivals" to also subtract those hours × hourly rate from net pay; leave it unticked to just see the figures without deducting anything.
📝 Draft mode — tick "Save as draft" to generate a review copy first (clearly marked DRAFT everywhere, incl. print/PDF). Correct any OT, adjustments, or exclusions below, then generate again — it keeps overwriting the same draft for this month/branch. Untick the box and generate once more to finalize it as the official payroll.
💳 Loans — the "Loan (auto)" column is a live figure computed directly from each employee's active loan (Loans tab) — not manually editable here; capped so the final installment never overcharges. To change what's deducted, edit or pause the loan in the Loans tab. It's only posted to the loan's balance when you finalize (untick "Save as draft") — generating drafts never touches loan balances, and re-finalizing the same month safely corrects itself instead of double-charging.
| ⛔ | Emp# | Name | Branch | Nat | Basic | Normal OT hrs | Holiday OT hrs | Late hrs | Unpaid days | Incentive/Adj. (BHD) | Adj. reason | Loan (auto) | Advance | Note | Detail |
|---|
| Month | Year | Branch | Period | Employees | Total Net (BHD) | Generated | Actions |
|---|
Each branch run generates a separate WPS file. Only Transfer-payment employees are included. Cash/Hold employees are shown separately below.
| Area | Last synced |
|---|
| User | Role | Device | Last seen |
|---|
Every change you make is saved to this device instantly, then synced to the cloud automatically within a few seconds — the "Last synced" times above confirm that's actually happening. If "Cloud connection" ever shows offline, changes are still saved locally and will sync as soon as the connection returns; nothing is lost in the meantime as long as you don't clear this browser's data before it reconnects.
a) Go to console.firebase.google.com → sign in with any Google account → Create a project → name it (e.g. jaberi-attendance) → disable Analytics → Create
b) Left menu: Build → Realtime Database → Create database → choose location → Start in test mode → Enable
c) Copy the database URL shown at the top (looks like
https://jaberi-attendance-default-rtdb.firebaseio.com)
a) After saving the database above, click this button — it downloads a special copy named index.html with the database built inside:
b) Go to neocities.org (free forever) → sign up → Edit Site → delete their index.html → Upload your downloaded index.html
c) Your address is
yourname.neocities.org — paste it below
yourname.neocities.org address here, not a custom domain, unless you've verified the domain's DNS is correctly pointed at Neocities. The free address always works with no extra setup; a misconfigured custom domain fails in ways that look like a system problem but aren't.
Payroll period start/end has moved to the Run Payroll tab, right where you generate each pay run, so it's quicker to change month to month. GOSI wage ceiling is used in Final Settlement gratuity calculations for Bahraini employees — under SIO, Bahraini nationals are covered by pension up to this ceiling, so employer gratuity applies only to basic salary above it. Currently BHD 4,000/month per GOSI regulations; verify with your labour consultant if this changes.
Upload the GOSI salary report for a branch (e.g. the SIO/GOSI export) to update every matching employee's GOSI Salary in one go — matched by CPR number. Do this once per branch as you receive each file; re-uploading is safe and just overwrites the previous GOSI Salary for whoever matches.
Adds an "✉ Email" button in the Notifications tab and Leave Requests list. Clicking it opens your own email app (Outlook, Gmail, Mail — whatever's already set up on this device) with the recipients, subject, and full request details pre-filled — you just hit Send. Sent from your real company email account, no third-party service, no sign-up, nothing else to configure.
Each CR-registered company in the group. The short code is used as the employee's "Branch" value throughout the system, and Leave & Final Settlement statements let you pick which company to print under. The NDA representative here is used automatically whenever an NDA is generated for anyone under this company (Documents tab) — set it once, no need to re-enter it each time.
| Company name | CR number | Short code | NDA Representative | Letterhead | Actions |
|---|
Defaults follow common Bahrain Labour Law practice: annual leave accrues at 30 days ÷ 12 = 2.5 days per month, starting from the employee's join date and prorated by calendar day for a partial month (Leave tab has a "Run Annual Leave Accrual" tool that applies this). Sick leave is paid in tiers per year of service — full pay for the first block of days, half pay for the next block, then unpaid (Sick Leave Pay Calculator in the Leave tab uses these numbers). If enabled, sick leave taken during the probation period (default 3 months / 90 days from the join date, or the employee's own Probation End Date if set) is blocked from deducting the sick leave balance — the Leave Adjustment screen will flag it and direct you to record it as unpaid absence in payroll instead. Adjust here if your company policy differs from the statutory default — confirm with your labour consultant before relying on this for compliance.
All Fridays are always off-days for OT purposes — any hours worked pay 1.5×. Public holidays added here also trigger the 1.5× rule.
Step 1 — Off-day/Public holiday: Every hour worked × 1.5 for both nationalities, no daily threshold applied.
Step 2 — Normal day: OT starts after 9 hrs/day (Bahraini × 1.25) or 8.75 hrs/day (Non-Bahraini × 1.0).
Step 3 — Weighted total: sum all days' (OT hours × day rate) across the period.
Step 4 — OT pay (BHD): Basic ÷ 30 ÷ 8 × weighted total.
This is the single super-admin account — it always has access to every tab. Use "HR Team Users" below to create named logins with limited access for other staff.
If a device (e.g. your phone) keeps rejecting a password that works elsewhere, the most reliable fix is the reset email above — it doesn't need any existing password, Firebase verifies you via the email link instead. After setting a new password through that link: come back here, enter whatever password currently works in "Current password," and set that same new password again in "New password" — this makes sure this app's local record matches Firebase exactly.
By default, the cloud database (punches, leave requests, selfies…) has no real login check — anyone with the database address could read or write it directly. This adds a genuine credential check on top of it. Once set up, every HR login (above and in "HR Team Users") also signs in to Firebase for real, and the database itself can be locked to require it.
One-time setup: ① In the Firebase console, open your project → ⚙️ Project settings → General → copy the Web API Key → paste it above → Save → ② Build → Authentication → Get started → Sign-in method → enable Email/Password AND Anonymous (Anonymous lets the staff punch page keep working with no login screen, while still being authenticated) → ③ set an admin email above and re-save your credentials so the super-admin account gets a real Firebase login too → ④ in "HR Team Users" below, add an email for each user — the first time you set/change their password, a matching Firebase account is created automatically → ⑤ finally, go to Realtime Database → Rules and replace the rules with:
{
"rules": {
".read": "auth != null",
".write": "auth != null"
}
}
This closes the database to everyone except signed-in users (including the anonymous punch-page sign-in). Do this last, only after you've confirmed the admin and HR user logins above are working — publishing this rule before anyone has a working Firebase login would lock everyone out, including the punch page, until it's fixed.
Give each HR team member their own username and password, and choose exactly which tabs they can see. Every change they make is stamped with their name in the Activity Log below and on printed documents (e.g. "Prepared by").
| Username | Full name | Tabs allowed | Email / Security | Actions |
|---|
Who did what and when — showing the most recent 300 on screen; the Excel and PDF downloads include the full stored log (up to 2000 actions).
| When | User | Action | Target | Details |
|---|
Clears all payroll runs and restores original imported employee data. Requires entering the admin password twice to confirm. A one-time undo is available immediately after, in case this was triggered by mistake.